2020-08-22 23:50:10 +00:00
# pragma once
2021-07-04 20:47:09 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2020-08-22 23:50:10 +00:00
# include <stdint.h>
# include <stddef.h>
/************************
* * * Team Kitty , 2020 * * *
* * * Chroma * * *
* * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all of the structures and definitions
* required to compatibly access the PCI bus ,
* as well as set up new PCI devices , PCI bridges , and manipulate
* the connections of PCI lanes .
*/
# define PCI_CONFIG_ADDRESS 0xCF8
# define PCI_CONFIG_DATA 0xCFC
2021-03-19 02:18:39 +00:00
const char * PCIGetDeviceName_Subclass ( uint8_t DeviceClass , uint8_t Subclass , uint8_t ProgrammableInterface ) ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
const char * PCIGetClassName ( uint8_t DeviceClass ) ;
2020-08-22 23:50:10 +00:00
2020-08-23 01:32:47 +00:00
void PCIEnumerate ( ) ;
2020-08-22 23:50:10 +00:00
2020-08-23 01:32:47 +00:00
uint32_t PCIReadConfig ( uint8_t bus , uint8_t slot , uint8_t function , uint8_t offset ) ;
2020-08-22 23:50:10 +00:00
typedef struct __attribute__ ( ( packed ) ) {
2021-03-19 02:18:39 +00:00
uint8_t IOMapped : 1 ; // Device can respond to I/O access
uint8_t MMIOMapped : 1 ; // Device can respond to memory access (device is MMIO mapped)
uint8_t IsBusMaster : 1 ; // Device is Bus Master; can generate PCI addresses
uint8_t MonitorSpecialCycle : 1 ; // Device can monitor Special Cycle
uint8_t AllowMemWriteInvalidate : 1 ; // Device can generate Memory Write And Invalidate commands; else Memory Write must be used
uint8_t SnoopVGA : 1 ; // Device snoops the VGA palette on write; else is treated like a normal access
uint8_t RespondsParityError : 1 ; // Device responds to Parity Errors by setting PERR#; else will set pci_status#ParityError and continue.
2020-08-22 23:50:10 +00:00
uint8_t _reserved : 1 ; // Hardwired to 0
2021-03-19 02:18:39 +00:00
uint8_t SystemErr : 1 ; // Enable SERR# driver; System ERRor
uint8_t FastBack2Back : 1 ; // Device is allowed to generate fast back-to-back transactions to other agents.
uint8_t DisableInterrupt : 1 ; // Disable assertion of INTx# signal; else enable.
2020-08-22 23:50:10 +00:00
} pci_command_t ;
typedef struct __attribute__ ( ( packed ) ) {
uint8_t _reserved : 3 ; // 3 bits hardwired to 0
2021-03-19 02:18:39 +00:00
uint8_t InterruptActive : 1 ; // State of device's INTx# signal. If pci_command#DisableInterrupt is 0 and this is 1, the signal will be asserted.
uint8_t Capabilities : 1 ; // If set, device will implement New Capabilities list at 0x34 offset.
uint8_t Mhz66Capable : 1 ; // Device can run at 66MHz. Else, device will run at 33MHz.
2020-08-22 23:50:10 +00:00
uint8_t _reserved1 : 1 ; // Reserved as of 3.0, Used in 2.1 as "Supports User Definable Features"
2021-03-19 02:18:39 +00:00
uint8_t FastBack2Back : 1 ; // Device is allowed to accept fast back-to-back transactions from other agents.
uint8_t MasterParityError : 1 ; // Only set when PERR# is asserted by the Bus Master while pci_command#RespondsParityError is set.
uint8_t DEVSELTiming : 2 ; // Read-Only; represents the slowest time a device will assert DEVSEL#. 00 = fast, 01 = medium, 11 = slow.
uint8_t TargetAborted : 1 ; // Target device terminated transaction via Target-Abort
uint8_t ReceivedTargetAbort : 1 ; // Master's connection was terminated by Target-Abort
uint8_t ReceivedMasterAbort : 1 ; // Master's connection was terminated by Master-Abort
uint8_t SystemAssertedError : 1 ; // Device asserted SERR#
uint8_t ParityError : 1 ; // Device detected parity error. Parity error may not be handled.
2020-08-22 23:50:10 +00:00
} pci_status_t ;
typedef struct __attribute__ ( ( packed ) ) {
2021-03-19 02:18:39 +00:00
uint16_t VendorID ; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid.
uint16_t DeviceID ; // 16 bit Device ID allocated by the vendor.
pci_command_t Command ; // 16 bit PCI_COMMAND register.
pci_status_t Status ; // 16 bit PCI_STATUS register.
uint8_t RevisionID ; // 8 bit register, revision identifier specified by vendor.
uint8_t ProgrammingInterface ; // 8 bit register, identifies any programming interface the device may have.
uint8_t Subclass ; // 8 bit Subclass code; identifies the specific function of the device
uint8_t ClassCode ; // 8 bit Class Code; identifies the function of the device
uint8_t CacheLine ; // 8 bit; specifies system cache line size in 32-bit blocks. Devices can limit this. Unsupported values are treated as 0.
uint8_t LatencyTimer ; // 8 bit; specifies latency timer in (bus clock) units.
uint8_t HeaderType ; // 8 bit; identifies the layout of the header and the type of device; 00 = device, 01 = pci-pci bridge, 11 = CardBus bridge. Multi-function defined by bit 7.
uint8_t BuiltInSelfTest ; // 8 bit; status and control of a device's built-in self-test (BIST)
2020-08-22 23:50:10 +00:00
} pci_header_common_t ;
typedef struct __attribute__ ( ( packed ) ) {
// pci_header_common_t first, then..
2021-03-19 02:18:39 +00:00
uint32_t BARs [ 6 ] ; // 6 x 32 bit Base Address Registers (BARs)
uint32_t CISPtr ; // Points to Card Information Structure for PCI devices that share silicon with CardBus
uint16_t SubsysVendor ;
uint16_t SubsysID ;
uint32_t ExpansionBAR ; // Points to the base of an Expansion ROM.
uint8_t Capabilities ; // The pointer generated by pci_status#capabilities_list
2020-08-22 23:50:10 +00:00
uint8_t _reserved [ 3 ] ; // 24 bit reserved at top end of register.
uint32_t _reserved2 ;
2021-03-19 02:18:39 +00:00
uint8_t InterruptPin ; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
uint8_t InterruptActive ; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
uint8_t MinimumTimeshare ; // Specifies the length of the burst period, in quarter-microsecond units
uint8_t MaxmimumTimeshare ; // Specifies how often the device accesses the PCI bus - in quarter-microseconds
2020-08-22 23:50:10 +00:00
} pci_header_device_t ;
typedef struct __attribute__ ( ( packed ) ) {
// pci_header_common_t first
2021-03-19 02:18:39 +00:00
uint32_t BARs [ 2 ] ;
uint8_t PrimaryBus ; // Primary Bus Number.
uint8_t SecondaryBus ; // Secondary Bus Number.
uint8_t SubordinateBus ; // Subordinate Bus Number.
uint8_t LatencyTimer ; // Secondary Latency Timer.
uint8_t IOBaseLow ; // IO Base is 24 bits. This is lower 8.
uint8_t IOLimitLow ; // IO Limit is 24 bits. This is lower 8.
pci_status_t SecondaryStatus ; // Secondary Status.
uint16_t MemoryBase ;
uint16_t MemoryLimit ;
uint16_t PrefetchBaseLow ; // Prefetchable Memory Base is 48 bits. This is lower 16.
uint16_t PrefetchLimitLow ; // Prefetchable Memory Limit is 48 bits. This is lower 16.
uint32_t PrefetchBaseHigh ; // Prefetchable Memory Base is 48 bits. This is upper 32.
uint32_t PrefetchLimitHigh ; // Prefetchable Memory Limit is 48 bits. This is upper 32.
uint16_t IOBaseHigh ; // IO Base is 24 bits. This is upper 16.
uint16_t IOLimitHigh ; // IO Limit is 24 bits. This is upper 16.
uint8_t Capabilities ; // Pointer generated by pci_status#capabilities_list
2020-08-22 23:50:10 +00:00
uint8_t _reserved [ 3 ] ; // 24 reserved bits.
2021-03-19 02:18:39 +00:00
uint32_t ExpansionBAR ; // Base of Expansion ROM.
uint8_t InterruptPin ; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
uint8_t InterruptActive ; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
uint16_t BridgeControl ;
2020-08-22 23:50:10 +00:00
} pci_header_bridge_t ;
typedef struct {
uint16_t segment ;
uint8_t bus ;
uint8_t slot ;
uint8_t function ;
} pci_address_t ;
typedef struct {
2021-03-19 02:18:39 +00:00
uint8_t Present : 1 ;
uint8_t MMIO : 1 ;
2020-08-22 23:50:10 +00:00
union {
2021-03-19 02:18:39 +00:00
size_t Address ;
uint16_t Port ;
2020-08-22 23:50:10 +00:00
} ;
2021-03-19 02:18:39 +00:00
size_t Length ;
2020-08-22 23:50:10 +00:00
} pci_bar_t ;
2021-03-19 02:18:39 +00:00
typedef struct pci_device {
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
struct pci_dev * Parent ; // Parent of the device (for PCI hubs / splitters)
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
uint16_t DeviceID ;
uint16_t VendorID ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
uint8_t DeviceClass ;
uint8_t Subclass ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
uint8_t ProgrammableInterface ;
2020-08-22 23:50:10 +00:00
pci_address_t address ;
2021-03-19 02:18:39 +00:00
pci_bar_t BARs [ 6 ] ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
int IRQ ; // The IRQ of the device if already handled
2020-08-22 23:50:10 +00:00
// The headers!
2021-03-19 02:18:39 +00:00
volatile pci_header_common_t * Header ;
2020-08-22 23:50:10 +00:00
union { // The device can only be one of these at a time, but they both form part of the config space.
volatile pci_header_bridge_t * bridge ;
volatile pci_header_device_t * device ;
} ;
2021-03-19 02:18:39 +00:00
struct pci_dev * * Children ; // If this device is a hub, it has children...
2020-08-22 23:50:10 +00:00
// acpi_node_t acpi;
2021-03-19 02:18:39 +00:00
} pci_device_t ;
2020-08-22 23:50:10 +00:00
typedef struct {
pci_address_t key ;
2021-03-19 02:18:39 +00:00
pci_device_t * value ;
2020-08-22 23:50:10 +00:00
} pci_entry_t ;
2021-03-19 02:18:39 +00:00
extern pci_device_t * * pci_root_devices ;
2021-07-04 20:47:09 +00:00
extern pci_entry_t * pci_map ;
# ifdef __cplusplus
}
# endif