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

📄 uhci.asm

📁 AMI 主板的BIOS源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the ControlTdCallback routine.
; The ActiveFlag field will be set to TRUE.

	or	si, si
	jz	DevReqSkipDataTds	;Br if no data transfer (data length=0)

	cmp	si, MAX_CONTROL_DATA_SIZE
	jb	@f			;Br if not more data than we can handle
	mov	si, MAX_CONTROL_DATA_SIZE ;Limit to amount of data that we can handle
@@:
	mov	di, offset TdControlData ;DI = ptr of TdControlData
	mov	dh, 1			;Start with a data 1 token

DevReqNextDataTd:
	movzx	eax, di
	add	eax, size Transfer_Descriptor
	add	eax, HcdDataArea
	mov	(Transfer_Descriptor ptr [di]).TD_Link_Pointer, eax

	movzx	eax, (DeviceTableEntry ptr [bx]).LowSpeedFlag ;AL = 0/1 for hi/lo
	shl	eax, 26
	or	eax, INTERRUPT_ON_COMPLETE or THREE_ERRORS or ACTIVE
	mov	(Transfer_Descriptor ptr [di]).TD_Control_Status, eax

	mov	(Transfer_Descriptor ptr [di]).TD_Buffer_Pointer, ebp

	movzx	eax, si			;ESI = data length
	cmp	ax, (DeviceTableEntry ptr [bx]).Endp0MaxPacket
	jbe	@f			;Br if remaining data <= max packet size
	mov	ax, (DeviceTableEntry ptr [bx]).Endp0MaxPacket
@@:	sub	si, ax			;Subtract packet size from overall data length
	add	ebp, eax		;Update the buffer pointer
	dec	ax			;AX = packet data size - 1
	shl	eax, 21

	or	eax, ecx		;EAX[18:8] = Device address / endpoint
	mov	al, OUT_PACKET		;EAX[7:0] = OUT PID
	test	dl, 80h
	jz	@f			;Br if host sending data to device (OUT)
	mov	al, IN_PACKET		;EAX[7:0] = IN PID
@@:
	test	dh, 1
	jz	@f			;Br if this packet is a data 0 token
	or	eax, DATA_TOGGLE	;Make packet into a data 1
@@:
	mov	(Transfer_Descriptor ptr [di]).TD_Token, eax

	mov	(Transfer_Descriptor ptr [di]).CSReloadValue, 0
	mov	(Transfer_Descriptor ptr [di]).pCallback, offset cgroup:ControlTdCallback
	add	(Transfer_Descriptor ptr [di]).pCallback, orgbase
	mov	(Transfer_Descriptor ptr [di]).ActiveFlag, TRUE

	add	di, size Transfer_Descriptor ;Point to next data TD
	xor	dh, 1			;Toggle between data 1 / data 0
	or	si, si
	jnz	DevReqNextDataTd	;Br if more data TDs must be built

	sub	di, size Transfer_Descriptor ;Point to last data TD
	mov	eax, HcdDataArea	;EAX = seg containing TDs
	add	eax, offset TdControlStatus ;EAX = abs addr of TdControlStatus
	mov	(Transfer_Descriptor ptr [di]).TD_Link_Pointer, eax

DevReqSkipDataTds:

; Fill in various fields in the TdControlStatus.
; The TD_Link_Pointer field will point to TERMINATE.
; The TD_Control_Status field will be set to active and interrupt on complete.
; The TD_Token field will contain the packet size (0), the device address,
;   endpoint, and a setup PID with opposite data direction as that defined
;   in the request type (DL).
; The TD_Buffer_Pointer field will point to the TD's DataArea buffer even
;   though we are not expecting any data transfer.
; The CSReloadValue field will contain 0 because this is a "one shot" packet.
; The pCallback will be set to point to the ControlTdCallback routine.
; The ActiveFlag field will be set to TRUE.

	mov	di, offset TdControlStatus ;DI = ptr to TdControlStatus

	mov	(Transfer_Descriptor ptr [di]).TD_Link_Pointer, TERMINATE

	movzx	eax, (DeviceTableEntry ptr [bx]).LowSpeedFlag ;AL = 0/1 for hi/lo
	shl	eax, 26
	or	eax, INTERRUPT_ON_COMPLETE or THREE_ERRORS or ACTIVE
	mov	(Transfer_Descriptor ptr [di]).TD_Control_Status, eax

	mov	eax, ecx		;EAX[18:8] = Device address / endpoint
	mov	al, OUT_PACKET		;EAX[7:0] = OUT PID
	test	dl, 80h
	jnz	@f			;Br if device sending data to host (IN)
	mov	al, IN_PACKET		;EAX[7:0] = IN PID
