#ifndef _PCIVAR_H_
#define _PCIVAR_H_
#include <sys/power.h>
#include <sys/queue.h>
#include <sys/systm.h>
#define PCI_DOMAINMAX 65535
#define PCI_BUSMAX 255
#define PCI_SLOTMAX 31
#define PCI_FUNCMAX 7
#define PCI_REGMAX 255
#define PCI_MAXMAPS_0 6
#define PCI_MAXMAPS_1 2
#define PCI_MAXMAPS_2 1
typedef uint64_t pci_addr_t;
struct pcicfg_pp {
uint16_t pp_cap;
uint8_t pp_status;
uint8_t pp_pmcsr;
uint8_t pp_data;
};
struct vpd_readonly {
char keyword[2];
char *value;
};
struct vpd_write {
char keyword[2];
char *value;
int start;
int len;
};
struct pcicfg_vpd {
uint8_t vpd_reg;
char vpd_cached;
char *vpd_ident;
int vpd_rocnt;
struct vpd_readonly *vpd_ros;
int vpd_wcnt;
struct vpd_write *vpd_w;
};
struct pcicfg_msi {
uint16_t msi_ctrl;
uint8_t msi_location;
uint8_t msi_msgnum;
int msi_alloc;
uint64_t msi_addr;
uint16_t msi_data;
u_int msi_handlers;
};
struct msix_vector {
TAILQ_ENTRY(msix_vector) mv_link;
uint64_t mv_address;
uint32_t mv_data;
int mv_rid;
};
TAILQ_HEAD(msix_vectorlist, msix_vector);
struct pcicfg_msix {
uint16_t msix_ctrl;
uint16_t msix_msgnum;
uint8_t msix_location;
uint8_t msix_table_bar;
uint8_t msix_pba_bar;
uint32_t msix_table_offset;
uint32_t msix_pba_offset;
int msix_alloc;
struct resource *msix_table_res;
struct resource *msix_pba_res;
struct msix_vectorlist msix_vectors;
};
struct pcicfg_ht {
uint8_t ht_slave;
uint8_t ht_msimap;
uint16_t ht_msictrl;
uint64_t ht_msiaddr;
};
struct pcicfg_expr {
uint8_t expr_ptr;
uint16_t expr_cap;
uint32_t expr_slotcap;
};
struct pcicfg_pcix {
uint8_t pcix_ptr;
};
typedef struct pcicfg {
device_t dev;
uint32_t bar[PCI_MAXMAPS_0];
uint32_t bios;
uint16_t subvendor;
uint16_t subdevice;
uint16_t vendor;
uint16_t device;
uint16_t cmdreg;
uint16_t statreg;
uint8_t baseclass;
uint8_t subclass;
uint8_t progif;
uint8_t revid;
uint8_t hdrtype;
uint8_t cachelnsz;
uint8_t intpin;
uint8_t intline;
uint8_t mingnt;
uint8_t maxlat;
uint8_t lattimer;
uint8_t mfdev;
uint8_t nummaps;
uint32_t domain;
uint8_t bus;
uint8_t slot;
uint8_t func;
uint8_t dummy;
struct pcicfg_pp pp;
struct pcicfg_vpd vpd;
struct pcicfg_msi msi;
struct pcicfg_msix msix;
struct pcicfg_ht ht;
struct pcicfg_expr expr;
struct pcicfg_pcix pcix;
} pcicfgregs;
typedef struct {
pci_addr_t pmembase;
pci_addr_t pmemlimit;
uint32_t membase;
uint32_t memlimit;
uint32_t iobase;
uint32_t iolimit;
uint16_t secstat;
uint16_t bridgectl;
uint8_t seclat;
} pcih1cfgregs;
typedef struct {
uint32_t membase0;
uint32_t memlimit0;
uint32_t membase1;
uint32_t memlimit1;
uint32_t iobase0;
uint32_t iolimit0;
uint32_t iobase1;
uint32_t iolimit1;
uint32_t pccardif;
uint16_t secstat;
uint16_t bridgectl;
uint8_t seclat;
} pcih2cfgregs;
extern uint32_t pci_numdevs;
#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
struct pci_devinfo {
STAILQ_ENTRY(pci_devinfo) pci_links;
struct resource_list resources;
pcicfgregs cfg;
struct pci_conf conf;
};
#endif
#ifdef _SYS_BUS_H_
#include "pci_if.h"
#define PCI_RF_DENSE 0x10000
#define PCI_RF_BWX 0x20000
enum pci_device_ivars {
PCI_IVAR_SUBVENDOR,
PCI_IVAR_SUBDEVICE,
PCI_IVAR_VENDOR,
PCI_IVAR_DEVICE,
PCI_IVAR_DEVID,
PCI_IVAR_CLASS,
PCI_IVAR_SUBCLASS,
PCI_IVAR_PROGIF,
PCI_IVAR_REVID,
PCI_IVAR_INTPIN,
PCI_IVAR_IRQ,
PCI_IVAR_DOMAIN,
PCI_IVAR_BUS,
PCI_IVAR_SLOT,
PCI_IVAR_FUNCTION,
PCI_IVAR_ETHADDR,
PCI_IVAR_CMDREG,
PCI_IVAR_CACHELNSZ,
PCI_IVAR_MINGNT,
PCI_IVAR_MAXLAT,
PCI_IVAR_LATTIMER,
PCI_IVAR_PCIXCAP_PTR,
PCI_IVAR_PCIECAP_PTR,
PCI_IVAR_VPDCAP_PTR
};
#define PCI_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(pci, var, PCI, ivar, type)
PCI_ACCESSOR(subvendor, SUBVENDOR, uint16_t)
PCI_ACCESSOR(subdevice, SUBDEVICE, uint16_t)
PCI_ACCESSOR(vendor, VENDOR, uint16_t)
PCI_ACCESSOR(device, DEVICE, uint16_t)
PCI_ACCESSOR(devid, DEVID, uint32_t)
PCI_ACCESSOR(class, CLASS, uint8_t)
PCI_ACCESSOR(subclass, SUBCLASS, uint8_t)
PCI_ACCESSOR(progif, PROGIF, uint8_t)
PCI_ACCESSOR(revid, REVID, uint8_t)
PCI_ACCESSOR(intpin, INTPIN, uint8_t)
PCI_ACCESSOR(irq, IRQ, uint8_t)
PCI_ACCESSOR(domain, DOMAIN, uint32_t)
PCI_ACCESSOR(bus, BUS, uint8_t)
PCI_ACCESSOR(slot, SLOT, uint8_t)
PCI_ACCESSOR(function, FUNCTION, uint8_t)
PCI_ACCESSOR(ether, ETHADDR, uint8_t *)
PCI_ACCESSOR(cmdreg, CMDREG, uint8_t)
PCI_ACCESSOR(cachelnsz, CACHELNSZ, uint8_t)
PCI_ACCESSOR(mingnt, MINGNT, uint8_t)
PCI_ACCESSOR(maxlat, MAXLAT, uint8_t)
PCI_ACCESSOR(lattimer, LATTIMER, uint8_t)
PCI_ACCESSOR(pcixcap_ptr, PCIXCAP_PTR, uint8_t)
PCI_ACCESSOR(pciecap_ptr, PCIECAP_PTR, uint8_t)
PCI_ACCESSOR(vpdcap_ptr, VPDCAP_PTR, uint8_t)
#undef PCI_ACCESSOR
static __inline uint32_t
pci_read_config(device_t dev, int reg, int width)
{
return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width);
}
static __inline void
pci_write_config(device_t dev, int reg, uint32_t val, int width)
{
PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width);
}
enum pcib_device_ivars {
PCIB_IVAR_DOMAIN,
PCIB_IVAR_BUS
};
#define PCIB_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(pcib, var, PCIB, ivar, type)
PCIB_ACCESSOR(domain, DOMAIN, uint32_t)
PCIB_ACCESSOR(bus, BUS, uint32_t)
#undef PCIB_ACCESSOR
#define PCI_INVALID_IRQ 255
#define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ)
static __inline int
pci_enable_busmaster(device_t dev)
{
return(PCI_ENABLE_BUSMASTER(device_get_parent(dev), dev));
}
static __inline int
pci_disable_busmaster(device_t dev)
{
return(PCI_DISABLE_BUSMASTER(device_get_parent(dev), dev));
}
static __inline int
pci_enable_io(device_t dev, int space)
{
return(PCI_ENABLE_IO(device_get_parent(dev), dev, space));
}
static __inline int
pci_disable_io(device_t dev, int space)
{
return(PCI_DISABLE_IO(device_get_parent(dev), dev, space));
}
static __inline int
pci_get_vpd_ident(device_t dev, const char **identptr)
{
return(PCI_GET_VPD_IDENT(device_get_parent(dev), dev, identptr));
}
static __inline int
pci_get_vpd_readonly(device_t dev, const char *kw, const char **identptr)
{
return(PCI_GET_VPD_READONLY(device_get_parent(dev), dev, kw, identptr));
}
static __inline int
pci_is_vga_ioport_range(u_long start, u_long end)
{
return (((start >= 0x3b0 && end <= 0x3bb) ||
(start >= 0x3c0 && end <= 0x3df)) ? 1 : 0);
}
static __inline int
pci_is_vga_memory_range(u_long start, u_long end)
{
return ((start >= 0xa0000 && end <= 0xbffff) ? 1 : 0);
}
int pcie_slot_implemented(device_t);
void pcie_set_max_readrq(device_t, uint16_t);
uint16_t pcie_get_max_readrq(device_t);
#define PCI_POWERSTATE_D0 0
#define PCI_POWERSTATE_D1 1
#define PCI_POWERSTATE_D2 2
#define PCI_POWERSTATE_D3_HOT 3
#define PCI_POWERSTATE_D3_COLD 4
#define PCI_POWERSTATE_D3 PCI_POWERSTATE_D3_COLD
#define PCI_POWERSTATE_MAX PCI_POWERSTATE_D3_COLD
#define PCI_POWERSTATE_COUNT 5
#define PCI_POWERSTATE_UNKNOWN -1
static __inline const char *
pci_powerstate_to_str(int state)
{
KASSERT(state >= PCI_POWERSTATE_D0 && state <= PCI_POWERSTATE_MAX,
("state out of bounds"));
return powerstate_to_str(state);
}
static __inline int
pci_set_powerstate(device_t dev, int state)
{
return PCI_SET_POWERSTATE(device_get_parent(dev), dev, state);
}
static __inline int
pci_get_powerstate(device_t dev)
{
return PCI_GET_POWERSTATE(device_get_parent(dev), dev);
}
static __inline int
pci_find_extcap(device_t dev, int capability, int *capreg)
{
return PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg);
}
static __inline int
pci_is_pcie(device_t dev)
{
return (pci_get_pciecap_ptr(dev) != 0);
}
static __inline int
pci_is_pcix(device_t dev)
{
return (pci_get_pcixcap_ptr(dev) != 0);
}
static __inline int
pci_alloc_msi(device_t dev, int *rid, int count, int cpuid)
{
return (PCI_ALLOC_MSI(device_get_parent(dev), dev, rid, count, cpuid));
}
static __inline int
pci_release_msi(device_t dev)
{
return (PCI_RELEASE_MSI(device_get_parent(dev), dev));
}
static __inline int
pci_alloc_msix_vector(device_t dev, u_int vector, int *rid, int cpuid)
{
return (PCI_ALLOC_MSIX_VECTOR(device_get_parent(dev), dev, vector, rid,
cpuid));
}
static __inline int
pci_release_msix_vector(device_t dev, int rid)
{
return PCI_RELEASE_MSIX_VECTOR(device_get_parent(dev), dev, rid);
}
static __inline int
pci_msi_count(device_t dev)
{
return (PCI_MSI_COUNT(device_get_parent(dev), dev));
}
static __inline int
pci_msix_count(device_t dev)
{
return (PCI_MSIX_COUNT(device_get_parent(dev), dev));
}
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t);
device_t pci_find_device(uint16_t, uint16_t);
device_t pci_find_class(uint8_t class, uint8_t subclass);
#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
device_t pci_iterate_class(struct pci_devinfo **dinfop,
uint8_t class, uint8_t subclass);
#endif
int pci_pending_msix_vector(device_t dev, u_int index);
int pci_setup_msix(device_t dev);
void pci_teardown_msix(device_t dev);
void pci_enable_msix(device_t dev);
void pci_disable_msix(device_t dev);
int pci_msi_device_blacklisted(device_t dev);
void pci_ht_map_msi(device_t dev, uint64_t addr);
void pci_restore_state(device_t dev);
void pci_save_state(device_t dev);
int pci_alloc_1intr(device_t dev, int msi_enable, int *rid, u_int *flags);
#define PCI_INTR_TYPE_LEGACY 0
#define PCI_INTR_TYPE_MSI 1
#define PCI_INTR_TYPE_MSIX 2
#endif
extern struct dev_ops pci_ops;
STAILQ_HEAD(devlist, pci_devinfo);
extern struct devlist pci_devq;
extern uint32_t pci_generation;
#define VGA_PCI_BIOS_SHADOW_ADDR 0xC0000
#define VGA_PCI_BIOS_SHADOW_SIZE 131072
int vga_pci_is_boot_display(device_t dev);
void * vga_pci_map_bios(device_t dev, size_t *size);
void vga_pci_unmap_bios(device_t dev, void *bios);
#endif