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

📄 uhci.asm

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

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

; Bulk stall condition is checked and cleared elsewhere
	or	bLastCommandStatus, USB_BULK_STALLED

	jmp	SHORT UBTS_ErrorExit

UBTS_NotStalled:
; Calculate amount of data transferred and return the value
	mov	di, pBulkDataTD
UBTS_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	UBTS_Cnt

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

UBTS_Cnt:
	inc	ax

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

; Add to total size transferred
	add	wRetStatus, ax

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

UBTS_EndLoop:
UBTS_ErrorExit:

; Free bulk data TDs
	mov	ax, pBulkDataTD
	call	UHCI_FreeTD

UBTS_Exit:
	mov	ax, wRetStatus
	ret
UHCI_BulkTransfer	ENDP

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

UHCI_InterruptTransfer	PROC NEAR SYSCALL PUBLIC

	push	bx
	push	ecx
	push	edx
	push	si
	push	di
	push	fs

; Set return status as failure
	xor	eax, eax
	mov	fs, ax		; Return status

; 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	bx, (HCStruc PTR [di]).pDescriptorPtr
; Init Active flag in the interrupt data TD to FALSE
	mov	bx, (UHCIDescriptors PTR [bx]).TDInterruptData
	mov	(UHCI_TD PTR [bx]).ActiveFlag, FALSE

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

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

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

	mov	di, (DeviceInfo PTR [si]).pMassInfoPtr
; Form device address and endpoint in proper order and bit position
	movzx	eax, (DeviceInfo PTR [si]).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

	push	si
	cmp	(MassDeviceInfo PTR [di]).pLUN0DevInfoPtr, 0
	je	UIT_ToggleBitDone
	mov	si, (MassDeviceInfo PTR [di]).pLUN0DevInfoPtr
UIT_ToggleBitDone:
	mov	al, (DeviceInfo PTR [si]).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 [bx]).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	(DeviceInfo PTR [si]).bDataSync, al
	pop	ax		; AL - Updated data toggle
; Set toggle bit appropriately
	shl	al, cl
	or	(DeviceInfo PTR [si]).bDataSync, al
	pop	si

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


; Activate the TDInterruptData TD
	or	(UHCI_TD PTR [bx]).ControlStatus, UHCI_TD_ACTIVE

	mov	di, bx		; TD pointer
	mov	bx, si		; DeviceInfo pointer
; Now wait for the interrupt data TD to complete.
; BX - DeviceInfo Ptr, DI - TD to wait on
	call	UHCIWaitForTransferComplete
; SI - HCStruc Ptr (returned from UHCIWaitForTransferComplete)

; 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_Exit		; Br if any error bits set in status

	xor	ax, ax
	dec	ax
	mov	fs, ax

UIT_Exit:
	mov	ax, fs

	pop	fs
	pop	di
	pop	si
	pop	edx
	pop	ecx
	pop	bx
	ret
UHCI_InterruptTransfer	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCI_ProcessTDCompletion
;
; Description:	This function is called to process the TD completion
;
; Input: 	SI	Pointer to HCStruc
;
; Output: 	ZR	Interrupt not processed
;		NZ	Interrupt is processed
;
; Modified:	AX
;
; Referrals:	UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCI_ProcessTDCompletion	PROC NEAR SYSCALL PUBLIC USES BX DX EDI

	mov	dx, WORD PTR (HCStruc PTR [si]).dBaseAddress
; Read the UHCI status register
	add	dx, UHCI_STATUS_REG
	in	ax, dx

; Check whether any USB transaction completion interrupt is generated
	test	al, UHC_USB_INTERRUPT
	jz	UPTC_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

; Transaction completion interrupt occurred. Check the status completion.
	mov	bx, (HCStruc PTR [si]).pDescriptorPtr

	xor	ax, ax		; Device Info pointer = 0

; Check whether TDControlSetup is completed
; SI	HCStruc pointer
; AX	Device Info pointer
	mov	di, (UHCIDescriptors PTR [bx]).TDControlSetup
	call	UHCIParseAndProcessTD

; Check whether TDRepeat is completed
; SI	HCStruc pointer
; AX	Device Info pointer
	mov	di, (UHCIDescriptors PTR [bx]).TDRepeat
	call	UHCI_ProcessTD

; Check whether TDRootHub is completed
; SI	HCStruc pointer
; AX	Device Info pointer
	mov	di, (UHCIDescriptors PTR [bx]).TDRootHub
	call	UHCI_ProcessTD

; Check whether TDBulkData is completed
; SI	HCStruc pointer
; AX	Device Info pointer
	mov	di, (UHCIDescriptors PTR [bx]).TDBulkData
	call	UHCIParseAndProcessTD

; Check whether TDInterruptData is completed
; SI	HCStruc pointer
; AX	Device Info pointer
	mov	di, (UHCIDescriptors PTR [bx]).TDInterruptData
	call	UHCI_ProcessTD

; Check whether any polling TD has completed from its DeviceInfo structure
	mov	bx, OFFSET DeviceInfoTable	;BX - DeviceInfoTable[0]
UPTC_NextEntry:
	test	(DeviceInfo PTR [bx]).bFlag, DEV_INFO_DEV_PRESENT
	jz	UPTC_SkipEntry		;Br if this DeviceTableEntry is not in use

	cmp	(DeviceInfo PTR [bx]).pHCStrucPtr, si
	jne	UPTC_SkipEntry		;Br if matching entry found

; Structure found. Process the TD
; SI	HCStruc pointer
; BX	Device Info pointer
	mov	ax, bx
	mov	di, (DeviceInfo PTR [bx]).pPollTDPtr
	call	UHCI_ProcessTD

UPTC_SkipEntry:
	add	bx, SIZE DeviceInfo
	cmp	bx, OFFSET DeviceInfoTableEnd
	jb	UPTC_NextEntry		;Br if more entries to check

; Clear the zero flag
	or	sp, sp
UPTC_NoTransCompInt:
	ret
UHCI_ProcessTDCompletion	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	UHCI_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: 	SI	Pointer to HCStruc
;
; Output: 	AX	0 	Interrupt not processed
;			FFFFh 	Interrupt processed
;
; Modified:	AX
;
; Referrals:	UHCI_TD
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

UHCI_ProcessInterrupt	PROC NEAR SYSCALL PUBLIC USES BX ECX DX SI EDI

        LOCAL   wIntProcessFlag:WORD, wIOPort:WORD, bTemp:BYTE

; Set as interrupt not processed
	mov	wIntProcessFlag, 0

	mov	dx, WORD PTR (HCStruc PTR [si]).dBaseAddress
	mov	wIOPort, dx

; Check whether the controller is still under BIOS control
; Read the frame list base address and compare with stored value
	push	dx
	add	dx, UHCI_FRAME_LIST_BASE
	in	eax, dx
	pop	dx
	and	eax, (NOT 0FFFh)
	cmp	eax, (HCStruc PTR [si]).dHcdDataArea
	jne	UPI_NoTransCompInt	; Control is not with BIOS

IF	(MKF_USB_MODE EQ 2)

; Check port 60h/64h trapping SMI
IF	(MKF_USB_KBC_EMULATION)
	push	dx

	test	dUSBInitFlag, USB_PORT_TRAPPING_BIT
	jz	UPI_NoTrapSet

	mov	dx, (HCStruc PTR [si]).wBusDevFuncNum
	mov	ah, PCI_REG_LEGACY_SUPPORT
	call	read_pci_dword_far
	mov	wTrapSet, bx		; Used later


	mov	al, TRAP_REQUEST_DISABLE
	call	USB_ProcessTrapRequest


	mov	ax, bx
	and	al, 0Fh		; Mask off unwanted bits
	and	al, ah
	jz	UPI_NoTrapSet

; DX	Bus, device, function number of the UHCI controller
; AL	Trap status
	call	USBKBDHandlePortTrapping
	mov	wTrapSet, bx		; Used later
	
UPI_NoTrapSet:
	pop	dx
ENDIF

; Check re-init flag and initialize HC if needed (only for SMI mode)
	cmp	bReInitUSB, TRUE
	jne	UPI_SkipReInit

; Check if configure flag set.
        push    dx
	add	dx, UHCI_COMMAND_REG
	in	ax,dx
        pop     dx
        jmp     $+2
        jmp     $+2
	test	ax, UHC_CONFIGURE_FLAG
	jnz	UPI_SkipReInit                  ; Jump if already set

; Clear re-init flag
	mov	bReInitUSB, FALSE

; Disconnect devices from the ports
	push	dx
	mov	dh, (HCStruc PTR [si]).bHCNumber
	or	dh, BIT7		; Indicate as root hub
	mov	dl, 1

; Disconnect device from Port1
; DH	Hub/HC number
; DL	Port number
; SI	HCStruc pointer
        call	USBDisconnectDevice

; Disconnect device from Port2
	inc	dl
        call	USBDisconnectDevice
	pop	dx

; Reinit the USB HC
; SI	HCStruc pointer
; EDI	Data area address
; ECX	Data area size
	mov	edi, (HCStruc PTR [si]).dHcdDataArea
	mov	ecx, UHCI_DATA_AREA_SIZE
	call	UHCI_Start
        jmp     UPI_NoTransCompInt

UPI_SkipReInit:
ENDIF

	call	UHCI_ProcessTDCompletion
	jz	UPI_NoTransCompInt

; Set as interrupt processed
	mov	wIntProcessFlag, 0FFFFh

UPI_NoTransCompInt:

; Check re-init flag and initialize HC if needed (only for SMI mode)
IF	(MKF_USB_MODE EQ 2)

; Check port 60h/64h trapping SMI
IF	(MKF_USB_KBC_EMULATION)
	push	dx

	test	dUSBInitFlag, USB_PORT_TRAPPING_BIT
	jz	UPI_NoTrapSet0

	mov	al, TRAP_REQUEST_CLEA

⌨️ 快捷键说明

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