sortix-mirror/kernel/include/sortix/kernel/pci.h

189 lines
7.4 KiB
C++

/*
* Copyright (c) 2011-2017 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* sortix/kernel/pci.h
* Functions for handling PCI devices.
*/
#ifndef _INCLUDE_SORTIX_KERNEL_PCI_H
#define _INCLUDE_SORTIX_KERNEL_PCI_H
#include <endian.h>
#include <stdint.h>
namespace Sortix {
typedef struct
{
uint16_t deviceid;
uint16_t vendorid;
} pciid_t;
typedef struct
{
uint8_t classid;
uint8_t subclassid;
uint8_t progif;
uint8_t revid;
} pcitype_t;
// memset(&pcifind, 255, sizeof(pcifind)) and fill out rest.
struct pcifind_t
{
public:
pcifind_t() {}
constexpr pcifind_t(void* context_, uint16_t vendorid_, uint16_t deviceid_,
uint8_t classid_ = 0xff, uint8_t subclassid_ = 0xff,
uint8_t progif_ = 0xff, uint8_t revid_ = 0xff) :
context(context_), vendorid(vendorid_), deviceid(deviceid_),
classid(classid_), subclassid(subclassid_), progif(progif_),
revid(revid_)
{
}
public:
void* context;
uint16_t vendorid;
uint16_t deviceid;
uint8_t classid;
uint8_t subclassid;
uint8_t progif;
uint8_t revid;
};
static const uint8_t PCIBAR_TYPE_IOSPACE = 0x0 << 1 | 0x1 << 0;
static const uint8_t PCIBAR_TYPE_16BIT = 0x1 << 1 | 0x0 << 0;
static const uint8_t PCIBAR_TYPE_32BIT = 0x0 << 1 | 0x0 << 0;
static const uint8_t PCIBAR_TYPE_64BIT = 0x2 << 1 | 0x0 << 0;
typedef struct
{
public:
uint64_t addr_raw;
uint64_t size_raw;
public:
uint64_t addr() const { return is_iospace() ?
addr_raw & 0xFFFFFFFFFFFFFFFC :
addr_raw & 0xFFFFFFFFFFFFFFF0; }
uint64_t size() const { return size_raw & 0xFFFFFFFFFFFFFFFF; }
uint8_t type() const { return (addr_raw & 3) == PCIBAR_TYPE_IOSPACE ?
(addr_raw & 3) : (addr_raw & 0x7); }
uint32_t ioaddr() const { return addr_raw & 0xFFFFFFFC; };
bool is_prefetchable() const { return addr_raw & 0x8; }
bool is_iospace() const { return type() == PCIBAR_TYPE_IOSPACE; }
bool is_16bit() const { return type() == PCIBAR_TYPE_16BIT; }
bool is_32bit() const { return type() == PCIBAR_TYPE_32BIT; }
bool is_64bit() const { return type() == PCIBAR_TYPE_64BIT; }
bool is_mmio() const { return is_16bit() || is_32bit() || is_64bit(); }
} pcibar_t;
static const uint8_t PCIFIELD_VENDOR_ID = 0x00;
static const uint8_t PCIFIELD_DEVICE_ID = 0x02;
static const uint8_t PCIFIELD_COMMAND = 0x04;
static const uint8_t PCIFIELD_STATUS = 0x06;
static const uint8_t PCIFIELD_REVISION_ID = 0x08;
static const uint8_t PCIFIELD_PROG_IF = 0x09;
static const uint8_t PCIFIELD_SUBCLASS = 0x0A;
static const uint8_t PCIFIELD_CLASS = 0x0B;
static const uint8_t PCIFIELD_CACHE_LINE_SIZE = 0x0C;
static const uint8_t PCIFIELD_LATENCY_TIMER = 0x0D;
static const uint8_t PCIFIELD_HEADER_TYPE = 0x0E;
static const uint8_t PCIFIELD_BIST = 0x0F;
static const uint8_t PCIFIELD_RAW_BAR0 = 0x10;
static const uint8_t PCIFIELD_RAW_BAR1 = 0x14;
static const uint8_t PCIFIELD_RAW_BAR2 = 0x18;
static const uint8_t PCIFIELD_PRIMARY_BUS_NUMBER = 0x18;
static const uint8_t PCIFIELD_SECONDARY_BUS_NUMBER = 0x19;
static const uint8_t PCIFIELD_SUBORDINATE_BUS_NUMBER = 0x1A;
static const uint8_t PCIFIELD_SECONDARY_LATENCY_TIMER = 0x1B;
static const uint8_t PCIFIELD_RAW_BAR3 = 0x1C;
static const uint8_t PCIFIELD_IO_BASE = 0x1C;
static const uint8_t PCIFIELD_IO_LIMIT = 0x1D;
static const uint8_t PCIFIELD_SECONDARY_STATUS = 0x1E;
static const uint8_t PCIFIELD_RAW_BAR4 = 0x20;
static const uint8_t PCIFIELD_MEMORY_BASE = 0x20;
static const uint8_t PCIFIELD_MEMORY_LIMIT = 0x22;
static const uint8_t PCIFIELD_RAW_BAR5 = 0x24;
static const uint8_t PCIFIELD_PREFETCHABLE_MEMORY_BASE = 0x24;
static const uint8_t PCIFIELD_PREFETCHABLE_MEMORY_LIMIT = 0x26;
static const uint8_t PCIFIELD_CARDBUS_CIS_POINTER = 0x28;
static const uint8_t PCIFIELD_PREFETCHABLE_BASE_UPPER_BITS = 0x28;
static const uint8_t PCIFIELD_SUBSYSTEM_VENDOR_ID = 0x2C;
static const uint8_t PCIFIELD_PREFETCHABLE_LIMIT_UPPER_BITS = 0x2C;
static const uint8_t PCIFIELD_SUBSYSTEM_ID = 0x2E;
static const uint8_t PCIFIELD_EXPANSION_ROM_BASE_ADDRESS = 0x30;
static const uint8_t PCIFIELD_CAPABILITIES = 0x34;
static const uint8_t PCIFIELD_EXPANSION_ROM_BASE_ADDRESS_PCI_BRIDGE = 0x38;
static const uint8_t PCIFIELD_INTERRUPT_LINE = 0x3C;
static const uint8_t PCIFIELD_INTERRUPT_PIN = 0x3D;
static const uint8_t PCIFIELD_MIN_GRANT = 0x3E;
static const uint8_t PCIFIELD_MAX_LATENCY = 0x3F;
static const uint8_t PCIFIELD_BRIDGE_CONTROL = 0x3E;
static const uint16_t PCIFIELD_COMMAND_IO_SPACE = 1 << 0;
static const uint16_t PCIFIELD_COMMAND_MEMORY_SPACE = 1 << 1;
static const uint16_t PCIFIELD_COMMAND_BUS_MASTER = 1 << 2;
static const uint16_t PCIFIELD_COMMAND_SPECIAL_CYCLES = 1 << 3;
static const uint16_t PCIFIELD_COMMAND_MEMORY_WRITE_AND_INVALIDATE = 1 << 4;
static const uint16_t PCIFIELD_COMMAND_VGA_PALETTE_SNOOP = 1 << 5;
static const uint16_t PCIFIELD_COMMAND_PARITY_ERROR_RESPONSE = 1 << 6;
static const uint16_t PCIFIELD_COMMAND_SERR = 1 << 8;
static const uint16_t PCIFIELD_COMMAND_FAST_BACK_TO_BACK = 1 << 9;
static const uint16_t PCIFIELD_COMMAND_INTERRUPT_DISABLE = 1 << 10;
namespace PCI {
void Init();
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func);
void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */);
uint8_t Read8(uint32_t devaddr, uint8_t off); // Host endian
uint16_t Read16(uint32_t devaddr, uint8_t off); // Host endian
uint32_t Read32(uint32_t devaddr, uint8_t off); // Host endian
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off); // PCI endian
void Write8(uint32_t devaddr, uint8_t off, uint8_t val); // Host endian
void Write16(uint32_t devaddr, uint8_t off, uint16_t val); // Host endian
void Write32(uint32_t devaddr, uint8_t off, uint32_t val); // Host endian
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val); // PCI endian
pciid_t GetDeviceId(uint32_t devaddr);
pcitype_t GetDeviceType(uint32_t devaddr);
void Search(bool (*callback)(uint32_t devaddr,
const pciid_t* id,
const pcitype_t* type,
void* context,
void* pattern_context),
void* context,
const pcifind_t* patterns,
size_t pattern_count);
uint32_t SearchForDevices(pcifind_t pcifind, uint32_t last = 0);
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar);
pcibar_t GetExpansionROM(uint32_t devaddr);
void EnableExpansionROM(uint32_t devaddr);
void DisableExpansionROM(uint32_t devaddr);
bool IsExpansionROMEnabled(uint32_t devaddr);
uint8_t SetupInterruptLine(uint32_t devaddr);
void EnableBusMaster(uint32_t devaddr);
void DisableBusMaster(uint32_t devaddr);
void EnableMemoryWrite(uint32_t devaddr);
void DisableMemoryWrite(uint32_t devaddr);
void EnableInterruptLine(uint32_t devaddr);
void DisableInterruptLine(uint32_t devaddr);
uint8_t GetInterruptIndex(uint32_t devaddr);
} // namespace PCI
} // namespace Sortix
#endif