Luna/kernel/src/arch/PCI.h

136 lines
2.7 KiB
C++

#pragma once
#include <luna/Types.h>
namespace PCI
{
enum Field : u32
{
VendorID = 0x00,
DeviceID = 0x02,
Command = 0x04,
Status = 0x06,
RevisionID = 0x08,
ProgIF = 0x09,
Subclass = 0x0a,
Class = 0x0b,
HeaderType = 0x0e,
BAR0 = 0x10,
BAR1 = 0x14,
BAR2 = 0x18,
BAR3 = 0x1c,
SecondaryBus = 0x19,
InterruptLine = 0x3c,
};
enum CommandField : u16
{
CMD_IO_SPACE = 1 << 0,
CMD_MEMORY_SPACE = 1 << 1,
CMD_BUS_MASTER = 1 << 2,
CMD_SPECIAL_CYCLES = 1 << 3,
CMD_MEMORY_WRITE_AND_INVALIDATE = 1 << 4,
CMD_VGA_PALETTE_SNOOP = 1 << 5,
CMD_PARITY_ERROR_RESPONSE = 1 << 6,
CMD_SERR = 1 << 8,
CMD_FAST_BACK_TO_BACK = 1 << 9,
CMD_INTERRUPT_DISABLE = 1 << 10,
};
struct BAR
{
public:
BAR(u32 raw);
bool is_iospace()
{
return m_raw & 0x01;
}
bool is_memory_space()
{
return !is_iospace();
}
u16 port()
{
return (u16)(m_raw & 0xfffffffc);
}
u8 type()
{
return (m_raw >> 1) & 0x03;
}
bool is_prefetchable()
{
return m_raw & (1 << 3);
}
u32 address_32bit()
{
return m_raw & 0xFFFFFFF0;
}
private:
u32 m_raw;
};
struct Device
{
struct ID
{
u16 vendor;
u16 device;
};
struct Type
{
u8 klass;
u8 subclass;
u8 prog_if;
};
struct Address
{
u32 bus;
u32 slot;
u32 function;
};
BAR getBAR(u8 index) const;
ID id;
Type type;
Address address;
};
typedef void (*Callback)(const Device&);
struct Match
{
i16 klass { -1 };
i16 subclass { -1 };
i16 prog_if { -1 };
};
constexpr u16 INVALID_ID = 0xFFFF;
// Architecture-dependent.
u8 read8(const Device::Address& address, u32 field);
u16 read16(const Device::Address& address, u32 field);
u32 read32(const Device::Address& address, u32 field);
void write8(const Device::Address& address, u32 field, u8 value);
void write16(const Device::Address& address, u32 field, u16 value);
void write32(const Device::Address& address, u32 field, u32 value);
Device::ID read_id(const Device::Address& address);
Device::Type read_type(const Device::Address& address);
void scan(Callback callback, Match match);
}