Add a Device class to PCI
This commit is contained in:
parent
c3e5251687
commit
8a93c53277
@ -1,6 +1,21 @@
|
||||
#pragma once
|
||||
#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
|
||||
{
|
||||
struct DeviceID
|
||||
@ -8,6 +23,7 @@ namespace PCI
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
};
|
||||
|
||||
struct DeviceType
|
||||
{
|
||||
uint8_t dev_class;
|
||||
@ -15,6 +31,60 @@ namespace PCI
|
||||
uint8_t prog_if;
|
||||
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);
|
||||
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);
|
||||
@ -24,5 +94,5 @@ namespace PCI
|
||||
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);
|
||||
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&));
|
||||
}
|
@ -8,15 +8,6 @@
|
||||
#define PCI_ADDRESS 0xCF8
|
||||
#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;
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
@ -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);
|
||||
pci_scan_bus(sub_bus, callback);
|
||||
}
|
||||
PCI::Device device{device_id, device_type, bus, slot, function};
|
||||
pci_lock.release();
|
||||
callback(device_id, device_type);
|
||||
callback(device);
|
||||
pci_lock.acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PCI::scan(void (*callback)(PCI::DeviceID&, PCI::DeviceType&))
|
||||
void PCI::scan(void (*callback)(PCI::Device&))
|
||||
{
|
||||
pci_lock.acquire();
|
||||
pci_scan_bus(0, callback);
|
||||
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);
|
||||
}
|
@ -149,9 +149,10 @@ extern "C" void _start()
|
||||
|
||||
kinfoln("Interrupts enabled");
|
||||
|
||||
PCI::scan([](PCI::DeviceID& dev_id, PCI::DeviceType& dev_type) {
|
||||
kinfoln("Found PCI device %x:%x, class %x, subclass %x, prog if %x, revision %d", dev_id.vendor, dev_id.device,
|
||||
dev_type.dev_class, dev_type.dev_subclass, dev_type.prog_if, dev_type.revision);
|
||||
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, dev.type().dev_class, dev.type().dev_subclass, dev.type().prog_if,
|
||||
dev.type().revision);
|
||||
});
|
||||
|
||||
Scheduler::exit();
|
||||
|
Loading…
Reference in New Issue
Block a user