Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

305 lines
7.4 KiB

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; STARTEND.ASM
;
; Copyright (c) Microsoft Corporation 1989, 1990. All rights reserved.
;
; This module contains the routines which initialize, and clean
; up the driver after Libentry/WEP/Enable/Diable called by windows.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
?PLM=1 ; pascal call convention
?WIN=0 ; Windows prolog/epilog code
?DF=1
PMODE=1
.xlist
include cmacros.inc
include int31.inc
include windows.inc
include mmddk.inc
include mmsystem.inc
include timer.inc
.list
externA __WinFlags
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Local data segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sBegin DATA
; ISR support
public lpOLDISR
lpOldISR dd ?
ifdef RMODE_INT
public RModeOldISR
RModeOldISR dd 0
public RModeCodeSegment
RModeCodeSegment dw ?
endif ;RMODE_INT
externW Events
externW wNextTime
ifdef NEC_98
externB bClockFlag ; 5Mhz = 0 ; 8Mhz = other
endif ; NEC_98
sEnd DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Code segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
externFP tddISR ; in local.asm
externFP tddSetInterruptPeriodFar ; in timer.asm
ifdef RMODE_INT
externW RmodeDataSegment ; in local.asm
externFP tddRModeISR ; in local.asm
endif
externFP GetSelectorBase ; kernel
externFP AllocCStoDSAlias ; kernel
externFP FreeSelector ; kernel
sBegin CodeInit
assumes cs,CodeInit
assumes ds,Data
assumes es,nothing
;----------------------------Private-Routine----------------------------;
; SegmentFromSelector
;
; Converts a selector to a segment...note that this routine assumes
; the memory pointed to by the selector is below the 1Meg line!
;
; Params:
; AX = selector to convert to segment
;
; Returns:
; AX = segment of selector given
;
; Error Returns:
; None
;
; Registers Destroyed:
; none
;
;-----------------------------------------------------------------------;
assumes ds,Data
assumes es,nothing
SegmentFromSelector proc near
cCall GetSelectorBase,<ax> ;DX:AX = base of selector
rept 4
shr dx,1
rcr ax,1
endm
;AX now points to *segment* (iff selector is based below 1Mb)
ret
SegmentFromSelector endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; @doc INTERNAL
;
; @api WORD | Enable | This function enables the driver. It
; will hook interrupts and validate the hardware.
;
; @rdesc Returns 1 if successfull, and 0 otherwise.
;
; @comm This function is automatically invoked when the library is
; first loaded. It is included so that win386 could call it
; when it switches VMs.
;
; @xref Disable
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cProc Enable286 <FAR, PUBLIC> <si, di>
cBegin
; make sure clock interrupts are disabled until after
; service routine has been initialized!!
AssertSLI
cli
; get the currently owned timer interrupt vector
; get interrupt vector, and specify timer interrupt number
; mov ax,03500H + TIMERINTERRUPT
; push es
; int 21h ; get the current vector in ES:BX
; mov lpOldISR.Sel,es
; mov lpOldISR.Off,bx ; save the old vector
; pop es
;
; ; set vector to our isr
;
; ; set interrupt vector function, and specify the timer interrupt number
; mov ax,02500h + TIMERINTERRUPT
; push ds
; mov dx,seg tddISR
; mov ds,dx
; assumes ds,nothing
; mov dx,offset tddISR
; int 21h ; set the new vector
; pop ds
; assumes ds,DATA
;
; mov ax,[wNextTime]
; not ax
; mov [wNextTime],ax ; force set of period
; call tddSetInterruptPeriodFar
ifdef RMODE_INT
;
; if running under DOSX set the RMODE interrupt too
;
mov ax,__WinFlags
test ax,WF_PMODE
jz enable_no_dosx
mov ax,seg tddRModeISR
call SegmentFromSelector
or dx,dx ; ACK! above 1Mb
jnz enable_no_dosx
mov [RModeCodeSegment],ax ; save the segment of the code segment
mov ax,ds ; get SEGMENT of our data segment
call SegmentFromSelector
push ax ; save on stack
mov ax,seg tddRModeISR ; write data SEGMENT into _INTERRUPT
cCall AllocCStoDSAlias,<ax> ; code segment -- requires a data alias
mov es,ax
pop ax
mov es:[RModeDataSegment],ax
cCall FreeSelector,<es> ; don't need CS alias any longer
mov ax,Get_RM_IntVector ; get the real mode IRQ0 vector
mov bl,DOSX_IRQ + TIMERINTERRUPT
int 31h ; DOSX get real mode vector in CX:DX
mov RModeOldISR.lo,dx ; save old ISR
mov RModeOldISR.hi,cx
mov cx,RModeCodeSegment ; CX:DX --> real mode ISR
mov dx,offset tddRModeISR
mov ax,Set_RM_IntVector ; DOSX Set Vector Function
int 31h ; Set the DOS vector real mode
enable_no_dosx:
endif
sti
mov ax,1
cEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; @doc INTERNAL
;
; @api WORD | Disable | This function disables the driver.
; It disables the hardware, unhooks interrupts and removes
; all time events from the queue.
;
; @rdesc Returns 1 if successfull, and 0 otherwise.
;
; @comm This function is called automatically when Windows unloads
; the library and invokes the WEP() function. It is included
; here so that WIN386 can use it when switching VMs.
;
; @xref Enable
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cProc Disable286 <FAR, PUBLIC> <si, di>
; note that all this is in the reverse order to Enable
cBegin
AssertSLI
cli
ifdef NEC_98
setmask TIMERMASK
mov al,36h
out timodeset,al ; Timer mode set
delay 8253,O-O
mov ax,0f000h ; count(25msec * 2457.6)
cmp byte ptr bClockFlag,00h ; Q : clock 5 MHz ?
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
else ; NEC_98
; set timer back to 55ms BIOS service
xor cx,cx ; 65536 ticks per period
mov al,TMR_MODE3_RW ; Read/Write counter 0 mode 3 (two bytes)
out TMR_CTRL_REG,al
mov al,cl
out TMR_CNTR_0,al ; write low byte
mov al,ch
out TMR_CNTR_0,al ; write high byte
endif ; NEC_98
ifdef RMODE_INT
;
; check for a REAL mode int handler and un-hook it.
;
mov dx,RModeOldISR.lo
mov cx,RModeOldISR.hi
jcxz disable_no_dosx
mov bl,DOSX_IRQ + TIMERINTERRUPT
mov ax,Set_RM_IntVector ;DOSX Set Vector Function
int 31h ;Set the DOS vector real mode
disable_no_dosx:
endif
; restore the old interrupt vector
mov ax,02500h + TIMERINTERRUPT
; set interrupt vector function, and specify the timer interrupt number
push ds
lds dx,lpOldISR
assumes ds,nothing
int 21h ; reset the old vector
pop ds
assumes ds,DATA
sti
mov ax,1
cEnd
sEnd
end