154 lines
4.2 KiB
C
154 lines
4.2 KiB
C
#ifndef _SYS_PCI_H
|
|
#define _SYS_PCI_H
|
|
|
|
#include <inttypes.h>
|
|
#include <sys/io.h>
|
|
|
|
#define MAX_PCI_FUNC 8
|
|
#define MAX_PCI_DEVICES 32
|
|
#define MAX_PCI_BUSES 256
|
|
#define LINUX_KERNEL_MODULE_SIZE 64
|
|
#define PCI_VENDOR_NAME_SIZE 256
|
|
#define PCI_PRODUCT_NAME_SIZE 256
|
|
#define PCI_CLASS_NAME_SIZE 256
|
|
#define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10
|
|
#define MAX_PCI_CLASSES 256
|
|
|
|
typedef uint32_t pciaddr_t;
|
|
|
|
enum {
|
|
ENOPCIIDS = 100,
|
|
ENOMODULESPCIMAP,
|
|
ENOMODULESALIAS
|
|
};
|
|
|
|
/* a structure for extended pci information */
|
|
/* XXX: use pointers for these? */
|
|
struct pci_dev_info {
|
|
char vendor_name[PCI_VENDOR_NAME_SIZE];
|
|
char product_name[PCI_PRODUCT_NAME_SIZE];
|
|
char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE]
|
|
[MAX_KERNEL_MODULES_PER_PCI_DEVICE];
|
|
int linux_kernel_module_count;
|
|
char class_name[PCI_CLASS_NAME_SIZE]; /* The most precise class name */
|
|
char category_name[PCI_CLASS_NAME_SIZE]; /*The general category */
|
|
uint8_t irq;
|
|
uint8_t latency;
|
|
};
|
|
|
|
/* PCI device (really, function) */
|
|
struct pci_device {
|
|
union {
|
|
struct {
|
|
uint16_t vendor;
|
|
uint16_t product;
|
|
uint16_t sub_vendor;
|
|
uint16_t sub_product;
|
|
uint8_t revision;
|
|
uint8_t class[3];
|
|
};
|
|
struct {
|
|
uint32_t vid_did;
|
|
uint32_t svid_sdid;
|
|
uint32_t rid_class;
|
|
};
|
|
};
|
|
struct pci_dev_info *dev_info;
|
|
struct pci_device *next;
|
|
};
|
|
|
|
/* PCI device ("slot") structure */
|
|
struct pci_slot {
|
|
struct pci_device *func[MAX_PCI_FUNC];
|
|
};
|
|
|
|
/* PCI bus structure */
|
|
struct pci_bus {
|
|
struct pci_slot *slot[MAX_PCI_DEVICES];
|
|
};
|
|
|
|
/* PCI domain structure */
|
|
struct pci_domain {
|
|
struct pci_bus *bus[MAX_PCI_BUSES];
|
|
};
|
|
|
|
/* Iterate over a PCI domain */
|
|
#define for_each_pci_func(funcp, domain) \
|
|
for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
|
|
if ((domain)->bus[__pci_bus]) \
|
|
for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
|
|
if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
|
|
for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
|
|
if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
|
|
func[__pci_func]))
|
|
|
|
#define for_each_pci_func3(funcp, domain, addr) \
|
|
for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
|
|
if ((domain)->bus[__pci_bus]) \
|
|
for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
|
|
if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
|
|
for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
|
|
if (((addr) = pci_mkaddr(__pci_bus, __pci_slot, __pci_func, 0)), \
|
|
((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
|
|
func[__pci_func]))
|
|
|
|
struct match {
|
|
struct match *next;
|
|
uint32_t did;
|
|
uint32_t did_mask;
|
|
uint32_t sid;
|
|
uint32_t sid_mask;
|
|
uint8_t rid_min, rid_max;
|
|
char *filename;
|
|
};
|
|
|
|
static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev,
|
|
uint32_t func, uint32_t reg)
|
|
{
|
|
return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) |
|
|
((func & 0x07) << 8) | (reg & 0xff);
|
|
}
|
|
|
|
static inline int pci_bus(pciaddr_t addr)
|
|
{
|
|
return (addr >> 16) & 0xff;
|
|
}
|
|
|
|
static inline int pci_dev(pciaddr_t addr)
|
|
{
|
|
return (addr >> 11) & 0x1f;
|
|
}
|
|
|
|
static inline int pci_func(pciaddr_t addr)
|
|
{
|
|
return (addr >> 8) & 0x07;
|
|
}
|
|
|
|
enum pci_config_type {
|
|
PCI_CFG_NONE = -1, /* badness */
|
|
PCI_CFG_AUTO = 0, /* autodetect */
|
|
PCI_CFG_TYPE1 = 1,
|
|
PCI_CFG_TYPE2 = 2,
|
|
PCI_CFG_BIOS = 3,
|
|
};
|
|
|
|
enum pci_config_type pci_set_config_type(enum pci_config_type);
|
|
|
|
uint8_t pci_readb(pciaddr_t);
|
|
uint16_t pci_readw(pciaddr_t);
|
|
uint32_t pci_readl(pciaddr_t);
|
|
void pci_writeb(uint8_t, pciaddr_t);
|
|
void pci_writew(uint16_t, pciaddr_t);
|
|
void pci_writel(uint32_t, pciaddr_t);
|
|
|
|
struct pci_domain *pci_scan(void);
|
|
void free_pci_domain(struct pci_domain *domain);
|
|
struct match *find_pci_device(const struct pci_domain *pci_domain,
|
|
struct match *list);
|
|
int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
|
|
int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path);
|
|
int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path);
|
|
int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
|
|
void gather_additional_pci_config(struct pci_domain *domain);
|
|
#endif /* _SYS_PCI_H */
|