📄 ohci_bb.asm
字号:
; Set FS:DI to point to the memory base address of the HC
mov eax, MKF_USB_BB_MEM_BASE
shr eax, 4
mov fs, ax
xor di, di
pop eax
ret
OHCIBB_SetFS_DI ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_ResetHC
;
; Description: This function resets the OHCI controller
;
; Input: FS:DI Pointer to mem base address
;
; Output: None
;
; Modified: Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCIBB_ResetHC PROC NEAR
push cx
; Issue a software reset and HC go to UsbSuspend state
mov DWORD PTR FS:[di+OHCI_COMMAND_STATUS], HC_RESET
; Wait for ensure HC stay in UsbSuspend > 2ms
; 134*15us = 2 ms, Delay 2ms (see p42)
mov cx, ((2 * 1000) / 15) ; 2ms delay
call fixed_delay_far
; Let HC go to UsbReset state for reset Root Hub and downstream ports
mov DWORD PTR FS:[di+OHCI_CONTROL_REG], USBRESET
; Wait 10ms for assertion of reset
mov cx, ((10 * 1000) / 15) ; 10ms delay
call fixed_delay_far
pop cx
ret
OHCIBB_ResetHC ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_StartEDSchedule
;
; Description: This function starts the standard ED schedules for the
; USB host controller
;
; Input: FS:DI Pointer to the memory base address
;
; Output: ZR On error
; NZ On success
;
; Modified: Nothing
;
; Referrals: OHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCIBB_StartEDSchedule PROC NEAR
push cx
push si
push di
push es
; Schedule the EDs
; Form the initial values for the loop
push USB_DATA
pop es
xor di, di
mov cx, CurrentHC.wAsyncListSize
cld
; The ED schedule should be added in proper order otherwise the
; links will get garbled. The proper order is to add ED for interrupt
; transfer (1ms) followed by ED for keyboard polling (8ms)
OBSES_FrameListInitLoop:
; Schedule 1ms ED for Interrupt transfer
mov si, OFFSET EDInterrupt
; SI - ED Pointer
; ES:DI - Far pointer to the frame list
call OHCIBB_AddED
; Check for 8ms ED for keyboard polling
test cx, 007h
jnz OBSES_Continue
IF MKF_USB_BB_DEV_KBD
; Yes. Schedule 8ms TD
mov si, OFFSET EDKeyboard
call OHCIBB_AddED
ENDIF ;; IF MKF_USB_BB_DEV_KBD
OBSES_Continue:
add di, 4
loop OBSES_FrameListInitLoop
OBSES_Exit:
or sp, sp ; Clear ZR flag
pop es
pop di
pop si
pop cx
ret
OHCIBB_StartEDSchedule ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_AddED
;
; Description: This function adds a ED 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: OHCI_ED
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCIBB_AddED PROC NEAR
push eax
push ebx
push esi
; Load parameters to registers
movzx esi, si
or (OHCI_ED PTR [si]).Control, ED_SKIP_TDQ ; Skip this ED
mov ebx, DWORD PTR ES:[di]
; Form the 32bit absolute ED 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 ED
mov (OHCI_ED PTR [si]).LinkPointer, ebx
pop esi
pop ebx
pop eax
ret
OHCIBB_AddED ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_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>
OHCIBB_ControlTransfer PROC NEAR SYSCALL PUBLIC
push fs
push es
pushad
;;; Necessary for OHCI host controllers
;; mov cx, ((5 * 1000) / 15) ; 5ms delay
;; call fixed_delay_far
; Setup the local variables
mov dx, (DeviceInfo PTR [si]).CntrlXfer.wLength
; Build the device request in the data area of the control setup qTD
mov di, OFFSET GTDControlSetup.SetupData
call USBBB_CopyDeviceRequest
; 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
mov di, OFFSET 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 GTDControlSetup
; The TailPointer field will be set to OHCI_TERMINATE
; The LinkPointer field will be set to OHCI_TERMINATE
movzx eax, (DeviceInfo PTR [si]).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 [si]).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 [si]).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
; Fill in various fields in the GTDControlSetup.
mov di, OFFSET GTDControlSetup
; DI - Pointer to GTDControlSetup
; 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 OHCIBB_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, dGlobalDataArea ; 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
cmp dx, 0
jz OCT_SkipDataTds ; No data to transfer
; Fill in various fields in the TDControlData.
mov di, OFFSET GTDData
; DI - Pointer to TDData
; 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 OHCIBB_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 [si]).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
mov eax, (DeviceInfo PTR [si]).CntrlXfer.fpBuffer
mov (OHCI_TD PTR [di]).CurrentBufferPointer, eax
movzx eax, dx ; 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, (DeviceInfo PTR [si]).CntrlXfer.fpBuffer
dec eax
mov (OHCI_TD PTR [di]).BufferEnd, eax
OCT_SkipDataTds:
; Fill in various fields in the TDControlStatus.
mov di, OFFSET GTDControlStatus
; 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 OHCIBB_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 [si]).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
; Link all the pointers together
push bx
push si
mov bx, OFFSET EDControl
mov si, OFFSET GTDControlSetup
movzx eax, si
add eax, dGlobalDataArea
mov (OHCI_ED PTR [bx]).HeadPointer, eax
push si
mov bx, OFFSET GTDData
cmp dx, 0
jnz OCT_NoData
mov bx, OFFSET GTDControlStatus
OCT_NoData:
movzx eax, bx
add eax, dGlobalDataArea
mov (OHCI_TD PTR [si]).LinkPointer, eax
cmp bx, OFFSET GTDData
jne OCT_TDLinkDone
mov eax, OFFSET GTDControlStatus
push ax
add eax, dGlobalDataArea
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:OHCIBB_ControlTDCallback
mov (OHCI_TD PTR [si]).ActiveFlag, TRUE
mov esi, (OHCI_TD PTR [si]).LinkPointer
or esi, esi
jz OCT_TDLinkReallyDone
sub esi, dGlobalDataArea
jmp SHORT OCT_InitTD
OCT_TDLinkReallyDone:
pop si
pop bx
; Now complete the control queue, so set ED_SKIP_TDQ=0
mov di, OFFSET EDControl
; DI - Pointer to EDControl
and (OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ
; Set the HcControlHeadED register to point to the EDControl.
movzx eax, di
add eax, dGlobalDataArea
; Set FS:DI to point to the memory base address of the HC
call OHCIBB_SetFS_DI
mov DWORD PTR FS:[di+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.
or DWORD PTR FS:[di+OHCI_COMMAND_STATUS], CONTROL_LIST_FILLED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -