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

📄 ohci.asm

📁 <BIOS研发技术剖析>书的源代码,包括完整的BIOS汇编语言源程序.
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Next_TD, eax

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

; Fill in various fields in the TdControlData.
; The TD_Control field will be set so BUFFER_ROUNDING=1,
;   DIRECTION_PID=OUT_PACKET/IN_PACKET, DELAY_INTERRUPT=IntD,
;   DATA_TOGGLE=DATA1_TOGGLE, ERROR_COUNT=NO_ERRORS, CONDITION_CODE=NOT_ACCESSED
; The GTD_Current_Buffer_Pointer field will point to the caller's buffer
;   which is now in EBP.
; The GTD_Buffer_End field will point to the last byte of the caller's buffer.
; The GTD_Next_TD 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 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.

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

	mov	di, offset TdControlData ;DI = ptr of TdControlData

	mov	eax, BUFFER_ROUNDING or OUT_PACKET or DELAY_INTERRUPT or DATA1_TOGGLE or NO_ERRORS or (NOT_ACCESSED shl 28)
	test	dl, 80h
	jz	@f			;Br if host sending data to device (OUT)
	mov	eax, BUFFER_ROUNDING or IN_PACKET  or IntD or DATA1_TOGGLE or NO_ERRORS or (NOT_ACCESSED shl 28)
@@:	mov	(General_Transfer_Descriptor ptr [di]).GTD_Control, eax

	mov	(General_Transfer_Descriptor ptr [di]).GTD_Current_Buffer_Pointer, ebp

	movzx	eax, si 		;ESI = data length
	cmp	ax, size DeviceRequestDataBuf
	jbe	@f			;Br if processedn data <= buffer size
	mov	ax, size DeviceRequestDataBuf
@@:	add	ebp, eax		;Update the buffer pointer
	dec	ebp
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Buffer_End, ebp

	mov	eax, HcdDataArea	;EAX = seg containing TDs
	add	eax, offset TdControlStatus ;EAX = abs addr of TdControlStatus
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Next_TD, eax

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

DevReqSkipDataTd:

; Fill in various fields in the TdControlStatus.
; The TD_Control field will be set so BUFFER_ROUNDING=1,
;   DIRECTION_PID=IN_PACKET/OUT_PACKET, DELAY_INTERRUPT=IntD,
;   DATA_TOGGLE=DATA1_TOGGLE, ERROR_COUNT=NO_ERRORS, CONDITION_CODE=NOT_ACCESSED
; The GTD_Current_Buffer_Pointer field will point to NULL
; The GTD_Buffer_End field will point to NULL.
; The GTD_Next_TD field will point to TERMINATE.
; 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.
; The DeviceAddress field does not need to be set since the Control TDs do
;   not need rebinding to the EdControl.

	mov	di, offset TdControlStatus ;DI = ptr to TdControlStatus

	mov	eax, BUFFER_ROUNDING or IN_PACKET or IntD or DATA1_TOGGLE or NO_ERRORS or (NOT_ACCESSED shl 28)
	test	dl, 80h
	jz	@f			;Br if host sending data to device (OUT)
	mov	eax, BUFFER_ROUNDING or OUT_PACKET  or IntD or DATA1_TOGGLE or NO_ERRORS or (NOT_ACCESSED shl 28)
@@:	mov	(General_Transfer_Descriptor ptr [di]).GTD_Control, eax

	xor	eax, eax
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Current_Buffer_Pointer, eax
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Buffer_End, eax
	mov	(General_Transfer_Descriptor ptr [di]).GTD_Next_TD, eax
	mov	(General_Transfer_Descriptor ptr [di]).CSReloadValue, eax

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

; Now complete the Control queue, so set SKIP_TDQ=0

	mov	di, offset EdControl
	and	(Endpoint_Descriptor ptr [di]).ED_Control,not SKIP_TDQ

; Set the HcControlHeadED register to point to the EdControl.

	mov	eax, offset EdControl
	add	eax, HcdDataArea
	mov	dx, OHCI_CONTROL_HEAD_ED
	call	WriteUsbOperRegDword

; Now put the TdControlSetup, TdControlData, and TdControlStatus 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.

	mov	eax, CONTROL_LIST_FILLED
	mov	dx, OHCI_COMMAND_STATUS
	call	WriteUsbOperRegDword

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

