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

📄 ehci.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	EHCIBulkTransfer
;
; 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.)
;		NOTE: Make sure that amount of bytes to transfer should not
;		      exceed MAX_EHCI_DATA_SIZE
;
; 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
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

EHCIBulkTransfer	PROC NEAR SYSCALL PUBLIC USES EBX CX DX SI DI ES

	LOCAL	wMaxPkt:WORD, bEndp:BYTE, bDatToggle:BYTE, fpBUFFER:DWORD

; 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

; Get EHCIDescriptors pointer in BX
	mov	bx, (DeviceInfo PTR [si]).pHCStrucPtr
	mov	bx, (HCStruc PTR [bx]).pDescriptorPtr

; Get the QHBulk pointer in Di
	mov	di, (EHCIDescriptors PTR [bx]).QHBulk

; Set the QH's dNextqTDPtr field to bulk data qTD and dAltqTDPtr field to
; EHCI_TERMINATE. Also set QH's link pointer to itself
	movzx	eax, (EHCIDescriptors PTR [bx]).qTDBulkData

; Intialize the queue head
	call	EHCIInitializeQueueHead		; DI	Queue head pointer

; Set the first qTD pointer
	mov	(EHCI_QH PTR [di]).pFirstqTD, ax

	add	eax, HcdGlobalDataArea
	mov	(EHCI_QH PTR [di]).dNextqTDPtr, eax

	movzx	eax, di
	add	eax, HcdGlobalDataArea
	or	eax, EHCI_QUEUE_HEAD
	mov	(EHCI_QH PTR [di]).dLinkPointer, eax

	push	bx		; Descriptor pointer

; Get device info pointer
	movzx	eax, (DeviceInfo PTR [si]).bDeviceAddress
	movzx	bx, bEndp
	shl	bx, 8
	or	ax, bx		; AX - Device address & Endpoint

; Set max packet size
	movzx	ebx, wMaxPkt
	shl	ebx, 16
	or	eax, ebx

; Set the data toggle control
IF	MKF_EHCI_ASYNC_BELL_SUPPORT
	or	eax, QH_USE_QTD_DT
ELSE
	or	eax, (QH_USE_QTD_DT OR QH_HEAD_OF_LIST)
ENDIF	;; MKF_EHCI_ASYNC_BELL_SUPPORT

; Set the device speed
; Reset the device speed bits
	xor	ebx, ebx
	mov	bl, (DeviceInfo PTR [si]).bEndpointSpeed
	; BL = 00/01/10 for HI/LO/FULL

; Assume as a high speed device
	or	eax, QH_HIGH_SPEED	; 10b - High speed

; Check for high speed
	or	bl, bl
	je	ebtsSpeedFound		; Yes. HI-speed

	and	bl, 1			; Mask off most-significant bit
	shl	bx, 12			; EAX[12] = full/low speed flag

	and	eax, NOT QH_ENDPOINT_SPEED
	or	eax, ebx

	push	eax
	push	bx
	mov	bx, si
; Set the hub address and port number
	call	EHCI_GetHiSpeedHubPortNumber
	; AX	Hispeed hub port number & device number
	shl	eax, 16
	or	eax, BIT14		; Split complete Xaction
	or	(EHCI_QH PTR [di]).dEndPntCap, eax
	pop	bx
	pop	eax

ebtsSpeedFound:

	pop	bx			; Descriptor pointer
; Update the AH's endpoint characteristcs field with the data formed
	mov	(EHCI_QH PTR [di]).dEndPntCharac, eax

; Fill the bulk data qTD with relevant information
; The token field will be set so
;   Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
;   Size = size of the data,
;   Data Toggle = bDatToggle,
;   Error Count = QTD_NO_ERRORS,
;   Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
; The buffer pointers field will point to the fpBuffer buffer
;   which was before initialized to contain a DeviceRequest struc.
; The dNextqTDPtr field will point to the qTDControlSetup
; The dAltNextqTDPtr field will be set to EHCI_TERMINATE

	mov	di, (EHCIDescriptors PTR [bx]).qTDBulkData

	mov	(EHCI_QTD PTR [di]).dToken, QTD_IN_TOKEN OR \
				QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_ACTIVE
	test	dl, BIT7
	jnz	ebtsInPacket		; Br if host sending data to device (OUT)

; OUT packet
	mov	(EHCI_QTD PTR [di]).dToken, QTD_OUT_TOKEN OR \
				QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_DO_OUT OR QTD_ACTIVE
ebtsInPacket:

; Set the data toggle depending on the bDatToggle value
	movzx	eax, bDatToggle
	shl	eax, 31
	or	(EHCI_QTD PTR [di]).dToken, eax

; Set length
	movzx	eax, cx
	shl	eax, 16
	or	(EHCI_QTD PTR [di]).dToken, eax

; Update buffer pointers
	mov	eax, fpBuffer
; DI	QTD pointer
; EAX	Buffer address (32bit absolute)
; CX	Size of the buffer
	call	EHCISetQTDBufferPointers

; Update next & alternate next qTD pointers
	mov	eax, EHCI_TERMINATE
	mov	(EHCI_QTD PTR [di]).dNextqTDPtr, eax
	mov	(EHCI_QTD PTR [di]).dAltNextqTDPtr, eax


	push	si

	mov	si, (DeviceInfo PTR [si]).pHCStrucPtr
	EHCI_SET_FS_EDI

	mov	bx, (EHCIDescriptors PTR [bx]).QHBulk
					; bx - Pointer to QHBulk

IF	MKF_EHCI_ASYNC_BELL_SUPPORT
; EAX = EHCI_TERMINATE
	mov	(EHCI_QH PTR [bx]).dLinkPointer, eax

; Insert the QHBulk into the Async list
	mov	ax, bx
	add	eax, HcdGlobalDataArea
	or	eax, EHCI_QUEUE_HEAD
	push	bx
	mov	bx, pQHAsyncXfer
	xchg	(EHCI_QH PTR [bx]).dLinkPointer, eax
	pop	bx
	mov	(EHCI_QH PTR [bx]).dLinkPointer, eax

ELSE

; Set the ASYNCLISTADDR register to point to the QHBulk
	movzx	eax, bx
	add	eax, HcdGlobalDataArea
	EHCI_DWORD_WRITE_MEM	si, EHCI_ASYNCLISTADDR, eax
ENDIF
	mov	(EHCI_QH PTR [bx]).bActive, TRUE

; Now put the bulk QH into the HC's schedule by
; setting the Async. schedule enabled field of USBCMD register
; This will cause the HC to execute the transaction in the next active frame.
	call	EHCIStartAsyncSchedule	; SI	HCStruc pointer

; Set bulk condition as not stalled
	and	bLastCommandStatus, NOT (USB_BULK_STALLED + USB_BULK_TIMEDOUT)

; Now wait for bulk transaction to be complete
; the EHCIProcessInterrupt will set its active flag to FALSE.
; Now wait for the bulk transfer to complete
; SI	HCStruc pointer
; BX	QH to wait for
	call	EHCIWaitForTransferComplete
IF	MKF_EHCI_ASYNC_BELL_SUPPORT
; Disconnect QHBulk from the Async list
; BX	Pointer to the QHControl
	call	EHCIRemoveQHFromAsyncList
ENDIF

	mov	ax, bx		; To test the error condition
; Check whether the QH stopped or timed out
	cmp	(EHCI_QH PTR [bx]).bActive, FALSE
	je	ebtsCheckError
IFE	MKF_EHCI_ASYNC_BELL_SUPPORT
; Stop the Async transfer
	call	EHCIStopAsyncSchedule	; SI	HCStruc pointer
ENDIF


	mov	(EHCI_QH PTR [bx]).bActive, FALSE

; Set time out status
	or	bLastCommandStatus, USB_BULK_TIMEDOUT
	jmp	SHORT ebtsXferError

ebtsCheckError:
; Check for the error conditions - if possible recover from them
	test	(EHCI_QH PTR [bx]).bErrorStatus, QTD_HALTED
	jz	ebtsXferOkay

; Reset time out status
	and	bLastCommandStatus, NOT USB_BULK_TIMEDOUT

; Stall condition is checked and cleared elsewhere
	or	bLastCommandStatus, USB_BULK_STALLED

ebtsXferError:
	xor	ax, ax		; Error

ebtsXferOkay:

	RESTORE_FS_EDI
	pop	si		; Device info structure

	or	ax, ax
	jz	ebtsExit

	push	cx
; Update the data toggle value into the mass info structure
	mov	eax, (EHCI_QH PTR [bx]).dToken
	and	eax, QH_DATA_TOGGLE
	shr	eax, 31
	and	al, 1		; Mask off top bits
	mov	cl, al
; SI	DeviceInfo structure
; DL	Xfer direction
; CL	Data toggle value
	call	USBMiscUpdateBulkDataSync
	pop	cx

