diff --git a/src/kernel/device_manager.cpp b/src/kernel/device_manager.cpp index 6ef9419..9612f89 100644 --- a/src/kernel/device_manager.cpp +++ b/src/kernel/device_manager.cpp @@ -36,15 +36,6 @@ struct acpi2_rsdp uint8_t reserved[3]; } __attribute__ ((packed)); -struct pci_group -{ - uint16_t group; - uint16_t bus_start; - uint16_t bus_end; - - uint32_t *base; -}; - uint8_t acpi_checksum(const void *p, size_t len, size_t off = 0) { @@ -63,12 +54,7 @@ acpi_table_header::validate(uint32_t expected_type) const device_manager::device_manager(const void *root_table) : m_lapic(nullptr), - m_num_ioapics(0), - m_pci(nullptr), - m_num_pci_groups(0), - m_devices(nullptr), - m_num_devices(0), - m_num_device_entries(0) + m_num_ioapics(0) { kassert(root_table != 0, "ACPI root table pointer is null."); @@ -280,9 +266,7 @@ void device_manager::load_mcfg(const acpi_mcfg *mcfg) { size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry)); - - m_pci = new pci_group[count]; - m_num_pci_groups = count; + m_pci.set_size(count); page_manager *pm = page_manager::get(); diff --git a/src/kernel/device_manager.h b/src/kernel/device_manager.h index fd5279b..e23108a 100644 --- a/src/kernel/device_manager.h +++ b/src/kernel/device_manager.h @@ -2,6 +2,7 @@ /// \file device_manager.h /// The device manager and related device classes. #include +#include "kutil/vector.h" struct acpi_xsdt; struct acpi_apic; @@ -9,12 +10,54 @@ struct acpi_mcfg; class lapic; class ioapic; -class pci_device; -struct pci_group; - enum class isr : uint8_t; +/// Information about a discovered PCIe device +class pci_device +{ +public: + /// Default constructor creates an empty object. + pci_device(); + + /// Constructor + /// \arg group The group number of this device's bus + /// \arg bus The bus number this device is on + /// \arg device The device 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); + +private: + uint32_t *m_base; + + /// Bus address: 15:8 bus, 7:3 device, 2:0 device + uint16_t m_bus_addr; + + uint16_t m_vendor; + uint16_t m_device; + + uint8_t m_class; + uint8_t m_subclass; + uint8_t m_prog_if; + uint8_t m_revision; + + // Might as well cache these to fill out the struct align + isr m_irq; + uint8_t m_header_type; +}; + + +/// Represents data about a PCI bus group from the ACPI MCFG +struct pci_group +{ + uint16_t group; + uint16_t bus_start; + uint16_t bus_end; + + uint32_t *base; +}; + + /// Manager for all system hardware devices class device_manager { @@ -56,47 +99,9 @@ private: ioapic *m_ioapics[16]; int m_num_ioapics; - pci_group *m_pci; - int m_num_pci_groups; - - pci_device *m_devices; - int m_num_devices; - int m_num_device_entries; + kutil::vector m_pci; + kutil::vector m_devices; device_manager() = delete; device_manager(const device_manager &) = delete; }; - - -/// Information about a discovered PCIe device -class pci_device -{ -public: - /// Default constructor creates an empty object. - pci_device(); - - /// Constructor - /// \arg group The group number of this device's bus - /// \arg bus The bus number this device is on - /// \arg device The device 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); - -private: - uint32_t *m_base; - - /// Bus address: 15:8 bus, 7:3 device, 2:0 device - uint16_t m_bus_addr; - - uint16_t m_vendor; - uint16_t m_device; - - uint8_t m_class; - uint8_t m_subclass; - uint8_t m_prog_if; - uint8_t m_revision; - - // Might as well cache these to fill out the struct align - isr m_irq; - uint8_t m_header_type; -}; diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index a6b33b8..bb716ba 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -47,7 +47,7 @@ init_console(const popcorn_data *header) log::init(cons); log::enable(logs::apic, log::level::info); - log::enable(logs::devices, log::level::info); + log::enable(logs::devices, log::level::debug); log::enable(logs::memory, log::level::debug); } diff --git a/src/modules/kutil/memory.cpp b/src/modules/kutil/memory.cpp index 0cd81d5..8ad1d5f 100644 --- a/src/modules/kutil/memory.cpp +++ b/src/modules/kutil/memory.cpp @@ -6,8 +6,17 @@ void * memset(void *s, uint8_t v, size_t n) { uint8_t *p = reinterpret_cast(s); - for (int i = 0; i < n; ++i) p[i] = 0; + for (size_t i = 0; i < n; ++i) p[i] = v; return s; } +void * +memcpy(void *dest, void *src, size_t n) +{ + uint8_t *s = reinterpret_cast(src); + uint8_t *d = reinterpret_cast(dest); + for (size_t i = 0; i < n; ++i) d[i] = s[i]; + return d; +} + } // namespace kutil diff --git a/src/modules/kutil/memory.h b/src/modules/kutil/memory.h index 64869ea..b94b5d4 100644 --- a/src/modules/kutil/memory.h +++ b/src/modules/kutil/memory.h @@ -8,8 +8,20 @@ using addr_t = uint64_t; namespace kutil { +/// Fill memory with the given value. +/// \arg p The beginning of the memory area to fill +/// \arg v The byte value to fill memory with +/// \arg n The size in bytes of the memory area +/// \returns A pointer to the filled memory void * memset(void *p, uint8_t v, size_t n); +/// Copy an area of memory to another +/// \dest The memory to copy to +/// \src The memory to copy from +/// \n The number of bytes to copy +/// \returns A pointer to the destination memory +void * memcpy(void *dest, void *src, size_t n); + template inline T read_from(const void *p) { return *reinterpret_cast(p); } diff --git a/src/modules/kutil/vector.h b/src/modules/kutil/vector.h new file mode 100644 index 0000000..855dc46 --- /dev/null +++ b/src/modules/kutil/vector.h @@ -0,0 +1,132 @@ +#pragma once +/// \file vector.h +/// Definition of a simple dynamic vector collection for use in kernel space + +#include +#include "kutil/memory.h" + +namespace kutil { + +/// A dynamic array. +template +class vector +{ +public: + /// Default constructor. Creates an empty vector with no capacity. + vector() : + m_size(0), + m_capacity(0), + m_elements(nullptr) + {} + + /// Constructor. Creates an empty array with capacity. + /// \arg capacity Initial capacity to allocate + vector(size_t capacity) : + m_size(0), + m_capacity(0), + m_elements(nullptr) + { + set_capacity(capacity); + } + + /// Copy constructor. Allocates a copy of the other's array. + vector(const vector& other) : + m_size(0), + m_capacity(0), + m_elements(nullptr) + { + set_capacity(other.m_capacity); + kutil::memcpy(m_elements, other.m_elements, other.m_size * sizeof(T)); + m_size = other.m_size; + } + + /// Move constructor. Takes ownership of the other's array. + vector(vector&& other) : + m_size(other.m_size), + m_capacity(other.m_capacity), + m_elements(other.m_elements) + { + other.m_size = 0; + other.m_capacity = 0; + other.m_elements = nullptr; + } + + /// Destructor. Destroys any remaining items in the array. + ~vector() + { + while (m_size) remove(); + delete [] m_elements; + } + + /// Access an element in the array. + inline T & operator[] (size_t i) { return m_elements[i]; } + + /// Access an element in the array. + inline const T & operator[] (size_t i) const { return m_elements[i]; } + + /// Add an item onto the array by copying it. + /// \arg item the item to add + void append(const T& item) + { + ensure_capacity(m_size + 1); + m_elements[m_size] = item; + m_size += 1; + } + + /// Remove an item from the end of the array. + void remove() + { + m_size -= 1; + m_elements[m_size].~T(); + } + + /// Set the size of the array. Any new items are default + /// constructed. The array is realloced if needed. + /// \arg size The new size + void set_size(size_t size) + { + ensure_capacity(size); + for (size_t i = m_size; i < size; ++i) + new (&m_elements[i]) T; + m_size = size; + } + + /// Ensure the array will fit an item. + /// \arg size Size of the array + void ensure_capacity(size_t size) + { + if (m_capacity >= size) return; + + size_t capacity = m_capacity; + while (capacity < size) { + if (capacity == 0) capacity = 4; + else capacity *= 2; + } + set_capacity(capacity); + } + + /// Reallocate the array. Copy over any old elements that will + /// fit into the new array. The rest are destroyed. + /// \arg capacity Number of elements to allocate + void set_capacity(size_t capacity) + { + T *new_array = new T[capacity]; + size_t size = std::min(capacity, m_size); + + kutil::memcpy(new_array, m_elements, size * sizeof(T)); + + while (size < m_size) remove(); + m_size = size; + m_capacity = capacity; + + delete [] m_elements; + m_elements = new_array; + } + +private: + size_t m_size; + size_t m_capacity; + T *m_elements; +}; + +} // namespace kutil