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

📄 usb.asm

📁 AMI 主板的BIOS源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;    entry                                                                     ;
; 10. Configure the device using SetConfiguration, SetInterface, and           ;
;     SetProtocol commands                                                     ;
; 11. Activate polling for the device by calling UsbActivatePolling            ;
; 12. Done                                                                     ;
;                                                                              ;
; Input:  AL = USB Device address of hub where new device has been plugged in  ;
;              00 - 7F = Device address of hub on the USB                      ;
;              80 - FE = Reserved                                              ;
;              FF      = Root hub                                              ;
;         AH = Port number within hub where new device has been plugged in     ;
;         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-7: Reserved                                               ;
;         DS = ES = usbdseg                                                    ;
;                                                                              ;
; Output: Nothing                                                              ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
UsbDetectNewDevice	proc near
	pusha
	push	es

; First set the speed of entry 0 in the DeviceTable 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	si, offset DeviceTable	;SI = ptr to DeviceTableEntry[0]
	mov	(DeviceTableEntry ptr [si]).DeviceAddress, 0
	shr	bl, 1			;Full/Low speed bit in bit 0
	and	bl, 1			;BL = 00/01 for Full/Low speed
	mov	(DeviceTableEntry ptr [si]).LowSpeedFlag, bl
	mov	(DeviceTableEntry ptr [si]).Endp0MaxPacket, 40h
	mov	word ptr ((DeviceTableEntry ptr [si]).HubDeviceNumber), ax
	mov	(DeviceTableEntry ptr [si]).BiosDeviceType, 00h

; Next enable the port on the hub where the device is connected.
; HubDeviceNumber is in AL and HubPortNumber is in AH.
; Full speed / low speed flag is in BL.

	call	UsbEnableHubPort	;Enables/resets the port and delays

; 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 learn the real
; MaxPacket size that the device is using, because this piece of information
; is at offset 7 in the device descriptor.

	push	si
	mov	al, 0			;AL = default device address
	mov	ah, 0			;Send command to endpoint 0 on device
	mov	ch, DESC_TYPE_DEVICE	;CH = Descriptor type
	mov	cl, 0			;CL = Descriptor index
	mov	si, 8d			;SI = Size of descriptor
	call	_UsbGetDescriptor	;Returns ES:DI = descriptor data
	pop	si
	jc	NewDeviceAbort		;Br if error during command

	movzx	ax, es:(DeviceDescriptor ptr [di]).Endp0MaxPacket
	mov	(DeviceTableEntry ptr [si]).Endp0MaxPacket, ax

; Delay for 5 milliseconds after premature termination of the GetDescriptor
; command above.  This was added to accomodate the Philips Infra-Red keyboard
; (Vid=0471, Pid=0601, Ver=1.00) which stops responding during the status
; phase of the SetAddress command below if SetAddress follows the
; GetDescriptor command by only 2ms.

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


; Now find a free device address.  This is done by searching through the array
; of DeviceTable entries, trying addresses until an unused one is found.

	mov	dl, 1			;First device address to try

FindAddrNextAddr:
	mov	si, offset DeviceTable	;SI = ptr to DeviceTable[0]

FindAddrNextEntry:
	cmp	(DeviceTableEntry ptr [si]).Present, TRUE
	jne	FindAddrSkipEntry	;Br if found unused entry
	cmp	(DeviceTableEntry ptr [si]).DeviceAddress, dl
	je	FindAddrSkipAddr	;Br if addr DL is already used
	
FindAddrSkipEntry:
	add	si, size DeviceTableEntry
	cmp	si, offset DeviceTableEnd
	jb	FindAddrNextEntry	;Br if not to end of DeviceTable
	jmp	NewDeviceFoundAddr	;Made it all the way through the DeviceTable
					; array wthout finding addr DL
FindAddrSkipAddr:
	inc	dl			;Inc address to try
	cmp	dl, MAX_DEVICE_ADDR
	jbe	FindAddrNextAddr	;Br if still more addresses to try
	jmp	NewDeviceDone		;No free address was found so abort

; A free device address is now in DL.  Now send a SetAddress command to the
; device to set it to its new USB device address (in DL).

NewDeviceFoundAddr:
	mov	al, dl			;AL = new device address
	call	_UsbSetAddress
	mov	si, offset DeviceTable	;SI = ptr to DeviceTable[0]
	jc	NewDeviceAbort		;Br if error setting address

	mov	(DeviceTableEntry ptr [si]).DeviceAddress, dl

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

	push	si
	mov	al, dl			;AL = new device address
	mov	ah, 0			;Send command to endpoint 0 on device
	mov	ch, DESC_TYPE_DEVICE	;CH = Descriptor type
	mov	cl, 0			;CL = Descriptor index
	mov	si, 18d			;SI = Size of descriptor
	call	_UsbGetDescriptor	;Returns ES:DI = descriptor data
	pop	si
	jc	NewDeviceAbort		;Br if error during command

	mov	cx, es:(DeviceDescriptor ptr [di]).VendorId
	mov	(DeviceTableEntry ptr [si]).VendorId, cx
	mov	cx, es:(DeviceDescriptor ptr [di]).DeviceId
	mov	(DeviceTableEntry ptr [si]).DeviceId, cx

; 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, or hub support.

	mov	cl, es:(DeviceDescriptor ptr [di]).NumConfigs
	mov	(DeviceTableEntry ptr [si]).NumConfigs, cl
	mov	(DeviceTableEntry ptr [si]).ConfigNum, 0

NewDeviceNextConfig:
	push	si
	mov	al, dl			;AL = new device address
	mov	ah, 0			;Send command to endpoint 0 on device
	mov	ch, DESC_TYPE_CONFIG	;CH = Descriptor type
	mov	cl, (DeviceTableEntry ptr [si]).ConfigNum ;CL = Desc index
	mov	si, MAX_CONTROL_DATA_SIZE - 1 ;SI = Max size of descriptor
	call	_UsbGetDescriptor	;Returns ES:DI = descriptor data
	pop	si
	jc	NewDeviceAbort		;Br if error during command

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

	cmp	es:(ConfigDescriptor ptr [di]).DescType, DESC_TYPE_CONFIG
	jne	NewDeviceSkipConfig	;Br if device did not return config desc

	mov	al, es:(ConfigDescriptor ptr [di]).ConfigValue ;AL = Config value
	mov	(DeviceTableEntry ptr [si]).ConfigNum, al
	mov	bp, es:(ConfigDescriptor ptr [di]).TotalLength
	cmp	bp, MAX_CONTROL_DATA_SIZE - 1 ;BP = size of all data returned
	jb	@f			  ;Br if data did not overflow
	mov	bp, MAX_CONTROL_DATA_SIZE - 1 ;Limit size of data to what we can handle
@@:
	movzx	bx, es:(ConfigDescriptor ptr [di]).DescLength

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

NewDeviceNextInterface:
	cmp	es:(InterfaceDescriptor ptr [di+bx]).DescType, DESC_TYPE_INTERFACE
	jne	NewDeviceSkipInterface	;Br if not on an interface desc

	mov	al, es:(InterfaceDescriptor ptr [di+bx]).InterfaceNum
	mov	(DeviceTableEntry ptr [si]).InterfaceNum, al
	mov	al, es:(InterfaceDescriptor ptr [di+bx]).AltSettingNum
	mov	(DeviceTableEntry ptr [si]).AltSettingNum, al

	call	CheckForAndConfigureKeyboard
	jnc	NewDeviceSkipInterface	;Br if successful
	call	CheckForAndConfigureMouse
	jnc	NewDeviceSkipInterface	;Br if successful
	call	CheckForAndConfigureHub

NewDeviceSkipInterface:
	movzx	ax, es:(ConfigDescriptor ptr [di+bx]).DescLength ;BX = next desc
	or	ax, ax
	jz	NewDeviceSkipConfig	;Br if 0 length desc (should never happen, but...)
	add	bx, ax			;BX = ptr to next desc
	cmp	bx, bp
	jb	NewDeviceNextInterface	;Br if not past end of data

NewDeviceSkipConfig:
	cmp	(DeviceTableEntry ptr [si]).BiosDeviceType, 00h
	jne	NewDeviceSuccess	;Br if at least on usable interface was found already
	inc	(DeviceTableEntry ptr [si]).ConfigNum
	mov	al, (DeviceTableEntry ptr [si]).ConfigNum
	cmp	al, (DeviceTableEntry ptr [si]).NumConfigs
	jb	NewDeviceNextConfig	;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.

	mov	ah, 4			;Issue connect beep (high & short)
	mov	cx, 1000h
	call	SpeakerBeep
	jmp	short NewDeviceDisablePort

NewDeviceAbort:
	mov	ah, 64			;Issue error beep (low & long)
	mov	cx, 4000h
	call	SpeakerBeep

NewDeviceDisablePort:
	mov	ax, word ptr ((DeviceTableEntry ptr [si]).HubDeviceNumber)
	call	UsbDisableHubPort	;Disables the hub/port at AL/AH

NewDeviceDone:
	mov	si, offset DeviceTable	;SI = ptr to DeviceTableEntry[0]
	mov	(DeviceTableEntry ptr [si]).DeviceAddress, 0
	pop	es
	popa
	ret

NewDeviceSuccess:
	mov	ah, 4			;Issue connect beep (high & short)
	mov	cx, 1000h
	mov	cx, 400h
	call	SpeakerBeep
	jmp	short NewDeviceDone

UsbDetectNewDevice	endp


;---------------------------------------;
; CheckForAndConfigureKeyboard          ;
;---------------------------------------;--------------------------------------;
; This function checks an interface descriptor of a device to see if it        ;
; describes a HID/Boot/Keyboard device.  If the device is a keyboard, then     ;
; it is configured and initialized.                                            ;
;                                                                              ;
; Input: ES:DI+BX = Pointer to an interface descriptor supported by device     ;
;        ES:DI+BP = Limit of the data returned by device during the last       ;
;                   Get Configuration Descriptor command                       ;
;        DS:SI = Pointer to DeviceTableEntry[0] which contains some info       ;
;                from the device, config, and interface descriptors            ;
;                                                                              ;
; Output: CF = Set if keyboard was not found                                   ;
;              Clear if keyboard was found and initialized                     ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
CheckForAndConfigureKeyboard	proc near
	pusha

; ES:DI+BX points to an InterfaceDescriptor.  Check its BaseClass, SubClass,
; and Protocol fields for a HID/Boot/Keyboard device.

	cmp	es:(InterfaceDescriptor ptr [di+bx]).BaseClass, BASS_CLASS_HID
	stc
	jne	CheckKbdDone		;Br if this interface is not a HID device
	cmp	es:(InterfaceDescriptor ptr [di+bx]).SubClass, SUB_CLASS_BOOT_DEVICE
	stc
	jne	CheckKbdDone		;Br if this interface is not a boot device
	cmp	es:(InterfaceDescriptor ptr [di+bx]).Protocol, PROTOCOL_KEYBOARD
	stc
	jne	CheckKbdDone		;Br if this interface is not a keyboard

; Set the BiosDeviceType field in DeviceTableEntry[0].  This serves as a flag
; that indicates a usable interface has been found in the current configuration.
; This is needed so we can check for other usable interfaces in the current
; configuration (i.e. composite device), but not try to search in other
; configurations.

	mov     (DeviceTableEntry ptr [si]).BiosDeviceType, BIOS_DEV_TYPE_KEYBOARD
	mov     (DeviceTableEntry ptr [si]).pDeviceCallback, offset cgroup:ProcessKeyboardData
	add     (DeviceTableEntry ptr [si]).pDeviceCallback, orgbase

; Call a common routine to handle the remaining initialization that is done
; for all devices.

	call	ConfigureNewDevice	;Finish init for new device
					; Returns CF set/clear appropriately
CheckKbdDone:
	popa
	ret
CheckForAndConfigureKeyboard	endp


;---------------------------------------;
; CheckForAndConfigureMouse             ;

⌨️ 快捷键说明

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