* Copyright 2006, Axel DΓΆrfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "apm.h"
#include "bios.h"
#include <boot/kernel_args.h>
#include <boot/platform.h>
#include <boot/stage2.h>
#ifdef TRACE_APM
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
status_t
apm_init(void)
{
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) {
return B_ERROR;
}
regs.eax = BIOS_APM_DISCONNECT;
regs.ebx = 0;
call_bios(0x15, ®s);
regs.eax = BIOS_APM_CONNECT_32_BIT;
regs.ebx = 0;
call_bios(0x15, ®s);
if ((regs.flags & CARRY_FLAG) != 0) {
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;
}