Put devices into a device vector.
This commit is contained in:
@@ -52,6 +52,22 @@ acpi_table_header::validate(uint32_t expected_type) const
|
|||||||
return !expected_type || (expected_type == type);
|
return !expected_type || (expected_type == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pci_device::pci_device() :
|
||||||
|
m_base(nullptr),
|
||||||
|
m_bus_addr(0),
|
||||||
|
m_vendor(0),
|
||||||
|
m_device(0),
|
||||||
|
m_class(0),
|
||||||
|
m_subclass(0),
|
||||||
|
m_prog_if(0),
|
||||||
|
m_revision(0),
|
||||||
|
m_irq(isr::isrIgnoreF),
|
||||||
|
m_header_type(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
device_manager::device_manager(const void *root_table) :
|
device_manager::device_manager(const void *root_table) :
|
||||||
m_lapic(nullptr),
|
m_lapic(nullptr),
|
||||||
m_num_ioapics(0)
|
m_num_ioapics(0)
|
||||||
@@ -210,63 +226,12 @@ device_manager::load_apic(const acpi_apic *apic)
|
|||||||
m_lapic->enable();
|
m_lapic->enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t *
|
|
||||||
base_for(uint32_t *group, int bus, int dev, int func)
|
|
||||||
{
|
|
||||||
return kutil::offset_pointer(group,
|
|
||||||
(bus << 20) + (dev << 15) + (func << 12));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
check_function(uint32_t *group, int bus, int dev, int func)
|
|
||||||
{
|
|
||||||
uint32_t *base = base_for(group, bus, dev, func);
|
|
||||||
|
|
||||||
uint32_t vendor = base[0] & 0xffff;
|
|
||||||
uint32_t device = (base[0] >> 16) & 0xffff;
|
|
||||||
if (vendor == 0xffff) return false;
|
|
||||||
|
|
||||||
uint32_t revision = base[2] & 0xff;
|
|
||||||
uint32_t subclass = (base[2] >> 16) & 0xff;
|
|
||||||
uint32_t devclass = (base[2] >> 24) & 0xff;
|
|
||||||
|
|
||||||
uint32_t header = (base[3] >> 16) & 0x7f;
|
|
||||||
bool multi = ((base[3] >> 16) & 0x80) == 0x80;
|
|
||||||
|
|
||||||
log::info(logs::devices, "Found PCIe device at %02d:%02d:%d of type %d.%d id %04x:%04x",
|
|
||||||
bus, dev, func, devclass, subclass, vendor, device);
|
|
||||||
|
|
||||||
if (header == 0) {
|
|
||||||
log::debug(logs::devices, " Interrupt: %d", (base[15] >> 8) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
return multi;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_device(uint32_t *group, int bus, int dev)
|
|
||||||
{
|
|
||||||
if (check_function(group, bus, dev, 0)) {
|
|
||||||
for (int i = 1; i < 8; ++i)
|
|
||||||
check_function(group, bus, dev, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
enumerate_devices(pci_group &group)
|
|
||||||
{
|
|
||||||
for (int bus = group.bus_start; bus <= group.bus_end; ++bus) {
|
|
||||||
for (int dev = 0; dev < 32; ++dev) {
|
|
||||||
check_device(group.base, bus - group.bus_start, dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::load_mcfg(const acpi_mcfg *mcfg)
|
device_manager::load_mcfg(const acpi_mcfg *mcfg)
|
||||||
{
|
{
|
||||||
size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry));
|
size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry));
|
||||||
m_pci.set_size(count);
|
m_pci.set_size(count);
|
||||||
|
m_devices.set_capacity(16);
|
||||||
|
|
||||||
page_manager *pm = page_manager::get();
|
page_manager *pm = page_manager::get();
|
||||||
|
|
||||||
@@ -286,6 +251,65 @@ device_manager::load_mcfg(const acpi_mcfg *mcfg)
|
|||||||
|
|
||||||
log::debug(logs::devices, " Found MCFG entry: base %lx group %d bus %d-%d",
|
log::debug(logs::devices, " Found MCFG entry: base %lx group %d bus %d-%d",
|
||||||
mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end);
|
mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end);
|
||||||
enumerate_devices(m_pci[i]);
|
}
|
||||||
|
|
||||||
|
probe_pci();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static bool
|
||||||
|
check_function(uint32_t *group, int bus, int dev, int func)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
device_manager::probe_pci()
|
||||||
|
{
|
||||||
|
for (auto &pci : m_pci) {
|
||||||
|
log::debug(logs::devices, "Probing PCI group at base %016lx", pci.base);
|
||||||
|
|
||||||
|
for (int bus = pci.bus_start; bus <= pci.bus_end; ++bus) {
|
||||||
|
for (int dev = 0; dev < 32; ++dev) {
|
||||||
|
if (!pci.has_device(bus, dev, 0)) continue;
|
||||||
|
|
||||||
|
auto &d0 = m_devices.emplace(pci, bus, dev, 0);
|
||||||
|
if (!d0.multi()) continue;
|
||||||
|
|
||||||
|
for (int i = 1; i < 8; ++i) {
|
||||||
|
if (pci.has_device(bus, dev, i))
|
||||||
|
m_devices.emplace(pci, bus, dev, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pci_group::has_device(uint8_t bus, uint8_t device, uint8_t func)
|
||||||
|
{
|
||||||
|
return (*base_for(bus, device, func) & 0xffff) != 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func) :
|
||||||
|
m_base(group.base_for(bus, device, func)),
|
||||||
|
m_bus_addr(bus_addr(bus, device, func)),
|
||||||
|
m_irq(isr::isrIgnoreF)
|
||||||
|
{
|
||||||
|
m_vendor = m_base[0] & 0xffff;
|
||||||
|
m_device = (m_base[0] >> 16) & 0xffff;
|
||||||
|
|
||||||
|
m_revision = m_base[2] & 0xff;
|
||||||
|
m_subclass = (m_base[2] >> 16) & 0xff;
|
||||||
|
m_class = (m_base[2] >> 24) & 0xff;
|
||||||
|
|
||||||
|
m_header_type = (m_base[3] >> 16) & 0x7f;
|
||||||
|
m_multi = ((m_base[3] >> 16) & 0x80) == 0x80;
|
||||||
|
|
||||||
|
log::info(logs::devices, "Found PCIe device at %02d:%02d:%d of type %d.%d id %04x:%04x",
|
||||||
|
bus, device, func, m_class, m_subclass, m_vendor, m_device);
|
||||||
|
|
||||||
|
if (m_header_type == 0) {
|
||||||
|
log::debug(logs::devices, " Interrupt: %d", (m_base[15] >> 8) & 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
struct acpi_xsdt;
|
struct acpi_xsdt;
|
||||||
struct acpi_apic;
|
struct acpi_apic;
|
||||||
struct acpi_mcfg;
|
struct acpi_mcfg;
|
||||||
|
|
||||||
class lapic;
|
class lapic;
|
||||||
class ioapic;
|
class ioapic;
|
||||||
enum class isr : uint8_t;
|
enum class isr : uint8_t;
|
||||||
|
struct pci_group;
|
||||||
|
|
||||||
|
|
||||||
/// Information about a discovered PCIe device
|
/// Information about a discovered PCIe device
|
||||||
@@ -21,11 +21,25 @@ public:
|
|||||||
pci_device();
|
pci_device();
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// \arg group The group number of this device's bus
|
/// \arg group The group of this device's bus
|
||||||
/// \arg bus The bus number this device is on
|
/// \arg bus The bus number this device is on
|
||||||
/// \arg device The device number of this device
|
/// \arg device The device number of this device
|
||||||
/// \arg func The function number of this device
|
/// \arg func The function number of this device
|
||||||
pci_device(uint16_t group, uint8_t bus, uint8_t device, uint8_t func);
|
pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func);
|
||||||
|
|
||||||
|
/// Check if this device is multi-function.
|
||||||
|
/// \returns True if this device is multi-function
|
||||||
|
inline bool multi() const { return m_multi; }
|
||||||
|
|
||||||
|
/// Get a bus address, given the bus/device/function numbers.
|
||||||
|
/// \arg bus Number of the bus
|
||||||
|
/// \arg device Index of the device on the bus
|
||||||
|
/// \arg func The function number within the device
|
||||||
|
/// \returns The computed bus_addr
|
||||||
|
static inline uint16_t bus_addr(uint8_t bus, uint8_t device, uint8_t func)
|
||||||
|
{
|
||||||
|
return bus << 8 | device << 3 | func;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t *m_base;
|
uint32_t *m_base;
|
||||||
@@ -40,6 +54,7 @@ private:
|
|||||||
uint8_t m_subclass;
|
uint8_t m_subclass;
|
||||||
uint8_t m_prog_if;
|
uint8_t m_prog_if;
|
||||||
uint8_t m_revision;
|
uint8_t m_revision;
|
||||||
|
bool m_multi;
|
||||||
|
|
||||||
// Might as well cache these to fill out the struct align
|
// Might as well cache these to fill out the struct align
|
||||||
isr m_irq;
|
isr m_irq;
|
||||||
@@ -55,6 +70,24 @@ struct pci_group
|
|||||||
uint16_t bus_end;
|
uint16_t bus_end;
|
||||||
|
|
||||||
uint32_t *base;
|
uint32_t *base;
|
||||||
|
|
||||||
|
/// Get the base address of the MMIO configuration registers for a device
|
||||||
|
/// \arg bus The bus number of the device (relative to this group)
|
||||||
|
/// \arg device The device number on the given bus
|
||||||
|
/// \arg func The function number on the device
|
||||||
|
/// \returns A pointer to the memory-mapped configuration registers
|
||||||
|
inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func)
|
||||||
|
{
|
||||||
|
return kutil::offset_pointer(base,
|
||||||
|
pci_device::bus_addr(bus, device, func) << 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the given device function is present.
|
||||||
|
/// \arg bus The bus number of the device (relative to this group)
|
||||||
|
/// \arg device The device number on the given bus
|
||||||
|
/// \arg func The function number on the device
|
||||||
|
/// \returns True if the device function is present
|
||||||
|
bool has_device(uint8_t bus, uint8_t device, uint8_t func);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
/// Definition of a simple dynamic vector collection for use in kernel space
|
/// Definition of a simple dynamic vector collection for use in kernel space
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
#include "kutil/memory.h"
|
#include "kutil/memory.h"
|
||||||
|
|
||||||
namespace kutil {
|
namespace kutil {
|
||||||
@@ -58,19 +59,50 @@ public:
|
|||||||
delete [] m_elements;
|
delete [] m_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the size of the array.
|
||||||
|
/// \returns The number of elements in the array
|
||||||
|
inline size_t count() const { return m_size; }
|
||||||
|
|
||||||
/// Access an element in the array.
|
/// Access an element in the array.
|
||||||
inline T & operator[] (size_t i) { return m_elements[i]; }
|
inline T & operator[] (size_t i) { return m_elements[i]; }
|
||||||
|
|
||||||
/// Access an element in the array.
|
/// Access an element in the array.
|
||||||
inline const T & operator[] (size_t i) const { return m_elements[i]; }
|
inline const T & operator[] (size_t i) const { return m_elements[i]; }
|
||||||
|
|
||||||
|
/// Get a pointer to the beginning for iteration.
|
||||||
|
/// \returns A pointer to the beginning of the array
|
||||||
|
T * begin() { return m_elements; }
|
||||||
|
|
||||||
|
/// Get a pointer to the beginning for iteration.
|
||||||
|
/// \returns A pointer to the beginning of the array
|
||||||
|
const T * begin() const { return m_elements; }
|
||||||
|
|
||||||
|
/// Get a pointer to the end for iteration.
|
||||||
|
/// \returns A pointer to the end of the array
|
||||||
|
T * end() { return m_elements + m_size; }
|
||||||
|
|
||||||
|
/// Get a pointer to the end for iteration.
|
||||||
|
/// \returns A pointer to the end of the array
|
||||||
|
const T * end() const { return m_elements + m_size; }
|
||||||
|
|
||||||
/// Add an item onto the array by copying it.
|
/// Add an item onto the array by copying it.
|
||||||
/// \arg item the item to add
|
/// \arg item The item to add
|
||||||
void append(const T& item)
|
/// \returns A reference to the added item
|
||||||
|
T & append(const T& item)
|
||||||
{
|
{
|
||||||
ensure_capacity(m_size + 1);
|
ensure_capacity(m_size + 1);
|
||||||
m_elements[m_size] = item;
|
m_elements[m_size] = item;
|
||||||
m_size += 1;
|
return m_elements[m_size++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct an item in place onto the end of the array.
|
||||||
|
/// \returns A reference to the added item
|
||||||
|
template <typename... Args>
|
||||||
|
T & emplace(Args&&... args)
|
||||||
|
{
|
||||||
|
ensure_capacity(m_size + 1);
|
||||||
|
new (&m_elements[m_size]) T(std::forward<Args>(args)...);
|
||||||
|
return m_elements[m_size++];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an item from the end of the array.
|
/// Remove an item from the end of the array.
|
||||||
|
|||||||
Reference in New Issue
Block a user