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#include <libpayload.h>
31#include <pci.h>
32#include <pci/pci.h>
33
34
35static pcidev_t libpci_to_lb(struct pci_dev *dev)
36{
37 return PCI_DEV(dev->bus, dev->dev, dev->func);
38}
39
40
41u8 pci_read_byte(struct pci_dev *dev, int pos)
42{
43 return pci_read_config8(libpci_to_lb(dev), pos);
44}
45
46u16 pci_read_word(struct pci_dev *dev, int pos)
47{
48 return pci_read_config16(libpci_to_lb(dev), pos);
49}
50
51u32 pci_read_long(struct pci_dev *dev, int pos)
52{
53 return pci_read_config32(libpci_to_lb(dev), pos);
54}
55
56int pci_write_byte(struct pci_dev *dev, int pos, u8 data)
57{
58 pci_write_config8(libpci_to_lb(dev), pos, data);
59 return 1;
60}
61
62int pci_write_word(struct pci_dev *dev, int pos, u16 data)
63{
64 pci_write_config16(libpci_to_lb(dev), pos, data);
65 return 1;
66}
67
68int pci_write_long(struct pci_dev *dev, int pos, u32 data)
69{
70 pci_write_config32(libpci_to_lb(dev), pos, data);
71 return 1;
72}
73
74struct pci_access *pci_alloc(void)
75{
76 struct pci_access *pacc = malloc(sizeof(*pacc));
77 return pacc;
78}
79
80void pci_init(struct pci_access *pacc)
81{
82 memset(pacc, 0, sizeof(*pacc));
83}
84
85void pci_cleanup(__attribute__ ((unused)) struct pci_access *pacc)
86{
87}
88
89void pci_filter_init(struct pci_access* pacc, struct pci_filter* pf)
90{
91 pf->domain = -1;
92 pf->bus = -1;
93 pf->dev = -1;
94 pf->func = -1;
95 pf->vendor = -1;
96 pf->device = -1;
97}
98
99
100
101
102
103char *pci_filter_parse_slot(struct pci_filter* filter, const char* id)
104{
105 char *endptr;
106
107 filter->func = filter->dev = filter->bus = filter->domain = -1;
108
109 char *funcp = strrchr(id, '.');
110 if (funcp) {
111 filter->func = strtoul(funcp+1, &endptr, 0);
112 if (endptr[0] != '\0') return "invalid pci device string";
113 }
114
115 char *devp = strrchr(id, ':');
116 if (!devp) {
117 filter->dev = strtoul(id, &endptr, 0);
118 } else {
119 filter->dev = strtoul(devp+1, &endptr, 0);
120 }
121 if (endptr != funcp) return "invalid pci device string";
122 if (!devp) return NULL;
123
124 char *busp = strchr(id, ':');
125 if (busp == devp) {
126 filter->bus = strtoul(id, &endptr, 0);
127 } else {
128 filter->bus = strtoul(busp+1, &endptr, 0);
129 }
130 if (endptr != funcp) return "invalid pci device string";
131 if (busp == devp) return NULL;
132
133 filter->domain = strtoul(id, &endptr, 0);
134 if (endptr != busp) return "invalid pci device string";
135
136 return NULL;
137}
138
139int pci_filter_match(struct pci_filter* pf, struct pci_dev* dev)
140{
141 if ((pf->domain > -1) && (pf->domain != dev->domain))
142 return 0;
143 if ((pf->bus > -1) && (pf->bus != dev->bus))
144 return 0;
145 if ((pf->dev > -1) && (pf->dev != dev->dev))
146 return 0;
147 if ((pf->func > -1) && (pf->func != dev->func))
148 return 0;
149 if ((pf->vendor > -1) && (pf->vendor != dev->vendor_id))
150 return 0;
151 if ((pf->device > -1) && (pf->device != dev->device_id))
152 return 0;
153 return 1;
154}
155
156static struct pci_dev *pci_scan_single_bus(struct pci_dev *dev, int bus)
157{
158 int devfn;
159 u32 val;
160 unsigned char hdr;
161
162 for (devfn = 0; devfn < 0x100; devfn++) {
163 int func = devfn & 0x7;
164 int slot = (devfn >> 3) & 0x1f;
165
166 val = pci_read_config32(PCI_DEV(bus, slot, func),
167 REG_VENDOR_ID);
168
169 if (val == 0xffffffff || val == 0x00000000 ||
170 val == 0x0000ffff || val == 0xffff0000)
171 continue;
172
173 dev->next = malloc(sizeof(struct pci_dev));
174 dev = dev->next;
175 dev->domain = 0;
176 dev->bus = bus;
177 dev->dev = slot;
178 dev->func = func;
179 dev->vendor_id = val & 0xffff;
180 dev->device_id = val >> 16;
181 dev->next = 0;
182
183 hdr = pci_read_config8(PCI_DEV(bus, slot, func),
184 REG_HEADER_TYPE);
185 hdr &= 0x7F;
186
187 if (hdr == HEADER_TYPE_BRIDGE || hdr == HEADER_TYPE_CARDBUS) {
188 unsigned int busses;
189 busses = pci_read_config32(PCI_DEV(bus, slot, func),
190 REG_PRIMARY_BUS);
191 busses = (busses >> 8) & 0xFF;
192
193
194
195
196 if (busses != bus)
197 dev = pci_scan_single_bus(dev, busses);
198 }
199 }
200
201 return dev;
202}
203
204void pci_scan_bus(struct pci_access* pacc)
205{
206 struct pci_dev rootdev;
207 pci_scan_single_bus(&rootdev, 0);
208 pacc->devices = rootdev.next;
209}
210
211struct pci_dev *pci_get_dev(struct pci_access* pacc, u16 domain, u8 bus, u8 dev, u8 func)
212{
213 struct pci_dev *cur = malloc(sizeof(*cur));
214 cur->domain = domain;
215 cur->bus = bus;
216 cur->dev = dev;
217 cur->func = func;
218 return cur;
219}
220
221