windows-nt/Source/XPSP1/NT/base/boot/detect/i386/pccarda.asm
2020-09-26 16:20:57 +08:00

495 lines
10 KiB
NASM

title "PcCard IRQ detection"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; pccarda.asm
;
; Abstract:
;
; This module implements the assembly code necessary to support the
; scanning of ISA IRQ's for cardbus controllers.
;
; Author:
;
; Neil Sandlin (neilsa) 10-Dec-1991.
; The "Clear_IR" routines were taken from win9x code (vpicd)
;
; Environment:
;
; x86 Real Mode.
;
; Revision History:
;
;
;--
.xlist
include pccard.inc
.list
.386
_DATA SEGMENT PARA USE16 PUBLIC 'DATA'
_DATA ENDS
_TEXT SEGMENT PARA USE16 PUBLIC 'CODE'
ASSUME CS: _TEXT, DS:NOTHING, SS:NOTHING
;++
;
; clr_ir_int_proc
;
; Routine Description:
;
; Interrupt handler for clearing IR bit. Just EOIs the PICs.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
Clr_IR_Int dw 0 ; Current int # being processed
public clr_ir_int_proc
clr_ir_int_proc proc far
push ax
mov ax, Clr_IR_Int
cmp ax, 8 ; Q: is int on the master PIC?
jb CIP_eoi ; Y: only eoi master PIC
sub ax, 8 ; AL = int on slave PIC
or al, PIC_SPEC_EOI
out PIC_A0, al ; EOI the specific interrupt
mov al, 2 ; EOI the master PIC
CIP_eoi:
or al, PIC_SPEC_EOI
out PIC_20, al ; EOI the specific interrupt
mov al, 0FFh ; Mask all interrupts
out PIC_A1, al
out PIC_21, al
pop ax
iret
clr_ir_int_proc endp
;++
;
; clr_ir_enable_int
;
; Routine Description:
;
;
; Arguments:
;
; EAX = interrupt to hook and enable.
; Interrupts must be disabled on entry.
;
; Return Value:
;
; None.
;
;--
clr_ir_enable_int proc near
push bx
push esi
; Hook interrupt so it can be handled.
mov Clr_IR_Int, ax ; Set current interrupt being processed
cmp ax, 8 ; Q: is int on the master PIC?
jb CIEI_master ; Y: based at 8
add ax, 68h ; N: based at 70h
jmp CIEI_vector
CIEI_master:
add ax, 8
CIEI_vector:
mov bx, ax
shl bx, 2 ; IVT vector offset
push ds
mov ax, 0
mov ds, ax
ASSUME DS:NOTHING
mov si, offset clr_ir_int_proc
xchg word ptr [bx], si ; LSW
ror esi, 16
push cs
pop si
xchg word ptr [bx+2], si ; MSW
ror esi, 16 ; ESI = old handler offset
pop ds
ASSUME DS:_DATA
sti
nop ; allow interrupt to occur
nop
nop
cli
; UnHook interrupt.
push ds
mov ax, 0
mov ds, ax
ASSUME DS:NOTHING
mov word ptr [bx], si ; Restore LSW
ror esi, 16
mov word ptr [bx+2], si ; Restore MSW
pop ds
ASSUME DS:_DATA
pop esi
pop bx
ret
clr_ir_enable_int endp
;++
;
; _Clear_IR_Bits
;
; Routine Description:
;
; This routine and its support routines were copied (and munged) from
; win9x's vxd\vpicd\vpicserv.asm.
;
; Clears the desired Interrupt Request bits in the PIC.
; Interrupt must be masked at the PIC on entry.
;
; Arguments:
;
; [ESP+4] = bit mask of bits to clear
; Interrupts must be disabled on entry.
;
; Return Value:
;
; None.
;
;--
public _Clear_IR_Bits
_Clear_IR_Bits proc near
push bp
mov bp, sp
BitMask equ [bp+4]
push eax
push ebx
push ecx
push edx
mov bx, BitMask ; BX = mask to clear
or bx, bx ; Are there any bits to clear?
jz CIB_exit ; no, return
pushfd
cli
in al, PIC_A1
mov ah, al
in al, PIC_21
push eax
mov al, 0FFh
out PIC_A1, al
; Walk each bit from the lowest bit to highest on each controller.
mov ecx, 01h ; CL = test mask
CIB_loop20:
test bl, cl
jz CIB_next20
mov al, cl
not al
out PIC_21, al ; Unmask the specific interrupt
bsf eax, ecx
call clr_ir_enable_int ; Hook interrupt and enable it
mov al, 0FFh ; Mask all interrupts
out PIC_21, al
CIB_next20:
shl cl, 1
jnz CIB_loop20 ; Clear next bit
; Setup for second PIC. Handle the second controller by setting
; up both PICs, since they are chained.
mov bl, bh ; BL = second PICs mask to clear
mov cl, 01h ; CL = test mask
CIB_loopA0:
test bl, cl
jz CIB_nextA0
mov al, 0FBh ; Mask for chained master PIC
out PIC_21, al ; Unmask the specific interrupt
mov al, cl
not al
out PIC_A1, al ; Unmask the specific interrupt
xchg cl, ch
bsf eax, ecx
call clr_ir_enable_int ; Hook interrupt and enable it
xchg cl, ch
mov al, 0FFh ; Mask all interrupts
out PIC_A1, al
out PIC_21, al
CIB_nextA0:
shl cl, 1
jnz CIB_loopA0 ; Clear next bit
pop eax
out PIC_21, al
mov al, ah
out PIC_A1, al
popfd
CIB_exit:
pop edx
pop ecx
pop ebx
pop eax
mov sp, bp
pop bp
ret
_Clear_IR_Bits endp
;++
;
; GetPCIType1Data
;
; Routine Description:
;
; Arguments:
;
; Return Value:
;
; None.
;
;--
public _GetPCIType1Data
_GetPCIType1Data proc near
push bp
mov bp, sp
push bx
push di
gpd_addr equ [bp+4]
gpd_offset equ [bp+8]
gpd_buffer equ [bp+10]
gpd_width equ [bp+12]
mov dx, PCI_TYPE1_ADDR_PORT
mov eax, gpd_addr
out dx, eax
mov bx, gpd_buffer
mov dx, gpd_offset
add dx, PCI_TYPE1_DATA_PORT
mov di, gpd_width
cmp di, 1
jnz @f
in al, dx
mov [bx], al
jmp gpd_exit
@@:
cmp di, 2
jnz @f
in ax, dx
mov [bx], al
mov [bx+1], ah
jmp gpd_exit
@@:
cmp di, 4
jnz gpd_exit
in eax, dx
mov [bx], al
mov [bx+1], ah
shr eax, 16
mov [bx+2], al
mov [bx+3], ah
gpd_exit:
pop di
pop bx
mov sp, bp
pop bp
ret
_GetPCIType1Data endp
;++
;
; SetPCIType1Data
;
; Routine Description:
;
; Arguments:
;
; Return Value:
;
; None.
;
;--
public _SetPCIType1Data
_SetPCIType1Data proc near
push bp
mov bp, sp
push bx
push di
spd_addr equ [bp+4]
spd_offset equ [bp+8]
spd_buffer equ [bp+10]
spd_width equ [bp+12]
mov dx, PCI_TYPE1_ADDR_PORT
mov eax, spd_addr
out dx, eax
mov bx, spd_buffer
mov dx, spd_offset
add dx, PCI_TYPE1_DATA_PORT
mov di, spd_width
cmp di, 1
jnz @f
mov al, [bx]
out dx, al
jmp spd_exit
@@:
cmp di, 2
jnz @f
mov al, [bx]
mov ah, [bx+1]
out dx, ax
jmp spd_exit
@@:
cmp di, 4
jnz spd_exit
mov al, [bx+2]
mov ah, [bx+3]
shl eax, 16
mov al, [bx]
mov ah, [bx+1]
out dx, eax
spd_exit:
pop di
pop bx
mov sp, bp
pop bp
ret
_SetPCIType1Data endp
;++
;
; TimeOut
;
; Routine Description:
;
; This routine implements a stall for waiting on hardware. It uses the
; PC timer hardware (8237). The caller needs to insure that this hardware
; exists on the machine before calling this function.
;
; The function will take as input the count, and decrement the count
; matching the timer hardware's count. It returns when the count reaches
; zero. The caller must insure that the clock is programmed at the
; desired rate.
;
; Arguments:
;
; Count - number of clock ticks to wait (approx 840ns per tick)
;
; Return Value:
;
; None.
;
;--
public _TimeOut
_TimeOut proc near
TMCTRL_LATCHCNT0 equ 0d2h
TIMERPORT_CONTROL equ 43h
TIMERPORT_CNT0 equ 40h
push bp
mov bp, sp
push cx
push si
push di
to_count equ [bp+4]
mov dx, TIMERPORT_CONTROL
mov al, TMCTRL_LATCHCNT0
out dx, al
mov dx, TIMERPORT_CNT0
in al, dx
mov ah, al
in al, dx
xchg ah, al
mov si, ax
xor cx, cx
; si = prevtime
; cx = ExpireTime
timeloop:
mov dx, TIMERPORT_CONTROL
mov al, TMCTRL_LATCHCNT0
out dx, al
mov dx, TIMERPORT_CNT0
in al, dx
mov ah, al
in al, dx
xchg ah, al
mov di, ax
cmp ax, si
jbe @f
; wrapped
neg ax
add ax, si
add cx, ax
jmp timeincr
@@:
sub si, ax
add cx, si
timeincr:
mov si, di
cmp cx, to_count
jb timeloop
pop di
pop si
pop cx
mov sp, bp
pop bp
ret
_TimeOut endp
_TEXT ends
end