📄 uhci_bb.asm
字号:
; Output: ZR On error
; NZ On success
;
; Modified: Nothing
;
; Referrals: UHCI_TD
;
; Notes: This routine creates 1ms and 8ms schedules
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCIBB_StartTDSchedule PROC NEAR PUBLIC
pushad
push es
; Schedule the TDs
; Make QHControl link pointer to null
mov di, OFFSET QHControl
mov (UHCI_QH PTR [di]).LinkPointer, UHCI_TERMINATE
; Form the initial values for the loop
push USB_DATA
pop es
xor di, di
mov cx, CurrentHC.wAsyncListSize
cld
; The TD schedule should be added in proper order otherwise the
; links will get garbled. The proper order is to add all the 1ms TDs,
; followed by 2ms, 8ms and finally 256ms TD.
UBSTS_FrameListInitLoop:
;;; Schedule the QHControl for 1ms
;; mov si, OFFSET QHControl
;;; ES:DI Frame list pointer index
;;; SI TD to add
;; call UHCIBB_AddTD
; Check for 8ms TD schedule
test cx, 007h
jnz UBSTS_Continue
IF MKF_USB_BB_DEV_KBD
; Yes. Schedule the TDKeyboard for 8ms
mov si, OFFSET TDKeyboard
; ES:DI Frame list pointer index
; SI TD to add
call UHCIBB_AddTD
ENDIF ;; IF MKF_USB_BB_DEV_KBD
UBSTS_Continue:
add di, 4
loop UBSTS_FrameListInitLoop
; Success. Clear the zero flag
or sp, sp
pop es
popad
ret
UHCIBB_StartTDSchedule ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCIBB_AddTD
;
; Description: This function adds a TD to the frame list
;
; Input: SI Pointer to the TD to be added
; ES:DI Pointer to the frame list
;
; Output: Nothing
;
; Modified: Nothing
;
; Referrals: UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCIBB_AddTD PROC NEAR
push eax
push edx
push esi
; Load parameters to registers
movzx esi, si
; Get current frame list pointer address
mov edx, DWORD PTR ES:[di]
; Form the 32bit absolute TD address
push ds
pop ax
movzx eax, ax
shl eax, 4
add eax, esi
; Save it in the current frame list pointer
mov DWORD PTR ES:[di], eax
; Link the old frame list pointer address in the link pointer of TD
mov (UHCI_TD PTR [si]).LinkPointer, edx
pop esi
pop edx
pop eax
ret
UHCIBB_AddTD ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCIBB_ControlTransfer
;
; Description: This function executes a control transaction on the USB.
; One setup packet is generated containing the device request
; parameters supplied by the caller. The setup packet may be
; followed by data in or data out packets containing data sent
; from the host to the device or vice-versa. This function
; will not return until the request either completes
; successfully or completes in error (due to time out, etc.)
;
; Input: SI Pointer to the DeviceInfo structure
; The device info structure has the necessary information for
; the control transfer:
; CntrlXfer.wRequest Request type (low byte)
; Bit 7 : Data direction
; 0 = Host sending data to device
; 1 = Device sending data to host
; Bit 6-5 : Type
; 00 = Standard USB request
; 01 = Class specific
; 10 = Vendor specific
; 11 = Reserved
; Bit 4-0 : Recipient
; 00000 = Device
; 00001 = Interface
; 00010 = Endpoint
; 00100 - 11111 = Reserved
; Request code (high byte), a one byte
; code describing the actual device
; request to be executed (ex: Get
; Configuration, Set Address etc)
; CntrlXfer.wIndex wIndex request parameter (meaning varies)
; CntrlXfer.wValue wValue request parameter (meaning varies)
; CntrlXfer.fpBuffer Data buffer pointer
; CntrlXfer.wLength Number of bytes of data to be transferred
;
; Output: NZ On successfull completion
; ZR On error
;
; Modified: None
;
; Referrals: DeviceInfo
;
; Notes: Endpoint is always assumed as 0 for control transfer
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
UHCIBB_ControlTransfer PROC NEAR SYSCALL PUBLIC
push es
pushad
; Build the device request in the data area of the control setup TD
mov di, OFFSET TDControlSetup.DataArea
call USBBB_CopyDeviceRequest
; Set the global temp variables for code size reduction
xor ecx, ecx
mov cx, (DeviceInfo PTR [si]).CntrlXfer.wLength
; EDX will contain the device address and endpoint shifted and ready to go
; into the TDs' token field.
xor eax, eax ; EAX[3:0] = Endpoint (00-0Fh)
;; shl eax, 7 ; EAX[10:7] = Endpoint (00-0Fh)
or al, (DeviceInfo PTR [si]).bDeviceAddress
; EAX[10:0] = Dev. Addr & Endpoint
shl eax, 8 ; EAX[18:8] = Dev. Addr & Endpoint
mov edx, eax
; Fill in various fields in the control setup TD.
; The LinkPointer field will point to the control data TD if data will
; be sent/received or to the control status TD if no data is expected.
; The ControlStatus field will be set to active and interrupt on complete.
; The Token field will contain the packet size (size of DeviceRequest
; struc), the device address, endpoint, and a setup PID.
; The BufferPointer field will point to the TD's DataArea buffer which
; was just initialized to contain a DeviceRequest struc.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the UHCI_ControlTDCallback routine.
; The ActiveFlag field will be set to TRUE.
mov di, OFFSET TDControlSetup
; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
call UHCIBB_FillCntrlXferFields ; SI-DevInfo, DI-TD
mov eax, edx
; EAX[18:8] = Device address / endpoint
or eax, SETUP_PACKET OR ((SIZE DeviceRequest - 1) shl 21)
; Set PID=Setup, and MaxLen
mov (UHCI_TD PTR [di]).Token, eax
mov eax, OFFSET TDControlSetup.DataArea
add eax, dGlobalDataArea ;EAX = abs addr of TD's data buffer
mov (UHCI_TD PTR [di]).BufferPointer, eax
; Fill in various fields in the control data TD. Enough control data TDs
; must be initialized to handle the amount of data expected. The length
; of the data transfer is currently in wLength.
; LinkPointer field will be set to the next data TD or the status TD.
; ControlStatus field will be se to active and interrupt on complete.
; Token field will contain the data transfer size (still in wLength), device
; address (in pDevInfo), endpoint (in dTemp), and an in or out PID
; (in wReqType).
; BufferPointer field will point to the data buffer passed in by the
; caller (currently in EDX).
; CSReloadValue field will contain 0 because this is a "one shot" packet.
; pCallback will be set to point to the UHCI_ControlTDCallback routine.
; ActiveFlag field will be set to TRUE.
or cx, cx
jz UBCT_SkipDataTds ; No data to transfer
cmp cx, MAX_CONTROL_DATA_SIZE
jb UBCT_DataSizeOkay ; Data size within limit
mov cx, MAX_CONTROL_DATA_SIZE ; Limit the data size
UBCT_DataSizeOkay:
mov bx, OFFSET TDData ; BX - Pointer to control
; data TD
; DI = PTR of TD control data
or ecx, BIT16 ; Start with a data 1 token
UBCT_NextDataTd:
; Link the new TD to the previous TD
movzx eax, bx
add eax, dGlobalDataArea
; Set the vertical flag
or eax, UHCI_VERTICAL_FLAG
mov (UHCI_TD PTR [di]).LinkPointer, eax
mov di, bx
mov eax, (DeviceInfo PTR [si]).CntrlXfer.fpBuffer
mov (UHCI_TD PTR [di]).BufferPointer, eax
movzx eax, cx ; Data length
cmp ax, (DeviceInfo PTR [si]).wEndp0MaxPacket
jbe UBCT_PktSizeAdjusted ; Packet size is valid
mov ax, (DeviceInfo PTR [si]).wEndp0MaxPacket
UBCT_PktSizeAdjusted:
sub cx, ax ; Adjust overall data size
add (DeviceInfo PTR [si]).CntrlXfer.fpBuffer, eax ; Adjust buffer pointer
dec ax ; AX = packet data size - 1
shl eax, 21
or eax, edx ; EAX[18:8]=Dev. addr & endp
mov al, OUT_PACKET ; EAX[7:0] = OUT PID
test (DeviceInfo PTR [si]).CntrlXfer.wRequest, BIT7
jz UBCT_PIDFound ; OUT PID
mov al, IN_PACKET ; EAX[7:0] = IN PID
UBCT_PIDFound:
test ecx, BIT16
jz UBCT_DataToggle ; DATA0 packet
or eax, DATA_TOGGLE ; Make packet into a data 1
UBCT_DataToggle:
mov (UHCI_TD PTR [di]).Token, eax
; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
call UHCIBB_FillCntrlXferFields ; SI-DevInfo, DI-TD
; Enable short packet detect
or (UHCI_TD PTR [di]).ControlStatus, UHCI_TD_SHORT_PACKET_DETECT
xor ecx, BIT16 ; Toggle between DATA1/DATA0
add bx, SIZE UHCI_TD ; Point BX to next TD
or cx, cx
jnz UBCT_NextDataTd ; More data TDs must be built
;; End the data TD list
mov (UHCI_TD PTR [di]).LinkPointer, UHCI_TERMINATE
UBCT_SkipDataTds:
; Make the next TD to point to the TD control status
mov eax, OFFSET TDControlStatus
add eax, dGlobalDataArea
mov (UHCI_TD PTR [di]).LinkPointer, eax
; DI = PTR of TD control status
mov di, OFFSET TDControlStatus
; Fill in various fields in the TD control status.
; LinkPointer field will point to TERMINATE.
; ControlStatus field will be set to active and interrupt on complete.
; Token field will contain the packet size (0), the device address,
; endpoint, and a setup PID with opposite data direction as that defined
; in the request type (wReqType).
; BufferPointer field will point to the TD's DataArea buffer even though
; we are not expecting any data transfer.
; CSReloadValue field will contain 0 because this is a "one shot" packet.
; pCallback will be set to point to the UHCI_ControlTDCallback routine.
; ActiveFlag field will be set to TRUE.
mov (UHCI_TD PTR [di]).LinkPointer, UHCI_TERMINATE
mov eax, edx ; EAX[18:8] = Device address / endpoint
mov al, OUT_PACKET ; EAX[7:0] = OUT PID
test (DeviceInfo PTR [si]).CntrlXfer.wRequest, BIT7
jnz UBCT_StatPIDFound ; IN PID
mov al, IN_PACKET ; EAX[7:0] = IN PID
UBCT_StatPIDFound:
or eax, (DATA_TOGGLE OR (UHCI_TD_DATA_LENGTH SHL 21)) ; DATA0/DATA1
mov (UHCI_TD PTR [di]).Token, eax
mov eax, OFFSET TDControlStatus.DataArea
add eax, dGlobalDataArea ; EAX = abs addr of TD's data buffer
mov (UHCI_TD PTR [di]).BufferPointer, eax
; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
call UHCIBB_FillCntrlXferFields ; SI-DevInfo, DI-TD
; Now put the control setup, data and status into the HC's schedule by
; pointing QhControl's element pointer to control setup TD.
; This will cause the HC to execute the transaction in the next active frame.
mov si, OFFSET QHControl
mov edi, OFFSET TDControlSetup
add edi, dGlobalDataArea
mov (UHCI_QH PTR [si]).ElementPointer, edi
; Now wait for the control status TD to complete. When it has completed,
; the UHCI_ControlTDCallback will set its active flag to FALSE.
mov di, OFFSET TDControlStatus ; Control status TD pointer
call UHCIBB_WaitForTransferComplete
; Remove the control setup, data, and status TDs from the
; HC's schedule by pointing QhControl's link pointer to UHCI_TERMINATE.
push di
mov di, OFFSET QHControl
mov (UHCI_QH PTR [di]).ElementPointer, UHCI_TERMINATE
pop di
; Finally check for any error bits set in both the TdControlStatus.
; If the TD did not complete successfully, return errors status.
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 UBCT_ErrorExit ; Br if any error bits set in status
; Return success (Clear Zero flag)
or sp, sp
jmp SHORT UBCT_Exit
UBCT_ErrorExit:
; Error! Set zero flag
cmp sp, sp
UBCT_Exit:
popad
pop es
ret
UHCIBB_ControlTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: UHCIBB_BulkTransfer
;
; Description: This function executes a bulk transaction on the USB. The
; transfer may be either DATA_IN or DATA_OUT packets containing
; data sent from the host to the device or vice-versa. This
; function wil not return until the request either completes
; successfully or completes with error (due to time out, etc.)
;
; Input: DL Transfer direction
; Bit 7 : Data direction
; 0 Host sending data to device
; 1 Device sending data to host
; Bit 6-0 : Reserved
; EDI Buffer containing data to be sent to the device or
; buffer to be used to receive data. Value in 32 bit
; absolute address
; CX Number of bytes of data to be transferred in or out
; of the host controller
;
; Output: ZR On error
; NZ On success
; AX Amount of data transferred
;
; Modified: EAX
;
; Notes: Make sure that amount of bytes to transfer should not exceed
; MAX_UHCI_BULK_DATA_SIZE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
; Bulk transfer related global temporary variables
dUHCIControlStatus DWORD ?
dUHCIToken DWORD ?
UHCIBB_BulkTransfer PROC NEAR SYSCALL
push fs
pushad
push 0
pop fs
; Check for 0 length transfer (if so, exit)
or cx, cx
jz UBBT_Success
; Get Bulk IN/OUT enpoint number, data sync value & max packet size
call USBMBB_GetBulkEndPointInfo
; AX Max packet value
; BL Endpoint number
; BH Data sync value
; Store the appropriate max packet size and endpoint number
; in the local variables
push ax ; Save max packet size
; Form device address and endpoint in proper order and bit position
movzx eax, bl ; EAX[3:0] = Endpoint
shl eax, 7 ; EAX[10:7] = Endpoint
mov esi, eax
movzx eax, CurrentDevice.bDeviceAddress
or eax, esi ; EAX[10:0] = Dev. Addr & Endpoint
shl eax, 8 ; EAX[18:8] = Dev. Addr & Endpoint
mov dUHCIToken, eax
mov al, OUT_PACKET ; EAX[7:0] = OUT PID
test dl, BIT7
jz UBBT_PIDFound ; OUT PID
mov al, IN_PACKET ; EAX[7:0] = IN PID
UBBT_PIDFound:
test bh, 1
jz UBBT_DataToggle ; DATA0 packet
or eax, DATA_TOGGLE ; Make packet into a data 1
UBBT_DataToggle:
or dUHCIToken, eax
pop si ; Restore max packet size
; Form control status
movzx eax, CurrentDevice.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 OR UHCI_TD_ACTIVE OR \
UHCI_TD_SHORT_PACKET_DETECT)
mov dUHCIControlStatus, eax
; Save the buffer pointer in EBX
mov ebx, edi ; Buffer pointer
; Form the bulk data TDs
mov di, OFFSET TDData
UBBT_PrepareNextBulkTD:
; Form pointer to the next TD and link it in the current TD
movzx eax, di
add eax, SIZE UHCI_TD
add eax, dGlobalDataArea
; Set the vertical flag
or eax, UHCI_VERTICAL_FLAG
mov (UHCI_TD PTR [di]).LinkPointer, eax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -