📄 ohci.asm
字号:
mov eax, SKIP_TDQ or ED_IN_PACKET or (DEFAULT_PACKET_LENGTH shl 16) ;Set PID=In, and MaxLen
mov (Endpoint_Descriptor ptr [di]).ED_Control, eax
; set Delay interrupt to 1,Condition code=not accessed
; Data toggle=DATA0=00b,
mov eax, BUFFER_ROUNDING or IN_PACKET or IntD or (NOT_ACCESSED shl 28)
mov (General_Transfer_Descriptor ptr [si]).GTD_CONTROL,eax
mov (General_Transfer_Descriptor ptr [si]).CSReloadValue,eax
; set GTD's data buffer to GTD_Setup[0]-[7],
; DeviceAddress for device address in UsbHcIsr,
; GTD_Setup[0] for ProcessKeyboardData in PollingTdCallback
lea ax, (General_transfer_Descriptor ptr [si]).GTD_Setup ;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 (General_transfer_Descriptor ptr [si]).GTD_CURRENT_BUFFER_POINTER,eax
add eax, 7
mov (General_transfer_Descriptor ptr [si]).GTD_Buffer_End,eax
mov (General_transfer_Descriptor ptr [si]).GTD_Next_TD,TERMINATE
mov (General_Transfer_Descriptor ptr [si]).pCallback, offset cgroup:PollingTdCallback
add (General_Transfer_Descriptor ptr [si]).pCallback, orgbase
mov (General_Transfer_Descriptor ptr [si]).ActiveFlag, FALSE
add di, size Endpoint_Descriptor
add si, size General_Transfer_Descriptor
inc cl ;Inc ED counter(0-16 for device table entry 0-16)
cmp cl, MAX_DEVICES
jbe InitListNextEd ;Br if more EDs to init
; Setup EdRepeat and TdRepeat. It will run a interrupt transaction to a
; nonexistant dummy device. This will have the effect of generating a periodic
; interrupt used to generate keyboard repeat. This ED/TD is normally inactive,
; and is only activated when a key is pressed.
mov di, offset EdRepeat ;DI = ptr to EdRepeat
mov (Endpoint_Descriptor ptr [di]).ED_Control, DUMMY_DEVICE_ADDR or ED_IN_PACKET or (DEFAULT_PACKET_LENGTH shl 16) or SKIP_TDQ
mov (Endpoint_Descriptor ptr [di]).Next_ED, TERMINATE
mov eax, HcdDataArea
add eax, offset TdRepeat
mov (Endpoint_Descriptor ptr [di]).TDQ_Head_Pointer, eax
mov (Endpoint_Descriptor ptr [di]).TDQ_Tail_Pointer, TERMINATE
mov si, offset TdRepeat ;SI = ptr to TdRepeat
mov eax, BUFFER_ROUNDING or IN_PACKET or IntD or (NOT_ACCESSED shl 28) or ONE_ERROR
mov (General_Transfer_Descriptor ptr [si]).GTD_CONTROL, eax
mov (General_Transfer_Descriptor ptr [si]).CSReloadValue, eax
lea ax, (General_transfer_Descriptor ptr [si]).GTD_Setup ;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 (General_transfer_Descriptor ptr [si]).GTD_CURRENT_BUFFER_POINTER, eax
mov (General_transfer_Descriptor ptr [si]).GTD_Buffer_End, eax
mov (General_transfer_Descriptor ptr [si]).GTD_Next_TD, TERMINATE
mov (General_Transfer_Descriptor ptr [si]).pCallback, offset cgroup:RepeatTdCallback
add (General_Transfer_Descriptor ptr [si]).pCallback, orgbase
mov (General_Transfer_Descriptor ptr [si]).ActiveFlag, TRUE
; Set the periodic start time=2e67h(10% off from HcFmInterval)
mov dx, OHCI_PERIODIC_START
mov eax, 2e67h
call WriteUsbOperRegDword
; Read the HC's Root Hub Descriptor A register. The lower 8 bits of this
; register indicate how many ports are on the HC's root hub. Save this
; information for later use.
mov dx, OHCI_RH_DESCRIPTOR_A
call ReadUsbOperRegDword ;EAX[7:0] = number of root hub ports
mov RootHubPortCount, al ;Save port count for later
; Hook the interrupt that has been assigned to the host controller.
ifdef DOS_DEBUG
mov bx, UsbHcBusDevFuncNum ;BX = HC's PCI bus/dev/function number
mov di, USB_IRQ_LEVEL
mov si, PCI_REG_ADDRESS_BYTE
call smi_pci_read_cfg ;Returns CL = IRQ level assigned to HC
or cl, cl
jz UsbInitDone ;Br if HC did not get an IRQ
mov HC_Interrupt_Level, cl
add cl, 8 ;IRQ 0/1/../7 -> INT 8/9/../F
cmp cl, 10h
jb InitVector ;Br if IRQ 0..7
add cl, 70h - 10h ;Add offset of second 8259's vectors
InitVector:
movzx bx, cl ;BX = HC's interrupt vector
shl bx, 2 ;BX = addr of interrupt vector to hook
mov ax, cs ;AX = CS
shl eax, 16 ;Put CS in upper half of EAX
mov ax, offset cgroup:UsbHcIsr ;EAX = CS:Offset of USB's ISR
push ds
push 0 ;Set DS = 0
pop ds
mov dword ptr [bx], eax ;Hook interrupt
pop ds
else
; Enable the HC's SMI generation on port 60/64 read/write and USB interrupt.
mov bx, UsbHcBusDevFuncNum
call EnableKBCTraps ;Returns CL[3:0] = 60/64 r/w trap flags
or cl, 10h ;Always enable SMI on USB interrupt
call UsbHcChipsetInit
endif
; Unmask the host controller's IRQ level in the 8259
ifdef DOS_DEBUG
mov cl, HC_Interrupt_Level ;CL = IRQ used by the HC (0..15)
mov bx, 1
shl bx, cl ;BX = bit map with one bit set
not bx ;BX = bit map with one bit clear
in al, 21h ;AL = First 8259's mask reg
and al, bl ;Adjust mask
out 21h, al ;Write mask back
in al, 0A1h ;AL = Second 8259's mask reg
and al, bh ;Adjust mask
out 0A1h, al ;Write mask back
endif
; Set the operational bit in the host controller so that power can be applied
; to the ports.
ifdef DOS_DEBUG
mov eax, USBOPERATIONAL
else
mov eax, USBOPERATIONAL or INTERRUPT_ROUTING
endif
mov dx, OHCI_CONTROL_REG
call WriteUsbOperRegDword ;Start the host controller running
; Enable global port power so that new devices can be detected.
mov dx, OHCI_RH_STATUS ;First enable global power
mov eax, SET_GLOBAL_POWER
call WriteUsbOperRegDword
mov cl, 1 ;CL will count through port numbers
mov dx, OHCI_RH_PORT1_STATUS;DX will count through port regs
EnablePowerNextPort:
mov eax, SET_PORT_POWER
call WriteUsbOperRegDword ;Enable individual port's power
ifdef HC_PATCH_NAT_OHCI
push cx
mov cx, 29Ah ;10ms / 15us
call pm_fixed_delay ;Delay 10ms
pop cx
endif
add dx, 4 ;DX = next root hub status port
inc cl ;CL = next port number
cmp cl, RootHubPortCount
jbe EnablePowerNextPort ;Br if still more ports to check
mov cx, 29Ah ;10ms / 15us
call pm_fixed_delay ;Delay 10ms
; Set the HcFrameInterval register
mov dx, OHCI_FRAME_REMAINING
call ReadUsbOperRegDword ;EAX = HcFmRemaining register
xor eax, 80000000h ;Toggle FRT bit
and eax, 80000000h ;Save only FRT bit
or eax, 7FF82EDFh ;Set FSMPS to 7FFFh bits or 4095.7 bytes
mov dx, OHCI_FRAME_INTERVAL ;restore the HcFmInterval reg
call WriteUsbOperRegDword
; Start the host controller for control list only (no periodic list)
ifdef DOS_DEBUG
; mov eax, PERIODIC_LIST_ENABLE or CONTROL_LIST_ENABLE or USBOPERATIONAL
mov eax, CONTROL_LIST_ENABLE or USBOPERATIONAL
else
; mov eax, PERIODIC_LIST_ENABLE or CONTROL_LIST_ENABLE or USBOPERATIONAL or INTERRUPT_ROUTING
mov eax, CONTROL_LIST_ENABLE or USBOPERATIONAL or INTERRUPT_ROUTING
endif
mov dx, OHCI_CONTROL_REG
call WriteUsbOperRegDword ;Start the host controller running
; Check the root hub ports to see if a device is connected. If so, then
; call UsbHubPortChange to handle the attachment of a new device.
mov cl, 1 ;CL will count through port numbers
mov dx, OHCI_RH_PORT1_STATUS;DX will count through port regs
InitRootHubNextPort:
test InitializationFlags, INIT_FLAG_ENUM_DISABLE
jnz @f ;Br if USB enum is disabled
mov al, 0FFh
mov ah, cl ;AH = port number
call UsbGetRootHubPortStatus ;Returns BL,CF (ignore CF and BL bit 2)
test bl, 00000001b ;Test device connected bit
jz @f ;Br if no device connected
call UsbHubPortChange ;Process the connection/disconnection
@@:
call ReadUsbOperRegDword ;EAX = value from port 1 status reg
and eax, 0FFFF0000h ;Keep only the change indicator bits
call WriteUsbOperRegDword ;Write back to clear the change bits
add dx, 4 ;DX = next root hub status port
inc cl ;CL = next port number
cmp cl, RootHubPortCount
jbe InitRootHubNextPort ;Br if still more ports to check
; Initialize the flag StatusChangeInProgress to indicate that a root hub status
; change is not in progress.
mov StatusChangeInProgress, FALSE
;Enable interrupts from the host controller
mov eax, MASTER_INTERRUPT_ENABLE or WRITEBACK_DONEHEAD_ENABLE or RH_STATUS_CHANGE_ENABLE or OWNERSHIP_CHANGE_ENABLE
mov dx, OHCI_INTERRUPT_ENABLE
call WriteUsbOperRegDword ;Enable SOF, WDH, RHSC interrupts
; Start the host controller for periodic list and control list.
ifdef DOS_DEBUG
mov eax, PERIODIC_LIST_ENABLE or CONTROL_LIST_ENABLE or USBOPERATIONAL
else
mov eax, PERIODIC_LIST_ENABLE or CONTROL_LIST_ENABLE or USBOPERATIONAL or INTERRUPT_ROUTING
endif
mov dx, OHCI_CONTROL_REG
call WriteUsbOperRegDword ;Start the host controller running
UsbInitDone:
ifdef DOS_DEBUG
pop es
pop ds
endif
popad
ret
_UsbHcInit endp
;---------------------------------------;
; UsbHcClose ;
;---------------------------------------;--------------------------------------;
; This function shuts down and disables the USB host controller. ;
; ;
; Input: Nothing ;
; ;
; Output: Nothing ;
; ;
; Destroys: Nothing ;
;------------------------------------------------------------------------------;
_UsbHcClose proc near
pusha
ifdef DOS_DEBUG
push ds
push es
push DOS_DEBUG_DATA_AREA
push DOS_DEBUG_DATA_AREA
pop ds
pop es
endif
push edx
call GetUsbHcBusDevFunc ;Returns BX = b/d/f, destroys AX,ECX,EDX
pop edx
jc @f ;Br if USB HC not found
mov UsbHcBusDevFuncNum,bx
mov di, PCI_REG_VENDID
mov si, PCI_REG_ADDRESS_DWORD
call smi_pci_read_cfg ;Returns ECX = Vendor/Device ID
inc ecx
jz UsbHcCloseDone ;Br if HC is disabled
mov di, USB_BASE_ADDRESS
mov si, PCI_REG_ADDRESS_DWORD
call smi_pci_read_cfg ;Returns ECX = memory base of HC
and cl, 0F0h ;Clear reserved bits
mov Oper_Reg_Base_Address, ecx
@@:
; Stop the host controller
mov eax, USBRESET
mov dx, OHCI_CONTROL_REG
call WriteUsbOperRegDword ;Write to HC control reg
; Disable interrupts from the host controller
mov eax, 0ffffffffh
mov dx, OHCI_INTERRUPT_DISABLE
call WriteUsbOperRegDword ;Disable all HC interrupts
; Disable the HC's SMI generation on port 60/64 read/write and USB interrupt.
mov bx, UsbHcBusDevFuncNum
call UsbHcChipsetShutdown
; Mask the host controller's IRQ level in the 8259
ifdef DOS_DEBUG
mov cl, HC_Interrupt_Level ;CL = IRQ used by the HC (0..15)
mov bx, 1
shl bx, cl ;BX = bit map with one bit set
in al, 21h ;AL = First 8259's mask reg
or al, bl ;Adjust mask
out 21h, al ;Write mask back
in al, 0A1h ;AL = Second 8259's mask reg
or al, bh ;Adjust mask
out 0A1h, al ;Write mask back
endif
UsbHcCloseDone:
ifdef DOS_DEBUG
pop es
pop ds
endif
popa
ret
_UsbHcClose endp
;---------------------------------------;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -