#ifndef _LINUX_PCI_H_
#define _LINUX_PCI_H_
#include <sys/types.h>
#include <sys/param.h>
#include <machine/cpu.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <uvm/uvm_extern.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kobject.h>
#include <linux/dma-mapping.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>
struct pci_dev;
struct pci_bus {
pci_chipset_tag_t pc;
unsigned char number;
int domain_nr;
pcitag_t *bridgetag;
struct pci_dev *self;
};
struct pci_acpi {
struct aml_node *node;
};
struct pci_dev {
struct pci_bus _bus;
struct pci_bus *bus;
unsigned int devfn;
uint16_t vendor;
uint16_t device;
uint16_t subsystem_vendor;
uint16_t subsystem_device;
uint8_t revision;
uint32_t class;
pci_chipset_tag_t pc;
pcitag_t tag;
struct pci_softc *pci;
int irq;
int msi_enabled;
uint8_t no_64bit_msi;
uint8_t ltr_path;
struct pci_acpi dev;
struct device *_dev;
};
#define PCI_ANY_ID (uint16_t) (~0U)
#define PCI_DEVICE(v, p) \
.vendor = (v), \
.device = (p), \
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID
#ifndef PCI_MEM_START
#define PCI_MEM_START 0
#endif
#ifndef PCI_MEM_END
#define PCI_MEM_END 0xffffffff
#endif
#ifndef PCI_MEM64_END
#define PCI_MEM64_END 0xffffffffffffffff
#endif
#define PCI_VENDOR_ID_APPLE PCI_VENDOR_APPLE
#define PCI_VENDOR_ID_ASUSTEK PCI_VENDOR_ASUSTEK
#define PCI_VENDOR_ID_ATI PCI_VENDOR_ATI
#define PCI_VENDOR_ID_DELL PCI_VENDOR_DELL
#define PCI_VENDOR_ID_HP PCI_VENDOR_HP
#define PCI_VENDOR_ID_IBM PCI_VENDOR_IBM
#define PCI_VENDOR_ID_INTEL PCI_VENDOR_INTEL
#define PCI_VENDOR_ID_SONY PCI_VENDOR_SONY
#define PCI_VENDOR_ID_VIA PCI_VENDOR_VIATECH
#define PCI_DEVICE_ID_ATI_RADEON_QY PCI_PRODUCT_ATI_RADEON_QY
#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
#define PCI_SUBDEVICE_ID_QEMU 0x1100
#define PCI_DEVFN(slot, func) ((slot) << 3 | (func))
#define PCI_SLOT(devfn) ((devfn) >> 3)
#define PCI_FUNC(devfn) ((devfn) & 0x7)
#define PCI_BUS_NUM(devfn) (((devfn) >> 8) & 0xff)
#define pci_dev_put(x)
#define PCI_EXP_DEVSTA 0x0a
#define PCI_EXP_DEVSTA_TRPND (1 << 5)
#define PCI_EXP_LNKCAP 0x0c
#define PCI_EXP_LNKCAP_CLKPM (1 << 18)
#define PCI_EXP_LNKCTL 0x10
#define PCI_EXP_LNKCTL_HAWD (1 << 9)
#define PCI_EXP_LNKSTA 0x12
#define PCI_EXP_DEVCTL2 0x28
#define PCI_EXP_DEVCTL2_LTR_EN (1 << 10)
#define PCI_EXP_LNKCTL2 0x30
#define PCI_EXP_LNKCTL2_ENTER_COMP (1 << 4)
#define PCI_EXP_LNKCTL2_TX_MARGIN 0x0380
#define PCI_EXP_LNKCTL2_TLS PCI_PCIE_LCSR2_TLS
#define PCI_EXP_LNKCTL2_TLS_2_5GT PCI_PCIE_LCSR2_TLS_2_5
#define PCI_EXP_LNKCTL2_TLS_5_0GT PCI_PCIE_LCSR2_TLS_5
#define PCI_EXP_LNKCTL2_TLS_8_0GT PCI_PCIE_LCSR2_TLS_8
#define PCI_COMMAND PCI_COMMAND_STATUS_REG
#define PCI_COMMAND_MEMORY PCI_COMMAND_MEM_ENABLE
#define PCI_PRIMARY_BUS PCI_PRIBUS_1
#define PCI_POSSIBLE_ERROR(r) ((r) == 0xffffffff)
static inline int
pci_read_config_dword(struct pci_dev *pdev, int reg, u32 *val)
{
*val = pci_conf_read(pdev->pc, pdev->tag, reg);
return 0;
}
static inline int
pci_read_config_word(struct pci_dev *pdev, int reg, u16 *val)
{
uint32_t v;
v = pci_conf_read(pdev->pc, pdev->tag, (reg & ~0x2));
*val = (v >> ((reg & 0x2) * 8));
return 0;
}
static inline int
pci_read_config_byte(struct pci_dev *pdev, int reg, u8 *val)
{
uint32_t v;
v = pci_conf_read(pdev->pc, pdev->tag, (reg & ~0x3));
*val = (v >> ((reg & 0x3) * 8));
return 0;
}
static inline int
pci_write_config_dword(struct pci_dev *pdev, int reg, u32 val)
{
pci_conf_write(pdev->pc, pdev->tag, reg, val);
return 0;
}
static inline int
pci_write_config_word(struct pci_dev *pdev, int reg, u16 val)
{
uint32_t v;
v = pci_conf_read(pdev->pc, pdev->tag, (reg & ~0x2));
v &= ~(0xffff << ((reg & 0x2) * 8));
v |= (val << ((reg & 0x2) * 8));
pci_conf_write(pdev->pc, pdev->tag, (reg & ~0x2), v);
return 0;
}
static inline int
pci_write_config_byte(struct pci_dev *pdev, int reg, u8 val)
{
uint32_t v;
v = pci_conf_read(pdev->pc, pdev->tag, (reg & ~0x3));
v &= ~(0xff << ((reg & 0x3) * 8));
v |= (val << ((reg & 0x3) * 8));
pci_conf_write(pdev->pc, pdev->tag, (reg & ~0x3), v);
return 0;
}
static inline int
pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn,
int reg, u16 *val)
{
pcitag_t tag = pci_make_tag(bus->pc, bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn));
uint32_t v;
v = pci_conf_read(bus->pc, tag, (reg & ~0x2));
*val = (v >> ((reg & 0x2) * 8));
return 0;
}
static inline int
pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
int reg, u8 *val)
{
pcitag_t tag = pci_make_tag(bus->pc, bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn));
uint32_t v;
v = pci_conf_read(bus->pc, tag, (reg & ~0x3));
*val = (v >> ((reg & 0x3) * 8));
return 0;
}
static inline int
pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn,
int reg, u8 val)
{
pcitag_t tag = pci_make_tag(bus->pc, bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn));
uint32_t v;
v = pci_conf_read(bus->pc, tag, (reg & ~0x3));
v &= ~(0xff << ((reg & 0x3) * 8));
v |= (val << ((reg & 0x3) * 8));
pci_conf_write(bus->pc, tag, (reg & ~0x3), v);
return 0;
}
static inline int
pci_pcie_cap(struct pci_dev *pdev)
{
int pos;
if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
&pos, NULL))
return -EINVAL;
return pos;
}
bool pcie_aspm_enabled(struct pci_dev *);
static inline bool
pci_is_pcie(struct pci_dev *pdev)
{
return (pci_pcie_cap(pdev) > 0);
}
static inline bool
pci_is_root_bus(struct pci_bus *pbus)
{
return (pbus->bridgetag == NULL);
}
static inline struct pci_dev *
pci_upstream_bridge(struct pci_dev *pdev)
{
if (pci_is_root_bus(pdev->bus))
return NULL;
return pdev->bus->self;
}
static inline bool
pci_pr3_present(struct pci_dev *pdev)
{
return false;
}
static inline int
pcie_capability_read_dword(struct pci_dev *pdev, int off, u32 *val)
{
int pos;
if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
&pos, NULL)) {
*val = 0;
return -EINVAL;
}
*val = pci_conf_read(pdev->pc, pdev->tag, pos + off);
return 0;
}
static inline int
pcie_capability_read_word(struct pci_dev *pdev, int off, u16 *val)
{
int pos;
if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
&pos, NULL)) {
*val = 0;
return -EINVAL;
}
pci_read_config_word(pdev, pos + off, val);
return 0;
}
static inline int
pcie_capability_write_word(struct pci_dev *pdev, int off, u16 val)
{
int pos;
if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
&pos, NULL))
return -EINVAL;
pci_write_config_word(pdev, pos + off, val);
return 0;
}
static inline int
pcie_capability_set_word(struct pci_dev *pdev, int off, u16 val)
{
u16 r;
pcie_capability_read_word(pdev, off, &r);
r |= val;
pcie_capability_write_word(pdev, off, r);
return 0;
}
static inline int
pcie_capability_clear_word(struct pci_dev *pdev, int off, u16 c)
{
u16 r;
pcie_capability_read_word(pdev, off, &r);
r &= ~c;
pcie_capability_write_word(pdev, off, r);
return 0;
}
static inline int
pcie_capability_clear_and_set_word(struct pci_dev *pdev, int off, u16 c, u16 s)
{
u16 r;
pcie_capability_read_word(pdev, off, &r);
r &= ~c;
r |= s;
pcie_capability_write_word(pdev, off, r);
return 0;
}
static inline int
pcie_get_readrq(struct pci_dev *pdev)
{
uint16_t val;
pcie_capability_read_word(pdev, PCI_PCIE_DCSR, &val);
return 128 << ((val & PCI_PCIE_DCSR_MPS) >> 12);
}
static inline int
pcie_set_readrq(struct pci_dev *pdev, int rrq)
{
uint16_t val;
pcie_capability_read_word(pdev, PCI_PCIE_DCSR, &val);
val &= ~PCI_PCIE_DCSR_MPS;
val |= (ffs(rrq) - 8) << 12;
return pcie_capability_write_word(pdev, PCI_PCIE_DCSR, val);
}
static inline void
pci_set_master(struct pci_dev *pdev)
{
}
static inline void
pci_clear_master(struct pci_dev *pdev)
{
}
static inline void
pci_save_state(struct pci_dev *pdev)
{
}
static inline void
pci_restore_state(struct pci_dev *pdev)
{
}
static inline int
pci_enable_msi(struct pci_dev *pdev)
{
return 0;
}
static inline void
pci_disable_msi(struct pci_dev *pdev)
{
}
typedef enum {
PCI_D0,
PCI_D1,
PCI_D2,
PCI_D3hot,
PCI_D3cold
} pci_power_t;
enum pci_bus_speed {
PCIE_SPEED_2_5GT,
PCIE_SPEED_5_0GT,
PCIE_SPEED_8_0GT,
PCIE_SPEED_16_0GT,
PCIE_SPEED_32_0GT,
PCIE_SPEED_64_0GT,
PCI_SPEED_UNKNOWN
};
enum pcie_link_width {
PCIE_LNK_X1 = 1,
PCIE_LNK_X2 = 2,
PCIE_LNK_X4 = 4,
PCIE_LNK_X8 = 8,
PCIE_LNK_X12 = 12,
PCIE_LNK_X16 = 16,
PCIE_LNK_X32 = 32,
PCIE_LNK_WIDTH_UNKNOWN = 0xff
};
typedef unsigned int pci_ers_result_t;
typedef unsigned int pci_channel_state_t;
#define PCI_ERS_RESULT_DISCONNECT 0
#define PCI_ERS_RESULT_RECOVERED 1
enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *);
enum pcie_link_width pcie_get_width_cap(struct pci_dev *);
int pci_resize_resource(struct pci_dev *, int, int);
static inline void
pcie_bandwidth_available(struct pci_dev *pdev, struct pci_dev **ldev,
enum pci_bus_speed *speed, enum pcie_link_width *width)
{
struct pci_dev *bdev = pdev->bus->self;
if (bdev == NULL)
return;
if (speed)
*speed = pcie_get_speed_cap(bdev);
if (width)
*width = pcie_get_width_cap(bdev);
}
static inline int
pci_enable_device(struct pci_dev *pdev)
{
return 0;
}
static inline void
pci_disable_device(struct pci_dev *pdev)
{
}
static inline int
pci_wait_for_pending_transaction(struct pci_dev *pdev)
{
return 0;
}
static inline bool
pci_is_thunderbolt_attached(struct pci_dev *pdev)
{
return false;
}
static inline void
pci_set_drvdata(struct pci_dev *pdev, void *data)
{
dev_set_drvdata(pdev->_dev, data);
}
static inline void *
pci_get_drvdata(struct pci_dev *pdev)
{
return dev_get_drvdata(pdev->_dev);
}
static inline int
pci_domain_nr(struct pci_bus *pbus)
{
return pbus->domain_nr;
}
static inline int
pci_irq_vector(struct pci_dev *pdev, unsigned int num)
{
return pdev->irq;
}
static inline void
pci_free_irq_vectors(struct pci_dev *pdev)
{
}
static inline int
pci_set_power_state(struct pci_dev *dev, int state)
{
return 0;
}
struct pci_driver;
static inline int
pci_register_driver(struct pci_driver *pci_drv)
{
return 0;
}
static inline void
pci_unregister_driver(void *d)
{
}
static inline u16
pci_dev_id(struct pci_dev *dev)
{
return dev->devfn | (dev->bus->number << 8);
}
static inline const struct pci_device_id *
pci_match_id(const struct pci_device_id *ids, struct pci_dev *pdev)
{
int i = 0;
for (i = 0; ids[i].vendor != 0; i++) {
if ((ids[i].vendor == pdev->vendor) &&
(ids[i].device == pdev->device ||
ids[i].device == PCI_ANY_ID) &&
(ids[i].subvendor == PCI_ANY_ID) &&
(ids[i].subdevice == PCI_ANY_ID))
return &ids[i];
}
return NULL;
}
#define PCI_BASE_CLASS_DISPLAY PCI_CLASS_DISPLAY
#define PCI_CLASS_DISPLAY_VGA \
((PCI_CLASS_DISPLAY << 8) | PCI_SUBCLASS_DISPLAY_VGA)
#define PCI_CLASS_DISPLAY_OTHER \
((PCI_CLASS_DISPLAY << 8) | PCI_SUBCLASS_DISPLAY_MISC)
#define PCI_CLASS_ACCELERATOR_PROCESSING \
(PCI_CLASS_ACCELERATOR << 8)
static inline bool
pci_device_is_present(struct pci_dev *pdev)
{
return true;
}
static inline bool
pci_dev_is_disconnected(struct pci_dev *pdev)
{
return false;
}
static inline bool
dev_is_pci(struct device *dev)
{
return true;
}
#endif