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

📄 ohci.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;			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:	AX
;
; Referrals:	None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

OHCI_ControlTransfer	PROC NEAR SYSCALL PUBLIC 

	LOCAL	wLength:WORD

	push	ebx
	push	cx
	push	edx
	push	si
	push	di

; Necessary for OHCI host controllers
	mov	ax, ((5 * 1000) / 15)	; 5ms delay
	call	USBMisc_FixedDelay

; 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, (OHCIDescriptors PTR [di]).TDControlSetup
	add	di, OHCI_TD.SetupData
	call	USBMiscFormDeviceRequest	; BX	DeviceInfo structure
	pop	di

; Prepare some registers that will be used in building the TDs below.
; wLength  contains the data length.
; fpBuffer contains the absolute address of the data buffer.
; wRequest contains the request type (bit 7 = 0/1 for Out/In).
; 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 TD being built.
; EAX will be left free to use as a scratch register.

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

; The ED control field will be set so
;   Function address & Endpoint number = ESI,
;   Direction = From TD,
;   Speed = DeviceInfo.bEndpointSpeed,
;   Skip = 1, Format = 0,
;   Max packet size  = DeviceInfo.wEndp0MaxPacket
; The HeadPointer field will be set to TDControlSetup
; The TailPointer field will be set to OHCI_TERMINATE
; The LinkPointer field will be set to OHCI_TERMINATE

	movzx	eax, (DeviceInfo PTR [bx]).wEndp0MaxPacket
; Force the max packet size to 64 bytes
	cmp	ax, 40h
	jbe	OCT_EndPointOkay
	mov	ax, 40h
OCT_EndPointOkay:
	shl	eax, 16			; EAX[26:16] = device's packet size

	movzx	ax, (DeviceInfo PTR [bx]).bEndpointSpeed
	; AL = 00/01/10 for HI/LO/FULL
	and	al, 1			; Mask off MSb
	shl	ax, 13			; EAX[13] = full/low speed flag
	or	al, (DeviceInfo PTR [bx]).bDeviceAddress	; EAX[10:0] = Endp/Addr
	or	eax, ED_SKIP_TDQ
	mov	(OHCI_ED PTR [di]).Control, eax

	xor	eax, eax		; OHCI_TERMINATE
	mov	(OHCI_ED PTR [di]).TailPointer, eax
	mov	(OHCI_ED PTR [di]).LinkPointer, eax
	pop	di

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

; The ControlStatus field will be set so
;   Buffer Rounding = 1,
;   Direction PID = GTD_SETUP_PACKET,
;   Delay Interrupt = GTD_IntD,
;   Data Toggle = GTD_SETUP_TOGGLE,
;   Error Count = GTD_NO_ERRORS,
;   Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to the TD's SetupData buffer
;   which was before initialized to contain a DeviceRequest struc.
; The BufferEnd field will point to the last byte of the TD's SetupData
;   buffer.
; The LinkPointer field will point to the TDControlData if data will
;   be sent/received or to the TDControlStatus if no data is expected.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTDCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
;   not need rebinding to the EDControl.

	mov	(OHCI_TD PTR [di]).ControlStatus, GTD_BUFFER_ROUNDING OR \
				GTD_SETUP_PACKET OR GTD_SETUP_TOGGLE OR \
				GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)

	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 8 byte data buffer
	mov	(OHCI_TD PTR [di]).CurrentBufferPointer, eax

	add	eax, (SIZE (OHCI_TD PTR [di]).SetupData) - 1
	mov	(OHCI_TD PTR [di]).BufferEnd, eax

	pop	di

	cmp	wLength, 0
	jz	OCT_SkipDataTds			; No data to transfer

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

; The ControlStatus field will be set so
;   Buffer Rounding = 1,
;   Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
;   Delay Interrupt = GTD_IntD,
;   Data Toggle = GTD_DATA1_TOGGLE,
;   Error Count = GTD_NO_ERRORS,
;   Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to the caller's buffer
;   which is now in EBP.
; The BufferEnd field will point to the last byte of the caller's buffer.
; The LinkPointer field will point to the TDControlStatus.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTDCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
;   not need rebinding to the EDControl.

	mov	eax, GTD_BUFFER_ROUNDING OR GTD_OUT_PACKET OR \
		     GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jz	OCT_OutPacket		; Br if host sending data to device (OUT)
	mov	eax, GTD_BUFFER_ROUNDING OR GTD_IN_PACKET OR GTD_IntD OR \
		     GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
OCT_OutPacket:
	mov	(OHCI_TD PTR [di]).ControlStatus, eax

; Change Seg:Off in fpBuffer to 32 bit absolute address
	call	USBMiscGetFarBufferAddress	; BX	DevInfo
; Return value in EDX
	mov	(OHCI_TD PTR [di]).CurrentBufferPointer, edx

	movzx	eax, wLength 		; EAX = data length
	cmp	ax, MAX_CONTROL_DATA_SIZE
	jbe	OCT_BufferOkay		; Br if processed data <= buffer size
	mov	ax, MAX_CONTROL_DATA_SIZE
OCT_BufferOkay:
	add	eax, edx
	dec	eax
	mov	(OHCI_TD PTR [di]).BufferEnd, eax

	pop	di

OCT_SkipDataTds:

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

; The ControlStaus field will be set so
;   Buffer Rounding = 1,
;   Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
;   Delay Interrupt = GTD_IntD,
;   Data Toggle = GTD_DATA1_TOGGLE,
;   Error Count = GTD_NO_ERRORS,
;   Condition Code = GTD_NOT_ACCESSED
; The CurrentBufferPointer field will point to NULL
; The BufferEnd field will point to NULL.
; The LinkPointer field will point to OHCI_TERMINATE.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the OHCI_ControlTdCallback routine.
; The ActiveFlag field will be set to TRUE.
; The DeviceAddress field does not need to be set since the Control TDs do
;   not need rebinding to the EdControl.

; For OUT control transfer status should be IN and
; for IN cotrol transfer, status should be OUT
	mov	eax, GTD_BUFFER_ROUNDING OR GTD_IN_PACKET OR GTD_IntD OR \
		     GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR (GTD_NOT_ACCESSED SHL 28)
	test	(DeviceInfo PTR [bx]).CntrlXfer.wRequest, BIT7
	jz	OCT_InPacket		; Br if host sending data to device (OUT)
	mov	eax, GTD_BUFFER_ROUNDING OR GTD_OUT_PACKET OR \
		     GTD_DATA1_TOGGLE OR GTD_NO_ERRORS OR \
		     (GTD_NOT_ACCESSED SHL 28)
OCT_InPacket:
	mov	(OHCI_TD PTR [di]).ControlStatus, eax

	xor	eax, eax
	mov	(OHCI_TD PTR [di]).CurrentBufferPointer, eax
	mov	(OHCI_TD PTR [di]).BufferEnd, eax
	mov	(OHCI_TD PTR [di]).LinkPointer, eax
	pop	di			; Control setup TD

; Link all the pointers together
	push	bx
	push	si
	mov	bx, (OHCIDescriptors PTR [di]).EDControl
	mov	si, (OHCIDescriptors PTR [di]).TDControlSetup
	movzx	eax, si
	add	eax, HcdGlobalDataArea
	mov	(OHCI_ED PTR [bx]).HeadPointer, eax

	push	si
	mov	bx, (OHCIDescriptors PTR [di]).TDControlData
	cmp	wLength, 0
	jnz	OCT_NoData
	mov	bx, (OHCIDescriptors PTR [di]).TDControlStatus
OCT_NoData:
	movzx	eax, bx
	add	eax, HcdGlobalDataArea
	mov	(OHCI_TD PTR [si]).LinkPointer, eax

	cmp	bx, (OHCIDescriptors PTR [di]).TDControlData
	jne	OCT_TDLinkDone

	movzx	eax, (OHCIDescriptors PTR [di]).TDControlStatus
	push	ax
	add	eax, HcdGlobalDataArea
	mov	(OHCI_TD PTR [bx]).LinkPointer, eax
	pop	bx

OCT_TDLinkDone:
	xor	eax, eax
	mov	(OHCI_TD PTR [bx]).LinkPointer, eax
	pop	si

OCT_InitTD:
	mov	(OHCI_TD PTR [si]).CSReloadValue, 0
	mov	(OHCI_TD PTR [si]).pCallback, OFFSET cs:OHCI_ControlTDCallback
	mov	(OHCI_TD PTR [si]).ActiveFlag, TRUE
	mov	esi, (OHCI_TD PTR [si]).LinkPointer
	or	esi, esi
	jz	OCT_TDLinkReallyDone
	sub	esi, HcdGlobalDataArea
	jmp	SHORT OCT_InitTD
	
OCT_TDLinkReallyDone:
	pop	si
	pop	bx

; Now complete the control queue, so set ED_SKIP_TDQ=0
	push	di
	mov	di, (OHCIDescriptors PTR [di]).EDControl
					; DI - Pointer to EDControl
	and	(OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ

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

; Set the HcControlHeadED register to point to the EDControl.
	movzx	eax, di

	SET_FS_EDI

	add	eax, HcdGlobalDataArea
	USBPORT_DWORD_WRITE_MEM	si, OHCI_CONTROL_HEAD_ED, eax

; Now put the control setup, data and status into the HC's schedule by
; setting the ControllListFilled field of HcCommandStatus reg.
; This will cause the HC to execute the transaction in the next active frame.
	USBPORT_DWORD_WRITE_MEM	si, OHCI_COMMAND_STATUS, CONTROL_LIST_FILLED

	RESTORE_FS_EDI
	pop	di

; Now wait for the control status TD to complete.  When it has completed,
; the OHCI_ControlTDCallback will set its active flag to FALSE.

	mov	di, (OHCIDescriptors PTR [di]).TDControlStatus
					; DI - Pointer to TDControlStatus

; Now wait for the control status TD to complete.
	call	OHCIWaitForTransferComplete

; Stop the HC from processing the EDControl by setting its Skip bit.
	push	di
	mov	di, (HCStruc PTR [si]).pDescriptorPtr
	mov	di, (OHCIDescriptors PTR [di]).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

	and	bLastCommandStatus, NOT USB_CONTROL_STALLED
; Check for stall condition
	cmp	bl, GTD_STALL
	jne	oct_NotStalled
; Control stall condition is checked and cleared elsewhere
	or	bLastCommandStatus, USB_CONTROL_STALLED
oct_NotStalled:

	or	bl, bl
	mov	ax, 0			; Indicate error, preserve ZF
	jnz	OCT_Exit		; Br if any error bits set in status
	mov	ax, 0FFFFh		; Indicate success

OCT_Exit:

	pop	di
	pop	si
	pop	edx
	pop	cx
	pop	ebx
	ret

OHCI_ControlTransfer	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	OHCI_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 in 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_OHCI_BULK_DATA_SIZE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

OHCI_BulkTransfer	PROC NEAR SYSCALL PUBLIC

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

	push	ebx
	push	cx
	push	si
	push	di

; 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

; Set the SKIP bit in the EdBulk to avoid accidental scheduling
	mov	bx, (DeviceInfo PTR [si]).pHCStrucPtr
	mov	bx, (HCStruc PTR [bx]).pDescriptorPtr
	mov	di, (OHCIDescriptors PTR [bx]).EDBulk
	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.
	movzx	eax, (OHCIDescriptors PTR [bx]).TDBulkData
	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

; 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:

	push	bx		; Descriptor pointer

; Get device info pointer
	mov	al, (DeviceInfo PTR [si]).bDeviceAddress

⌨️ 快捷键说明

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