File:
[DragonFly] /
src /
sys /
bus /
pci /
i386 /
pcibus.c
Revision
1.10:
download - view:
text,
annotated -
select for diffs
Sat Feb 21 06:37:06 2004 UTC (9 years, 3 months ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
Synchronize a bunch of things from FreeBSD-5 in preparation for the new
ACPICA driver support.
* Bring in a lot of new bus and pci DEV_METHODs from FreeBSD-5
* split apic.h into apicreg.h and apicio.h
* rename INTR_TYPE_FAST -> INTR_FAST and move the #define
* rename INTR_TYPE_EXCL -> INTR_EXCL and move the #define
* rename some PCIR_ registers and add additional macros from FreeBSD-5
* note: new pcib bus call, host_pcib_get_busno() imported.
* kern/subr_power.c no longer optional.
Other changes:
* machine/smp.h machine smp/smptests.h can now be #included unconditionally,
and some APIC_IO vs SMP separation has been done as well.
* gd_acpi_id and gd_apic_id added to machine/globaldata.h prep for new
ACPI code.
Despite all the changes, the generated code should be virtually the same.
These were mostly additions which the pre-existing code does not (yet) use.
1: /*
2: * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice unmodified, this list of conditions, and the following
10: * disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: *
26: * $FreeBSD: src/sys/i386/isa/pcibus.c,v 1.57.2.12 2003/08/07 06:19:26 imp Exp $
27: * $DragonFly: src/sys/bus/pci/i386/pcibus.c,v 1.10 2004/02/21 06:37:06 dillon Exp $
28: *
29: */
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/bus.h>
34: #include <sys/kernel.h>
35: #include <sys/malloc.h>
36:
37: #include <bus/pci/pcivar.h>
38: #include <bus/pci/pcireg.h>
39: #include <bus/pci/i386/pcibus.h>
40: #include <bus/isa/isavar.h>
41: #include <bus/pci/i386/pci_cfgreg.h>
42: #include <machine/md_var.h>
43: #include <machine/nexusvar.h>
44:
45: #include "pcib_if.h"
46:
47: static int
48: nexus_pcib_maxslots(device_t dev)
49: {
50: return 31;
51: }
52:
53: /*
54: * Read configuration space register.
55: */
56: static u_int32_t
57: nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
58: int reg, int bytes)
59: {
60: return (pci_cfgregread(bus, slot, func, reg, bytes));
61: }
62:
63: /*
64: * Write configuration space register.
65: */
66: static void
67: nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
68: int reg, u_int32_t data, int bytes)
69: {
70: pci_cfgregwrite(bus, slot, func, reg, data, bytes);
71: }
72:
73: static devclass_t pcib_devclass;
74:
75: static const char *
76: nexus_pcib_is_host_bridge(int bus, int slot, int func,
77: u_int32_t id, u_int8_t class, u_int8_t subclass,
78: u_int8_t *busnum)
79: {
80: const char *s = NULL;
81: static u_int8_t pxb[4]; /* hack for 450nx */
82:
83: *busnum = 0;
84:
85: switch (id) {
86: case 0x12258086:
87: s = "Intel 824?? host to PCI bridge";
88: /* XXX This is a guess */
89: /* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
90: *busnum = bus;
91: break;
92: case 0x71208086:
93: s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
94: break;
95: case 0x71228086:
96: s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
97: break;
98: case 0x71248086:
99: s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
100: break;
101: case 0x71808086:
102: s = "Intel 82443LX (440 LX) host to PCI bridge";
103: break;
104: case 0x71908086:
105: s = "Intel 82443BX (440 BX) host to PCI bridge";
106: break;
107: case 0x71928086:
108: s = "Intel 82443BX host to PCI bridge (AGP disabled)";
109: break;
110: case 0x71948086:
111: s = "Intel 82443MX host to PCI bridge";
112: break;
113: case 0x71a08086:
114: s = "Intel 82443GX host to PCI bridge";
115: break;
116: case 0x71a18086:
117: s = "Intel 82443GX host to AGP bridge";
118: break;
119: case 0x71a28086:
120: s = "Intel 82443GX host to PCI bridge (AGP disabled)";
121: break;
122: case 0x84c48086:
123: s = "Intel 82454KX/GX (Orion) host to PCI bridge";
124: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
125: break;
126: case 0x84ca8086:
127: /*
128: * For the 450nx chipset, there is a whole bundle of
129: * things pretending to be host bridges. The MIOC will
130: * be seen first and isn't really a pci bridge (the
131: * actual busses are attached to the PXB's). We need to
132: * read the registers of the MIOC to figure out the
133: * bus numbers for the PXB channels.
134: *
135: * Since the MIOC doesn't have a pci bus attached, we
136: * pretend it wasn't there.
137: */
138: pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
139: 0xd0, 1); /* BUSNO[0] */
140: pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
141: 0xd1, 1) + 1; /* SUBA[0]+1 */
142: pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
143: 0xd3, 1); /* BUSNO[1] */
144: pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
145: 0xd4, 1) + 1; /* SUBA[1]+1 */
146: return NULL;
147: case 0x84cb8086:
148: switch (slot) {
149: case 0x12:
150: s = "Intel 82454NX PXB#0, Bus#A";
151: *busnum = pxb[0];
152: break;
153: case 0x13:
154: s = "Intel 82454NX PXB#0, Bus#B";
155: *busnum = pxb[1];
156: break;
157: case 0x14:
158: s = "Intel 82454NX PXB#1, Bus#A";
159: *busnum = pxb[2];
160: break;
161: case 0x15:
162: s = "Intel 82454NX PXB#1, Bus#B";
163: *busnum = pxb[3];
164: break;
165: }
166: break;
167: case 0x1A308086:
168: s = "Intel 82845 Host to PCI bridge";
169: break;
170:
171: /* AMD -- vendor 0x1022 */
172: case 0x30001022:
173: s = "AMD Elan SC520 host to PCI bridge";
174: #ifdef CPU_ELAN
175: init_AMD_Elan_sc520();
176: #else
177: printf("*** WARNING: kernel option CPU_ELAN missing");
178: printf("-- timekeeping may be wrong\n");
179: #endif
180: break;
181: case 0x70061022:
182: s = "AMD-751 host to PCI bridge";
183: break;
184: case 0x700e1022:
185: s = "AMD-761 host to PCI bridge";
186: break;
187:
188: /* SiS -- vendor 0x1039 */
189: case 0x04961039:
190: s = "SiS 85c496";
191: break;
192: case 0x04061039:
193: s = "SiS 85c501";
194: break;
195: case 0x06011039:
196: s = "SiS 85c601";
197: break;
198: case 0x55911039:
199: s = "SiS 5591 host to PCI bridge";
200: break;
201: case 0x00011039:
202: s = "SiS 5591 host to AGP bridge";
203: break;
204:
205: /* VLSI -- vendor 0x1004 */
206: case 0x00051004:
207: s = "VLSI 82C592 Host to PCI bridge";
208: break;
209:
210: /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
211: /* totally. Please let me know if anything wrong. -F */
212: /* XXX need info on the MVP3 -- any takers? */
213: case 0x05981106:
214: s = "VIA 82C598MVP (Apollo MVP3) host bridge";
215: break;
216:
217: /* AcerLabs -- vendor 0x10b9 */
218: /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
219: /* id is '10b9" but the register always shows "10b9". -Foxfair */
220: case 0x154110b9:
221: s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
222: break;
223:
224: /* OPTi -- vendor 0x1045 */
225: case 0xc7011045:
226: s = "OPTi 82C700 host to PCI bridge";
227: break;
228: case 0xc8221045:
229: s = "OPTi 82C822 host to PCI Bridge";
230: break;
231:
232: /* ServerWorks -- vendor 0x1166 */
233: case 0x00051166:
234: s = "ServerWorks NB6536 2.0HE host to PCI bridge";
235: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
236: break;
237:
238: case 0x00061166:
239: /* FALLTHROUGH */
240: case 0x00081166:
241: s = "ServerWorks host to PCI bridge";
242: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
243: break;
244:
245: case 0x00091166:
246: s = "ServerWorks NB6635 3.0LE host to PCI bridge";
247: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
248: break;
249:
250: case 0x00101166:
251: s = "ServerWorks CIOB30 host to PCI bridge";
252: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
253: break;
254:
255: /* XXX unknown chipset, but working */
256: case 0x00171166:
257: /* FALLTHROUGH */
258: case 0x01011166:
259: s = "ServerWorks host to PCI bridge(unknown chipset)";
260: *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
261: break;
262:
263: /* Integrated Micro Solutions -- vendor 0x10e0 */
264: case 0x884910e0:
265: s = "Integrated Micro Solutions VL Bridge";
266: break;
267:
268: default:
269: if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
270: s = "Host to PCI bridge";
271: break;
272: }
273:
274: return s;
275: }
276:
277: /*
278: * Scan the first pci bus for host-pci bridges and add pcib instances
279: * to the nexus for each bridge.
280: */
281: static void
282: nexus_pcib_identify(driver_t *driver, device_t parent)
283: {
284: int bus, slot, func;
285: u_int8_t hdrtype;
286: int found = 0;
287: int pcifunchigh;
288: int found824xx = 0;
289: device_t child;
290: devclass_t pci_devclass;
291:
292: if (pci_cfgregopen() == 0)
293: return;
294: /*
295: * Check to see if we haven't already had a PCI bus added
296: * via some other means. If we have, bail since otherwise
297: * we're going to end up duplicating it.
298: */
299: if ((pci_devclass = devclass_find("pci")) &&
300: devclass_get_device(pci_devclass,0))
301: return;
302:
303: bus = 0;
304: retry:
305: for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
306: func = 0;
307: hdrtype = nexus_pcib_read_config(0, bus, slot, func,
308: PCIR_HDRTYPE, 1);
309: if ((hdrtype & ~PCIM_MFDEV) > 2)
310: continue;
311: if (hdrtype & PCIM_MFDEV)
312: pcifunchigh = 7;
313: else
314: pcifunchigh = 0;
315: for (func = 0; func <= pcifunchigh; func++) {
316: /*
317: * Read the IDs and class from the device.
318: */
319: u_int32_t id;
320: u_int8_t class, subclass, busnum;
321: const char *s;
322: device_t *devs;
323: int ndevs, i;
324:
325: id = nexus_pcib_read_config(0, bus, slot, func,
326: PCIR_DEVVENDOR, 4);
327: if (id == -1)
328: continue;
329: class = nexus_pcib_read_config(0, bus, slot, func,
330: PCIR_CLASS, 1);
331: subclass = nexus_pcib_read_config(0, bus, slot, func,
332: PCIR_SUBCLASS, 1);
333:
334: s = nexus_pcib_is_host_bridge(bus, slot, func,
335: id, class, subclass,
336: &busnum);
337: if (s == NULL)
338: continue;
339:
340: /*
341: * Check to see if the physical bus has already
342: * been seen. Eg: hybrid 32 and 64 bit host
343: * bridges to the same logical bus.
344: */
345: if (device_get_children(parent, &devs, &ndevs) == 0) {
346: for (i = 0; s != NULL && i < ndevs; i++) {
347: if (strcmp(device_get_name(devs[i]),
348: "pcib") != 0)
349: continue;
350: if (nexus_get_pcibus(devs[i]) == busnum)
351: s = NULL;
352: }
353: free(devs, M_TEMP);
354: }
355:
356: if (s == NULL)
357: continue;
358: /*
359: * Add at priority 100+busnum to make sure we
360: * go after any motherboard resources. This also
361: * causes us to scan the pci bridges in bus order,
362: * for debug output sanity.
363: */
364: child = BUS_ADD_CHILD(parent, 100 + busnum,
365: "pcib", busnum);
366: device_set_desc(child, s);
367: nexus_set_pcibus(child, busnum);
368:
369: found = 1;
370: if (id == 0x12258086)
371: found824xx = 1;
372: }
373: }
374: if (found824xx && bus == 0) {
375: bus++;
376: goto retry;
377: }
378:
379: /*
380: * Make sure we add at least one bridge since some old
381: * hardware doesn't actually have a host-pci bridge device.
382: * Note that pci_cfgregopen() thinks we have PCI devices..
383: */
384: if (!found) {
385: if (bootverbose)
386: printf(
387: "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
388: child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
389: nexus_set_pcibus(child, 0);
390: }
391: }
392:
393: static int
394: nexus_pcib_probe(device_t dev)
395: {
396: devclass_t pci_devclass;
397:
398: if (pci_cfgregopen() == 0)
399: return (ENXIO);
400: /*
401: * Check to see if we haven't already had a PCI bus added
402: * via some other means. If we have, bail since otherwise
403: * we're going to end up duplicating it.
404: */
405: if ((pci_devclass = devclass_find("pci")) &&
406: devclass_get_device(pci_devclass, device_get_unit(dev)))
407: return (ENXIO);
408:
409: return (0);
410: }
411:
412: static int
413: nexus_pcib_attach(device_t dev)
414: {
415: device_t child;
416:
417: child = device_add_child(dev, "pci", device_get_unit(dev));
418:
419: return (bus_generic_attach(dev));
420: }
421:
422: static int
423: nexus_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
424: {
425: switch (which) {
426: case PCIB_IVAR_BUS:
427: *result = nexus_get_pcibus(dev);
428: return (0);
429: }
430: return (ENOENT);
431: }
432:
433: static int
434: nexus_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
435: {
436: switch (which) {
437: case PCIB_IVAR_BUS:
438: nexus_set_pcibus(dev, value);
439: return (0);
440: }
441: return (ENOENT);
442: }
443:
444: /* route interrupt */
445:
446: static int
447: nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
448: {
449: return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
450: pci_get_irq(dev)));
451: }
452:
453: static device_method_t nexus_pcib_methods[] = {
454: /* Device interface */
455: DEVMETHOD(device_identify, nexus_pcib_identify),
456: DEVMETHOD(device_probe, nexus_pcib_probe),
457: DEVMETHOD(device_attach, nexus_pcib_attach),
458: DEVMETHOD(device_shutdown, bus_generic_shutdown),
459: DEVMETHOD(device_suspend, bus_generic_suspend),
460: DEVMETHOD(device_resume, bus_generic_resume),
461:
462: /* Bus interface */
463: DEVMETHOD(bus_print_child, bus_generic_print_child),
464: DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
465: DEVMETHOD(bus_write_ivar, nexus_pcib_write_ivar),
466: DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
467: DEVMETHOD(bus_release_resource, bus_generic_release_resource),
468: DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
469: DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
470: DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
471: DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
472:
473: /* pcib interface */
474: DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
475: DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
476: DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
477: DEVMETHOD(pcib_route_interrupt, nexus_pcib_route_interrupt),
478:
479: { 0, 0 }
480: };
481:
482: static driver_t nexus_pcib_driver = {
483: "pcib",
484: nexus_pcib_methods,
485: 1,
486: };
487:
488: DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
489:
490:
491: /*
492: * Provide a device to "eat" the host->pci bridges that we dug up above
493: * and stop them showing up twice on the probes. This also stops them
494: * showing up as 'none' in pciconf -l.
495: */
496: static int
497: pci_hostb_probe(device_t dev)
498: {
499: if (pci_get_class(dev) == PCIC_BRIDGE &&
500: pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
501: device_set_desc(dev, "Host to PCI bridge");
502: device_quiet(dev);
503: return 0;
504: }
505: return (ENXIO);
506: }
507:
508: static int
509: pci_hostb_attach(device_t dev)
510: {
511: return (0);
512: }
513:
514: static device_method_t pci_hostb_methods[] = {
515: /* Device interface */
516: DEVMETHOD(device_probe, pci_hostb_probe),
517: DEVMETHOD(device_attach, pci_hostb_attach),
518: DEVMETHOD(device_shutdown, bus_generic_shutdown),
519: DEVMETHOD(device_suspend, bus_generic_suspend),
520: DEVMETHOD(device_resume, bus_generic_resume),
521:
522: { 0, 0 }
523: };
524: static driver_t pci_hostb_driver = {
525: "hostb",
526: pci_hostb_methods,
527: 1,
528: };
529: static devclass_t pci_hostb_devclass;
530:
531: DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0);
532:
533:
534: /*
535: * Install placeholder to claim the resources owned by the
536: * PCI bus interface. This could be used to extract the
537: * config space registers in the extreme case where the PnP
538: * ID is available and the PCI BIOS isn't, but for now we just
539: * eat the PnP ID and do nothing else.
540: *
541: * XXX we should silence this probe, as it will generally confuse
542: * people.
543: */
544: static struct isa_pnp_id pcibus_pnp_ids[] = {
545: { 0x030ad041 /* PNP030A */, "PCI Bus" },
546: { 0 }
547: };
548:
549: static int
550: pcibus_pnp_probe(device_t dev)
551: {
552: int result;
553:
554: if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
555: device_quiet(dev);
556: return (result);
557: }
558:
559: static int
560: pcibus_pnp_attach(device_t dev)
561: {
562: return(0);
563: }
564:
565: static device_method_t pcibus_pnp_methods[] = {
566: /* Device interface */
567: DEVMETHOD(device_probe, pcibus_pnp_probe),
568: DEVMETHOD(device_attach, pcibus_pnp_attach),
569: DEVMETHOD(device_detach, bus_generic_detach),
570: DEVMETHOD(device_shutdown, bus_generic_shutdown),
571: DEVMETHOD(device_suspend, bus_generic_suspend),
572: DEVMETHOD(device_resume, bus_generic_resume),
573: { 0, 0 }
574: };
575:
576: static driver_t pcibus_pnp_driver = {
577: "pcibus_pnp",
578: pcibus_pnp_methods,
579: 1, /* no softc */
580: };
581:
582: static devclass_t pcibus_pnp_devclass;
583:
584: DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);