pci_subr.c revision 164264
147061Sbrian/*-
247061Sbrian * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
347061Sbrian * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
447061Sbrian * Copyright (c) 2000 BSDi
547061Sbrian * All rights reserved.
647061Sbrian *
747061Sbrian * Redistribution and use in source and binary forms, with or without
847061Sbrian * modification, are permitted provided that the following conditions
947061Sbrian * are met:
1047061Sbrian * 1. Redistributions of source code must retain the above copyright
1147061Sbrian *    notice, this list of conditions and the following disclaimer.
1247061Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1347061Sbrian *    notice, this list of conditions and the following disclaimer in the
1447061Sbrian *    documentation and/or other materials provided with the distribution.
1547061Sbrian * 3. The name of the author may not be used to endorse or promote products
1647061Sbrian *    derived from this software without specific prior written permission.
1747061Sbrian *
1847061Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1947061Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2047061Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2147061Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2247061Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2347061Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2447061Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2547061Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2647461Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2747061Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2847061Sbrian * SUCH DAMAGE.
2947061Sbrian */
3047061Sbrian
3147061Sbrian#include <sys/cdefs.h>
3247061Sbrian__FBSDID("$FreeBSD: head/sys/dev/pci/pci_pci.c 164264 2006-11-13 21:47:30Z jhb $");
3347061Sbrian
3447061Sbrian/*
3547061Sbrian * PCI:PCI bridge support.
3647061Sbrian */
3747061Sbrian
3847061Sbrian#include <sys/param.h>
3947061Sbrian#include <sys/systm.h>
4047061Sbrian#include <sys/kernel.h>
4147061Sbrian#include <sys/module.h>
4247061Sbrian#include <sys/bus.h>
4347061Sbrian#include <machine/bus.h>
4447061Sbrian#include <sys/rman.h>
4547061Sbrian#include <sys/sysctl.h>
4647061Sbrian
4747061Sbrian#include <machine/resource.h>
4847061Sbrian
4947061Sbrian#include <dev/pci/pcivar.h>
5047061Sbrian#include <dev/pci/pcireg.h>
5147061Sbrian#include <dev/pci/pcib_private.h>
5247061Sbrian
5347061Sbrian#include "pcib_if.h"
5447061Sbrian
5547061Sbrianstatic int		pcib_probe(device_t dev);
5647061Sbrian
5747061Sbrianstatic device_method_t pcib_methods[] = {
5847061Sbrian    /* Device interface */
5947061Sbrian    DEVMETHOD(device_probe,		pcib_probe),
6047061Sbrian    DEVMETHOD(device_attach,		pcib_attach),
6147061Sbrian    DEVMETHOD(device_detach,		bus_generic_detach),
6247061Sbrian    DEVMETHOD(device_shutdown,		bus_generic_shutdown),
6347061Sbrian    DEVMETHOD(device_suspend,		bus_generic_suspend),
6447061Sbrian    DEVMETHOD(device_resume,		bus_generic_resume),
6547061Sbrian
6647061Sbrian    /* Bus interface */
6747061Sbrian    DEVMETHOD(bus_print_child,		bus_generic_print_child),
6847061Sbrian    DEVMETHOD(bus_read_ivar,		pcib_read_ivar),
6947061Sbrian    DEVMETHOD(bus_write_ivar,		pcib_write_ivar),
7047061Sbrian    DEVMETHOD(bus_alloc_resource,	pcib_alloc_resource),
7147061Sbrian    DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
7247061Sbrian    DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
7347061Sbrian    DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
7447061Sbrian    DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
7547061Sbrian    DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
7647061Sbrian
7747061Sbrian    /* pcib interface */
7847061Sbrian    DEVMETHOD(pcib_maxslots,		pcib_maxslots),
7947061Sbrian    DEVMETHOD(pcib_read_config,		pcib_read_config),
8047061Sbrian    DEVMETHOD(pcib_write_config,	pcib_write_config),
8147061Sbrian    DEVMETHOD(pcib_route_interrupt,	pcib_route_interrupt),
8247061Sbrian    DEVMETHOD(pcib_alloc_msi,		pcib_alloc_msi),
8347061Sbrian    DEVMETHOD(pcib_release_msi,		pcib_release_msi),
8447061Sbrian    DEVMETHOD(pcib_alloc_msix,		pcib_alloc_msix),
8547061Sbrian    DEVMETHOD(pcib_release_msix,	pcib_release_msix),
8647061Sbrian
8747061Sbrian    { 0, 0 }
8847061Sbrian};
8947061Sbrian
9047061Sbrianstatic devclass_t pcib_devclass;
9147061Sbrian
9247061SbrianDEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc));
9347061SbrianDRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
9447061Sbrian
9547061Sbrian/*
9647061Sbrian * Is the prefetch window open (eg, can we allocate memory in it?)
9747061Sbrian */
9847061Sbrianstatic int
9947061Sbrianpcib_is_prefetch_open(struct pcib_softc *sc)
10047061Sbrian{
10147061Sbrian	return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit);
10247061Sbrian}
10347061Sbrian
10447061Sbrian/*
10547061Sbrian * Is the nonprefetch window open (eg, can we allocate memory in it?)
10647061Sbrian */
10747061Sbrianstatic int
10847061Sbrianpcib_is_nonprefetch_open(struct pcib_softc *sc)
10947061Sbrian{
11047061Sbrian	return (sc->membase > 0 && sc->membase < sc->memlimit);
11147061Sbrian}
11247061Sbrian
11347061Sbrian/*
11447061Sbrian * Is the io window open (eg, can we allocate ports in it?)
11547061Sbrian */
11647061Sbrianstatic int
11747061Sbrianpcib_is_io_open(struct pcib_softc *sc)
11847061Sbrian{
11947061Sbrian	return (sc->iobase > 0 && sc->iobase < sc->iolimit);
12047061Sbrian}
12147061Sbrian
12247061Sbrian/*
12347061Sbrian * Generic device interface
12447061Sbrian */
12547061Sbrianstatic int
12647061Sbrianpcib_probe(device_t dev)
12747061Sbrian{
12847061Sbrian    if ((pci_get_class(dev) == PCIC_BRIDGE) &&
12947061Sbrian	(pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) {
13047061Sbrian	device_set_desc(dev, "PCI-PCI bridge");
13147061Sbrian	return(-10000);
13247061Sbrian    }
13347061Sbrian    return(ENXIO);
13447061Sbrian}
13547061Sbrian
13647061Sbrianvoid
13747061Sbrianpcib_attach_common(device_t dev)
13847061Sbrian{
13947461Sbrian    struct pcib_softc	*sc;
14047061Sbrian    uint8_t		iolow;
14147061Sbrian
14247461Sbrian    sc = device_get_softc(dev);
14347061Sbrian    sc->dev = dev;
14447461Sbrian
14547461Sbrian    /*
14647461Sbrian     * Get current bridge configuration.
14747061Sbrian     */
14847461Sbrian    sc->command   = pci_read_config(dev, PCIR_COMMAND, 1);
14947061Sbrian    sc->secbus    = pci_read_config(dev, PCIR_SECBUS_1, 1);
15047061Sbrian    sc->subbus    = pci_read_config(dev, PCIR_SUBBUS_1, 1);
15147061Sbrian    sc->secstat   = pci_read_config(dev, PCIR_SECSTAT_1, 2);
15247061Sbrian    sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
15347061Sbrian    sc->seclat    = pci_read_config(dev, PCIR_SECLAT_1, 1);
15447061Sbrian
15547061Sbrian    /*
15647061Sbrian     * Determine current I/O decode.
15747061Sbrian     */
15847061Sbrian    if (sc->command & PCIM_CMD_PORTEN) {
15947061Sbrian	iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1);
16047061Sbrian	if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
16147061Sbrian	    sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2),
16247061Sbrian				       pci_read_config(dev, PCIR_IOBASEL_1, 1));
16347061Sbrian	} else {
16447061Sbrian	    sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1));
16547061Sbrian	}
16647061Sbrian
16747061Sbrian	iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1);
16847061Sbrian	if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
16947061Sbrian	    sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2),
17047061Sbrian					 pci_read_config(dev, PCIR_IOLIMITL_1, 1));
17147061Sbrian	} else {
17247061Sbrian	    sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1));
17347061Sbrian	}
17447061Sbrian    }
17547061Sbrian
17647061Sbrian    /*
17747061Sbrian     * Determine current memory decode.
17847061Sbrian     */
17947061Sbrian    if (sc->command & PCIM_CMD_MEMEN) {
18047061Sbrian	sc->membase   = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2));
18147061Sbrian	sc->memlimit  = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2));
18247061Sbrian	sc->pmembase  = PCI_PPBMEMBASE(pci_read_config(dev, PCIR_PMBASEH_1, 4),
18347061Sbrian	    pci_read_config(dev, PCIR_PMBASEL_1, 2));
18447061Sbrian	sc->pmemlimit = PCI_PPBMEMLIMIT(pci_read_config(dev, PCIR_PMLIMITH_1, 4),
18547061Sbrian	    pci_read_config(dev, PCIR_PMLIMITL_1, 2));
18647061Sbrian    }
18747061Sbrian
18847061Sbrian    /*
18947061Sbrian     * Quirk handling.
19047061Sbrian     */
19147061Sbrian    switch (pci_get_devid(dev)) {
19247061Sbrian    case 0x12258086:		/* Intel 82454KX/GX (Orion) */
19347061Sbrian	{
19447061Sbrian	    uint8_t	supbus;
19547061Sbrian
19647061Sbrian	    supbus = pci_read_config(dev, 0x41, 1);
19747061Sbrian	    if (supbus != 0xff) {
19847061Sbrian		sc->secbus = supbus + 1;
19947061Sbrian		sc->subbus = supbus + 1;
20047061Sbrian	    }
20147061Sbrian	    break;
20247061Sbrian	}
20347061Sbrian
20447061Sbrian    /*
20547061Sbrian     * The i82380FB mobile docking controller is a PCI-PCI bridge,
20647061Sbrian     * and it is a subtractive bridge.  However, the ProgIf is wrong
20747061Sbrian     * so the normal setting of PCIB_SUBTRACTIVE bit doesn't
20847061Sbrian     * happen.  There's also a Toshiba bridge that behaves this
20947061Sbrian     * way.
21047061Sbrian     */
21147061Sbrian    case 0x124b8086:		/* Intel 82380FB Mobile */
21247061Sbrian    case 0x060513d7:		/* Toshiba ???? */
21347061Sbrian	sc->flags |= PCIB_SUBTRACTIVE;
21447061Sbrian	break;
21547061Sbrian
21647061Sbrian    /* Compaq R3000 BIOS sets wrong subordinate bus number. */
21747061Sbrian    case 0x00dd10de:
21847061Sbrian	{
21947061Sbrian	    char *cp;
22047061Sbrian
22147061Sbrian	    if ((cp = getenv("smbios.planar.maker")) == NULL)
22247061Sbrian		break;
22347061Sbrian	    if (strncmp(cp, "Compal", 6) != 0) {
22447061Sbrian		freeenv(cp);
22547061Sbrian		break;
22647061Sbrian	    }
22747061Sbrian	    freeenv(cp);
22847061Sbrian	    if ((cp = getenv("smbios.planar.product")) == NULL)
22947061Sbrian		break;
23047061Sbrian	    if (strncmp(cp, "08A0", 4) != 0) {
23147061Sbrian		freeenv(cp);
23247061Sbrian		break;
23347061Sbrian	    }
23447061Sbrian	    freeenv(cp);
23547061Sbrian	    if (sc->subbus < 0xa) {
23647061Sbrian		pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1);
23747061Sbrian		sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1);
23847061Sbrian	    }
23947061Sbrian	    break;
24047061Sbrian	}
24147061Sbrian    }
24247061Sbrian
24347061Sbrian    /*
24447061Sbrian     * Intel 815, 845 and other chipsets say they are PCI-PCI bridges,
24547061Sbrian     * but have a ProgIF of 0x80.  The 82801 family (AA, AB, BAM/CAM,
24647061Sbrian     * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese.
24747061Sbrian     * This means they act as if they were subtractively decoding
24847061Sbrian     * bridges and pass all transactions.  Mark them and real ProgIf 1
24947061Sbrian     * parts as subtractive.
25047061Sbrian     */
25147061Sbrian    if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 ||
25247061Sbrian      pci_read_config(dev, PCIR_PROGIF, 1) == 1)
25347061Sbrian	sc->flags |= PCIB_SUBTRACTIVE;
25447061Sbrian
25547061Sbrian    if (bootverbose) {
25647061Sbrian	device_printf(dev, "  secondary bus     %d\n", sc->secbus);
25747061Sbrian	device_printf(dev, "  subordinate bus   %d\n", sc->subbus);
25847061Sbrian	device_printf(dev, "  I/O decode        0x%x-0x%x\n", sc->iobase, sc->iolimit);
25947061Sbrian	if (pcib_is_nonprefetch_open(sc))
26047461Sbrian	    device_printf(dev, "  memory decode     0x%jx-0x%jx\n",
26147061Sbrian	      (uintmax_t)sc->membase, (uintmax_t)sc->memlimit);
26247061Sbrian	if (pcib_is_prefetch_open(sc))
26347061Sbrian	    device_printf(dev, "  prefetched decode 0x%jx-0x%jx\n",
26447061Sbrian	      (uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit);
26547061Sbrian	else
266	    device_printf(dev, "  no prefetched decode\n");
267	if (sc->flags & PCIB_SUBTRACTIVE)
268	    device_printf(dev, "  Subtractively decoded bridge.\n");
269    }
270
271    /*
272     * XXX If the secondary bus number is zero, we should assign a bus number
273     *     since the BIOS hasn't, then initialise the bridge.
274     */
275
276    /*
277     * XXX If the subordinate bus number is less than the secondary bus number,
278     *     we should pick a better value.  One sensible alternative would be to
279     *     pick 255; the only tradeoff here is that configuration transactions
280     *     would be more widely routed than absolutely necessary.
281     */
282}
283
284int
285pcib_attach(device_t dev)
286{
287    struct pcib_softc	*sc;
288    device_t		child;
289
290    pcib_attach_common(dev);
291    sc = device_get_softc(dev);
292    if (sc->secbus != 0) {
293	child = device_add_child(dev, "pci", sc->secbus);
294	if (child != NULL)
295	    return(bus_generic_attach(dev));
296    }
297
298    /* no secondary bus; we should have fixed this */
299    return(0);
300}
301
302int
303pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
304{
305    struct pcib_softc	*sc = device_get_softc(dev);
306
307    switch (which) {
308    case PCIB_IVAR_BUS:
309	*result = sc->secbus;
310	return(0);
311    }
312    return(ENOENT);
313}
314
315int
316pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
317{
318    struct pcib_softc	*sc = device_get_softc(dev);
319
320    switch (which) {
321    case PCIB_IVAR_BUS:
322	sc->secbus = value;
323	break;
324    }
325    return(ENOENT);
326}
327
328/*
329 * We have to trap resource allocation requests and ensure that the bridge
330 * is set up to, or capable of handling them.
331 */
332struct resource *
333pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
334    u_long start, u_long end, u_long count, u_int flags)
335{
336	struct pcib_softc	*sc = device_get_softc(dev);
337	const char *name, *suffix;
338	int ok;
339
340	/*
341	 * Fail the allocation for this range if it's not supported.
342	 */
343	name = device_get_nameunit(child);
344	if (name == NULL) {
345		name = "";
346		suffix = "";
347	} else
348		suffix = " ";
349	switch (type) {
350	case SYS_RES_IOPORT:
351		ok = 0;
352		if (!pcib_is_io_open(sc))
353			break;
354		ok = (start >= sc->iobase && end <= sc->iolimit);
355
356		/*
357		 * Make sure we allow access to VGA I/O addresses when the
358		 * bridge has the "VGA Enable" bit set.
359		 */
360		if (!ok && pci_is_vga_ioport_range(start, end))
361			ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0;
362
363		if ((sc->flags & PCIB_SUBTRACTIVE) == 0) {
364			if (!ok) {
365				if (start < sc->iobase)
366					start = sc->iobase;
367				if (end > sc->iolimit)
368					end = sc->iolimit;
369				if (start < end)
370					ok = 1;
371			}
372		} else {
373			ok = 1;
374#if 1
375			if (start < sc->iobase && end > sc->iolimit) {
376				start = sc->iobase;
377				end = sc->iolimit;
378			}
379#endif
380		}
381		if (end < start) {
382			device_printf(dev, "ioport: end (%lx) < start (%lx)\n",
383			    end, start);
384			start = 0;
385			end = 0;
386			ok = 0;
387		}
388		if (!ok) {
389			device_printf(dev, "%s%srequested unsupported I/O "
390			    "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n",
391			    name, suffix, start, end, sc->iobase, sc->iolimit);
392			return (NULL);
393		}
394		if (bootverbose)
395			device_printf(dev,
396			    "%s%srequested I/O range 0x%lx-0x%lx: in range\n",
397			    name, suffix, start, end);
398		break;
399
400	case SYS_RES_MEMORY:
401		ok = 0;
402		if (pcib_is_nonprefetch_open(sc))
403			ok = ok || (start >= sc->membase && end <= sc->memlimit);
404		if (pcib_is_prefetch_open(sc))
405			ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit);
406
407		/*
408		 * Make sure we allow access to VGA memory addresses when the
409		 * bridge has the "VGA Enable" bit set.
410		 */
411		if (!ok && pci_is_vga_memory_range(start, end))
412			ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0;
413
414		if ((sc->flags & PCIB_SUBTRACTIVE) == 0) {
415			if (!ok) {
416				ok = 1;
417				if (flags & RF_PREFETCHABLE) {
418					if (pcib_is_prefetch_open(sc)) {
419						if (start < sc->pmembase)
420							start = sc->pmembase;
421						if (end > sc->pmemlimit)
422							end = sc->pmemlimit;
423					} else {
424						ok = 0;
425					}
426				} else {	/* non-prefetchable */
427					if (pcib_is_nonprefetch_open(sc)) {
428						if (start < sc->membase)
429							start = sc->membase;
430						if (end > sc->memlimit)
431							end = sc->memlimit;
432					} else {
433						ok = 0;
434					}
435				}
436			}
437		} else if (!ok) {
438			ok = 1;	/* subtractive bridge: always ok */
439#if 1
440			if (pcib_is_nonprefetch_open(sc)) {
441				if (start < sc->membase && end > sc->memlimit) {
442					start = sc->membase;
443					end = sc->memlimit;
444				}
445			}
446			if (pcib_is_prefetch_open(sc)) {
447				if (start < sc->pmembase && end > sc->pmemlimit) {
448					start = sc->pmembase;
449					end = sc->pmemlimit;
450				}
451			}
452#endif
453		}
454		if (end < start) {
455			device_printf(dev, "memory: end (%lx) < start (%lx)\n",
456			    end, start);
457			start = 0;
458			end = 0;
459			ok = 0;
460		}
461		if (!ok && bootverbose)
462			device_printf(dev,
463			    "%s%srequested unsupported memory range %#lx-%#lx "
464			    "(decoding %#jx-%#jx, %#jx-%#jx)\n",
465			    name, suffix, start, end,
466			    (uintmax_t)sc->membase, (uintmax_t)sc->memlimit,
467			    (uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit);
468		if (!ok)
469			return (NULL);
470		if (bootverbose)
471			device_printf(dev,"%s%srequested memory range "
472			    "0x%lx-0x%lx: good\n",
473			    name, suffix, start, end);
474		break;
475
476	default:
477		break;
478	}
479	/*
480	 * Bridge is OK decoding this resource, so pass it up.
481	 */
482	return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
483	    count, flags));
484}
485
486/*
487 * PCIB interface.
488 */
489int
490pcib_maxslots(device_t dev)
491{
492    return(PCI_SLOTMAX);
493}
494
495/*
496 * Since we are a child of a PCI bus, its parent must support the pcib interface.
497 */
498uint32_t
499pcib_read_config(device_t dev, int b, int s, int f, int reg, int width)
500{
501    return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width));
502}
503
504void
505pcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width)
506{
507    PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width);
508}
509
510/*
511 * Route an interrupt across a PCI bridge.
512 */
513int
514pcib_route_interrupt(device_t pcib, device_t dev, int pin)
515{
516    device_t	bus;
517    int		parent_intpin;
518    int		intnum;
519
520    /*
521     *
522     * The PCI standard defines a swizzle of the child-side device/intpin to
523     * the parent-side intpin as follows.
524     *
525     * device = device on child bus
526     * child_intpin = intpin on child bus slot (0-3)
527     * parent_intpin = intpin on parent bus slot (0-3)
528     *
529     * parent_intpin = (device + child_intpin) % 4
530     */
531    parent_intpin = (pci_get_slot(dev) + (pin - 1)) % 4;
532
533    /*
534     * Our parent is a PCI bus.  Its parent must export the pcib interface
535     * which includes the ability to route interrupts.
536     */
537    bus = device_get_parent(pcib);
538    intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1);
539    if (PCI_INTERRUPT_VALID(intnum) && bootverbose) {
540	device_printf(pcib, "slot %d INT%c is routed to irq %d\n",
541	    pci_get_slot(dev), 'A' + pin - 1, intnum);
542    }
543    return(intnum);
544}
545
546/* Pass request to alloc MSI messages up to the parent bridge. */
547int
548pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
549{
550	device_t bus;
551
552	bus = device_get_parent(pcib);
553	return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
554	    irqs));
555}
556
557/* Pass request to release MSI messages up to the parent bridge. */
558int
559pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs)
560{
561	device_t bus;
562
563	bus = device_get_parent(pcib);
564	return (PCIB_RELEASE_MSI(device_get_parent(bus), dev, count, irqs));
565}
566
567/* Pass request to alloc an MSI-X message up to the parent bridge. */
568int
569pcib_alloc_msix(device_t pcib, device_t dev, int index, int *irq)
570{
571	device_t bus;
572
573	bus = device_get_parent(pcib);
574	return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, index, irq));
575}
576
577/* Pass request to release an MSI-X message up to the parent bridge. */
578int
579pcib_release_msix(device_t pcib, device_t dev, int irq)
580{
581	device_t bus;
582
583	bus = device_get_parent(pcib);
584	return (PCIB_RELEASE_MSIX(device_get_parent(bus), dev, irq));
585}
586
587/*
588 * Try to read the bus number of a host-PCI bridge using appropriate config
589 * registers.
590 */
591int
592host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
593    uint8_t *busnum)
594{
595	uint32_t id;
596
597	id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4);
598	if (id == 0xffffffff)
599		return (0);
600
601	switch (id) {
602	case 0x12258086:
603		/* Intel 824?? */
604		/* XXX This is a guess */
605		/* *busnum = read_config(bus, slot, func, 0x41, 1); */
606		*busnum = bus;
607		break;
608	case 0x84c48086:
609		/* Intel 82454KX/GX (Orion) */
610		*busnum = read_config(bus, slot, func, 0x4a, 1);
611		break;
612	case 0x84ca8086:
613		/*
614		 * For the 450nx chipset, there is a whole bundle of
615		 * things pretending to be host bridges. The MIOC will
616		 * be seen first and isn't really a pci bridge (the
617		 * actual busses are attached to the PXB's). We need to
618		 * read the registers of the MIOC to figure out the
619		 * bus numbers for the PXB channels.
620		 *
621		 * Since the MIOC doesn't have a pci bus attached, we
622		 * pretend it wasn't there.
623		 */
624		return (0);
625	case 0x84cb8086:
626		switch (slot) {
627		case 0x12:
628			/* Intel 82454NX PXB#0, Bus#A */
629			*busnum = read_config(bus, 0x10, func, 0xd0, 1);
630			break;
631		case 0x13:
632			/* Intel 82454NX PXB#0, Bus#B */
633			*busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1;
634			break;
635		case 0x14:
636			/* Intel 82454NX PXB#1, Bus#A */
637			*busnum = read_config(bus, 0x10, func, 0xd3, 1);
638			break;
639		case 0x15:
640			/* Intel 82454NX PXB#1, Bus#B */
641			*busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1;
642			break;
643		}
644		break;
645
646		/* ServerWorks -- vendor 0x1166 */
647	case 0x00051166:
648	case 0x00061166:
649	case 0x00081166:
650	case 0x00091166:
651	case 0x00101166:
652	case 0x00111166:
653	case 0x00171166:
654	case 0x01011166:
655	case 0x010f1014:
656	case 0x02011166:
657	case 0x03021014:
658		*busnum = read_config(bus, slot, func, 0x44, 1);
659		break;
660
661		/* Compaq/HP -- vendor 0x0e11 */
662	case 0x60100e11:
663		*busnum = read_config(bus, slot, func, 0xc8, 1);
664		break;
665	default:
666		/* Don't know how to read bus number. */
667		return 0;
668	}
669
670	return 1;
671}
672