diff --git a/kernel/include/kernel/PCI.h b/kernel/include/kernel/PCI.h index db07a054..d222c954 100644 --- a/kernel/include/kernel/PCI.h +++ b/kernel/include/kernel/PCI.h @@ -8,22 +8,35 @@ namespace Kernel class PCIDevice { public: - const uint8_t bus; - const uint8_t dev; - const uint8_t func; - - const uint8_t class_code; - const uint8_t subclass; + PCIDevice(uint8_t, uint8_t, uint8_t); uint32_t read_dword(uint8_t) const; uint16_t read_word(uint8_t) const; uint8_t read_byte(uint8_t) const; + + uint8_t bus() const { return m_bus; } + uint8_t dev() const { return m_dev; } + uint8_t func() const { return m_func; } + + uint8_t class_code() const { return m_class_code; } + uint8_t subclass() const { return m_subclass; } + + private: + uint8_t m_bus; + uint8_t m_dev; + uint8_t m_func; + + uint8_t m_class_code; + uint8_t m_subclass; }; class PCI { + BAN_NON_COPYABLE(PCI); + BAN_NON_MOVABLE(PCI); + public: - static bool initialize(); + static void initialize(); static PCI& get(); const BAN::Vector& devices() const { return m_devices; } diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 0b38222e..e01e4c5b 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -35,10 +35,10 @@ namespace Kernel // Initialize all storage controllers for (auto& device : PCI::get().devices()) { - if (device.class_code != 0x01) + if (device.class_code() != 0x01) continue; - switch (device.subclass) + switch (device.subclass()) { case 0x0: dwarnln("unsupported SCSI Bus Controller"); diff --git a/kernel/kernel/PCI.cpp b/kernel/kernel/PCI.cpp index d0a3c3a8..73627f6b 100644 --- a/kernel/kernel/PCI.cpp +++ b/kernel/kernel/PCI.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -11,15 +10,14 @@ namespace Kernel { - PCI* s_instance = nullptr; + static PCI* s_instance = nullptr; - bool PCI::initialize() + void PCI::initialize() { ASSERT(s_instance == nullptr); s_instance = new PCI(); ASSERT(s_instance); s_instance->check_all_buses(); - return !s_instance->m_devices.empty(); } PCI& PCI::get() @@ -49,31 +47,22 @@ namespace Kernel void PCI::check_function(uint8_t bus, uint8_t dev, uint8_t func) { - uint32_t type = read_config_dword(bus, dev, func, 0x08); - PCIDevice device { - bus, - dev, - func, - (uint8_t)(type >> 24), - (uint8_t)(type >> 16), - }; - MUST(m_devices.push_back(BAN::move(device))); + MUST(m_devices.emplace_back(bus, dev, func)); + auto& device = m_devices.back(); + if (device.class_code() == 0x06 && device.subclass() == 0x04) + check_bus(device.read_byte(0x19)); } void PCI::check_device(uint8_t bus, uint8_t dev) { if (get_vendor_id(bus, dev, 0) == INVALID) return; + + check_function(bus, dev, 0); if (get_header_type(bus, dev, 0) & MULTI_FUNCTION) - { - for (uint8_t func = 0; func < 8; func++) + for (uint8_t func = 1; func < 8; func++) if (get_vendor_id(bus, dev, func) != INVALID) check_function(bus, dev, func); - } - else - { - check_function(bus, dev, 0); - } } void PCI::check_bus(uint8_t bus) @@ -86,9 +75,8 @@ namespace Kernel { if (get_header_type(0, 0, 0) & MULTI_FUNCTION) { - for (int func = 0; func < 8; func++) - if (get_vendor_id(0, 0, func) != INVALID) - check_bus(func); + for (int func = 0; func < 8 && get_vendor_id(0, 0, func) != INVALID; func++) + check_bus(func); } else { @@ -96,23 +84,31 @@ namespace Kernel } } + PCIDevice::PCIDevice(uint8_t bus, uint8_t dev, uint8_t func) + : m_bus(bus), m_dev(dev), m_func(func) + { + uint32_t type = read_word(0x0A); + m_class_code = (uint8_t)(type >> 8); + m_subclass = (uint8_t)(type); + } + uint32_t PCIDevice::read_dword(uint8_t offset) const { ASSERT((offset & 0x03) == 0); - return read_config_dword(bus, dev, func, offset); + return read_config_dword(m_bus, m_dev, m_func, offset); } uint16_t PCIDevice::read_word(uint8_t offset) const { ASSERT((offset & 0x01) == 0); - uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC); - return (uint16_t)(dword >> (offset & 0x03)); + uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC); + return (uint16_t)(dword >> (8 * (offset & 0x03))); } uint8_t PCIDevice::read_byte(uint8_t offset) const { - uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC); - return (uint8_t)(dword >> (offset & 0x03)); + uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC); + return (uint8_t)(dword >> (8 * (offset & 0x03))); } } \ No newline at end of file diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 53f5ff4f..7dcffc8e 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -254,6 +254,13 @@ argument_done: IO::outb(0x64, 0xFE); asm volatile("cli; hlt"); } + else if (arguments.front() == "lspci") + { + if (arguments.size() != 1) + return TTY_PRINTLN("'lspci' does not support command line arguments"); + for (auto& device : PCI::get().devices()) + TTY_PRINTLN("{2H}:{2H}.{2H} {2H}", device.bus(), device.dev(), device.func(), device.class_code()); + } else if (arguments.front() == "ls") { if (!VirtualFileSystem::is_initialized()) diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index da01928c..508f4a60 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -86,6 +86,9 @@ extern "C" void kernel_main() MMU::intialize(); dprintln("MMU initialized"); + PCI::initialize(); + dprintln("PCI initialized"); + TerminalDriver* terminal_driver = VesaTerminalDriver::create(); ASSERT(terminal_driver); dprintln("VESA initialized"); @@ -97,10 +100,6 @@ extern "C" void kernel_main() PIT::initialize(); dprintln("PIT initialized"); - if (!PCI::initialize()) - Kernel::panic("Could not initialize PCI"); - dprintln("PCI initialized"); - if (!Input::initialize()) dprintln("Could not initialize input drivers"); dprintln("Input initialized");