1 /* 2 * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "apm.h" 8 #include "bios.h" 9 10 #include <boot/kernel_args.h> 11 #include <boot/platform.h> 12 #include <boot/stage2.h> 13 14 15 //#define TRACE_APM 16 #ifdef TRACE_APM 17 # define TRACE(x) dprintf x 18 #else 19 # define TRACE(x) ; 20 #endif 21 22 23 status_t 24 apm_init(void) 25 { 26 // check if APM is available 27 28 struct bios_regs regs; 29 regs.eax = BIOS_APM_CHECK; 30 regs.ebx = 0; 31 call_bios(0x15, ®s); 32 33 if ((regs.flags & CARRY_FLAG) != 0 34 || (regs.ebx & 0xffff) != 'PM') { 35 dprintf("No APM available.\n"); 36 return B_ERROR; 37 } 38 39 const apm_info &info = gKernelArgs.platform_args.apm; 40 gKernelArgs.platform_args.apm.version = regs.eax & 0xffff; 41 gKernelArgs.platform_args.apm.flags = regs.ecx & 0xffff; 42 43 dprintf("APM version %d.%d available, flags %x.\n", 44 (info.version >> 8) & 0xf, info.version & 0xf, info.flags); 45 46 if ((info.version & 0xf) < 2) { 47 // 32-bit protected mode interface was not available before 1.2 48 return B_ERROR; 49 } 50 51 // there can always be one connection, so make sure we're 52 // the one - and disconnect 53 54 regs.eax = BIOS_APM_DISCONNECT; 55 regs.ebx = 0; 56 call_bios(0x15, ®s); 57 // We don't care if this fails - there might not have been 58 // any connection before. 59 60 // try to connect to the 32-bit interface 61 62 regs.eax = BIOS_APM_CONNECT_32_BIT; 63 regs.ebx = 0; 64 call_bios(0x15, ®s); 65 if ((regs.flags & CARRY_FLAG) != 0) { 66 // reset the version, so that the kernel won't try to use APM 67 gKernelArgs.platform_args.apm.version = 0; 68 return B_ERROR; 69 } 70 71 gKernelArgs.platform_args.apm.code32_segment_base = regs.eax & 0xffff; 72 gKernelArgs.platform_args.apm.code32_segment_offset = regs.ebx; 73 gKernelArgs.platform_args.apm.code32_segment_length = regs.esi & 0xffff; 74 75 gKernelArgs.platform_args.apm.code16_segment_base = regs.ecx & 0xffff; 76 gKernelArgs.platform_args.apm.code16_segment_length = regs.esi >> 16; 77 78 gKernelArgs.platform_args.apm.data_segment_base = regs.edx & 0xffff; 79 gKernelArgs.platform_args.apm.data_segment_length = regs.edi & 0xffff; 80 81 TRACE((" code32: 0x%x, 0x%lx, length 0x%x\n", 82 info.code32_segment_base, info.code32_segment_offset, info.code32_segment_length)); 83 TRACE((" code16: 0x%x, length 0x%x\n", 84 info.code16_segment_base, info.code16_segment_length)); 85 TRACE((" data: 0x%x, length 0x%x\n", 86 info.data_segment_base, info.data_segment_length)); 87 88 return B_OK; 89 } 90