📄 ohci_bb.asm
字号:
; Now wait for the control status TD to complete. When it has completed,
; the OHCIBB_ControlTDCallback will set its active flag to FALSE.
mov di, OFFSET GTDControlStatus
; DI - Pointer to TDControlStatus
; Now wait for the control status TD to complete.
call OHCIBB_WaitForTransferComplete
; Stop the HC from processing the EDControl by setting its Skip bit.
push di
mov di, OFFSET 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
or bl, bl
jnz OBCT_Error
; Success. Clear the zero flag
or sp, sp
jmp SHORT OBCT_Exit
OBCT_Error:
; Error. Set zero flag
cmp sp, sp
OBCT_Exit:
popad
pop es
pop fs
ret
OHCIBB_ControlTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_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_OHCI_BULK_DATA_SIZE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCIBB_BulkTransfer PROC NEAR SYSCALL PUBLIC
LOCAL wMaxPkt:WORD, bEndp:BYTE, bDatToggle:BYTE, fpBuffer:DWORD
push fs
push ebx
push cx
push si
push di
; 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
mov wMaxPkt, ax
mov bEndp, bl
mov bDatToggle, bh
; Save the buffer value
mov fpBuffer, edi
; Set the SKIP bit in the EDControl to avoid accidental scheduling
mov di, OFFSET EDControl
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.
mov eax, OFFSET GTDData
add eax, dGlobalDataArea
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:
; Get device info pointer
mov al, CurrentDevice.bDeviceAddress
movzx bx, bEndp
shl bx, 7
or ax, bx ; AX - Device address & Endpoint
; Set max packet size
movzx ebx, wMaxPkt
shl ebx, 16
or eax, ebx
; Update the ED's control field with the data formed
; ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES.
or (OHCI_ED PTR [di]).Control, eax
; Fill the general bulk data TD with relevant information. Set the
; TD's control field with buffer rounding set to 1, direction PID to
; don't care, delay interrupt to INTD, data toggle to the latest data
; toggle value, error count to no errors and condition code to not accessed.
mov di, OFFSET GTDData
; Set the data toggle to DATA0 (SETUP_TOGGLE)
mov eax, GTD_BUFFER_ROUNDING or GTD_IN_PACKET or GTD_IntD or \
GTD_SETUP_TOGGLE or GTD_NO_ERRORS or \
(GTD_NOT_ACCESSED shl 28)
mov (OHCI_TD PTR [di]).ControlStatus, eax
; Set the data toggle depending on the bDatToggle value
movzx eax, bDatToggle
shl eax, 24
or (OHCI_TD PTR [di]).ControlStatus, eax
; GTD current buffer pointer field will point to the caller's buffer which
; now in the variable fpBuffer
mov eax, fpBuffer
mov (OHCI_TD PTR [di]).CurrentBufferPointer, eax
; GTD's buffer end field will point to the last byte of the caller's buffer
movzx eax, cx ; Data length
add eax, fpBuffer ; End of the buffer
dec eax
mov (OHCI_TD PTR [di]).BufferEnd, eax
; GTD's link pointer field will be set to OHCI_TERMINATE
mov (OHCI_TD PTR [di]).LinkPointer, OHCI_TERMINATE
; GTD's CSReloadValue field will contain 0 because this is
; a "one shot" packet
mov (OHCI_TD PTR [di]).CSReloadValue, 0
; GTD's pCallback will point to the OHCI_GeneralTDCallback routine
mov (OHCI_TD PTR [di]).pCallback, OFFSET cs:OHCIBB_GeneralTDCallback
; GTD's ActiveFlag field will be set to TRUE.
mov (OHCI_TD PTR [di]).ActiveFlag, TRUE
; Enable the bulk queue by activating the bulk ED
mov di, OFFSET EDControl
and (OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ
; Set the HCBulkHeadED register to point to the bulk ED
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_BULK_HEAD_ED], eax
; Set bulk condition as not stalled
mov bLastBulkCommandStalled, FALSE
; Enable the bulk list processing
or DWORD PTR FS:[di+OHCI_COMMAND_STATUS], BULK_LIST_FILLED
mov di, OFFSET GTDData
; Now wait for the bulk data TD to complete.
call OHCIBB_WaitForTransferComplete
; Stop the HC from processing the EDControl by setting its Skip bit.
push di
mov di, OFFSET EDControl
or (OHCI_ED PTR [di]).Control, ED_SKIP_TDQ
pop di
push cx
; Update the data toggle value into the mass info structure
mov eax, (OHCI_TD PTR [di]).ControlStatus
and eax, GTD_DATA_TOGGLE
shr eax, 24
and al, 1 ; Mask off top bits
mov cl, al
; DL Xfer direction
; CL Data toggle value
call USBMBB_UpdateBulkDataSync
pop cx
; Check for the error conditions - if possible recover from them
mov eax, (OHCI_TD PTR [di]).ControlStatus
shr eax, 28
or al, al
jz OBTS_Success
; Check for stall condition
cmp al, GTD_STALL
jne OBTS_ErrorExit
; Stall condition is checked and cleared elsewhere
mov bLastBulkCommandStalled, TRUE
OBTS_ErrorExit:
; Return with error
xor ax, ax
cmp sp, sp ; Set zero flag
jmp SHORT OBTS_Exit
OBTS_Success:
; Get the size of data transferred
; Size transferred is calculated by subtracting end address with current
; buffer pointer and subtracting that value from the total size
mov ebx, (OHCI_TD PTR [di]).CurrentBufferPointer
or ebx, ebx
jz OBTS_FoundSize
mov eax, (OHCI_TD PTR [di]).BufferEnd
sub eax, ebx
or ax, ax
jz OBTS_FoundSize
sub cx, ax ; Size in CX
dec cx
OBTS_FoundSize:
mov ax, cx
or sp, sp ; Clear zero flag
OBTS_Exit:
pop di
pop si
pop cx
pop ebx
pop fs
ret
OHCIBB_BulkTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCIBB_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: 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: ZR On error
; NZ On success
;
; 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>
OHCIBB_InterruptTransfer PROC NEAR SYSCALL PUBLIC USES EAX EBX CX EDX SI DI
LOCAL wMaxPkt:WORD, bEndp:BYTE, bDatToggle:BYTE
; Change Seg:Off in fpBuffer to 32 bit absolute address
mov ax, ds
movzx eax, ax
shl eax, 4
movzx edx, dx
add edx, eax
; Set the SKIP bit in the EDInterrupt to avoid accidental scheduling
mov di, OFFSET EDInterrupt
mov (OHCI_ED PTR [di]).Control, ED_SKIP_TDQ
; Set the ED's head pointer field to interrupt data TD and tail pointer
; field to OHCI_TERMINATE. Also set ED's link pointer to OHCI_TERMINATE.
mov eax, OFFSET GTDData
add eax, dGlobalDataArea
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
; Get maximum packet size from device info structure
mov ax, CurrentDevice.wIntMaxPkt
mov wMaxPkt, ax
mov al, CurrentDevice.bIntEndpoint
mov bEndp, al
mov al, CurrentDevice.bDataSync
and al, USB_INT_DATA_SYNC
shr al, USB_INT_DATA_SYNC_SHIFT
mov bDatToggle, al
; Form the data needed for ED's control field with the available information
mov eax, ED_IN_PACKET
push bx
; Get device info pointer
mov al, CurrentDevice.bDeviceAddress
movzx bx, bEndp
shl bx, 7
or ax, bx ; AX - Device address & Endpoint
; Set max packet size
movzx ebx, wMaxPkt
shl ebx, 16
or eax, ebx
pop bx
; Update the ED's control field with the data formed
; ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES.
or (OHCI_ED PTR [di]).Control, eax
; Fill the general interrupt data TD with relevant information. Set the
; TD's control field with buffer rounding set to 1, direction PID to
; don't care, delay interrupt to INTD, data toggle to the latest data
; toggle value, error count to no errors and condition code to not accessed.
mov di, OFFSET GTDData
; Set the data toggle to DATA0 (SETUP_TOGGLE)
mov eax, GTD_BUFFER_ROUNDING or GTD_IN_PACKET or GTD_IntD or \
GTD_SETUP_TOGGLE or GTD_NO_ERRORS or \
(GTD_NOT_ACCESSED shl 28)
mov (OHCI_TD PTR [di]).ControlStatus, eax
; Set the data toggle depending on the bDatToggle value
movzx eax, bDatToggle
shl eax, 24
or (OHCI_TD PTR [di]).ControlStatus, eax
; GTD current buffer pointer field will point to the caller's buffer
mov (OHCI_TD PTR [di]).CurrentBufferPointer, edx
; GTD's buffer end field will point to the last byte of the caller's buffer
movzx eax, cx ; Data length
add eax, edx ; End of the buffer
dec eax
mov (OHCI_TD PTR [di]).BufferEnd, eax
; GTD's link pointer field will be set to OHCI_TERMINATE
mov (OHCI_TD PTR [di]).LinkPointer, OHCI_TERMINATE
; GTD's CSReloadValue field will contain 0 because this is
; a "one shot" packet
mov (OHCI_TD PTR [di]).CSReloadValue, 0
; GTD's pCallback will point to the OHCI_GeneralTDCallback routine
mov (OHCI_TD PTR [di]).pCallback, OFFSET cs:OHCIBB_GeneralTDCallback
; GTD's ActiveFlag field will be set to TRUE.
mov (OHCI_TD PTR [di]).ActiveFlag, TRUE
; Enable the interrupt queue by activating the interrupt ED
mov di, OFFSET EDInterrupt
and (OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ
mov di, OFFSET GTDData
; Now wait for the interrupt data TD to complete.
call OHCIBB_WaitForTransferComplete
; Stop the HC from processing the EDInterrupt by setting its Skip bit.
push di
mov di, OFFSET EDInterrupt
or (OHCI_ED PTR [di]).Control, ED_SKIP_TDQ
pop di
; Get appropriate data sync shift value
mov cl, USB_INT_DATA_SYNC_SHIFT
; Reset toggle bit
mov al, 1
shl al, cl
not al
and CurrentDevice.bDataSync, al
; Set toggle bit appropriately
mov eax, (OHCI_TD PTR [di]).ControlStatus
and eax, GTD_DATA_TOGGLE
shr eax, 24
and al, 1 ; Mask off top bits
shl al, cl
or CurrentDevice.bDataSync, al
; Check for the error conditions - if possible recover from them
mov eax, (OHCI_TD PTR [di]).ControlStatus
shr eax, 28
or al, al
jz OIT_Success
; Return with error. Set the zero flag
cmp sp, sp
jmp SHORT OIT_Exit
OIT_Success:
; Clear the zero flag
or sp, sp
OIT_Exit:
ret
OHCIBB_InterruptTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: OHCIBB_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: Nothing (All necessary data are in global variables)
;
; Output: None
;
; Modified: Nothing
;
; Referrals: OHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCIBB_ProcessInterrupt PROC NEAR SYSCALL PUBLIC
push fs
push eax
push ebx
push edx
push si
push edi
; Set FS:DI to point to the memory base address of the HC
call OHCIBB_SetFS_DI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -