📄 uhci.asm
字号:
; Check for endpoint STALL condition
test (UHCI_TD PTR [di]).ControlStatus, UHCI_TD_STALLED
jz UBTS_NotStalled
; Bulk stall condition is checked and cleared elsewhere
or bLastCommandStatus, USB_BULK_STALLED
jmp SHORT UBTS_ErrorExit
UBTS_NotStalled:
; Calculate amount of data transferred and return the value
mov di, pBulkDataTD
UBTS_NextTD:
mov eax, (UHCI_TD PTR [di]).ControlStatus
and ax, UHCI_TD_DATA_LENGTH ; AX = actual byte count - 1
or ax, ax ; Assume zero as zero!!!!
jnz UBTS_Cnt
; Check for short packet detect
test eax, UHCI_TD_SHORT_PACKET_DETECT
jnz UBTS_SizeOkay
UBTS_Cnt:
inc ax
cmp ax, (UHCI_TD_DATA_LENGTH+1) ; (07FFh + 1)
jne UBTS_SizeOkay
; Zero length. Set ax accordingly
xor ax, ax
UBTS_SizeOkay:
; Add to total size transferred
add wRetStatus, ax
mov ebx, (UHCI_TD PTR [di]).LinkPointer
test ebx, UHCI_TERMINATE
jnz UBTS_EndLoop
; Mask off low order bits
and bl, NOT UHCI_VERTICAL_FLAG
sub ebx, HcdGlobalDataArea ; Point to next TD
mov di, bx
jmp SHORT UBTS_NextTD
UBTS_EndLoop:
UBTS_ErrorExit:
; Free bulk data TDs
mov ax, pBulkDataTD
call UHCI_FreeTD
UBTS_Exit:
mov ax, wRetStatus
ret
UHCI_BulkTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCI_InterruptTransfer
;
; Description: This function executes an interrupt transaction on the USB.
; The data transfer direction is always DATA_IN. This
; function wil not return until the request either completes
; successfully or completes in error (due to time out, etc.)
;
; Input: DI Pointer to HCStruc of the host controller
; SI DeviceInfo structure
; DX Buffer containing data to be sent to the device or
; buffer to be used to receive data
; CX number of bytes of data to be transferred in
;
; Output: AX 0xFFFF SUCCESS
; AX 0 ERROR
;
; Modified: EAX
;
; Notes: DO NOT TOUCH THE LINK POINTER OF THE TDInterruptData. It is
; statically allocated and linked with other items in the
; 1ms schedule
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCI_InterruptTransfer PROC NEAR SYSCALL PUBLIC
push bx
push ecx
push edx
push si
push di
push fs
; Set return status as failure
xor eax, eax
mov fs, ax ; Return status
; Change Seg:Off in fpBuffer to 32 bit absolute address
push ds
pop ax
shl eax, 4
movzx edx, dx
add edx, eax
; Check for 0 length transfer (if so, exit)
or cx, cx
je UIT_Exit
mov bx, (HCStruc PTR [di]).pDescriptorPtr
; Init Active flag in the interrupt data TD to FALSE
mov bx, (UHCIDescriptors PTR [bx]).TDInterruptData
mov (UHCI_TD PTR [bx]).ActiveFlag, FALSE
; Set the endpoint speed
movzx eax, (DeviceInfo PTR [si]).bEndPointSpeed
; AL = 11/01/10 for HI/LO/FULL
and al, 1 ; Mask off MSH
shl eax, 26
or eax, (UHCI_TD_INTERRUPT_ON_COMPLETE OR UHCI_TD_THREE_ERRORS)
mov (UHCI_TD PTR [bx]).ControlStatus, eax
; Set the buffer pointer
mov (UHCI_TD PTR [bx]).BufferPointer, edx
xor edx, edx
; Now EDX is free form the device address in it
mov dl, (DeviceInfo PTR [si]).bDeviceAddress
; EDX[6:0] = Device address
mov di, (DeviceInfo PTR [si]).pMassInfoPtr
; Form device address and endpoint in proper order and bit position
movzx eax, (DeviceInfo PTR [si]).bIntEndpoint
; EAX[3:0] = Endpoint
shl eax, 7 ; EAX[10:7] = Endpoint
or edx, eax
shl edx, 8 ; EDX[18:8] = DevAddr & Endp
; Fill in various fields in the interrupt data TD
; Set length field
mov eax, ecx ; wLength = data length
dec ax ; AX = packet data size - 1
shl eax, 21
or edx, eax ; EDX[18:8]=Dev. addr & endp
push si
cmp (MassDeviceInfo PTR [di]).pLUN0DevInfoPtr, 0
je UIT_ToggleBitDone
mov si, (MassDeviceInfo PTR [di]).pLUN0DevInfoPtr
UIT_ToggleBitDone:
mov al, (DeviceInfo PTR [si]).bDataSync
and al, USB_INT_DATA_SYNC
shr al, USB_INT_DATA_SYNC_SHIFT
mov dl, IN_PACKET ; EAX[7:0] = IN PID
test al, 1
jz UIT_DataToggle ; DATA0 packet
or edx, DATA_TOGGLE ; Make packet into a data 1
UIT_DataToggle:
mov (UHCI_TD PTR [bx]).Token, edx
xor al, 1 ; Toggle between DATA1/DATA0
push ax
; Update the data toggle value into the structure
mov cl, USB_INT_DATA_SYNC_SHIFT
; Reset toggle bit
mov al, 1
shl al, cl
not al
and (DeviceInfo PTR [si]).bDataSync, al
pop ax ; AL - Updated data toggle
; Set toggle bit appropriately
shl al, cl
or (DeviceInfo PTR [si]).bDataSync, al
pop si
mov (UHCI_TD PTR [bx]).CSReloadValue, 0
mov (UHCI_TD PTR [bx]).pCallback, OFFSET cs:UHCI_InterruptTDCallback
mov (UHCI_TD PTR [bx]).ActiveFlag, TRUE
; Activate the TDInterruptData TD
or (UHCI_TD PTR [bx]).ControlStatus, UHCI_TD_ACTIVE
mov di, bx ; TD pointer
mov bx, si ; DeviceInfo pointer
; Now wait for the interrupt data TD to complete.
; BX - DeviceInfo Ptr, DI - TD to wait on
call UHCIWaitForTransferComplete
; SI - HCStruc Ptr (returned from UHCIWaitForTransferComplete)
; Finally check for errors in the completed interrupt data TD
; If the TD did not complete successfully, return with error.
test (UHCI_TD PTR [di]).ControlStatus, (UHCI_TD_BITSTUFF_ERROR OR \
UHCI_TD_CRC_TIMEOUT_ERROR OR UHCI_TD_NAK_RECEIVED OR \
UHCI_TD_BABBLE_DETECTED OR UHCI_TD_DATA_BUFFER_ERROR OR UHCI_TD_STALLED)
jnz UIT_Exit ; Br if any error bits set in status
xor ax, ax
dec ax
mov fs, ax
UIT_Exit:
mov ax, fs
pop fs
pop di
pop si
pop edx
pop ecx
pop bx
ret
UHCI_InterruptTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCI_ProcessTDCompletion
;
; Description: This function is called to process the TD completion
;
; Input: SI Pointer to HCStruc
;
; Output: ZR Interrupt not processed
; NZ Interrupt is processed
;
; Modified: AX
;
; Referrals: UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCI_ProcessTDCompletion PROC NEAR SYSCALL PUBLIC USES BX DX EDI
mov dx, WORD PTR (HCStruc PTR [si]).dBaseAddress
; Read the UHCI status register
add dx, UHCI_STATUS_REG
in ax, dx
; Check whether any USB transaction completion interrupt is generated
test al, UHC_USB_INTERRUPT
jz UPTC_NoTransCompInt ; No interrupt asserted
; Clear interrupt status in the host controller
jcxz SHORT $+2
jcxz SHORT $+2
in ax, dx
jcxz SHORT $+2
jcxz SHORT $+2
out dx, ax
; Transaction completion interrupt occurred. Check the status completion.
mov bx, (HCStruc PTR [si]).pDescriptorPtr
xor ax, ax ; Device Info pointer = 0
; Check whether TDControlSetup is completed
; SI HCStruc pointer
; AX Device Info pointer
mov di, (UHCIDescriptors PTR [bx]).TDControlSetup
call UHCIParseAndProcessTD
; Check whether TDRepeat is completed
; SI HCStruc pointer
; AX Device Info pointer
mov di, (UHCIDescriptors PTR [bx]).TDRepeat
call UHCI_ProcessTD
; Check whether TDRootHub is completed
; SI HCStruc pointer
; AX Device Info pointer
mov di, (UHCIDescriptors PTR [bx]).TDRootHub
call UHCI_ProcessTD
; Check whether TDBulkData is completed
; SI HCStruc pointer
; AX Device Info pointer
mov di, (UHCIDescriptors PTR [bx]).TDBulkData
call UHCIParseAndProcessTD
; Check whether TDInterruptData is completed
; SI HCStruc pointer
; AX Device Info pointer
mov di, (UHCIDescriptors PTR [bx]).TDInterruptData
call UHCI_ProcessTD
; Check whether any polling TD has completed from its DeviceInfo structure
mov bx, OFFSET DeviceInfoTable ;BX - DeviceInfoTable[0]
UPTC_NextEntry:
test (DeviceInfo PTR [bx]).bFlag, DEV_INFO_DEV_PRESENT
jz UPTC_SkipEntry ;Br if this DeviceTableEntry is not in use
cmp (DeviceInfo PTR [bx]).pHCStrucPtr, si
jne UPTC_SkipEntry ;Br if matching entry found
; Structure found. Process the TD
; SI HCStruc pointer
; BX Device Info pointer
mov ax, bx
mov di, (DeviceInfo PTR [bx]).pPollTDPtr
call UHCI_ProcessTD
UPTC_SkipEntry:
add bx, SIZE DeviceInfo
cmp bx, OFFSET DeviceInfoTableEnd
jb UPTC_NextEntry ;Br if more entries to check
; Clear the zero flag
or sp, sp
UPTC_NoTransCompInt:
ret
UHCI_ProcessTDCompletion ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCI_ProcessInterrupt
;
; Description: This function is called when the USB interrupt bit is
; set. This function will parse through the TDs and QHs to
; find out completed TDs and call their respective call
; back functions
;
; Input: SI Pointer to HCStruc
;
; Output: AX 0 Interrupt not processed
; FFFFh Interrupt processed
;
; Modified: AX
;
; Referrals: UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCI_ProcessInterrupt PROC NEAR SYSCALL PUBLIC USES BX ECX DX SI EDI
LOCAL wIntProcessFlag:WORD, wIOPort:WORD, bTemp:BYTE
; Set as interrupt not processed
mov wIntProcessFlag, 0
mov dx, WORD PTR (HCStruc PTR [si]).dBaseAddress
mov wIOPort, dx
; Check whether the controller is still under BIOS control
; Read the frame list base address and compare with stored value
push dx
add dx, UHCI_FRAME_LIST_BASE
in eax, dx
pop dx
and eax, (NOT 0FFFh)
cmp eax, (HCStruc PTR [si]).dHcdDataArea
jne UPI_NoTransCompInt ; Control is not with BIOS
IF (MKF_USB_MODE EQ 2)
; Check port 60h/64h trapping SMI
IF (MKF_USB_KBC_EMULATION)
push dx
test dUSBInitFlag, USB_PORT_TRAPPING_BIT
jz UPI_NoTrapSet
mov dx, (HCStruc PTR [si]).wBusDevFuncNum
mov ah, PCI_REG_LEGACY_SUPPORT
call read_pci_dword_far
mov wTrapSet, bx ; Used later
mov al, TRAP_REQUEST_DISABLE
call USB_ProcessTrapRequest
mov ax, bx
and al, 0Fh ; Mask off unwanted bits
and al, ah
jz UPI_NoTrapSet
; DX Bus, device, function number of the UHCI controller
; AL Trap status
call USBKBDHandlePortTrapping
mov wTrapSet, bx ; Used later
UPI_NoTrapSet:
pop dx
ENDIF
; Check re-init flag and initialize HC if needed (only for SMI mode)
cmp bReInitUSB, TRUE
jne UPI_SkipReInit
; Check if configure flag set.
push dx
add dx, UHCI_COMMAND_REG
in ax,dx
pop dx
jmp $+2
jmp $+2
test ax, UHC_CONFIGURE_FLAG
jnz UPI_SkipReInit ; Jump if already set
; Clear re-init flag
mov bReInitUSB, FALSE
; Disconnect devices from the ports
push dx
mov dh, (HCStruc PTR [si]).bHCNumber
or dh, BIT7 ; Indicate as root hub
mov dl, 1
; Disconnect device from Port1
; DH Hub/HC number
; DL Port number
; SI HCStruc pointer
call USBDisconnectDevice
; Disconnect device from Port2
inc dl
call USBDisconnectDevice
pop dx
; Reinit the USB HC
; SI HCStruc pointer
; EDI Data area address
; ECX Data area size
mov edi, (HCStruc PTR [si]).dHcdDataArea
mov ecx, UHCI_DATA_AREA_SIZE
call UHCI_Start
jmp UPI_NoTransCompInt
UPI_SkipReInit:
ENDIF
call UHCI_ProcessTDCompletion
jz UPI_NoTransCompInt
; Set as interrupt processed
mov wIntProcessFlag, 0FFFFh
UPI_NoTransCompInt:
; Check re-init flag and initialize HC if needed (only for SMI mode)
IF (MKF_USB_MODE EQ 2)
; Check port 60h/64h trapping SMI
IF (MKF_USB_KBC_EMULATION)
push dx
test dUSBInitFlag, USB_PORT_TRAPPING_BIT
jz UPI_NoTrapSet0
mov al, TRAP_REQUEST_CLEA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -