Kernel: PCIDevice is now class with getters and constructor

This commit is contained in:
Bananymous 2023-03-07 18:56:08 +02:00
parent b4ce438ca7
commit a9acf1f6dc
5 changed files with 56 additions and 41 deletions

View File

@ -8,22 +8,35 @@ namespace Kernel
class PCIDevice class PCIDevice
{ {
public: public:
const uint8_t bus; PCIDevice(uint8_t, uint8_t, uint8_t);
const uint8_t dev;
const uint8_t func;
const uint8_t class_code;
const uint8_t subclass;
uint32_t read_dword(uint8_t) const; uint32_t read_dword(uint8_t) const;
uint16_t read_word(uint8_t) const; uint16_t read_word(uint8_t) const;
uint8_t read_byte(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 class PCI
{ {
BAN_NON_COPYABLE(PCI);
BAN_NON_MOVABLE(PCI);
public: public:
static bool initialize(); static void initialize();
static PCI& get(); static PCI& get();
const BAN::Vector<PCIDevice>& devices() const { return m_devices; } const BAN::Vector<PCIDevice>& devices() const { return m_devices; }

View File

@ -35,10 +35,10 @@ namespace Kernel
// Initialize all storage controllers // Initialize all storage controllers
for (auto& device : PCI::get().devices()) for (auto& device : PCI::get().devices())
{ {
if (device.class_code != 0x01) if (device.class_code() != 0x01)
continue; continue;
switch (device.subclass) switch (device.subclass())
{ {
case 0x0: case 0x0:
dwarnln("unsupported SCSI Bus Controller"); dwarnln("unsupported SCSI Bus Controller");

View File

@ -1,4 +1,3 @@
#include <kernel/Debug.h>
#include <kernel/IO.h> #include <kernel/IO.h>
#include <kernel/PCI.h> #include <kernel/PCI.h>
@ -11,15 +10,14 @@
namespace Kernel namespace Kernel
{ {
PCI* s_instance = nullptr; static PCI* s_instance = nullptr;
bool PCI::initialize() void PCI::initialize()
{ {
ASSERT(s_instance == nullptr); ASSERT(s_instance == nullptr);
s_instance = new PCI(); s_instance = new PCI();
ASSERT(s_instance); ASSERT(s_instance);
s_instance->check_all_buses(); s_instance->check_all_buses();
return !s_instance->m_devices.empty();
} }
PCI& PCI::get() PCI& PCI::get()
@ -49,31 +47,22 @@ namespace Kernel
void PCI::check_function(uint8_t bus, uint8_t dev, uint8_t func) void PCI::check_function(uint8_t bus, uint8_t dev, uint8_t func)
{ {
uint32_t type = read_config_dword(bus, dev, func, 0x08); MUST(m_devices.emplace_back(bus, dev, func));
PCIDevice device { auto& device = m_devices.back();
bus, if (device.class_code() == 0x06 && device.subclass() == 0x04)
dev, check_bus(device.read_byte(0x19));
func,
(uint8_t)(type >> 24),
(uint8_t)(type >> 16),
};
MUST(m_devices.push_back(BAN::move(device)));
} }
void PCI::check_device(uint8_t bus, uint8_t dev) void PCI::check_device(uint8_t bus, uint8_t dev)
{ {
if (get_vendor_id(bus, dev, 0) == INVALID) if (get_vendor_id(bus, dev, 0) == INVALID)
return; return;
check_function(bus, dev, 0);
if (get_header_type(bus, dev, 0) & MULTI_FUNCTION) if (get_header_type(bus, dev, 0) & MULTI_FUNCTION)
{ for (uint8_t func = 1; func < 8; func++)
for (uint8_t func = 0; func < 8; func++)
if (get_vendor_id(bus, dev, func) != INVALID) if (get_vendor_id(bus, dev, func) != INVALID)
check_function(bus, dev, func); check_function(bus, dev, func);
}
else
{
check_function(bus, dev, 0);
}
} }
void PCI::check_bus(uint8_t bus) void PCI::check_bus(uint8_t bus)
@ -86,9 +75,8 @@ namespace Kernel
{ {
if (get_header_type(0, 0, 0) & MULTI_FUNCTION) if (get_header_type(0, 0, 0) & MULTI_FUNCTION)
{ {
for (int func = 0; func < 8; func++) for (int func = 0; func < 8 && get_vendor_id(0, 0, func) != INVALID; func++)
if (get_vendor_id(0, 0, func) != INVALID) check_bus(func);
check_bus(func);
} }
else 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 uint32_t PCIDevice::read_dword(uint8_t offset) const
{ {
ASSERT((offset & 0x03) == 0); 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 uint16_t PCIDevice::read_word(uint8_t offset) const
{ {
ASSERT((offset & 0x01) == 0); ASSERT((offset & 0x01) == 0);
uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC); uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC);
return (uint16_t)(dword >> (offset & 0x03)); return (uint16_t)(dword >> (8 * (offset & 0x03)));
} }
uint8_t PCIDevice::read_byte(uint8_t offset) const uint8_t PCIDevice::read_byte(uint8_t offset) const
{ {
uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC); uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC);
return (uint8_t)(dword >> (offset & 0x03)); return (uint8_t)(dword >> (8 * (offset & 0x03)));
} }
} }

View File

@ -254,6 +254,13 @@ argument_done:
IO::outb(0x64, 0xFE); IO::outb(0x64, 0xFE);
asm volatile("cli; hlt"); 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") else if (arguments.front() == "ls")
{ {
if (!VirtualFileSystem::is_initialized()) if (!VirtualFileSystem::is_initialized())

View File

@ -86,6 +86,9 @@ extern "C" void kernel_main()
MMU::intialize(); MMU::intialize();
dprintln("MMU initialized"); dprintln("MMU initialized");
PCI::initialize();
dprintln("PCI initialized");
TerminalDriver* terminal_driver = VesaTerminalDriver::create(); TerminalDriver* terminal_driver = VesaTerminalDriver::create();
ASSERT(terminal_driver); ASSERT(terminal_driver);
dprintln("VESA initialized"); dprintln("VESA initialized");
@ -97,10 +100,6 @@ extern "C" void kernel_main()
PIT::initialize(); PIT::initialize();
dprintln("PIT initialized"); dprintln("PIT initialized");
if (!PCI::initialize())
Kernel::panic("Could not initialize PCI");
dprintln("PCI initialized");
if (!Input::initialize()) if (!Input::initialize())
dprintln("Could not initialize input drivers"); dprintln("Could not initialize input drivers");
dprintln("Input initialized"); dprintln("Input initialized");