summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/com32/include/sys/pci.h
blob: aba1f9657ad49d82848458e64f88a57ef2c5a8cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#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 */