This source file includes following definitions.
- pcibiosprobe
- pcibiosattach
- pcibios_pir_init
- pcibios_get_status
- pcibios_get_intr_routing
- pcibios_return_code
- pcibios_print_exclirq
- pcibios_print_pir_table
- pci_device_foreach
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 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/device.h>
97 #include <sys/malloc.h>
98
99 #include <dev/isa/isareg.h>
100 #include <i386/isa/isa_machdep.h>
101
102 #include <dev/pci/pcireg.h>
103 #include <dev/pci/pcivar.h>
104 #include <dev/pci/pcidevs.h>
105
106 #include <i386/pci/pcibiosvar.h>
107
108 #include <machine/biosvar.h>
109
110 int pcibios_flags;
111 int pcibios_present;
112
113 struct pcibios_pir_header pcibios_pir_header;
114 struct pcibios_intr_routing *pcibios_pir_table;
115 int pcibios_pir_table_nentries;
116 int pcibios_flags = 0;
117
118 struct bios32_entry pcibios_entry;
119 struct bios32_entry_info pcibios_entry_info;
120
121 struct pcibios_intr_routing *pcibios_pir_init(struct pcibios_softc *);
122
123 int pcibios_get_status(struct pcibios_softc *,
124 u_int32_t *, u_int32_t *, u_int32_t *,
125 u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *);
126 int pcibios_get_intr_routing(struct pcibios_softc *,
127 struct pcibios_intr_routing *, int *, u_int16_t *);
128
129 int pcibios_return_code(struct pcibios_softc *, u_int16_t, const char *);
130
131 void pcibios_print_exclirq(struct pcibios_softc *);
132 void pcibios_print_pir_table(void);
133
134 #define PCI_IRQ_TABLE_START 0xf0000
135 #define PCI_IRQ_TABLE_END 0xfffff
136
137 struct cfdriver pcibios_cd = {
138 NULL, "pcibios", DV_DULL
139 };
140
141 int pcibiosprobe(struct device *, void *, void *);
142 void pcibiosattach(struct device *, struct device *, void *);
143
144 struct cfattach pcibios_ca = {
145 sizeof(struct pcibios_softc), pcibiosprobe, pcibiosattach
146 };
147
148 int
149 pcibiosprobe(struct device *parent, void *match, void *aux)
150 {
151 struct bios_attach_args *ba = aux;
152 u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus;
153 int rv;
154
155 if (strcmp(ba->bios_dev, "pcibios"))
156 return 0;
157
158 rv = bios32_service(PCIBIOS_SIGNATURE, &pcibios_entry,
159 &pcibios_entry_info);
160
161 PCIBIOS_PRINTV(("pcibiosprobe: 0x%lx:0x%lx at 0x%lx[0x%lx]\n",
162 pcibios_entry.segment, pcibios_entry.offset,
163 pcibios_entry_info.bei_base, pcibios_entry_info.bei_size));
164
165 return rv &&
166 pcibios_get_status(NULL, &rev_maj, &rev_min, &mech1, &mech2,
167 &scmech1, &scmech2, &maxbus) == PCIBIOS_SUCCESS;
168 }
169
170 void
171 pcibiosattach(struct device *parent, struct device *self, void *aux)
172 {
173 struct pcibios_softc *sc = (struct pcibios_softc *)self;
174 u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2;
175
176 pcibios_flags = sc->sc_dev.dv_cfdata->cf_flags;
177
178 pcibios_get_status((struct pcibios_softc *)self, &rev_maj,
179 &rev_min, &mech1, &mech2,
180 &scmech1, &scmech2, &sc->max_bus);
181
182 printf(": rev %d.%d @ 0x%lx/0x%lx\n",
183 rev_maj, rev_min >> 4, pcibios_entry_info.bei_base,
184 pcibios_entry_info.bei_size);
185
186 PCIBIOS_PRINTV(("%s: config mechanism %s%s, special cycles %s%s, "
187 "last bus %d\n", sc->sc_dev.dv_xname,
188 mech1 ? "[1]" : "[x]", mech2 ? "[2]" : "[x]",
189 scmech1 ? "[1]" : "[x]", scmech2 ? "[2]" : "[x]", sc->max_bus));
190
191
192
193
194
195 pci_mode = mech1 ? 1 : 2;
196
197 pcibios_present = 1;
198
199
200
201
202
203 if (!(pcibios_flags & PCIBIOS_INTR_FIXUP) &&
204 pcibios_pir_init((struct pcibios_softc *)self) != NULL) {
205 int rv;
206
207
208
209
210 rv = pci_intr_fixup(sc, NULL, I386_BUS_SPACE_IO);
211 switch (rv) {
212 case -1:
213
214 printf("%s: Warning, unable to fix up PCI interrupt "
215 "routing\n", sc->sc_dev.dv_xname);
216 break;
217
218 case 1:
219
220 printf("%s: interrupt fixup failed\n", sc->sc_dev.dv_xname);
221 return;
222 }
223
224
225
226
227
228 }
229
230 if (!(pcibios_flags & PCIBIOS_BUS_FIXUP)) {
231 sc->max_bus = pci_bus_fixup(NULL, 0);
232 printf("%s: PCI bus #%d is the last bus\n",
233 sc->sc_dev.dv_xname, sc->max_bus);
234 }
235
236 if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP))
237 pci_addr_fixup(sc, NULL, sc->max_bus);
238 }
239
240 struct pcibios_intr_routing *
241 pcibios_pir_init(struct pcibios_softc *sc)
242 {
243 paddr_t pa;
244
245 pcibios_pir_table = NULL;
246 for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) {
247 u_int8_t *p, cksum;
248 struct pcibios_pir_header *pirh;
249 int i;
250
251 p = ISA_HOLE_VADDR(pa);
252 pirh = (struct pcibios_pir_header *)p;
253
254
255
256
257
258 if (pirh->signature != BIOS32_MAKESIG('$', 'P', 'I', 'R') &&
259 pirh->signature != BIOS32_MAKESIG('_', 'P', 'I', 'R'))
260 continue;
261
262 if (pirh->tablesize < sizeof(*pirh))
263 continue;
264
265 cksum = 0;
266 for (i = 0; i < pirh->tablesize; i++)
267 cksum += p[i];
268
269 printf("%s: PCI IRQ Routing Table rev %d.%d @ 0x%lx/%d "
270 "(%d entries)\n", sc->sc_dev.dv_xname,
271 pirh->version >> 8, pirh->version & 0xff, pa,
272 pirh->tablesize, (pirh->tablesize - sizeof(*pirh)) / 16);
273
274 if (cksum != 0) {
275 printf("%s: bad IRQ table checksum\n",
276 sc->sc_dev.dv_xname);
277 continue;
278 }
279
280 if (pirh->tablesize % 16 != 0) {
281 printf("%s: bad IRQ table size\n", sc->sc_dev.dv_xname);
282 continue;
283 }
284
285 if (pirh->version != 0x0100) {
286 printf("%s: unsupported IRQ table version\n",
287 sc->sc_dev.dv_xname);
288 continue;
289 }
290
291
292
293
294 pcibios_pir_header = *pirh;
295 pcibios_pir_table =
296 malloc(pirh->tablesize - sizeof(*pirh), M_DEVBUF, M_NOWAIT);
297 if (pcibios_pir_table == NULL) {
298 printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
299 return NULL;
300 }
301 bcopy(p + sizeof(*pirh), pcibios_pir_table,
302 pirh->tablesize - sizeof(*pirh));
303 pcibios_pir_table_nentries =
304 (pirh->tablesize - sizeof(*pirh)) / 16;
305
306 }
307
308
309
310
311
312
313
314
315 if (pcibios_pir_table == NULL) {
316
317 pcibios_pir_table_nentries = 32;
318 pcibios_pir_table = malloc(pcibios_pir_table_nentries *
319 sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT);
320 if (pcibios_pir_table == NULL) {
321 printf("%s: no memory for $PIR\n", sc->sc_dev.dv_xname);
322 return NULL;
323 }
324 if (pcibios_get_intr_routing(sc, pcibios_pir_table,
325 &pcibios_pir_table_nentries,
326 &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) {
327 printf("%s: PCI IRQ Routing information unavailable.\n",
328 sc->sc_dev.dv_xname);
329 free(pcibios_pir_table, M_DEVBUF);
330 pcibios_pir_table = NULL;
331 pcibios_pir_table_nentries = 0;
332 return NULL;
333 }
334 printf("%s: PCI BIOS has %d Interrupt Routing table entries\n",
335 sc->sc_dev.dv_xname, pcibios_pir_table_nentries);
336 }
337
338 pcibios_print_exclirq(sc);
339 if (pcibios_flags & PCIBIOS_INTRDEBUG)
340 pcibios_print_pir_table();
341 return pcibios_pir_table;
342 }
343
344 int
345 pcibios_get_status(struct pcibios_softc *sc, u_int32_t *rev_maj,
346 u_int32_t *rev_min, u_int32_t *mech1, u_int32_t *mech2, u_int32_t *scmech1,
347 u_int32_t *scmech2, u_int32_t *maxbus)
348 {
349 u_int32_t ax, bx, cx, edx;
350 int rv;
351
352 __asm __volatile("pushl %%es\n\t"
353 "pushl %%ds\n\t"
354 "movw 4(%%edi), %%cx\n\t"
355 "movl %%ecx, %%ds\n\t"
356 "lcall %%cs:*(%%edi)\n\t"
357 "pop %%ds\n\t"
358 "pop %%es\n\t"
359 "jc 1f\n\t"
360 "xor %%ah, %%ah\n"
361 "1:"
362 : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx)
363 : "0" (0xb101), "D" (&pcibios_entry)
364 : "cc", "memory");
365
366 rv = pcibios_return_code(sc, ax, "pcibios_get_status");
367 if (rv != PCIBIOS_SUCCESS)
368 return (rv);
369
370 if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' '))
371 return (PCIBIOS_SERVICE_NOT_PRESENT);
372
373
374
375
376 *mech1 = ax & 1;
377 *mech2 = ax & (1 << 1);
378 *scmech1 = ax & (1 << 4);
379 *scmech2 = ax & (1 << 5);
380 *rev_maj = (bx >> 8) & 0xff;
381 *rev_min = bx & 0xff;
382 *maxbus = cx & 0xff;
383
384 return (PCIBIOS_SUCCESS);
385 }
386
387 int
388 pcibios_get_intr_routing(struct pcibios_softc *sc,
389 struct pcibios_intr_routing *table, int *nentries, u_int16_t *exclirq)
390 {
391 u_int32_t ax, bx;
392 int rv;
393 struct {
394 u_int16_t size;
395 u_int32_t offset;
396 u_int16_t segment;
397 } __attribute__((__packed__)) args;
398
399 args.size = *nentries * sizeof(*table);
400 args.offset = (u_int32_t)table;
401 args.segment = GSEL(GDATA_SEL, SEL_KPL);
402
403 memset(table, 0, args.size);
404
405 __asm __volatile("pushl %%es\n\t"
406 "pushl %%ds\n\t"
407 "movw 4(%%esi), %%cx\n\t"
408 "movl %%ecx, %%ds\n\t"
409 "lcall %%cs:*(%%esi)\n\t"
410 "popl %%ds\n\t"
411 "popl %%es\n\t"
412 "jc 1f\n\t"
413 "xor %%ah, %%ah\n"
414 "1:\n"
415 : "=a" (ax), "=b" (bx)
416 : "0" (0xb10e), "1" (0), "D" (&args), "S" (&pcibios_entry)
417 : "%ecx", "%edx", "cc", "memory");
418
419 rv = pcibios_return_code(sc, ax, "pcibios_get_intr_routing");
420 if (rv != PCIBIOS_SUCCESS)
421 return (rv);
422
423 *nentries = args.size / sizeof(*table);
424 *exclirq |= bx;
425
426 return (PCIBIOS_SUCCESS);
427 }
428
429 int
430 pcibios_return_code(struct pcibios_softc *sc, u_int16_t ax, const char *func)
431 {
432 const char *errstr;
433 int rv = ax >> 8;
434 char *nam;
435
436 if (sc)
437 nam = sc->sc_dev.dv_xname;
438 else
439 nam = "pcibios0";
440
441 switch (rv) {
442 case PCIBIOS_SUCCESS:
443 return (PCIBIOS_SUCCESS);
444
445 case PCIBIOS_SERVICE_NOT_PRESENT:
446 errstr = "service not present";
447 break;
448
449 case PCIBIOS_FUNCTION_NOT_SUPPORTED:
450 errstr = "function not supported";
451 break;
452
453 case PCIBIOS_BAD_VENDOR_ID:
454 errstr = "bad vendor ID";
455 break;
456
457 case PCIBIOS_DEVICE_NOT_FOUND:
458 errstr = "device not found";
459 break;
460
461 case PCIBIOS_BAD_REGISTER_NUMBER:
462 errstr = "bad register number";
463 break;
464
465 case PCIBIOS_SET_FAILED:
466 errstr = "set failed";
467 break;
468
469 case PCIBIOS_BUFFER_TOO_SMALL:
470 errstr = "buffer too small";
471 break;
472
473 default:
474 printf("%s: %s - unknown return code 0x%x\n",
475 nam, func, rv);
476 return (rv);
477 }
478
479 printf("%s: %s - %s\n", nam, func, errstr);
480 return (rv);
481 }
482
483 void
484 pcibios_print_exclirq(struct pcibios_softc *sc)
485 {
486 int i;
487
488 if (pcibios_pir_header.exclusive_irq) {
489 printf("%s: PCI Exclusive IRQs:", sc->sc_dev.dv_xname);
490 for (i = 0; i < 16; i++) {
491 if (pcibios_pir_header.exclusive_irq & (1 << i))
492 printf(" %d", i);
493 }
494 printf("\n");
495 }
496 }
497
498 void
499 pcibios_print_pir_table(void)
500 {
501 int i, j;
502
503 for (i = 0; i < pcibios_pir_table_nentries; i++) {
504 printf("PIR Entry %d:\n", i);
505 printf("\tBus: %d Device: %d\n",
506 pcibios_pir_table[i].bus,
507 PIR_DEVFUNC_DEVICE(pcibios_pir_table[i].device));
508 for (j = 0; j < 4; j++) {
509 printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n",
510 'A' + j,
511 pcibios_pir_table[i].linkmap[j].link,
512 pcibios_pir_table[i].linkmap[j].bitmap);
513 }
514 }
515 }
516
517 void
518 pci_device_foreach(struct pcibios_softc *sc, pci_chipset_tag_t pc, int maxbus,
519 void (*func)(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t))
520 {
521 const struct pci_quirkdata *qd;
522 int bus, device, function, maxdevs, nfuncs;
523 pcireg_t id, bhlcr;
524 pcitag_t tag;
525
526 for (bus = 0; bus <= maxbus; bus++) {
527 maxdevs = pci_bus_maxdevs(pc, bus);
528 for (device = 0; device < maxdevs; device++) {
529 tag = pci_make_tag(pc, bus, device, 0);
530 id = pci_conf_read(pc, tag, PCI_ID_REG);
531
532
533 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
534 continue;
535
536 if (PCI_VENDOR(id) == 0)
537 continue;
538
539 qd = pci_lookup_quirkdata(PCI_VENDOR(id),
540 PCI_PRODUCT(id));
541
542 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
543 if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
544 (qd != NULL &&
545 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
546 nfuncs = 8;
547 else
548 nfuncs = 1;
549
550 for (function = 0; function < nfuncs; function++) {
551 tag = pci_make_tag(pc, bus, device, function);
552 id = pci_conf_read(pc, tag, PCI_ID_REG);
553
554
555 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
556 continue;
557
558
559
560
561 if (PCI_VENDOR(id) == 0)
562 continue;
563 (*func)(sc, pc, tag);
564 }
565 }
566 }
567 }