;	mov	bx, 20000d		;Repeat this loop this number of times
					; before giving up (~50us per iteration)
	mov	bx, 2500
WaitForComplete:
	mov	dx, OHCI_INTERRUPT_STATUS
	call	ReadUsbOperRegDword	;AX = value from status register
	test	eax, WRITEBACK_DONEHEAD
	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	TdControlSetup.ActiveFlag, FALSE
	jne	DevReqNotComplete		;Br if TdControlSetup not completed
	cmp	TdControlData.ActiveFlag, FALSE
	jne	DevReqNotComplete		;Br if TdControlData not completed
	cmp	TdControlStatus.ActiveFlag, FALSE
	je	DevReqComplete			;Br if TdControlStatus completed

DevReqNotComplete:
;; for port 1 cannot work
	mov	cx, 3
;	mov	cx, 96*2
	call	pm_fixed_delay		;Delay 45us

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

	or	(General_Transfer_Descriptor ptr [di]).GTD_Control, (DEVICE_NOT_RESPOND shl 28)

DevReqComplete:

; Stop the HC from processing the EdControl by setting its Skip bit.

	mov	di, offset EdControl
	or	(Endpoint_Descriptor ptr [di]).ED_Control, SKIP_TDQ

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

	mov	eax, TdControlStatus.GTD_Control
	shr	eax, 28			;AL[3:0] = Completion status
	or	al, al
	clc				;Indicate success
	jz	DeviceRequestDone	;Br if no error bits are set

	;----------------------------------------------------------------------
	; Patch for Compaq OHCI HC which reports DataUnderrun error on any
	; short packet (even if buffer rounding is enabled).
	ifdef HC_PATCH_COMPAQ_OHCI
	cmp	al, DATA_UNDERRUN
	clc				;Indicate success
	je	DeviceRequestDone	;Br if DataUnderrun error
	endif
	;----------------------------------------------------------------------

	stc				;Indicate error

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	eax
	push	dx

	shl 	ah, 2			;AH = 4/8 for port 1/2
	mov 	dx, OHCI_RH_PORT1_STATUS - 4
	add 	dl, ah			;DX = Port 1/2 control reg
	call	ReadUsbOperRegDword	;EAX = value from port control reg

	xor 	bl, bl			;Init the output values

	test	al, CURRENT_CONNECT_STATUS
	jz  	@f			;Br if no device present
	or  	bl, 00000001b		;Set connect status bit
@@:
	test	ax, LOW_SPEED_DEVICE_ATTACHED
	jz  	@f			;Br if high speed device
	or  	bl, 00000010b		;Set low speed bit
@@:
	test	eax, CONNECT_STATUS_CHANGE
	jz  	@f			;Br if no change in connect status
	or  	bl, 00000100b		;Set connect status change bit
@@:
	pop 	dx
	pop 	eax
	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
	pushad

	shl 	ah, 2			;AH = 4/8 for port 1/2
	mov 	dx, OHCI_RH_PORT1_STATUS - 4
	add 	dl, ah			;DX = Port 1/2 control reg

	mov  	eax, SET_PORT_ENABLE
	call	WriteUsbOperRegDword	;Enable the port

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

	mov	eax, SET_PORT_RESET	;Make reset signaling active
	call	WriteUsbOperRegDword

EnablePortWaitForReset:
	call	ReadUsbOperRegDword
	test	eax, PORT_RESET_STATUS
	jnz	EnablePortWaitForReset	;Br if reset still active

	mov	eax, PORT_RESET_STATUS_CHANGE
	call	WriteUsbOperRegDword	;Clear reset status change bit

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

ifdef HC_PATCH_NAT_OHCI
	mov  	eax, SET_PORT_ENABLE
	call	WriteUsbOperRegDword	;Enable the port
endif

	popad
	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, 2			;AH = 4/8 for port 1/2
	mov 	dx, OHCI_RH_PORT1_STATUS - 4
	add 	dl, ah			;DX = Port 1/2 control reg
	call	ReadUsbOperRegDword	;AX = value from port control reg
	or 	eax, CLEAR_PORT_ENABLE	;Clear enable bit
	call	WriteUsbOperRegDword

	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

⌨️ 快捷键说明

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