Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 1 addition & 7 deletions include/drivers/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Device {
Driver* driver = nullptr;
Device* parent = nullptr;

private:
protected:
string deviceName;
DeviceType deviceType;
};
Expand Down Expand Up @@ -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;
Expand Down
112 changes: 112 additions & 0 deletions include/drivers/pci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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<u32>(bus) << 16)
| (static_cast<u32>(slot) << 11)
| (static_cast<u32>(function) << 8)
| (static_cast<u32>(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 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
20 changes: 20 additions & 0 deletions include/io/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
36 changes: 36 additions & 0 deletions include/kernel/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T>
requires ByteNumber<T>
void print(T num) {
if constexpr (T(-1) < T(0)) {
printSigned(static_cast<i64>(num));
}
else {
printNumber(static_cast<u64>(num));
}
}

template <typename... Args>
requires(sizeof...(Args) > 1)
void print(const Args&... args) {
(print(args), ...);
}

template <typename... Args>
requires(sizeof...(Args) > 1)
void println(const Args&... args) {
print(args...);
putChar('\n');
}

inline void switchTo(ConsoleOutputMode mode) {
outputMode = mode;
}
Expand Down
73 changes: 73 additions & 0 deletions include/kernel/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#pragma once
#include "types.h"
#include "console.h"

enum class LogType {
Console,
Expand Down Expand Up @@ -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 <typename T>
requires ByteNumber<T>
void writeValue(LogType logType, T value) {
if constexpr (T(-1) < T(0)) {
writeValue(logType, static_cast<i64>(value));
}
else {
writeValue(logType, static_cast<u64>(value));
}
}

template <typename... Args>
void writeValues(LogType logType, const Args&... args) {
(writeValue(logType, args), ...);
}

template <typename... Args>
requires(sizeof...(Args) > 0)
void log(LogType logType, const Args&... args) {
writePrefix(logType, "[LOG] ");
writeValues(logType, args...);
writeLineEnd(logType);
}

template <typename... Args>
requires(sizeof...(Args) > 1)
void log(const Args&... args) {
log(LogType::Serial, args...);
}

template <typename... Args>
requires(sizeof...(Args) > 0)
void warn(LogType logType, const Args&... args) {
writePrefix(logType, "[WARNING] ");
writeValues(logType, args...);
writeLineEnd(logType);
}

template <typename... Args>
requires(sizeof...(Args) > 1)
void warn(const Args&... args) {
warn(LogType::Serial, args...);
}

template <typename... Args>
requires(sizeof...(Args) > 0)
void error(LogType logType, const Args&... args) {
writePrefix(logType, "[ERROR] ");
writeValues(logType, args...);
writeLineEnd(logType);
}

template <typename... Args>
requires(sizeof...(Args) > 1)
void error(const Args&... args) {
error(LogType::Serial, args...);
}

inline void serialError(const char* message) {
error(message, LogType::Serial);
Expand Down
23 changes: 23 additions & 0 deletions include/kernel/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,29 @@ namespace memory {
UniquePtr<T> makeUnique(Args&&... args) {
return UniquePtr<T>(new T(static_cast<Args&&>(args)...));
}

template <typename T>
struct RemoveReference {
using type = T;
};

template <typename T>
struct RemoveReference<T&> {
using type = T&;
};

template <typename T>
struct RemoveReference<T&&> {
using type = T;
};

template <typename T>
using RemoveReferenceType = typename RemoveReference<T>::type;

template <typename T>
constexpr RemoveReferenceType<T>&& move(T&& value) noexcept {
return static_cast<RemoveReferenceType<T>&&>(value);
}
}

void* operator new(usize size);
Expand Down
Loading
Loading