/* * 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 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; } const apm_info &info = gKernelArgs.platform_args.apm; gKernelArgs.platform_args.apm.version = regs.eax & 0xffff; gKernelArgs.platform_args.apm.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) { // reset the version, so that the kernel won't try to use APM gKernelArgs.platform_args.apm.version = 0; return B_ERROR; } gKernelArgs.platform_args.apm.code32_segment_base = regs.eax & 0xffff; gKernelArgs.platform_args.apm.code32_segment_offset = regs.ebx; gKernelArgs.platform_args.apm.code32_segment_length = regs.esi & 0xffff; gKernelArgs.platform_args.apm.code16_segment_base = regs.ecx & 0xffff; gKernelArgs.platform_args.apm.code16_segment_length = regs.esi >> 16; gKernelArgs.platform_args.apm.data_segment_base = regs.edx & 0xffff; gKernelArgs.platform_args.apm.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; }