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

📄 uhci_bb.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	mov	eax, dUHCIControlStatus
	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, si
	jbe	UBBT_PktSizeAdjusted		; Packet size is valid
	mov	ax, si
UBBT_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, dUHCIToken
	mov	(UHCI_TD PTR [di]).Token, eax

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

	xor	dUHCIToken, DATA_TOGGLE			; Toggle between DATA1/DATA0

; Position to next data TD
	add	di, SIZE UHCI_TD

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

; Position to the last TD
	sub	di, SIZE UHCI_TD

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

; Update the data toggle value into the mass info structure
	mov	cl, 1
	test	dUHCIToken, DATA_TOGGLE			; Toggle between DATA1/DATA0
	jnz	UBBT_UpdateToggle
	dec	cl	; CL = 0
UBBT_UpdateToggle:
; DL	Xfer direction
; CL	Data toggle value
	call	USBMBB_UpdateBulkDataSync

; Clear bulk stall condition flag
	mov	bLastBulkCommandStalled, FALSE

; Schedule the bulk TDs by adding them in the bulk queue head
	push	di
	mov	di, OFFSET QHControl

	mov	eax, OFFSET TDData
; Save the bulk data TD pointer
	add	eax, dGlobalDataArea
; 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
	call	UHCIBB_WaitForTransferComplete
; SI - HCStruc Ptr (returned from UHCIWaitForTransferComplete)

; Remove the bulk data TDs from the HC's schedule by pointing QHControl
; element pointer to TERMINATE.
	push	di
	mov	di, OFFSET QHControl
	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_CRC_TIMEOUT_ERROR OR UHCI_TD_NAK_RECEIVED OR \
			UHCI_TD_BABBLE_DETECTED OR UHCI_TD_DATA_BUFFER_ERROR)
	jnz	UBBT_ErrorExit		; Br if any error bits set in status

; Check for endpoint STALL condition
	test	(UHCI_TD PTR [di]).ControlStatus, UHCI_TD_STALLED
	jz	UBBT_NotStalled

; Bulk stall condition is checked and cleared elsewhere
	mov	bLastBulkCommandStalled, TRUE

	jmp	SHORT UBBT_ErrorExit

UBBT_NotStalled:

; Calculate amount of data transferred and return the value
	mov	di, OFFSET TDData
	xor	cx, cx
UBBT_NextTD:
	mov	eax, (UHCI_TD PTR [di]).ControlStatus
	and	ax, UHCI_TD_DATA_LENGTH	; AX = actual byte count - 1
	or	ax, ax			; Assume zero as zero!!!!
	jnz	UBBT_Cnt

; Check for short packet detect
	test	eax, UHCI_TD_SHORT_PACKET_DETECT
	jnz	UBBT_SizeOkay

UBBT_Cnt:
	inc	ax

	cmp	ax, (UHCI_TD_DATA_LENGTH+1)	; (07FFh + 1)
	jne	UBBT_SizeOkay
; Zero length. Set ax accordingly
	xor	ax, ax
UBBT_SizeOkay:

; Add to total size transferred
	add	cx, ax

	mov	ebx, (UHCI_TD PTR [di]).LinkPointer
	test	ebx, UHCI_TERMINATE
	jnz	UBBT_EndLoop
; Mask off low order bits
	and	bl, NOT UHCI_VERTICAL_FLAG
	sub	ebx, dGlobalDataArea		; Point to next TD
	mov	di, bx
	jmp	SHORT UBBT_NextTD

UBBT_EndLoop:
	push	cx
	pop	fs

UBBT_Success:
	or	sp, sp
	jmp	SHORT UBBT_Exit

UBBT_ErrorExit:
; Set the error flags
	cmp	sp, sp

UBBT_Exit:
	popad
	mov	ax, fs
	pop	fs
	ret
UHCIBB_BulkTransfer	ENDP

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

UHCIBB_InterruptTransfer	PROC NEAR PUBLIC

	push	eax
	push	ecx
	push	edx
	push	di

; Change Seg:Off in fpBuffer to 32 bit absolute address
	push	ds
	pop	ax
	shl	eax, 4
	movzx	edx, dx
	add	edx, eax

; Check for 0 length transfer (if so, exit)
	or	cx, cx
	je	UIT_Exit

	mov	di, OFFSET TDData
	mov	(UHCI_TD PTR [di]).ActiveFlag, FALSE

; Set the endpoint speed
	movzx	eax, CurrentDevice.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)
	mov	(UHCI_TD PTR [di]).ControlStatus, eax

; Set the buffer pointer
	mov	(UHCI_TD PTR [di]).BufferPointer, edx

	xor	edx, edx
; Now EDX is free form the device address in it
	mov	dl, CurrentDevice.bDeviceAddress
					; EDX[6:0] = Device address

; Form device address and endpoint in proper order and bit position
	movzx	eax, CurrentDevice.bIntEndpoint
; EAX[3:0] = Endpoint
	shl	eax, 7			; EAX[10:7] = Endpoint
	or	edx, eax
	shl	edx, 8			; EDX[18:8] = DevAddr & Endp

; Fill in various fields in the interrupt data TD
; Set length field
	mov	eax, ecx		;  wLength = data length
	dec	ax			; AX = packet data size - 1
	shl	eax, 21
	or	edx, eax		; EDX[18:8]=Dev. addr & endp

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

	mov	dl, IN_PACKET			; EAX[7:0] = IN PID

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

	xor	al, 1			; Toggle between DATA1/DATA0
	push	ax
; Update the data toggle value into the structure
	mov	cl, USB_INT_DATA_SYNC_SHIFT
; Reset toggle bit
	mov	al, 1
	shl	al, cl
	not	al
	and	CurrentDevice.bDataSync, al
	pop	ax		; AL - Updated data toggle
; Set toggle bit appropriately
	shl	al, cl
	or	CurrentDevice.bDataSync, al

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

; Schedule the interrupt TD
	push	di
	mov	di, OFFSET QHControl
	mov	eax, OFFSET TDData
; Save the bulk data TD pointer
	add	eax, dGlobalDataArea
	mov	(UHCI_QH PTR [di]).ElementPointer, eax
	pop	di

; Now wait for the interrupt data TD to complete.
	call	UHCIBB_WaitForTransferComplete

; Finally check for errors in the completed interrupt data TD
; If the TD did not complete successfully, return with error.
	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	UIT_ErrorExit		; Br if any error bits set in status

	or	sp, sp		; Clear zero flag
	jmp	SHORT UIT_Exit

UIT_ErrorExit:
	cmp	sp, sp		; Set zero flag

UIT_Exit:
	pop	di
	pop	edx
	pop	ecx
	pop	eax
	ret
UHCIBB_InterruptTransfer	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCIBB_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: 	Nothing
;
; Modified:	None
;
; Referrals:	UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCIBB_ProcessInterrupt		PROC NEAR SYSCALL PUBLIC

	push	eax
	push	dx
	push	edi

; Read the UHCI status register
	mov	dx, (MKF_USB_BB_IO_BASE + UHCI_STATUS_REG)
	in	ax, dx

; Check whether any USB transaction completion interrupt is generated
	test	al, UHC_USB_INTERRUPT
	jz	UBPI_NoTransCompInt	; No interrupt asserted

; Clear interrupt status in the host controller
	jcxz	SHORT $+2
	jcxz	SHORT $+2
	in	ax, dx
	jcxz	SHORT $+2
	jcxz	SHORT $+2
	out	dx, ax

	mov	di, OFFSET TDControlSetup
	call	UHCIBB_ParseAndProcessTD

	mov	di, OFFSET TDData
	call	UHCIBB_ParseAndProcessTD

IF	MKF_USB_BB_DEV_KBD
	mov	di, OFFSET TDKeyboard
	call	UHCIBB_ProcessTD
ENDIF	;; IF	MKF_USB_BB_DEV_KBD

UBPI_NoTransCompInt:

	pop	edi
	pop	dx
	pop	eax
	ret
UHCIBB_ProcessInterrupt		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCIBB_ActivateKeyboardPolling
;
; Description:	This function activates the polling TD for the USB keyboard 
;
; Input: 	None
;
; Output: 	ZR	On error
;		NZ	On successfull completion
;
; Modified:	Nothing
;
; Referrals:	UHCI_TD, DeviceInfo
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCIBB_ActivateKeyboardPolling		PROC NEAR PUBLIC

IF	MKF_USB_BB_DEV_KBD
	push	eax
	push	ebx
	push	dx
	push	di

	mov	di, OFFSET TDKeyboard
	mov	(UHCI_TD PTR [di]).ControlStatus, 0	; Inactive

; Save the pointer in DeviceInfo
	mov	CurrentDevice.pPollTDPtr, di

; Set the packet PID & packet length
	mov	eax, IN_PACKET OR ((DEFAULT_PACKET_LENGTH - 1) SHL 21)
					; Set PID=In, and MaxLen
	mov	(UHCI_TD PTR [di]).Token, eax

; Set the address and endpoint fields in the TD's token field
	movzx	eax, CurrentDevice.bEndPointNum
	shl	eax, 7			; EAX[10:7] = Endpoint number to poll
	or	al, CurrentDevice.bDeviceAddress
					; EAX[6:0] = Addr

	shl	eax, 8			; EAX[18:15]/[14:8] = Endp/Addr

	and	(UHCI_TD PTR [di]).Token, NOT (ENDPOINT OR DEVICE_ADDRESS)
	or	(UHCI_TD PTR [di]).Token, eax

	lea	ax, (UHCI_TD PTR [di]).DataArea
					; AX = Pointer to TD's data area
	movzx	eax, ax			; Clear upper half of EAX
	add	eax, dGlobalDataArea	; EAX = Absolute address of TD's buff
	mov	(UHCI_TD PTR [di]).BufferPointer, eax

	mov	(UHCI_TD PTR [di]).pCallback, OFFSET CS:UHCIBB_KeyboardPollingCallback

; Make the TD active and set the high/low speed flag in the TD's
; control status and CSReloadValue fields.

	movzx	eax, CurrentDevice.bEndPointSpeed
	; AL = 11/01/10 for HI/LO/FULL
	and	al, 1				; Mask off MSb
	shl	eax, 26
        or	eax, (UHCI_TD_ACTIVE OR UHCI_TD_INTERRUPT_ON_COMPLETE OR UHCI_TD_THREE_ERRORS)
	mov	(UHCI_TD PTR [di]).CSReloadValue, eax
	mov	(UHCI_TD PTR [di]).ActiveFlag, TRUE
	mov	(UHCI_TD PTR [di]).ControlStatus, eax

; Capture the HC IRQ to point to the common IRQ handler
	call	USBBB_CaptureHCInterrupt

; Program HC to enable USB interrupts

	mov	ah, SB_USB_REG_LEGSUP
	mov	dx, CurrentHC.wBusDevFuncNum
	call	read_pci_dword_FAR
	and	bx, 00CFh
; Enable PIRQD
	or	bx, 2000h	; For BootBlock or IRQ mode
	call	write_pci_dword_FAR

; Finally enable interrupts (SMIs) from the host controller.
	mov	dx, (MKF_USB_BB_IO_BASE + UHCI_INTERRUPT_ENABLE)
	mov	ax, (UHC_IOC_ENABLE OR UHC_TIMEOUT_CRC_ENABLE)
	out	dx, ax

	pop	di
	pop	dx
	pop	ebx
	pop	eax
ENDIF	;; IF	MKF_USB_BB_DEV_KBD
	or	sp, sp		; Clear zero flag
	ret
UHCIBB_ActivateKeyboardPolling		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCIBB_DeactivateKeyboardPolling
;
; Description:	This function de-activates the polling TD for the USB keyboard
;
; Input: 	None
;
; Output: 	ZR	On error
;		NZ	On successfull completion
;
; Modified:	Nothing
;
; Referrals:	UHCI_TD, DeviceInfo
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCIBB_DeactivateKeyboardPolling	PROC NEAR PUBLIC

IF	MKF_USB_BB_DEV_KBD
	push	di

; Get a pointer to the device's TD from the poll TD pointer
	mov	di, OFFSET TDKeyboard

; Set the TD to inactive and prevent the HC from processing it.
	mov	(UHCI_TD PTR [di]).ControlStatus, UHCI_TD_THREE_ERRORS
	mov	(UHCI_TD PTR [di]).CSReloadValue, UHCI_TD_THREE_ERRORS
	mov	(UHCI_TD PTR [di]).ActiveFlag, FALSE

; Remove the polling TD from the schedule
	mov	CurrentDevice.pPollTDPtr, 0

	pop	di
ENDIF	;; IF	MKF_USB_BB_DEV_KBD
	or	sp, sp		; Clear zero flag
	ret
UHCIBB_DeactivateKeyboardPolling	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCIBB_FillCntrlXferFields
;

⌨️ 快捷键说明

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