Home | History | Annotate | Download | only in sys
      1 #ifndef _SYS_PCI_H
      2 #define _SYS_PCI_H
      3 
      4 #include <inttypes.h>
      5 #include <sys/io.h>
      6 
      7 #define MAX_PCI_FUNC		  8
      8 #define MAX_PCI_DEVICES		 32
      9 #define MAX_PCI_BUSES		256
     10 #define LINUX_KERNEL_MODULE_SIZE 64
     11 #define PCI_VENDOR_NAME_SIZE	256
     12 #define PCI_PRODUCT_NAME_SIZE	256
     13 #define PCI_CLASS_NAME_SIZE	256
     14 #define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10
     15 #define MAX_PCI_CLASSES		256
     16 
     17 typedef uint32_t pciaddr_t;
     18 
     19 enum {
     20 	ENOPCIIDS = 100,
     21 	ENOMODULESPCIMAP,
     22 	ENOMODULESALIAS
     23 };
     24 
     25 /* a structure for extended pci information */
     26 /* XXX: use pointers for these? */
     27 struct pci_dev_info {
     28     char vendor_name[PCI_VENDOR_NAME_SIZE];
     29     char product_name[PCI_PRODUCT_NAME_SIZE];
     30     char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE]
     31 	[MAX_KERNEL_MODULES_PER_PCI_DEVICE];
     32     int linux_kernel_module_count;
     33     char class_name[PCI_CLASS_NAME_SIZE];	/* The most precise class name */
     34     char category_name[PCI_CLASS_NAME_SIZE];	/*The general category */
     35     uint8_t irq;
     36     uint8_t latency;
     37 };
     38 
     39 /* PCI device (really, function) */
     40 struct pci_device {
     41     union {
     42 	struct {
     43 	    uint16_t vendor;
     44 	    uint16_t product;
     45 	    uint16_t sub_vendor;
     46 	    uint16_t sub_product;
     47 	    uint8_t revision;
     48 	    uint8_t class[3];
     49 	};
     50 	struct {
     51 	    uint32_t vid_did;
     52 	    uint32_t svid_sdid;
     53 	    uint32_t rid_class;
     54 	};
     55     };
     56     struct pci_dev_info *dev_info;
     57     struct pci_device *next;
     58 };
     59 
     60 /* PCI device ("slot") structure */
     61 struct pci_slot {
     62     struct pci_device *func[MAX_PCI_FUNC];
     63 };
     64 
     65 /* PCI bus structure */
     66 struct pci_bus {
     67     struct pci_slot *slot[MAX_PCI_DEVICES];
     68 };
     69 
     70 /* PCI domain structure */
     71 struct pci_domain {
     72     struct pci_bus *bus[MAX_PCI_BUSES];
     73 };
     74 
     75 /* Iterate over a PCI domain */
     76 #define for_each_pci_func(funcp, domain) \
     77   for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
     78     if ((domain)->bus[__pci_bus]) \
     79       for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
     80 	if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
     81 	  for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
     82 	    if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
     83 		 func[__pci_func]))
     84 
     85 #define for_each_pci_func3(funcp, domain, addr) \
     86   for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
     87     if ((domain)->bus[__pci_bus]) \
     88       for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
     89 	if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
     90 	  for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
     91 	    if (((addr) = pci_mkaddr(__pci_bus, __pci_slot, __pci_func, 0)), \
     92 		((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
     93 		 func[__pci_func]))
     94 
     95 struct match {
     96     struct match *next;
     97     uint32_t did;
     98     uint32_t did_mask;
     99     uint32_t sid;
    100     uint32_t sid_mask;
    101     uint8_t rid_min, rid_max;
    102     char *filename;
    103 };
    104 
    105 static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev,
    106 				   uint32_t func, uint32_t reg)
    107 {
    108     return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) |
    109 	((func & 0x07) << 8) | (reg & 0xff);
    110 }
    111 
    112 static inline int pci_bus(pciaddr_t addr)
    113 {
    114     return (addr >> 16) & 0xff;
    115 }
    116 
    117 static inline int pci_dev(pciaddr_t addr)
    118 {
    119     return (addr >> 11) & 0x1f;
    120 }
    121 
    122 static inline int pci_func(pciaddr_t addr)
    123 {
    124     return (addr >> 8) & 0x07;
    125 }
    126 
    127 enum pci_config_type {
    128     PCI_CFG_NONE = -1,		/* badness */
    129     PCI_CFG_AUTO = 0,		/* autodetect */
    130     PCI_CFG_TYPE1 = 1,
    131     PCI_CFG_TYPE2 = 2,
    132     PCI_CFG_BIOS = 3,
    133 };
    134 
    135 enum pci_config_type pci_set_config_type(enum pci_config_type);
    136 
    137 uint8_t pci_readb(pciaddr_t);
    138 uint16_t pci_readw(pciaddr_t);
    139 uint32_t pci_readl(pciaddr_t);
    140 void pci_writeb(uint8_t, pciaddr_t);
    141 void pci_writew(uint16_t, pciaddr_t);
    142 void pci_writel(uint32_t, pciaddr_t);
    143 
    144 struct pci_domain *pci_scan(void);
    145 void free_pci_domain(struct pci_domain *domain);
    146 struct match *find_pci_device(const struct pci_domain *pci_domain,
    147 			      struct match *list);
    148 int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
    149 int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path);
    150 int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path);
    151 int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
    152 void gather_additional_pci_config(struct pci_domain *domain);
    153 #endif /* _SYS_PCI_H */
    154