From e914d4b0df59f0221a6e49fa0881261eb82d42f0 Mon Sep 17 00:00:00 2001 From: Max Van den Eynde Date: Fri, 5 Jun 2026 15:11:42 +0200 Subject: [PATCH 1/2] Basic PCI functionality --- include/drivers/driver.h | 6 - include/drivers/pci.h | 108 ++++++++++++++++ include/io/io.h | 20 +++ include/kernel/memory.h | 23 ++++ kernel/core/systems.cpp | 4 + kernel/drivers/pci.cpp | 268 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 423 insertions(+), 6 deletions(-) create mode 100644 include/drivers/pci.h create mode 100644 kernel/drivers/pci.cpp diff --git a/include/drivers/driver.h b/include/drivers/driver.h index 4970689..954dcd1 100644 --- a/include/drivers/driver.h +++ b/include/drivers/driver.h @@ -75,12 +75,6 @@ class CharacterDevice : public Device { virtual int write(const u8* buffer, usize size) = 0; }; -class PCIDevice : public Device { -public: - PCIDevice(string name, DeviceType type) : Device(name, type) { - } -}; - class Driver { public: Driver() = default; diff --git a/include/drivers/pci.h b/include/drivers/pci.h new file mode 100644 index 0000000..656299b --- /dev/null +++ b/include/drivers/pci.h @@ -0,0 +1,108 @@ +/* +* pci.h +* As part of the Avery project +* Created by Max Van den Eynde in 2026 +* -------------------------------------- +* Description: Peripheral Component Interconnect definitions +* Copyright (c) 2026 Max Van den Eynde +*/ + +#ifndef AVERY_PCI_H +#define AVERY_PCI_H +#include "driver.h" + +enum class PCIBarType { + None, + IO, + MMIO32, + MMIO64, +}; + +struct PCIBar { + PCIBarType type; + + u64 address; + u64 size; + + bool prefetchable; +}; + +class PCIDevice : public Device { +public: + PCIDevice(string name, u8 bus, u8 slot, u8 function); + + [[nodiscard]] u8 bus() const; + [[nodiscard]] u8 slot() const; + [[nodiscard]] u8 function() const; + + [[nodiscard]] u16 vendorID() const; + [[nodiscard]] u16 deviceID() const; + + [[nodiscard]] PCIBar bar(u8 index) const; + + [[nodiscard]] u8 classCode() const; + [[nodiscard]] u8 subclass() const; + [[nodiscard]] u8 progIF() const; + [[nodiscard]] u8 revisionID() const; + + [[nodiscard]] u8 interruptLine() const; + [[nodiscard]] u8 interruptPin() const; + + [[nodiscard]] bool isClass(u8 classCode, u8 subClass) const; + [[nodiscard]] bool isVendorDevice(u16 vendor, u16 device) const; + + void enableIOSpace() const; + void enableMemorySpace() const; + void enableBusMastering() const; + + void createMMIOInterface(u8 barIndex); + [[nodiscard]] mmio::Interface* mmioInterface() const; + +private: + u8 pciBus; + u8 pciSlot; + u8 pciFunction; + + u16 pciVendorID; + u16 pciDeviceID; + + u8 pciClassCode; + u8 pciSubClass; + u8 pciProgIF; + u8 pciRevisionID; + + u8 pciInterruptLine; + u8 pciInterruptPin; + + PCIBar bars[6]{}; + + [[nodiscard]] PCIBar readBAR(u8 index) const; + + mmio::Interface* interface; +}; + +namespace pci { + constexpr u16 ConfigAddress = 0xCF8; + constexpr u16 ConfigData = 0xCFC; + + inline u32 configAddress(u8 bus, u8 slot, u8 function, u8 offset) { + return (1u << 31) + | (static_cast(bus) << 16) + | (static_cast(slot) << 11) + | (static_cast(function) << 8) + | (static_cast(offset) & 0xFC); + } + + u32 read32(u8 bus, u8 slot, u8 function, u8 offset); + u16 read16(u8 bus, u8 slot, u8 function, u8 offset); + u8 read8(u8 bus, u8 slot, u8 function, u8 offset); + void write32(u8 bus, u8 slot, u8 function, u8 offset, u32 value); + + void checkBus(u8 bus); + void checkSlot(u8 bus, u8 slot); + void checkFunction(u8 bus, u8 slot, u8 function); + + void enumerateAndCreateDevices(); +} + +#endif //AVERY_PCI_H diff --git a/include/io/io.h b/include/io/io.h index ab0fecc..d63afe5 100644 --- a/include/io/io.h +++ b/include/io/io.h @@ -31,5 +31,25 @@ namespace io { return val; } + + inline void outl(u16 port, u32 value) { + asm volatile( + "outl %0, %1" + : + : "a"(value), "Nd"(port) + ); + } + + inline u32 inl(u16 port) { + u32 val; + + asm volatile( + "inl %1, %0" + : "=a"(val) + : "Nd"(port) + ); + + return val; + } } #endif //AVERY_IO_H diff --git a/include/kernel/memory.h b/include/kernel/memory.h index 7563b4f..3b5f5cd 100644 --- a/include/kernel/memory.h +++ b/include/kernel/memory.h @@ -76,6 +76,29 @@ namespace memory { UniquePtr makeUnique(Args&&... args) { return UniquePtr(new T(static_cast(args)...)); } + + template + struct RemoveReference { + using type = T; + }; + + template + struct RemoveReference { + using type = T&; + }; + + template + struct RemoveReference { + using type = T; + }; + + template + using RemoveReferenceType = typename RemoveReference::type; + + template + constexpr RemoveReferenceType&& move(T&& value) noexcept { + return static_cast&&>(value); + } } void* operator new(usize size); diff --git a/kernel/core/systems.cpp b/kernel/core/systems.cpp index 545af4b..b2d4f2d 100644 --- a/kernel/core/systems.cpp +++ b/kernel/core/systems.cpp @@ -14,6 +14,7 @@ #include "core/idt.h" #include "core/irq.h" #include "core/isr.h" +#include "drivers/pci.h" #include "kernel/memory.h" void core::initSystems(volatile struct limine_memmap_request& request) { @@ -29,5 +30,8 @@ void core::initSystems(volatile struct limine_memmap_request& request) { initIrq(); debug::log("All IRQs bound correctly"); + pci::enumerateAndCreateDevices(); + debug::log("Enumerated and created all PCI devices"); + asm volatile("sti"); } diff --git a/kernel/drivers/pci.cpp b/kernel/drivers/pci.cpp new file mode 100644 index 0000000..2c7d60c --- /dev/null +++ b/kernel/drivers/pci.cpp @@ -0,0 +1,268 @@ +/* +* pci.cpp +* As part of the Avery project +* Created by Max Van den Eynde in 2026 +* -------------------------------------- +* Description: Discover and treatment of PCI devices +* Copyright (c) 2026 Max Van den Eynde +*/ + +#include + +#include "io/io.h" +#include "kernel/debug.h" +#include "kernel/memory.h" + +namespace pci { + u32 read32(u8 bus, u8 slot, u8 function, u8 offset) { + io::outl(ConfigAddress, configAddress(bus, slot, function, offset)); + return io::inl(ConfigAddress); + } + + u16 read16(u8 bus, u8 slot, u8 function, u8 offset) { + u32 value = read32(bus, slot, function, offset); + return (value >> ((offset & 2) * 8)) & 0xFFFF; + } + + u8 read8(u8 bus, u8 slot, u8 function, u8 offset) { + u32 value = read32(bus, slot, function, offset); + return (value >> ((offset & 1) * 8)) & 0xFF; + } + + void write32(u8 bus, u8 slot, u8 function, u8 offset, u32 value) { + io::outl(ConfigAddress, configAddress(bus, slot, function, offset)); + io::outl(ConfigAddress, value); + } + + void enumerateAndCreateDevices() { + for (u16 bus = 0; bus < 256; bus++) { + checkBus(static_cast(bus)); + } + } + + void checkBus(u8 bus) { + for (u8 slot = 0; slot < 32; slot++) { + checkSlot(bus, slot); + } + } + + void checkSlot(u8 bus, u8 slot) { + u16 vendor = pci::read16(bus, slot, 0, 0x00); + + if (vendor == 0xFFFF) { + return; + } + + checkFunction(bus, slot, 0); + + u8 headerType = pci::read8(bus, slot, 0, 0x0E); + + if (headerType & 0x80) { + for (u8 function = 1; function < 8; function++) { + if (pci::read16(bus, slot, function, 0x00) != 0xFFFF) { + checkFunction(bus, slot, function); + } + } + } + } + + void checkFunction(u8 bus, u8 slot, u8 function) { + auto* device = new PCIDevice("", bus, slot, function); + debug::log("Registering "); + + DeviceManager::registerDevice(device); + } +} + +PCIDevice::PCIDevice(string name, u8 bus, u8 slot, u8 function) : Device(memory::move(name), DeviceType::PCI), + pciBus(bus), + pciSlot(slot), pciFunction(function) { + pciVendorID = pci::read16(bus, slot, function, 0x00); + pciDeviceID = pci::read16(bus, slot, function, 0x02); + + pciRevisionID = pci::read8(bus, slot, function, 0x08); + pciProgIF = pci::read8(bus, slot, function, 0x09); + pciSubClass = pci::read8(bus, slot, function, 0x0A); + pciClassCode = pci::read8(bus, slot, function, 0x0B); + + pciInterruptLine = pci::read8(bus, slot, function, 0x3C); + pciInterruptPin = pci::read8(bus, slot, function, 0x3D); + + interface = nullptr; + + for (u8 i = 0; i < 6; i++) { + bars[i] = readBAR(i); + } +} + +u8 PCIDevice::bus() const { + return pciBus; +} + +u8 PCIDevice::slot() const { + return pciSlot; +} + +u8 PCIDevice::function() const { + return pciFunction; +} + +u16 PCIDevice::vendorID() const { + return pciVendorID; +} + +u16 PCIDevice::deviceID() const { + return pciDeviceID; +} + +u8 PCIDevice::classCode() const { + return pciClassCode; +} + +u8 PCIDevice::subclass() const { + return pciSubClass; +} + +u8 PCIDevice::progIF() const { + return pciProgIF; +} + +u8 PCIDevice::revisionID() const { + return pciRevisionID; +} + +u8 PCIDevice::interruptLine() const { + return pciInterruptLine; +} + +u8 PCIDevice::interruptPin() const { + return pciInterruptPin; +} + +PCIBar PCIDevice::bar(u8 index) const { + if (index >= 6) { + return PCIBar{ + PCIBarType::None, + 0, + 0, + false + }; + } + return bars[index]; +} + +PCIBar PCIDevice::readBAR(u8 index) const { + if (index >= 6) { + return { + PCIBarType::None, + 0, + 0, + false + }; + } + + u8 offset = 0x10 + index * 4; + + u32 original = pci::read32(pciBus, pciSlot, pciFunction, offset); + + if (original == 0) { + return { + PCIBarType::None, + 0, + 0, + false + }; + } + + pci::write32(pciBus, pciSlot, pciFunction, offset, 0xFFFFFFFF); + u32 sizeMask = pci::read32(pciBus, pciSlot, pciFunction, offset); + pci::write32(pciBus, pciSlot, pciFunction, offset, original); + + PCIBar result{}; + + if (original & 0x1) { + result.type = PCIBarType::IO; + result.address = original & ~0x3ull; + result.size = ~(sizeMask & ~0x3u) + 1; + result.prefetchable = false; + return result; + } + + u8 memoryType = (original >> 1) & 0x3; + result.prefetchable = original & (1 << 3); + + if (memoryType == 0x0) { + result.type = PCIBarType::MMIO32; + result.address = original & 0xFull; + result.size = ~(sizeMask & ~0xFu) + 1; + return result; + } + + if (memoryType == 0x2) { + u32 originalHigh = pci::read32(pciBus, pciSlot, pciFunction, offset + 4); + + pci::write32(pciBus, pciSlot, pciFunction, offset + 4, 0xFFFFFFFF); + u32 sizeMaskHigh = pci::read32(pciBus, pciSlot, pciFunction, offset + 4); + pci::write32(pciBus, pciSlot, pciFunction, offset + 4, originalHigh); + + result.type = PCIBarType::MMIO64; + + result.address = ((u64)originalHigh << 32) + | (original & ~0xFull); + + u64 fullMask = + ((u64)sizeMaskHigh << 32) | + (sizeMask & ~0xFu); + + result.size = ~fullMask + 1; + return result; + } + + return { + PCIBarType::None, + 0, + 0, + false, + }; +} + +void PCIDevice::createMMIOInterface(u8 barIndex) { + PCIBar selected = bar(barIndex); + + if (selected.type != PCIBarType::MMIO32 && selected.type != PCIBarType::MMIO64) { + interface = nullptr; + return; + } + + interface = new mmio::Interface(selected.address, selected.size); +} + +mmio::Interface* PCIDevice::mmioInterface() const { + return interface; +} + +void PCIDevice::enableIOSpace() const { + u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); + command |= 1 << 0; + pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); +} + +void PCIDevice::enableMemorySpace() const { + u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); + command |= 1 << 1; + pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); +} + +void PCIDevice::enableBusMastering() const { + u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); + command |= 1 << 2; + pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); +} + +bool PCIDevice::isClass(u8 classCode, u8 subClass) const { + return pciClassCode == classCode && subClass == pciSubClass; +} + +bool PCIDevice::isVendorDevice(u16 vendor, u16 device) const { + return pciVendorID == vendor && device == pciDeviceID; +} From f6115d582bc68c80abd0d0b78fec4de27abfd9b0 Mon Sep 17 00:00:00 2001 From: Max Van den Eynde Date: Fri, 5 Jun 2026 15:34:58 +0200 Subject: [PATCH 2/2] Finished PCI descovery and registration --- README.md | 4 +- include/drivers/driver.h | 2 +- include/drivers/pci.h | 4 ++ include/kernel/console.h | 36 +++++++++++ include/kernel/debug.h | 73 ++++++++++++++++++++++ kernel/core/debug.cpp | 117 ++++++++++++++++++++++++++++-------- kernel/drivers/pci.cpp | 127 ++++++++++++++++++++++++++++++++++++--- kernel/io/console.cpp | 54 +++++++++++++++++ 8 files changed, 382 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 4efa625..af3488a 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ practices while remaining approachable to contributors and learners alike. ### Hardware discovery -- [ ] PCI enumeration -- [ ] PCI BAR support +- [x] PCI enumeration +- [x] PCI BAR support ### Storage diff --git a/include/drivers/driver.h b/include/drivers/driver.h index 954dcd1..3b20a5d 100644 --- a/include/drivers/driver.h +++ b/include/drivers/driver.h @@ -44,7 +44,7 @@ class Device { Driver* driver = nullptr; Device* parent = nullptr; -private: +protected: string deviceName; DeviceType deviceType; }; diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 656299b..9cdf9c3 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -97,12 +97,16 @@ namespace pci { u16 read16(u8 bus, u8 slot, u8 function, u8 offset); u8 read8(u8 bus, u8 slot, u8 function, u8 offset); void write32(u8 bus, u8 slot, u8 function, u8 offset, u32 value); + void write16(u8 bus, u8 slot, u8 function, u8 offset, u16 value); void checkBus(u8 bus); void checkSlot(u8 bus, u8 slot); void checkFunction(u8 bus, u8 slot, u8 function); void enumerateAndCreateDevices(); + + cstring className(u8 classCode); + cstring subclassName(u8 classCode, u8 subClass); } #endif //AVERY_PCI_H diff --git a/include/kernel/console.h b/include/kernel/console.h index 8c7b72f..d3fa4df 100644 --- a/include/kernel/console.h +++ b/include/kernel/console.h @@ -29,13 +29,49 @@ namespace out { void initFramebufferConsole(const Framebuffer& framebuffer); void print(cstring str); void print(const string& str); + void print(char c); + void print(bool value); + void print(u8 num); + void print(u16 num); + void print(u32 num); + void print(u64 num); + void print(i16 num); + void print(i32 num); + void print(i64 num); + void print(const void* ptr); void println(cstring str); void println(const string& str); + void println(); void printHex(u64 num); void printNumber(u64 num); + void printSigned(i64 num); void putChar(char c); void clear(); + template + requires ByteNumber + void print(T num) { + if constexpr (T(-1) < T(0)) { + printSigned(static_cast(num)); + } + else { + printNumber(static_cast(num)); + } + } + + template + requires(sizeof...(Args) > 1) + void print(const Args&... args) { + (print(args), ...); + } + + template + requires(sizeof...(Args) > 1) + void println(const Args&... args) { + print(args...); + putChar('\n'); + } + inline void switchTo(ConsoleOutputMode mode) { outputMode = mode; } diff --git a/include/kernel/debug.h b/include/kernel/debug.h index fc786ba..b6d7852 100644 --- a/include/kernel/debug.h +++ b/include/kernel/debug.h @@ -12,6 +12,7 @@ #pragma once #include "types.h" +#include "console.h" enum class LogType { Console, @@ -82,6 +83,78 @@ namespace debug { void log(const char* message, LogType logType = LogType::Serial); void warn(const char* message, LogType logType = LogType::Serial); void error(const char* message, LogType logType = LogType::Serial); + void writePrefix(LogType logType, cstring prefix); + void writeValue(LogType logType, cstring value); + void writeValue(LogType logType, const string& value); + void writeValue(LogType logType, char value); + void writeValue(LogType logType, bool value); + void writeValue(LogType logType, u8 value); + void writeValue(LogType logType, u16 value); + void writeValue(LogType logType, u32 value); + void writeValue(LogType logType, u64 value); + void writeValue(LogType logType, i16 value); + void writeValue(LogType logType, i32 value); + void writeValue(LogType logType, i64 value); + void writeValue(LogType logType, const void* value); + void writeLineEnd(LogType logType); + + template + requires ByteNumber + void writeValue(LogType logType, T value) { + if constexpr (T(-1) < T(0)) { + writeValue(logType, static_cast(value)); + } + else { + writeValue(logType, static_cast(value)); + } + } + + template + void writeValues(LogType logType, const Args&... args) { + (writeValue(logType, args), ...); + } + + template + requires(sizeof...(Args) > 0) + void log(LogType logType, const Args&... args) { + writePrefix(logType, "[LOG] "); + writeValues(logType, args...); + writeLineEnd(logType); + } + + template + requires(sizeof...(Args) > 1) + void log(const Args&... args) { + log(LogType::Serial, args...); + } + + template + requires(sizeof...(Args) > 0) + void warn(LogType logType, const Args&... args) { + writePrefix(logType, "[WARNING] "); + writeValues(logType, args...); + writeLineEnd(logType); + } + + template + requires(sizeof...(Args) > 1) + void warn(const Args&... args) { + warn(LogType::Serial, args...); + } + + template + requires(sizeof...(Args) > 0) + void error(LogType logType, const Args&... args) { + writePrefix(logType, "[ERROR] "); + writeValues(logType, args...); + writeLineEnd(logType); + } + + template + requires(sizeof...(Args) > 1) + void error(const Args&... args) { + error(LogType::Serial, args...); + } inline void serialError(const char* message) { error(message, LogType::Serial); diff --git a/kernel/core/debug.cpp b/kernel/core/debug.cpp index 05cd973..e4b9f18 100644 --- a/kernel/core/debug.cpp +++ b/kernel/core/debug.cpp @@ -41,44 +41,114 @@ void debug::kernelPanic(const char* message, const char* file, } void debug::log(const char* message, LogType logType) { + log(logType, message); +} + + +void debug::warn(const char* message, LogType logType) { + warn(logType, message); +} + + +void debug::error(const char* message, LogType logType) { + error(logType, message); +} + +void debug::writePrefix(LogType logType, cstring prefix) { if (logType == LogType::Serial) { - io::serialWrite("[LOG] "); - io::serialWrite(message); - io::serialWrite("\n"); + io::serialWrite(prefix); + return; } - else { + + if (prefix[1] == 'L') { out::setColor(Color::green, Color::black); - out::print("[LOG]"); - out::println(message); } -} + else if (prefix[1] == 'W') { + out::setColor(Color::yellow, Color::black); + } + else { + out::setColor(Color::red, Color::black); + } + out::print(prefix); +} -void debug::warn(const char* message, LogType logType) { +void debug::writeValue(LogType logType, cstring value) { if (logType == LogType::Serial) { - io::serialWrite("[WARNING] "); - io::serialWrite(message); - io::serialWrite("\n"); + io::serialWrite(value); + return; } - else { - out::setColor(Color::yellow, Color::black); - out::print("[WARNING] "); - out::println(message); + + out::print(value); +} + +void debug::writeValue(LogType logType, const string& value) { + writeValue(logType, value.cStr()); +} + +void debug::writeValue(LogType logType, char value) { + if (logType == LogType::Serial) { + io::serialWriteChar(value); + return; } + + out::putChar(value); } +void debug::writeValue(LogType logType, bool value) { + writeValue(logType, value ? "true" : "false"); +} -void debug::error(const char* message, LogType logType) { +void debug::writeValue(LogType logType, u8 value) { + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, u16 value) { + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, u32 value) { + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, u64 value) { if (logType == LogType::Serial) { - io::serialWrite("[ERROR] "); - io::serialWrite(message); - io::serialWrite("\n"); + io::serialWriteNumber(value); + return; } - else { - out::setColor(Color::red, Color::black); - out::print("[ERROR] "); - out::println(message); + + out::printNumber(value); +} + +void debug::writeValue(LogType logType, i16 value) { + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, i32 value) { + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, i64 value) { + if (value < 0) { + writeValue(logType, '-'); + writeValue(logType, static_cast(-(value + 1)) + 1); + return; } + + writeValue(logType, static_cast(value)); +} + +void debug::writeValue(LogType logType, const void* value) { + if (logType == LogType::Serial) { + io::serialWriteHex(reinterpret_cast(value)); + return; + } + + out::printHex(reinterpret_cast(value)); +} + +void debug::writeLineEnd(LogType logType) { + writeValue(logType, '\n'); } void debug::stackTrace(LogType type) { @@ -114,4 +184,3 @@ void debug::stackTrace(LogType type) { } - diff --git a/kernel/drivers/pci.cpp b/kernel/drivers/pci.cpp index 2c7d60c..37230b9 100644 --- a/kernel/drivers/pci.cpp +++ b/kernel/drivers/pci.cpp @@ -16,7 +16,7 @@ namespace pci { u32 read32(u8 bus, u8 slot, u8 function, u8 offset) { io::outl(ConfigAddress, configAddress(bus, slot, function, offset)); - return io::inl(ConfigAddress); + return io::inl(ConfigData); } u16 read16(u8 bus, u8 slot, u8 function, u8 offset) { @@ -26,12 +26,22 @@ namespace pci { u8 read8(u8 bus, u8 slot, u8 function, u8 offset) { u32 value = read32(bus, slot, function, offset); - return (value >> ((offset & 1) * 8)) & 0xFF; + return (value >> ((offset & 3) * 8)) & 0xFF; } void write32(u8 bus, u8 slot, u8 function, u8 offset, u32 value) { io::outl(ConfigAddress, configAddress(bus, slot, function, offset)); - io::outl(ConfigAddress, value); + io::outl(ConfigData, value); + } + + void write16(u8 bus, u8 slot, u8 function, u8 offset, u16 value) { + u32 old = read32(bus, slot, function, offset & 0xFC); + u32 shift = (offset & 2) * 8; + + old &= ~(0xFFFFu << shift); + old |= (static_cast(value) << shift); + + write32(bus, slot, function, offset & 0xFC, old); } void enumerateAndCreateDevices() { @@ -68,10 +78,101 @@ namespace pci { void checkFunction(u8 bus, u8 slot, u8 function) { auto* device = new PCIDevice("", bus, slot, function); - debug::log("Registering "); + debug::log("Registering PCI device: BUS ", bus, " SLOT ", slot, " FUNCTION ", function, " NAME ", + device->name()); DeviceManager::registerDevice(device); } + + cstring className(u8 classCode) { + switch (classCode) { + case 0x00: return "Unclassified"; + case 0x01: return "Mass Storage Controller"; + case 0x02: return "Network Controller"; + case 0x03: return "Display Controller"; + case 0x04: return "Multimedia Controller"; + case 0x05: return "Memory Controller"; + case 0x06: return "Bridge Device"; + case 0x07: return "Simple Communication Controller"; + case 0x08: return "Base System Peripheral"; + case 0x09: return "Input Device Controller"; + case 0x0A: return "Docking Station"; + case 0x0B: return "Processor"; + case 0x0C: return "Serial Bus Controller"; + case 0x0D: return "Wireless Controller"; + case 0x0E: return "Intelligent Controller"; + case 0x0F: return "Satellite Communication Controller"; + case 0x10: return "Encryption Controller"; + case 0x11: return "Signal Processing Controller"; + case 0x12: return "Processing Accelerator"; + case 0x13: return "Non-Essential Instrumentation"; + case 0x40: return "Coprocessor"; + case 0xFF: return "Vendor Specific or Unassigned"; + default: return "Unknown"; + } + } + + cstring subclassName(u8 classCode, u8 subclass) { + switch (classCode) { + case 0x01: + switch (subclass) { + case 0x00: return "SCSI Storage Controller"; + case 0x01: return "IDE Controller"; + case 0x02: return "Floppy Disk Controller"; + case 0x03: return "IPI Bus Controller"; + case 0x04: return "RAID Controller"; + case 0x05: return "ATA Controller"; + case 0x06: return "SATA Controller"; + case 0x07: return "Serial Attached SCSI Controller"; + case 0x08: return "Non-Volatile Memory Controller"; + default: return "Mass Storage Controller"; + } + + case 0x02: + switch (subclass) { + case 0x00: return "Ethernet Controller"; + default: return "Network Controller"; + } + + case 0x03: + switch (subclass) { + case 0x00: return "VGA Compatible Controller"; + case 0x01: return "XGA Controller"; + case 0x02: return "3D Controller"; + default: return "Display Controller"; + } + + case 0x06: + switch (subclass) { + case 0x00: return "Host Bridge"; + case 0x01: return "ISA Bridge"; + case 0x02: return "EISA Bridge"; + case 0x03: return "MCA Bridge"; + case 0x04: return "PCI-to-PCI Bridge"; + case 0x05: return "PCMCIA Bridge"; + case 0x06: return "NuBus Bridge"; + case 0x07: return "CardBus Bridge"; + case 0x08: return "RACEway Bridge"; + default: return "Bridge Device"; + } + + case 0x0C: + switch (subclass) { + case 0x00: return "FireWire Controller"; + case 0x01: return "ACCESS.bus Controller"; + case 0x02: return "SSA Controller"; + case 0x03: return "USB Controller"; + case 0x04: return "Fibre Channel Controller"; + case 0x05: return "SMBus Controller"; + case 0x06: return "InfiniBand Controller"; + case 0x07: return "IPMI Interface"; + case 0x08: return "SERCOS Interface"; + case 0x09: return "CANbus Controller"; + default: return "Serial Bus Controller"; + } + default: return ""; + } + } } PCIDevice::PCIDevice(string name, u8 bus, u8 slot, u8 function) : Device(memory::move(name), DeviceType::PCI), @@ -85,6 +186,16 @@ PCIDevice::PCIDevice(string name, u8 bus, u8 slot, u8 function) : Device(memory: pciSubClass = pci::read8(bus, slot, function, 0x0A); pciClassCode = pci::read8(bus, slot, function, 0x0B); + this->deviceName = "PCI Device / "; + this->deviceName.append(pci::className(pciClassCode)); + cstring subclassNameCstr = pci::subclassName(pciClassCode, pciSubClass); + string subclassName = string(subclassNameCstr); + if (!subclassName.empty()) { + this->deviceName.append(" ("); + this->deviceName.append(subclassNameCstr); + this->deviceName.append(")"); + } + pciInterruptLine = pci::read8(bus, slot, function, 0x3C); pciInterruptPin = pci::read8(bus, slot, function, 0x3D); @@ -193,7 +304,7 @@ PCIBar PCIDevice::readBAR(u8 index) const { if (memoryType == 0x0) { result.type = PCIBarType::MMIO32; - result.address = original & 0xFull; + result.address = original & ~0xFull; result.size = ~(sizeMask & ~0xFu) + 1; return result; } @@ -244,19 +355,19 @@ mmio::Interface* PCIDevice::mmioInterface() const { void PCIDevice::enableIOSpace() const { u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); command |= 1 << 0; - pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); + pci::write16(pciBus, pciSlot, pciFunction, 0x4, command); } void PCIDevice::enableMemorySpace() const { u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); command |= 1 << 1; - pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); + pci::write16(pciBus, pciSlot, pciFunction, 0x4, command); } void PCIDevice::enableBusMastering() const { u16 command = pci::read16(pciBus, pciSlot, pciFunction, 0x4); command |= 1 << 2; - pci::write32(pciBus, pciSlot, pciFunction, 0x4, command); + pci::write16(pciBus, pciSlot, pciFunction, 0x4, command); } bool PCIDevice::isClass(u8 classCode, u8 subClass) const { diff --git a/kernel/io/console.cpp b/kernel/io/console.cpp index cf04f2e..ff70863 100644 --- a/kernel/io/console.cpp +++ b/kernel/io/console.cpp @@ -45,6 +45,46 @@ void out::print(const string& str) { print(str.cStr()); } +void out::print(char c) { + putChar(c); +} + +void out::print(bool value) { + print(value ? "true" : "false"); +} + +void out::print(u8 num) { + printNumber(num); +} + +void out::print(u16 num) { + printNumber(num); +} + +void out::print(u32 num) { + printNumber(num); +} + +void out::print(u64 num) { + printNumber(num); +} + +void out::print(i16 num) { + printSigned(num); +} + +void out::print(i32 num) { + printSigned(num); +} + +void out::print(i64 num) { + printSigned(num); +} + +void out::print(const void* ptr) { + printHex(reinterpret_cast(ptr)); +} + void out::clear() { if (outputMode == ConsoleOutputMode::Framebuffer && consoleAccess != nullptr) { consoleAccess->clear(); @@ -67,6 +107,10 @@ void out::println(const string& str) { println(str.cStr()); } +void out::println() { + putChar('\n'); +} + void out::setColor(Color fg, Color bg) { if (outputMode == ConsoleOutputMode::Framebuffer && consoleAccess != nullptr) { consoleAccess->setColor(fg, bg); @@ -128,6 +172,16 @@ void out::printNumber(u64 num) { print(&buffer[index]); } +void out::printSigned(i64 num) { + if (num < 0) { + putChar('-'); + printNumber(static_cast(-(num + 1)) + 1); + return; + } + + printNumber(static_cast(num)); +} + char in::getChar() { while (!keyboard::hasChar()) { if (out::outputMode == ConsoleOutputMode::Framebuffer && GlobalFramebufferConsole != nullptr) {