Code: Select all
PowerDown:
call DisableAllIRQs
mov al,11h
out 020h,al
out 0A0h,al
mov al,08h
out 021h,al
mov al,070h
out 0A1h,al
mov al,4
out 021h,al
mov al,2
out 0A1h,al
mov al,1
out 021h,al
out 0A1h,al
jmp 28h:RealModePowerDown
use16
PowerManagmentVersion dw 0
NoPowerManagment db 'No power management functionality',10,13,0
ErrorMessage db 'Power management error',10,13,0
WrongVersion db 'Need APM version 1.1 or better',10,13,0
RealModePowerDown:
mov ax,30h
mov ds,ax
mov ss,ax
nop
mov bx,[RealModeCS]
push bx
lea bx,[DoPowerDownRealMode]
push bx
mov eax,cr0
and al,0xFE
mov cr0,eax
retf
DoPowerDownRealMode:
mov ax,cs ; Save CS to AX
mov ds,ax ; Put DS to CS
mov ax,[StackSegment] ; Save original stack segment to AX
mov ss,ax ; Replace original stack segment
mov ax,[StackPointer] ; Save the stack pointer to AX
movzx esp,ax ; and Replace original stack pointer (force 16 bit)
nop ; Take a CPU clock tick
mov es,ax ; Update ES with AX
mov fs,ax ; Update FS with AX
mov gs,ax ; Update GS with AX
;;;;;;;;;;;;;;;;;;;;;;;
;; Load real mode IDTR
;;;;;;;;;;;;;;;;;;;;;;;
lidt [RIDTR] ; Load original IVT from 0000:0000
push cs ; Put CS on stack
pop ds ; Put CS from stack to DS
push ds ; Save DS to the stack
pop es ; Update ES with DS from stack
mov al,0 ; Re-enable realmode IVT by turning on all IRQs
out 0A1h,al ; Updates lower 7 IRQs
out 021h,al ; Updates upper 8 IRQs
sti ; Re-enable interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Now to do the real mode interrupt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,5300h ; See if APM available
mov bx,0 ; device = BIOS
int 15h
mov si,NoPowerManagment
jc .Error
cmp ax,101h ; See if version 1.1 or greater
mov dx,WrongVersion
jc .Error
mov [PowerManagmentVersion],ax
mov ax,5301h ; Do a real mode connection
mov bx,0 ; device = BIOS
int 15h
jnc .NoConnectionError
cmp ah,2 ; Pass if already connected
mov si,ErrorMessage ; else error
jnz .Error
.NoConnectionError:
mov ax,530eh ; Enable latest version of APM
mov bx,0 ; device = BIOS
mov cx,[PowerManagmentVersion] ; version
int 15h
mov si,ErrorMessage
jc .Error
mov ax,530dh ; Now engage and enable CPU management
mov bx,1 ; device = all
mov cx,1 ; enable
int 15h
mov si,ErrorMessage
jc .Error
mov ax,530fh
mov bx,1 ; device = ALL
mov cx,1 ; enable
int 15h
mov si,ErrorMessage
jc .Error
mov ax,5307h ; Do the power down
mov bx,1 ; device = ALL
mov cx,3 ; mode = OFF
int 15h ; shutdown CPU
mov si,ErrorMessage
.Error:
call PrintString
jmp CheckCodeSegment ; Change this to the DOS check for EXIT or REBOOT
; ret
Use32 ; No expected return