65 lines
1.8 KiB
C++
65 lines
1.8 KiB
C++
#include "arch/PCI.h"
|
|
#include "arch/x86_64/IO.h"
|
|
#include <luna/Check.h>
|
|
#include <luna/Ignore.h>
|
|
|
|
#define PCI_ADDRESS_PORT 0xCF8
|
|
#define PCI_VALUE_PORT 0xCFC
|
|
|
|
static inline constexpr u32 make_pci_address(const PCI::Device::Address& address, u32 field)
|
|
{
|
|
return 0x80000000 | (address.bus << 16) | (address.slot << 11) | (address.function << 8) | ((field)&0xFC);
|
|
}
|
|
|
|
namespace PCI
|
|
{
|
|
u8 read8(const Device::Address& address, u32 field)
|
|
{
|
|
IO::outl(PCI_ADDRESS_PORT, make_pci_address(address, field));
|
|
return IO::inb(PCI_VALUE_PORT + (field & 3));
|
|
}
|
|
|
|
u16 read16(const Device::Address& address, u32 field)
|
|
{
|
|
IO::outl(PCI_ADDRESS_PORT, make_pci_address(address, field));
|
|
return IO::inw(PCI_VALUE_PORT + (field & 2));
|
|
}
|
|
|
|
u32 read32(const Device::Address& address, u32 field)
|
|
{
|
|
IO::outl(PCI_ADDRESS_PORT, make_pci_address(address, field));
|
|
return IO::inl(PCI_VALUE_PORT);
|
|
}
|
|
|
|
void write8(const Device::Address& address, u32 field, u8 value)
|
|
{
|
|
u8 offset = (u8)(field & ~0x3);
|
|
union {
|
|
u8 split[4];
|
|
u32 full;
|
|
};
|
|
full = read32(address, offset);
|
|
split[(field & 0x3)] = value;
|
|
write32(address, offset, full);
|
|
}
|
|
|
|
void write16(const Device::Address& address, u32 field, u16 value)
|
|
{
|
|
u8 offset = (u8)(field & ~0x3);
|
|
union {
|
|
u8 split[4];
|
|
u32 full;
|
|
};
|
|
full = read32(address, offset);
|
|
split[(field & 0x3)] = (u8)(value >> 8);
|
|
split[(field & 0x3) + 1] = (u8)(value & 0xff);
|
|
write32(address, offset, full);
|
|
}
|
|
|
|
void write32(const Device::Address& address, u32 field, u32 value)
|
|
{
|
|
IO::outl(PCI_ADDRESS_PORT, make_pci_address(address, field));
|
|
IO::outl(PCI_VALUE_PORT, value);
|
|
}
|
|
}
|