📄 ohci.asm
字号:
; 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.)
; wIndex wIndex request parameter (meaning varies)
; wValue wValue request parameter (meaning varies)
; fpBuffer Buffer containing data to be sent to the
; device or buffer to be used to receive data
; wLength wLength request parameter, number of bytes
; of data to be transferred in or out
; of the host controller
;
; Output: AX 0xFFFF SUCCESS
; AX 0 ERROR
;
; Modified: AX
;
; Referrals: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCI_ControlTransfer PROC NEAR SYSCALL PUBLIC
LOCAL wLength:WORD
push ebx
push cx
push edx
push si
push di
; Necessary for OHCI host controllers
mov ax, ((5 * 1000) / 15) ; 5ms delay
call USBMisc_FixedDelay
; Setup the local variables
mov ax, (DeviceInfo PTR [bx]).CntrlXfer.wLength
mov wLength, ax
mov si, (DeviceInfo PTR [bx]).pHCStrucPtr
; Get the control setup TD address in register DI
mov di, (HCStruc PTR [si]).pDescriptorPtr
; Build the device request in the data area of the control setup qTD
push di
mov di, (OHCIDescriptors PTR [di]).TDControlSetup
add di, OHCI_TD.SetupData
call USBMiscFormDeviceRequest ; BX DeviceInfo structure
pop di
; Prepare some registers that will be used in building the TDs below.
; wLength contains the data length.
; fpBuffer contains the absolute address of the data buffer.
; wRequest contains the request type (bit 7 = 0/1 for Out/In).
; BX will contain a pointer to the DeviceInfo structure for the given device.
; DI will be left free to use as a pointer to the TD being built.
; EAX will be left free to use as a scratch register.
; Ready the EDControl for the control transfer
push di
mov di, (OHCIDescriptors PTR [di]).EDControl
; The ED control field will be set so
; Function address & Endpoint number = ESI,
; Direction = From TD,
; Speed = DeviceInfo.bEndpointSpeed,
; Skip = 1, Format = 0,
; Max packet size = DeviceInfo.wEndp0MaxPacket
; The HeadPointer field will be set to TDControlSetup
; The TailPointer field will be set to OHCI_TERMINATE
; The LinkPointer field will be set to OHCI_TERMINATE
movzx eax, (DeviceInfo PTR [bx]).wEndp0MaxPacket
; Force the max packet size to 64 bytes
cmp ax, 40h
jbe OCT_EndPointOkay
mov ax, 40h
OCT_EndPointOkay:
shl eax, 16 ; EAX[26:16] = device's packet size
movzx ax, (DeviceInfo PTR [bx]).bEndpointSpeed
; AL = 00/01/10 for HI/LO/FULL
and al, 1 ; Mask off MSb
shl ax, 13 ; EAX[13] = full/low speed flag
or al, (DeviceInfo PTR [bx]).bDeviceAddress ; EAX[10:0] = Endp/Addr
or eax, ED_SKIP_TDQ
mov (OHCI_ED PTR [di]).Control, eax
xor eax, eax ; OHCI_TERMINATE
mov (OHCI_ED PTR [di]).TailPointer, eax
mov (OHCI_ED PTR [di]).LinkPointer, eax
pop di
; Fill in various fields in the TDControlSetup.
push di
mov di, (OHCIDescriptors PTR [di]).TDControlSetup
; DI - Pointer to TDControlSetup
; The ControlStatus field will be set so
; Buffer Rounding = 1,
; Direction PID = GTD_SETUP_PACKET,
; Delay Interrupt = GTD_IntD,
; Data Toggle = GTD_SETUP_TOGGLE,
; Error Count = GTD_NO_ERRORS,
; Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to the TD's SetupData buffer
; which was before initialized to contain a DeviceRequest struc.
; The BufferEnd field will point to the last byte of the TD's SetupData
; buffer.
; The LinkPointer field will point to the TDControlData if data will
; be sent/received or to the TDControlStatus if no data is expected.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTDCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
; not need rebinding to the EDControl.
mov (OHCI_TD PTR [di]).ControlStatus, GTD_BUFFER_ROUNDING OR \
GTD_SETUP_PACKET OR GTD_SETUP_TOGGLE OR \
GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
lea ax, (OHCI_TD PTR [di]).SetupData
; AX = ptr to TD's data buffer
movzx eax, ax ; Clear upper half of EAX
add eax, HcdGlobalDataArea ; EAX = abs addr of TD's 8 byte data buffer
mov (OHCI_TD PTR [di]).CurrentBufferPointer, eax
add eax, (SIZE (OHCI_TD PTR [di]).SetupData) - 1
mov (OHCI_TD PTR [di]).BufferEnd, eax
pop di
cmp wLength, 0
jz OCT_SkipDataTds ; No data to transfer
; Fill in various fields in the TDControlData.
push di
mov di, (OHCIDescriptors PTR [di]).TDControlData
; DI - Pointer to TDControlData
; The ControlStatus field will be set so
; Buffer Rounding = 1,
; Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
; Delay Interrupt = GTD_IntD,
; Data Toggle = GTD_DATA1_TOGGLE,
; Error Count = GTD_NO_ERRORS,
; Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to the caller's buffer
; which is now in EBP.
; The BufferEnd field will point to the last byte of the caller's buffer.
; The LinkPointer field will point to the TDControlStatus.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTDCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
; not need rebinding to the EDControl.
mov eax, GTD_BUFFER_ROUNDING OR GTD_OUT_PACKET OR \
GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
test (DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
jz OCT_OutPacket ; Br if host sending data to device (OUT)
mov eax, GTD_BUFFER_ROUNDING OR GTD_IN_PACKET OR GTD_IntD OR \
GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
OCT_OutPacket:
mov (OHCI_TD PTR [di]).ControlStatus, eax
; Change Seg:Off in fpBuffer to 32 bit absolute address
call USBMiscGetFarBufferAddress ; BX DevInfo
; Return value in EDX
mov (OHCI_TD PTR [di]).CurrentBufferPointer, edx
movzx eax, wLength ; EAX = data length
cmp ax, MAX_CONTROL_DATA_SIZE
jbe OCT_BufferOkay ; Br if processed data <= buffer size
mov ax, MAX_CONTROL_DATA_SIZE
OCT_BufferOkay:
add eax, edx
dec eax
mov (OHCI_TD PTR [di]).BufferEnd, eax
pop di
OCT_SkipDataTds:
; Fill in various fields in the TDControlStatus.
push di
mov di, (OHCIDescriptors PTR [di]).TDControlStatus
; DI - Pointer to TDControlStatus
; The ControlStaus field will be set so
; Buffer Rounding = 1,
; Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
; Delay Interrupt = GTD_IntD,
; Data Toggle = GTD_DATA1_TOGGLE,
; Error Count = GTD_NO_ERRORS,
; Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to NULL
; The BufferEnd field will point to NULL.
; The LinkPointer field will point to OHCI_TERMINATE.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTdCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
; not need rebinding to the EdControl.
; For OUT control transfer status should be IN and
; for IN cotrol transfer, status should be OUT
mov eax, GTD_BUFFER_ROUNDING OR GTD_IN_PACKET OR GTD_IntD OR \
GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
test (DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
jz OCT_InPacket ; Br if host sending data to device (OUT)
mov eax, GTD_BUFFER_ROUNDING OR GTD_OUT_PACKET OR \
GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR \
(GTD_NOT_ACCESSED SHL 28)
OCT_InPacket:
mov (OHCI_TD PTR [di]).ControlStatus, eax
xor eax, eax
mov (OHCI_TD PTR [di]).CurrentBufferPointer, eax
mov (OHCI_TD PTR [di]).BufferEnd, eax
mov (OHCI_TD PTR [di]).LinkPointer, eax
pop di ; Control setup TD
; Link all the pointers together
push bx
push si
mov bx, (OHCIDescriptors PTR [di]).EDControl
mov si, (OHCIDescriptors PTR [di]).TDControlSetup
movzx eax, si
add eax, HcdGlobalDataArea
mov (OHCI_ED PTR [bx]).HeadPointer, eax
push si
mov bx, (OHCIDescriptors PTR [di]).TDControlData
cmp wLength, 0
jnz OCT_NoData
mov bx, (OHCIDescriptors PTR [di]).TDControlStatus
OCT_NoData:
movzx eax, bx
add eax, HcdGlobalDataArea
mov (OHCI_TD PTR [si]).LinkPointer, eax
cmp bx, (OHCIDescriptors PTR [di]).TDControlData
jne OCT_TDLinkDone
movzx eax, (OHCIDescriptors PTR [di]).TDControlStatus
push ax
add eax, HcdGlobalDataArea
mov (OHCI_TD PTR [bx]).LinkPointer, eax
pop bx
OCT_TDLinkDone:
xor eax, eax
mov (OHCI_TD PTR [bx]).LinkPointer, eax
pop si
OCT_InitTD:
mov (OHCI_TD PTR [si]).CSReloadValue, 0
mov (OHCI_TD PTR [si]).pCallback, OFFSET cs:OHCI_ControlTDCallback
mov (OHCI_TD PTR [si]).ActiveFlag, TRUE
mov esi, (OHCI_TD PTR [si]).LinkPointer
or esi, esi
jz OCT_TDLinkReallyDone
sub esi, HcdGlobalDataArea
jmp SHORT OCT_InitTD
OCT_TDLinkReallyDone:
pop si
pop bx
; Now complete the control queue, so set ED_SKIP_TDQ=0
push di
mov di, (OHCIDescriptors PTR [di]).EDControl
; DI - Pointer to EDControl
and (OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ
mov si, (DeviceInfo PTR [bx]).pHCStrucPtr
; Set the HcControlHeadED register to point to the EDControl.
movzx eax, di
SET_FS_EDI
add eax, HcdGlobalDataArea
USBPORT_DWORD_WRITE_MEM si, OHCI_CONTROL_HEAD_ED, eax
; Now put the control setup, data and status into the HC's schedule by
; setting the ControllListFilled field of HcCommandStatus reg.
; This will cause the HC to execute the transaction in the next active frame.
USBPORT_DWORD_WRITE_MEM si, OHCI_COMMAND_STATUS, CONTROL_LIST_FILLED
RESTORE_FS_EDI
pop di
; Now wait for the control status TD to complete. When it has completed,
; the OHCI_ControlTDCallback will set its active flag to FALSE.
mov di, (OHCIDescriptors PTR [di]).TDControlStatus
; DI - Pointer to TDControlStatus
; Now wait for the control status TD to complete.
call OHCIWaitForTransferComplete
; Stop the HC from processing the EDControl by setting its Skip bit.
push di
mov di, (HCStruc PTR [si]).pDescriptorPtr
mov di, (OHCIDescriptors PTR [di]).EDControl
or (OHCI_ED PTR [di]).Control, ED_SKIP_TDQ
pop di
; Finally check for any error bits set in both the TDControlStatus.
; If the TD did not complete successfully, return STC.
mov ebx, (OHCI_TD PTR [di]).ControlStatus
shr ebx, 28 ;AL[3:0] = Completion status
and bLastCommandStatus, NOT USB_CONTROL_STALLED
; Check for stall condition
cmp bl, GTD_STALL
jne oct_NotStalled
; Control stall condition is checked and cleared elsewhere
or bLastCommandStatus, USB_CONTROL_STALLED
oct_NotStalled:
or bl, bl
mov ax, 0 ; Indicate error, preserve ZF
jnz OCT_Exit ; Br if any error bits set in status
mov ax, 0FFFFh ; Indicate success
OCT_Exit:
pop di
pop si
pop edx
pop cx
pop ebx
ret
OHCI_ControlTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCI_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 in error (due to time out, etc.)
;
; Input: SI DeviceInfo structure (if available else 0)
; 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: AX Amount of data transferred
;
; Modified: EAX
;
; Notes: Make sure that amount of bytes to transfer should not exceed
; MAX_OHCI_BULK_DATA_SIZE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCI_BulkTransfer PROC NEAR SYSCALL PUBLIC
LOCAL wMaxPkt:WORD, bEndp:BYTE, bDatToggle:BYTE, fpBuffer:DWORD
push ebx
push cx
push si
push di
; Get Bulk IN/OUT enpoint number, data sync value & max packet size
call USBMiscGetBulkEndPointInfo
; AX Max packet value
; BL Endpoint number
; BH Data sync value
; Store the appropriate max packet size and endpoint number
; in the local variables
mov wMaxPkt, ax
mov bEndp, bl
mov bDatToggle, bh
; Save the buffer value
mov fpBuffer, edi
; Set the SKIP bit in the EdBulk to avoid accidental scheduling
mov bx, (DeviceInfo PTR [si]).pHCStrucPtr
mov bx, (HCStruc PTR [bx]).pDescriptorPtr
mov di, (OHCIDescriptors PTR [bx]).EDBulk
mov (OHCI_ED PTR [di]).Control, ED_SKIP_TDQ
; Set the ED's head pointer field to bulk data TD and tail pointer field to
; OHCI_TERMINATE. Also set ED's link pointer to OHCI_TERMINATE.
movzx eax, (OHCIDescriptors PTR [bx]).TDBulkData
add eax, HcdGlobalDataArea
mov (OHCI_ED PTR [di]).HeadPointer, eax
mov eax, OHCI_TERMINATE
mov (OHCI_ED PTR [di]).TailPointer, eax
mov (OHCI_ED PTR [di]).LinkPointer, eax
; Form the data needed for ED's control field with the available information
mov eax, ED_OUT_PACKET
test dl, BIT7
jz OBTS_OutPkt
mov eax, ED_IN_PACKET
OBTS_OutPkt:
push bx ; Descriptor pointer
; Get device info pointer
mov al, (DeviceInfo PTR [si]).bDeviceAddress
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -