⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uhci.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	mov	di, pSetup
	movzx	eax, pStatus
	add	eax, HcdGlobalDataArea	; EAX = Pointer to next TD
	mov	(UHCI_TD PTR [di]).LinkPointer, eax

; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
	call	UHCI_FillCntrlXferFields	; BX-DevInfo, DI-TD

	mov	eax, dTemp
		; 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

	lea	ax, (UHCI_TD PTR [di]).DataArea	; AX = PTR to TDs data buffer
	movzx	eax, ax			;Clear upper half of EAX
	add	eax, HcdGlobalDataArea	;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.

	mov	di, pSetup			; DI - Pointer to control
						; Setup TD
	cmp	wLength, 0
	jz	UCT_SkipDataTds			; No data to transfer

	cmp	wLength, MAX_CONTROL_DATA_SIZE
	jb	UCT_DataSizeOkay		; Data size within limit
	mov	wLength, MAX_CONTROL_DATA_SIZE	; Limit the data size
UCT_DataSizeOkay:

; DI = PTR of TD control data
	mov	bDatToggle, 1			; Start with a data 1 token

UCT_NextDataTd:
;; Allocate one more TD to be used either for more data or for TD Status
	call	USBMem_AllocOne
	jz	UCT_ErrorExit

; Check whether this is the first data TD
	cmp	pDataTd, 0
	jne	UCT_NotFirst

; Yes. It is the first TD store it in the local variable
	mov	pDataTd, ax

UCT_NotFirst:

; Link the new TD to the previous TD
	push	ax
	movzx	eax, ax
	add	eax, HcdGlobalDataArea
; Set the vertical flag
	or	eax, UHCI_VERTICAL_FLAG
	mov	(UHCI_TD PTR [di]).LinkPointer, eax
	pop	ax

	mov	di, ax				; Points to new TD

	mov	(UHCI_TD PTR [di]).BufferPointer, edx

	movzx	eax, wLength			;  wLength = data length
	cmp	ax, (DeviceInfo PTR [bx]).wEndp0MaxPacket
	jbe	UCT_PktSizeAdjusted		; Packet size is valid
	mov	ax, (DeviceInfo PTR [bx]).wEndp0MaxPacket
UCT_PktSizeAdjusted:
	sub	wLength, ax			; Adjust overall data size
	add	edx, eax			; Adjust buffer pointer
	dec	ax				; AX = packet data size - 1
	shl	eax, 21

	or	eax, dTemp			; EAX[18:8]=Dev. addr & endp
	mov	al, OUT_PACKET			; EAX[7:0] = OUT PID
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jz	UCT_PIDFound			; OUT PID
	mov	al, IN_PACKET			; EAX[7:0] = IN PID
UCT_PIDFound:
	test	bDatToggle, 1
	jz	UCT_DataToggle			; DATA0 packet
	or	eax, DATA_TOGGLE		; Make packet into a data 1
UCT_DataToggle:
	mov	(UHCI_TD PTR [di]).Token, eax

; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
	call	UHCI_FillCntrlXferFields	; BX-DevInfo, DI-TD
; Enable short packet detect
	or	(UHCI_TD PTR [di]).ControlStatus, UHCI_TD_SHORT_PACKET_DETECT

	xor	bDatToggle, 1			; Toggle between DATA1/DATA0
	cmp	wLength, 0
	jnz	UCT_NextDataTd			; More data TDs must be built

;; End the data TD list
	mov	(UHCI_TD PTR [di]).LinkPointer, UHCI_TERMINATE

; Make the end of the data TD list to point to the TD control status
	movzx	eax, pStatus
	add	eax, HcdGlobalDataArea
	mov	(UHCI_TD PTR [di]).LinkPointer, eax

UCT_SkipDataTds:

; DI = PTR of TD control status
	mov	di, pStatus

; Fill in various fields in the TD control status.
; LinkPointer field will point to UHCI_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, dTemp		; EAX[18:8] = Device address / endpoint
	mov	al, OUT_PACKET		; EAX[7:0] = OUT PID
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jnz	UCT_StatPIDFound	; IN PID
	mov	al, IN_PACKET		; EAX[7:0] = IN PID
UCT_StatPIDFound:
	or	eax, (DATA_TOGGLE OR (UHCI_TD_DATA_LENGTH SHL 21))	; DATA0/DATA1
	mov	(UHCI_TD PTR [di]).Token, eax

	lea	ax, (UHCI_TD PTR [di]).DataArea ; 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	(UHCI_TD PTR [di]).BufferPointer, eax

; Fill common control transfer fields (ControlStatus, call back routine,
; CSReloadValue and Active flag fields)
	call	UHCI_FillCntrlXferFields	; BX-DevInfo, DI-TD

	mov	pStatus, di		; Save pointer to control status TD

	mov	di, pSetup		; Control setup TD