ebtsSuccess:
; 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
; Get the first qTD pointer
	mov	di, (EHCI_QH PTR [bx]).pFirstqTD
	mov	eax, (EHCI_QTD PTR [di]).dToken
	and	eax, NOT QTD_DATA_TOGGLE	; Reset data toggle bit
	shr	eax, 16
	or	ax, ax
	jz	ebtsFoundSize
	sub	cx, ax
ebtsFoundSize:
	mov	ax, cx

ebtsExit:
	push	ax
	xor	eax, eax
	mov	(EHCI_QH PTR [bx]).pFirstqTD, ax
	inc	eax
	mov	(EHCI_QH PTR [bx]).dNextqTDPtr, eax
	pop	ax

	ret
EHCIBulkTransfer	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	EHCIInterruptTransfer
;
; 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>

EHCIInterruptTransfer	PROC NEAR SYSCALL PUBLIC USES EBX CX EDX SI DI

        LOCAL   bDatToggle:BYTE

        push    fs
        push    eax

; 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

	mov	al, (DeviceInfo PTR [si]).bDataSync
	and	al, USB_INT_DATA_SYNC
	shr	al, USB_INT_DATA_SYNC_SHIFT
	mov	bDatToggle, al

	mov	bx, (HCStruc PTR [di]).pDescriptorPtr

; Get the QHInterrupt pointer in Di
	mov	di, (EHCIDescriptors PTR [bx]).QHInterrupt

	mov	(EHCI_QH PTR [di]).pCallBackFunc, 0FFFFh
	push	bx		; Descriptor pointer

; Get device info pointer
	movzx	eax, (DeviceInfo PTR [si]).bDeviceAddress
	movzx	bx, (DeviceInfo PTR [si]).bIntEndpoint
	shl	bx, 8
	or	ax, bx		; AX - Device address & Endpoint

; Set max packet size
	movzx	ebx, (DeviceInfo PTR [si]).wIntMaxPkt
	shl	ebx, 16
	or	eax, ebx

; Set the data toggle control
	or	eax, (QH_USE_QTD_DT OR QH_HEAD_OF_LIST)

; Set the device speed
; Reset the device speed bits
	xor	ebx, ebx
	mov	bl, (DeviceInfo PTR [si]).bEndpointSpeed
	; BL = 00/01/10 for HI/LO/FULL

; Assume as a high speed device
	or	eax, QH_HIGH_SPEED	; 10b - High speed

; Check for high speed
	or	bl, bl
	je	eitsSpeedFound		; Yes. HI-speed

	and	bl, 1			; Mask off most-significant bit
	shl	bx, 12			; EAX[12] = full/low speed flag

	and	eax, NOT QH_ENDPOINT_SPEED
	or	eax, ebx

	push	eax
	push	bx
	mov	bx, si
; Set the hub address and port number
	call	EHCI_GetHiSpeedHubPortNumber
	; AX	Hispeed hub port number & device number
	shl	eax, 16
	or	eax, (BIT10 + BIT11 + BIT12)	; Split complete Xaction
	or	(EHCI_QH PTR [di]).dEndPntCap, eax
	pop	bx
	pop	eax

eitsSpeedFound:

	pop	bx			; Descriptor pointer
; Update the AH's endpoint characteristcs field with the data formed
	mov	(EHCI_QH PTR [di]).dEndPntCharac, eax

	or	(EHCI_QH PTR [di]).dEndPntCap, (BIT0 OR QH_ONE_XFER)
					; Interrupt schedule mask

; Fill the interrupt data qTD with relevant information
; The token field will be set so
;   Direction PID = QTD_IN_TOKEN,
;   Size = size of the data,
;   Data Toggle = bDatToggle,
;   Error Count = QTD_NO_ERRORS,
;   Status code = QTD_ACTIVE
; The buffer pointers field will point to the EDX
;   which was before initialized to contain a DeviceRequest struc.
; The dNextqTDPtr field will point to the qTDControlSetup
; The dAltNextqTDPtr field will be set to EHCI_TERMINATE

	mov	di, (EHCIDescriptors PTR [bx]).qTDInterruptData

	mov	(EHCI_QTD PTR [di]).dToken, QTD_IN_TOKEN OR \
				QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_ACTIVE

; Set the data toggle depending on the bDatToggle value
	movzx	eax, bDatToggle
	shl	eax, 31
	or	(EHCI_QTD PTR [di]).dToken, eax

; Set length
	movzx	eax, cx
	shl	eax, 16
	or	(EHCI_QTD PTR [di]).dToken, eax

; Update buffer poin

⌨️ 快捷键说明

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