windows-nt/Source/XPSP1/NT/base/mvdm/wow16/system/timer.asm
2020-09-26 16:20:57 +08:00

643 lines
12 KiB
NASM

;------------------------------ Module Header ------------------------------;
; Module Name: Timer interface procedures
;
; Created: ??-???-83
;
; Copyright (c) 1983, 1984, 1985, 1986, 1987 Microsoft Corporation
;
; History:
; 10-Jan-87 by ronm Adusted StackBase to be even
; 9-Jan-87 by ronm Patches to support HiTime.asm
;---------------------------------------------------------------------------;
TITLE Timer interface procedures
include system.inc
include wow.inc
include wowusr.inc
include vint.inc
ifdef NEC_98
include timer.inc
externA __ROMBIOS
endif ; NEC_98
externFP WOW16Call
; Interrupt vector to use
VECTOR equ 08h
assumes CS,CODE
sBegin DATA
PUBLIC timerTable
timerTable LABEL BYTE
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
tiblock <-1,0,0>
DW -1
DW -1
ifdef WOW
cTimers DW 0
endif
enabled DB 0 ; 0 means int 8 hook not installed
; 1 means int 8 hook installed
; >1 means inside our int 8 hook
ifdef NEC_98
externB reflected ; 930206
endif ; NEC_98
if 0
;
; no longer used
;
public StackBase
EVEN ; Put the stack at a word boundary!
StackBase DB 64 DUP (-1)
PUBLIC prevInt8Proc,prevSSSP,enabled
PUBLIC cms, cmsRound
DB 128 DUP (?)
int8stack LABEL BYTE ; Stack to use inside our int 8 hook
prevSSSP DD 0 ; Previous stack when inside our hook
endif
prevInt8Proc DD 0 ; Previous int 8 interrupt handler
cms DD 0 ; msec count.
cmsRound DW 0 ; for rounding off the msec count.
ifdef NEC_98
DB '@@@@'
TIINTFLAG1 DW 0
TIINTFLAG2 DW 0
endif ; NEC_98
sEnd
sBegin CODE ; Beginning of code segment
assumes CS,CODE
externW MyCSDS ; always in CS (even in ROM)
;--- timer hardware service -----------------------
;
noevent:
ifdef NEC_98
assumes ds, DATA
cmp [reflected],0
jne @f
NoReflect:
push ax
mov al,20h ; eoi
out 0,al
pop ax
pop ds
iret
@@: assumes ds,nothing
push ds
push ax
mov ax, __ROMBIOS
mov ds, ax
cmp word ptr ds:[018ah], 1 ; Q : timer counter end ?
pop ax
pop ds
je short NoReflect
endif ; NEC_98
assumes ds, DATA
; push address
push word ptr prevInt8Proc[2]
push word ptr prevInt8Proc[0]
; restore ds out of stack
push bp
mov bp, sp
mov ds, [bp+6]
assumes ds,nothing
pop bp
; jump to prev proc popping saved ds
retf 2
;----------------------------- Private Function ----------------------------;
;
; Entry: call far ptr timer_int
;
; Returns: nothing
;
; Registers Destroyed: none
;
; History:
; 09-Jan-87 by ronm Added hooks for the high resolution timer fns
; in hitime.asm
; ??-???-?? by ???? Wrote it
;---------------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc timer_int,<FAR,PUBLIC>
cBegin nogen
; Don't trash any registers.
push ds
mov ds,MyCSDS
assumes ds, DATA
add word ptr [cms][0],(res_low / 1000)
adc word ptr [cms][2],0
add [cmsRound],(res_low - ((res_low / 1000) * 1000))
cmp [cmsRound],1000
jb ti0
sub [cmsRound],1000
inc word ptr [cms][0]
jnz ti0
inc word ptr [cms][2]
ti0:
ifdef NEC_98
push dx ; clear int share reg.
push ax
mov dx,879h
in al,dx
pop ax
pop dx
endif ; NEC_98
cmp [enabled],1
jne noevent
inc [enabled]
ifdef NEC_98
cmp [reflected],0
je short ti01
endif ; NEC_98
pushf
; enable IF flag in stack flags to prevInt8Proc if they were
; on when this routine was entered -- this allows the 286 DOS
; extender to enable ints after running real mode Int 8 handler.
FLAGS1 = 3 ; +0 +2 +4 +6 +8 +10
FLAGS2 = 11 ; BP -> [bp] [fl] [ds] [ip] [cs] [fl]
push bp
mov bp,sp
test byte ptr FLAGS2[bp],02h
jz @f
or byte ptr FLAGS1[bp],02h
@@: pop bp
call [prevInt8Proc] ; call previous Int 8 routine
ifdef NEC_98
push ax
mask TIMERMASK
mov al,36h
out timodeset,al ; Timer mode set
delay 8253,O-O
mov ax,0f000h ;count(25msec * 2457.6)
push es
push ax
mov ax,40h
mov es,ax
test byte ptr es:[101h],80h ; Q : clock 2.5 MHz ?
pop ax
pop es
jz @f ;5MHz,10MHz,12MHz,20MHz 25MHz set
mov ax,0c300h ;8MHz,16MHz set
@@:
out ticntset,al
delay 8253,O-O
xchg ah,al
out ticntset,al
unmask TIMERMASK
pop ax
jmp short ti1
ti01:
push ax
mov al,20h ; eoi
out 0,al
pop ax
endif ; NEC_98
public ti1
ti1:
comment ~
FCLI
mov word ptr [prevSSSP][2],ss
mov word ptr [prevSSSP][0],sp
push ds
pop ss
mov sp,codeOffset int8stack
FSTI ; Allow interrupts
end comment ~
push ax
mov al,00001011b ; ask for 8259 status
ifdef NEC_98
out 00h,al
jmp $+2
jmp $+2
in al,00h ; get the status
else ; NEC_98
out 20h,al
jmp $+2
in al,20h ; get the status
endif ; NEC_98
or al,al
jnz TheEnd ; if other pending EOIs, just exit
push bp
push es
push bx
push cx
push dx
push si
push di
xor bp,bp ; No valid BP chain
mov si,doffset TimerTable
nextent:
cld
lodsw ; Get timer rate
.errnz tirate
inc ax ; -1 means unused entry
jnz checkent ; no, check used entry
lodsw ; yes, get timer count
.errnz 2-ticount
inc ax ; another -1 means end of table
jz lastent ; yes, all done
add si,4 ; o.w. skip to next entry
jmp nextent
checkent:
dec ax ; 0 means call at maximum rate
jz callent
dec word ptr DS:[si] ; o.w. decrement rate counter
.errnz 2-ticount
jz callent ; zero means timer has gone off
add si,6 ; o.w. skip to next entry
jmp nextent
callent:
mov DS:[si],ax
inc si
inc si
lea ax,[si-4] ; Pass timer handle in AX
.errnz 4-tiproc
call dword ptr DS:[si]
add si,4
jmp nextent
lastent:
pop di
pop si
pop dx
pop cx
pop bx
pop es
pop bp
TheEnd:
pop ax
dec [enabled]
comment ~
FCLI
mov ss,word ptr [prevSSSP][2]
mov sp,word ptr [prevSSSP][0]
FSTI
end comment ~
pop ds
iret
cEnd nogen
;============================================================================
; DWORD GetSystemMsecCount(void) - returns msec count.
;
assumes ds,nothing
assumes es,nothing
DUserThunk GETSYSTEMMSECCOUNT,0
;LabelFP <PUBLIC, GetSystemMsecCount>
;
; push ds
; mov ds, MyCSDS
; assumes ds, DATA
;
; mov ax,word ptr [cms][0]
; mov dx,word ptr [cms][2]
; pop ds
; retf
;----------------------------- Private Function ----------------------------;
;
; EnableSystemTimers() - enable hardware timer interrupts
;
; Entry: cCall far ptr EnableSystemTimers
;
; Returns: nothing
;
; Registers Destroyed: ??
;
; History:
; 09-Jan-87 by ronm Patched to support hitime.asm
; ??-???-?? by ???? Wrote it
;---------------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc EnableSystemTimers,<FAR,PUBLIC>
cBegin nogen
; All done if just already enabled
push ds
mov ds,MyCSDS
assumes ds, DATA
ifdef WOW
; see if we're being called by Create to really enable tics
cmp cTimers, 1
je est_doit
endif
cmp enabled,0
jne edone
est_doit:
mov [enabled],1
ifdef WOW
; don't install the tic handler if no systemtimers registered
cmp cTimers, 0
je edone
endif
; Save away current timer interrupt vector value
mov ax,3500h or VECTOR
int 21h
mov word ptr [PrevInt8Proc][0],bx
mov word ptr [PrevInt8Proc][2],es
; Setup timer interrupt vector to point to our interrupt routine
mov ax,2500h or VECTOR
push cs
pop ds
mov dx,codeOFFSET timer_int
int 21h
ifdef NEC_98
mask TIMERMASK
mov al,36h
out timodeset,al ; Timer mode set
delay 8253,O-O
mov ax,0f000h ;count(25msec * 2457.6)
push es
push ax
mov ax,40h
mov es,ax
test byte ptr es:[101h],80h ; Q : clock 2.5 MHz ?
pop ax
pop es
jz @f ;5MHz,10MHz,12MHz,20MHz 25MHz set
mov ax,0c300h ;8MHz,16MHz set
@@:
out ticntset,al
delay 8253,O-O
xchg ah,al
out ticntset,al
unmask TIMERMASK
sti
endif ; NEC_98
edone:
pop ds
ret
cEnd nogen
;-----------------------------------------------------------------------;
; DisableSystemTimers
;
; DisableSystemTimers() - disable system timer interrupts, restoring
; the previous timer interrupt handler.
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Mon 21-Nov-1988 18:44:44 -by- David N. Weise [davidw]
; Added this nifty comment block.
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc DisableSystemTimers,<FAR,PUBLIC>
cBegin nogen
push ds
mov ds,MyCSDS
assumes ds, DATA
; Do nothing if not enabled
cmp [enabled],0
je ddone
ifdef NEC_98
mask TIMERMASK
endif ; NEC_98
mov [enabled],0
; Restore the timer interrupt vector to point to previous value
mov ax,2500h or VECTOR
lds dx,prevInt8Proc
int 21h
ddone:
pop ds
ret
cEnd nogen
;-----------------------------------------------------------------------;
; CreateSystemTimer
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Mon 21-Nov-1988 18:44:44 -by- David N. Weise [davidw]
; Added this nifty comment block.
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc CreateSystemTimer,<PUBLIC,FAR>
ParmW rate
ParmD lpproc
cBegin
mov ds,MyCSDS
assumes ds, DATA
mov bx,doffset timerTable
mov ax,rate
or ax,ax
jz ctfirst
mov cx,1000 ; change msecs into ticks.
mul cx
mov cx,res_low
div cx
ctfirst:
FCLI ; beginning of critical section
ctloop:
cmp ds:[bx].tirate,-1
jne ctnext
cmp ds:[bx].ticount,-1
je ctfail
mov cx,OFF_lpproc
mov dx,SEG_lpproc
mov word ptr ds:[bx].tiproc[0],cx
mov word ptr ds:[bx].tiproc[2],dx
mov ds:[bx].ticount,ax
mov ds:[bx].tirate,ax ; Set this last
ifdef WOW
; turn on tics if the count is going from 0 -> 1 and they're
; supposed to be enabled
inc cTimers
cmp cTimers, 1
jne @f
cmp enabled, 0 ; need to turn on tics?
je @f ; -> nope
push bx
call EnableSystemTimers
pop bx
@@:
endif
jmp short ctexit
ctnext: add bx,SIZE tiblock
jmp ctloop
ctfail: xor bx,bx
ctexit: FSTI ; end of critical section
mov ax,bx
mov cx,bx
cEnd
;-----------------------------------------------------------------------;
; KillSystemTimer
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Mon 21-Nov-1988 18:44:44 -by- David N. Weise [davidw]
; Added this nifty comment block.
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc KillSystemTimer,<PUBLIC,FAR>,<di>
parmW htimer
cBegin
mov es,MyCSDS
assumes es,nothing
mov di,doffset TimerTable
mov ax,htimer
ktloop: cmp es:[di].tirate,-1
jne ktmatch
cmp es:[di].ticount,-1
jne ktnext
jmp short ktexit
ktmatch:
cmp di,ax
jne ktnext
cld
mov ax,-1
stosw
not ax
stosw
stosw
stosw
ifdef WOW
dec es:[cTimers] ; was this the last one?
jnz @f ; -> nope
cmp es:[enabled], 0 ; are tics on?
je @f ; -> nope
; Restore the timer interrupt vector to point to previous value
push ax
mov ax,2500h or VECTOR
lds dx,es:[prevInt8Proc]
int 21h
pop ax
@@:
endif
jmp short ktexit
ktnext: add di,SIZE tiblock
jmp ktloop
ktexit: mov cx,ax
cEnd
ifdef NEC_98
LabelFP <PUBLIC, InquireLongInts>
;------- '88/01/07 -----------------------------------
MOV AX,1
; mov ax,cs:[AT_DOS30]
;------------------------------------------------------
mov cx,ax
retf
endif ; NEC_98
sEnd CODE ; End of code segment
END