📄 ohci.asm
字号:
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 ; Descriptor pointer
; 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, (OHCIDescriptors PTR [bx]).TDBulkData
; 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:OHCI_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, (OHCIDescriptors PTR [bx]).EDBulk
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, HcdGlobalDataArea
push si
mov si, (DeviceInfo PTR [si]).pHCStrucPtr
SET_FS_EDI
USBPORT_DWORD_WRITE_MEM si, OHCI_BULK_HEAD_ED, eax
; Clear bulk stall/time out condition flag
and bLastCommandStatus, NOT (USB_BULK_STALLED + USB_BULK_TIMEDOUT)
; Enable the bulk list processing
USBPORT_DWORD_SET_MEM si, OHCI_COMMAND_STATUS, BULK_LIST_FILLED
RESTORE_FS_EDI
mov di, (OHCIDescriptors PTR [bx]).TDBulkData
; Now wait for the bulk data TD to complete.
call OHCIWaitForTransferComplete
pop si
; Stop the HC from processing the EDBulk by setting its Skip bit.
push di
mov di, (OHCIDescriptors PTR [bx]).EDBulk
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
; SI DeviceInfo structure
; DL Xfer direction
; CL Data toggle value
call USBMiscUpdateBulkDataSync
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
cmp al, GTD_DEVICE_NOT_RESPOND
jne OBTS_CheckStall
; Bulk time out condition is checked and cleared elsewhere
or bLastCommandStatus, USB_BULK_TIMEDOUT
jmp SHORT OBTS_ErrorExit
OBTS_CheckStall:
; Check for stall condition
cmp al, GTD_STALL
jne OBTS_ErrorExit
; Bulk stall condition is checked and cleared elsewhere
or bLastCommandStatus, USB_BULK_STALLED
OBTS_ErrorExit:
; Return with error
xor ax, ax
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
OBTS_Exit:
pop di
pop si
pop cx
pop ebx
ret
OHCI_BulkTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCI_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>
OHCI_InterruptTransfer PROC NEAR SYSCALL PUBLIC USES 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 bx, (HCStruc PTR [di]).pDescriptorPtr
mov di, (OHCIDescriptors PTR [bx]).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.
movzx eax, (OHCIDescriptors PTR [bx]).TDInterruptData
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
push si
; Get mass struc in SI
; Get maximum packet size from device info structure
mov ax, (DeviceInfo PTR [si]).wIntMaxPkt
mov wMaxPkt, ax
mov al, (DeviceInfo PTR [si]).bIntEndpoint
mov bEndp, al
mov al, (DeviceInfo PTR [si]).bDataSync
and al, USB_INT_DATA_SYNC
shr al, USB_INT_DATA_SYNC_SHIFT
mov bDatToggle, al
pop si
; 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, (DeviceInfo PTR [si]).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, (OHCIDescriptors PTR [bx]).TDInterruptData
; 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:OHCI_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, (OHCIDescriptors PTR [bx]).EDInterrupt
and (OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ
push si
mov si, (DeviceInfo PTR [si]).pHCStrucPtr
mov di, (OHCIDescriptors PTR [bx]).TDInterruptData
; Now wait for the interrupt data TD to complete.
call OHCIWaitForTransferComplete
pop si
; Stop the HC from processing the EDInterrupt by setting its Skip bit.
push di
mov di, (OHCIDescriptors PTR [bx]).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
push di
mov di, (DeviceInfo PTR [si]).pMassInfoPtr
cmp (MassDeviceInfo PTR [di]).pLUN0DevInfoPtr, 0
je OIT_ToggleBitDone
mov si, (MassDeviceInfo PTR [di]).pLUN0DevInfoPtr
OIT_ToggleBitDone:
pop di
; Reset toggle bit
mov al, 1
shl al, cl
not al
and (DeviceInfo PTR [si]).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 (DeviceInfo PTR [si]).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
mov ax, 0FFFFh
jz OIT_Success
; Return with error
xor ax, ax
OIT_Success:
OIT_Exit:
ret
OHCI_InterruptTransfer ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure: OHCI_ActivatePolling
;
; Description: This function activates the polling TD for the requested
; device. The device may be a USB keyboard or USB hub
;
; Input: BX Pointer to the device information structure
;
; Output: AX 0 on error, 0FFFFh on success
;
; Modified: AX
;
; Referrals: OHCI_TD, DeviceInfo
;
; Notes: For the keyboard device this routine allocates TDRepeat
; also, if it is not already allocated. This routine allocate
; a polling TD and schedule it to 8ms schedule for keyboards
; and to 1024ms schedule for hubs.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
OHCI_ActivatePolling PROC NEAR SYSCALL PUBLIC USES BX SI EDI CX DX
; Set registers with needed value
mov si, (DeviceInfo PTR [bx]).pHCStrucPtr
mov di, (HCStruc PTR [si]).pDescriptorPtr
mov dl, (DeviceInfo PTR [bx]).bDeviceType
; Check whether the activate polling is for HID device
cmp dl, BIOS_DEV_TYPE_KEYBOARD
je OAP_InstallRepeatTD
cmp dl, BIOS_DEV_TYPE_MOUSE
jne OAP_RepeatTDDone
OAP_InstallRepeatTD:
; Check whether a TD is allocated for TDRepeat if not allocate one.
cmp (OHCIDescriptors PTR [di]).TDRepeat, 0
jne OAP_RepeatTDDone ; Already allocated
; Allocate a ED/TD for EDRepeat/TDRepeat
mov al, 2
call USBMem_Alloc
jz OAP_Exit
push di ; Save OHCIDescriptors
push ax
mov (OHCIDescriptors PTR [di]).EDRepeat, ax
add ax, SIZE OHCI_ED
mov (OHCIDescriptors PTR [di]).TDRepeat, ax
pop ax
mov di, ax
add ax, SIZE OHCI_ED
mov cx, ax
; Setup EDRepeat and TDRepeat. It will run a interrupt transaction to a
; nonexistant dummy device. This will have the effect of generating
; a periodic interrupt used to generate keyboard repeat. This ED/TD
; is normally inactive, and is only activated when a key is pressed.
; DI - EDRepeat
; CX - TDRepeat
mov (OHCI_ED PTR [di]).Control, DUMMY_DEVICE_ADDR OR \
ED_IN_PACKET OR (DEFAULT_PACKET_LENGTH SHL 16) OR ED_SKIP_TDQ
mov (OHCI_ED PTR [di]).LinkPointer, OHCI_TERMINATE
movzx eax, cx ; TDRepeat
add eax, HcdGlobalDataArea
mov (OHCI_ED PTR [di]).HeadPointer, eax
mov (OHCI_ED PTR [di]).TailPointer, OHCI_TERMINATE
push di
mov di, cx ; DI = ptr to TdRepeat
mov eax, GTD_BUFFER_ROUNDING OR GTD_IN_PACKET OR GTD_IntD OR \
(GTD_NOT_ACCESSED SHL 28) OR GTD_ONE_ERROR
mov (OHCI_TD PTR [di]).ControlStatus, eax
mov (OHCI_TD PTR [di]).CSReloadValue, eax
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 data buffer
mov (OHCI_TD PTR [di]).Cur
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -