diff --git a/src/drivers/pci.c b/src/drivers/pci.c new file mode 100644 index 0000000..ba6e210 --- /dev/null +++ b/src/drivers/pci.c @@ -0,0 +1,105 @@ +// PCI bus driver implementation +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#include +#include "pci.h" +#include "../libc/stdio.h" + +static inline void outl(uint16_t port, uint32_t value) +{ + __asm__ volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t ret; + __asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +void pci_write_config_address(uint32_t address) +{ + outl(PCI_CONFIG_ADDRESS, address); +} + +uint32_t pci_read_config_data() +{ + return inl(PCI_CONFIG_DATA); +} + +uint32_t pci_config_address(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) +{ + return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC); +} + +uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) +{ + uint32_t address = pci_config_address(bus, device, function, offset); + pci_write_config_address(address); + return pci_read_config_data(); +} + +pci_device_t pci_get_device(uint8_t bus, uint8_t device, uint8_t function) +{ + pci_device_t dev; + + uint32_t reg0 = pci_read(bus, device, function, 0x00); // Vendor ID, Device ID + uint32_t reg2 = pci_read(bus, device, function, 0x08); // Class, Subclass, Prog IF, Revision + + dev.vendor_id = reg0 & 0xFFFF; + dev.device_id = (reg0 >> 16) & 0xFFFF; + dev.class_code = (reg2 >> 24) & 0xFF; + dev.subclass = (reg2 >> 16) & 0xFF; + dev.prog_if = (reg2 >> 8) & 0xFF; + dev.revision_id = reg2 & 0xFF; + dev.bus = bus; + dev.device = device; + dev.function = function; + + return dev; +} + +void scan_pci_bus() +{ + for (uint16_t bus = 0; bus < 256; bus++) { + for (uint8_t device = 0; device < 32; device++) { + for (uint8_t function = 0; function < 8; function++) { + pci_device_t dev = pci_get_device(bus, device, function); + + if (dev.vendor_id != 0xFFFF) { + + char* vendor_string; + switch(dev.vendor_id) + { + case 0x8086: + vendor_string = "Intel Corporation"; + break; + case 0x1234: + vendor_string = "Brain Actuated Technologies"; + break; + default: + vendor_string = "Unknown"; + break; + } + + char* device_string; + switch(dev.device_id) + { + case 0x1237: + device_string = "440FX - 82441FX PMC"; + break; + default: + device_string = "Unknown"; + break; + } + + printf("PCI Device found: Bus %u, Device %u, Function %u, Vendor ID: 0x%x (%s), Device ID: 0x%x (%s), Class: 0x%x\n", + dev.bus, dev.device, dev.function, dev.vendor_id, vendor_string, dev.device_id, device_string, dev.class_code); + } + } + } + } +} + diff --git a/src/drivers/pci.h b/src/drivers/pci.h new file mode 100644 index 0000000..d9483bb --- /dev/null +++ b/src/drivers/pci.h @@ -0,0 +1,29 @@ +// PCI bus driver implementation header +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#ifndef PCI_H +#define PCI_H + +#include + +#define PCI_CONFIG_ADDRESS 0xCF8 +#define PCI_CONFIG_DATA 0xCFC + +typedef struct +{ + uint16_t vendor_id; + uint16_t device_id; + uint8_t class_code; + uint8_t subclass; + uint8_t prog_if; + uint8_t revision_id; + uint8_t bus; + uint8_t device; + uint8_t function; +} pci_device_t; + +void scan_pci_bus(); + +#endif diff --git a/src/kernel/shell.c b/src/kernel/shell.c index e9876f7..0aab0aa 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -143,6 +143,7 @@ void shell_install() register_command("ls", program_ls); register_command("cat", program_cat); register_command("bmp", program_bmp); + register_command("lspci", program_lspci); for (;;) { diff --git a/src/kernel/system.c b/src/kernel/system.c index 5af9b8e..7c6561b 100644 --- a/src/kernel/system.c +++ b/src/kernel/system.c @@ -50,3 +50,4 @@ void panic() { for (;;); } + diff --git a/src/programs/misc.c b/src/programs/misc.c index fd206fa..94c1ec5 100644 --- a/src/programs/misc.c +++ b/src/programs/misc.c @@ -10,6 +10,7 @@ #include "../drivers/ata.h" #include "../drivers/rtc.h" #include "../kernel/io.h" +#include "../drivers/pci.h" // Print a rainbow colorful text for testing @@ -73,7 +74,7 @@ void program_uptime() void program_help() { - printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\n"); + printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\n"); } // Panic @@ -143,3 +144,10 @@ void program_reboot() while (1) asm volatile("hlt"); } + +// List PCI buses and devices + +void program_lspci() +{ + scan_pci_bus(); +} diff --git a/src/programs/programs.h b/src/programs/programs.h index 11c799e..81cbbc3 100644 --- a/src/programs/programs.h +++ b/src/programs/programs.h @@ -39,5 +39,6 @@ void program_ls(); void program_cat(); void program_bmp(); +void program_lspci(); #endif