DragonFly submit List (threaded) for 2003-12
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]
pcib newbus handling
Hi all,
attached patch adds the pcib interface from FreeBSD 5. This
is the version of Dec. 2000 to keep the diff small.
The PCI compat patch is required.
I haven't kept the Alpha PCI hose support since Alphas are
unsupported ATM anyway. When that platform is resurrected,
the bus space functions have to be updated to handled that.
bus/pci/i386/pcibus.c can be removed afterwards. This should
be tested. I am not sure wether our AT PIC claims IRQ 2,
perhaps we should conditionally bump irq_rman.rm_start to 3
in the !APIC_IO && !PC98 case.
Joerg
diff -uNr sys.old/bus/pci/i386/pci_bus.c sys/bus/pci/i386/pci_bus.c
--- sys.old/bus/pci/i386/pci_bus.c Thu Jan 1 00:00:00 1970
+++ sys/bus/pci/i386/pci_bus.c Sat Dec 20 17:08:07 2003
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/pci/pci_bus.c,v 1.71 2000/10/16 07:25:08 imp Exp $
+ * $DragonFly$
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcireg.h>
+#include <bus/isa/isavar.h>
+#include <machine/nexusvar.h>
+#include <bus/pci/i386/pci_cfgreg.h>
+#include <machine/segments.h>
+#include <machine/pc/bios.h>
+
+#include "pcib_if.h"
+
+static int
+nexus_pcib_maxslots(device_t dev)
+{
+ return 31;
+}
+
+/* read configuration space register */
+
+static u_int32_t
+nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
+ int reg, int bytes)
+{
+ return(pci_cfgregread(bus, slot, func, reg, bytes));
+}
+
+/* write configuration space register */
+
+static void
+nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
+ int reg, u_int32_t data, int bytes)
+{
+ pci_cfgregwrite(bus, slot, func, reg, data, bytes);
+}
+
+/* route interrupt */
+
+static int
+nexus_pcib_route_interrupt(device_t bus, device_t device, int pin)
+{
+ return(pci_cfgintr(nexus_get_pcibus(bus), pci_get_slot(device), pin, pci_get_irq(device)));
+}
+
+static devclass_t pcib_devclass;
+
+static const char *
+nexus_pcib_is_host_bridge(int bus, int slot, int func,
+ u_int32_t id, u_int8_t class, u_int8_t subclass,
+ u_int8_t *busnum)
+{
+ const char *s = NULL;
+ static u_int8_t pxb[4]; /* hack for 450nx */
+
+ *busnum = 0;
+
+ switch (id) {
+ case 0x12258086:
+ s = "Intel 824?? host to PCI bridge";
+ /* XXX This is a guess */
+ /* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
+ *busnum = bus;
+ break;
+ case 0x71208086:
+ s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
+ break;
+ case 0x71228086:
+ s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
+ break;
+ case 0x71248086:
+ s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
+ break;
+ case 0x71808086:
+ s = "Intel 82443LX (440 LX) host to PCI bridge";
+ break;
+ case 0x71908086:
+ s = "Intel 82443BX (440 BX) host to PCI bridge";
+ break;
+ case 0x71928086:
+ s = "Intel 82443BX host to PCI bridge (AGP disabled)";
+ break;
+ case 0x71948086:
+ s = "Intel 82443MX host to PCI bridge";
+ break;
+ case 0x71a08086:
+ s = "Intel 82443GX host to PCI bridge";
+ break;
+ case 0x71a18086:
+ s = "Intel 82443GX host to AGP bridge";
+ break;
+ case 0x71a28086:
+ s = "Intel 82443GX host to PCI bridge (AGP disabled)";
+ break;
+ case 0x84c48086:
+ s = "Intel 82454KX/GX (Orion) host to PCI bridge";
+ *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
+ break;
+ case 0x84ca8086:
+ /*
+ * For the 450nx chipset, there is a whole bundle of
+ * things pretending to be host bridges. The MIOC will
+ * be seen first and isn't really a pci bridge (the
+ * actual busses are attached to the PXB's). We need to
+ * read the registers of the MIOC to figure out the
+ * bus numbers for the PXB channels.
+ *
+ * Since the MIOC doesn't have a pci bus attached, we
+ * pretend it wasn't there.
+ */
+ pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
+ 0xd0, 1); /* BUSNO[0] */
+ pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
+ 0xd1, 1) + 1; /* SUBA[0]+1 */
+ pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
+ 0xd3, 1); /* BUSNO[1] */
+ pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
+ 0xd4, 1) + 1; /* SUBA[1]+1 */
+ return NULL;
+ case 0x84cb8086:
+ switch (slot) {
+ case 0x12:
+ s = "Intel 82454NX PXB#0, Bus#A";
+ *busnum = pxb[0];
+ break;
+ case 0x13:
+ s = "Intel 82454NX PXB#0, Bus#B";
+ *busnum = pxb[1];
+ break;
+ case 0x14:
+ s = "Intel 82454NX PXB#1, Bus#A";
+ *busnum = pxb[2];
+ break;
+ case 0x15:
+ s = "Intel 82454NX PXB#1, Bus#B";
+ *busnum = pxb[3];
+ break;
+ }
+ break;
+
+ /* AMD -- vendor 0x1022 */
+ case 0x70061022:
+ s = "AMD-751 host to PCI bridge";
+ break;
+
+ /* SiS -- vendor 0x1039 */
+ case 0x04961039:
+ s = "SiS 85c496";
+ break;
+ case 0x04061039:
+ s = "SiS 85c501";
+ break;
+ case 0x06011039:
+ s = "SiS 85c601";
+ break;
+ case 0x55911039:
+ s = "SiS 5591 host to PCI bridge";
+ break;
+ case 0x00011039:
+ s = "SiS 5591 host to AGP bridge";
+ break;
+
+ /* VLSI -- vendor 0x1004 */
+ case 0x00051004:
+ s = "VLSI 82C592 Host to PCI bridge";
+ break;
+
+ /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
+ /* totally. Please let me know if anything wrong. -F */
+ /* XXX need info on the MVP3 -- any takers? */
+ case 0x05981106:
+ s = "VIA 82C598MVP (Apollo MVP3) host bridge";
+ break;
+
+ /* AcerLabs -- vendor 0x10b9 */
+ /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
+ /* id is '10b9" but the register always shows "10b9". -Foxfair */
+ case 0x154110b9:
+ s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
+ break;
+
+ /* OPTi -- vendor 0x1045 */
+ case 0xc7011045:
+ s = "OPTi 82C700 host to PCI bridge";
+ break;
+ case 0xc8221045:
+ s = "OPTi 82C822 host to PCI Bridge";
+ break;
+
+ /* ServerWorks -- vendor 0x1166 */
+ case 0x00051166:
+ s = "ServerWorks NB6536 2.0HE host to PCI bridge";
+ *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+ break;
+
+ case 0x00061166:
+ /* FALLTHROUGH */
+ case 0x00081166:
+ s = "ServerWorks host to PCI bridge";
+ *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+ break;
+
+ case 0x00091166:
+ s = "ServerWorks NB6635 3.0LE host to PCI bridge";
+ *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+ break;
+
+ /* Integrated Micro Solutions -- vendor 0x10e0 */
+ case 0x884910e0:
+ s = "Integrated Micro Solutions VL Bridge";
+ break;
+
+ default:
+ if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
+ s = "Host to PCI bridge";
+ break;
+ }
+
+ return s;
+}
+
+/*
+ * Scan the first pci bus for host-pci bridges and add pcib instances
+ * to the nexus for each bridge.
+ */
+static void
+nexus_pcib_identify(driver_t *driver, device_t parent)
+{
+ int bus, slot, func;
+ u_int8_t hdrtype;
+ int found = 0;
+ int pcifunchigh;
+ int found824xx = 0;
+ device_t child;
+ devclass_t pci_devclass;
+
+ if (pci_cfgregopen() == 0)
+ return;
+ /*
+ * Check to see if we haven't already had a PCI bus added
+ * via some other means. If we have, bail since otherwise
+ * we're going to end up duplicating it.
+ */
+ if ((pci_devclass = devclass_find("pci")) &&
+ devclass_get_device(pci_devclass, 0))
+ return;
+
+
+ bus = 0;
+ retry:
+ for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+ func = 0;
+ hdrtype = nexus_pcib_read_config(0, bus, slot, func,
+ PCIR_HEADERTYPE, 1);
+ if (hdrtype & PCIM_MFDEV)
+ pcifunchigh = 7;
+ else
+ pcifunchigh = 0;
+ for (func = 0; func <= pcifunchigh; func++) {
+ /*
+ * Read the IDs and class from the device.
+ */
+ u_int32_t id;
+ u_int8_t class, subclass, busnum;
+ const char *s;
+ device_t *devs;
+ int ndevs, i;
+
+ id = nexus_pcib_read_config(0, bus, slot, func,
+ PCIR_DEVVENDOR, 4);
+ if (id == -1)
+ continue;
+ class = nexus_pcib_read_config(0, bus, slot, func,
+ PCIR_CLASS, 1);
+ subclass = nexus_pcib_read_config(0, bus, slot, func,
+ PCIR_SUBCLASS, 1);
+
+ s = nexus_pcib_is_host_bridge(bus, slot, func,
+ id, class, subclass,
+ &busnum);
+ if (s == NULL)
+ continue;
+
+ /*
+ * Check to see if the physical bus has already
+ * been seen. Eg: hybrid 32 and 64 bit host
+ * bridges to the same logical bus.
+ */
+ if (device_get_children(parent, &devs, &ndevs) == 0) {
+ for (i = 0; s != NULL && i < ndevs; i++) {
+ if (strcmp(device_get_name(devs[i]),
+ "pcib") != 0)
+ continue;
+ if (nexus_get_pcibus(devs[i]) == busnum)
+ s = NULL;
+ }
+ free(devs, M_TEMP);
+ }
+
+ if (s == NULL)
+ continue;
+ /*
+ * Add at priority 100 to make sure we
+ * go after any motherboard resources
+ */
+ child = BUS_ADD_CHILD(parent, 100,
+ "pcib", busnum);
+ device_set_desc(child, s);
+ nexus_set_pcibus(child, busnum);
+
+ found = 1;
+ if (id == 0x12258086)
+ found824xx = 1;
+ }
+ }
+ if (found824xx && bus == 0) {
+ bus++;
+ goto retry;
+ }
+
+ /*
+ * Make sure we add at least one bridge since some old
+ * hardware doesn't actually have a host-pci bridge device.
+ * Note that pci_cfgregopen() thinks we have PCI devices..
+ */
+ if (!found) {
+ if (bootverbose)
+ printf(
+ "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
+ child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
+ nexus_set_pcibus(child, 0);
+ }
+}
+
+static int
+nexus_pcib_probe(device_t dev)
+{
+ devclass_t pci_devclass;
+
+ if (pci_cfgregopen() == 0)
+ return ENXIO;
+ /*
+ * Check to see if we haven't already had a PCI bus added
+ * via some other means. If we have, bail since otherwise
+ * we're going to end up duplicating it.
+ */
+ if ((pci_devclass = devclass_find("pci")) &&
+ devclass_get_device(pci_devclass, device_get_unit(dev)))
+ return ENXIO;
+
+ return 0;
+}
+
+static int
+nexus_pcib_attach(device_t dev)
+{
+ device_t child;
+
+ child = device_add_child(dev, "pci", device_get_unit(dev));
+
+ return bus_generic_attach(dev);
+}
+
+static int
+nexus_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = nexus_get_pcibus(dev);
+ return 0;
+ }
+ return ENOENT;
+}
+
+static int
+nexus_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ nexus_set_pcibus(dev, value);
+ return 0;
+ }
+ return ENOENT;
+}
+
+
+static device_method_t nexus_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, nexus_pcib_identify),
+ DEVMETHOD(device_probe, nexus_pcib_probe),
+ DEVMETHOD(device_attach, nexus_pcib_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, nexus_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
+ DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
+ DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, nexus_pcib_route_interrupt),
+
+ { 0, 0 }
+};
+
+static driver_t nexus_pcib_driver = {
+ "pcib",
+ nexus_pcib_methods,
+ 1,
+};
+
+DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
+
+
+/*
+ * Provide a device to "eat" the host->pci bridges that we dug up above
+ * and stop them showing up twice on the probes. This also stops them
+ * showing up as 'none' in pciconf -l.
+ */
+static int
+pci_hostb_probe(device_t dev)
+{
+
+ if (pci_get_class(dev) == PCIC_BRIDGE &&
+ pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
+ device_set_desc(dev, "Host to PCI bridge");
+ device_quiet(dev);
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+pci_hostb_attach(device_t dev)
+{
+
+ return 0;
+}
+
+static device_method_t pci_hostb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pci_hostb_probe),
+ DEVMETHOD(device_attach, pci_hostb_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ { 0, 0 }
+};
+static driver_t pci_hostb_driver = {
+ "hostb",
+ pci_hostb_methods,
+ 1,
+};
+static devclass_t pci_hostb_devclass;
+
+DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0);
+
+
+/*
+ * Install placeholder to claim the resources owned by the
+ * PCI bus interface. This could be used to extract the
+ * config space registers in the extreme case where the PnP
+ * ID is available and the PCI BIOS isn't, but for now we just
+ * eat the PnP ID and do nothing else.
+ *
+ * XXX we should silence this probe, as it will generally confuse
+ * people.
+ */
+static struct isa_pnp_id pcibus_pnp_ids[] = {
+ { 0x030ad041 /* PNP030A */, "PCI Bus" },
+ { 0 }
+};
+
+static int
+pcibus_pnp_probe(device_t dev)
+{
+ int result;
+
+ if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
+ device_quiet(dev);
+ return(result);
+}
+
+static int
+pcibus_pnp_attach(device_t dev)
+{
+ return(0);
+}
+
+static device_method_t pcibus_pnp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pcibus_pnp_probe),
+ DEVMETHOD(device_attach, pcibus_pnp_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ { 0, 0 }
+};
+
+static driver_t pcibus_pnp_driver = {
+ "pcibus_pnp",
+ pcibus_pnp_methods,
+ 1, /* no softc */
+};
+
+static devclass_t pcibus_pnp_devclass;
+
+DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
diff -uNr sys.old/bus/pci/i386/pci_cfgreg.c sys/bus/pci/i386/pci_cfgreg.c
--- sys.old/bus/pci/i386/pci_cfgreg.c Thu Aug 7 21:16:47 2003
+++ sys/bus/pci/i386/pci_cfgreg.c Sat Dec 20 17:08:07 2003
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/i386/isa/pci_cfgreg.c,v 1.1.2.7 2001/11/28 05:47:03 imp Exp $
+ * $FreeBSD: src/sys/i386/pci/pci_cfgreg.c,v 1.101 2003/02/18 03:36:48 peter Exp $
* $DragonFly: src/sys/bus/pci/i386/pci_cfgreg.c,v 1.3 2003/08/07 21:16:47 dillon Exp $
*
*/
@@ -36,15 +36,14 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
#include <bus/pci/pcivar.h>
#include <bus/pci/pcireg.h>
#include <bus/isa/isavar.h>
-#include "pcibus.h"
-/* #include <machine/nexusvar.h> */
-#include <machine/pci_cfgreg.h>
+#include <bus/pci/i386/pci_cfgreg.h>
#include <machine/segments.h>
#include <machine/pc/bios.h>
@@ -52,41 +51,65 @@
#include <machine/smp.h>
#endif /* APIC_IO */
+#include "pcib_if.h"
+
+#define PRVERB(a) do { \
+ if (bootverbose) \
+ printf a ; \
+} while(0)
+
static int cfgmech;
static int devmax;
-#define PRVERB(a) printf a
+static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
static int pci_cfgintr_linked(struct PIR_entry *pe, int pin);
static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
+static void pci_print_irqmask(u_int16_t irqs);
+static void pci_print_route_table(struct PIR_table *prt, int size);
static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
static int pcireg_cfgopen(void);
-static struct PIR_table *pci_route_table;
-static int pci_route_count;
+static struct PIR_table *pci_route_table;
+static int pci_route_count;
+
+/*
+ * Some BIOS writers seem to want to ignore the spec and put
+ * 0 in the intline rather than 255 to indicate none. Some use
+ * numbers in the range 128-254 to indicate something strange and
+ * apparently undocumented anywhere. Assume these are completely bogus
+ * and map them to 255, which means "none".
+ */
+static __inline__ int
+pci_i386_map_intline(int line)
+{
+ if (line == 0 || line >= 128)
+ return (PCI_INVALID_IRQ);
+ return (line);
+}
static u_int16_t
pcibios_get_version(void)
{
- struct bios_regs args;
+ struct bios_regs args;
- if (PCIbios.entry == 0) {
- PRVERB(("pcibios: No call entry point\n"));
- return (0);
- }
- args.eax = PCIBIOS_BIOS_PRESENT;
- if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
- PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
- return (0);
- }
- if (args.edx != 0x20494350) {
- PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
- return (0);
- }
- return (args.ebx & 0xffff);
+ if (PCIbios.ventry == 0) {
+ PRVERB(("pcibios: No call entry point\n"));
+ return (0);
+ }
+ args.eax = PCIBIOS_BIOS_PRESENT;
+ if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
+ PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
+ return (0);
+ }
+ if (args.edx != 0x20494350) {
+ PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
+ return (0);
+ }
+ return (args.ebx & 0xffff);
}
/*
@@ -95,92 +118,122 @@
int
pci_cfgregopen(void)
{
- static int opened = 0;
- u_long sigaddr;
- static struct PIR_table *pt;
- u_int8_t ck, *cv;
- int i;
-
- if (opened)
- return(1);
+ static int opened = 0;
+ u_long sigaddr;
+ static struct PIR_table *pt;
+ u_int16_t v;
+ u_int8_t ck, *cv;
+ int i;
+
+ if (opened)
+ return(1);
+
+ if (pcireg_cfgopen() == 0)
+ return(0);
+
+ v = pcibios_get_version();
+ if (v > 0)
+ printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8,
+ v & 0xff);
- if (pcireg_cfgopen() == 0)
- return(0);
-
- /*
- * Look for the interrupt routing table.
- */
- /* We use PCI BIOS's PIR table if it's available */
- if (pcibios_get_version() >= 0x0210 && pt == NULL &&
- (sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0) {
- pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
- for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) {
- ck += cv[i];
- }
- if (ck == 0) {
- pci_route_table = pt;
- pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry);
- printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table);
+ /*
+ * Look for the interrupt routing table.
+ *
+ * We use PCI BIOS's PIR table if it's available $PIR is the
+ * standard way to do this. Sadly, some machines are not
+ * standards conforming and have _PIR instead. We shrug and cope
+ * by looking for both.
+ */
+ if (pcibios_get_version() >= 0x0210 && pt == NULL) {
+ sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0);
+ if (sigaddr == 0)
+ sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0);
+ if (sigaddr != 0) {
+ pt = (struct PIR_table *)(uintptr_t)
+ BIOS_PADDRTOVADDR(sigaddr);
+ for (cv = (u_int8_t *)pt, ck = 0, i = 0;
+ i < (pt->pt_header.ph_length); i++) {
+ ck += cv[i];
+ }
+ if (ck == 0 && pt->pt_header.ph_length >
+ sizeof(struct PIR_header)) {
+ pci_route_table = pt;
+ pci_route_count = (pt->pt_header.ph_length -
+ sizeof(struct PIR_header)) /
+ sizeof(struct PIR_entry);
+ printf("Using $PIR table, %d entries at %p\n",
+ pci_route_count, pci_route_table);
+ if (bootverbose)
+ pci_print_route_table(pci_route_table,
+ pci_route_count);
+ }
+ }
}
- }
-
- opened = 1;
- return(1);
+ opened = 1;
+ return(1);
}
/*
* Read configuration space register
*/
-static u_int32_t
-pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
-{
- return(pcireg_cfgread(bus, slot, func, reg, bytes));
-}
-
u_int32_t
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
{
+ uint32_t line;
#ifdef APIC_IO
- /*
- * If we are using the APIC, the contents of the intline register will probably
- * be wrong (since they are set up for use with the PIC.
- * Rather than rewrite these registers (maybe that would be smarter) we trap
- * attempts to read them and translate to our private vector numbers.
- */
- if ((reg == PCIR_INTLINE) && (bytes == 1)) {
- int pin, line;
-
- pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
- line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
-
- if (pin != 0) {
- int airq;
-
- airq = pci_apic_irq(bus, slot, pin);
- if (airq >= 0) {
- /* PCI specific entry found in MP table */
- if (airq != line)
- undirect_pci_irq(line);
- return(airq);
- } else {
- /*
- * PCI interrupts might be redirected to the
- * ISA bus according to some MP tables. Use the
- * same methods as used by the ISA devices
- * devices to find the proper IOAPIC int pin.
- */
- airq = isa_apic_irq(line);
- if ((airq >= 0) && (airq != line)) {
- /* XXX: undirect_pci_irq() ? */
- undirect_isa_irq(line);
- return(airq);
+ uint32_t pin;
+
+ /*
+ * If we are using the APIC, the contents of the intline
+ * register will probably be wrong (since they are set up for
+ * use with the PIC. Rather than rewrite these registers
+ * (maybe that would be smarter) we trap attempts to read them
+ * and translate to our private vector numbers.
+ */
+ if ((reg == PCIR_INTLINE) && (bytes == 1)) {
+
+ pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+
+ if (pin != 0) {
+ int airq;
+
+ airq = pci_apic_irq(bus, slot, pin);
+ if (airq >= 0) {
+ /* PCI specific entry found in MP table */
+ if (airq != line)
+ undirect_pci_irq(line);
+ return(airq);
+ } else {
+ /*
+ * PCI interrupts might be redirected
+ * to the ISA bus according to some MP
+ * tables. Use the same methods as
+ * used by the ISA devices devices to
+ * find the proper IOAPIC int pin.
+ */
+ airq = isa_apic_irq(line);
+ if ((airq >= 0) && (airq != line)) {
+ /* XXX: undirect_pci_irq() ? */
+ undirect_isa_irq(line);
+ return(airq);
+ }
+ }
}
- }
+ return(line);
+ }
+#else
+ /*
+ * Some BIOS writers seem to want to ignore the spec and put
+ * 0 in the intline rather than 255 to indicate none. The rest of
+ * the code uses 255 as an invalid IRQ.
+ */
+ if (reg == PCIR_INTLINE && bytes == 1) {
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+ return pci_i386_map_intline(line);
}
- return(line);
- }
#endif /* APIC_IO */
- return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+ return(pcireg_cfgread(bus, slot, func, reg, bytes));
}
/*
@@ -189,89 +242,158 @@
void
pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
- return(pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
-}
-
-int
-pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
-{
- return(pci_cfgregread(cfg->bus, cfg->slot, cfg->func, reg, bytes));
-}
-void
-pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
-{
- pci_cfgregwrite(cfg->bus, cfg->slot, cfg->func, reg, data, bytes);
+ pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
}
-
/*
* Route a PCI interrupt
- *
- * XXX we don't do anything "right" with the function number in the PIR table
- * (because the consumer isn't currently passing it in). We don't care
- * anyway, due to the way PCI interrupts are assigned.
*/
int
-pci_cfgintr(int bus, int device, int pin)
+pci_cfgintr(int bus, int device, int pin, int oldirq)
{
- struct PIR_entry *pe;
- int i, irq;
- struct bios_regs args;
- u_int16_t v;
- int already = 0;
-
- v = pcibios_get_version();
- if (v < 0x0210) {
- PRVERB((
- "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
- (v & 0xff00) >> 8, v & 0xff));
- return (255);
- }
- if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
- (pin < 1) || (pin > 4))
- return(255);
-
- /*
- * Scan the entry table for a contender
- */
- for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) {
- if ((bus != pe->pe_bus) || (device != pe->pe_device))
- continue;
-
- irq = pci_cfgintr_linked(pe, pin);
- if (irq != 255)
- already = 1;
- if (irq == 255)
- irq = pci_cfgintr_unique(pe, pin);
- if (irq == 255)
- irq = pci_cfgintr_virgin(pe, pin);
-
- if (irq == 255)
- break;
+ struct PIR_entry *pe;
+ int i, irq;
+ struct bios_regs args;
+ int already = 0;
+ int errok = 0;
+
+ if(pin==1 && device==9)
+ already = 10;
+ if(pin==1 && device==10)
+ already = 6;
+
+ if(already)
+ {
+ u_long intr;
+ u_char irq = already;
+
+#define PCI_INTERRUPT_REG 0x3c
+#define PCI_INTERRUPT_LINE_SHIFT 0
+#define PCI_INTERRUPT_LINE_MASK 0xff
+#define PCI_INTERRUPT_LINE(icr) \
+ (((icr) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK)
+
+ intr = pci_cfgregread(bus, device, 0 , PCI_INTERRUPT_REG, 4);
+ if (irq != PCI_INTERRUPT_LINE(intr)) {
+ intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ intr |= (irq << PCI_INTERRUPT_LINE_SHIFT);
+ pci_cfgregwrite(bus, device,0 , PCI_INTERRUPT_REG, intr, 4);
+ }
+
+ return irq;
+ }
+
+ already = 0;
+
+ v = pcibios_get_version();
+ if (v < 0x0210) {
+ PRVERB((
+ "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
+ (v & 0xff00) >> 8, v & 0xff));
+ return (PCI_INVALID_IRQ);
+ }
+ if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
+ (pin < 1) || (pin > 4))
+ return(PCI_INVALID_IRQ);
/*
- * Ask the BIOS to route the interrupt
+ * Scan the entry table for a contender
*/
- args.eax = PCIBIOS_ROUTE_INTERRUPT;
- args.ebx = (bus << 8) | (device << 3);
- args.ecx = (irq << 8) | (0xa + pin - 1); /* pin value is 0xa - 0xd */
- if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) && !already) {
- /*
- * XXX if it fails, we should try to smack the router
- * hardware directly.
- * XXX Also, there may be other choices that we can try that
- * will work.
- */
- PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
- return(255);
+ for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count;
+ i++, pe++) {
+ if ((bus != pe->pe_bus) || (device != pe->pe_device))
+ continue;
+ /*
+ * A link of 0 means that this intpin is not connected to
+ * any other device's interrupt pins and is not connected to
+ * any of the Interrupt Router's interrupt pins, so we can't
+ * route it.
+ */
+ if (pe->pe_intpin[pin - 1].link == 0)
+ continue;
+
+ if (pci_cfgintr_valid(pe, pin, oldirq)) {
+ printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
+ device, 'A' + pin - 1, oldirq);
+ return (oldirq);
+ }
+
+ /*
+ * We try to find a linked interrupt, then we look to see
+ * if the interrupt is uniquely routed, then we look for
+ * a virgin interrupt. The virgin interrupt should return
+ * an interrupt we can route, but if that fails, maybe we
+ * should try harder to route a different interrupt.
+ * However, experience has shown that that's rarely the
+ * failure mode we see.
+ */
+ irq = pci_cfgintr_linked(pe, pin);
+ if (irq != PCI_INVALID_IRQ)
+ already = 1;
+ if (irq == PCI_INVALID_IRQ) {
+ irq = pci_cfgintr_unique(pe, pin);
+ if (irq != PCI_INVALID_IRQ)
+ errok = 1;
+ }
+ if (irq == PCI_INVALID_IRQ)
+ irq = pci_cfgintr_virgin(pe, pin);
+ if (irq == PCI_INVALID_IRQ)
+ break;
+
+ /*
+ * Ask the BIOS to route the interrupt. If we picked an
+ * interrupt that failed, we should really try other
+ * choices that the BIOS offers us.
+ *
+ * For uniquely routed interrupts, we need to try
+ * to route them on some machines. Yet other machines
+ * fail to route, so we have to pretend that in that
+ * case it worked. Isn't pc hardware fun?
+ *
+ * NOTE: if we want to whack hardware to do this, then
+ * I think the right way to do that would be to have
+ * bridge drivers that do this. I'm not sure that the
+ * $PIR table would be valid for those interrupt
+ * routers.
+ */
+ args.eax = PCIBIOS_ROUTE_INTERRUPT;
+ args.ebx = (bus << 8) | (device << 3);
+ /* pin value is 0xa - 0xd */
+ args.ecx = (irq << 8) | (0xa + pin - 1);
+ if (!already &&
+ bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) &&
+ !errok) {
+ PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
+ return(PCI_INVALID_IRQ);
+ }
+ printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus,
+ device, 'A' + pin - 1, irq);
+ return(irq);
}
- printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, device, 'A' + pin - 1, irq);
- return(irq);
- }
- PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1));
- return(255);
+ PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus,
+ device, 'A' + pin - 1));
+ return(PCI_INVALID_IRQ);
+}
+
+/*
+ * Check to see if an existing IRQ setting is valid.
+ */
+static int
+pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
+{
+ uint32_t irqmask;
+
+ if (!PCI_INTERRUPT_VALID(irq))
+ return (0);
+ irqmask = pe->pe_intpin[pin - 1].irqs;
+ if (irqmask & (1 << irq)) {
+ PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
+ return (1);
+ }
+ return (0);
}
/*
@@ -280,14 +402,16 @@
static int
pci_cfgintr_unique(struct PIR_entry *pe, int pin)
{
- int irq;
+ int irq;
+ uint32_t irqmask;
- if (powerof2(pe->pe_intpin[pin - 1].irqs)) {
- irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
- PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
- return(irq);
- }
- return(255);
+ irqmask = pe->pe_intpin[pin - 1].irqs;
+ if (irqmask != 0 && powerof2(irqmask)) {
+ irq = ffs(irqmask) - 1;
+ PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
+ return(irq);
+ }
+ return(PCI_INVALID_IRQ);
}
/*
@@ -297,40 +421,43 @@
static int
pci_cfgintr_linked(struct PIR_entry *pe, int pin)
{
- struct PIR_entry *oe;
- struct PIR_intpin *pi;
- int i, j, irq;
-
- /*
- * Scan table slots.
- */
- for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) {
-
- /* scan interrupt pins */
- for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
-
- /* don't look at the entry we're trying to match with */
- if ((pe == oe) && (i == (pin - 1)))
- continue;
-
- /* compare link bytes */
- if (pi->link != pe->pe_intpin[pin - 1].link)
- continue;
-
- /* link destination mapped to a unique interrupt? */
- if (powerof2(pi->irqs)) {
- irq = ffs(pi->irqs) - 1;
- PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
- pi->link, irq));
- return(irq);
- }
+ struct PIR_entry *oe;
+ struct PIR_intpin *pi;
+ int i, j, irq;
- /* look for the real PCI device that matches this table entry */
- if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255)
- return(irq);
+ /*
+ * Scan table slots.
+ */
+ for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count;
+ i++, oe++) {
+ /* scan interrupt pins */
+ for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
+
+ /* don't look at the entry we're trying to match */
+ if ((pe == oe) && (i == (pin - 1)))
+ continue;
+ /* compare link bytes */
+ if (pi->link != pe->pe_intpin[pin - 1].link)
+ continue;
+ /* link destination mapped to a unique interrupt? */
+ if (pi->irqs != 0 && powerof2(pi->irqs)) {
+ irq = ffs(pi->irqs) - 1;
+ PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
+ pi->link, irq));
+ return(irq);
+ }
+
+ /*
+ * look for the real PCI device that matches this
+ * table entry
+ */
+ irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device,
+ j, pin);
+ if (irq != PCI_INVALID_IRQ)
+ return(irq);
+ }
}
- }
- return(255);
+ return(PCI_INVALID_IRQ);
}
/*
@@ -340,55 +467,51 @@
static int
pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
{
- devclass_t pci_devclass;
- device_t *pci_devices;
- int pci_count;
- device_t *pci_children;
- int pci_childcount;
- device_t *busp, *childp;
- int i, j, irq;
-
- /*
- * Find all the PCI busses.
- */
- pci_count = 0;
- if ((pci_devclass = devclass_find("pci")) != NULL)
- devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
-
- /*
- * Scan all the PCI busses/devices looking for this one.
- */
- irq = 255;
- for (i = 0, busp = pci_devices; (i < pci_count) && (irq == 255); i++, busp++) {
- pci_childcount = 0;
- device_get_children(*busp, &pci_children, &pci_childcount);
+ devclass_t pci_devclass;
+ device_t *pci_devices;
+ int pci_count;
+ device_t *pci_children;
+ int pci_childcount;
+ device_t *busp, *childp;
+ int i, j, irq;
+
+ /*
+ * Find all the PCI busses.
+ */
+ pci_count = 0;
+ if ((pci_devclass = devclass_find("pci")) != NULL)
+ devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
+
+ /*
+ * Scan all the PCI busses/devices looking for this one.
+ */
+ irq = PCI_INVALID_IRQ;
+ for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ);
+ i++, busp++) {
+ pci_childcount = 0;
+ device_get_children(*busp, &pci_children, &pci_childcount);
- for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
- if ((pci_get_bus(*childp) == bus) &&
- (pci_get_slot(*childp) == device) &&
- (pci_get_intpin(*childp) == matchpin)) {
- irq = pci_get_irq(*childp);
- /*
- * Some BIOS writers seem to want to ignore the spec and put
- * 0 in the intline rather than 255 to indicate none. Once
- * we've found one that matches, we break because there can
- * be no others (which is why test looks a little odd).
- */
- if (irq == 0)
- irq = 255;
- if (irq != 255)
- PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
- pe->pe_intpin[pin - 1].link, irq,
- pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp)));
- break;
- }
+ for (j = 0, childp = pci_children; j < pci_childcount; j++,
+ childp++) {
+ if ((pci_get_bus(*childp) == bus) &&
+ (pci_get_slot(*childp) == device) &&
+ (pci_get_intpin(*childp) == matchpin)) {
+ irq = pci_i386_map_intline(pci_get_irq(*childp));
+ if (irq != PCI_INVALID_IRQ)
+ PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
+ pe->pe_intpin[pin - 1].link, irq,
+ pci_get_bus(*childp),
+ pci_get_slot(*childp),
+ pci_get_function(*childp)));
+ break;
+ }
+ }
+ if (pci_children != NULL)
+ free(pci_children, M_TEMP);
}
- if (pci_children != NULL)
- free(pci_children, M_TEMP);
- }
- if (pci_devices != NULL)
- free(pci_devices, M_TEMP);
- return(irq);
+ if (pci_devices != NULL)
+ free(pci_devices, M_TEMP);
+ return(irq);
}
/*
@@ -397,30 +520,102 @@
static int
pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
{
- int irq, ibit;
+ int irq, ibit;
- /* first scan the set of PCI-only interrupts and see if any of these are routable */
- for (irq = 0; irq < 16; irq++) {
- ibit = (1 << irq);
-
- /* can we use this interrupt? */
- if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
- (pe->pe_intpin[pin - 1].irqs & ibit)) {
- PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
- return(irq);
+ /*
+ * first scan the set of PCI-only interrupts and see if any of these
+ * are routable
+ */
+ for (irq = 0; irq < 16; irq++) {
+ ibit = (1 << irq);
+
+ /* can we use this interrupt? */
+ if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
+ (pe->pe_intpin[pin - 1].irqs & ibit)) {
+ PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
+ return(irq);
+ }
}
- }
- /* life is tough, so just pick an interrupt */
- for (irq = 0; irq < 16; irq++) {
- ibit = (1 << irq);
-
- if (pe->pe_intpin[pin - 1].irqs & ibit) {
- PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
- return(irq);
+ /* life is tough, so just pick an interrupt */
+ for (irq = 0; irq < 16; irq++) {
+ ibit = (1 << irq);
+ if (pe->pe_intpin[pin - 1].irqs & ibit) {
+ PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
+ return(irq);
+ }
}
- }
- return(255);
+ return(PCI_INVALID_IRQ);
+}
+
+static void
+pci_print_irqmask(u_int16_t irqs)
+{
+ int i, first;
+
+ if (irqs == 0) {
+ printf("none");
+ return;
+ }
+ first = 1;
+ for (i = 0; i < 16; i++, irqs >>= 1)
+ if (irqs & 1) {
+ if (!first)
+ printf(" ");
+ else
+ first = 0;
+ printf("%d", i);
+ }
+}
+
+/*
+ * Dump the contents of a PCI BIOS Interrupt Routing Table to the console.
+ */
+static void
+pci_print_route_table(struct PIR_table *prt, int size)
+{
+ struct PIR_entry *entry;
+ struct PIR_intpin *intpin;
+ int i, pin;
+
+ printf("PCI-Only Interrupts: ");
+ pci_print_irqmask(prt->pt_header.ph_pci_irqs);
+ printf("\nLocation Bus Device Pin Link IRQs\n");
+ entry = &prt->pt_entry[0];
+ for (i = 0; i < size; i++, entry++) {
+ intpin = &entry->pe_intpin[0];
+ for (pin = 0; pin < 4; pin++, intpin++)
+ if (intpin->link != 0) {
+ if (entry->pe_slot == 0)
+ printf("embedded ");
+ else
+ printf("slot %-3d ", entry->pe_slot);
+ printf(" %3d %3d %c 0x%02x ",
+ entry->pe_bus, entry->pe_device,
+ 'A' + pin, intpin->link);
+ pci_print_irqmask(intpin->irqs);
+ printf("\n");
+ }
+ }
+}
+
+/*
+ * See if any interrupts for a given PCI bus are routed in the PIR. Don't
+ * even bother looking if the BIOS doesn't support routing anyways.
+ */
+int
+pci_probe_route_table(int bus)
+{
+ int i;
+ u_int16_t v;
+
+ v = pcibios_get_version();
+ if (v < 0x0210)
+ return (0);
+ for (i = 0; i < pci_route_count; i++)
+ if (pci_route_table->pt_entry[i].pe_bus == bus)
+ return (1);
+ return (0);
}
/*
@@ -431,214 +626,218 @@
static int
pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
{
- int dataport = 0;
+ int dataport = 0;
- if (bus <= PCI_BUSMAX
- && slot < devmax
- && func <= PCI_FUNCMAX
- && reg <= PCI_REGMAX
- && bytes != 3
- && (unsigned) bytes <= 4
- && (reg & (bytes -1)) == 0) {
- switch (cfgmech) {
- case 1:
- outl(CONF1_ADDR_PORT, (1 << 31)
- | (bus << 16) | (slot << 11)
- | (func << 8) | (reg & ~0x03));
- dataport = CONF1_DATA_PORT + (reg & 0x03);
- break;
- case 2:
- outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
- outb(CONF2_FORWARD_PORT, bus);
- dataport = 0xc000 | (slot << 8) | reg;
- break;
+ if (bus <= PCI_BUSMAX
+ && slot < devmax
+ && func <= PCI_FUNCMAX
+ && reg <= PCI_REGMAX
+ && bytes != 3
+ && (unsigned) bytes <= 4
+ && (reg & (bytes - 1)) == 0) {
+ switch (cfgmech) {
+ case 1:
+ outl(CONF1_ADDR_PORT, (1 << 31)
+ | (bus << 16) | (slot << 11)
+ | (func << 8) | (reg & ~0x03));
+ dataport = CONF1_DATA_PORT + (reg & 0x03);
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
}
- }
- return (dataport);
+ return (dataport);
}
/* disable configuration space accesses */
static void
pci_cfgdisable(void)
{
- switch (cfgmech) {
- case 1:
- outl(CONF1_ADDR_PORT, 0);
- break;
- case 2:
- outb(CONF2_ENABLE_PORT, 0);
- outb(CONF2_FORWARD_PORT, 0);
- break;
- }
+ switch (cfgmech) {
+ case 1:
+ outl(CONF1_ADDR_PORT, 0);
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0);
+ outb(CONF2_FORWARD_PORT, 0);
+ break;
+ }
}
static int
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
- int data = -1;
- int port;
+ int data = -1;
+ int port;
- port = pci_cfgenable(bus, slot, func, reg, bytes);
-
- if (port != 0) {
- switch (bytes) {
- case 1:
- data = inb(port);
- break;
- case 2:
- data = inw(port);
- break;
- case 4:
- data = inl(port);
- break;
+ port = pci_cfgenable(bus, slot, func, reg, bytes);
+ if (port != 0) {
+ switch (bytes) {
+ case 1:
+ data = inb(port);
+ break;
+ case 2:
+ data = inw(port);
+ break;
+ case 4:
+ data = inl(port);
+ break;
+ }
+ pci_cfgdisable();
}
- pci_cfgdisable();
- }
- return (data);
+ return (data);
}
static void
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
- int port;
+ int port;
- port = pci_cfgenable(bus, slot, func, reg, bytes);
- if (port != 0) {
- switch (bytes) {
- case 1:
- outb(port, data);
- break;
- case 2:
- outw(port, data);
- break;
- case 4:
- outl(port, data);
- break;
+ port = pci_cfgenable(bus, slot, func, reg, bytes);
+ if (port != 0) {
+ switch (bytes) {
+ case 1:
+ outb(port, data);
+ break;
+ case 2:
+ outw(port, data);
+ break;
+ case 4:
+ outl(port, data);
+ break;
+ }
+ pci_cfgdisable();
}
- pci_cfgdisable();
- }
}
/* check whether the configuration mechanism has been correctly identified */
static int
pci_cfgcheck(int maxdev)
{
- u_char device;
-
- if (bootverbose)
- printf("pci_cfgcheck:\tdevice ");
+ uint32_t id, class;
+ uint8_t header;
+ uint8_t device;
+ int port;
- for (device = 0; device < maxdev; device++) {
- unsigned id, class, header;
if (bootverbose)
- printf("%d ", device);
+ printf("pci_cfgcheck:\tdevice ");
- id = inl(pci_cfgenable(0, device, 0, 0, 4));
- if (id == 0 || id == -1)
- continue;
-
- class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
- if (bootverbose)
- printf("[class=%06x] ", class);
- if (class == 0 || (class & 0xf870ff) != 0)
- continue;
+ for (device = 0; device < maxdev; device++) {
+ if (bootverbose)
+ printf("%d ", device);
+
+ port = pci_cfgenable(0, device, 0, 0, 4);
+ id = inl(port);
+ if (id == 0 || id == 0xffffffff)
+ continue;
+
+ port = pci_cfgenable(0, device, 0, 8, 4);
+ class = inl(port) >> 8;
+ if (bootverbose)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf870ff) != 0)
+ continue;
+
+ port = pci_cfgenable(0, device, 0, 14, 1);
+ header = inb(port);
+ if (bootverbose)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
+ continue;
- header = inb(pci_cfgenable(0, device, 0, 14, 1));
- if (bootverbose)
- printf("[hdr=%02x] ", header);
- if ((header & 0x7e) != 0)
- continue;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
- if (bootverbose)
- printf("is there (id=%08x)\n", id);
+ pci_cfgdisable();
+ return (1);
+ }
+ if (bootverbose)
+ printf("-- nothing found\n");
pci_cfgdisable();
- return (1);
- }
- if (bootverbose)
- printf("-- nothing found\n");
-
- pci_cfgdisable();
- return (0);
+ return (0);
}
static int
pcireg_cfgopen(void)
{
- unsigned long mode1res,oldval1;
- unsigned char mode2res,oldval2;
-
- oldval1 = inl(CONF1_ADDR_PORT);
-
- if (bootverbose) {
- printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
- oldval1);
- }
+ uint32_t mode1res, oldval1;
+ uint8_t mode2res, oldval2;
- if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
+ oldval1 = inl(CONF1_ADDR_PORT);
- cfgmech = 1;
- devmax = 32;
+ if (bootverbose) {
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n",
+ oldval1);
+ }
- outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
- outb(CONF1_ADDR_PORT +3, 0);
- mode1res = inl(CONF1_ADDR_PORT);
- outl(CONF1_ADDR_PORT, oldval1);
+ if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- if (bootverbose)
- printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ cfgmech = 1;
+ devmax = 32;
- if (mode1res) {
- if (pci_cfgcheck(32))
- return (cfgmech);
- }
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
+ outb(CONF1_ADDR_PORT + 3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
- outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
- mode1res = inl(CONF1_ADDR_PORT);
- outl(CONF1_ADDR_PORT, oldval1);
+ if (bootverbose)
+ printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
- if (bootverbose)
- printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ if (mode1res) {
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pci_cfgcheck(32))
- return (cfgmech);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
+
+ if (bootverbose)
+ printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
+
+ if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- }
- oldval2 = inb(CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
- if (bootverbose) {
- printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
- oldval2);
- }
+ if (bootverbose) {
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
+ }
- if ((oldval2 & 0xf0) == 0) {
+ if ((oldval2 & 0xf0) == 0) {
- cfgmech = 2;
- devmax = 16;
+ cfgmech = 2;
+ devmax = 16;
- outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
- mode2res = inb(CONF2_ENABLE_PORT);
- outb(CONF2_ENABLE_PORT, oldval2);
+ outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ mode2res = inb(CONF2_ENABLE_PORT);
+ outb(CONF2_ENABLE_PORT, oldval2);
- if (bootverbose)
- printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ if (bootverbose)
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
- if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf("pci_open(2a):\tnow trying mechanism 2\n");
+ if (mode2res == CONF2_ENABLE_RES) {
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- if (pci_cfgcheck(16))
- return (cfgmech);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
+ }
}
- }
- cfgmech = 0;
- devmax = 0;
- return (cfgmech);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff -uNr sys.old/bus/pci/i386/pci_cfgreg.h sys/bus/pci/i386/pci_cfgreg.h
--- sys.old/bus/pci/i386/pci_cfgreg.h Thu Jan 1 00:00:00 1970
+++ sys/bus/pci/i386/pci_cfgreg.h Sat Dec 20 17:08:07 2003
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/pci_cfgreg.h,v 1.9 2003/02/18 03:36:48 peter Exp $
+ * $DragonFly$
+ *
+ */
+
+#define CONF1_ADDR_PORT 0x0cf8
+#define CONF1_DATA_PORT 0x0cfc
+
+#define CONF1_ENABLE 0x80000000ul
+#define CONF1_ENABLE_CHK 0x80000000ul
+#define CONF1_ENABLE_MSK 0x7ff00000ul
+#define CONF1_ENABLE_CHK1 0xff000001ul
+#define CONF1_ENABLE_MSK1 0x80000001ul
+#define CONF1_ENABLE_RES1 0x80000000ul
+
+#define CONF2_ENABLE_PORT 0x0cf8
+#ifdef PC98
+#define CONF2_FORWARD_PORT 0x0cf9
+#else
+#define CONF2_FORWARD_PORT 0x0cfa
+#endif
+
+#define CONF2_ENABLE_CHK 0x0e
+#define CONF2_ENABLE_RES 0x0e
+
+int pci_cfgregopen(void);
+u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
+void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
+int pci_cfgintr(int bus, int device, int pin, int oldirq);
+int pci_probe_route_table(int bus);
+
+#define PCI_INVALID_IRQ 255
+#define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ)
diff -uNr sys.old/bus/pci/pci.c sys/bus/pci/pci.c
--- sys.old/bus/pci/pci.c Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pci.c Sat Dec 20 17:08:07 2003
@@ -24,6 +24,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/pci/pci.c,v 1.141.2.15 2002/04/30 17:48:18 tmm Exp $
+ * merged in revision 1.167, skipped 1.162 and 1.166
* $DragonFly: src/sys/bus/pci/pci.c,v 1.6 2003/11/17 00:54:39 asmodai Exp $
*
*/
@@ -62,6 +63,8 @@
#include "pcireg.h"
#include "pcivar.h"
+#include "pcib_if.h"
+
#ifdef __alpha__
#include <machine/rpb.h>
#endif
@@ -72,7 +75,7 @@
static devclass_t pci_devclass;
-static void pci_read_extcap(pcicfgregs *cfg);
+static void pci_read_extcap(device_t dev, pcicfgregs *cfg);
struct pci_quirk {
u_int32_t devid; /* Vendor/device of the card */
@@ -219,109 +222,115 @@
/* read config data specific to header type 1 device (PCI to PCI bridge) */
static void *
-pci_readppb(pcicfgregs *cfg)
+pci_readppb(device_t pcib, int b, int s, int f)
{
pcih1cfgregs *p;
- p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK);
+ p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK | M_ZERO);
if (p == NULL)
return (NULL);
- bzero(p, sizeof *p);
-
- p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
- p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
+ p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
+ p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
- p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
+ p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
- p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2),
- pci_cfgread(cfg, PCIR_IOBASEL_1, 1));
- p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2),
- pci_cfgread(cfg, PCIR_IOLIMITL_1, 1));
+ p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_IOBASEH_1, 2),
+ PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_IOBASEL_1, 1));
+ p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_IOLIMITH_1, 2),
+ PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_IOLIMITL_1, 1));
p->membase = PCI_PPBMEMBASE (0,
- pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
+ PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_MEMBASE_1, 2));
p->memlimit = PCI_PPBMEMLIMIT (0,
- pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
+ PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_MEMLIMIT_1, 2));
p->pmembase = PCI_PPBMEMBASE (
- (pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
- pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
+ (pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
+ PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
p->pmemlimit = PCI_PPBMEMLIMIT (
- (pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
- pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
+ (pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,
+ PCIR_PMLIMITH_1, 4),
+ PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
return (p);
}
/* read config data specific to header type 2 device (PCI to CardBus bridge) */
static void *
-pci_readpcb(pcicfgregs *cfg)
+pci_readpcb(device_t pcib, int b, int s, int f)
{
pcih2cfgregs *p;
- p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK);
+ p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK | M_ZERO);
if (p == NULL)
return (NULL);
- bzero(p, sizeof *p);
-
- p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
- p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
+ p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2);
+ p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2);
- p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
+ p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_2, 1);
- p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4);
- p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4);
- p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4);
- p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4);
-
- p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4);
- p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4);
- p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4);
- p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4);
+ p->membase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE0_2, 4);
+ p->memlimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT0_2, 4);
+ p->membase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE1_2, 4);
+ p->memlimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT1_2, 4);
+
+ p->iobase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE0_2, 4);
+ p->iolimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT0_2, 4);
+ p->iobase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE1_2, 4);
+ p->iolimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT1_2, 4);
- p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
+ p->pccardif = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PCCARDIF_2, 4);
return p;
}
/* extract header type specific config data */
static void
-pci_hdrtypedata(pcicfgregs *cfg)
+pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
{
+#define REG(n,w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
switch (cfg->hdrtype) {
case 0:
- cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
- cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
+ cfg->subvendor = REG(PCIR_SUBVEND_0, 2);
+ cfg->subdevice = REG(PCIR_SUBDEV_0, 2);
cfg->nummaps = PCI_MAXMAPS_0;
break;
case 1:
- cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2);
- cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2);
- cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1);
- cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1);
+ cfg->subvendor = REG(PCIR_SUBVEND_1, 2);
+ cfg->subdevice = REG(PCIR_SUBDEV_1, 2);
+ cfg->secondarybus = REG(PCIR_SECBUS_1, 1);
+ cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1);
cfg->nummaps = PCI_MAXMAPS_1;
- cfg->hdrspec = pci_readppb(cfg);
+ cfg->hdrspec = pci_readppb(pcib, b, s, f);
break;
case 2:
- cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_2, 2);
- cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2);
- cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1);
- cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1);
+ cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
+ cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
+ cfg->secondarybus = REG(PCIR_SECBUS_2, 1);
+ cfg->subordinatebus = REG(PCIR_SUBBUS_2, 1);
cfg->nummaps = PCI_MAXMAPS_2;
- cfg->hdrspec = pci_readpcb(cfg);
+ cfg->hdrspec = pci_readpcb(pcib, b, s, f);
break;
}
+#undef REG
}
/* read configuration header into pcicfgrect structure */
static struct pci_devinfo *
-pci_readcfg(pcicfgregs *probe)
+pci_read_device(device_t pcib, int b, int s, int f)
{
-#define REG(n, w) pci_cfgread(probe, n, w)
+#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
pcicfgregs *cfg = NULL;
struct pci_devinfo *devlist_entry;
@@ -331,33 +340,31 @@
devlist_entry = NULL;
- if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
+ if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) {
devlist_entry = malloc(sizeof(struct pci_devinfo),
- M_DEVBUF, M_WAITOK);
+ M_DEVBUF, M_WAITOK | M_ZERO);
if (devlist_entry == NULL)
return (NULL);
- bzero(devlist_entry, sizeof *devlist_entry);
cfg = &devlist_entry->cfg;
- cfg->hose = probe->hose;
- cfg->bus = probe->bus;
- cfg->slot = probe->slot;
- cfg->func = probe->func;
- cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2);
- cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2);
- cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2);
- cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2);
- cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1);
- cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1);
- cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1);
- cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1);
- cfg->hdrtype = pci_cfgread(cfg, PCIR_HEADERTYPE, 1);
- cfg->cachelnsz = pci_cfgread(cfg, PCIR_CACHELNSZ, 1);
- cfg->lattimer = pci_cfgread(cfg, PCIR_LATTIMER, 1);
- cfg->intpin = pci_cfgread(cfg, PCIR_INTPIN, 1);
- cfg->intline = pci_cfgread(cfg, PCIR_INTLINE, 1);
+ cfg->bus = b;
+ cfg->slot = s;
+ cfg->func = f;
+ cfg->vendor = REG(PCIR_VENDOR, 2);
+ cfg->device = REG(PCIR_DEVICE, 2);
+ cfg->cmdreg = REG(PCIR_COMMAND, 2);
+ cfg->statreg = REG(PCIR_STATUS, 2);
+ cfg->baseclass = REG(PCIR_CLASS, 1);
+ cfg->subclass = REG(PCIR_SUBCLASS, 1);
+ cfg->progif = REG(PCIR_PROGIF, 1);
+ cfg->revid = REG(PCIR_REVID, 1);
+ cfg->hdrtype = REG(PCIR_HEADERTYPE, 1);
+ cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1);
+ cfg->lattimer = REG(PCIR_LATTIMER, 1);
+ cfg->intpin = REG(PCIR_INTPIN, 1);
+ cfg->intline = REG(PCIR_INTLINE, 1);
#ifdef __alpha__
alpha_platform_assign_pciintr(cfg);
#endif
@@ -390,17 +397,17 @@
}
#endif /* APIC_IO */
- cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
- cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
+ cfg->mingnt = REG(PCIR_MINGNT, 1);
+ cfg->maxlat = REG(PCIR_MAXLAT, 1);
cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
cfg->hdrtype &= ~PCIM_MFDEV;
pci_fixancient(cfg);
- pci_hdrtypedata(cfg);
+ pci_hdrtypedata(pcib, b, s, f, cfg);
if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)
- pci_read_extcap(cfg);
+ pci_read_extcap(pcib, cfg);
STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
@@ -427,9 +434,9 @@
}
static void
-pci_read_extcap(pcicfgregs *cfg)
+pci_read_extcap(device_t pcib, pcicfgregs *cfg)
{
-#define REG(n, w) pci_cfgread(cfg, n, w)
+#define REG(n, w) PCIB_READ_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, w)
int ptr, nextptr, ptrptr;
switch (cfg->hdrtype) {
@@ -781,6 +788,7 @@
static int
pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
+ device_t pci, pcib;
struct pci_io *io;
const char *name;
int error;
@@ -1022,17 +1030,30 @@
case PCIOCREAD:
io = (struct pci_io *)data;
switch(io->pi_width) {
- pcicfgregs probe;
case 4:
case 2:
case 1:
- probe.hose = -1;
- probe.bus = io->pi_sel.pc_bus;
- probe.slot = io->pi_sel.pc_dev;
- probe.func = io->pi_sel.pc_func;
- io->pi_data = pci_cfgread(&probe,
- io->pi_reg, io->pi_width);
- error = 0;
+ /*
+ * Assume that the user-level bus number is
+ * actually the pciN instance number. We map
+ * from that to the real pcib+bus combination.
+ */
+ pci = devclass_get_device(pci_devclass,
+ io->pi_sel.pc_bus);
+ if (pci) {
+ int b = pcib_get_bus(pci);
+ pcib = device_get_parent(pci);
+ io->pi_data =
+ PCIB_READ_CONFIG(pcib,
+ b,
+ io->pi_sel.pc_dev,
+ io->pi_sel.pc_func,
+ io->pi_reg,
+ io->pi_width);
+ error = 0;
+ } else {
+ error = ENODEV;
+ }
break;
default:
error = ENODEV;
@@ -1043,17 +1064,30 @@
case PCIOCWRITE:
io = (struct pci_io *)data;
switch(io->pi_width) {
- pcicfgregs probe;
case 4:
case 2:
case 1:
- probe.hose = -1;
- probe.bus = io->pi_sel.pc_bus;
- probe.slot = io->pi_sel.pc_dev;
- probe.func = io->pi_sel.pc_func;
- pci_cfgwrite(&probe,
- io->pi_reg, io->pi_data, io->pi_width);
- error = 0;
+ /*
+ * Assume that the user-level bus number is
+ * actually the pciN instance number. We map
+ * from that to the real pcib+bus combination.
+ */
+ pci = devclass_get_device(pci_devclass,
+ io->pi_sel.pc_bus);
+ if (pci) {
+ int b = pcib_get_bus(pci);
+ pcib = device_get_parent(pci);
+ PCIB_WRITE_CONFIG(pcib,
+ b,
+ io->pi_sel.pc_dev,
+ io->pi_sel.pc_func,
+ io->pi_reg,
+ io->pi_data,
+ io->pi_width);
+ error = 0;
+ } else {
+ error = ENODEV;
+ }
break;
default:
error = ENODEV;
@@ -1105,6 +1139,8 @@
printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
cfg->vendor, cfg->device, cfg->revid);
+ printf("\tbus=%d, slot=%d, func=%d\n",
+ cfg->bus, cfg->slot, cfg->func);
printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
cfg->baseclass, cfg->subclass, cfg->progif,
cfg->hdrtype, cfg->mfdev);
@@ -1123,15 +1159,17 @@
}
static int
-pci_porten(pcicfgregs *cfg)
+pci_porten(device_t pcib, int b, int s, int f)
{
- return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
+ return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
+ & PCIM_CMD_PORTEN) != 0;
}
static int
-pci_memen(pcicfgregs *cfg)
+pci_memen(device_t pcib, int b, int s, int f)
{
- return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
+ return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
+ & PCIM_CMD_MEMEN) != 0;
}
/*
@@ -1139,26 +1177,28 @@
* register is a 32bit map register or 2 if it is a 64bit register.
*/
static int
-pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
+pci_add_map(device_t pcib, int b, int s, int f, int reg,
+ struct resource_list *rl)
{
- struct pci_devinfo *dinfo = device_get_ivars(dev);
- struct resource_list *rl = &dinfo->resources;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
u_int8_t ln2range;
u_int32_t testval;
-
+
+#ifdef PCI_ENABLE_IO_MODES
+ u_int16_t cmd;
+#endif
int type;
- map = pci_cfgread(cfg, reg, 4);
+ map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
if (map == 0 || map == 0xffffffff)
return 1; /* skip invalid entry */
- pci_cfgwrite(cfg, reg, 0xffffffff, 4);
- testval = pci_cfgread(cfg, reg, 4);
- pci_cfgwrite(cfg, reg, map, 4);
+ PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4);
+ testval = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
+ PCIB_WRITE_CONFIG(pcib, b, s, f, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
@@ -1169,59 +1209,8 @@
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
- base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
+ base |= (u_int64_t) PCIB_READ_CONFIG(pcib, b, s, f, reg+4, 4);
}
-
-#ifdef __alpha__
- /*
- * XXX: encode hose number in the base addr,
- * This will go away once the bus_space functions
- * can deal with multiple hoses
- */
-
- if (cfg->hose) {
- u_int32_t mask, shift, maxh;
-
- switch (hwrpb->rpb_type) {
- case ST_DEC_4100:
- case -ST_DEC_4100:
- mask = 0xc0000000;
- shift = 30;
- maxh = 4; /* not a hose. MCPCIA instance # */
- break;
- case ST_DEC_21000:
- mask = 0xf8000000;
- shift = 27;
- maxh = 32;
- break;
- case ST_DEC_6600:
- mask = 0x80000000;
- shift = 31;
- maxh = 2;
- break;
- default:
- mask = 0;
- shift = 0;
- maxh = 0;
- break;
- }
- if (base & mask) {
- printf("base addr = 0x%llx\n", (long long) base);
- printf("mask addr = 0x%lx\n", (long) mask);
- printf("hacked addr = 0x%llx\n", (long long)
- (base | ((u_int64_t)cfg->hose << shift)));
- panic("hose encoding hack would clobber base addr");
- /* NOTREACHED */
- }
- if (cfg->hose >= maxh) {
- panic("Hose %d - can only encode %d hose(s)",
- cfg->hose, maxh);
- /* NOTREACHED */
- }
- base |= ((u_int64_t)cfg->hose << shift);
- }
-#endif
-
/*
* This code theoretically does the right thing, but has
* undesirable side effects in some cases where
@@ -1229,18 +1218,20 @@
* enabled. Leave them alone by default.
*/
#ifdef PCI_ENABLE_IO_MODES
- if (type == SYS_RES_IOPORT && !pci_porten(cfg)) {
- cfg->cmdreg |= PCIM_CMD_PORTEN;
- pci_cfgwrite(cfg, PCIR_COMMAND, cfg->cmdreg, 2);
- }
- if (type == SYS_RES_MEMORY && !pci_memen(cfg)) {
- cfg->cmdreg |= PCIM_CMD_MEMEN;
- pci_cfgwrite(cfg, PCIR_COMMAND, cfg->cmdreg, 2);
+ if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f)) {
+ cmd = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2);
+ cmd |= PCIM_CMD_PORTEN;
+ PCIB_WRITE_CONFIG(pcib, b, s, f, PCIR_COMMAND, cmd, 2);
+ }
+ if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f)) {
+ cmd = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2);
+ cmd |= PCIM_CMD_MEMEN;
+ PCIB_WRITE_CONFIG(pcib, b, s, f, PCIR_COMMAND, cmd, 2);
}
#else
- if (type == SYS_RES_IOPORT && !pci_porten(cfg))
+ if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
return 1;
- if (type == SYS_RES_MEMORY && !pci_memen(cfg))
+ if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
return 1;
#endif
@@ -1258,21 +1249,22 @@
}
static void
-pci_add_resources(device_t dev, pcicfgregs* cfg)
+pci_add_resources(device_t pcib, int b, int s, int f, device_t dev)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
+ pcicfgregs *cfg = &dinfo->cfg;
struct resource_list *rl = &dinfo->resources;
struct pci_quirk *q;
int i;
for (i = 0; i < cfg->nummaps;) {
- i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
+ i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl);
}
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == ((cfg->device << 16) | cfg->vendor)
&& q->type == PCI_QUIRK_MAP_REG)
- pci_add_map(dev, cfg, q->arg1);
+ pci_add_map(pcib, b, s, f, q->arg1, rl);
}
if (cfg->intpin > 0 && cfg->intline != 255)
@@ -1283,26 +1275,17 @@
static void
pci_add_children(device_t dev, int busno)
{
- pcicfgregs probe;
-
-#ifdef SIMOS
-#undef PCI_SLOTMAX
-#define PCI_SLOTMAX 0
-#endif
+ device_t pcib = device_get_parent(dev);
+ int maxslots;
+ int s, f;
- bzero(&probe, sizeof probe);
-#ifdef __alpha__
- probe.hose = pcib_get_hose(dev);
-#endif
-#ifdef __i386__
- probe.hose = 0;
-#endif
- probe.bus = busno;
+ maxslots = PCIB_MAXSLOTS(pcib);
- for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
+ for (s = 0; s <= maxslots; s++) {
int pcifunchigh = 0;
- for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
- struct pci_devinfo *dinfo = pci_readcfg(&probe);
+ for (f = 0; f <= pcifunchigh; f++) {
+ struct pci_devinfo *dinfo =
+ pci_read_device(pcib, busno, s, f);
if (dinfo != NULL) {
if (dinfo->cfg.mfdev)
pcifunchigh = 7;
@@ -1310,19 +1293,34 @@
pci_print_verbose(dinfo);
dinfo->cfg.dev = device_add_child(dev, NULL, -1);
device_set_ivars(dinfo->cfg.dev, dinfo);
- pci_add_resources(dinfo->cfg.dev, &dinfo->cfg);
+ pci_add_resources(pcib, busno, s, f,
+ dinfo->cfg.dev);
}
}
}
}
static int
-pci_new_probe(device_t dev)
+pci_probe(device_t dev)
{
- static int once;
+ static int once, busno;
device_set_desc(dev, "PCI bus");
- pci_add_children(dev, device_get_unit(dev));
+
+ if (bootverbose)
+ device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev));
+
+ /*
+ * Since there can be multiple independently numbered PCI
+ * busses on some large alpha systems, we can't use the unit
+ * number to decide what bus we are probing. We ask the parent
+ * pcib what our bus number is.
+ */
+ busno = pcib_get_bus(dev);
+ if (busno < 0)
+ return ENXIO;
+ pci_add_children(dev, busno);
+
if (!once) {
make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci");
once++;
@@ -1401,6 +1399,7 @@
desc = pci_ata_match(child);
if (!desc) desc = pci_usb_match(child);
if (!desc) desc = pci_vga_match(child);
+ if (!desc) desc = pci_chip_match(child);
if (!desc) {
desc = "unknown card";
unknown++;
@@ -1423,7 +1422,7 @@
}
static int
-pci_read_ivar(device_t dev, device_t child, int which, u_long *result)
+pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct pci_devinfo *dinfo;
pcicfgregs *cfg;
@@ -1480,12 +1479,6 @@
case PCI_IVAR_SUBORDINATEBUS:
*result = cfg->subordinatebus;
break;
- case PCI_IVAR_HOSE:
- /*
- * Pass up to parent bridge.
- */
- *result = pcib_get_hose(dev);
- break;
default:
return ENOENT;
}
@@ -1536,8 +1529,8 @@
{
struct pci_devinfo *dinfo = device_get_ivars(child);
struct resource_list *rl = &dinfo->resources;
-
-#ifdef __i386__ /* Only supported on x86 in stable */
+
+#ifdef __i386__
pcicfgregs *cfg = &dinfo->cfg;
/*
* Perform lazy resource allocation
@@ -1552,8 +1545,9 @@
if ((type == SYS_RES_IRQ) &&
(cfg->intline == 255 || cfg->intline == 0) &&
(cfg->intpin != 0) && (start == 0) && (end == ~0UL)) {
- cfg->intline = pci_cfgintr(pci_get_bus(child),
- pci_get_slot(child), cfg->intpin);
+ cfg->intline = PCIB_ROUTE_INTERRUPT(
+ device_get_parent(dev), pci_get_slot(child),
+ cfg->intpin);
if (cfg->intline != 255) {
pci_write_config(child, PCIR_INTLINE,
cfg->intline, 1);
@@ -1619,7 +1613,10 @@
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
- return pci_cfgread(cfg, reg, width);
+
+ return PCIB_READ_CONFIG(device_get_parent(dev),
+ cfg->bus, cfg->slot, cfg->func,
+ reg, width);
}
static void
@@ -1628,7 +1625,10 @@
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
- pci_cfgwrite(cfg, reg, val, width);
+
+ return PCIB_WRITE_CONFIG(device_get_parent(dev),
+ cfg->bus, cfg->slot, cfg->func,
+ reg, val, width);
}
static int
@@ -1648,7 +1648,7 @@
static device_method_t pci_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, pci_new_probe),
+ DEVMETHOD(device_probe, pci_probe),
DEVMETHOD(device_attach, bus_generic_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
diff -uNr sys.old/bus/pci/pci_compat.c sys/bus/pci/pci_compat.c
--- sys.old/bus/pci/pci_compat.c Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pci_compat.c Sat Dec 20 17:08:07 2003
@@ -69,6 +69,18 @@
}
int
+pci_cfgread (pcicfgregs *cfg, int reg, int bytes)
+{
+ return (pci_read_config(cfg->dev, reg, bytes));
+}
+
+void
+pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ pci_write_config(cfg->dev, reg, data, bytes);
+}
+
+int
pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa)
{
int rid;
diff -uNr sys.old/bus/pci/pcib_if.m sys/bus/pci/pcib_if.m
--- sys.old/bus/pci/pcib_if.m Thu Jan 1 00:00:00 1970
+++ sys/bus/pci/pcib_if.m Sat Dec 20 17:08:07 2003
@@ -0,0 +1,82 @@
+#
+# Copyright (c) 2000 Doug Rabson
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: src/sys/pci/pcib_if.m,v 1.2 2000/10/16 19:43:44 imp Exp $
+# $DragonFly$
+#
+
+#include <sys/bus.h>
+
+INTERFACE pcib;
+
+#
+# Return the number of slots on the attached PCI bus.
+#
+METHOD int maxslots {
+ device_t dev;
+};
+
+#
+# Read configuration space on the PCI bus. The bus, slot and func
+# arguments determine the device which is being read and the reg
+# argument is a byte offset into configuration space for that
+# device. The width argument (which should be 1, 2 or 4) specifies how
+# many byte of configuration space to read from that offset.
+#
+METHOD u_int32_t read_config {
+ device_t dev;
+ int bus;
+ int slot;
+ int func;
+ int reg;
+ int width;
+};
+
+#
+# Write configuration space on the PCI bus. The bus, slot and func
+# arguments determine the device which is being written and the reg
+# argument is a byte offset into configuration space for that
+# device. The value field is written to the configuration space, with
+# the number of bytes written depending on the width argument.
+#
+METHOD void write_config {
+ device_t dev;
+ int bus;
+ int slot;
+ int func;
+ int reg;
+ u_int32_t value;
+ int width;
+};
+
+#
+# Route an interrupt. Returns a value suitable for stuffing into
+# a device's interrupt register.
+#
+METHOD int route_interrupt {
+ device_t bus;
+ device_t device;
+ int pin;
+};
diff -uNr sys.old/bus/pci/pcisupport.c sys/bus/pci/pcisupport.c
--- sys.old/bus/pci/pcisupport.c Fri Oct 31 22:00:13 2003
+++ sys/bus/pci/pcisupport.c Sat Dec 20 17:08:07 2003
@@ -58,6 +58,8 @@
#include <vm/vm_object.h>
#include <vm/pmap.h>
+#include "pcib_if.h"
+
/*---------------------------------------------------------
**
** Intel chipsets for 486 / Pentium processor
@@ -768,7 +770,7 @@
desc = pcib_match(dev);
if (desc) {
device_set_desc_copy(dev, desc);
- return 0;
+ return -1000;
}
return ENXIO;
@@ -777,30 +779,71 @@
static int pcib_attach(device_t dev)
{
u_int8_t secondary;
+ device_t child;
chipset_attach(dev, device_get_unit(dev));
secondary = pci_get_secondarybus(dev);
if (secondary) {
- device_add_child(dev, "pci", secondary);
+ child = device_add_child(dev, "pci", -1);
+ *(int*) device_get_softc(dev) = secondary;
return bus_generic_attach(dev);
} else
return 0;
}
static int
-pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
+pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
- if (which == PCIB_IVAR_HOSE) {
- /*
- * Pass up to parent bus.
- */
- *result = pci_get_hose(dev);
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = *(int*) device_get_softc(dev);
return(0);
}
return ENOENT;
}
+static int
+pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *(int*) device_get_softc(dev) = value;
+ return (0);
+ }
+ return ENOENT;
+}
+
+static int
+pcib_maxslots(device_t dev)
+{
+ return 31;
+}
+
+static u_int32_t
+pcib_read_config(device_t dev, int b, int s, int f,
+ int reg, int width)
+{
+ /*
+ * Pass through to the next ppb up the chain (i.e. our
+ * grandparent).
+ */
+ return PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)),
+ b, s, f, reg, width);
+}
+
+static void
+pcib_write_config(device_t dev, int b, int s, int f,
+ int reg, int val, int width)
+{
+ /*
+ * Pass through to the next ppb up the chain (i.e. our
+ * grandparent).
+ */
+ PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)),
+ b, s, f, reg, val, width);
+}
+
/*
* Route an interrupt across a PCI bridge.
*/
@@ -849,6 +892,7 @@
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@@ -858,13 +902,19 @@
/* pci interface */
DEVMETHOD(pci_route_interrupt, pcib_route_interrupt),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, pcib_maxslots),
+ DEVMETHOD(pcib_read_config, pcib_read_config),
+ DEVMETHOD(pcib_write_config, pcib_write_config),
+
{ 0, 0 }
};
static driver_t pcib_driver = {
"pcib",
pcib_methods,
- 1,
+ sizeof(int),
};
static devclass_t pcib_devclass;
@@ -1166,8 +1216,8 @@
}
-static const char*
-chip_match(device_t dev)
+const char*
+pci_chip_match(device_t dev)
{
unsigned rev;
@@ -1369,53 +1419,6 @@
return NULL;
}
-static int chip_probe(device_t dev)
-{
- const char *desc;
-
- desc = chip_match(dev);
- if (desc) {
- if (pci_get_class(dev) == PCIC_BRIDGE
- && pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
- /*
- * Suppress printing this device since the nexus
- * has already described it.
- */
- device_quiet(dev);
- }
-
- device_set_desc_copy(dev, desc);
- return -10000; /* Low match priority */
- }
-
- return ENXIO;
-}
-
-static int chip_attach(device_t dev)
-{
- chipset_attach(dev, device_get_unit(dev));
-
- return 0;
-}
-
-static device_method_t chip_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, chip_probe),
- DEVMETHOD(device_attach, chip_attach),
-
- { 0, 0 }
-};
-
-static driver_t chip_driver = {
- "chip",
- chip_methods,
- 1,
-};
-
-static devclass_t chip_devclass;
-
-DRIVER_MODULE(chip, pci, chip_driver, chip_devclass, 0, 0);
-
/*---------------------------------------------------------
**
** Catchall driver for VGA devices
@@ -1932,20 +1935,34 @@
**---------------------------------------------------------
*/
-static int
-ign_probe (device_t dev)
+static const char*
+ign_match(device_t dev)
{
switch (pci_get_devid(dev)) {
case 0x10001042ul: /* wd */
- return 0;
-/* return ("SMC FDC 37c665");*/
+ return ("SMC FDC 37c665");
};
+
+ return NULL;
+}
+
+static int
+ign_probe(device_t dev)
+{
+ const char *s;
+
+ s = ign_match(dev);
+ if (s) {
+ device_set_desc(dev, s);
+ device_quiet(dev);
+ return -1000;
+ }
return ENXIO;
}
static int
-ign_attach (device_t dev)
+ign_attach(device_t dev)
{
return 0;
}
diff -uNr sys.old/bus/pci/pcivar.h sys/bus/pci/pcivar.h
--- sys.old/bus/pci/pcivar.h Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pcivar.h Sat Dec 20 17:08:07 2003
@@ -24,6 +24,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/pci/pcivar.h,v 1.41.2.2 2002/01/10 12:08:22 mdodd Exp $
+ * merged in revision 1.48
* $DragonFly: src/sys/bus/pci/pcivar.h,v 1.2 2003/06/17 04:28:57 dillon Exp $
*
*/
@@ -83,7 +84,6 @@
u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
u_int8_t nummaps; /* actual number of PCI maps used */
- u_int8_t hose; /* hose which bus is attached to */
u_int8_t bus; /* config space bus address */
u_int8_t slot; /* config space slot address */
u_int8_t func; /* config space function number */
@@ -156,6 +156,7 @@
const char *pci_ata_match(struct device *dev);
const char *pci_usb_match(struct device *dev);
const char *pci_vga_match(struct device *dev);
+const char *pci_chip_match(struct device *dev);
/* low level PCI config register functions provided by pcibus.c */
@@ -197,7 +198,6 @@
PCI_IVAR_FUNCTION,
PCI_IVAR_SECONDARYBUS,
PCI_IVAR_SUBORDINATEBUS,
- PCI_IVAR_HOSE,
};
@@ -214,7 +214,7 @@
\
static __inline void pci_set_ ## A(device_t dev, T t) \
{ \
- u_long v = (u_long) t; \
+ uintptr_t v = (uintptr_t) t; \
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v); \
}
@@ -234,7 +234,8 @@
PCI_ACCESSOR(function, FUNCTION, u_int8_t)
PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t)
PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t)
-PCI_ACCESSOR(hose, HOSE, u_int32_t)
+
+#undef PCI_ACCESSOR
static __inline u_int32_t
pci_read_config(device_t dev, int reg, int width)
@@ -317,7 +318,7 @@
/*typedef enum pci_device_ivars pcib_device_ivars;*/
enum pcib_device_ivars {
- PCIB_IVAR_HOSE,
+ PCIB_IVAR_BUS,
};
#define PCIB_ACCESSOR(A, B, T) \
@@ -331,11 +332,13 @@
\
static __inline void pcib_set_ ## A(device_t dev, T t) \
{ \
- u_long v = (u_long) t; \
+ uintptr_t v = (uintptr_t) t; \
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \
}
-PCIB_ACCESSOR(hose, HOSE, u_int32_t)
+PCIB_ACCESSOR(bus, BUS, u_int32_t)
+
+#undef PCIB_ACCESSOR
device_t pci_find_bsf(u_int8_t, u_int8_t, u_int8_t);
device_t pci_find_device(u_int16_t, u_int16_t);
diff -uNr sys.old/conf/files sys/conf/files
--- sys.old/conf/files Sat Dec 20 16:56:09 2003
+++ sys/conf/files Sat Dec 20 17:08:07 2003
@@ -1106,6 +1106,7 @@
warning "Old PCI driver compatability shims present."
bus/pci/pcisupport.c optional pci
bus/pci/pci_if.m optional pci
+bus/pci/pcib_if.m optional pci
dev/disk/simos/simos.c optional simos
dev/powermng/i386/alpm/alpm.c optional alpm
dev/misc/xrpu/xrpu.c optional xrpu
diff -uNr sys.old/conf/files.i386 sys/conf/files.i386
--- sys.old/conf/files.i386 Sun Dec 7 19:23:36 2003
+++ sys/conf/files.i386 Sat Dec 20 17:08:07 2003
@@ -273,7 +273,7 @@
dev/sound/isa/i386/pca/pcaudio.c optional pca
bus/iicbus/i386/pcf.c optional pcf
bus/pci/i386/pci_cfgreg.c optional pci
-bus/pci/i386/pcibus.c optional pci
+bus/pci/i386/pci_bus.c optional pci
dev/video/pcvt/i386/pcvt_drv.c optional vt
dev/video/pcvt/i386/pcvt_ext.c optional vt
dev/video/pcvt/i386/pcvt_kbd.c optional vt
diff -uNr sys.old/i386/i386/nexus.c sys/i386/i386/nexus.c
--- sys.old/i386/i386/nexus.c Thu Aug 7 21:17:22 2003
+++ sys/i386/i386/nexus.c Sat Dec 20 17:08:07 2003
@@ -27,6 +27,7 @@
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/i386/i386/nexus.c,v 1.26.2.10 2003/02/22 13:16:45 imp Exp $
+ * Mostly updated to 1.37
* $DragonFly: src/sys/i386/i386/nexus.c,v 1.3 2003/08/07 21:17:22 dillon Exp $
*/
@@ -57,12 +58,14 @@
#include <vm/pmap.h>
#include <machine/pmap.h>
+#include <machine/nexusvar.h>
#include <machine/resource.h>
#ifdef APIC_IO
#include <machine/smp.h>
#include <machine/mpapic.h>
#endif
+#include <bus/isa/isavar.h>
#ifdef PC98
#include <pc98/pc98/pc98.h>
#else
@@ -73,6 +76,7 @@
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
+ int nx_pcibus;
};
#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
@@ -87,6 +91,8 @@
int unit);
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
u_long, u_long, u_long, u_int);
+static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
static int nexus_activate_resource(device_t, device_t, int, int,
struct resource *);
static int nexus_deactivate_resource(device_t, device_t, int, int,
@@ -113,8 +119,8 @@
/* Bus interface */
DEVMETHOD(bus_print_child, nexus_print_child),
DEVMETHOD(bus_add_child, nexus_add_child),
- DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
- DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
+ DEVMETHOD(bus_read_ivar, nexus_read_ivar),
+ DEVMETHOD(bus_write_ivar, nexus_write_ivar),
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
DEVMETHOD(bus_release_resource, nexus_release_resource),
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
@@ -144,36 +150,39 @@
device_quiet(dev); /* suppress attach message for neatness */
/*
+ * XXX working notes:
+ *
+ * - IRQ resource creation should be moved to the PIC/APIC driver.
+ * - DRQ resource creation should be moved to the DMAC driver.
+ * - The above should be sorted to probe earlier than any child busses.
+ *
+ * - Leave I/O and memory creation here, as child probes may need them.
+ * (especially e.g. ACPI)
+ */
+
+
+ /*
* IRQ's are on the mainboard on old systems, but on the ISA part
* of PCI->ISA bridges. There would be multiple sets of IRQs on
* multi-ISA-bus systems. PCI interrupts are routed to the ISA
* component, so in a way, PCI can be a partial child of an ISA bus(!).
* APIC interrupts are global though.
- * In the non-APIC case, disallow the use of IRQ 2.
+ *
+ * XXX We depend on the AT PIC driver correctly claiming IRQ 2
+ * to prevent its reuse elsewhere in the !APIC_IO case.
*/
irq_rman.rm_start = 0;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "Interrupt request lines";
#ifdef APIC_IO
irq_rman.rm_end = APIC_INTMAPSIZE - 1;
- if (rman_init(&irq_rman)
- || rman_manage_region(&irq_rman,
- irq_rman.rm_start, irq_rman.rm_end))
- panic("nexus_probe irq_rman");
#else
irq_rman.rm_end = 15;
-#ifdef PC98
+#endif
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman,
irq_rman.rm_start, irq_rman.rm_end))
panic("nexus_probe irq_rman");
-#else
- if (rman_init(&irq_rman)
- || rman_manage_region(&irq_rman, irq_rman.rm_start, 1)
- || rman_manage_region(&irq_rman, 3, irq_rman.rm_end))
- panic("nexus_probe irq_rman");
-#endif /* PC98 */
-#endif
/*
* ISA DMA on PCI systems is implemented in the ISA part of each
@@ -262,7 +271,7 @@
struct resource_list *rl = &ndev->nx_resources;
int retval = 0;
- if (SLIST_FIRST(rl))
+ if (SLIST_FIRST(rl) || ndev->nx_pcibus != -1)
retval += printf(" at");
retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
@@ -275,10 +284,13 @@
static int
nexus_print_child(device_t bus, device_t child)
{
+ struct nexus_device *ndev = DEVTONX(child);
int retval = 0;
retval += bus_print_child_header(bus, child);
retval += nexus_print_all_resources(child);
+ if (ndev->nx_pcibus != -1)
+ retval += printf(" pcibus %d", ndev->nx_pcibus);
retval += printf(" on motherboard\n");
return (retval);
@@ -294,6 +306,7 @@
if (!ndev)
return(0);
resource_list_init(&ndev->nx_resources);
+ ndev->nx_pcibus = -1;
child = device_add_child_ordered(bus, order, name, unit);
@@ -303,6 +316,36 @@
return(child);
}
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct nexus_device *ndev = DEVTONX(child);
+
+ switch (which) {
+ case NEXUS_IVAR_PCIBUS:
+ *result = ndev->nx_pcibus;
+ break;
+ default:
+ return ENOENT;
+ }
+ return 0;
+}
+
+static int
+nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct nexus_device *ndev = DEVTONX(child);
+
+ switch (which) {
+ case NEXUS_IVAR_PCIBUS:
+ ndev->nx_pcibus = value;
+ break;
+ default:
+ return ENOENT;
+ }
+ return 0;
+}
+
/*
* Allocate a resource on behalf of child. NB: child is usually going to be a
* child of one of our descendants, not a direct child of nexus0.
@@ -405,18 +448,18 @@
if (rman_get_bustag(r) == I386_BUS_SPACE_MEM) {
caddr_t vaddr = 0;
- if (r->r_end < 1024 * 1024) {
+ if (rman_get_end(r) < 1024 * 1024) {
/*
* The first 1Mb is mapped at KERNBASE.
*/
- vaddr = (caddr_t)(uintptr_t)(KERNBASE + r->r_start);
+ vaddr = (caddr_t)(uintptr_t)(KERNBASE + rman_get_start(r));
} else {
u_int32_t paddr;
u_int32_t psize;
u_int32_t poffs;
- paddr = r->r_start;
- psize = r->r_end - r->r_start;
+ paddr = rman_get_start(r);
+ psize = rman_get_size(r);
poffs = paddr - trunc_page(paddr);
vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
@@ -440,10 +483,11 @@
/*
* If this is a memory resource, unmap it.
*/
- if ((rman_get_bustag(r) == I386_BUS_SPACE_MEM) && (r->r_end >= 1024 * 1024)) {
+ if ((rman_get_bustag(r) == I386_BUS_SPACE_MEM) &&
+ (rman_get_end(r) >= 1024 * 1024)) {
u_int32_t psize;
- psize = r->r_end - r->r_start;
+ psize = rman_get_size(r);
pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize);
}
@@ -454,7 +498,7 @@
nexus_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
- if (r->r_flags & RF_ACTIVE) {
+ if (rman_get_flags(r) & RF_ACTIVE) {
int error = bus_deactivate_resource(child, type, rid, r);
if (error)
return error;
@@ -574,3 +618,51 @@
resource_list_delete(rl, type, rid);
}
+
+/*
+ * Placeholder which claims PnP 'devices' which describe system
+ * resources.
+ */
+static struct isa_pnp_id sysresource_ids[] = {
+ { 0x010cd041 /* PNP0c01 */, "System Memory" },
+ { 0x020cd041 /* PNP0c02 */, "System Resource" },
+ { 0 }
+};
+
+static int
+sysresource_probe(device_t dev)
+{
+ int result;
+
+ if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, sysresource_ids)) >= 0) {
+ device_quiet(dev);
+ }
+ return (result);
+}
+
+static int
+sysresource_attach(device_t dev)
+{
+ return (0);
+}
+
+static device_method_t sysresource_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, sysresource_probe),
+ DEVMETHOD(device_attach, sysresource_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ { 0, 0 }
+};
+
+static driver_t sysresource_driver = {
+ "sysresource",
+ sysresource_methods,
+ 1, /* no softc */
+};
+
+static devclass_t sysresource_devclass;
+
+DRIVER_MODULE(sysresource, isa, sysresource_driver, sysresource_devclass, 0, 0);
diff -uNr sys.old/i386/include/nexusvar.h sys/i386/include/nexusvar.h
--- sys.old/i386/include/nexusvar.h Thu Jan 1 00:00:00 1970
+++ sys/i386/include/nexusvar.h Sat Dec 20 17:08:07 2003
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2000 Peter Wemm <peter@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/nexusvar.h,v 1.1 2000/09/28 00:37:31 peter Exp $
+ * $DragonFly$
+ */
+
+#ifndef _MACHINE_NEXUSVAR_H_
+#define _MACHINE_NEXUSVAR_H_ 1
+
+enum nexus_device_ivars {
+ NEXUS_IVAR_PCIBUS
+};
+
+#define NEXUS_ACCESSOR(A, B, T) \
+ \
+static __inline T nexus_get_ ## A(device_t dev) \
+{ \
+ uintptr_t v; \
+ BUS_READ_IVAR(device_get_parent(dev), dev, NEXUS_IVAR_ ## B, &v); \
+ return (T) v; \
+} \
+ \
+static __inline void nexus_set_ ## A(device_t dev, T t) \
+{ \
+ uintptr_t v = (uintptr_t) t; \
+ BUS_WRITE_IVAR(device_get_parent(dev), dev, NEXUS_IVAR_ ## B, v); \
+}
+
+NEXUS_ACCESSOR(pcibus, PCIBUS, u_int32_t)
+
+#undef NEXUS_ACCESSOR
+
+#endif /* !_MACHINE_NEXUSVAR_H_ */
diff -uNr sys.old/sys/rman.h sys/sys/rman.h
--- sys.old/sys/rman.h Sat Jul 19 21:14:50 2003
+++ sys/sys/rman.h Sat Dec 20 17:08:07 2003
@@ -64,6 +64,7 @@
#define RF_TIMESHARE 0x0008 /* resource permits time-division sharing */
#define RF_WANTED 0x0010 /* somebody is waiting for this resource */
#define RF_FIRSTSHARE 0x0020 /* first in sharing list */
+#define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */
#define RF_ALIGNMENT_SHIFT 10 /* alignment size bit starts bit 10 */
#define RF_ALIGNMENT_MASK (0x003F << RF_ALIGNMENT_SHIFT)
@@ -100,6 +101,8 @@
#define rman_get_start(r) ((r)->r_start)
#define rman_get_end(r) ((r)->r_end)
+#define rman_get_device(r) ((r)->r_dev)
+#define rman_get_size(r) (((r)->r_end - (r)->r_start) +1 )
#define rman_get_flags(r) ((r)->r_flags)
#define rman_set_virtual(r,v) ((r)->r_virtual = (v))
#define rman_get_virtual(r) ((r)->r_virtual)
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]