From ba61df6d0b3076ef132a0c602a5908bfeffcb7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 10 Jan 2006 22:54:36 +0000 Subject: [PATCH] Beginnings of APM support: we now connect to the APM BIOS in 32 bit protected mode. We don't do anything with it yet, though, so the BIOS will probably ignore us since we are supposed to poll for events. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15900 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/apm.h | 21 +++++ headers/private/kernel/arch/x86/descriptors.h | 15 ++- .../platform/bios_ia32/platform_kernel_args.h | 6 +- src/system/boot/platform/bios_ia32/Jamfile | 1 + src/system/boot/platform/bios_ia32/apm.cpp | 92 +++++++++++++++++++ src/system/boot/platform/bios_ia32/apm.h | 18 ++++ src/system/boot/platform/bios_ia32/start.c | 4 +- 7 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 headers/private/kernel/arch/x86/apm.h create mode 100644 src/system/boot/platform/bios_ia32/apm.cpp create mode 100644 src/system/boot/platform/bios_ia32/apm.h diff --git a/headers/private/kernel/arch/x86/apm.h b/headers/private/kernel/arch/x86/apm.h new file mode 100644 index 0000000000..3a973489a9 --- /dev/null +++ b/headers/private/kernel/arch/x86/apm.h @@ -0,0 +1,21 @@ +#ifndef KERNEL_APM_H +#define KERNEL_APM_H + + +#include + + +typedef struct apm_info { + uint16 version; + uint16 flags; + uint16 code32_segment_base; + uint32 code32_segment_offset; + uint16 code32_segment_length; + uint16 code16_segment_base; + uint16 code16_segment_length; + uint16 data_segment_base; + uint16 data_segment_length; +} apm_info; + + +#endif /* KERNEL_APM_H */ diff --git a/headers/private/kernel/arch/x86/descriptors.h b/headers/private/kernel/arch/x86/descriptors.h index 1e4a86f4b8..b138d5773d 100644 --- a/headers/private/kernel/arch/x86/descriptors.h +++ b/headers/private/kernel/arch/x86/descriptors.h @@ -1,7 +1,10 @@ /* -** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ #ifndef _KERNEL_ARCH_x86_DESCRIPTORS_H #define _KERNEL_ARCH_x86_DESCRIPTORS_H @@ -12,14 +15,18 @@ #define USER_CODE_SEG 0x1b #define USER_DATA_SEG 0x23 +#define APM_CODE32_SEGMENT 0x28 +#define APM_CODE16_SEGMENT 0x30 +#define APM_DATA_SEGMENT 0x38 #ifndef _ASSEMBLER // this file can also be included from assembler as well // (and is in arch_interrupts.S) -#define DOUBLE_FAULT_TSS_BASE_SEGMENT 5 +#define DOUBLE_FAULT_TSS_BASE_SEGMENT 8 #define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) #define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) // defines entries in the GDT/LDT diff --git a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h index d0875e72c3..dd637cb791 100644 --- a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h +++ b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_BOOT_PLATFORM_BIOS_IA32_KERNEL_ARGS_H @@ -9,6 +9,8 @@ # error This file is included from only #endif + +#include #include @@ -25,6 +27,8 @@ typedef struct { uint16 boot_drive_number; bios_drive *drives; // this does not contain the boot drive + + apm_info apm; } platform_kernel_args; #endif /* KERNEL_BOOT_PLATFORM_BIOS_IA32_KERNEL_ARGS_H */ diff --git a/src/system/boot/platform/bios_ia32/Jamfile b/src/system/boot/platform/bios_ia32/Jamfile index 4a40605dea..399725fb94 100644 --- a/src/system/boot/platform/bios_ia32/Jamfile +++ b/src/system/boot/platform/bios_ia32/Jamfile @@ -24,6 +24,7 @@ KernelMergeObject boot_platform_bios_ia32.o : smp_trampoline.S support.S video.cpp + apm.cpp # generic text_menu.cpp diff --git a/src/system/boot/platform/bios_ia32/apm.cpp b/src/system/boot/platform/bios_ia32/apm.cpp new file mode 100644 index 0000000000..e191707924 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/apm.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "apm.h" +#include "bios.h" + +#include +#include +#include + + +//#define TRACE_APM +#ifdef TRACE_APM +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +// int 0x15 APM definitions +#define BIOS_APM_CHECK 0x5300 +#define BIOS_APM_CONNECT_32_BIT 0x5303 +#define BIOS_APM_DISCONNECT 0x5304 + + +status_t +apm_init(void) +{ + // check if APM is available + + struct bios_regs regs; + regs.eax = BIOS_APM_CHECK; + regs.ebx = 0; + call_bios(0x15, ®s); + + if ((regs.flags & CARRY_FLAG) != 0 + || (regs.ebx & 0xffff) != 'PM') { + dprintf("No APM available.\n"); + return B_ERROR; + } + + apm_info &info = gKernelArgs.platform_args.apm; + info.version = regs.eax & 0xffff; + info.flags = regs.ecx & 0xffff; + + dprintf("APM version %d.%d available, flags %x.\n", + (info.version >> 8) & 0xf, info.version & 0xf, info.flags); + + if ((info.version & 0xf) < 2) { + // 32-bit protected mode interface was not available before 1.2 + return B_ERROR; + } + + // there can always be one connection, so make sure we're + // the one - and disconnect + + regs.eax = BIOS_APM_DISCONNECT; + regs.ebx = 0; + call_bios(0x15, ®s); + // We don't care if this fails - there might not have been + // any connection before. + + // try to connect to the 32-bit interface + + regs.eax = BIOS_APM_CONNECT_32_BIT; + regs.ebx = 0; + call_bios(0x15, ®s); + if ((regs.flags & CARRY_FLAG) != 0) + return B_ERROR; + + info.code32_segment_base = regs.eax & 0xffff; + info.code32_segment_offset = regs.ebx; + info.code32_segment_length = regs.esi & 0xffff; + + info.code16_segment_base = regs.ecx & 0xffff; + info.code16_segment_length = regs.esi >> 16; + + info.data_segment_base = regs.edx & 0xffff; + info.data_segment_length = regs.edi & 0xffff; + + TRACE((" code32: 0x%x, 0x%lx, length 0x%x\n", + info.code32_segment_base, info.code32_segment_offset, info.code32_segment_length)); + TRACE((" code16: 0x%x, length 0x%x\n", + info.code16_segment_base, info.code16_segment_length)); + TRACE((" data: 0x%x, length 0x%x\n", + info.data_segment_base, info.data_segment_length)); + + return B_OK; +} diff --git a/src/system/boot/platform/bios_ia32/apm.h b/src/system/boot/platform/bios_ia32/apm.h new file mode 100644 index 0000000000..2abe1fffe1 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/apm.h @@ -0,0 +1,18 @@ +/* + * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef APM_H +#define APM_H + + +#include + + +extern +#ifdef __cplusplus +"C" +#endif +status_t apm_init(void); + +#endif /* APM_H */ diff --git a/src/system/boot/platform/bios_ia32/start.c b/src/system/boot/platform/bios_ia32/start.c index 8e38402c4d..e9b9d30249 100644 --- a/src/system/boot/platform/bios_ia32/start.c +++ b/src/system/boot/platform/bios_ia32/start.c @@ -1,11 +1,12 @@ /* - * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ #include "serial.h" #include "console.h" +#include "apm.h" #include "cpu.h" #include "mmu.h" #include "smp.h" @@ -128,6 +129,7 @@ _start(void) //if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT) serial_enable(); + apm_init(); smp_init(); main(&args); }