📄 uhci.asm
字号:
add bx, offset DeviceTable ;BX = ptr to DeviceTableEntry
pop ax
call (DeviceTableEntry ptr [bx]).pDeviceCallback
PollingTdError:
mov eax, (Transfer_Descriptor ptr [di]).CSReloadValue
mov (Transfer_Descriptor ptr [di]).TD_Control_Status, eax
xor (Transfer_Descriptor ptr [di]).TD_Token, DATA_TOGGLE
mov (Transfer_Descriptor ptr [di]).ActiveFlag, TRUE
pop si
pop bx
pop eax
ret
PollingTdCallback endp
;---------------------------------------;
; ControlTdCallback ;
;---------------------------------------;--------------------------------------;
; This function is called when the ControlSetup and ControlData TDs complete a ;
; control transaction to the assigned device. ;
; ;
; Input: DS:DI = Pointer to TD that completed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ControlTdCallback proc near
push eax
push ebx
; Check to see if the TD that just completed has any error bits set. If
; any of the ControlTds (Setup, Data, or Status) complete with an error, set
; ActiveFlag of the TdControlStatus and copy the error information from the
; TD that just completed into the TdControlStatus.
mov eax, (Transfer_Descriptor ptr [di]).TD_Control_Status
test eax, STATUS_FIELD
jz ControlNoError ;Br if the TD completed with no error
mov TdControlStatus.TD_Control_Status, eax
mov TdControlStatus.ActiveFlag, FALSE
jmp short ControlDone
; Check the amount of data tranferred by the TD that just completed. If
; less than a full packet was transferred, then the device has no more
; data to send. In this case we should point the QhControl's
; Q_Element_Link_Pointer field to the TdControlStatus because that the
; remaining TdControlData TDs are not needed.
ControlNoError:
mov eax, (Transfer_Descriptor ptr [di]).TD_Control_Status
and ax, ACTUAL_LENGTH ;AX = actual byte count - 1
mov ebx, (Transfer_Descriptor ptr [di]).TD_Token
shr ebx, 21 ;BX = expected byte count - 1
cmp ax, bx
je ControlDone ;Br if actual = expected count
mov bx, offset QhControl
mov eax, HcdDataArea ;EAX = seg containing TDs
add eax, offset TdControlStatus ;EAX = abs addr of TdControlStatus
mov (Q_Head ptr [bx]).Q_Element_Link_Pointer, eax
; Make the TD that just completed inactive. It may be the TdControlSetup,
; one of the TdControlData TDs, or the TdControlStatus.
ControlDone:
mov (Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
pop ebx
pop eax
ret
ControlTdCallback endp
;---------------------------------------;
; RootHubTdCallback ;
;---------------------------------------;--------------------------------------;
; This function is called when the TdRootHub completes a transaction. This ;
; TD runs a dummy interrupt transaction to a non-existant device address for ;
; the purpose of generating a periodic timeout interrupt. This periodic ;
; interrupt may be used to check for new devices on the root hub etc. ;
; ;
; Input: DS:DI = Pointer to TD that completed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
RootHubTdCallback proc near
push eax
push dx
; First deactivate the TdRootHub so this callback function will not get
; reentered.
mov (Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
; Mask the Host Controller interrupt so the ISR does not get re-entered due
; to an IOC interrupt from any TDs that complete in frames while we are
; configuring a new device that has just been plugged in.
xor ax, ax
mov dx, USB_INTERRUPT_ENABLE
call WriteUsbIoRegWord ;Disable IOC, timeout, CRC interrupts
; Check ports 1 and 2 on the root hub for any change in connect status. If the
; connect status has been changed on either or both of these ports, then call the
; routine UsbHubPortChange for each changed port.
mov dx, USB_PORT1_CONTROL
call ReadUsbIoRegWord ;AX = value from port 1 control reg
test al, CONNECT_STATUS_CHANGE
jz @f ;Br if no change for port 1
mov ax, 01FFh ;AH = port number, AL = device addr (FF=root hub)
call UsbHubPortChange ;Process the connection/disconnection
mov dx, USB_PORT1_CONTROL
call ReadUsbIoRegWord ;AX = value from port 1 control reg
call WriteUsbIoRegWord ;Write back to clear the change bit
@@:
mov dx, USB_PORT2_CONTROL
call ReadUsbIoRegWord ;AX = value from port 2 control reg
test al, CONNECT_STATUS_CHANGE
jz @f ;Br if no change for port 2
mov ax, 02FFh ;AH = port number, AL = device addr (FF=root hub)
call UsbHubPortChange ;Process the connection/disconnection
mov dx, USB_PORT2_CONTROL
call ReadUsbIoRegWord ;AX = value from port 2 control reg
call WriteUsbIoRegWord ;Write back to clear the change bit
@@:
; Call the USB keyboard code's periodic entry point. The keyboard code uses
; this periodic call to check the state of the keyboard LED status byte
; (at 40:17) and resync the USB keyboard's LEDs to match that byte if needed.
call OneSecondPeriodicHandler
; Renable 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
; Reactivate the TdRootHub
mov eax, (Transfer_Descriptor ptr [di]).CSReloadValue
mov (Transfer_Descriptor ptr [di]).TD_Control_Status, eax
xor (Transfer_Descriptor ptr [di]).TD_Token, DATA_TOGGLE
mov (Transfer_Descriptor ptr [di]).ActiveFlag, TRUE
pop dx
pop eax
ret
RootHubTdCallback endp
;---------------------------------------;
; RepeatTdCallback ;
;---------------------------------------;--------------------------------------;
; This function is called when TdRepeat completes a transaction. This ;
; TD runs a dummy interrupt transaction to a non-existant device address for ;
; the purpose of generating a periodic timeout interrupt which in turn is used ;
; to generate keyboard repeat. ;
; ;
; Input: DS:DI = Pointer to TD that completed ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
RepeatTdCallback proc near
push eax
; First deactivate the TdRepeat so this callback function will not get
; reentered.
mov (Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
call PeriodicInterruptHandler
; Reactivate the TdRepeat
mov eax, (Transfer_Descriptor ptr [di]).CSReloadValue
mov (Transfer_Descriptor ptr [di]).TD_Control_Status, eax
xor (Transfer_Descriptor ptr [di]).TD_Token, DATA_TOGGLE
;;; mov (Transfer_Descriptor ptr [di]).ActiveFlag, TRUE
pop eax
ret
RepeatTdCallback endp
;---------------------------------------;
; EnablePeriodicInterrupt ;
;---------------------------------------;--------------------------------------;
; This function enables the periodic interrupt. ;
;
;
; AL = Value to write to register ;
; DS = Segment containing IO_Space_Base_Address variable ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
WriteUsbIoRegByte proc near
push dx
add dx, IO_Space_Base_Address
out dx, al
pop dx
ret
WriteUsbIoRegByte endp
;---------------------------------------;
; ReadUsbIoRegWord ;
;---------------------------------------;--------------------------------------;
; This function reads a word from the given register in the USB host ;
; controller. ;
; ;
; Input: DX = Register offset to read ;
; DS = Segment containing IO_Space_Base_Address variable ;
; ;
; Output: AX = Value read from register ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ReadUsbIoRegWord proc near
push dx
add dx, IO_Space_Base_Address
in ax, dx
pop dx
ret
ReadUsbIoRegWord endp
;---------------------------------------;
; WriteUsbIoRegWord ;
;---------------------------------------;--------------------------------------;
; This function writes a word to the given register in the USB host ;
; controller. ;
; ;
; Input: DX = Register offset to write ;
; AX = Value to write to register ;
; DS = Segment containing IO_Space_Base_Address variable ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
WriteUsbIoRegWord proc near
push dx
add dx, IO_Space_Base_Address
out dx, ax
pop dx
ret
WriteUsbIoRegWord endp
;---------------------------------------;
; ReadUsbIoRegDword ;
;---------------------------------------;--------------------------------------;
; This function reads a dword from the given register in the USB host ;
; controller. ;
; ;
; Input: DX = Register offset to read ;
; DS = Segment containing IO_Space_Base_Address variable ;
; ;
; Output: EAX = Value read from register ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
ReadUsbIoRegDword proc near
push dx
add dx, IO_Space_Base_Address
in eax, dx
pop dx
ret
ReadUsbIoRegDword endp
;---------------------------------------;
; WriteUsbIoRegDword ;
;---------------------------------------;--------------------------------------;
; This function writes a dword to the given register in the USB host ;
; controller. ;
; ;
; Input: DX = Register offset to write ;
; EAX = Value to write to register ;
; DS = Segment containing IO_Space_Base_Address variable ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
WriteUsbIoRegDword proc near
push dx
add dx, IO_Space_Base_Address
out dx, eax
pop dx
ret
WriteUsbIoRegDword endp
assume ds:nothing
assume es:nothing
assume cs:nothing
_text ends
end
;*****************************************************************;
;*****************************************************************;
;** **;
;** (C)Copyright 1985-1996, American Megatrends, Inc. **;
;** **;
;** All Rights Reserved. **;
;** **;
;** 6145-F Northbe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -