; Arguments: ; ah Bus Number (0 .. 255) ; al Device Number (0 .. 31) ; ; Returns: ; - true/false (eax) pci_device_exists: push dword esi sub esp, 8 mov esi, esp mov [esi], edx mov [esi + 4], eax .make_address: xor eax, eax ; Enable Bit or al, 1 ; Make space for 8 Reserved Bits and 8 Bytes of bus number. shl eax, 15 ; Bus Number mov al, [esi + 5] ; Device Number shl eax, 5 ; Make space for device number mov dl, [esi + 4] and dl, 0x1f or al, dl shl eax, 11 .io_task: mov dx, PCI_CONFIG_ADDRESS_PORT out dx, eax mov dx, PCI_CONFIG_DATA_PORT in eax, dx cmp ax, 0xffff jne .device_found .not_a_device: mov edx, [esi] add esp, 8 pop dword esi xor eax, eax ret .device_found: mov edx, [esi] add esp, 8 pop dword esi mov eax, 1 ret ; Arguments: ; [FURTHEST FROM EBP] ; 3. U32 PCI Device Class & Subclass ; (Higher byte: Class, lower byte: Subclass) ; 2. U32 PCI Device Address ; 1. Ptr32 Pointer to PCI driver area of 65536 bytes ; [NEAREST TO EBP] pci_append_device: push dword esi sub esp, 64 mov esi, esp mov [esi + (64 - 4)], eax mov [esi + (64 - 8)], ebx mov [esi + (64 - 12)], ecx mov [esi + (64 - 20)], edi .get_device_count: mov ebx, [ebp - 4] xor ecx, ecx mov cx, [ebx + PCI_DEVICE_COUNT_OFFSET] mov [esi + 4], cx .calculate_device_offset: ; Every device slot has 16 bytes, multiply index with 16 shl cx, 4 ; Point into driver device area (add device area start on top) add ecx, ebx add ecx, PCI_DEVICE_COUNT_OFFSET mov ebx, ecx .set_device: mov ecx, [ebp - 8] mov [ebx], ecx mov ecx, [ebp - 12] mov [ebx + 4], ecx increment_device_count: .epilog: mov eax, [esi + (64 - 4)] mov ebx, [esi + (64 - 8)] mov ecx, [esi + (64 - 12)] mov edi, [esi + (64 - 20)] add esp, 64 pop dword esi ret ; Arguments: ; [FURTHER FROM EBP] ; 2. U32 Bus Number (0 .. 255) ; 1. Ptr32 Pointer to PCI driver area of 65536 bytes ; [NEAREST TO EBP] ; ; Returns: ; - Number of devics on the bus (eax) pci_enumerate_bus: push dword esi sub esp, 64 mov esi, esp mov [esi + (64 - 8)], ebx mov [esi + (64 - 12)], ecx mov [esi + (64 - 20)], edi ; [esi]: Device-in-bus Index ; [esi + 4]: Number of existing devices ; [esi + 8]: Bus number mov [esi], dword 0 mov [esi + 4], dword 0 mov eax, [ebp - 8] mov [esi + 8], eax .initialize_device_loop: .device_loop: cmp [esi], dword 32 jae .epilog .test_whether_device_exists: push ebp mov ebp, esp mov ah, [esi + 8] ; Bus Number mov al, [esi] ; Device Number call pci_device_exists mov esp, ebp pop ebp cmp ax, 0 je .no_device .call_append_device: push ebp mov ebp, esp push dword [esi + 8] push dword 0xcafebabe push dword 0xdeadbeef call pci_append_device mov esp, ebp pop ebp mov eax, [esi + 4] inc eax mov [esi + 4], eax .no_device: mov ecx, [esi] inc ecx mov [esi], ecx jmp .device_loop .epilog: mov ebx, [esi + (64 - 8)] mov ecx, [esi + (64 - 12)] mov edi, [esi + (64 - 20)] mov eax, [esi + 4] add esp, 64 pop dword esi ret ; Arguments: ; [FURTHEST FROM EBP] ; 2. U32 Maximum number of devices to enumerate ; (0 to eliminate limit) ; 1. Ptr32 Pointer to PCI driver area of 65536 bytes ; [NEAREST TO EBP] pci_enumerate: push dword esi sub esp, 64 mov esi, esp mov [esi + (64 - 4)], eax mov [esi + (64 - 8)], ebx mov [esi + (64 - 12)], ecx mov [esi + (64 - 16)], edx mov [esi + (64 - 20)], edi ; [esi]: Number of devices found ; ecx: Bus Index mov edx, [ebp - 4] mov [esi + 4], edx .bus_loop: xor ecx, ecx mov [esi], dword 0 .bus_loop_body: ; Test whether the device count is unlimited, ; ignore the device count check if it is. cmp [ebp - 8], dword 0 je .call_bus_enumerator mov edx, [esi] cmp edx, [ebp - 8] jae .epilog .call_bus_enumerator: push ebp mov ebp, esp push dword [esi + 4] push ecx call pci_enumerate_bus mov esp, ebp pop ebp ; Add the number of devices found on the bus ; to the number of devices found in total. add [esi], eax mov ebx, [esi + 4] add [ebx + PCI_DEVICE_COUNT_OFFSET], ax ; Go to the next bus (if there is one) inc ecx cmp ecx, 256 jb .bus_loop_body .epilog: mov ebx, [esi + (64 - 8)] mov ecx, [esi + (64 - 12)] mov edx, [esi + (64 - 16)] mov edi, [esi + (64 - 20)] mov eax, [esi] add esp, 64 pop dword esi ret