2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
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.
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.
30 #include <sys/param.h>
31 #include <sys/systm.h>
33 #include <sys/kernel.h>
35 #include <pci/pcivar.h>
36 #include <pci/pcireg.h>
37 #include <i386/isa/pcibus.h>
42 /* enable configuration space accesses and return data port address */
45 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
51 && func <= PCI_FUNCMAX
54 && (unsigned) bytes <= 4
55 && (reg & (bytes -1)) == 0) {
58 outl(CONF1_ADDR_PORT, (1 << 31)
59 | (bus << 16) | (slot << 11)
60 | (func << 8) | (reg & ~0x03));
61 dataport = CONF1_DATA_PORT + (reg & 0x03);
64 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
65 outb(CONF2_FORWARD_PORT, bus);
66 dataport = 0xc000 | (slot << 8) | reg;
73 /* disable configuration space accesses */
80 outl(CONF1_ADDR_PORT, 0);
83 outb(CONF2_ENABLE_PORT, 0);
84 outb(CONF2_FORWARD_PORT, 0);
89 /* read configuration space register */
92 pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
97 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
116 /* write configuration space register */
119 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
123 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
140 /* check whether the configuration mechanism has been correct identified */
143 pci_cfgcheck(int maxdev)
148 printf("pci_cfgcheck:\tdevice ");
150 for (device = 0; device < maxdev; device++) {
151 unsigned id, class, header;
153 printf("%d ", device);
155 id = inl(pci_cfgenable(0, device, 0, 0, 4));
156 if (id == 0 || id == -1)
159 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
161 printf("[class=%06x] ", class);
162 if (class == 0 || (class & 0xf870ff) != 0)
165 header = inb(pci_cfgenable(0, device, 0, 14, 1));
167 printf("[hdr=%02x] ", header);
168 if ((header & 0x7e) != 0)
172 printf("is there (id=%08x)\n", id);
178 printf("-- nothing found\n");
187 unsigned long mode1res,oldval1;
188 unsigned char mode2res,oldval2;
190 oldval1 = inl(CONF1_ADDR_PORT);
193 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
197 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
202 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
203 outb(CONF1_ADDR_PORT +3, 0);
204 mode1res = inl(CONF1_ADDR_PORT);
205 outl(CONF1_ADDR_PORT, oldval1);
208 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
209 mode1res, CONF1_ENABLE_CHK);
212 if (pci_cfgcheck(32))
216 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
217 mode1res = inl(CONF1_ADDR_PORT);
218 outl(CONF1_ADDR_PORT, oldval1);
221 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
222 mode1res, CONF1_ENABLE_CHK1);
224 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
225 if (pci_cfgcheck(32))
230 oldval2 = inb(CONF2_ENABLE_PORT);
233 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
237 if ((oldval2 & 0xf0) == 0) {
242 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
243 mode2res = inb(CONF2_ENABLE_PORT);
244 outb(CONF2_ENABLE_PORT, oldval2);
247 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
248 mode2res, CONF2_ENABLE_CHK);
250 if (mode2res == CONF2_ENABLE_RES) {
252 printf("pci_open(2a):\tnow trying mechanism 2\n");
254 if (pci_cfgcheck(16))
264 static devclass_t pcib_devclass;
267 nexus_pcib_is_host_bridge(pcicfgregs *cfg,
268 u_int32_t id, u_int8_t class, u_int8_t subclass,
271 const char *s = NULL;
272 static u_int8_t pxb[4]; /* hack for 450nx */
278 s = "Intel 824?? host to PCI bridge";
279 /* XXX This is a guess */
280 /* *busnum = pci_cfgread(cfg, 0x41, 1); */
284 s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
287 s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
290 s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
293 s = "Intel 82443LX (440 LX) host to PCI bridge";
296 s = "Intel 82443BX (440 BX) host to PCI bridge";
299 s = "Intel 82443BX host to PCI bridge (AGP disabled)";
302 s = "Intel 82443GX host to PCI bridge";
305 s = "Intel 82443GX host to AGP bridge";
308 s = "Intel 82443GX host to PCI bridge (AGP disabled)";
311 s = "Intel 82454KX/GX (Orion) host to PCI bridge";
312 *busnum = pci_cfgread(cfg, 0x4a, 1);
316 * For the 450nx chipset, there is a whole bundle of
317 * things pretending to be host bridges. The MIOC will
318 * be seen first and isn't really a pci bridge (the
319 * actual busses are attached to the PXB's). We need to
320 * read the registers of the MIOC to figure out the
321 * bus numbers for the PXB channels.
323 * Since the MIOC doesn't have a pci bus attached, we
324 * pretend it wasn't there.
326 pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
327 pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
328 pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
329 pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
334 s = "Intel 82454NX PXB#0, Bus#A";
338 s = "Intel 82454NX PXB#0, Bus#B";
342 s = "Intel 82454NX PXB#1, Bus#A";
346 s = "Intel 82454NX PXB#1, Bus#B";
352 /* AMD -- vendor 0x1022 */
354 s = "AMD-751 host to PCI bridge";
357 /* SiS -- vendor 0x1039 */
368 s = "SiS 5591 host to PCI bridge";
371 s = "SiS 5591 host to AGP bridge";
374 /* VLSI -- vendor 0x1004 */
376 s = "VLSI 82C592 Host to PCI bridge";
379 /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
380 /* totally. Please let me know if anything wrong. -F */
381 /* XXX need info on the MVP3 -- any takers? */
383 s = "VIA 82C598MVP (Apollo MVP3) host bridge";
386 /* AcerLabs -- vendor 0x10b9 */
387 /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
388 /* id is '10b9" but the register always shows "10b9". -Foxfair */
390 s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
393 /* OPTi -- vendor 0x1045 */
395 s = "OPTi 82C822 host to PCI Bridge";
398 /* RCC -- vendor 0x1166 */
400 s = "RCC HE host to PCI bridge";
401 *busnum = pci_cfgread(cfg, 0x44, 1);
407 s = "RCC host to PCI bridge";
408 *busnum = pci_cfgread(cfg, 0x44, 1);
412 s = "RCC LE host to PCI bridge";
413 *busnum = pci_cfgread(cfg, 0x44, 1);
416 /* Integrated Micro Solutions -- vendor 0x10e0 */
418 s = "Integrated Micro Solutions VL Bridge";
422 if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
423 s = "Host to PCI bridge";
431 * Scan the first pci bus for host-pci bridges and add pcib instances
432 * to the nexus for each bridge.
435 nexus_pcib_identify(driver_t *driver, device_t parent)
443 if (pci_cfgopen() == 0)
448 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
450 hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
451 if (hdrtype & PCIM_MFDEV)
456 probe.func <= pcifunchigh;
459 * Read the IDs and class from the device.
462 u_int8_t class, subclass, busnum;
466 id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
469 class = pci_cfgread(&probe, PCIR_CLASS, 1);
470 subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
472 s = nexus_pcib_is_host_bridge(&probe, id,
477 * Add at priority 100 to make sure we
478 * go after any motherboard resources
480 child = BUS_ADD_CHILD(parent, 100,
482 device_set_desc(child, s);
484 if (id == 0x12258086)
489 if (found824xx && probe.bus == 0) {
495 * Make sure we add at least one bridge since some old
496 * hardware doesn't actually have a host-pci bridge device.
497 * Note that pci_cfgopen() thinks we have PCI devices..
502 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
503 BUS_ADD_CHILD(parent, 100, "pcib", 0);
508 nexus_pcib_probe(device_t dev)
510 if (pci_cfgopen() != 0) {
511 device_add_child(dev, "pci", device_get_unit(dev));
517 static device_method_t nexus_pcib_methods[] = {
518 /* Device interface */
519 DEVMETHOD(device_identify, nexus_pcib_identify),
520 DEVMETHOD(device_probe, nexus_pcib_probe),
521 DEVMETHOD(device_attach, bus_generic_attach),
522 DEVMETHOD(device_shutdown, bus_generic_shutdown),
523 DEVMETHOD(device_suspend, bus_generic_suspend),
524 DEVMETHOD(device_resume, bus_generic_resume),
527 DEVMETHOD(bus_print_child, bus_generic_print_child),
528 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
529 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
530 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
531 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
532 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
533 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
538 static driver_t nexus_pcib_driver = {
544 DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);