; Now put the control setup, data and status into the HC's schedule by
; pointing QhControl's link pointer to control setup TD.
; This will cause the HC to execute the transaction in the next active frame.

	mov	si, (DeviceInfo PTR [bx]).pHCStrucPtr
	mov	si, (HCStruc PTR [si]).pDescriptorPtr
; BX - Device Info
; SI - UHCIDescriptor pointer
; DI - Control setup TD

; Save control setup address in UHCIDescriptors
	mov	ax, pSetup
	mov	(UHCIDescriptors PTR [si]).TDControlSetup, ax
; Save control status address in UHCIDescriptors
	mov	ax, pStatus
	mov	(UHCIDescriptors PTR [si]).TDControlStatus, ax

	mov	si, (UHCIDescriptors PTR [si]).QHControl
	movzx	edi, di
	add	edi, HcdGlobalDataArea
	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, pStatus		; Control status TD pointer
; BX - DeviceInfo Ptr, DI - TD to wait on
	call	UHCIWaitForTransferComplete
; SI - HCStruc Ptr (returned from )

; 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, (HCStruc PTR [si]).pDescriptorPtr
	mov	bx, (UHCIDescriptors PTR [di]).TDControlSetup
; Set control setup and status pointers to zero
	xor	ax, ax
	mov	(UHCIDescriptors PTR [di]).TDControlSetup, ax
	mov	(UHCIDescriptors PTR [di]).TDControlStatus, ax

	mov	di, (UHCIDescriptors PTR [di]).QHControl
	mov	(UHCI_QH PTR [di]).ElementPointer, UHCI_TERMINATE
	pop	di

; Clear the stalled condition flag
	and	bLastCommandStatus, NOT USB_CONTROL_STALLED

; Check for stall condition
	test	(UHCI_TD PTR [di]).ControlStatus, UHCI_TD_STALLED
	jz	uct_NotStalled

; Command stalled set the error bit appropriately
	or	bLastCommandStatus, USB_CONTROL_STALLED

uct_NotStalled:

; 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	UCT_ErrorExit		; Br if any error bits set in status

	mov	wRetStatus, 0FFFFh	; return success

UCT_ErrorExit:

; BX - pointer to the control setup
; Free control setup TD (in BX)
	call	USBMem_FreeOne
	add	bx, SIZE UHCI_TD
; Free control status TD (in BX)
	call	USBMem_FreeOne

; Free control data TDs
	mov	ax, pDataTD
	call	UHCI_FreeTD

UCT_Exit:

	popad
	pop	es
	mov	ax, wRetStatus		; Return return status
	ret

UHCI_ControlTransfer	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCI_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:	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_UHCI_BULK_DATA_SIZE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCI_BulkTransfer	PROC NEAR SYSCALL PUBLIC USES EBX CX DX SI DI

	LOCAL	dTemp:DWORD, bDatToggle:BYTE, wRetStatus:WORD, wMaxPkt:WORD,
		bEndp:BYTE, bNumBulkTD:BYTE, pBulkDataTD

; Set return status as failure
	mov	wRetStatus, 0

; Check for 0 length transfer (if so, exit)
	or	cx, cx
	jz	UBTS_Exit

; 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

	push	dx		; Save transfer direction
; Calculate number of TDs needed
	mov	ax, cx
	xor	dx, dx
	div	wMaxPkt

	or	dx, dx
	jz	UBTS_NoRemainder

; Adjust number of TDs needed
	inc	ax

UBTS_NoRemainder:

	pop	dx		; Restore transfer direction

; AX = Number of TDs needed. Save it in a local variable
	mov	bNumBulkTD, al

; Allocate required TDs for bulk transfer
	call	USBMem_Alloc
	jz	UBTS_Exit

	mov	pBulkDataTD, ax

; Form device address and endpoint in proper order and bit position
	movzx	eax, bEndp		; EAX[3:0] = Endpoint
	shl	eax, 7			; EAX[10:7] = Endpoint
	mov	dTemp, eax
	movzx	eax, (DeviceInfo PTR [si]).bDeviceAddress
	or	eax, dTemp		; EAX[10:0] = Dev. Addr & Endpoint
	shl	eax, 8			; EAX[18:8] = Dev. Addr & Endpoint
	mov	dTemp, eax

; Save the buffer pointer in EBX
	mov	ebx, edi		; Buffer pointer

; Form the bulk data TDs
	mov	di, pBulkDataTD

UBTS_PrepareNextBulkTD:

; Form pointer to the next TD and link it in the current TD
	movzx	eax, di
	add	eax, SIZE UHCI_TD
	add	eax, HcdGlobalDataArea
; Set the vertical flag
	or	eax, UHCI_VERTICAL_FLAG
	mov	(UHCI_TD PTR [di]).LinkPointer, eax

	movzx	eax, (DeviceInfo PTR [si]).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	(UHCI_TD PTR [di]).ControlStatus, eax

	mov	(UHCI_TD PTR [di]).BufferPointer, ebx

; Adjust remaining length and buffer address
	movzx	eax, cx			;  wLength = data length
	cmp	ax, wMaxPkt
	jbe	UBTS_PktSizeAdjusted		; Packet size is valid
	mov	ax, wMaxPkt
UBTS_PktSizeAdjusted:
	sub	cx, ax				; Adjust overall data size
	add	ebx, eax			; Adjust buffer pointer
	dec	ax				; AX = packet data size - 1
	shl	eax, 21

	or	eax, dTemp			; EAX[18:8]=Dev. addr & endp

	mov	al, OUT_PACKET			; EAX[7:0] = OUT PID
	test	dl, BIT7
	jz	UBTS_PIDFound			; OUT PID
	mov	al, IN_PACKET			; EAX[7:0] = IN PID
UBTS_PIDFound:

	test	bDatToggle, 1
	jz	UBTS_DataToggle			; DATA0 packet
	or	eax, DATA_TOGGLE		; Make packet into a data 1
UBTS_DataToggle:
	mov	(UHCI_TD PTR [di]).Token, eax

	mov	(UHCI_TD PTR [di]).CSReloadValue, 0
	mov	(UHCI_TD PTR [di]).pCallback, OFFSET cs:UHCI_BulkTDCallback
	mov	(UHCI_TD PTR [di]).ActiveFlag, TRUE

	xor	bDatToggle, 1			; Toggle between DATA1/DATA0

; Position to next data TD
	add	di, SIZE UHCI_TD

; Check and build more data TDs
	cmp	cx, 0
	jnz	UBTS_PrepareNextBulkTD

; Position to the last TD
	sub	di, SIZE UHCI_TD

; End the data TD list
	mov	(UHCI_TD PTR [di]).LinkPointer, UHCI_TERMINATE


; Clear bulk stall/time out condition flag
	and	bLastCommandStatus, NOT (USB_BULK_STALLED + USB_BULK_TIMEDOUT)

; Schedule the bulk TDs by adding them in the bulk queue head
	push	di
	mov	bx, (DeviceInfo PTR [si]).pHCStrucPtr
	mov	bx, (HCStruc PTR [bx]).pDescriptorPtr
	mov	di, (UHCIDescriptors PTR [bx]).QHBulk

	movzx	eax, pBulkDataTD
; Save the bulk data TD pointer
	mov	(UHCIDescriptors PTR [bx]).TDBulkData, ax

	add	eax, HcdGlobalDataArea
; Set the vertical flag
	or	eax, UHCI_VERTICAL_FLAG
	mov	(UHCI_QH PTR [di]).ElementPointer, eax
	pop	di

; Wait for the last bulk data TD to complete. When the last TD completed its
; task the UHCI_BulkTDCallback routine will set its active flag to FALSE

	xchg	si, bx
; BX - DeviceInfo Ptr, DI - TD to wait on
	call	UHCIWaitForTransferComplete
; SI - HCStruc Ptr (returned from UHCIWaitForTransferComplete)

; Remove the bulk data TDs from the HC's schedule by pointing QhBulk
; link pointer to UHCI_TERMINATE.
	push	di
	mov	bx, (HCStruc PTR [si]).pDescriptorPtr
	mov	(UHCIDescriptors PTR [bx]).TDBulkData, 0
	mov	di, (UHCIDescriptors PTR [bx]).QHBulk
	mov	(UHCI_QH PTR [di]).ElementPointer, UHCI_TERMINATE
	pop	di

; Finally check for any error bits set in the ControlStatus field.
; If the TD did not complete successfully, return STC.
	test	(UHCI_TD PTR [di]).ControlStatus, (UHCI_TD_BITSTUFF_ERROR OR \
			UHCI_TD_NAK_RECEIVED OR UHCI_TD_BABBLE_DETECTED OR \
			UHCI_TD_DATA_BUFFER_ERROR)
	jnz	UBTS_ErrorExit		; Br if any error bits set in status

; Check for time out condition
	test	(UHCI_TD PTR [di]).ControlStatus, UHCI_TD_CRC_TIMEOUT_ERROR
	jz	UBTS_NotTimedOut

; Timed out condition is checked and cleared elsewhere
	or	bLastCommandStatus, USB_BULK_TIMEDOUT

	jmp	SHORT UBTS_ErrorExit

UBTS_NotTimedOut:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -