Add a Device class to PCI

This commit is contained in:
apio 2022-09-23 17:24:45 +02:00
parent c3e5251687
commit 8a93c53277
3 changed files with 155 additions and 16 deletions

View File

@ -1,6 +1,21 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#define PCI_VENDOR_FIELD 0x0
#define PCI_DEVICE_FIELD 0x2
#define PCI_SUBCLASS_FIELD 0xa
#define PCI_CLASS_FIELD 0xb
#define PCI_REVISION_ID_FIELD 0x8
#define PCI_PROG_IF_FIELD 0x9
#define PCI_HEADER_TYPE_FIELD 0xe
#define PCI_SECONDARY_BUS_NUMBER_FIELD 0x19
#define PCI_BAR0_FIELD 0x10
#define PCI_BAR1_FIELD 0x14
#define PCI_BAR2_FIELD 0x18
#define PCI_BAR3_FIELD 0x1C
#define PCI_BAR4_FIELD 0x20
#define PCI_BAR5_FIELD 0x24
namespace PCI namespace PCI
{ {
struct DeviceID struct DeviceID
@ -8,6 +23,7 @@ namespace PCI
uint16_t vendor; uint16_t vendor;
uint16_t device; uint16_t device;
}; };
struct DeviceType struct DeviceType
{ {
uint8_t dev_class; uint8_t dev_class;
@ -15,6 +31,60 @@ namespace PCI
uint8_t prog_if; uint8_t prog_if;
uint8_t revision; uint8_t revision;
}; };
struct Device
{
void write8(int32_t offset, uint8_t value);
void write16(int32_t offset, uint16_t value);
void write32(int32_t offset, uint32_t value);
uint8_t read8(int32_t offset);
uint16_t read16(int32_t offset);
uint32_t read32(int32_t offset);
uint32_t getBAR0();
uint32_t getBAR1();
uint32_t getBAR2();
uint32_t getBAR3();
uint32_t getBAR4();
uint32_t getBAR5();
uint8_t bus()
{
return m_bus;
}
uint8_t slot()
{
return m_slot;
}
uint8_t function()
{
return m_function;
}
DeviceID id()
{
return m_id;
}
DeviceType type()
{
return m_type;
}
Device(DeviceID id, DeviceType type, uint8_t bus, uint8_t slot, uint8_t function);
Device(uint8_t bus, uint8_t slot, uint8_t function);
Device(const Device& other);
private:
uint8_t m_bus;
uint8_t m_slot;
uint8_t m_function;
DeviceID m_id;
DeviceType m_type;
};
uint32_t raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); uint32_t raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
void raw_write8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint8_t value); void raw_write8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint8_t value);
void raw_write16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint16_t value); void raw_write16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint16_t value);
@ -24,5 +94,5 @@ namespace PCI
uint32_t raw_read32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); uint32_t raw_read32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
DeviceID get_device_id(uint32_t bus, uint32_t slot, uint32_t function); DeviceID get_device_id(uint32_t bus, uint32_t slot, uint32_t function);
DeviceType get_device_type(uint32_t bus, uint32_t slot, uint32_t function); DeviceType get_device_type(uint32_t bus, uint32_t slot, uint32_t function);
void scan(void (*callback)(PCI::DeviceID&, PCI::DeviceType&)); void scan(void (*callback)(PCI::Device&));
} }

View File

@ -8,15 +8,6 @@
#define PCI_ADDRESS 0xCF8 #define PCI_ADDRESS 0xCF8
#define PCI_VALUE 0xCFC #define PCI_VALUE 0xCFC
#define PCI_VENDOR_FIELD 0x0
#define PCI_DEVICE_FIELD 0x2
#define PCI_SUBCLASS_FIELD 0xa
#define PCI_CLASS_FIELD 0xb
#define PCI_REVISION_ID_FIELD 0x8
#define PCI_PROG_IF_FIELD 0x9
#define PCI_HEADER_TYPE_FIELD 0xe
#define PCI_SECONDARY_BUS_NUMBER_FIELD 0x19
Spinlock pci_lock; Spinlock pci_lock;
uint32_t PCI::raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset) uint32_t PCI::raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset)
@ -76,7 +67,7 @@ PCI::DeviceType PCI::get_device_type(uint32_t bus, uint32_t slot, uint32_t funct
return {dev_class, dev_subclass, prog_if, revision}; return {dev_class, dev_subclass, prog_if, revision};
} }
static void pci_scan_bus(uint8_t bus, void (*callback)(PCI::DeviceID&, PCI::DeviceType&)) static void pci_scan_bus(uint8_t bus, void (*callback)(PCI::Device&))
{ {
for (uint8_t slot = 0; slot < 32; slot++) for (uint8_t slot = 0; slot < 32; slot++)
{ {
@ -96,16 +87,93 @@ static void pci_scan_bus(uint8_t bus, void (*callback)(PCI::DeviceID&, PCI::Devi
uint8_t sub_bus = PCI::raw_read8(bus, slot, function, PCI_SECONDARY_BUS_NUMBER_FIELD); uint8_t sub_bus = PCI::raw_read8(bus, slot, function, PCI_SECONDARY_BUS_NUMBER_FIELD);
pci_scan_bus(sub_bus, callback); pci_scan_bus(sub_bus, callback);
} }
PCI::Device device{device_id, device_type, bus, slot, function};
pci_lock.release(); pci_lock.release();
callback(device_id, device_type); callback(device);
pci_lock.acquire(); pci_lock.acquire();
} }
} }
} }
void PCI::scan(void (*callback)(PCI::DeviceID&, PCI::DeviceType&)) void PCI::scan(void (*callback)(PCI::Device&))
{ {
pci_lock.acquire(); pci_lock.acquire();
pci_scan_bus(0, callback); pci_scan_bus(0, callback);
pci_lock.release(); pci_lock.release();
}
PCI::Device::Device(const Device& other)
: m_id(other.m_id), m_type(other.m_type), m_bus(other.m_bus), m_slot(other.m_slot), m_function(other.m_function)
{
}
PCI::Device::Device(uint8_t bus, uint8_t slot, uint8_t function) : m_bus(bus), m_slot(slot), m_function(function)
{
m_id = get_device_id(m_bus, m_slot, m_function);
m_type = get_device_type(m_bus, m_slot, m_function);
}
PCI::Device::Device(DeviceID id, DeviceType type, uint8_t bus, uint8_t slot, uint8_t function)
: m_id(id), m_type(type), m_bus(bus), m_slot(slot), m_function(function)
{
}
void PCI::Device::write8(int32_t offset, uint8_t value)
{
PCI::raw_write8(m_bus, m_slot, m_function, offset, value);
}
void PCI::Device::write16(int32_t offset, uint16_t value)
{
PCI::raw_write16(m_bus, m_slot, m_function, offset, value);
}
void PCI::Device::write32(int32_t offset, uint32_t value)
{
PCI::raw_write32(m_bus, m_slot, m_function, offset, value);
}
uint8_t PCI::Device::read8(int32_t offset)
{
return PCI::raw_read8(m_bus, m_slot, m_function, offset);
}
uint16_t PCI::Device::read16(int32_t offset)
{
return PCI::raw_read16(m_bus, m_slot, m_function, offset);
}
uint32_t PCI::Device::read32(int32_t offset)
{
return PCI::raw_read32(m_bus, m_slot, m_function, offset);
}
uint32_t PCI::Device::getBAR0()
{
return read32(PCI_BAR0_FIELD);
}
uint32_t PCI::Device::getBAR1()
{
return read32(PCI_BAR1_FIELD);
}
uint32_t PCI::Device::getBAR2()
{
return read32(PCI_BAR2_FIELD);
}
uint32_t PCI::Device::getBAR3()
{
return read32(PCI_BAR3_FIELD);
}
uint32_t PCI::Device::getBAR4()
{
return read32(PCI_BAR4_FIELD);
}
uint32_t PCI::Device::getBAR5()
{
return read32(PCI_BAR5_FIELD);
} }

View File

@ -149,9 +149,10 @@ extern "C" void _start()
kinfoln("Interrupts enabled"); kinfoln("Interrupts enabled");
PCI::scan([](PCI::DeviceID& dev_id, PCI::DeviceType& dev_type) { PCI::scan([](PCI::Device& dev) {
kinfoln("Found PCI device %x:%x, class %x, subclass %x, prog if %x, revision %d", dev_id.vendor, dev_id.device, kinfoln("Found PCI device %x:%x, class %x, subclass %x, prog if %x, revision %d", dev.id().vendor,
dev_type.dev_class, dev_type.dev_subclass, dev_type.prog_if, dev_type.revision); dev.id().device, dev.type().dev_class, dev.type().dev_subclass, dev.type().prog_if,
dev.type().revision);
}); });
Scheduler::exit(); Scheduler::exit();