Compare commits

...

2 Commits

Author SHA1 Message Date
Eric-Paul Ickhorn 18e5b049a4
Add PCI register read utility
The newly added utility routine reads the content of a known PCI
device's register given the index assigned to the device during
enumeration and the index of the register (and the PCI driver area,
but that is implied).
2024-07-23 01:01:20 +02:00
Eric-Paul Ickhorn 1285994cbf
Improve coding style of PCI device enumerator
The arguments of all of the statements are now indented and one or two
comments have been rewritten partially, improving readability.
2024-07-23 00:51:04 +02:00
2 changed files with 238 additions and 170 deletions

View File

@ -6,52 +6,53 @@
; Returns:
; - true/false (eax)
pci_device_exists:
push dword esi
sub esp, 8
mov esi, esp
push dword esi
sub esp, 8
mov esi, esp
mov [esi], edx
mov [esi + 4], eax
mov [esi], edx
mov [esi + 4], eax
.make_address:
xor eax, eax
xor eax, eax
; Enable Bit
or al, 1
or al, 1
; Make space for 8 Reserved Bits and 8 Bytes of bus number.
shl eax, 15
shl eax, 15
; Bus Number
mov al, [esi + 5]
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
; Make space for device number
shl eax, 5
mov dl, [esi + 4]
and dl, 0x1f
or al, dl
shl eax, 11
.io_task:
mov dx, PCI_CONFIG_ADDRESS_PORT
out dx, eax
.input_output:
mov dx, PCI_CONFIG_ADDRESS_PORT
out dx, eax
mov dx, PCI_CONFIG_DATA_PORT
in eax, dx
mov dx, PCI_CONFIG_DATA_PORT
in eax, dx
cmp ax, 0xffff
jne .device_found
cmp ax, 0xffff
jne .device_found
.not_a_device:
mov edx, [esi]
mov edx, [esi]
add esp, 8
pop dword esi
add esp, 8
pop dword esi
xor eax, eax
xor eax, eax
ret
.device_found:
mov edx, [esi]
mov edx, [esi]
add esp, 8
pop dword esi
mov eax, 1
add esp, 8
pop dword esi
mov eax, 1
ret
@ -66,26 +67,26 @@ pci_device_exists:
; 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
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
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
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 ecx, 4
; Point into driver device area (add device area start on top)
mov ebx, [ebp - 4]
mov ebx, [ebp - 4]
add ebx, PCI_DEVICE_AREA_OFFSET
add ebx, ecx
@ -96,7 +97,7 @@ pci_append_device:
mov [ebx + 2], cx
.increment_device_count:
mov ebx, [ebp - 4]
mov ebx, [ebp - 4]
inc word [ebx + PCI_DEVICE_COUNT_OFFSET]
.epilog:
@ -121,54 +122,55 @@ pci_append_device:
; ax PCI Device Class & Subclass
; (Higher byte: Class, lower byte: Subclass)
pci_get_device_class_at_address:
push dword esi
sub esp, 64
mov esi, esp
push dword esi
sub esp, 64
mov esi, esp
mov [esi + (64 - 8)], ebx
mov [esi + (64 - 12)], ecx
mov [esi + (64 - 16)], edx
mov [esi + (64 - 20)], edi
mov [esi + (64 - 8)], ebx
mov [esi + (64 - 12)], ecx
mov [esi + (64 - 16)], edx
mov [esi + (64 - 20)], edi
.create_address:
xor eax, eax
xor eax, eax
; Enable Bit
or al, 1
or al, 1
; Make space for 8 Reserved Bits and 8 Bytes of bus number.
shl eax, 15
shl eax, 15
; Bus Number
mov al, [ebp - 2]
mov al, [ebp - 2]
; Device Number
shl eax, 5 ; Make space for device number
mov dl, [ebp - 4]
and dl, 0x1f
or al, dl
shl eax, 11
; Make space for device number
shl eax, 5
mov dl, [ebp - 4]
and dl, 0x1f
or al, dl
shl eax, 11
; Include the register offset of the configuration space
; register which contains the class and subclass
or eax, 8
or eax, 8
.input_output:
mov dx, PCI_CONFIG_ADDRESS_PORT
out dx, eax
mov dx, PCI_CONFIG_ADDRESS_PORT
out dx, eax
mov dx, PCI_CONFIG_DATA_PORT
in eax, dx
mov dx, PCI_CONFIG_DATA_PORT
in eax, dx
; Remove the parts of the register which aren't part of the
; PCI class- and subclass-code
shr eax, 16
shr eax, 16
.epilog:
mov ebx, [esi + (64 - 8)]
mov ecx, [esi + (64 - 12)]
mov edx, [esi + (64 - 16)]
mov edi, [esi + (64 - 20)]
mov ebx, [esi + (64 - 8)]
mov ecx, [esi + (64 - 12)]
mov edx, [esi + (64 - 16)]
mov edi, [esi + (64 - 20)]
add esp, 64
pop dword esi
add esp, 64
pop dword esi
ret
@ -182,91 +184,87 @@ pci_get_device_class_at_address:
; Returns:
; - Number of devics on the bus (eax)
pci_enumerate_bus:
push dword esi
sub esp, 64
mov esi, esp
push dword esi
sub esp, 64
mov esi, esp
mov [esi + (64 - 8)], ebx
mov [esi + (64 - 12)], ecx
mov [esi + (64 - 20)], edi
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
mov eax, [ebp - 4]
mov [esi + 12], eax
; [esi + 12]:
mov [esi], dword 0
mov [esi + 4], dword 0
mov eax, [ebp - 8]
mov [esi + 8], eax
mov eax, [ebp - 4]
mov [esi + 12], eax
.initialize_device_loop:
.device_loop:
cmp [esi], dword 32
jae .epilog
cmp [esi], dword 32
jae .epilog
.test_whether_device_exists:
mov ah, [esi + 8] ; Bus Number
mov al, [esi] ; Device Number
mov [esi + 16], ax
mov ah, [esi + 8] ; Bus Number
mov al, [esi] ; Device Number
mov [esi + 16], ax
push ebp
mov ebp, esp
call pci_device_exists
mov esp, ebp
pop ebp
push ebp
mov ebp, esp
call pci_device_exists
mov esp, ebp
pop ebp
cmp ax, 0
je .no_device
cmp ax, 0
je .no_device
.append_device:
mov al, [esi + 8]
mov ah, [esi]
mov al, [esi + 8]
mov ah, [esi]
; Device Number in DX
xor dx, dx
mov dl, ah
xor ah, ah
xor dx, dx
mov dl, ah
xor ah, ah
push ebp
mov ebp, esp
push ax
push dx
call pci_get_device_class_at_address
mov esp, ebp
pop ebp
push ebp
mov ebp, esp
push ax
push dx
call pci_get_device_class_at_address
mov esp, ebp
pop ebp
mov cx, ax
mov ax, [esi + 16]
mov cx, ax
mov ax, [esi + 16]
push ebp
mov ebp, esp
push dword [esi + 12]
push ax
push cx
call pci_append_device
mov esp, ebp
pop ebp
push ebp
mov ebp, esp
push dword [esi + 12]
push ax
push cx
call pci_append_device
mov esp, ebp
pop ebp
mov eax, [esi + 4]
inc eax
mov [esi + 4], eax
mov ebx, [ebp - 4]
.no_device:
mov ecx, [esi]
inc ecx
mov [esi], ecx
jmp .device_loop
inc dword [esi]
jmp .device_loop
.epilog:
mov ebx, [esi + (64 - 8)]
mov ecx, [esi + (64 - 12)]
mov edi, [esi + (64 - 20)]
mov ebx, [esi + (64 - 8)]
mov ecx, [esi + (64 - 12)]
mov edi, [esi + (64 - 20)]
mov eax, [esi + 4]
mov eax, [esi + 4]
add esp, 64
pop dword esi
add esp, 64
pop dword esi
ret
@ -277,70 +275,72 @@ pci_enumerate_bus:
; (0 to eliminate limit)
; 1. Ptr32 Pointer to PCI driver area of 65536 bytes
; [NEAREST TO EBP]
; Returns:
; eax: Number of devices read
pci_enumerate:
push dword esi
sub esp, 64
mov esi, esp
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
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
mov edx, [ebp - 4]
mov [esi + 4], edx
; Set the device count to 0 explicitly, just for safety.
mov ebx, [ebp - 4]
add ebx, PCI_DEVICE_COUNT_OFFSET
mov [ebx], word 0
mov ebx, [ebp - 4]
add ebx, PCI_DEVICE_COUNT_OFFSET
mov [ebx], word 0
.bus_loop:
xor ecx, ecx
mov [esi], dword 0
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
cmp [ebp - 8], dword 0
je .call_bus_enumerator
mov edx, [esi]
cmp edx, [ebp - 8]
jae .epilog
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
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
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
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]
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
add esp, 64
pop dword esi
ret

View File

@ -0,0 +1,68 @@
; Arguments:
; [FURTHER FROM EBP]
; 3. U16 Register Index
; 2. U16 Device Index in device list
; 1. Ptr32 Pointer to PCI driver area
; [NEAREST TO EBP]
pci_read_register:
push dword esi
sub esp, 64
mov esi, esp
mov [esi + (64 - 8)], ebx
mov [esi + (64 - 12)], ecx
mov [esi + (64 - 16)], edx
mov [esi + (64 - 20)], edi
.check_device_index:
; todo: Boundary checks
.get_device:
xor ebx, ebx
mov bx, [ebp - 6]
shl ebx, 4
; Point into the driver's device area
add ebx, [ebp - 4]
add ebx, PCI_DEVICE_AREA_OFFSET
mov [esi], ebx
xor eax, eax
mov ax, [ebx]
mov [esi + 4], ah
mov [esi + 5], al
.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, 9
or al, [ebp - 8]
shl eax, 2
.input_output:
mov dx, PCI_CONFIG_ADDRESS_PORT
out dx, eax
mov dx, PCI_CONFIG_DATA_PORT
in eax, dx
.epilog:
mov ebx, [esi + (64 - 8)]
mov ecx, [esi + (64 - 12)]
mov edx, [esi + (64 - 16)]
mov edi, [esi + (64 - 20)]
add esp, 64
pop dword esi
ret