forked from KolibriOS/kolibrios
117 lines
3.3 KiB
HTML
117 lines
3.3 KiB
HTML
; =============================================================================
|
|
; Модуль : PCI Device Detection
|
|
; Назначение : Обнаружение и идентификация PCI устройства VirtualBox
|
|
; Файл : core/pci.inc
|
|
; =============================================================================
|
|
|
|
align 4
|
|
pci_device dd ? ; Указатель на структуру PCI устройства VBox
|
|
|
|
; vmmdev_probe — Поиск PCI устройства VirtualBox в системе
|
|
proc vmmdev_probe
|
|
call pci_find_vmmdev
|
|
test eax, eax
|
|
jnz .fail
|
|
call pci_init_vmmdev_irq
|
|
test eax, eax
|
|
jnz .fail
|
|
call pci_init_vmmdev_bar
|
|
test eax, eax
|
|
jnz .fail
|
|
xor eax, eax
|
|
ret
|
|
.fail:
|
|
DEBUGF 2, "[VBoxGuest] [PCI] Initialization failed\n"
|
|
mov eax, VERR_GENERAL_FAILURE
|
|
ret
|
|
endp
|
|
|
|
proc pci_find_vmmdev
|
|
; Получаем список PCI устройств
|
|
invoke GetPCIList
|
|
mov ebx, eax ; EBX = начало списка (якорь)
|
|
|
|
.search_loop:
|
|
mov eax, [eax + PCIDEV.fd]
|
|
cmp eax, ebx
|
|
je .not_found
|
|
|
|
; Сравниваем Vendor/Device ID
|
|
mov edx, [eax + PCIDEV.vendor_device_id]
|
|
cmp edx, (VBOX_DEVICE_ID shl 16) + VBOX_VENDOR_ID
|
|
jne .search_loop
|
|
|
|
.found:
|
|
mov [pci_device], eax
|
|
|
|
DEBUGF 2, "[VBoxGuest] [PCI] VBox device found\n"
|
|
xor eax, eax
|
|
ret
|
|
|
|
.not_found:
|
|
DEBUGF 2, "[VBoxGuest] [PCI] VBox device NOT found\n"
|
|
mov eax, VERR_GENERAL_FAILURE
|
|
ret
|
|
endp
|
|
|
|
; pci_init_vmmdev_irq — Чтение IRQ линии из PCI конфигурации
|
|
proc pci_init_vmmdev_irq
|
|
mov ebx, [pci_device]
|
|
DEBUGF 2, "[VBoxGuest] [PCI] pci_device=0x%x\n", [pci_device]
|
|
test ebx, ebx
|
|
jz .no_device
|
|
|
|
; Читаем IRQ линию из PCI конфигурации
|
|
invoke PciRead32, dword [ebx + PCIDEV.bus], dword [ebx + PCIDEV.devfn], PCI_header00.interrupt_line
|
|
movzx eax, al ; IRQ линия - младший байт
|
|
|
|
; Проверяем валидность IRQ (должна быть 0-15)
|
|
cmp eax, 16
|
|
jae .invalid_irq
|
|
|
|
; Сохраняем IRQ в структуре устройства
|
|
mov [vbox_device.irq], eax
|
|
DEBUGF 2, "[VBoxGuest] [PCI] IRQ line: %d\n", eax
|
|
|
|
xor eax, eax
|
|
ret
|
|
|
|
.no_device:
|
|
DEBUGF 2, "[VBoxGuest] [PCI] ERROR: No PCI device for IRQ init\n"
|
|
mov eax, VERR_GENERAL_FAILURE
|
|
ret
|
|
|
|
.invalid_irq:
|
|
DEBUGF 2, "[VBoxGuest] [PCI] ERROR: Invalid IRQ line: %d\n", eax
|
|
mov eax, VERR_GENERAL_FAILURE
|
|
ret
|
|
|
|
endp
|
|
|
|
; pci_init_vmmdev_bar — Чтение BAR0 (I/O) и BAR1 (MMIO) из PCI конфигурации
|
|
proc pci_init_vmmdev_bar
|
|
mov ebx, [pci_device]
|
|
test ebx, ebx
|
|
jz .no_device
|
|
|
|
; Читаем BAR0 (I/O port)
|
|
invoke PciRead32, dword [ebx + PCIDEV.bus], dword [ebx + PCIDEV.devfn], PCI_header00.base_addr_0
|
|
and eax, not 0xF
|
|
mov [vbox_device.port], ax
|
|
DEBUGF 2, "[VBoxGuest] [PCI] BAR0 (I/O Port): 0x%x\n", eax
|
|
|
|
; Читаем BAR1 (MMIO)
|
|
invoke PciRead32, dword [ebx + PCIDEV.bus], dword [ebx + PCIDEV.devfn], PCI_header00.base_addr_1
|
|
and eax, not 0xF
|
|
mov [vbox_device.mmio_phys], eax
|
|
DEBUGF 2, "[VBoxGuest] [PCI] BAR1 (MMIO): phys=0x%x\n", eax
|
|
|
|
xor eax, eax
|
|
ret
|
|
|
|
.no_device:
|
|
DEBUGF 2, "[VBoxGuest] [PCI] ERROR: No PCI device for BAR init\n"
|
|
mov eax, VERR_GENERAL_FAILURE
|
|
ret
|
|
|
|
endp |