1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * PCI support code.
10 * There really should be a driver for this, it's not terribly safe
11 * without locks or restrictions on what can be poked (e.g. Axil NX801).
12 */
13 enum { /* configuration mechanism #1 */
14 PciADDR = 0xCF8, /* CONFIG_ADDRESS */
15 PciDATA = 0xCFC, /* CONFIG_DATA */
16
17 /* configuration mechanism #2 */
18 PciCSE = 0xCF8, /* configuration space enable */
19 PciFORWARD = 0xCFA, /* which bus */
20
21 MaxFNO = 7,
22 MaxUBN = 255,
23 };
24
25 static int pcicfgmode = -1;
26 static int pcimaxdno;
27 static Pcidev* pciroot;
28 static Pcidev* pcilist;
29 static Pcidev* pcitail;
30
31 static int pcicfgrw32(int, int, int, int);
32
33 static int
pciscan(int bno,Pcidev ** list)34 pciscan(int bno, Pcidev** list)
35 {
36 ulong v;
37 Pcidev *p, *head, *tail;
38 int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
39
40 maxubn = bno;
41 head = nil;
42 tail = nil;
43 for(dno = 0; dno <= pcimaxdno; dno++){
44 maxfno = 0;
45 for(fno = 0; fno <= maxfno; fno++){
46 /*
47 * For this possible device, form the bus+device+function
48 * triplet needed to address it and try to read the vendor
49 * and device ID. If successful, allocate a device struct
50 * and start to fill it in with some useful information from
51 * the device's configuration space.
52 */
53 tbdf = MKBUS(BusPCI, bno, dno, fno);
54 l = pcicfgrw32(tbdf, PciVID, 0, 1);
55 if(l == 0xFFFFFFFF || l == 0)
56 continue;
57 p = mallocz(sizeof(*p), 1);
58 p->tbdf = tbdf;
59 p->vid = l;
60 p->did = l>>16;
61 p->rid = pcicfgr8(p, PciRID);
62
63 if(pcilist != nil)
64 pcitail->list = p;
65 else
66 pcilist = p;
67 pcitail = p;
68
69 p->intl = pcicfgr8(p, PciINTL);
70 p->ccru = pcicfgr16(p, PciCCRu);
71
72 /*
73 * If the device is a multi-function device adjust the
74 * loop count so all possible functions are checked.
75 */
76 hdt = pcicfgr8(p, PciHDT);
77 if(hdt & 0x80)
78 maxfno = MaxFNO;
79
80 /*
81 * If appropriate, read the base address registers
82 * and work out the sizes.
83 */
84 switch(p->ccru>>8){
85
86 case 0x01: /* mass storage controller */
87 case 0x02: /* network controller */
88 case 0x03: /* display controller */
89 case 0x04: /* multimedia device */
90 case 0x07: /* simple communication controllers */
91 case 0x08: /* base system peripherals */
92 case 0x09: /* input devices */
93 case 0x0A: /* docking stations */
94 case 0x0B: /* processors */
95 case 0x0C: /* serial bus controllers */
96 if((hdt & 0x7F) != 0)
97 break;
98 rno = PciBAR0 - 4;
99 for(i = 0; i < nelem(p->mem); i++){
100 rno += 4;
101 p->mem[i].bar = pcicfgr32(p, rno);
102 pcicfgw32(p, rno, -1);
103 v = pcicfgr32(p, rno);
104 pcicfgw32(p, rno, p->mem[i].bar);
105 p->mem[i].size = -(v & ~0xF);
106 }
107 break;
108
109 case 0x00:
110 case 0x05: /* memory controller */
111 case 0x06: /* bridge device */
112 default:
113 break;
114 }
115
116 if(head != nil)
117 tail->link = p;
118 else
119 head = p;
120 tail = p;
121 }
122 }
123
124 *list = head;
125 for(p = head; p != nil; p = p->link){
126 /*
127 * Find PCI-PCI bridges and recursively descend the tree.
128 */
129 if(p->ccru != ((0x06<<8)|0x04))
130 continue;
131
132 /*
133 * If the secondary or subordinate bus number is not initialised
134 * try to do what the PCI BIOS should have done and fill in the
135 * numbers as the tree is descended. On the way down the subordinate
136 * bus number is set to the maximum as it's not known how many
137 * buses are behind this one; the final value is set on the way
138 * back up.
139 */
140 sbn = pcicfgr8(p, PciSBN);
141 ubn = pcicfgr8(p, PciUBN);
142 if(sbn == 0 || ubn == 0){
143 sbn = maxubn+1;
144 /*
145 * Make sure memory, I/O and master enables are off,
146 * set the primary, secondary and subordinate bus numbers
147 * and clear the secondary status before attempting to
148 * scan the secondary bus.
149 *
150 * Initialisation of the bridge should be done here.
151 */
152 pcicfgw32(p, PciPCR, 0xFFFF0000);
153 l = (MaxUBN<<16)|(sbn<<8)|bno;
154 pcicfgw32(p, PciPBN, l);
155 pcicfgw16(p, PciSPSR, 0xFFFF);
156 maxubn = pciscan(sbn, &p->bridge);
157 l = (maxubn<<16)|(sbn<<8)|bno;
158 pcicfgw32(p, PciPBN, l);
159 }
160 else{
161 maxubn = ubn;
162 pciscan(sbn, &p->bridge);
163 }
164 }
165
166 return maxubn;
167 }
168
169 static void
pcicfginit(void)170 pcicfginit(void)
171 {
172 #ifdef kernel
173 char *p;
174 #endif /* kernel */
175 int bno;
176 Pcidev **list;
177
178 if(pcicfgmode == -1){
179 /*
180 * Try to determine which PCI configuration mode is implemented.
181 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
182 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
183 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
184 * a device behind these addresses so if Mode2 accesses fail try
185 * for Mode1 (which is preferred, Mode2 is deprecated).
186 */
187 outportb(PciCSE, 0);
188 if(inportb(PciCSE) == 0){
189 pcicfgmode = 2;
190 pcimaxdno = 15;
191 }
192 else{
193 outportl(PciADDR, 0);
194 if(inportl(PciADDR) == 0){
195 pcicfgmode = 1;
196 pcimaxdno = 31;
197 }
198 }
199
200 if(pcicfgmode > 0){
201 list = &pciroot;
202 for(bno = 0; bno < 256; bno++){
203 bno = pciscan(bno, list);
204 while(*list)
205 list = &(*list)->link;
206 }
207
208 }
209 }
210 }
211
212 static int
pcicfgrw8(int tbdf,int rno,int data,int read)213 pcicfgrw8(int tbdf, int rno, int data, int read)
214 {
215 int o, type, x;
216
217 if(pcicfgmode == -1)
218 pcicfginit();
219
220 if(BUSBNO(tbdf))
221 type = 0x01;
222 else
223 type = 0x00;
224 x = -1;
225 if(BUSDNO(tbdf) > pcimaxdno)
226 return x;
227
228 switch(pcicfgmode){
229
230 case 1:
231 o = rno & 0x03;
232 rno &= ~0x03;
233 outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
234 if(read)
235 x = inportb(PciDATA+o);
236 else
237 outportb(PciDATA+o, data);
238 outportl(PciADDR, 0);
239 break;
240
241 case 2:
242 outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
243 outportb(PciFORWARD, BUSBNO(tbdf));
244 if(read)
245 x = inportb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
246 else
247 outportb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
248 outportb(PciCSE, 0);
249 break;
250 }
251
252 return x;
253 }
254
255 int
pcicfgr8(Pcidev * pcidev,int rno)256 pcicfgr8(Pcidev* pcidev, int rno)
257 {
258 return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
259 }
260
261 void
pcicfgw8(Pcidev * pcidev,int rno,int data)262 pcicfgw8(Pcidev* pcidev, int rno, int data)
263 {
264 pcicfgrw8(pcidev->tbdf, rno, data, 0);
265 }
266
267 static int
pcicfgrw16(int tbdf,int rno,int data,int read)268 pcicfgrw16(int tbdf, int rno, int data, int read)
269 {
270 int o, type, x;
271
272 if(pcicfgmode == -1)
273 pcicfginit();
274
275 if(BUSBNO(tbdf))
276 type = 0x01;
277 else
278 type = 0x00;
279 x = -1;
280 if(BUSDNO(tbdf) > pcimaxdno)
281 return x;
282
283 switch(pcicfgmode){
284
285 case 1:
286 o = rno & 0x02;
287 rno &= ~0x03;
288 outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
289 if(read)
290 x = inportw(PciDATA+o);
291 else
292 outportw(PciDATA+o, data);
293 outportl(PciADDR, 0);
294 break;
295
296 case 2:
297 outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
298 outportb(PciFORWARD, BUSBNO(tbdf));
299 if(read)
300 x = inportw((0xC000|(BUSDNO(tbdf)<<8)) + rno);
301 else
302 outportw((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
303 outportb(PciCSE, 0);
304 break;
305 }
306
307 return x;
308 }
309
310 int
pcicfgr16(Pcidev * pcidev,int rno)311 pcicfgr16(Pcidev* pcidev, int rno)
312 {
313 return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
314 }
315
316 void
pcicfgw16(Pcidev * pcidev,int rno,int data)317 pcicfgw16(Pcidev* pcidev, int rno, int data)
318 {
319 pcicfgrw16(pcidev->tbdf, rno, data, 0);
320 }
321
322 static int
pcicfgrw32(int tbdf,int rno,int data,int read)323 pcicfgrw32(int tbdf, int rno, int data, int read)
324 {
325 int type, x;
326
327 if(pcicfgmode == -1)
328 pcicfginit();
329
330 if(BUSBNO(tbdf))
331 type = 0x01;
332 else
333 type = 0x00;
334 x = -1;
335 if(BUSDNO(tbdf) > pcimaxdno)
336 return x;
337
338 switch(pcicfgmode){
339
340 case 1:
341 rno &= ~0x03;
342 outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
343 if(read)
344 x = inportl(PciDATA);
345 else
346 outportl(PciDATA, data);
347 outportl(PciADDR, 0);
348 break;
349
350 case 2:
351 outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
352 outportb(PciFORWARD, BUSBNO(tbdf));
353 if(read)
354 x = inportl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
355 else
356 outportl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
357 outportb(PciCSE, 0);
358 break;
359 }
360
361 return x;
362 }
363
364 int
pcicfgr32(Pcidev * pcidev,int rno)365 pcicfgr32(Pcidev* pcidev, int rno)
366 {
367 return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
368 }
369
370 void
pcicfgw32(Pcidev * pcidev,int rno,int data)371 pcicfgw32(Pcidev* pcidev, int rno, int data)
372 {
373 pcicfgrw32(pcidev->tbdf, rno, data, 0);
374 }
375
376 Pcidev*
pcimatch(Pcidev * prev,int vid,int did)377 pcimatch(Pcidev* prev, int vid, int did)
378 {
379 if(pcicfgmode == -1)
380 pcicfginit();
381
382 if(prev == nil)
383 prev = pcilist;
384 else
385 prev = prev->list;
386
387 while(prev != nil) {
388 if(prev->vid == vid && (did == 0 || prev->did == did))
389 break;
390 prev = prev->list;
391 }
392 return prev;
393 }
394
395 void
pcihinv(Pcidev * p)396 pcihinv(Pcidev* p)
397 {
398 int i;
399 Pcidev *t;
400
401 if(pcicfgmode == -1)
402 pcicfginit();
403
404
405 if(p == nil) {
406 p = pciroot;
407 Bprint(&stdout, "bus dev type vid did intl memory\n");
408 }
409 for(t = p; t != nil; t = t->link) {
410 Bprint(&stdout, "%d %2d/%d %.4ux %.4ux %.4ux %2d ",
411 BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
412 t->ccru, t->vid, t->did, t->intl);
413
414 for(i = 0; i < nelem(p->mem); i++) {
415 if(t->mem[i].size == 0)
416 continue;
417 Bprint(&stdout, "%d:%.8lux %d ", i,
418 t->mem[i].bar, t->mem[i].size);
419 }
420 Bprint(&stdout, "\n");
421 }
422 while(p != nil) {
423 if(p->bridge != nil)
424 pcihinv(p->bridge);
425 p = p->link;
426 }
427 }
428