?? power.asm
字號:
pop es
pop di
pop si ; M086
jmp short PS_SRet
PS_Get_Stats:
IFDEF INCL_APM
cmp bx,PW_GET_APM_STATS ; ; M076
ja PS_Inv_Parm_Err ; invalid info level ?
je PS_Get_APM_Stats ; APM statistics (resume count ) ?
ELSE
or bx,bx ; only Idle detection stats will be
jnz PS_Inv_Parm_Err ; returned
ENDIF
cmp cx,size IDLE_INFO ; No, Idle detection statistics
jb PS_Buff_Ovf_Err ; Buffer not sufficient ; M076
push si ; M086
push di
lea di, INFO
PS_Transf_Stats:
push es
mov es,Bios_Data_Word
assume es:Bios_Data
assume es:nothing
mov bx,-1 ; get stats ; there is no set stats
jmp short PS_Exch_ESDS_SIDI
IFDEF INCL_APM
PS_Get_APM_Stats:
cmp cx, APM_STATS_STRUC_SIZE
jb PS_Buff_Ovf_Err ; Buffer not sufficient ; M076
push si ; M088
push di
lea di,APM_RESUME_COUNT
jmp short PS_Transf_Stats
ENDIF ; of IFDEF INCL_APM
PS_Inv_Parm_Err:
mov ax,ERROR_PM_INVALID_PARAMETER
stc
jmp short PS_Ret
PS_SRet: xor ax,ax ; M084 : Clear CY and put
; 0 in AX to mean no error
PS_Ret:
pop ds
ret
PS_Buff_Ovf_Err:
mov ax,ERROR_PM_BUFFER_TOO_SMALL
jmp PS_FRet
PS_GetSet_PWState:
mov ds,cs:Bios_Data_Word
assume ds:Bios_Data
or bh,bh ; get power state ?
call GetPowStatus ; M089 : old state in AL
mov bh,al ; get old status
mov ax,0 ; M084 : Assume no error
jz PS_APM_Ret ; M084
test bl,PWSTATE_RESERVED_BITS
jnz PS_Inv_Parm_Err
push bx ; save old status on stack
; set power status
test bl,1 ; check for POWER.SYS/EXE enable
jnz PS_Enable_Power
; disable POWER.SYS
test POWER_STATUS,1
jz PS_Test_APM_Bit ; already disabled
;
and [CONTROL].IDLE_FLG,NOT(IDLE_ACTIVE) ; turn of idle detection
and POWER_STATUS,NOT(1) ; turn off S/W PM
jmp short PS_Test_APM_Bit
PS_Enable_Power:
test POWER_STATUS,1
jnz PS_Test_APM_Bit ; already enabled
or [CONTROL].IDLE_FLG,IDLE_ACTIVE ; turn on idle detection
or POWER_STATUS,1 ; turn on S/W PM
;
PS_Test_APM_Bit:
;
IFDEF INCL_APM
call Do_APM_Control
ENDIF
;
pop bx ; get back old status
;
; M084: NSM
; At this point :
; CY set if error
; AX = error code
; NC -> AX = 0
;
PS_APM_Ret:
push ax ; M089 BEGIN
call GetPowStatus ; status in al
mov bl,al ; return with current status
pop ax ; M089 END
jmp PS_Ret
PS_GetSet_BaseLine:
mov ds,Bios_Data_Word
assume ds:Bios_Data
or bx,bx ; get base line ?
je PS_GetBaseLine
mov [BaseLineRef],bx
mov [KYC].BASE,bx
;
PS_GetBaseLine:
mov bx,[BaseLineRef]
mov cx,[BaseLineOvf]
jmp PS_SRet
Pwr_Services endp
;****************************** GetPowStatus **********
; Get the current power status
; Entry: none
; Exit: AL:Bit 0 - 1 if S/W PowMgmt enabled
; Bit 1 - 1 if H/W PowMgmt enabled
; Regs: AX
; M089: Created
;******************************************************************
GetPowStatus proc near
pushf
mov al,POWER_STATUS
test al,2 ; test for H/W enabled state
jnz GPS_Ret
; H/W not connected state; let us see if it is atleast enabled from what
; we know of before last disconnect.
IFDEF INCL_APM
test fAPM_STATE,1
jz @f
or al,2 ; H/W pow.mgmt enabled - POWER STD mode
@f:
ENDIF ; IFDEF INCL_APM
GPS_Ret:
popf
ret
GetPowStatus endp
IFDEF INCL_APM
;****************************** Do_APM_GetSet_PollCount **********
; INT 2F subfunction service procedure
; To get/set the APM pollcount
; Entry: BX = 0 -> get APM poll count
; otherwise, New poll count to be set
; Exit: BX = new APM Poll count
; Regs: BX,DS,Flags
;******************************************************************
Do_APM_GetSet_PollCount Proc NEAR
mov ds,cs:Bios_Data_Word
assume ds:Bios_Data
or bx,bx
jz DAPC_Get_PollCount
mov [APM_MAX_POLLCOUNT],bx
mov [APM_POLL_COUNT],bx ; M093
jmp short DAPC_Ret
DAPC_Get_PollCount:
mov bx,APM_MAX_POLLCOUNT
DAPC_Ret:
ret
Do_APM_GetSet_PollCount endp
;****************************** Do_APM_Control *********************
; INT 2F subfunction service procedure
; To (enable-connect to)/(disable-disconnect from) APM
; Entry: BL = 3 -> connect and enable APM ; M089
; BL = 2 -> stay disconnected but enable it if needed
; BL = 1 or 0 -> disconnect and disable
;
; Exit: CY if operation failed
; ax = error code
; ELSE AX = 0
;
; (POWER_STATUS flags updated properly
; fAPM_STATE also updated)
; APM_RESUME_COUNT initialised to zero if enable successful
;
; Regs: ax,bx,cx,dx
;******************************************************************
Do_APM_Control proc near
cmp bl,2 ; check for F/w PM bit enable
jae DACt_Enable_APM
; M089 BEGIN
; With the new definition of POWER STD, we need to enable APM but not
; connected to it (and sometime disable APM but we would not have been
; connected to it for doing it). Enable/disable can only be done if we
; are connected to APM and so We first connect to APM to enable/disable
; APM and depending on the requested state, we disconnect from APM
;
; Disconnect and disable APM
and [CMOSFlg],NOT(1) ; M091 reset STD mode+APM bit in CMOSFlg
test POWER_STATUS,2 ; are we connected already ?
jnz DACt_Dis_con_able ; yes, just disable and disconnect
; we are not connected ; so go connect to it first, enable it
; and then disable it!
IFDEF POWERALONE
call far ptr Check_and_Init_APM ; M003: always check for APM presence
ELSE
call Check_and_Init_APM_Ptr
ENDIF
; M089 END
DACt_Dis_con_able:
test fAPM_PRESENT,1 ; M003:no need to do anything if APM not
jz DACt_End ; M003:present
; disable APM
mov cx,APM_DISABLE_FUNC
call Do_APM_Enable_Disable ; disable APM ;M005
jc DACt_End
mov fAPM_STATE,0 ; flag APM disabled state
call Do_APM_DisConnect
and POWER_STATUS,NOT (2)
jmp short DACt_End
DACt_Enable_APM:
push bx ; save the desired state (input)
;M089 BEGIN
test POWER_STATUS,2
jz DACt_Connect ; Go connect and enable
test fAPM_STATE,1 ; are we also enabled ?
jnz DACt_ChkForDiscon ; yes, go see if we have to disconnect
mov cx,APM_ENABLE_FUNC
call Do_APM_Enable_Disable ; enable APM
mov fAPM_STATE,1 ; flag APM enabled state
DACt_Connect:
;M005 BEGIN - for resident driver call Check_and_Init_APM through pointer
IFDEF POWERALONE
call far ptr Check_and_Init_APM ; M003: always check for APM presence
ELSE
call Check_and_Init_APM_Ptr
ENDIF ; POWERALONE
;M005 END
jnc DACt_ChkForDiscon ; before connecting to it
jz DACt_APM_ConnErr ; ignore if APM not present
clc
DACt_ChkForDiscon:
pop bx ; get back requested APM state
and [CMOSFlg],NOT(1) ; assume not stdmode+apm
cmp bl,3 ; both S/W and F/W pwmgmt ON ?
je DACt_End ; Yes, all done
; User requested APM be ON but we should stay disconnected
call Do_APM_DisConnect
and POWER_STATUS,NOT (2)
test fAPM_PRESENT,1 ; M091
jz DACt_End ; M091
or [CMOSFlg],1 ; M091 set POWER_STDMODE+APM
mov [CMOSPollCount],MAXCMOSPOLLCOUNT ; M091
; M089 END
DACt_End: xor ax,ax ; M094 - ax=0 -> no error
DACt_Ret:
ret
DACt_APM_ConnErr:
pop bx
mov ax,ERROR_PM_ALREADY_CONNECTED ; put valid error code here
stc
jmp short DACt_Ret
Do_APM_Control endp
ENDIF
;********************** TIMER TIC READ ROUTINE *******************
; ax = READ_TMR0( void)
; purpose: to return tic stored in timer0
;
; M0FF:
; OEMs NOTE:
; This procedure should always return a count between 64k and 1
; This code assumes an 8254 timer chip and also assumes that 64k is the
; max count and counted DOWN.
; DOS usually uses mode 3 in both 8253/54. ( mode 2 counts the MAXCOUNT
; just once whereas mode counts it twice in a tic period). But in 8254,
; we can get half cycle we are in, in mode 3 whereas we can't get that
; info in 8253.
; OEMS, if they don't have an 8254, need to modify this code to always
; return a count as if we are operating in mode 2 (down counter).
PUBLIC Read_tmr0
Read_tmr0 proc near
assume ds:nothing, es:nothing
IFDEF 8253
cli
mov al,0
out 43h,al
jmp $+2
in al,40h
jmp $+2
mov ah,al
in al,40h
sti
xchg ah,al
ret
ELSE ; 8254 assumed so that we will know the mode
push bx
mov al,0c2h ; read mode as well as count of tmr0
cli
out 43h,al
jmp $+2
in al,40h ; status byte
; bit 7 -> first half cycle
; bit 1-3 -> mode
mov bl,al ; save status in bl&bh
mov bh,al
jmp $+2
in al,40h ; low byte of count
jmp $+2
mov ah,al
in al,40h ; high byte of count
sti
xchg ah,al ; ax = current tmr count
and bl,0eh ; mask everything but mode bits
cmp bl,6 ; mode 3 ?
jne rt_ret ; if mode 2 no need for adjustments
shr ax,1 ; halve for mode 3 cycle 1
test bh,80h ; is this cycle 2 ?
jz rt_ret ; yes, the count is already correct
add ax,8000h ; first cycle, so add 32k to the count
rt_ret:
pop bx
ret
ENDIF
Read_tmr0 endp
IFDEF DEBUG ; only use this code on test version
START_SOUND proc
mov al,0
out 42h,al
jmp $+2
mov al,50h
out 42h,al
mov al,3
in al,61h
jmp $+2
or al,3
out 61h,al
ret
START_SOUND endp
END_SOUND proc
in al,61h
jmp $+2
and al,not 3
out 61h,al
ret
END_SOUND endp
ENDIF ; IFDEF DEBUG
; Z.flag CheckV86()
; return - NZ, if 386 V86 or protected mode
PUBLIC CheckV86
CheckV86 proc near
assume ds:Bios_Data, es:nothing
test [CONTROL].CV86FLG,1 ; Avoid test
jz cv8ret ; if bit cleared
test [CONTROL].CV86FLG,2 ; is it a 386?
jz cv8all ; don't know yet ...
cv8386:
.386p
smsw [MSW]
.8086
test [MSW],1 ; check for protected mode
ret ; NZ, yes
cv8all: push ax ; run through all proccesors
push sp ; below 286?
pop ax
cmp sp,ax
jne cv8ex0 ; yes, disable check
pushf ; check TS
pop ax ; should be zero for 286
or ax,4000h ; try setting TS high
push ax
popf
pushf
pop ax ; restore TS
test ax,4000h ; did it remain 0?
jz cv8ex0 ; yes, 286
pop ax
or [CONTROL].CV86FLG,2 ; Set 386 bit to save time
jmp short cv8386
cv8ex0: xor ax,ax ; We don't have to test again
mov [CONTROL].CV86FLG,ax ; return ZF
pop ax
cv8ret: ret
CheckV86 endp
;***************** DO_IDLE OEM EXTENDABLE ****************
PUBLIC Do_idle_dos
Do_idle_dos proc far
assume ds:nothing, es:nothing
push ds
mov ds,Bios_Data_Word
assume ds:Bios_Data
call DO_IDLE
pop ds
assume ds:nothing
ret
Do_idle_dos endp
; CY.flag DO_IDLE()
; purpose: To put CPU in a low power state via a halt or
; OEM supplied OEM_IDLE routine.
; passed: control.IDLE_FLG - enables/disables DO_IDLE
; return: Carry Set, if IDLE was executed
PUBLIC Do_idle
Do_idle proc near
assume ds:Bios_Data, es:nothing
; JAH Start - If app supports IDLE only idle on int 2f idle entry point below
push ds
mov ds,PSPsegment ; DS:BX --> Current PSP in Dosdata
mov ds,WORD PTR ds:[CUR_PSP_OFFSET] ; DS -> current app's PSP
assume ds:Pdb_Data
cmp PDB_Idle,IDLE_SUPPORT_BYTE ; Check app's idle support byte
pop ds
assume ds:Bios_Data
je didex1 ; Idle aware app so don't idle
PUBLIC I2fIdleEntry
I2fIdleEntry: ; Entry point from int 2fh handler
; JAH End
test [CONTROL].IDLE_FLG,IDLE_ACTIVE
jnz didbgn
didex1: clc ; idle failed to execute
ret
didbgn: push ax
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -