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

📄 ehci.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;		shown below. In any case this routine will get the device
;		address of the hub number HISP_A :
;		Notations used:
;			MBPortX		Motherboard USB port
;			HISP_X		Hi-speed hub number X
;			FUSP_X		Full-speed hub number X
;			Device		Low/Full speed device
;		Config 1:
;		  MBPortX --> HISP_A --> Device
;		Config 2:
;		  MBPortX --> HISP_A --> FUSP_1 --> Device
;		Config 3:
;		  MBPortX --> HISP_B --> HISP_A --> Device
;		Config 4:
;		  MBPortX --> HISP_A --> FUSP_1 --> HISP_B --> Device
;		  In the above configuration the HISP_B will be operated in
;		full speed rather than hi-speed since it is connected to a
;		full speed hub
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

EHCI_GetHiSpeedHubPortNumber	PROC NEAR PUBLIC
	push	bx
	push	dx


eghshpn_TryNextHub:
; Get the device number of the immediate hub
	mov	dl, (DeviceInfo PTR [bx]).bHubDeviceNumber

; Get the device info structure for this device number
	call	USBGetDeviceInfoFromDevAddr	; DL device number
; AX	Pointer to the device info structure
	or	ax, ax
	jz	eghshpn_Exit

	xchg	bx, ax
; Check whether the hub is a USB 2.0 hub
	cmp	(DeviceInfo PTR [bx]).bEndpointSpeed, 0
	jne	eghshpn_TryNextHub

; The first USB 2.0 hub found to which the low/full speed device is connected
	xchg	bx, ax		; Restore the previous (USB 1.1) devices struc

	movzx	ax, (DeviceInfo PTR [bx]).bHubPortNumber
	shl	ax, 7
	or	al, (DeviceInfo PTR [bx]).bHubDeviceNumber

eghshpn_Exit:
	pop	dx
	pop	bx
	ret
EHCI_GetHiSpeedHubPortNumber	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	EHCIControlTransfer
;
; Description:	This function executes a device request command 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:	BX	DeviceInfo structure (if available else 0)
;		The temp data area in the BX contains the following data:
;		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.)
;		wIndex		wIndex request parameter (meaning varies)
;		wValue		wValue request parameter (meaning varies)
;		fpBuffer	Buffer containing data to be sent to the
;				device or buffer to be used to receive data
;		wLength		wLength request parameter, number of bytes
;				of data to be transferred in or out
;				of the host controller
;
; Output: 	AX	0xFFFF SUCCESS
;		AX	0      ERROR
;
; Modified:	EAX
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

EHCIControlTransfer	PROC NEAR SYSCALL PUBLIC

	LOCAL	wLength:WORD

	push	bx
	push	cx
	push	edx
	push	si
	push	di

; Setup the local variables
	mov	ax, (DeviceInfo PTR [bx]).CntrlXfer.wLength
	mov	wLength, ax

	mov	si, (DeviceInfo PTR [bx]).pHCStrucPtr
; Get the control setup TD address in register DI
	mov	di, (HCStruc PTR [si]).pDescriptorPtr

; Build the device request in the data area of the control setup qTD
	push	di
	mov	di, OFFSET aControlSetupData
	call	USBMiscFormDeviceRequest	; BX	DeviceInfo structure
	pop	di

; Prepare the registers that will be used in building the qTDs below.
; 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 qTD being built.
; EAX will be left free to use as a scratch register.


; Ready the QHControl for the control transfer
	push	di
	mov	di, (EHCIDescriptors PTR [di]).QHControl

; The QH endpoint characteristic field will be set so
;   Function address & Endpoint number = From DeviceInfo structure,
;   Direction = From TD,
;   Speed = DeviceInfo.bEndpointSpeed,
;   Skip = 1, Format = 0,
;   Max packet size  = DeviceInfo.wEndp0MaxPacket
; The dNextqTDPtr field will be set to qTDControlSetup
; The dAltNextqTDPtr field will be set to EHCI_TERMINATE
; The dCurrentqTDPtr field will be set to 0

; Intialize the queue head with null pointers
	call	EHCIInitializeQueueHead		; DI	Queue head pointer

	mov	dl, (DeviceInfo PTR [bx]).bEndpointSpeed
	; DL = 00/01/10 for HI/LO/FULL

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

; Check for high speed
	or	dl, dl
	je	ectSpeedFound		; Yes. HI-speed

	mov	al, dl
	and	al, 1			; Mask off most-significant bit
	shl	ax, 12			; EAX[12] = full/low speed flag

; Set bit15 to indicate that it is not a high speed device and the transfer
; is a control transfer
	or	eax, QH_CONTROL_ENDPOINT

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

; Use data toggle from qTD and this QH is the head of the queue
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
	or	al, (DeviceInfo PTR [bx]).bDeviceAddress
; EAX[6:0] = Dev. Addr, EAX[7] = I bit(0) & EAX[11:8] = Endpoint (0)

	mov	dx, (DeviceInfo PTR [bx]).wEndp0MaxPacket
	shl	edx, 16			; EDX[26:16] = device's packet size
	or	eax, edx
	mov	(EHCI_QH PTR [di]).dEndPntCharac, eax

; Pointers in QH are initialized later
	pop	di

; Fill in various fields in the qTDControlSetup.
	push	di
	mov	di, (EHCIDescriptors PTR [di]).qTDControlSetup
					; DI - Pointer to TDControlSetup

; The token field will be set so
;   Direction PID = QTD_SETUP_TOKEN,
;   Size = size of the data,
;   Data Toggle = QTD_SETUP_TOGGLE,
;   Error Count = QTD_NO_ERRORS,
;   Status code = QTD_DO_OUT + QTD_ACTIVE
; The buffer pointers field will point to the aControlSetupData buffer
;   which was before initialized to contain a DeviceRequest struc.
; The dNextqTDPtr field will point to the qTDControlData if data will
;   be sent/received or to the qTDControlStatus if no data is expected.
; The dAltNextqTDPtr field will be set to EHCI_TERMINATE

	mov	(EHCI_QTD PTR [di]).dToken, QTD_SETUP_TOKEN OR \
				QTD_SETUP_TOGGLE OR QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_DO_OUT OR QTD_ACTIVE \
				(8 SHL 16)	; Data size


; Update buffer pointers
	mov	eax, OFFSET aControlSetupData
					; EAX = Pointer to setup data
	add	eax, HcdGlobalDataArea	; EAX = abs addr of TD's 8 byte data buffer
	mov	cx, 8
; DI	QTD pointer
; EAX	Buffer address (32bit absolute)
; CX	Size of the buffer
	call	EHCISetQTDBufferPointers
	pop	di

	cmp	wLength, 0
	jz	ectSkipDataTds			; No data to transfer

; Fill in various fields in the qTDControlData
	push	di
	mov	di, (EHCIDescriptors PTR [di]).qTDControlData
					; DI - Pointer to TDControlData

; The token field will be set so
;   Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
;   Size = size of the data,
;   Data Toggle = QTD_DATA1_TOGGLE,
;   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	(EHCI_QTD PTR [di]).dToken, QTD_IN_TOKEN OR \
				QTD_DATA1_TOGGLE OR QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_ACTIVE
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jnz	ectInPacket		; Br if host sending data to device (OUT)

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

; Set length
	mov	ax, wLength
	mov	cx, ax		; Needed later
	shl	eax, 16
	or	(EHCI_QTD PTR [di]).dToken, eax

; Change Seg:Off in fpBuffer to 32 bit absolute address
	call	USBMiscGetFarBufferAddress	; BX	DevInfo
; Return value in EDX
	mov	eax, edx

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

	pop	di

ectSkipDataTds:

; Fill in various fields in the qTDControlStatus
	push	di
	mov	di, (EHCIDescriptors PTR [di]).qTDControlStatus
					; DI - Pointer to TDControlStatus

; The token field will be set so
;   Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
;   Size = 0,
;   Data Toggle = QTD_DATA1_TOGGLE,
;   Error Count = QTD_NO_ERRORS,
;   Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
; The buffer pointers field will be 0
; The dNextqTDPtr field will set to EHCI_TERMINATE
; The dAltNextqTDPtr field will be set to EHCI_TERMINATE

; For OUT control transfer status should be IN and
; for IN cotrol transfer, status should be OUT
	mov	(EHCI_QTD PTR [di]).dToken, QTD_IN_TOKEN OR \
				QTD_DATA1_TOGGLE OR QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_ACTIVE
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jz	ectInPacket0		; Br if host sending data to device (OUT)
; OUT packet
	mov	(EHCI_QTD PTR [di]).dToken, QTD_OUT_TOKEN OR \
				QTD_DATA1_TOGGLE OR QTD_IOC_BIT OR \
				QTD_NO_ERRORS OR QTD_DO_OUT OR QTD_ACTIVE
ectInPacket0:

; Update buffer pointers (with null values)
; DI	QTD pointer
; EAX	Buffer address (32bit absolute)
; CX	Size of the buffer
	xor	cx, cx
	call	EHCISetQTDBufferPointers
	pop	di			; Control setup TD

; Link the qTD formed now and connect them with the control queue head
	push	bx
	push	si

	mov	bx, (EHCIDescriptors PTR [di]).QHControl
	mov	si, (EHCIDescriptors PTR [di]).qTDControlSetup
	movzx	eax, si
	mov	(EHCI_QH PTR [bx]).pFirstqTD, ax
	add	eax, HcdGlobalDataArea
	mov	(EHCI_QH PTR [bx]).dNextqTDPtr, eax

	mov	bx, (EHCIDescriptors PTR [di]).qTDControlData
					; BX	Offset of TDControlData
	cmp	wLength, 0
	jnz	ectNoData		; Br if data length is non-zero

	mov	bx, (EHCIDescriptors PTR [di]).qTDControlStatus
					; BX	Offset of TDControlStatus
ectNoData:
	movzx	eax, bx
	add	eax, HcdGlobalDataArea	; EAX	32bit absolute address
	mov	(EHCI_QTD PTR [si]).dNextqTDPtr, eax

	cmp	bx, (EHCIDescriptors PTR [di]).qTDControlData
	jne	ectTDLinkDone

	movzx	eax, (EHCIDescriptors PTR [di]).qTDControlStatus
	push	ax
	add	eax, HcdGlobalDataArea	; EAX	32bit absolute address
	mov	(EHCI_QTD PTR [bx]).dNextqTDPtr, eax
	pop	bx

ectTDLinkDone:
	xor	eax, eax
	inc	eax
	mov	(EHCI_QTD PTR [bx]).dNextqTDPtr, eax
	pop	si
	pop	bx

	mov	bx, (EHCIDescriptors PTR [di]).QHControl
					; BX - Pointer to QHControl

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

; Insert the QHControl 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
ENDIF

	EHCI_SET_FS_EDI

IFE	MKF_EHCI_ASYNC_BELL_SUPPORT
; Set the ASYNCLISTADDR register to point to the QHControl
	movzx	eax, bx
	add	eax, HcdGlobalDataArea
	EHCI_DWORD_WRITE_MEM	si, EHCI_ASYNCLISTADDR, eax

; Set next QH pointer to itself (circular link)
	or	eax, EHCI_QUEUE_HEAD
	mov	(EHCI_QH PTR [bx]).dLinkPointer, eax
	mov	(EHCI_QH PTR [bx]).bActive, TRUE
ENDIF

; Now put the control setup, data and status 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

; Now wait for the control transfer to complete
; SI	HCStruc pointer
; BX	QH to wait for
	call	EHCIWaitForTransferComplete

IF	MKF_EHCI_ASYNC_BELL_SUPPORT
; Disconnect QHControl from the Async list
; BX	Pointer to the QHControl
	call	EHCIRemoveQHFromAsyncList
ENDIF

; Clear the stalled condition flag
	and	bLastCommandStatus, NOT USB_CONTROL_STALLED

; Check whether the QH stopped or timed out
	cmp	(EHCI_QH PTR [bx]).bActive, FALSE
	je	ectXferCheckError

IFE	MKF_EHCI_ASYNC_BELL_SUPPORT
; Stop the Async transfer
	call	EHCIStopAsyncSchedule	; SI	HCStruc pointer
ENDIF

	mov	(EHCI_QH PTR [bx]).bActive, FALSE
	xor	ax, ax		; Error
	jmp	SHORT ectExit

ectXferCheckError:
; Check for the stall condition
	test	(EHCI_QH PTR [bx]).bErrorStatus, QTD_HALTED
	jz	ectXferOkay

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

	jmp	SHORT ectExit

ectXferOkay:
	mov	ax, 0FFFFh		; Indicate success
ectExit:
	push	ax
	xor	eax, eax
	mov	(EHCI_QH PTR [bx]).pFirstqTD, ax
	inc	eax
	mov	(EHCI_QH PTR [bx]).dNextqTDPtr, eax
	pop	ax

	RESTORE_FS_EDI

	pop	di
	pop	si
	pop	edx
	pop	cx
	pop	bx
	ret

EHCIControlTransfer	ENDP

⌨️ 快捷键说明

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