📄 uhci.asm
字号:
mov (Transfer_Descriptor ptr [di]).TD_Buffer_Pointer, eax
mov (Transfer_Descriptor ptr [di]).CSReloadValue, TWO_ERRORS
mov (Transfer_Descriptor ptr [di]).pCallback, offset cgroup:RepeatTdCallback
add (Transfer_Descriptor ptr [di]).pCallback, orgbase
mov (Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
; Set TdRepeat's Link Pointer to Control Queue Head
mov eax, HcdDataArea
add eax, offset QhControl
or eax, QUEUE_HEAD ;EDX = seg containing TDs
mov (Transfer_Descriptor ptr [di]).TD_Link_Pointer, eax
; Initialize QhControl. The queue normally has no TDs in it. TDs are placed
; into the queue only when initializing a device (see UsbDeviceRequest
; function above).
mov di, offset QhControl
mov (Q_Head ptr [di]).Q_Head_Link_Pointer, TERMINATE
mov (Q_Head ptr [di]).Q_Element_Link_Pointer, TERMINATE
; Hook the interrupt that has been assigned to the host controller.
ifdef DOS_DEBUG
mov bx, UsbHcBusDevFuncNum
mov di, USB_IRQ_LEVEL
mov si, PCI_REG_ADDRESS_BYTE
call smi_pci_read_cfg ;Returns CL = IRQ level assigned to HC
mov HC_Interrupt_Level, cl
add cl, 8 ;IRQ 0/1/../7 -> INT 8/9/../F
cmp cl, 10h
jb InitVector ;Br if IRQ 0..7
add cl, 70h - 10h ;Add offset of second 8259's vectors
InitVector:
movzx bx, cl ;BX = HC's interrupt vector
shl bx, 2 ;BX = addr of interrupt vector to hook
mov ax, cs ;AX = CS
shl eax, 16 ;Put CS in upper half of EAX
mov ax, offset cgroup:UsbHcIsr ;EAX = CS:Offset of USB's ISR
push ds
push 0 ;Set DS = 0
pop ds
mov dword ptr [bx], eax ;Hook interrupt
pop ds
else
; Enable the HC's SMI generation on port 60/64 read/write and USB interrupt.
mov bx, UsbHcBusDevFuncNum
call EnableKBCTraps ;Returns CL[3:0] = 60/64 r/w trap flags
or cl, 10h ;Always enable SMI on USB interrupt
call UsbHcChipsetInit
endif
; Unmask the host controller's IRQ level in the 8259
ifdef DOS_DEBUG
mov cl, HC_Interrupt_Level ;CL = IRQ used by the HC (0..15)
mov bx, 1
shl bx, cl ;BX = bit map with one bit set
not bx ;BX = bit map with one bit clear
in al, 21h ;AL = First 8259's mask reg
and al, bl ;Adjust mask
out 21h, al ;Write mask back
in al, 0A1h ;AL = Second 8259's mask reg
and al, bh ;Adjust mask
out 0A1h, al ;Write mask back
endif
; Enable interrupts from the host controller
mov ax, IOC_ENABLE OR TIMEOUT_CRC_ENABLE
mov dx, USB_INTERRUPT_ENABLE
call WriteUsbIoRegWord ;Enable IOC, timeout, CRC interrupts
; Start the host controller and set the configured flag in the host controller
; to signal that it is up and running under BIOS control.
mov ax, HOST_CONTROLLER_RUN or CONFIGURE_FLAG
mov dx, USB_COMMAND_REG
call WriteUsbIoRegWord ;Start the host controller running
UsbInitDone:
ifdef DOS_DEBUG
pop es
pop ds
endif
popad
ret
_UsbHcInit endp
;---------------------------------------;
; UsbHcClose ;
;---------------------------------------;--------------------------------------;
; This function shuts down and disables the USB host controller. ;
; ;
; Input: Nothing ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
_UsbHcClose proc near
pusha
ifdef DOS_DEBUG
push ds
push es
push DOS_DEBUG_DATA_AREA
push DOS_DEBUG_DATA_AREA
pop ds
pop es
endif
; Stop the host controller
mov dx, USB_COMMAND_REG
call ReadUsbIoRegWord ;AX = HC command reg
and al, NOT HOST_CONTROLLER_RUN
call WriteUsbIoRegWord ;Write back to HC command reg
; Disable interrupts from the host controller
xor ax, ax
mov dx, USB_INTERRUPT_ENABLE
call WriteUsbIoRegWord ;Disable all HC interrupts
; Disable the HC's SMI generation on port 60/64 read/write and USB interrupt.
;; mov bx, UsbHcBusDevFuncNum
call GetUsbHcBusDevFunc ;Returns BX = b/d/f, destroys AX,ECX,EDX
jc @f ;Br if USB HC not found
call UsbHcChipsetShutdown
@@:
; Turn off ports
mov ax,01ffh
call UsbDisableRootHubPort
mov ax,02ffh
call UsbDisableRootHubPort
; Unconfigure everything
mov dx, USB_COMMAND_REG
mov ax,0
call WriteUsbIoRegWord ;Write to HC command reg
; Mask the host controller's IRQ level in the 8259
ifdef DOS_DEBUG
mov cl, HC_Interrupt_Level ;CL = IRQ used by the HC (0..15)
mov bx, 1
shl bx, cl ;BX = bit map with one bit set
in al, 21h ;AL = First 8259's mask reg
or al, bl ;Adjust mask
out 21h, al ;Write mask back
in al, 0A1h ;AL = Second 8259's mask reg
or al, bh ;Adjust mask
out 0A1h, al ;Write mask back
endif
; Unhook the interrupt that has been assigned to the host controller.
ifdef DOS_DEBUG
;..........................
endif
ifdef DOS_DEBUG
pop es
pop ds
endif
popa
ret
_UsbHcClose endp
;---------------------------------------;
; UsbHcIsr ;
;---------------------------------------;--------------------------------------;
; This is the main entry point that handles all interrupts generated by the ;
; USB host controller. ;
; ;
; Input: DS = ES Usb Data Area ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
UsbHcIsr proc near
pushad
ifdef DOS_DEBUG
push ds
push es
push DOS_DEBUG_DATA_AREA
push DOS_DEBUG_DATA_AREA
pop ds
pop es
endif
; Clear interrupt status in the host controller
mov dx, USB_STATUS_REG
call ReadUsbIoRegWord ;AX = HC status reg
call WriteUsbIoRegWord ;Write back to HC status reg to clear
; Loop through all of the TDs. For any TD whose ActiveFlag is TRUE and
; is completed (TD_Control_Status bit 23 clear), process the TD by calling
; its callback routine.
mov di, offset TdPool ;DI = offset of first TD in array
ServiceTdNextTd:
call ProcessTdIfNeeded ;Check if complete and do callback
add di, size Transfer_Descriptor
cmp di, offset TdPoolEnd
jb ServiceTdNextTd ;Br if more TDs to service
; Clear interrupt status in the host controller again..................
mov dx, USB_STATUS_REG
call ReadUsbIoRegWord ;AX = HC status reg
call WriteUsbIoRegWord ;Write back to HC status reg to clear
; Issue EOI to the 8259
ifdef DOS_DEBUG
mov al, 20h ;AL = EOI command
cmp HC_Interrupt_Level, 8
jb IsrEoiPri ;Br if using IRQ 0..7 (2nd 8259 needs no EOI)
out 0A0h, al
jcxz $+2
jcxz $+2
IsrEoiPri:
out 20h, al
jcxz $+2
jcxz $+2
endif
ifdef DOS_DEBUG
pop es
pop ds
endif
popad
ifdef DOS_DEBUG
iret
else
ret
endif
UsbHcIsr endp
;---------------------------------------;
; ProcessTdIfNeeded ;
;---------------------------------------;--------------------------------------;
; This function examines a TD and determines if it has completed. If the TD ;
; has completed, the TD's callback routine is given control. ;
; ;
; Input: DS:DI = Pointer to TD that completed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ProcessTdIfNeeded proc near
cmp (Transfer_Descriptor ptr [di]).ActiveFlag, TRUE
jne @f ;Br if TD is not active
test (Transfer_Descriptor ptr [di]).TD_Control_Status, ACTIVE
jnz @f ;Br if TD is not completed
cmp (Transfer_Descriptor ptr [di]).pCallback, 0
jz @f ;Br if TD's callback ptr is NULL
call (Transfer_Descriptor ptr [di]).pCallback
@@:
ret
ProcessTdIfNeeded endp
;---------------------------------------;
; PollingTdCallback ;
;---------------------------------------;--------------------------------------;
; This function is called when a polling TD from the TD pool completes an ;
; interrupt transaction to its assigned device. This routine should process ;
; any data in the TD's data buffer, handle any errors, and then copy the ;
; TD's CSReloadValue field into its TD_Control_Status field to put the TD back ;
; into service. ;
; ;
; Input: DS:DI = Pointer to TD that completed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
PollingTdCallback proc near
push eax
push bx
push si
mov (Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
test (Transfer_Descriptor ptr [di]).TD_Control_Status, STATUS_FIELD
jnz PollingTdError ;Br if any error bit is set in status
mov dx, USB_FRAME_NUM
call ReadUsbIoRegWord ;AX[10:0] = Frame number
mov cx, ax ;BX[10:0] = Frame number
mov ax, word ptr ((Transfer_Descriptor ptr [di]).TD_Token)
and ah, (DEVICE_ADDRESS shr 8) ;AH = Device address (1..7F)
lea si, (Transfer_Descriptor ptr [di]).DataArea
push ax
mov al, size DeviceTableEntry
mul ah ;AX = offset of DeviceTableEntry in DeviceTable
mov bx, ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -