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

📄 ohci_bb.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 4 页
字号:

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

	mov	di, OFFSET GTDControlStatus
					; DI - Pointer to TDControlStatus

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

; Stop the HC from processing the EDControl by setting its Skip bit.
	push	di
	mov	di, OFFSET 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
	or	bl, bl
	jnz	OBCT_Error
; Success. Clear the zero flag
	or	sp, sp
	jmp	SHORT OBCT_Exit
OBCT_Error:
; Error. Set zero flag
	cmp	sp, sp
OBCT_Exit:
	popad
	pop	es
	pop	fs
	ret

OHCIBB_ControlTransfer	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	OHCIBB_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:	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: 	ZR	On error
;		NZ	On success
;			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>


OHCIBB_BulkTransfer	PROC NEAR SYSCALL PUBLIC

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

	push	fs
	push	ebx
	push	cx
	push	si
	push	di

; Get Bulk IN/OUT enpoint number, data sync value & max packet size
	call	USBMBB_GetBulkEndPointInfo
; 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 EDControl to avoid accidental scheduling
	mov	di, OFFSET EDControl
	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.
	mov	eax, OFFSET GTDData
	add	eax, dGlobalDataArea
	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:

; Get device info pointer
	mov	al, CurrentDevice.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

; 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, OFFSET GTDData

; 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:OHCIBB_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, OFFSET EDControl
	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, dGlobalDataArea

; Set FS:DI to point to the memory base address of the HC
	call	OHCIBB_SetFS_DI

	mov	DWORD PTR FS:[di+OHCI_BULK_HEAD_ED], eax

; Set bulk condition as not stalled
	mov	bLastBulkCommandStalled, FALSE

; Enable the bulk list processing
	or	DWORD PTR FS:[di+OHCI_COMMAND_STATUS], BULK_LIST_FILLED

	mov	di, OFFSET GTDData
; Now wait for the bulk data TD to complete.
	call	OHCIBB_WaitForTransferComplete

; Stop the HC from processing the EDControl by setting its Skip bit.
	push	di
	mov	di, OFFSET EDControl
	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
; DL	Xfer direction
; CL	Data toggle value
	call	USBMBB_UpdateBulkDataSync
	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

; Check for stall condition
	cmp	al, GTD_STALL
	jne	OBTS_ErrorExit

; Stall condition is checked and cleared elsewhere
	mov	bLastBulkCommandStalled, TRUE


OBTS_ErrorExit:
; Return with error
	xor	ax, ax
	cmp	sp, sp		; Set zero flag
	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
	or	sp, sp			; Clear zero flag

OBTS_Exit:
	pop	di
	pop	si
	pop	cx
	pop	ebx
	pop	fs
	ret
OHCIBB_BulkTransfer	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	OHCIBB_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:	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: 	ZR	On error
;		NZ	On success
;
; 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>

OHCIBB_InterruptTransfer	PROC NEAR SYSCALL PUBLIC USES EAX 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	di, OFFSET 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.
	mov	eax, OFFSET GTDData
	add	eax, dGlobalDataArea
	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

; Get maximum packet size from device info structure
	mov	ax, CurrentDevice.wIntMaxPkt
	mov	wMaxPkt, ax

	mov	al, CurrentDevice.bIntEndpoint
	mov	bEndp, al

	mov	al, CurrentDevice.bDataSync
	and	al, USB_INT_DATA_SYNC
	shr	al, USB_INT_DATA_SYNC_SHIFT
	mov	bDatToggle, al

; 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, CurrentDevice.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, OFFSET GTDData

; 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:OHCIBB_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, OFFSET EDInterrupt
	and	(OHCI_ED PTR [di]).Control, NOT ED_SKIP_TDQ

	mov	di, OFFSET GTDData
; Now wait for the interrupt data TD to complete.
	call	OHCIBB_WaitForTransferComplete

; Stop the HC from processing the EDInterrupt by setting its Skip bit.
	push	di
	mov	di, OFFSET 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
; Reset toggle bit
	mov	al, 1
	shl	al, cl
	not	al
	and	CurrentDevice.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	CurrentDevice.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
	jz	OIT_Success
; Return with error. Set the zero flag
	cmp	sp, sp
	jmp	SHORT OIT_Exit
OIT_Success:
; Clear the zero flag
	or	sp, sp
OIT_Exit:
	ret
OHCIBB_InterruptTransfer	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:	OHCIBB_ProcessInterrupt
;
; Description:	This function is called when the USB interrupt bit is
;		set. This function will parse through the TDs and QHs to
;		find out completed TDs and call their respective call
;		back functions
;
; Input: 	Nothing (All necessary data are in global variables)
;
; Output: 	None
;
; Modified:	Nothing
;
; Referrals:	OHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

OHCIBB_ProcessInterrupt		PROC NEAR SYSCALL PUBLIC

	push	fs
	push	eax
	push	ebx
	push	edx
	push	si
	push	edi

; Set FS:DI to point to the memory base address of the HC
	call	OHCIBB_SetFS_DI

⌨️ 快捷键说明

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