; $Id: ;; @file ; Protected-mode APM implementation. ; ; ; Copyright (C) 2006-2016 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; ; you can redistribute it and/or modify it under the terms of the GNU ; General Public License (GPL) as published by the Free Software ; Foundation, in version 2 as it comes in the "COPYING" file of the ; VirtualBox OSE distribution. VirtualBox OSE is distributed in the ; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. ; include commondefs.inc ;; 16-bit protected mode APM entry point _TEXT segment public 'CODE' extern _apm_function:near ; implemented in C code public apm_pm16_entry SET_DEFAULT_CPU_286 ; APM function dispatch table apm_disp: dw offset apmf_disconnect ; 04h dw offset apmf_idle ; 05h dw offset apmf_busy ; 06h dw offset apmf_set_state ; 07h dw offset apmf_enable ; 08h dw offset apmf_restore ; 09h dw offset apmf_get_status ; 0Ah dw offset apmf_get_event ; 0Bh dw offset apmf_pwr_state ; 0Ch dw offset apmf_dev_pm ; 0Dh dw offset apmf_version ; 0Eh dw offset apmf_engage ; 0Fh dw offset apmf_get_caps ; 10h apm_disp_end: ; ; APM worker routine. Function code in AL; it is assumed that AL >= 4. ; Caller must preserve BP. ; apm_worker proc near sti ; TODO ?? necessary ?? push ax ; check if function is supported... xor ah, ah sub al, 4 mov bp, ax shl bp, 1 cmp al, (apm_disp_end - apm_disp) / 2 pop ax mov ah, 53h ; put back APM function jae apmw_bad_func ; validate function range jmp apm_disp[bp] ; and dispatch apmf_disconnect: ; function 04h jmp apmw_success apmf_idle: ; function 05h sti hlt jmp apmw_success apmf_busy: ; function 06h ; jmp apmw_success apmf_set_state: ; function 07h ; jmp apmw_success apmf_enable: ; function 08h jmp apmw_success apmf_restore: ; function 09h ; jmp apmw_success apmf_get_status: ; function 0Ah jmp apmw_bad_func apmf_get_event: ; function 0Bh mov ah, 80h jmp apmw_failure apmf_pwr_state: ; function 0Ch apmf_dev_pm: ; function 0Dh jmp apmw_bad_func apmf_version: ; function 0Eh mov ax, 0102h jmp apmw_success apmf_engage: ; function 0Fh ; TODO do something? jmp apmw_success apmf_get_caps: ; function 10h mov bl, 0 ; no batteries mov cx, 0 ; no special caps jmp apmw_success apmw_success: clc ; successful return ret apmw_bad_func: mov ah, 09h ; unrecognized device ID - generic apmw_failure: stc ; error for unsupported functions ret apm_worker endp ;; 16-bit protected mode APM entry point ;; According to the APM spec, only CS (16-bit code selector) is defined. ;; The data selector can be derived from it. apm_pm16_entry: mov ah, 2 ; mark as originating in 16-bit PM ; fall through apm_pm16_entry_from_32: push ds ; save registers push bp push cs pop bp add bp, 8 ; calculate data selector mov ds, bp ; load data segment call apm_worker ; call APM handler pop bp pop ds ; restore registers retf ; return to caller - 16-bit return ; even to 32-bit thunk! _TEXT ends .386 BIOS32 segment public 'CODE' use32 public apm_pm32_entry ;; 32-bit protected mode APM entry point and thunk ;; According to the APM spec, only CS (32-bit) is defined. 16-bit code ;; selector and the data selector can be derived from it. ;; WARNING: To simplify matters, we use 16-bit far return to go from 32-bit ;; code to 16-bit and back. As a consequence, the 32-bit APM code must lie ;; below 64K boundary in the 32-bit APM code segment. apm_pm32_entry: push ebp ; ebp is not used by APM mov bp, cs ; return address for 16-bit code push bp mov ebp, apm_pm32_back push bp ; Note: 16:16 address! push cs pop ebp add ebp, 8 ; calculate 16-bit code selector push bp ; push 16-bit code selector mov ebp, apm_pm16_entry_from_32 push bp ; push 16-bit offset mov ah, 3 ; mark as originating in 32-bit PM db 66h ; force a 16-bit return retf ; off to 16-bit code... apm_pm32_back: ; return here from 16-bit code pop ebp ; restore scratch register retf BIOS32 ends end