@@:	or	eax, DATA_TOGGLE or (7FFh shl 21) ;Make packet into a data 1 and length 0
	mov	(Transfer_Descriptor ptr [di]).TD_Token, eax

	lea	ax, (Transfer_Descriptor ptr [di]).DataArea ;AX = ptr to TD's data buffer
	movzx	eax, ax			;Clear upper half of EAX
	add	eax, HcdDataArea	;EAX = abs addr of TD's data buffer
	mov	(Transfer_Descriptor ptr [di]).TD_Buffer_Pointer, eax

	mov	(Transfer_Descriptor ptr [di]).CSReloadValue, 0
	mov	(Transfer_Descriptor ptr [di]).pCallback, offset cgroup:ControlTdCallback
	add	(Transfer_Descriptor ptr [di]).pCallback, orgbase
	mov	(Transfer_Descriptor ptr [di]).ActiveFlag, TRUE

; Now put the TdControlSetup, TdControlData TDs, and TdControlStatus into the
; HC's schedule by pointing QhControl's link pointer to TdControlSetup.
; This will cause the HC to execute the transaction in the next active frame.

	mov	di, offset QhControl
	mov	eax, HcdDataArea	   ;EAX = seg containing TDs
	add	eax, offset TdControlSetup ;EAX = abs addr of TdControlSetup
	mov	(Q_Head ptr [di]).Q_Element_Link_Pointer, eax

; Now wait for the TdControlStatus to complete.  When it has completed,
; the ControlTdCallback will its active flag to FALSE.

	mov	di, offset TdControlStatus ;DI = ptr of TdControlStatus
	mov	bx, 20000d		;Repeat this loop this number of times
					; before giving up (~50us per iteration)
WaitForComplete:
	mov	dx, USB_STATUS_REG
	call	ReadUsbIoRegWord	;AX = value from status register
	test	al, USB_INTERRUPT
	jz	@f			;Br if HC is not asserting IRQ

ifdef DOS_DEBUG
	pushf				;Simulate IRQ from the HC
	push	cs
	cli
endif
	call	UsbHcIsr
@@:
	cmp	(Transfer_Descriptor ptr [di]).ActiveFlag, FALSE
	je	DevReqComplete		;Br if TdControlStatus completed

	mov	cx, 3
	call	pm_fixed_delay		;Delay 45us

	dec	bx			;Dec timeout counter
	jnz	WaitForComplete		;Br if not time to give up yet

	or	(Transfer_Descriptor ptr [di]).TD_Control_Status, CRC_TIMEOUT_ERROR

DevReqComplete:

; Remove the TdControlSetup, TdControlData TDs, and TdControlStatus from the
; HC's schedule by pointing QhControl's link pointer to TERMINATE.

	mov	di, offset QhControl
	mov	(Q_Head ptr [di]).Q_Element_Link_Pointer, TERMINATE

; Finally check for any error bits set in both the TdControlStatus.
; If the TD did not complete successfully, return STC.

	test	TdControlStatus.TD_Control_Status, BITSTUFF_ERROR or CRC_TIMEOUT_ERROR or NAK_RECEIVED or BABBLE_DETECTED or DATA_BUFFER_ERROR or STALLED
	stc				;Indicate error
	jnz	DeviceRequestDone	;Br if any error bits set in status
	clc				;Indicate success

DeviceRequestDone:
	popad
	ret
UsbDeviceRequest	endp


;---------------------------------------;
; UsbGetRootHubPortStatus               ;
;---------------------------------------;--------------------------------------;
; This function returns the status of one port on the root hub.                ;
;                                                                              ;
; Input:  AH = Port number within hub                                          ;
;                                                                              ;
; Output: BL = Port status flags                                               ;
;              Bit 0: Connect status                                           ;
;                      0 = No device is connected to port                      ;
;                      1 = A device is connected to port                       ;
;              Bit 1: Device speed                                             ;
;                      0 = Full speed device attached                          ;
;                      1 = Low speed device attached                           ;
;              Bit 2: Connect status change                                    ;
;                      0 = Connect status has not changed                      ;
;                      1 = Device has been attached/removed                    ;
;              Bit 3-7: Reserved                                               ;
;         CF = Clear if the hub port's status was determined successfully      ;
;              Set if the hub port's status cannot be determined               ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
UsbGetRootHubPortStatus	proc near
	push	ax
	push	dx

	shl	ah, 1			;AH = 2/4 for port 1/2
	mov	dx, USB_PORT1_CONTROL - 2
	add	dl, ah			;DX = Port 1/2 control reg
	call	ReadUsbIoRegWord	;AX = value from port control reg

	xor	bl, bl			;Init the output values

	test	al, CONNECT_STATUS
	jz	@f			;Br if no device present
	or	bl, 00000001b		;Set connect status bit
@@:
	test	ax, LOW_SPEED_ATTACHED
	jz	@f			;Br if high speed device
	or	bl, 00000010b		;Set low speed bit
@@:
	test	ax, CONNECT_STATUS_CHANGE
	jz	@f			;Br if connect status not changed
	or	bl, 00000100b		;Set connect status change bit
@@:
	pop	dx
	pop	ax
	clc
	ret
UsbGetRootHubPortStatus	endp


;---------------------------------------;
; UsbEnableRootHubPort                  ;
;---------------------------------------;--------------------------------------;
; This function powers, resets, and enables one port on the root hub.          ;
;                                                                              ;
; Input: AH = Port number within hub                                           ;
;                                                                              ;
; Output: CF = Clear if the hub port was enabled successfully                  ;
;              Set if the hub port was not enabled                             ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
UsbEnableRootHubPort	proc near
	pusha

	shl	ah, 1			;AH = 2/4 for port 1/2
	mov	dx, USB_PORT1_CONTROL - 2
	add	dl, ah			;DX = Port 1/2 control reg
	call	ReadUsbIoRegWord	;AX = value from port control reg
	or	ax, PORT_ENABLE or PORT_RESET ;Set enable and reset bits
	call	WriteUsbIoRegWord

	mov	cx, 029Ah		;10ms / 15us
	call	pm_fixed_delay		;Delay 10ms

	call	ReadUsbIoRegWord	;AX = value from port control reg
	and	ax, not PORT_RESET	;Clear reset bit
	or	ax, PORT_ENABLE		;Set enable bit
	call	WriteUsbIoRegWord

	mov	cx, (1 * 1000) / 15	;1ms / 15us
	call	pm_fixed_delay		;Delay 10ms

	call	ReadUsbIoRegWord	;AX = value from port control reg
	or	ax, PORT_ENABLE		;Set enable bit
	call	WriteUsbIoRegWord

	mov	cx, (100 * 1000) / 15	;100ms / 15us
	call	pm_fixed_delay		;Delay 100ms

	popa
	clc
	ret
UsbEnableRootHubPort	endp


;---------------------------------------;
; UsbDisableRootHubPort                 ;
;---------------------------------------;--------------------------------------;
; This function disables one port on a USB hub or the root hub.                ;
;                                                                              ;
; Input: AH = Port number within hub                                           ;
;                                                                              ;
; Output: CF = Clear if the hub port was disabled successfully                 ;
;              Set if the hub port was not disabled                            ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
UsbDisableRootHubPort	proc near
	pusha

	shl	ah, 1			;AH = 2/4 for port 1/2
	mov	dx, USB_PORT1_CONTROL - 2
	add	dl, ah			;DX = Port 1/2 control reg
	call	ReadUsbIoRegWord	;AX = value from port control reg
	and	ax, not PORT_ENABLE	;Clear enable bit
	call	WriteUsbIoRegWord

	popa
	clc
	ret
UsbDisableRootHubPort	endp


;---------------------------------------;
; UsbHcCheckActive                      ;
;---------------------------------------;--------------------------------------;
; This function returns a flag indicating if the USB host controller is        ;
; currently active and under BIOS control.                                     ;
;                                                                              ;
; Input: Nothing (even DS and ES are undefined)                                ;
;                                                                              ;
; Output: CL = Flags                                                           ;
;                Bit[7:4] = Reserved                                           ;
;                Bit[3:1] = Number of ports on root hub of host controller     ;
;                Bit[0]   = 1 if USB BIOS is running host controller           ;
;                           0 if USB BIOS is not running host controller       ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
UsbHcCheckActive	proc near
	pushad

	call	GetUsbHcBusDevFunc	;Returns BX = b/d/f, destroys AX,ECX,EDX

	call	UsbHcChipsetGetStatus	;Returns CL[4:0] = USB & 60/64 r/w trap flags
	test	cl, 00010000b		;Bit 4 enables SMI on HC IRQ if set
	jz	CheckActiveNo		;Br if HC int not routed to SMI

	mov	di, USB_BASE_ADDRESS
	mov	si, PCI_REG_ADDRESS_WORD
	call	smi_pci_read_cfg	;Returns CX = I/O base of HC
	and	cl, 0FCh		;Mask out 2 reserved bits

⌨️ 快捷键说明

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