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

📄 usb.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 5 页
字号:
; DH - Sub class
; DL - Protocol
	call	(USB_DEV_HDR PTR cs:[si]).pChkDevType
	cmp	al, 0FFh
	je	UIACD_TryNextDriver

; Set the device type in the device info structure
	mov	(DeviceInfo PTR [bx]).bDeviceType, al

; Device identified. Issue common configure call
; Call a common routine to handle the remaining initialization that is done
; for all devices.
; BX - DeviceInfo, DI - Descriptor pointer, CX - End offset of desc ptr
	call	USB_ConfigureDevice
	jz	UIACD_DriverInitDone	; Error in configuring the device
; Updated new device info in the BX

	mov	wRetValue, bx
; Issue device specific initialization
; BX - DeviceInfo, DI - Descriptor pointer, CX - End offset of desc ptr
	call	(USB_DEV_HDR PTR cs:[si]).pCfgDevice
; On error reset the temporary device info structure indicating the
; device is not configured correctly
	jnz	UIACD_DriverInitDone

	mov	(DeviceInfo PTR [bx]).bDeviceType, 0

	jmp	SHORT UIACD_DriverInitDone

UIACD_TryNextDriver:
	pop	si
	add	si, 2
	jmp	SHORT UIACD_CheckNextDriver

UIACD_DriverInitDone:
	pop	si

UIACD_Exit:
	mov	ax, wRetValue
	ret
USBIdentifyAndConfigureDevice	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USB_DetectNewDevice
;
; Description:	This function is called when a new device is plugged
;		into a port on a hub. The hub may be a normal USB hub
;		or the root hub.
;
; Input: 	DH	USB device address of the hub whose status
;				has changed
;				bit 7	: 1 - Root hub, 0 for other hubs
;				bit 6-0	: Device address of the hub
;		DL	Port number
;		AL	Port status flags (See USB_PORT_STAT_XX equ)
;		SI	HCStruc of the host controller
;
; Output: 	AX	Pointer to the DevInfo structure for the newly
;			added device
;
; Modified:	AX
;
; Referrals:	DeviceInfo, HCStruc
;		DeviceDescriptor, ConfigDescriptor, InterfaceDescriptor
;		USB_GetDescriptor, USBEnableHubPort, USBDisableHubPort
;
; Notes:	This function does the following:
;		    1. Set the DeviceInfo entry for device 0 to be
;		       the same speed as the new device
;		    2. Find a free entry in the DeviceInfo (the position
;		       in the DeviceInfo array is the same as the new
;		       device address for the device)
;		    3. Enable the port on the hub
;		    4. Send a GetDescriptor (Device Descriptor) command
;		       to the device using an assumed MaxPacket size
;		       of 128 bytes, and make note of the actual MaxPacket
;		       size returned in the descriptor data
;		    5. Reset the hub port to handle any noncompliant devices
;		    6. Send a SetAddress command to the device to set it
;		       to its new address
;		    7. Send a GetDescriptor command to the device to get
;		       its Device descriptor
;		    8. Use GetConfiguration commands to search for
;		       a configuration that includes an interface type
;		       that the BIOS can use (keyboard, mouse, or hub)
;		    9. Use the data returned in the Device descriptor to
;		       fill in the DeviceInfo entry
;		   10. Configure the device using SetConfiguration,
;		       SetInterface, and
;		   11. SetProtocol commands
;		   12. Call device specific initializer to start polling
;		   13. Done
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USB_DetectNewDevice	PROC NEAR SYSCALL PUBLIC USES BX CX DX SI DI

	LOCAL	wDescLength:WORD, pBuffer:NEAR, wConfigLevel:WORD

; First set the speed of entry 0 in the DeviceInfo to run at the same speed
; as the new device.  This is necessary because we will initially communicate
; with the device at address 0 before assigning it a unique device address.

	mov	di, OFFSET DeviceInfoTable	; DI - DeviceInfo[0]

	mov	(DeviceInfo PTR [di]).bFlag, DEV_INFO_VALID_STRUC
	mov	(DeviceInfo PTR [di]).bDeviceAddress, 0
	mov	(DeviceInfo PTR [di]).wEndp0MaxPacket, 40h
	mov	(DeviceInfo PTR [di]).bDeviceType, 00h
	mov	(DeviceInfo PTR [di]).wIncompatFlags, 0

; Fill the speed of the device
	and	al, USB_PORT_STAT_DEV_SPEED_MASK
	shr	al, USB_PORT_STAT_DEV_SPEED_MASK_SHIFT
	mov	(DeviceInfo PTR [di]).bEndpointSpeed, al

; Fill hub address byte
	mov	(DeviceInfo PTR [di]).bHubDeviceNumber, dh

; Fill port number in the hub
	mov	(DeviceInfo PTR [di]).bHubPortNumber, dl

	mov	(DeviceInfo PTR [di]).pHCStrucPtr, si

; Next enable the port on the hub where the device is connected.
	test	dh, BIT7
	jz	UDND_SkipPortEnable

; DH	Hub/HC number
; DL	Port number
; SI	HCStruc pointer
	call	USBEnableHubPort

UDND_SkipPortEnable:

; Set BX to DeviceInfo pointer
	mov	bx, di

; Set config level
	mov	wConfigLevel, USB_ERR_DEV_INIT_MEM_ALLOC

; Allocate a block of memory for device request buffer
	mov	pBuffer, 0
	mov	al, (MAX_CONTROL_DATA_SIZE / USB_MEM_BLK_SIZE) 
	call	USBMem_Alloc
	jz	UDND_Error

; Save the pBuffer value in the Control Transfer temp area in the
; device info structure
	mov	WORD PTR (DeviceInfo PTR [bx]).CntrlXfer.fpBuffer, ax
	mov	pBuffer, ax
	mov	di, ax

; Set config level
	mov	wConfigLevel, USB_ERR_DEV_INIT_GET_DESC_8

; Next send a GetDescriptor command to the device to get its Device
; Descriptor. Assume a MaxPacket size of 64 bytes (the device will use 8,
; 16, 32, or 64). Regardless of the packet size used by te device we can
; always get the real MaxPacket size that the device is using, because
; this piece of information is at offset 7 in the device descriptor.

	mov	cx, 8
	mov	(DeviceInfo PTR [bx]).CntrlXfer.wValue, (DESC_TYPE_DEVICE SHL 8)
; SI - HCStruc, BX - pDevInfo, CX - Length
	call	USB_GetDescriptor
	jz	UDND_Error

; Set config level
	mov	wConfigLevel, USB_ERR_DEV_INIT_SET_ADDR

; Get and store the endpoint 0 max packet size
	movzx	ax, (DeviceDescriptor PTR [di]).bEndp0MaxPacket
	mov	(DeviceInfo PTR [bx]).wEndp0MaxPacket, ax

; Give some delay
	mov	ax, ((10 * 1000) / 15)	; 10ms delay
	call	USBMisc_FixedDelay

; Now send a GetDescriptor command to the device to get its device descriptor.

	mov	cx, 18
; SI - HCStruc, BX - pDevInfo, CX - Length
	call	USB_GetDescriptor
	jz	UDND_Error

; Set config level
	mov	wConfigLevel, USB_ERR_DEV_INIT_GET_DESC_200

; Get the relevant information from the descriptor and store it in
; device information struture
	mov	ax, (DeviceDescriptor PTR [di]).wVendorId
	mov	(DeviceInfo PTR [bx]).wVendorId, ax

	mov	ax, (DeviceDescriptor PTR [di]).wDeviceId
	mov	(DeviceInfo PTR [bx]).wDeviceId, ax

; Look at each of the device's ConfigDescriptors and InterfaceDescriptors
; until an InterfaceDescriptor is found with BaseClass, SubClass, and
; Protocol fields indicating boot keyboard, mouse, hub or storage support.
	mov	al, (DeviceDescriptor PTR [di]).bNumConfigs
	mov	(DeviceInfo PTR [bx]).bNumConfigs, al

	mov	(DeviceInfo PTR [bx]).bConfigNum, 0
UDND_NextConfig:

;;;;;;  Save DI if needed (for iteration)
	mov	cx, (MAX_CONTROL_DATA_SIZE - 1)
	mov	ah, DESC_TYPE_CONFIG
	mov	al, (DeviceInfo PTR [bx]).bConfigNum
	mov	(DeviceInfo PTR [bx]).CntrlXfer.wValue, ax
; SI - HCStruc, BX - pDevInfo, CX - Length
	call	USB_GetDescriptor	; Output DI - Descriptor read
	jz	UDND_Error

	;DI should now point to a ConfigDescriptor.  Verify this and
	;then get some fields out of it.  Then point to the next descriptor.

	cmp	(ConfigDescriptor PTR [di]).bDescType, DESC_TYPE_CONFIG
	jne	UDND_SkipConfig		;Br if device did not return config desc

	mov	al, (ConfigDescriptor PTR [di]).bConfigValue ;AL = Config value
	mov	(DeviceInfo PTR [bx]).bConfigNum, al

	mov	cx, (ConfigDescriptor PTR [di]).wTotalLength
	cmp	cx, MAX_CONTROL_DATA_SIZE - 1 ;BP = size of all data returned
	jb	UDND_NotOverFlowed
	mov	cx, MAX_CONTROL_DATA_SIZE - 1 ;Limit size of data to what we can handle
UDND_NotOverFlowed:
;;	mov	wDescLength, ax
; Convert size to end offset
	add	cx, di

	movzx	ax, (ConfigDescriptor PTR [di]).bDescLength
	add	di, ax

; DI should now point to an InterfaceDescriptor.  Verify this
; and then check its BaseClass, SubClass, and Protocol fields for
; usable devices.

UDND_NextInterface:
	cmp	(InterfaceDescriptor PTR [di]).bDescType, DESC_TYPE_INTERFACE
	jne	UDND_SkipInterface	;Br if not on an interface desc

	mov	al, (InterfaceDescriptor PTR [di]).bInterfaceNum
	mov	(DeviceInfo PTR [bx]).bInterfaceNum, al
	mov	al, (InterfaceDescriptor PTR [di]).bAltSettingNum
	mov	(DeviceInfo PTR [bx]).bAltSettingNum, al

; SI - HCStruc, BX - DevInfo, DI - Pointer to InterfaceDescriptor,
; CX - Pointer to descriptor end
	call	USBIdentifyAndConfigureDevice
	or	ax, ax
	jz	UDND_SkipInterface
; Successfully configured

; Returns new device info structure in AX
	mov	bx, ax

UDND_SkipInterface:

	movzx	ax, (ConfigDescriptor PTR [di]).bDescLength ;AX = next desc
	or	ax, ax
	jz	UDND_SkipConfig		;Br if 0 length desc (should never happen, but...)
	add	di, ax			;BX = ptr to next desc
	cmp	di, cx
	jae	UDND_SkipConfig		; End of data

; There is one more config. Set device info structure entry 0 for it
	mov	bx, OFFSET DeviceInfoTable	; BX - DeviceInfo[0]

; Multi-interface device. Set the bit appropriately
	or	(DeviceInfo PTR [bx]).bFlag, DEV_INFO_MULTI_IF
	jmp	SHORT UDND_NextInterface

UDND_SkipConfig:
	cmp	(DeviceInfo PTR [bx]).bDeviceType, 00h
	jne	UDND_Success	;Br if at least on usable interface was found already
	inc	(DeviceInfo PTR [bx]).bConfigNum
	mov	al, (DeviceInfo PTR [bx]).bConfigNum
	cmp	al, (DeviceInfo PTR [bx]).bNumConfigs
	jb	UDND_NextConfig	;Br if more configs to look at

; No configuration could be found which supports a device which can be used
; by the BIOS.  Beep politely and disable the hub port.
	push	bx
	mov	bl, 8
	mov	cx, 1000h
	call	USBMisc_SpeakerBeep
	pop	bx

; Log device configuration not found error
IF      MKF_DISPLAY_DEV_DISABLE_ERROR
	mov	ax, ERRUSB_DEVICE_DISABLED
        call	USBLogError
ENDIF

	jmp	SHORT UDND_DisablePort

UDND_Success:

	mov	bl, 4
	mov	cx, 400h
	call	USBMisc_SpeakerBeep

	mov	ax, si			; Valid device info structure
	jmp	short UDND_Done

UDND_Error:
	mov	ax, wConfigLevel
; Log configuration level
	call	USBLogError

;;; Log device configuration error
;;	mov	ax, ERRUSB_DEVICE_INIT
;;	call	USBLogError

	mov	ax, wConfigLevel

UDND_DisablePort:

; If error is during getdescriptor_8 call then skip device
; disabling
	cmp	wConfigLevel, USB_ERR_DEV_INIT_GET_DESC_8
	je	UDND_Done
	
; Disable the hub port
	mov	dh, (DeviceInfo PTR [bx]).bHubDeviceNumber
	mov	dl, (DeviceInfo PTR [bx]).bHubPortNumber
	mov	si, (DeviceInfo PTR [bx]).pHCStrucPtr
	call	USBDisableHubPort

	xor	ax, ax		; Invalid device info
UDND_Done:

	push	ax
	mov	si, OFFSET DeviceInfoTable	;SI = ptr to DeviceInfo[0]
	mov	(DeviceInfo PTR [si]).bDeviceAddress, 0

; Free the  memory allocated for device request buffer
	mov	al, (MAX_CONTROL_DATA_SIZE / USB_MEM_BLK_SIZE)
	mov	bx, pBuffer
	call	USBMem_Free

	pop	ax
	ret
USB_DetectNewDevice	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBDisconnectDevice
;
; Description:	This function is called when a device disconnect is
;		detected. This routine disables the hub port and stops the
;		device and its children by calling another routine.
;
; Input: 	DH	USB device address of the hub whose status
;			has changed
;			bit 7	: 1 - Root hub, 0 for other hubs
;			bit 6-0	: Device address of the hub
;		DL	Port number
;		SI	HCStruc of the host controller
;
; Output: 	Nothing
;
; Modified:	Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBDisconnectDevice	PROC NEAR SYSCALL PUBLIC USES BX CX

; A device has been disconnected from the USB.  First disable the hub port
; that the device was plugged into.  Then free up the device's entry in the
; DeviceTable.  If there an error occurs while disabling the port, assume
; that the device is still present an leave its DeviceTable entry in place.

; DH	Hub/HC number
; DL	Port number
; SI	HCStruc pointer
	call	USBDisableHubPort

; DH	Hub/HC number
; DL	Port number
; SI	HCStruc pointer
	call	USBStopDevice

	ret
USBDisconnectDevice	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBStopDevice
;
; Description:	This function is called when a device disconnect is
;		detected. This routine stops polling on the device, frees
;		its DeviceInfo entry, and notifies the keyboard/mouse code
;		that the device is disconnected.  This routine also
;		recursively processes any child devices if a hub is
;		disconnected.
;
; Input: 	DH	USB device address of the hub whose status
;			has changed
;			bit 7	: 1 - Root hub, 0 for other hubs
;			bit 6-0	: Device address of the hub
;		DL	Port number
;		SI	HCStruc of the host controller
;
; Output: 	Nothing
;
; Modified:	Nothing
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBStopDevice	PROC NEAR SYSCALL PUBLIC

	push	bx
	push	dx
	push	di

; Find the device info entry for this device.
	mov	bx, OFFSET DeviceInfoTable	; SI = Ptr to DeviceInfoTable
	add	bx, SIZE DeviceInfo		; Skip first entry

	xchg	dh, dl
UDD_CheckNextEntry:
	test	(DeviceInfo PTR [bx]).bFlag, DEV_INFO_VALID_STRUC
	jz	UDD_SkipEntry			; Entry not used

	cmp	WORD PTR ((DeviceInfo PTR [bx]).bHubDeviceNumber), dx
	jne	UDD_SkipEntry			; Hub/port number not matched

; Issue disconnect call for the device
	mov	di, (DeviceInfo PTR [bx]).pDevDriverPtr
	or	di, di
	jz	UDD_SkipDisConnect
	cmp	(USB_DEV_HDR PTR cs:[di]).pDisconDevice, 0
	je	UDD_SkipDisConnect
	pushf
	call	(USB_DEV_HDR PTR cs:[di]).pDisconDevice
	popf
UDD_SkipDisConnect:
; Some device driver may not have a disconnect routine. For those drivers
; reset the device info structure validity flag
	jnz	UDD_SkipUpdatingFlag	; Device driver has disconnect routine
; Device driver does not have disconnect routine
	and	(DeviceInfo PTR [bx]).bFlag, NOT (DEV_INFO_VALID_STRUC OR DEV_INFO_DEV_PRESENT)
UDD_SkipUpdatingFlag:

; Stop polling the device's interrupt endpoint.
; Get the HC device driver address in DI
	mov	di, (HCStruc PTR [si]).pHCDPointer
; SI	HCStruc
; BX	DeviceInfo
	call	(HCDHEADER PTR cs:[di]).pHCDDeactivatePolling

UDD_SkipEntry:
	add	bx, SIZE DeviceInfo		; Point to next DeviceInfo
	cmp	bx, OFFSET DeviceInfoTableEnd
	jb	UDD_CheckNextEntry		; More entries in DeviceInfo

UDD_Exit:
	pop	di
	pop	dx
	pop	bx

	ret
USBStopDevice	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBGetProperDeviceInfoStructure
;
; Description:	This routine searches for a device info structure that
;		matches the vendor and device id, and LUN of the device 
;		found. If such a device info structure not found, then it 
;		will return a free device info structure
;
; Input: 	EAX	Vendor and Device ID (Device ID in EAX+)
;		DL	Current LUN
;
; Output: 	SI	Pointer to new device info. struc. 0 on error
;
; Modified:	SI
;
; Referrals:	DeviceInfo
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBGetProperDeviceInfoStructure		PROC NEAR PUBLIC

	push	bx

	xor	bx, bx

; Scan through the device info table for a free entry. Also if the device
; connected is a mass storage device look for a device info structure whose
; device is disconnected and its vendor & device id matches the one of

⌨️ 快捷键说明

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