summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/include/pci_cfgreg.h48
-rw-r--r--sys/amd64/pci/pci_bus.c653
-rw-r--r--sys/amd64/pci/pci_cfgreg.c653
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/pci/pci.c2181
-rw-r--r--sys/dev/pci/pcireg.h446
-rw-r--r--sys/dev/pci/pcivar.h406
-rw-r--r--sys/i386/include/pci_cfgreg.h48
-rw-r--r--sys/i386/isa/pcibus.c653
-rw-r--r--sys/i386/isa/pcibus.h48
-rw-r--r--sys/i386/pci/pci_bus.c653
-rw-r--r--sys/i386/pci/pci_cfgreg.c653
-rw-r--r--sys/i386/pci/pci_pir.c653
-rw-r--r--sys/pci/pci.c2181
-rw-r--r--sys/pci/pci_compat.c351
-rw-r--r--sys/pci/pcireg.h446
-rw-r--r--sys/pci/pcisupport.c28
-rw-r--r--sys/pci/pcivar.h406
-rw-r--r--sys/pci/tek390.c15
19 files changed, 3252 insertions, 7271 deletions
diff --git a/sys/amd64/include/pci_cfgreg.h b/sys/amd64/include/pci_cfgreg.h
new file mode 100644
index 0000000..44556e7
--- /dev/null
+++ b/sys/amd64/include/pci_cfgreg.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#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
diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c
index 31de543..df84794 100644
--- a/sys/amd64/pci/pci_bus.c
+++ b/sys/amd64/pci/pci_bus.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index 31de543..df84794 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/conf/files b/sys/conf/files
index f1b650f..0361768 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -343,6 +343,7 @@ pci/if_vx_pci.c optional vx device-driver
pci/meteor.c optional meteor device-driver
pci/ncr.c optional ncr device-driver
pci/pci.c optional pci device-driver
+pci/pci_compat.c optional pci
pci/pcisupport.c optional pci
pci/tek390.c optional amd device-driver
pci/wdc_p.c optional wdc device-driver
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 4456fe6..b6f056e 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,1893 +1,459 @@
-/**************************************************************************
-**
-** $Id: pci.c,v 1.70 1997/04/26 11:46:18 peter Exp $
-**
-** General subroutines for the PCI bus.
-** pci_configure ()
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
#include "pci.h"
#if NPCI > 0
-/*========================================================
-**
-** #includes and declarations
-**
-**========================================================
-*/
-
-#include "opt_smp.h"
+#include <stddef.h>
+#include <sys/types.h>
#include <sys/param.h>
+#include <sys/time.h>
#include <sys/systm.h>
#include <sys/malloc.h>
-#include <sys/errno.h>
-#include <sys/kernel.h>
-#include <sys/proc.h> /* declaration of wakeup(), used by vm.h */
+#include <sys/fcntl.h>
#include <sys/conf.h>
+#include <sys/kernel.h>
#ifdef DEVFS
#include <sys/devfsext.h>
#endif /* DEVFS */
-#include <sys/fcntl.h>
#include <vm/vm.h>
-#include <vm/vm_param.h>
#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h> /* XXX inthand2_t */
-
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
+#include <pci/pcivar.h>
#include <pci/pci_ioctl.h>
-/*========================================================
-**
-** Structs and Functions
-**
-**========================================================
-*/
-
-struct pcicb {
- struct pcicb *pcicb_next;
- struct pcicb *pcicb_up;
- struct pcicb *pcicb_down;
- pcici_t pcicb_bridge;
-
- u_char pcicb_bus;
- u_char pcicb_subordinate;
- u_int pcicb_mfrom;
- u_int pcicb_mupto;
- u_int pcicb_mamount;
- u_short pcicb_pfrom;
- u_short pcicb_pupto;
- u_short pcicb_pamount;
- u_char pcicb_bfrom;
- u_char pcicb_bupto;
-
- u_long pcicb_iobase;
- u_long pcicb_iolimit;
- u_long pcicb_membase;
- u_long pcicb_memlimit;
- u_long pcicb_p_membase;
- u_long pcicb_p_memlimit;
-};
-
-struct pci_lkm {
- struct pci_device *dvp;
- struct pci_lkm *next;
-};
-
-static void
-not_supported (pcici_t tag, u_long type);
-
-static void
-pci_bus_config (void);
-
-static void
-pci_rescan (void);
-
-static void pci_attach (int bus, int dev, int func,
- struct pci_device *dvp, const char *name);
-
-static int
-pci_bridge_config (void);
+/* return highest PCI bus number known to be used, or -1 if none */
static int
-pci_mfdev (int bus, int device);
-
-static void pci_remember (int bus, int dev, int func, struct pci_device *dvp);
-
-/*========================================================
-**
-** Variables
-**
-**========================================================
-*/
-
-/*
-** log2 of safe burst len (in words)
-*/
-
-unsigned pci_max_burst_len = 3; /* 2=16Byte, 3=32Byte, 4=64Byte, ... */
-unsigned pci_mechanism = 0;
-unsigned pci_maxdevice = 0;
-unsigned pciroots = 0; /* XXX pcisupport.c increments this
- * for the Orion host to PCI bridge
- * UGLY hack ... :( Will be changed :)
- */
-/*--------------------------------------------------------
-**
-** Local variables.
-**
-**--------------------------------------------------------
-*/
-
-static struct pcibus *pcibus;
-
-static int pci_conf_count;
-static int pci_info_done;
-static int pcibusmax;
-static struct pcicb *pcicb;
-
-static struct pci_conf *pci_dev_list;
-static unsigned pci_dev_list_count;
-static unsigned pci_dev_list_size;
-
-static struct pci_lkm *pci_lkm_head;
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided for the device driver
-** to read/write the configuration space.
-**
-** pci_conf_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word alligned one).
-**
-** pci_conf_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word alligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-u_long
-pci_conf_read (pcici_t tag, u_long reg)
-{
- return (pcibus->pb_read (tag, reg));
-}
-
-void
-pci_conf_write (pcici_t tag, u_long reg, u_long data)
-{
- pcibus->pb_write (tag, reg, data);
-}
-
-/*========================================================
-**
-** Subroutines for configuration.
-**
-**========================================================
-*/
-
-static void
-pci_register_io (struct pcicb * cb, u_int base, u_int limit)
+pci_bushigh(void)
{
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("register_io: bus=%d base=%x limit=%x\n",
- cb->pcicb_bus, base, limit);
-#endif
-
- if (!cb->pcicb_pfrom || base < cb->pcicb_pfrom)
- cb->pcicb_pfrom = base;
- if (limit > cb->pcicb_pupto)
- cb->pcicb_pupto = limit;
-
- /*
- ** XXX should set bridge io mapping here
- ** but it can be mapped in 4k blocks only,
- ** leading to conflicts with isa/eisa ..
- */
+ if (pci_cfgopen() == 0)
+ return (-1);
+ return (0);
}
-static void
-pci_register_memory (struct pcicb * cb, u_int base, u_int limit)
-{
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("register_mem: bus=%d base=%x limit=%x\n",
- cb->pcicb_bus, base, limit);
-#endif
+/* return base address of memory or port map */
- if (!cb->pcicb_mfrom || base < cb->pcicb_mfrom)
- cb->pcicb_mfrom = base;
- if (limit > cb->pcicb_mupto)
- cb->pcicb_mupto = limit;
- /*
- ** set the bridges mapping
- **
- ** XXX should handle the 1Mb granularity.
- */
- if (cb->pcicb_bridge.tag) {
- pci_conf_write(cb->pcicb_bridge,
- PCI_PCI_BRIDGE_MEM_REG,
- (cb->pcicb_memlimit & 0xffff0000) |
- (cb->pcicb_membase >> 16));
- if (bootverbose)
- printf ("\t[pci%d uses memory from %x to %x]\n",
- cb->pcicb_bus,
- (unsigned) cb->pcicb_membase,
- (unsigned) cb->pcicb_memlimit);
- }
-}
-
-/*
-** XXX This function is neither complete nor tested.
-** It's only used if the bios hasn't done it's job
-** of mapping the pci devices in the physical memory.
-*/
-
-static u_int
-pci_memalloc (struct pcicb * cb, u_int addr, u_int size)
+static int
+pci_mapbase(unsigned mapreg)
{
- u_int result = 0, limit=0, newbase=0;
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("memalloc: bus=%d addr=%x size=%x ..\n",
- cb->pcicb_bus, addr, size);
-#endif
-
- if (!cb) goto done;
-
- if (!cb->pcicb_membase) {
- printf ("memalloc: bus%d: membase not set.\n",
- cb->pcicb_bus);
- goto done;
- }
-
- /*
- ** get upper allocation limit
- */
- limit = cb->pcicb_memlimit;
- if (cb->pcicb_mfrom && cb->pcicb_mfrom <= limit)
- limit = cb->pcicb_mfrom-1;
-
- /*
- ** address fixed, and impossible to allocate ?
- */
- if (addr && addr+size-1 > limit)
- goto done;
-
- /*
- ** get possible address
- */
-
- result = addr;
- if (!result) result = ((limit + 1) / size - 1) * size;
-
- /*
- ** if not local available, request from parent.
- */
-
- if (result < cb->pcicb_membase) {
- newbase = pci_memalloc (cb->pcicb_up, result, size);
- if (newbase) cb->pcicb_membase = result;
- else result=0;
- }
-done:
- if (result)
- pci_register_memory (cb, result, result+size-1);
-
-#ifdef PCI_BRIDGE_DEBUG
- printf ("memalloc: bus=%d addr=%x size=%x --> %x (limit=%x).\n",
- cb->pcicb_bus, addr, size, result, limit);
-#endif
-
- return (result);
+ int mask = 0x03;
+ if ((mapreg & 0x01) == 0)
+ mask = 0x0f;
+ return (mapreg & ~mask);
}
-/*========================================================
-**
-** pci_bridge_config()
-**
-** Configuration of a pci bridge.
-**
-**========================================================
-*/
+/* return map type of memory or port map */
static int
-pci_bridge_config (void)
-{
- pcici_t tag;
- struct pcicb* parent;
-
- tag = pcicb->pcicb_bridge;
- if (tag.tag) {
-
- if (!pcicb->pcicb_bus) {
- u_int data;
- /*
- ** Get the lowest available bus number.
- */
- pcicb->pcicb_bus = ++pcibusmax;
-
- /*
- ** and configure the bridge
- */
- data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
- data = PCI_PRIMARY_BUS_INSERT(data, pcicb->pcicb_up->pcicb_bus);
- data = PCI_SECONDARY_BUS_INSERT(data, pcicb->pcicb_bus);
- data = PCI_SUBORDINATE_BUS_INSERT(data, pcicb->pcicb_bus);
- pci_conf_write (tag, PCI_PCI_BRIDGE_BUS_REG, data);
-
- /*
- ** Propagate the new upper bus number limit.
- */
- for (parent = pcicb->pcicb_up; parent != NULL;
- parent = parent->pcicb_up)
- {
- if (parent->pcicb_subordinate >= pcicb->pcicb_bus)
- continue;
- parent->pcicb_subordinate = pcicb->pcicb_bus;
- if (!parent->pcicb_bridge.tag)
- continue;
- data = pci_conf_read
- (parent->pcicb_bridge, PCI_PCI_BRIDGE_BUS_REG);
- data = PCI_SUBORDINATE_BUS_INSERT
- (data, pcicb->pcicb_bus);
- pci_conf_write (parent->pcicb_bridge,
- PCI_PCI_BRIDGE_BUS_REG, data);
- }
- }
-
- if (!pcicb->pcicb_membase) {
- u_int size = 0x100000;
- pcicb->pcicb_membase = pci_memalloc (pcicb->pcicb_up, 0, size);
- if (pcicb->pcicb_membase)
- pcicb->pcicb_memlimit = pcicb->pcicb_membase+size-1;
- }
- }
- return pcicb->pcicb_bus;
-}
-
-/*========================================================
-**
-** pci_attach()
-**
-** Attach one device
-**
-**========================================================
-*/
-
-static void pci_attach (int bus, int dev, int func,
- struct pci_device *dvp, const char *name)
-{
- u_long data;
- int unit;
- u_char reg;
- u_char pciint;
- int irq;
-#if defined(APIC_IO)
- u_char airq = 0xff;
- u_char rirq = 0xff;
-#endif /* APIC_IO */
- pcici_t tag = pcibus->pb_tag (bus, dev, func);
-
- /*
- ** Get and increment the unit.
- */
-
- unit = (*dvp->pd_count)++;
-
- /*
- ** Announce this device
- */
-
- printf ("%s%d <%s> rev %d", dvp->pd_name, unit, name,
- (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff);
-
- /*
- ** Get the int pin number (pci interrupt number a-d)
- ** from the pci configuration space.
- */
-
- data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
-
- if (pciint) {
-
- printf (" int %c irq ", 0x60+pciint);
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(data);
-
- /*
- ** If it's zero, the isa irq number is unknown,
- ** and we cannot bind the pci interrupt.
- */
-
-#if defined(APIC_IO)
- if (irq && (irq != 0xff)) {
- airq = get_pci_apic_irq (bus, dev, pciint);
- if (airq != 0xff) { /* APIC IRQ exists */
- rirq = irq; /* 're-directed' IRQ */
- irq = airq; /* use APIC IRQ */
- }
- printf ("%d", irq);
- }
-#else
- if (irq && (irq != 0xff))
- printf ("%d", irq);
-#endif /* APIC_IO */
- else
- printf ("??");
+pci_maptype(unsigned mapreg)
+{
+ static u_int8_t maptype[0x10] = {
+ PCI_MAPMEM, PCI_MAPPORT,
+ PCI_MAPMEM, 0,
+ PCI_MAPMEM, PCI_MAPPORT,
+ 0, 0,
+ PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT,
+ PCI_MAPMEM|PCI_MAPMEMP, 0,
+ PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT,
+ 0, 0,
};
- printf (" on pci%d:%d:%d\n", bus, dev, func);
-
-#if defined(APIC_IO)
- if (airq != 0xff) { /* APIC IRQ exists */
- data = PCI_INTERRUPT_LINE_INSERT(data, airq);
- pci_conf_write (tag, PCI_INTERRUPT_REG, data);
- undirect_pci_irq (rirq); /* free for ISA card */
- }
-#endif /* APIC_IO */
-
- /*
- ** Read the current mapping,
- ** and update the pcicb fields.
- */
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
- data &= (PCI_CLASS_MASK|PCI_SUBCLASS_MASK);
- switch (data) {
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
- break;
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_CARDBUS: {
- u_int map, addr, size;
- map = pci_conf_read(tag, PCI_CARDBUS_SOCKET_REG);
- pci_conf_write (tag, PCI_CARDBUS_SOCKET_REG, 0xffffffff);
- size = pci_conf_read(tag, PCI_CARDBUS_SOCKET_REG);
- size = (~size) + 1;
- addr = pci_memalloc (pcicb, map, size);
- pci_conf_write (tag, PCI_CARDBUS_SOCKET_REG, addr);
- pcicb->pcicb_mamount += size;
- break;
- }
- default:
- for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4) {
- u_int map, addr, size;
-
-
- map = pci_conf_read (tag, reg);
- if (!(map & PCI_MAP_MEMORY_ADDRESS_MASK))
- continue;
-
- pci_conf_write (tag, reg, 0xffffffff);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, map);
-
- switch (data & 7) {
-
- default:
- continue;
- case 1:
- case 5:
- addr = map & PCI_MAP_IO_ADDRESS_MASK;
- size = -(data & PCI_MAP_IO_ADDRESS_MASK);
- size &= ~(addr ^ -addr);
-
- pci_register_io (pcicb, addr, addr+size-1);
- pcicb->pcicb_pamount += size;
- break;
-
- case 0:
- case 2:
- case 4:
- size = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
- addr = map & PCI_MAP_MEMORY_ADDRESS_MASK;
- if (addr >= 0x100000) {
- pci_register_memory (pcicb, addr, addr+size-1);
- pcicb->pcicb_mamount += size;
- };
- break;
- }
- if (bootverbose)
- printf ("\tmapreg[%02x] type=%d addr=%08x size=%04x.\n",
- reg, map&7, addr, size);
- }
- }
-
- /*
- ** attach device
- ** may produce additional log messages,
- ** i.e. when installing subdevices.
- */
-
- (*dvp->pd_attach) (tag, unit);
-
- /*
- ** Special processing of certain classes
- */
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
-
- switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
- struct pcicb *this, **link;
- unsigned char primary, secondary, subordinate;
- u_int command;
-
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
-
- /*
- ** get current configuration of the bridge.
- */
- data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
- primary = PCI_PRIMARY_BUS_EXTRACT (data);
- secondary = PCI_SECONDARY_BUS_EXTRACT(data);
- subordinate = PCI_SUBORDINATE_BUS_EXTRACT(data);
-#ifndef PCI_QUIET
- if (bootverbose) {
- printf ("\tbridge from pci%d to pci%d through %d.\n",
- primary, secondary, subordinate);
- printf ("\tmapping regs: io:%08lx mem:%08lx pmem:%08lx\n",
- pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG));
- }
-#endif
- /*
- ** check for uninitialized bridge.
- */
- if (!(primary < secondary
- && secondary <= subordinate
- && bus == primary)) {
-
- printf ("\tINCORRECTLY or NEVER CONFIGURED.\n");
- /*
- ** disable this bridge
- */
- pci_conf_write (tag, PCI_COMMAND_STATUS_REG, 0xffff0000);
- secondary = 0;
- subordinate = 0;
- };
-
- /*
- ** allocate bus descriptor for bus behind the bridge
- */
- link = &pcicb->pcicb_down;
- while (*link && (*link)->pcicb_bus < secondary)
- link = &(*link)->pcicb_next;
-
- this = malloc (sizeof (*this), M_DEVBUF, M_WAITOK);
-
- /*
- ** Initialize this descriptor so far.
- ** (the initialization is completed just before
- ** scanning the bus behind the bridge.
- */
- bzero (this, sizeof(*this));
- this->pcicb_next = *link;
- this->pcicb_up = pcicb;
- this->pcicb_bridge = tag;
- this->pcicb_bus = secondary;
- this->pcicb_subordinate = subordinate;
-
- command = pci_conf_read(tag,PCI_COMMAND_STATUS_REG);
-
- if (command & PCI_COMMAND_IO_ENABLE){
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped io region.
- */
- unsigned reg;
-
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG);
- this->pcicb_iobase = PCI_PPB_IOBASE_EXTRACT (reg);
- this->pcicb_iolimit = PCI_PPB_IOLIMIT_EXTRACT(reg);
-
- /*
- ** Note the used io space.
- */
- pci_register_io (pcicb, this->pcicb_iobase,
- this->pcicb_iolimit);
-
- };
-
- if (command & PCI_COMMAND_MEM_ENABLE) {
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped memory regions.
- */
- unsigned reg;
-
- /*
- ** non prefetchable memory
- */
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG);
- this->pcicb_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_membase,
- this->pcicb_memlimit);
-
- /*
- ** prefetchable memory
- */
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG);
- this->pcicb_p_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_p_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_p_membase,
- this->pcicb_p_memlimit);
- }
-
- /*
- ** Link it in chain.
- */
- *link=this;
-
- /*
- ** Update mapping info of parent bus.
- */
- if (!pcicb->pcicb_bfrom||secondary< pcicb->pcicb_bfrom)
- pcicb->pcicb_bfrom = secondary;
- if (subordinate > pcicb->pcicb_bupto)
- pcicb->pcicb_bupto = subordinate;
- }
+ return maptype[mapreg & 0x0f];
}
-/*========================================================
-**
-** pci_bus_config()
-**
-** Autoconfiguration of one pci bus.
-**
-**========================================================
-*/
+/* return log2 of map size decoded for memory or port map */
static int
-pci_mfdev (int bus, int device)
+pci_mapsize(unsigned testval)
{
- pcici_t tag0,tag1;
- unsigned pci_id0, pci_id1;
-
- /*
- ** Detect a multi-function device that complies to the PCI 2.0 spec
- */
- tag0 = pcibus->pb_tag (bus, device, 0);
- if (pci_conf_read (tag0, PCI_HEADER_MISC) & PCI_HEADER_MULTIFUNCTION)
- return 1;
-
- /*
- ** Well, as always: Theory and implementation of PCI ...
- **
- ** If there is a valid device ID returned for function 1 AND
- ** the device ID of function 0 and 1 is different OR
- ** the first mapping register of 0 and 1 differs,
- ** then assume a multi-function device anyway ...
- **
- ** Example of such a broken device: ISA and IDE chip i83371FB (Triton)
- */
- tag1 = pcibus->pb_tag (bus, device, 1);
- pci_id1 = pci_conf_read (tag1, PCI_ID_REG);
-
- if (pci_id1 != 0xffffffff) {
-
- pci_id0 = pci_conf_read (tag0, PCI_ID_REG);
-
- if (pci_id0 != pci_id1)
- return 1;
-
- if (pci_conf_read (tag0, PCI_MAP_REG_START)
- != pci_conf_read (tag1, PCI_MAP_REG_START))
- return 1;
- }
- return 0;
-}
+ int ln2size;
-static void
-pci_bus_config (void)
-{
- int bus_no;
- u_char device;
- u_char reg;
- pcici_t tag, mtag;
- pcidi_t type;
-
- struct pci_device *dvp;
-
- /*
- ** first initialize the bridge (bus controller chip)
- */
- bus_no = pci_bridge_config ();
-
- printf ("Probing for devices on PCI bus %d:\n", bus_no);
-#ifndef PCI_QUIET
- if (bootverbose && !pci_info_done) {
- pci_info_done=1;
- printf ("\tconfiguration mode %d allows %d devices.\n",
- pci_mechanism, pci_maxdevice);
- };
-#endif
- for (device=0; device<pci_maxdevice; device ++) {
- char *name = NULL;
- struct pci_device **dvpp;
- int func, maxfunc = 0;
-
- for (func=0; func <= maxfunc; func++) {
- tag = pcibus->pb_tag (bus_no, device, func);
- type = pci_conf_read (tag, PCI_ID_REG);
-
- if ((!type) || (type==0xfffffffful)) continue;
-
- /*
- ** lookup device in ioconfiguration:
- */
-
- dvpp = (struct pci_device **)pcidevice_set.ls_items;
-
- while (dvp = *dvpp++) {
- if (dvp->pd_probe) {
- if (name=(*dvp->pd_probe)(tag, type))
- break;
- }
- };
- /*
- ** check for mirrored devices.
- */
- if (func != 0) {
- goto real_device;
- }
- if (device & 0x10) {
- mtag=pcibus->pb_tag (bus_no,
- (u_char)(device & ~0x10), 0);
- } else if (device & 0x08) {
- mtag=pcibus->pb_tag (bus_no,
- (u_char)(device & ~0x08), 0);
- } else goto real_device;
-
- if (type!=pci_conf_read (mtag, PCI_ID_REG))
- goto real_device;
-
- for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4)
- if (pci_conf_read(tag,reg)!=pci_conf_read(mtag,reg))
- goto real_device;
-
-#ifndef PCI_QUIET
- if (dvp==NULL) continue;
- if (bootverbose)
- printf ("%s? <%s> mirrored on pci%d:%d\n",
- dvp->pd_name, name, bus_no, device);
-#endif
- continue;
-
- real_device:
-
-#ifndef PCI_QUIET
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose) {
- printf ("\tconfig header: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- pci_conf_read (tag, 0),
- pci_conf_read (tag, 4),
- pci_conf_read (tag, 8),
- pci_conf_read (tag, 12));
- }
-#endif
-#endif
-
- if (func == 0 && pci_mfdev (bus_no, device)) {
- maxfunc = 7;
- }
-
- pci_remember(bus_no, device, func, dvp);
-
- if (dvp==NULL) {
-#ifndef PCI_QUIET
- if (pci_conf_count)
- continue;
-
- if (maxfunc == 0)
- printf("%s%d:%d: ",
- pcibus->pb_name, bus_no, device);
- else
- printf("%s%d:%d:%d: ",
- pcibus->pb_name, bus_no, device, func);
- not_supported (tag, type);
-#endif
- continue;
- };
-
- if (*name) {
- pci_attach (bus_no, device, func, dvp, name);
- }
- }
- }
-
-#ifndef PCI_QUIET
- if (bootverbose) {
- if (pcicb->pcicb_mamount)
- printf ("%s%d: uses %ud bytes of memory from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_mamount,
- pcicb->pcicb_mfrom, pcicb->pcicb_mupto);
- if (pcicb->pcicb_pamount)
- printf ("%s%d: uses %ud bytes of I/O space from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_pamount,
- pcicb->pcicb_pfrom, pcicb->pcicb_pupto);
- if (pcicb->pcicb_bfrom)
- printf ("%s%d: subordinate busses from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_bfrom, pcicb->pcicb_bupto);
+ testval = pci_mapbase(testval);
+ ln2size = 32;
+ while ((testval & 0x80000000) != 0)
+ {
+ ln2size--;
+ testval <<= 1;
}
-#endif
+ return (ln2size);
}
-/*========================================================
-**
-** pci_configure ()
-**
-** Autoconfiguration of pci devices.
-**
-** Has to take care of mirrored devices, which are
-** entailed by incomplete decoding of pci address lines.
-**
-**========================================================
-*/
-
-void pci_configure()
-{
- struct pcibus **pbp = (struct pcibus**) pcibus_set.ls_items;
-
- /*
- ** check pci bus present
- */
+/* return log2 of address range supported by map register */
- while (!pci_maxdevice && (pcibus = *pbp++)) {
- (*pcibus->pb_setup)();
- }
-
- if (!pci_maxdevice) return;
-
- /*
- ** hello world ..
- */
-
- pciroots = 1;
- while (pciroots--) {
-
- pcicb = malloc (sizeof (struct pcicb), M_DEVBUF, M_WAITOK);
- if (pcicb == NULL) {
- return;
- }
- bzero (pcicb, sizeof (struct pcicb));
- pcicb->pcicb_bus = pcibusmax;
- pcicb->pcicb_iolimit = 0xffff;
- pcicb->pcicb_membase = 0x02000000;
- pcicb->pcicb_p_membase = 0x02000000;
- pcicb->pcicb_memlimit = 0xffffffff;
- pcicb->pcicb_p_memlimit = 0xffffffff;
-
- while (pcicb != NULL) {
- pci_bus_config ();
-
- if (pcibusmax < pcicb->pcicb_bus)
- (pcibusmax = pcicb->pcicb_bus);
-
- if (pcicb->pcicb_down) {
- pcicb = pcicb->pcicb_down;
- continue;
- };
-
- while (pcicb && !pcicb->pcicb_next)
- pcicb = pcicb->pcicb_up;
-
- if (pcicb)
- pcicb = pcicb->pcicb_next;
- }
- pcibusmax++;
+static int
+pci_maprange(unsigned mapreg)
+{
+ int ln2range = 0;
+ switch (mapreg & 0x07) {
+ case 0x00:
+ case 0x01:
+ case 0x05:
+ ln2range = 32;
+ break;
+ case 0x02:
+ ln2range = 20;
+ break;
+ case 0x04:
+ ln2range = 64;
+ break;
}
- pci_conf_count++;
+ return (ln2range);
}
-/*========================================================
-**
-** pci_rescan ()
-**
-** try to find lkm driver for device
-**
-** May be called more than once.
-** Any device is attached only once.
-**
-**========================================================
-*/
-
-static void pci_rescan()
+/* extract map parameters into newly allocated array of pcimap structures */
+
+static pcimap *
+pci_readmaps(pcicfgregs *cfg, int maxmaps)
{
int i;
- for (i = 0; i < pci_dev_list_count; i++)
- {
- struct pci_lkm *lkm;
- pcici_t tag;
- struct pci_device *dvp;
- pcidi_t type = pci_dev_list[i].pc_devid;
- char *name = NULL;
- int bus, dev, func;
-
- if (pci_dev_list[i].pc_dvp)
- continue;
-
- bus = pci_dev_list[i].pc_sel.pc_bus;
- dev = pci_dev_list[i].pc_sel.pc_dev;
- func = pci_dev_list[i].pc_sel.pc_func;
-
- tag = pcibus->pb_tag (bus, dev, func);
-
- for (lkm = pci_lkm_head; lkm; lkm = lkm->next) {
- dvp = lkm->dvp;
- if (name=(*dvp->pd_probe)(tag, type))
- break;
- }
- if (name && *name) {
- pcicb = pci_dev_list[i].pc_cb;
- pci_attach (bus, dev, func, dvp, name);
- pci_dev_list[i].pc_dvp = dvp;
+ pcimap *map;
+ int map64 = 0;
+
+ while (maxmaps > 0
+ && pci_cfgread(cfg, PCIR_MAPS + (maxmaps -1) *4, 4) == 0)
+ maxmaps--;
+
+ map = malloc(maxmaps * sizeof (pcimap), M_DEVBUF, M_WAITOK);
+ if (map != NULL) {
+ bzero(map, sizeof(pcimap) * maxmaps);
+
+ for (i = 0; i < maxmaps; i++) {
+ int reg = PCIR_MAPS + i*4;
+ u_int32_t base;
+ u_int32_t testval;
+
+ base = pci_cfgread(cfg, reg, 4);
+
+ if (map64 == 0) {
+ pci_cfgwrite(cfg, reg, 0xffffffff, 4);
+ testval = pci_cfgread(cfg, reg, 4);
+ pci_cfgwrite(cfg, reg, base, 4);
+
+ map[i].base = pci_mapbase(base);
+ map[i].type = pci_maptype(base);
+ map[i].ln2size = pci_mapsize(testval);
+ map[i].ln2range = pci_maprange(testval);
+ map64 = map[i].ln2range == 64;
+ } else {
+ /* only fill in base, other fields are 0 */
+ map[i].base = base;
+ map64 = 0;
+ }
+ if (map[i].type == 0) {
+ /*
+ * This indicates, that some config space register
+ * was mistaken to contain a map, while it in fact
+ * contains unrelated information!
+ * Ignore this map and all that might have been
+ * expected to follow ...
+ */
+ maxmaps = i;
+ }
}
+ cfg->nummaps = maxmaps;
}
+ return (map);
}
-/*========================================================
-**
-** pci_register_lkm ()
-**
-** Add LKM PCI driver's struct pci_device to pci_lkm chain
-**
-**========================================================
-*/
+/* adjust some values from PCI 1.0 devices to match 2.0 standards ... */
-int pci_register_lkm (struct pci_device *dvp, int if_revision)
+static void
+pci_fixancient(pcicfgregs *cfg)
{
- struct pci_lkm *lkm;
-
- if (if_revision != 0) {
- return -1;
- }
-
- if (!dvp || !dvp->pd_probe || !dvp->pd_attach) {
- return -1;
- }
-
- lkm = malloc (sizeof (*lkm), M_DEVBUF, M_WAITOK);
- if (!lkm) {
- return -1;
- }
+ if (cfg->hdrtype != 0)
+ return;
- lkm->dvp = dvp;
- lkm->next = pci_lkm_head;
- pci_lkm_head = lkm;
- pci_rescan();
- return 0;
+ /* PCI to PCI bridges use header type 1 */
+ if (cfg->class == PCIC_BRIDGE && cfg->subclass == PCIS_BRIDGE_PCI)
+ cfg->hdrtype = 1;
}
-/*-----------------------------------------------------------------------
-**
-** Map device into port space.
-**
-** Actually the device should have been mapped by the bios.
-** This function only reads and verifies the value.
-**
-** PCI-Specification: 6.2.5.1: address maps
-**
-**-----------------------------------------------------------------------
-*/
-
-int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
+/* read config data specific to header type 1 device (PCI to PCI bridge) */
+
+static void *
+pci_readppb(pcicfgregs *cfg)
{
- unsigned data, ioaddr, iosize;
- struct pcicb *link = pcicb;
+ pcih1cfgregs *p;
- /*
- ** sanity check
- */
+ p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK);
+ if (p == NULL)
+ return (NULL);
- if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
- printf ("pci_map_port failed: bad register=0x%x\n",
- (unsigned)reg);
- return (0);
- };
+ bzero(p, sizeof *p);
- /*
- ** get size and type of port
- **
- ** type is in the lowest two bits.
- ** If device requires 2^n bytes, the next
- ** n-2 bits are hardwired as 0.
- */
-
- ioaddr = pci_conf_read (tag, reg) & PCI_MAP_IO_ADDRESS_MASK;
- if (!ioaddr) {
- printf ("pci_map_port failed: not configured by bios.\n");
- return (0);
- };
+ p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
+ p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
- pci_conf_write (tag, reg, 0xfffffffful);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, ioaddr);
+ p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
- if ((data & 0x03) != PCI_MAP_IO) {
- printf ("pci_map_port failed: bad port type=0x%x\n",
- (unsigned) data);
- return (0);
- };
- iosize = -(data & PCI_MAP_IO_ADDRESS_MASK);
- iosize &= ~(ioaddr ^ -ioaddr);
- if (ioaddr < pcicb->pcicb_iobase
- || ioaddr + iosize -1 > pcicb->pcicb_iolimit) {
- printf ("pci_map_port failed: device's iorange 0x%x-0x%x "
- "is incompatible with its bridge's range 0x%x-0x%x\n",
- (unsigned) ioaddr, (unsigned) ioaddr + iosize - 1,
- (unsigned) pcicb->pcicb_iobase,
- (unsigned) pcicb->pcicb_iolimit);
- return (0);
- }
+ 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));
-#ifndef PCI_QUIET
- if (bootverbose)
- printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
- (unsigned) reg, (unsigned) ioaddr, (unsigned) iosize);
-#endif
- /*
- ** set the configuration register of and
- ** return the address to the driver.
- ** Make sure to enable each upstream bridge
- ** so I/O and DMA can go all the way.
- */
-
- for (;;) {
- data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff;
- data |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE;
- (void) pci_conf_write(tag, PCI_COMMAND_STATUS_REG, data);
- if ((link = link->pcicb_up) == NULL)
- break;
- tag = link->pcicb_bridge;
- }
+ p->membase = PCI_PPBMEMBASE (0,
+ pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
+ p->memlimit = PCI_PPBMEMLIMIT (0,
+ pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
- *pa = ioaddr;
+ p->pmembase = PCI_PPBMEMBASE (
+ (pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
+ pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
- return (1);
+ p->pmemlimit = PCI_PPBMEMLIMIT (
+ (pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
+ pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
+ return (p);
}
-/*-----------------------------------------------------------------------
-**
-** Map device into virtual and physical space
-**
-** Actually the device should have been mapped by the bios.
-** This function only reads and verifies the value.
-**
-** PCI-Specification: 6.2.5.1: address maps
-**
-**-----------------------------------------------------------------------
-*/
-
-int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
-{
- struct pcicb *link = pcicb;
- unsigned data ,paddr;
- vm_size_t psize, poffs;
- vm_offset_t vaddr;
-
- /*
- ** sanity check
- */
-
- if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
- printf ("pci_map_mem failed: bad register=0x%x\n",
- (unsigned)reg);
- return (0);
- };
-
- /*
- ** save old mapping, get size and type of memory
- **
- ** type is in the lowest four bits.
- ** If device requires 2^n bytes, the next
- ** n-4 bits are read as 0.
- */
-
- paddr = pci_conf_read (tag, reg) & PCI_MAP_MEMORY_ADDRESS_MASK;
- pci_conf_write (tag, reg, 0xfffffffful);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, paddr);
-
- /*
- ** check the type
- */
-
- if (!((data & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M
- && (paddr & ~0xfffff) == 0)
- && (data & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT){
- printf ("pci_map_mem failed: bad memory type=0x%x\n",
- (unsigned) data);
- return (0);
- };
-
- /*
- ** get the size.
- */
-
- psize = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
-
- if (!paddr || paddr == PCI_MAP_MEMORY_ADDRESS_MASK) {
- paddr = pci_memalloc (pcicb, 0, psize);
- if (!paddr) {
- printf ("pci_map_mem: not configured by bios.\n");
- return (0);
- };
- pci_register_memory (pcicb, paddr, paddr+psize-1);
- };
+/* read config data specific to header type 2 device (PCI to CardBus bridge) */
- if (paddr < pcicb->pcicb_membase ||
- paddr + psize - 1 > pcicb->pcicb_memlimit) {
- printf ("pci_map_mem failed: device's memrange 0x%x-0x%x is "
- "incompatible with its bridge's memrange 0x%x-0x%x\n",
- (unsigned) paddr,
- (unsigned) (paddr + psize - 1),
- (unsigned) pcicb->pcicb_membase,
- (unsigned) pcicb->pcicb_memlimit);
-/* return (0);*/
-/* ACHTUNG: Ist der Code richtig, wenn eine PCI-PCI-Bridge fuer
- * die PCI-Slots verwendet wird, aber die Onboard-Devices direkt
- * an der CPU-PCI-Bridge haengen (Siehe Compaq Prolinea Problem) ???
- */
- }
- pci_conf_write (tag, reg, paddr);
-
- /*
- ** Truncate paddr to page boundary.
- ** (Or does pmap_mapdev the job?)
- */
+static void *
+pci_readpcb(pcicfgregs *cfg)
+{
+ pcih2cfgregs *p;
- poffs = paddr - trunc_page (paddr);
- vaddr = (vm_offset_t) pmap_mapdev (paddr-poffs, psize+poffs);
+ p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK);
+ if (p == NULL)
+ return (NULL);
- if (!vaddr) return (0);
+ bzero(p, sizeof *p);
- vaddr += poffs;
+ p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
+ p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
+
+ p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
-#ifndef PCI_QUIET
- /*
- ** display values.
- */
+ 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);
- if (bootverbose)
- printf ("\treg%d: virtual=0x%lx physical=0x%lx size=0x%lx\n",
- (unsigned) reg, (u_long)vaddr, (u_long)paddr, (u_long)psize);
-#endif
- /*
- ** set the configuration register and
- ** return the address to the driver
- ** Make sure to enable each upstream bridge
- ** so memory and DMA can go all the way.
- */
-
- for (;;) {
- data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff;
- data |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
- (void) pci_conf_write(tag, PCI_COMMAND_STATUS_REG, data);
- if ((link = link->pcicb_up) == NULL)
- break;
- tag = link->pcicb_bridge;
- }
+ 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);
- *va = vaddr;
- *pa = paddr;
-
- return (1);
+ p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
+ return p;
}
-/*-----------------------------------------------------------------------
-**
-** Pci meta interrupt handler
-**
-** This handler assumes level triggered interrupts.
-** It's possible to build a kernel which handles shared
-** edge triggered interrupts by the options "PCI_EDGE_INT".
-** But there is a performance penalty.
-**
-** (Of course you can delete the #ifdef PCI_EDGE_INT bracketed
-** code at all :-) :-) :-)
-**
-**-----------------------------------------------------------------------
-*/
-
-static struct pci_int_desc*
- pci_int_desc [PCI_MAX_IRQ];
-
-#ifndef NO_SHARED_IRQ
-
-static inline unsigned
-splq (unsigned mask)
-{
- unsigned temp=cpl;
- cpl |= mask;
- return temp;
-}
+/* extract header type specific config data */
static void
-pci_int (int irq)
+pci_hdrtypedata(pcicfgregs *cfg)
{
- struct pci_int_desc * p;
- int s;
-
- if (irq<0 || irq >= PCI_MAX_IRQ) {
- printf ("pci_int: irq %d out of range, ignored\n", irq);
- return;
- };
- for (p = pci_int_desc[irq]; p!=NULL; p=p->pcid_next) {
- s = splq (*p->pcid_maskptr);
- (*p->pcid_handler) (p->pcid_argument);
- p-> pcid_tally++;
- splx (s);
-#if 0
- if (p->pcid_tally<20)
- printf ("PCI_INT: irq=%d h=%p cpl o=%x n=%x val=%d\n",
- irq, p->pcid_handler, s, cpl, c);
-#endif
- };
-}
-#endif
-
-/*-----------------------------------------------------------------------
-**
-** Auxiliary function for interrupt (un)mapping.
-**
-**-----------------------------------------------------------------------
-*/
-
-static u_int
-getirq (pcici_t tag)
-{
- u_int irq;
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(
- pci_conf_read (tag, PCI_INTERRUPT_REG));
-
- if (irq == 0 || irq == 0xff) {
- printf ("\tint line register not set by bios\n");
- return (0xff);
+ switch (cfg->hdrtype) {
+ case 0:
+ cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
+ cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
+ cfg->map = pci_readmaps(cfg, 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->map = pci_readmaps(cfg, PCI_MAXMAPS_1);
+ cfg->hdrspec = pci_readppb(cfg);
+ 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->map = pci_readmaps(cfg, PCI_MAXMAPS_2);
+ cfg->hdrspec = pci_readpcb(cfg);
+ break;
}
+}
- if (irq >= PCI_MAX_IRQ) {
- printf ("\tirq %d out of bounds (must be < %d).\n",
- irq, PCI_MAX_IRQ);
- return (0xff);
+/* read configuration header into pcicfgrect structure */
+
+static pcicfgregs *
+pci_readcfg(pcicfgregs *probe)
+{
+ pcicfgregs *cfg = NULL;
+
+ if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
+ cfg = malloc(sizeof (pcicfgregs), M_DEVBUF, M_WAITOK);
+ if (cfg == NULL)
+ return (cfg);
+
+ bzero(cfg, sizeof *cfg);
+
+ cfg->bus = probe->bus;
+ cfg->slot = probe->slot;
+ cfg->func = probe->func;
+ cfg->parent = probe->parent;
+
+ 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->class = 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->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
+ cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
+
+ cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
+ cfg->hdrtype &= ~PCIM_MFDEV;
+
+ pci_fixancient(cfg);
+ pci_hdrtypedata(cfg);
}
-
- return (irq);
+ return (cfg);
}
-static struct pci_int_desc **
-getintdescbytag (u_int irq, pcici_t tag)
-{
- struct pci_int_desc *p, **pp;
-
- pp=&pci_int_desc[irq];
- while (((p=*pp)) && !sametag(p->pcid_tag,tag))
- pp=&p->pcid_next;
-
- if (!p) return (NULL);
+/* free pcicfgregs structure and all depending data structures */
- return (pp);
-}
-
-static struct pci_int_desc *
-getintdescbymptr (u_int irq, unsigned * mptr)
+static int
+pci_freecfg(pcicfgregs *cfg)
{
- struct pci_int_desc *p;
-
- for (p=pci_int_desc[irq];p;p=p->pcid_next)
- if (p->pcid_maskptr == mptr) break;
- return (p);
+ if (cfg->hdrspec != NULL)
+ free(cfg->hdrspec, M_DEVBUF);
+ if (cfg->map != NULL)
+ free(cfg->map, M_DEVBUF);
+ free(cfg, M_DEVBUF);
+ return (0);
}
-/*-----------------------------------------------------------------------
-**
-** Map pci interrupt.
-**
-**-----------------------------------------------------------------------
-*/
-
-static unsigned pci_mask0 = 0;
-
-int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg, unsigned *maskptr)
+static void
+pci_addcfg(pcicfgregs *cfg)
{
- u_int irq;
- int result, oldspl;
- unsigned mask;
- struct pci_int_desc *tail, *mdp=NULL, *new=NULL;
-
- /*
- ** Get irq line from configuration space,
- ** and check for consistency.
- */
-
- irq = getirq (tag);
- if (irq == 0xff) {
- return (0);
- };
- mask= 1ul << irq;
-
- /*
- ** disable this interrupt.
- */
-
- oldspl = splq (mask);
-
- /*
- ** If handler for this tag already installed,
- ** remove it first.
- */
-
- if (getintdescbytag (irq, tag) != NULL)
- pci_unmap_int (tag);
-
- /*
- ** If this irq not yet included in the mask, include it.
- */
-
- mdp = getintdescbymptr (irq, maskptr);
- if (!mdp) {
- result = pcibus->pb_imaskinc (irq, maskptr);
- if (result)
- goto conflict;
- };
-
- /*
- ** Allocate descriptor and initialize it.
- */
-
- tail = pci_int_desc[irq];
-
- new = malloc (sizeof (*new), M_DEVBUF, M_WAITOK);
- bzero (new, sizeof (*new));
-
- new->pcid_next = tail;
- new->pcid_tag = tag;
- new->pcid_handler = func;
- new->pcid_argument = arg;
- new->pcid_maskptr = maskptr;
- new->pcid_tally = 0;
- new->pcid_mask = mask;
-
- /*
- ** If first handler: install it.
- ** If second handler: install shared-int-handler.
- */
-
- if (!tail) {
- /*
- ** first handler for this irq.
- */
-
- result = pcibus->pb_iattach
- /*
- * XXX if we get here, then `func' must be pci_int
- * so the bogus casts are almost OK since they just
- * undo the bogus casts that were needed to pass
- * pci_int and its arg to pci_map_int().
- */
- (irq, (inthand2_t *) func, (int) arg, maskptr);
- if (result) goto conflict;
-
-#ifdef NO_SHARED_IRQ
- } else goto conflict;
-#else
- } else if (!tail->pcid_next) {
- /*
- ** Second handler for this irq.
- */
-
- if (bootverbose)
- printf ("\tusing shared irq %d.\n", irq);
-
- /*
- ** replace old handler by shared-int-handler.
- */
-
- result = pcibus->pb_idetach (irq,
- (inthand2_t *) tail->pcid_handler);
- if (result)
- printf ("\tCANNOT DETACH INT HANDLER.\n");
-
- result = pcibus->pb_iattach (irq, pci_int, irq, &pci_mask0);
- if (result) {
- printf ("\tCANNOT ATTACH SHARED INT HANDLER.\n");
- goto fail;
- };
+#ifdef PCI_DEBUG
+ if (bootverbose) {
+ int i;
+ printf("new pci: vendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
+ cfg->vendor, cfg->device, cfg->revid);
+ printf("\t cmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
+ cfg->cmdreg, cfg->statreg, cfg->cachelnsz);
+ printf("\t class=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
+ cfg->class, cfg->subclass, cfg->progif, cfg->hdrtype, cfg->mfdev);
+ printf("\t lattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n",
+ cfg->lattimer, cfg->lattimer * 30,
+ cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250);
+
+ if (cfg->intpin > 0)
+ printf("\t intpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
+
+ for (i = 0; i < cfg->nummaps; i++) {
+ pcimap *m = &cfg->map[i];
+ printf("\t map[%d]: type %x, range %2d, base %08x, size %2d\n",
+ i, m->type, m->ln2range, m->base, m->ln2size);
+ }
}
-#endif
- /*
- ** Link new descriptor, reenable ints and done.
- */
-
- pci_int_desc[irq] = new;
- splx (oldspl);
- return (1);
-
- /*
- ** Handle some problems.
- */
-
-conflict:
- printf ("\tirq %d already in use.\n", irq);
-fail:
- /*
- ** If descriptor allocated, free it.
- ** If included in mask, remove it.
- */
-
- if (new) free(new, M_DEVBUF);
- if (!mdp) (void) pcibus->pb_imaskexc (irq, maskptr);
- splx (oldspl);
- return (0);
+#endif /* PCI_DEBUG */
+ pci_drvattach(cfg); /* XXX currently defined in pci_compat.c */
}
-/*-----------------------------------------------------------------------
-**
-** Unmap pci interrupt.
-**
-**-----------------------------------------------------------------------
-*/
+/* return pointer to device that is a bridge to this bus */
-int pci_unmap_int (pcici_t tag)
+static pcicfgregs *
+pci_bridgeto(int bus)
{
- int result, oldspl;
- struct pci_int_desc *this, **hook, *tail;
- unsigned irq;
-
- /*
- ** Get irq line from configuration space,
- ** and check for consistency.
- */
-
- irq = getirq (tag);
- if (irq == 0xff) {
- return (0);
- };
-
- /*
- ** Search and unlink interrupt descriptor.
- */
-
- hook = getintdescbytag (irq, tag);
- if (hook == NULL) {
- printf ("\tno irq %d handler for pci %x\n",
- irq, tag.tag);
- return (0);
- };
-
- this = *hook;
- *hook= this->pcid_next;
-
- /*
- ** Message
- */
-
- printf ("\tirq %d handler %p(%p) unmapped for pci %x after %d ints.\n",
- irq, this->pcid_handler, this->pcid_argument,
- this->pcid_tag.tag, this->pcid_tally);
-
- /*
- ** If this irq no longer included in the mask, remove it.
- */
-
- if (!getintdescbymptr (irq, this->pcid_maskptr))
- (void) pcibus->pb_imaskexc (irq, this->pcid_maskptr);
-
- tail = pci_int_desc[irq];
-
- if (tail == NULL) {
-
- /*
- ** Remove the old handler.
- */
-
- result = pcibus->pb_idetach (irq,
- (inthand2_t *) this->pcid_handler);
- if (result)
- printf ("\tirq %d: cannot remove handler.\n", irq);
-
- } else if (tail->pcid_next == NULL) {
-
- /*
- ** Remove the shared int handler.
- ** Install the last remaining handler.
- */
-
- oldspl = splq (1ul << irq);
-
- result = pcibus->pb_idetach (irq, pci_int);
- if (result)
- printf ("\tirq %d: cannot remove handler.\n", irq);
-
- result = pcibus->pb_iattach (irq,
- (inthand2_t *) tail->pcid_handler,
- (int) tail->pcid_argument,
- tail->pcid_maskptr);
-
- if (result)
- printf ("\tirq %d: cannot install handler.\n", irq);
-
- splx (oldspl);
- };
-
- free (this, M_DEVBUF);
- return (1);
+ return (NULL); /* XXX not yet implemented */
}
-/*-----------------------------------------------------------
-**
-** Display of unknown devices.
-**
-**-----------------------------------------------------------
-*/
-struct vt {
- u_short ident;
- char* name;
-};
-
-static struct vt VendorTable[] = {
- {0x0e11, "Compaq"},
- {0x1000, "NCR/Symbios"},
- {0x1002, "ATI Technologies Inc."},
- {0x1004, "VLSI"},
- {0x100B, "National Semiconductor"},
- {0x100E, "Weitek"},
- {0x1011, "Digital Equipment Corporation"},
- {0x1013, "Cirrus Logic"},
- {0x101A, "NCR"},
- {0x1022, "AMD"},
- {0x102B, "Matrox"},
- {0x102C, "Chips & Technologies"},
- {0x1039, "Silicon Integrated Systems"},
- {0x1042, "SMC"},
- {0x1044, "DPT"},
- {0x1045, "OPTI"},
- {0x104B, "Bus Logic"},
- {0x104C, "TI"},
- {0x1060, "UMC"},
- {0x1080, "Contaq"},
- {0x1095, "CMD"},
- {0x10b9, "ACER Labs"},
- {0x10c8, "NeoMagic"},
- {0x1106, "VIA Technologies"},
- {0x5333, "S3 Inc."},
- {0x8086, "Intel Corporation"},
- {0x9004, "Adaptec"},
- {0,0}
-};
-
-typedef struct {
- const int subclass;
- const char *name;
-} subclass_name;
-
-/* 0x00 prehistoric subclasses */
-static const subclass_name old_subclasses[] =
-{
- { 0x00, "misc" },
- { 0x01, "vga" },
- { 0x00, NULL }
-};
-
-/* 0x01 mass storage subclasses */
-static const subclass_name storage_subclasses[] =
-{
- { 0x00, "scsi" },
- { 0x01, "ide" },
- { 0x02, "floppy"},
- { 0x03, "ipi" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x02 network subclasses */
-static const subclass_name network_subclasses[] =
-{
- { 0x00, "ethernet" },
- { 0x01, "tokenring" },
- { 0x02, "fddi" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x03 display subclasses */
-static const subclass_name display_subclasses[] =
-{
- { 0x00, "vga" },
- { 0x01, "xga" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x04 multimedia subclasses */
-static const subclass_name multimedia_subclasses[] =
-{
- { 0x00, "video" },
- { 0x01, "audio" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x05 memory subclasses */
-static const subclass_name memory_subclasses[] =
-{
- { 0x00, "ram" },
- { 0x01, "flash" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x06 bridge subclasses */
-static const subclass_name bridge_subclasses[] =
-{
- { 0x00, "host" },
- { 0x01, "isa" },
- { 0x02, "eisa" },
- { 0x03, "mc" },
- { 0x04, "pci" },
- { 0x05, "pcmcia"},
- { 0x07, "cardbus"},
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-static const subclass_name *const subclasses[] = {
- old_subclasses,
- storage_subclasses,
- network_subclasses,
- display_subclasses,
- multimedia_subclasses,
- memory_subclasses,
- bridge_subclasses,
-};
-
-static const char *const majclasses[] = {
- "old",
- "storage",
- "network",
- "display",
- "multimedia",
- "memory",
- "bridge",
- "comms",
- "system",
- "input",
- "docking",
- "processor",
- "serial"
-};
-
-
-void not_supported (pcici_t tag, u_long type)
-{
- u_long reg;
- u_long data;
- u_char class;
- u_char subclass;
- struct vt * vp;
- int pciint;
- int irq;
-
- /*
- ** lookup the names.
- */
-
- for (vp=VendorTable; vp->ident; vp++)
- if (vp->ident == (type & 0xffff))
- break;
+/* scan one PCI bus for devices */
- /*
- ** and display them.
- */
-
- if (vp->ident) printf (vp->name);
- else printf ("vendor=0x%04lx", type & 0xffff);
-
- printf (", device=0x%04lx", type >> 16);
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
- class = (data >> 24) & 0xff;
- subclass = (data >> 16) & 0xff;
-
- if (class < sizeof(majclasses) / sizeof(majclasses[0])) {
- printf(", class=%s", majclasses[class]);
- } else {
- printf(", class=0x%02x", class);
- }
-
- if (class < sizeof(subclasses) / sizeof(subclasses[0])) {
- const subclass_name *p = subclasses[class];
- while (p->name && (p->subclass != subclass))
- p++;
- if (p->name) {
- printf(" (%s)", p->name);
- } else {
- printf(" (unknown subclass 0x%02lx)", subclass);
+static int
+pci_probebus(int bus)
+{
+ pcicfgregs probe;
+ int bushigh = bus;
+
+ bzero(&probe, sizeof probe);
+ probe.parent = pci_bridgeto(bus);
+ probe.bus = bus;
+ for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
+ int pcifunchigh = 0;
+ for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
+ pcicfgregs *cfg = pci_readcfg(&probe);
+ if (cfg != NULL) {
+ if (cfg->mfdev)
+ pcifunchigh = 7;
+
+ if (bushigh < cfg->subordinatebus)
+ bushigh = cfg->subordinatebus;
+
+ pci_addcfg(cfg);
+ cfg = NULL; /* we don't own this anymore ... */
+ }
}
- } else {
- printf(", subclass=0x%02x", subclass);
}
+ return (bushigh);
+}
- data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
-
- if (pciint) {
-
- printf (" int %c irq ", 0x60+pciint);
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(data);
-
- /*
- ** If it's zero, the isa irq number is unknown,
- ** and we cannot bind the pci interrupt.
- */
+/* scan a PCI bus tree reached through one PCI attachment point */
- if (irq && (irq != 0xff))
- printf ("%d", irq);
- else
- printf ("??");
- };
+int
+pci_probe(pciattach *parent)
+{
+ int bushigh;
+ int bus = 0;
- if (class != (PCI_CLASS_BRIDGE >> 24))
- printf (" [no driver assigned]");
- printf ("\n");
+ bushigh = pci_bushigh();
+ while (bus <= bushigh) {
+ int newbushigh;
- if (bootverbose) {
- if (class == (PCI_CLASS_BRIDGE >> 24)) {
- printf ("configuration space registers:");
- for (reg = 0; reg < 0x100; reg+=4) {
- if ((reg & 0x0f) == 0) printf ("\n%02x:\t", reg);
- printf ("%08x ", pci_conf_read (tag, reg));
- }
- printf ("\n");
- } else {
- for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
- data = pci_conf_read (tag, reg);
- if ((data&~7)==0) continue;
- switch (data&7) {
+ printf("Probing for devices on PCI bus %d:\n", bus);
+ newbushigh = pci_probebus(bus);
- case 1:
- case 5:
- printf ("\tmap(%x): io(%04lx)\n",
- reg, data & ~3);
- break;
- case 0:
- printf ("\tmap(%x): mem32(%08lx)\n",
- reg, data & ~7);
- break;
- case 2:
- printf ("\tmap(%x): mem20(%05lx)\n",
- reg, data & ~7);
- break;
- case 4:
- printf ("\tmap(%x): mem64(%08x%08lx)\n",
- reg, pci_conf_read (tag, reg +4), data & ~7);
- reg += 4;
- break;
- }
- }
- }
+ if (bushigh < newbushigh)
+ bushigh = newbushigh;
+ bus++;
}
+ return (bushigh);
}
/*
- * This is the user interface to the PCI configuration space.
+ * This is the user interface to PCI configuration space.
*/
-
-
-static void
-pci_remember(int bus, int dev, int func, struct pci_device *dvp)
-{
- struct pci_conf *p;
- pcici_t tag;
-
- if (++pci_dev_list_count > pci_dev_list_size) {
- struct pci_conf *new;
-
- pci_dev_list_size += 8;
- MALLOC(new, struct pci_conf *, pci_dev_list_size * sizeof *new,
- M_DEVL, M_NOWAIT);
- if (!new) {
- pci_dev_list_size -= 8;
- pci_dev_list_count--;
- return;
- }
-
- if (pci_dev_list) {
- bcopy(pci_dev_list, new, ((pci_dev_list_size - 8) *
- sizeof *new));
- FREE(pci_dev_list, M_DEVL);
- }
- pci_dev_list = new;
- }
-
- p = &pci_dev_list[pci_dev_list_count - 1];
- p->pc_sel.pc_bus = bus;
- p->pc_sel.pc_dev = dev;
- p->pc_sel.pc_func = func;
- p->pc_dvp = dvp;
- p->pc_cb = pcicb;
-
- tag = pcibus->pb_tag (bus, dev, func);
- p->pc_hdr = (pci_conf_read (tag, PCI_HEADER_MISC) >> 16) & 0xff;
- p->pc_devid = pci_conf_read(tag, PCI_ID_REG);
- p->pc_class = pci_conf_read(tag, PCI_CLASS_REG);
- switch (p->pc_hdr & 0x7f) {
- case 0:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG0);
- break;
- case 1:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG1);
- break;
- case 2:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG2);
- break;
- default:
- p->pc_subid = 0;
- }
-}
-
+
static int
pci_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
if ((oflags & FWRITE) && securelevel > 0) {
return EPERM;
}
-
return 0;
}
@@ -1904,79 +470,62 @@ pci_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
struct pci_io *io;
size_t iolen;
int error;
- pcici_t tag;
if (cmd != PCIOCGETCONF && !(flag & FWRITE))
return EPERM;
switch(cmd) {
case PCIOCGETCONF:
+#ifdef NOTYET
+static struct pci_conf *pci_dev_list;
+static unsigned pci_dev_list_count;
+static unsigned pci_dev_list_size;
+
cio = (struct pci_conf_io *)data;
iolen = min(cio->pci_len,
pci_dev_list_count * sizeof(struct pci_conf));
cio->pci_len = pci_dev_list_count * sizeof(struct pci_conf);
error = copyout(pci_dev_list, cio->pci_buf, iolen);
+#else
+ error = ENODEV;
+#endif
break;
case PCIOCREAD:
io = (struct pci_io *)data;
switch(io->pi_width) {
+ pcicfgregs probe;
case 4:
- tag = pcibus->pb_tag (io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func);
- io->pi_data = pci_conf_read(tag, io->pi_reg);
- error = 0;
- break;
case 2:
case 1:
- default:
- error = ENODEV;
- break;
- }
- break;
-
- case PCIOCWRITE:
- io = (struct pci_io *)data;
- switch(io->pi_width) {
- case 4:
- tag = pcibus->pb_tag (io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func);
- pci_conf_write(tag, io->pi_reg, io->pi_data);
+ 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;
break;
- case 2:
- case 1:
default:
error = ENODEV;
break;
}
break;
- case PCIOCATTACHED:
+ case PCIOCWRITE:
io = (struct pci_io *)data;
switch(io->pi_width) {
+ pcicfgregs probe;
case 4:
- {
- int i = pci_dev_list_count;
- struct pci_conf *p = pci_dev_list;
- error = ENODEV;
- while (i--) {
- if (io->pi_sel.pc_bus == p->pc_sel.pc_bus &&
- io->pi_sel.pc_dev == p->pc_sel.pc_dev &&
- io->pi_sel.pc_func == p->pc_sel.pc_func) {
- io->pi_data = (u_int32_t)p->pc_dvp;
- error = 0;
- break;
- }
- p++;
- }
- }
- break;
case 2:
case 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;
+ break;
default:
error = ENODEV;
break;
@@ -2017,4 +566,4 @@ pci_cdevinit(void *dummy)
SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL);
-#endif /* NPCI */
+#endif /* NPCI > 0 */
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index 05e3c07..cd5c6e8 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -1,208 +1,250 @@
-/**************************************************************************
-**
-** $Id: pcireg.h,v 1.13 1997/04/20 06:57:43 phk Exp $
-**
-** Names for PCI configuration space registers.
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#ifndef __PCI_REG_H__
-#define __PCI_REG_H__ "pl2 95/03/21"
-
+#ifndef PCI_COMPAT
+#define PCI_COMPAT
+#endif
/*
-** Device identification register; contains a vendor ID and a device ID.
-** We have little need to distinguish the two parts.
-*/
-#define PCI_ID_REG 0x00
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
/*
-** Command and status register.
-*/
-#define PCI_COMMAND_STATUS_REG 0x04
-
+ * PCIM_xxx: mask to locate subfield in register
+ * PCIR_xxx: config register offset
+ * PCIC_xxx: device class
+ * PCIS_xxx: device subclass
+ * PCIP_xxx: device programming interface
+ * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
+ * PCID_xxx: device ID
+ */
+
+/* some PCI bus constants */
+
+#define PCI_BUSMAX 255
+#define PCI_SLOTMAX 31
+#define PCI_FUNCMAX 7
+#define PCI_REGMAX 255
+
+/* PCI config header registers for all devices */
+
+#define PCIR_DEVVENDOR 0x00
+#define PCIR_VENDOR 0x00
+#define PCIR_DEVICE 0x02
+#define PCIR_COMMAND 0x04
+#define PCIR_STATUS 0x06
+#define PCIR_REVID 0x08
+#define PCIR_PROGIF 0x09
+#define PCIR_SUBCLASS 0x0a
+#define PCIR_CLASS 0x0b
+#define PCIR_CACHELNSZ 0x0c
+#define PCIR_LATTIMER 0x0d
+#define PCIR_HEADERTYPE 0x0e
+#define PCIM_MFDEV 0x80
+#define PCIR_BIST 0x0f
+
+/* config registers for header type 0 devices */
+
+#define PCIR_MAPS 0x10
+#define PCIR_CARDBUSCIS 0x28
+#define PCIR_SUBVEND_0 0x2c
+#define PCIR_SUBDEV_0 0x2e
+#define PCIR_INTLINE 0x3c
+#define PCIR_INTPIN 0x3d
+#define PCIR_MINGNT 0x3e
+#define PCIR_MAXLAT 0x3f
+
+/* config registers for header type 1 devices */
+
+#define PCIR_SECSTAT_1 0 /**/
+
+#define PCIR_PRIBUS_1 0x18
+#define PCIR_SECBUS_1 0x19
+#define PCIR_SUBBUS_1 0x1a
+#define PCIR_SECLAT_1 0x1b
+
+#define PCIR_IOBASEL_1 0x1c
+#define PCIR_IOLIMITL_1 0x1d
+#define PCIR_IOBASEH_1 0 /**/
+#define PCIR_IOLIMITH_1 0 /**/
+
+#define PCIR_MEMBASE_1 0x20
+#define PCIR_MEMLIMIT_1 0x22
+
+#define PCIR_PMBASEL_1 0x24
+#define PCIR_PMLIMITL_1 0x26
+#define PCIR_PMBASEH_1 0 /**/
+#define PCIR_PMLIMITH_1 0 /**/
+
+#define PCIR_BRIDGECTL_1 0 /**/
+
+#define PCIR_SUBVEND_1 0x34
+#define PCIR_SUBDEV_1 0x36
+
+/* config registers for header type 2 devices */
+
+#define PCIR_SECSTAT_2 0x16
+
+#define PCIR_PRIBUS_2 0x18
+#define PCIR_SECBUS_2 0x19
+#define PCIR_SUBBUS_2 0x1a
+#define PCIR_SECLAT_2 0x1b
+
+#define PCIR_MEMBASE0_2 0x1c
+#define PCIR_MEMLIMIT0_2 0x20
+#define PCIR_MEMBASE1_2 0x24
+#define PCIR_MEMLIMIT1_2 0x28
+#define PCIR_IOBASE0_2 0x2c
+#define PCIR_IOLIMIT0_2 0x30
+#define PCIR_IOBASE1_2 0x34
+#define PCIR_IOLIMIT1_2 0x38
+
+#define PCIR_BRIDGECTL_2 0x3e
+
+#define PCIR_SUBVEND_2 0x40
+#define PCIR_SUBDEV_2 0x42
+
+#define PCIR_PCCARDIF_2 0x44
+
+/* PCI device class, subclass and programming interface definitions */
+
+#define PCIC_OLD 0x00
+#define PCIS_OLD_NONVGA 0x00
+#define PCIS_OLD_VGA 0x01
+
+#define PCIC_STORAGE 0x01
+#define PCIS_STORAGE_SCSI 0x00
+#define PCIS_STORAGE_IDE 0x01
+#define PCIP_STORAGE_IDE_MODEPRIM 0x01
+#define PCIP_STORAGE_IDE_PROGINDPRIM 0x02
+#define PCIP_STORAGE_IDE_MODESEC 0x04
+#define PCIP_STORAGE_IDE_PROGINDSEC 0x08
+#define PCIP_STORAGE_IDE_MASTERDEV 0x80
+#define PCIS_STORAGE_FLOPPY 0x02
+#define PCIS_STORAGE_IPI 0x03
+#define PCIS_STORAGE_RAID 0x04
+#define PCIS_STORAGE_OTHER 0x80
+
+#define PCIC_NETWORK 0x02
+#define PCIS_NETWORK_ETHERNET 0x00
+#define PCIS_NETWORK_TOKENRING 0x01
+#define PCIS_NETWORK_FDDI 0x02
+#define PCIS_NETWORK_ATM 0x03
+#define PCIS_NETWORK_OTHER 0x80
+
+#define PCIC_DISPLAY 0x03
+#define PCIS_DISPLAY_VGA 0x00
+#define PCIS_DISPLAY_XGA 0x01
+#define PCIS_DISPLAY_OTHER 0x80
+
+#define PCIC_MULTIMEDIA 0x04
+#define PCIS_MULTIMEDIA_VIDEO 0x00
+#define PCIS_MULTIMEDIA_AUDIO 0x01
+#define PCIS_MULTIMEDIA_OTHER 0x80
+
+#define PCIC_MEMORY 0x05
+#define PCIS_MEMORY_RAM 0x00
+#define PCIS_MEMORY_FLASH 0x01
+#define PCIS_MEMORY_OTHER 0x80
+
+#define PCIC_BRIDGE 0x06
+#define PCIS_BRDIGE_HOST 0x00
+#define PCIS_BRIDGE_ISA 0x01
+#define PCIS_BRIDGE_EISA 0x02
+#define PCIS_BRIDGE_MCA 0x03
+#define PCIS_BRIDGE_PCI 0x04
+#define PCIS_BRIDGE_PCMCIA 0x05
+#define PCIS_BRIDGE_NUBUS 0x06
+#define PCIS_BRIDGE_CARDBUS 0x07
+#define PCIS_BRIDGE_OTHER 0x80
+
+#define PCIC_SIMPLECOMM 0x07
+#define PCIS_SIMPLECOMM_UART 0x00
+#define PCIS_SIMPLECOMM_PAR 0x01
+#define PCIS_SIMPLECOMM_OTHER 0x80
+
+#define PCIC_BASEPERIPH 0x08
+#define PCIS_BASEPERIPH_PIC 0x00
+#define PCIS_BASEPERIPH_DMA 0x01
+#define PCIS_BASEPERIPH_TIMER 0x02
+#define PCIS_BASEPERIPH_RTC 0x03
+#define PCIS_BASEPERIPH_OTHER 0x80
+
+#define PCIC_INPUTDEV 0x09
+#define PCIS_INPUTDEV_KEYBOARD 0x00
+#define PCIS_INPUTDEV_DIGITIZER 0x01
+#define PCIS_INPUTDEV_MOUSE 0x02
+#define PCIS_INPUTDEV_OTHER 0x80
+
+#define PCIC_DOCKING 0x0a
+#define PCIS_DOCKING_GENERIC 0x00
+#define PCIS_DOCKING_OTHER 0x80
+
+#define PCIC_PROCESSOR 0x0b
+#define PCIS_PROCESSOR_386 0x00
+#define PCIS_PROCESSOR_486 0x01
+#define PCIS_PROCESSOR_PENTIUM 0x02
+#define PCIS_PROCESSOR_ALPHA 0x10
+#define PCIS_PROCESSOR_POWERPC 0x20
+#define PCIS_PROCESSOR_COPROC 0x40
+
+#define PCIC_SERIALBUS 0x0c
+#define PCIS_SERIALBUS_FW 0x00
+#define PCIS_SERIALBUS_ACCESS 0x01
+#define PCIS_SERIALBUS_SSA 0x02
+#define PCIS_SERIALBUS_USB 0x03
+#define PCIS_SERIALBUS_FC 0x04
+#define PCIS_SERIALBUS
+#define PCIS_SERIALBUS
+
+#define PCIC_OTHER 0xff
+
+/* some PCI vendor definitions (only used to identify ancient devices !!! */
+
+#define PCIV_INTEL 0x8086
+
+#define PCID_INTEL_SATURN 0x0483
+#define PCID_INTEL_ORION 0x84c4
+
+/* for compatibility to FreeBSD-2.2 version of PCI code */
+
+#ifdef PCI_COMPAT
+
+#define PCI_ID_REG 0x00
+#define PCI_COMMAND_STATUS_REG 0x04
#define PCI_COMMAND_IO_ENABLE 0x00000001
-#define PCI_COMMAND_MEM_ENABLE 0x00000002
-#define PCI_COMMAND_MASTER_ENABLE 0x00000004
-#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008
-#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010
-#define PCI_COMMAND_PALETTE_ENABLE 0x00000020
-#define PCI_COMMAND_PARITY_ENABLE 0x00000040
-#define PCI_COMMAND_STEPPING_ENABLE 0x00000080
-#define PCI_COMMAND_SERR_ENABLE 0x00000100
-#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200
-
-#define PCI_STATUS_BACKTOBACK_OKAY 0x00800000
-#define PCI_STATUS_PARITY_ERROR 0x01000000
-#define PCI_STATUS_DEVSEL_FAST 0x00000000
-#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000
-#define PCI_STATUS_DEVSEL_SLOW 0x04000000
-#define PCI_STATUS_DEVSEL_MASK 0x06000000
-#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000
-#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000
-#define PCI_STATUS_MASTER_ABORT 0x20000000
-#define PCI_STATUS_SPECIAL_ERROR 0x40000000
-#define PCI_STATUS_PARITY_DETECT 0x80000000
-
-/*
-** Class register; defines basic type of device.
-*/
-#define PCI_CLASS_REG 0x08
-
-#define PCI_CLASS_MASK 0xff000000
-#define PCI_SUBCLASS_MASK 0x00ff0000
-
-/* base classes */
-#define PCI_CLASS_PREHISTORIC 0x00000000
-#define PCI_CLASS_MASS_STORAGE 0x01000000
-#define PCI_CLASS_NETWORK 0x02000000
-#define PCI_CLASS_DISPLAY 0x03000000
-#define PCI_CLASS_MULTIMEDIA 0x04000000
-#define PCI_CLASS_MEMORY 0x05000000
-#define PCI_CLASS_BRIDGE 0x06000000
-#define PCI_CLASS_UNDEFINED 0xff000000
-
-/* 0x00 prehistoric subclasses */
-#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00000000
-#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
-
-/* 0x01 mass storage subclasses */
-#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000
-#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x00010000
-#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x00020000
-#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x00030000
-#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x00800000
-
-/* 0x02 network subclasses */
-#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00000000
-#define PCI_SUBCLASS_NETWORK_TOKENRING 0x00010000
-#define PCI_SUBCLASS_NETWORK_FDDI 0x00020000
-#define PCI_SUBCLASS_NETWORK_MISC 0x00800000
-
-/* 0x03 display subclasses */
-#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000
-#define PCI_SUBCLASS_DISPLAY_XGA 0x00010000
-#define PCI_SUBCLASS_DISPLAY_MISC 0x00800000
-
-/* 0x04 multimedia subclasses */
-#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00000000
-#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x00010000
-#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x00800000
-
-/* 0x05 memory subclasses */
-#define PCI_SUBCLASS_MEMORY_RAM 0x00000000
-#define PCI_SUBCLASS_MEMORY_FLASH 0x00010000
-#define PCI_SUBCLASS_MEMORY_MISC 0x00800000
-
-/* 0x06 bridge subclasses */
-#define PCI_SUBCLASS_BRIDGE_HOST 0x00000000
-#define PCI_SUBCLASS_BRIDGE_ISA 0x00010000
-#define PCI_SUBCLASS_BRIDGE_EISA 0x00020000
-#define PCI_SUBCLASS_BRIDGE_MC 0x00030000
-#define PCI_SUBCLASS_BRIDGE_PCI 0x00040000
-#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x00050000
-#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x00070000
-#define PCI_SUBCLASS_BRIDGE_MISC 0x00800000
-
-/*
-** Header registers
-*/
-#define PCI_HEADER_MISC 0x0c
-
-#define PCI_HEADER_MULTIFUNCTION 0x00800000
-
-/*
-** Mapping registers
-*/
-#define PCI_MAP_REG_START 0x10
-#define PCI_MAP_REG_END 0x28
-
-#define PCI_MAP_MEMORY 0x00000000
+#define PCI_CLASS_REG 0x08
+#define PCI_CLASS_MASK 0xff000000
+#define PCI_SUBCLASS_MASK 0x00ff0000
+#define PCI_CLASS_PREHISTORIC 0x00000000
+#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
+#define PCI_CLASS_DISPLAY 0x03000000
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000
+#define PCI_CLASS_BRIDGE 0x06000000
+#define PCI_MAP_REG_START 0x10
+#define PCI_MAP_REG_END 0x28
#define PCI_MAP_IO 0x00000001
+#define PCI_INTERRUPT_REG 0x3c
-#define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000
-#define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002
-#define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004
-#define PCI_MAP_MEMORY_TYPE_MASK 0x00000006
-#define PCI_MAP_MEMORY_CACHABLE 0x00000008
-#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0
-
-#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc
-/*
-** PCI-PCI bridge mapping registers
-*/
-#define PCI_PCI_BRIDGE_BUS_REG 0x18
-#define PCI_PCI_BRIDGE_IO_REG 0x1c
-#define PCI_PCI_BRIDGE_MEM_REG 0x20
-#define PCI_PCI_BRIDGE_PMEM_REG 0x24
-
-#define PCI_SUBID_REG0 0x2c
-#define PCI_SUBID_REG1 0x34
-#define PCI_SUBID_REG2 0x40
-
-#define PCI_SUBORDINATE_BUS_MASK 0x00ff0000
-#define PCI_SECONDARY_BUS_MASK 0x0000ff00
-#define PCI_PRIMARY_BUS_MASK 0x000000ff
-
-#define PCI_SUBORDINATE_BUS_EXTRACT(x) (((x) >> 16) & 0xff)
-#define PCI_SECONDARY_BUS_EXTRACT(x) (((x) >> 8) & 0xff)
-#define PCI_PRIMARY_BUS_EXTRACT(x) (((x) ) & 0xff)
-
-#define PCI_PRIMARY_BUS_INSERT(x, y) (((x) & ~PCI_PRIMARY_BUS_MASK) | ((y) << 0))
-#define PCI_SECONDARY_BUS_INSERT(x, y) (((x) & ~PCI_SECONDARY_BUS_MASK) | ((y) << 8))
-#define PCI_SUBORDINATE_BUS_INSERT(x, y) (((x) & ~PCI_SUBORDINATE_BUS_MASK) | ((y) << 16))
-
-#define PCI_PPB_IOBASE_EXTRACT(x) (((x) << 8) & 0xF000)
-#define PCI_PPB_IOLIMIT_EXTRACT(x) (((x) << 0) & 0xF000 | 0x0FFF)
-
-#define PCI_PPB_MEMBASE_EXTRACT(x) (((x) << 16) & 0xFFF00000)
-#define PCI_PPB_MEMLIMIT_EXTRACT(x) (((x) << 0) & 0xFFF00000 | 0x000FFFFF)
-
-/*
-** PCI-Cardbus bridge mapping registers
-*/
-#define PCI_CARDBUS_SOCKET_REG 0x10
-
-/*
-** Interrupt configuration register
-*/
-#define PCI_INTERRUPT_REG 0x3c
-
-#define PCI_INTERRUPT_PIN_MASK 0x0000ff00
-#define PCI_INTERRUPT_PIN_EXTRACT(x) ((((x) & PCI_INTERRUPT_PIN_MASK) >> 8) & 0xff)
-#define PCI_INTERRUPT_PIN_NONE 0x00
-#define PCI_INTERRUPT_PIN_A 0x01
-#define PCI_INTERRUPT_PIN_B 0x02
-#define PCI_INTERRUPT_PIN_C 0x03
-#define PCI_INTERRUPT_PIN_D 0x04
-
-#define PCI_INTERRUPT_LINE_MASK 0x000000ff
-#define PCI_INTERRUPT_LINE_EXTRACT(x) ((((x) & PCI_INTERRUPT_LINE_MASK) >> 0) & 0xff)
-#define PCI_INTERRUPT_LINE_INSERT(x,v) (((x) & ~PCI_INTERRUPT_LINE_MASK) | ((v) << 0))
-
-#endif /* __PCI_REG_H__ */
+#endif /* PCI_COMPAT */
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index cb85100..4bb8496 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,129 +1,183 @@
-/**************************************************************************
-**
-** $Id$
-**
-** Declarations for pci device drivers.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#ifndef __PCI_VAR_H__
-#define __PCI_VAR_H__ "pl2 95/03/21"
-
-/*-----------------------------------------------------------------
-**
-** main pci initialization function.
-** called at boot time from autoconf.c
-**
-**-----------------------------------------------------------------
-*/
-
-void pci_configure (void);
-
-/*-----------------------------------------------------------------
-**
-** The pci configuration id describes a pci device on the bus.
-** It is constructed from: bus, device & function numbers.
-**
-**-----------------------------------------------------------------
-*/
-
-typedef union {
- u_long cfg1;
- struct {
- u_char enable;
- u_char forward;
- u_short port;
- } cfg2;
- unsigned tag;
- } pcici_t;
-
-#define sametag(x,y) ((x).tag == (y).tag)
-
-/*-----------------------------------------------------------------
-**
-** Each pci device has an unique device id.
-** It is used to find a matching driver.
-**
-**-----------------------------------------------------------------
-*/
-
-typedef u_long pcidi_t;
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided for the device driver
-** to read/write the configuration space.
-**
-** pci_conf_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word alligned one).
-**
-** pci_conf_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word alligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-u_long pci_conf_read (pcici_t tag, u_long reg );
-
-void pci_conf_write (pcici_t tag, u_long reg, u_long data);
-
-/*-----------------------------------------------------------------
-**
-** The pci driver structure.
-**
-** name: The short device name.
-**
-** probe: Checks if the driver can support a device
-** with this type. The tag may be used to get
-** more info with pci_read_conf(). See below.
-** It returns a string with the devices name,
-** or a NULL pointer, if the driver cannot
-** support this device.
-**
-** attach: Allocate a control structure and prepare
-** it. This function may use the pci mapping
-** functions. See below.
-** (configuration id) or type.
-**
-** count: A pointer to a unit counter.
-** It's used by the pci configurator to
-** allocate unit numbers.
-**
-**-----------------------------------------------------------------
-*/
+#ifndef PCI_COMPAT
+#define PCI_COMPAT
+#endif
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+/* some PCI bus constants */
+
+#define PCI_BUSMAX 255 /* highest supported bus number */
+#define PCI_SLOTMAX 31 /* highest supported slot number */
+#define PCI_FUNCMAX 7 /* highest supported function number */
+#define PCI_REGMAX 255 /* highest supported config register addr. */
+
+#define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */
+#define PCI_MAXMAPS_1 2 /* max. no. of maps for PCI to PCI bridge */
+#define PCI_MAXMAPS_2 1 /* max. no. of maps for CardBus bridge */
+
+/* pci_addr_t covers this system's PCI bus address space: 32 or 64 bit */
+
+#ifdef PCI_A64
+typedef u_int64_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
+#else
+typedef u_int32_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
+#endif
+
+/* map register information */
+
+typedef struct {
+ u_int32_t base;
+ u_int8_t type;
+#define PCI_MAPMEM 0x01 /* memory map */
+#define PCI_MAPMEMP 0x02 /* prefetchable memory map */
+#define PCI_MAPPORT 0x04 /* port map */
+ u_int8_t ln2size;
+ u_int8_t ln2range;
+/* u_int8_t dummy;*/
+} pcimap;
+
+/* config header information common to all header types */
+
+typedef struct pcicfg {
+ struct pcicfg *parent;
+ struct pcicfg *next;
+ pcimap *map; /* pointer to array of PCI maps */
+ void *hdrspec; /* pointer to header type specific data */
+
+ u_int16_t subvendor; /* card vendor ID */
+ u_int16_t subdevice; /* card device ID, assigned by card vendor */
+ u_int16_t vendor; /* chip vendor ID */
+ u_int16_t device; /* chip device ID, assigned by chip vendor */
+
+ u_int16_t cmdreg; /* disable/enable chip and PCI options */
+ u_int16_t statreg; /* supported PCI features and error state */
+
+ u_int8_t class; /* chip PCI class */
+ u_int8_t subclass; /* chip PCI subclass */
+ u_int8_t progif; /* chip PCI programming interface */
+ u_int8_t revid; /* chip revision ID */
+
+ u_int8_t hdrtype; /* chip config header type */
+ u_int8_t cachelnsz; /* cache line size in 4byte units */
+ u_int8_t intpin; /* PCI interrupt pin */
+ u_int8_t intline; /* interrupt line (IRQ for PC arch) */
+
+ u_int8_t mingnt; /* min. useful bus grant time in 250ns units */
+ u_int8_t maxlat; /* max. tolerated bus grant latency in 250ns */
+ u_int8_t lattimer; /* latency timer in units of 30ns bus cycles */
+
+ u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
+ u_int8_t nummaps; /* actual number of PCI maps used */
+
+ u_int8_t bus; /* config space bus address */
+ u_int8_t slot; /* config space slot address */
+ u_int8_t func; /* config space function number */
+
+ u_int8_t secondarybus; /* bus on secondary side of bridge, if any */
+ u_int8_t subordinatebus; /* topmost bus number behind bridge, if any */
+} pcicfgregs;
+
+/* additional type 1 device config header information (PCI to PCI bridge) */
+
+#ifdef PCI_A64
+#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
+#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
+#else
+#define PCI_PPBMEMBASE(h,l) (((l)<<16) & ~0xfffff)
+#define PCI_PPBMEMLIMIT(h,l) (((l)<<16) | 0xfffff)
+#endif /* PCI_A64 */
+
+#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff)
+#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff)
+
+typedef struct {
+ pci_addr_t pmembase; /* base address of prefetchable memory */
+ pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
+ u_int32_t membase; /* base address of memory window */
+ u_int32_t memlimit; /* topmost address of memory window */
+ u_int32_t iobase; /* base address of port window */
+ u_int32_t iolimit; /* topmost address of port window */
+ u_int16_t secstat; /* secondary bus status register */
+ u_int16_t bridgectl; /* bridge control register */
+ u_int8_t seclat; /* CardBus latency timer */
+} pcih1cfgregs;
+
+/* additional type 2 device config header information (CardBus bridge) */
+
+typedef struct {
+ u_int32_t membase0; /* base address of memory window */
+ u_int32_t memlimit0; /* topmost address of memory window */
+ u_int32_t membase1; /* base address of memory window */
+ u_int32_t memlimit1; /* topmost address of memory window */
+ u_int32_t iobase0; /* base address of port window */
+ u_int32_t iolimit0; /* topmost address of port window */
+ u_int32_t iobase1; /* base address of port window */
+ u_int32_t iolimit1; /* topmost address of port window */
+ u_int32_t pccardif; /* PC Card 16bit IF legacy more base addr. */
+ u_int16_t secstat; /* secondary bus status register */
+ u_int16_t bridgectl; /* bridge control register */
+ u_int8_t seclat; /* CardBus latency timer */
+} pcih2cfgregs;
+
+/* PCI bus attach definitions (there could be multiple PCI bus *trees* ... */
+
+typedef struct pciattach {
+ int unit;
+ int pcibushigh;
+ struct pciattach *next;
+} pciattach;
+
+/* externally visible functions */
+
+int pci_probe (pciattach *attach);
+void pci_drvattach(pcicfgregs *cfg);
+
+/* low level PCI config register functions provided by pcibus.c */
+
+int pci_cfgopen (void);
+int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
+void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
+
+/* for compatibility to FreeBSD-2.2 version of PCI code */
+
+#ifdef PCI_COMPAT
+
+typedef pcicfgregs *pcici_t;
+typedef unsigned pcidi_t;
+typedef void pci_inthand_t(void *arg);
+
+#define pci_max_burst_len (3)
+
+/* just copied from old PCI code for now ... */
+
+extern struct linker_set pcidevice_set;
+extern int pci_mechanism;
struct pci_device {
char* pd_name;
@@ -133,97 +187,17 @@ struct pci_device {
int (*pd_shutdown) (int, int);
};
-/*-----------------------------------------------------------------
-**
-** This table includes pointers to all pci device drivers.
-** It should be generated by the linker.
-**
-**-----------------------------------------------------------------
-*/
-
-extern struct linker_set pcidevice_set;
-
-extern unsigned pci_max_burst_len; /* log2 of safe burst transfer length */
-extern unsigned pci_mechanism;
-extern unsigned pci_maxdevice;
-
-/*-----------------------------------------------------------------
-**
-** Map a pci device to physical and virtual memory.
-**
-** Entry selects the register in the pci configuration
-** space, which supplies the size of the region, and
-** receives the physical address.
-**
-** In case of success the function sets the addresses
-** in *va and *pa, and returns 1.
-** In case of errors a message is written,
-** and the function returns 0.
-**
-**-----------------------------------------------------------------
-*/
-
-int pci_map_mem (pcici_t tag, u_long entry, vm_offset_t *va, vm_offset_t *pa);
-
-/*-----------------------------------------------------------------
-**
-** Map a pci device to an io port area.
-**
-** Entry selects the register in the pci configuration
-** space, which supplies the size of the region, and
-** receives the port number.
-**
-** In case of success the function sets the port number in pa,
-** and returns 1.
-** In case of errors a message is written,
-** and the function returns 0.
-**
-**-----------------------------------------------------------------
-*/
-
-int pci_map_port (pcici_t tag, u_long entry, u_short * pa);
-
-/*-----------------------------------------------------------------
-**
-** Map a pci interrupt to an isa irq line, and enable the interrupt.
-**
-** -----------------
-**
-** func is the interrupt handler, arg is the argument
-** to the handler (usually a pointer to a softc).
-**
-** The maskptr argument should be &bio_imask,
-** &net_imask etc. or NULL.
-**
-** If there is any error, a message is written, and
-** the function returns with zero.
-** Else it returns with a value different to zero.
-**
-** -----------------
-**
-** The irq number is read from the configuration space.
-** (Should have been set by the bios).
-**
-** Supports multiple handlers per irq (shared interrupts).
-**
-**-----------------------------------------------------------------
-*/
-
-typedef void pci_inthand_t(void *arg);
-
-struct pci_int_desc {
- struct pci_int_desc * pcid_next;
- pcici_t pcid_tag;
- pci_inthand_t *pcid_handler;
- void* pcid_argument;
- unsigned * pcid_maskptr;
- unsigned pcid_tally;
- unsigned pcid_mask;
+struct pci_lkm {
+ struct pci_device *dvp;
+ struct pci_lkm *next;
};
-int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg,
- unsigned *maskptr);
-
+u_long pci_conf_read (pcici_t tag, u_long reg);
+void pci_conf_write (pcici_t tag, u_long reg, u_long data);
+int pci_map_port (pcici_t tag, u_long reg, u_short* pa);
+int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
+int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg, unsigned *maskptr);
int pci_unmap_int (pcici_t tag);
+int pci_register_lkm (struct pci_device *dvp, int if_revision);
-#endif
+#endif /* PCI_COMPAT */
diff --git a/sys/i386/include/pci_cfgreg.h b/sys/i386/include/pci_cfgreg.h
new file mode 100644
index 0000000..44556e7
--- /dev/null
+++ b/sys/i386/include/pci_cfgreg.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#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
diff --git a/sys/i386/isa/pcibus.c b/sys/i386/isa/pcibus.c
index 31de543..df84794 100644
--- a/sys/i386/isa/pcibus.c
+++ b/sys/i386/isa/pcibus.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/i386/isa/pcibus.h b/sys/i386/isa/pcibus.h
new file mode 100644
index 0000000..44556e7
--- /dev/null
+++ b/sys/i386/isa/pcibus.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#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
diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c
index 31de543..df84794 100644
--- a/sys/i386/pci/pci_bus.c
+++ b/sys/i386/pci/pci_bus.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index 31de543..df84794 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index 31de543..df84794 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -1,538 +1,265 @@
-/**************************************************************************
-**
-** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
-**
-** pci bus subroutines for i386 architecture.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#include "vector.h"
-
-#include <sys/param.h>
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided by the pci bios.
-** They are used only by the pci configuration.
-**
-** pcibus_setup():
-** Probes for a pci system.
-** Sets pci_maxdevice and pci_mechanism.
-**
-** pcibus_tag():
-** Creates a handle for pci configuration space access.
-** This handle is given to the read/write functions.
-**
-** pcibus_ftag():
-** Creates a modified handle.
-**
-** pcibus_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word aligned one).
-**
-** pcibus_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-** pcibus_regirq():
-** Register an interrupt handler for a pci device.
-** Requires a tag (from pcitag), the register number
-** (should be a long word aligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-static int
-pcibus_check (void);
-
-static void
-pcibus_setup (void);
-
-static pcici_t
-pcibus_tag (u_char bus, u_char device, u_char func);
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func);
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg);
+#include <pci/pcivar.h>
+#include <i386/isa/pcibus.h>
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data);
+#ifdef PCI_COMPAT
+/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
+#define cfgmech pci_mechanism
+int cfgmech;
+#else
+static int cfgmech;
+#endif /* PCI_COMPAT */
+static int devmax;
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
+/* enable configuration space accesses and return data port address */
static int
-pcibus_ihandler_detach (int irq, inthand2_t *func);
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ 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,
+ (bus << 16) | (slot << 11) | (func << 8) | reg);
+ dataport = CONF1_DATA_PORT;
+ break;
+ case 2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ }
+ }
+ return (dataport);
+}
-static int
-pcibus_imask_include (int irq, unsigned* maskptr);
+/* disable configuration space accesses */
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr);
-
-static struct pcibus i386pci = {
- "pci",
- pcibus_setup,
- pcibus_tag,
- pcibus_ftag,
- pcibus_read,
- pcibus_write,
- pcibus_ihandler_attach,
- pcibus_ihandler_detach,
- pcibus_imask_include,
- pcibus_imask_exclude,
-};
+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;
+ }
+}
-/*
-** Announce structure to generic driver
-*/
+/* read configuration space register */
-DATA_SET (pcibus_set, i386pci);
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ int data = -1;
+ int port;
-/*--------------------------------------------------------------------
-**
-** Determine configuration mode
-**
-**--------------------------------------------------------------------
-*/
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+ return (data);
+}
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+/* write configuration space register */
-#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
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ int port;
-#define CONF2_ENABLE_PORT 0x0cf8
-#ifdef PC98
-#define CONF2_FORWARD_PORT 0x0cf9
-#else
-#define CONF2_FORWARD_PORT 0x0cfa
-#endif
+ port = pci_cfgenable(cfg->bus, cfg->slot, cfg->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();
+ }
+}
-#define CONF2_ENABLE_CHK 0x0e
-#define CONF2_ENABLE_RES 0x0e
+/* check whether the configuration mechanism has been correct identified */
static int
-pcibus_check (void)
+pci_cfgcheck(int maxdev)
{
u_char device;
- if (bootverbose) printf ("pcibus_check:\tdevice ");
+ if (bootverbose)
+ printf("pci_cfgcheck:\tdevice ");
- for (device = 0; device < pci_maxdevice; device++) {
- unsigned long id, class, header;
+ for (device = 0; device < maxdev; device++) {
+ unsigned id, class, header;
if (bootverbose)
- printf ("%d ", device);
- id = pcibus_read (pcibus_tag (0,device,0), 0);
- if ((id == 0) || (id == 0xfffffffful))
+ printf("%d ", device);
+
+ id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ if (id == 0 || id == -1)
continue;
- class = pcibus_read (pcibus_tag (0,device,0), 8);
+ class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
if (bootverbose)
- printf ("[class=%x] ", class >> 8);
- if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
+ printf("[class=%06x] ", class);
+ if (class == 0 || (class & 0xf8f0ff) != 0)
continue;
- header = pcibus_read (pcibus_tag (0,device,0), 12);
+ header = inb(pci_cfgenable(0, device, 0, 14, 1));
if (bootverbose)
- printf ("[hdr=%x] ", (header >> 16) & 0xff);
- if ((header & 0x007e0000) != 0)
+ printf("[hdr=%02x] ", header);
+ if ((header & 0x7e) != 0)
continue;
- if (bootverbose) printf ("is there (id=%08lx)\n", id);
- return 1;
+ if (bootverbose)
+ printf("is there (id=%08x)\n", id);
+
+ pci_cfgdisable();
+ return (1);
}
if (bootverbose)
- printf ("-- nothing found\n");
- return 0;
+ printf("-- nothing found\n");
+
+ pci_cfgdisable();
+ return (0);
}
-static void
-pcibus_setup (void)
+int
+pci_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
- oldval1 = inl (CONF1_ADDR_PORT);
+ oldval1 = inl(CONF1_ADDR_PORT);
if (bootverbose) {
- printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
+ printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
+ oldval1);
}
- /*---------------------------------------
- ** Assume configuration mechanism 1 for now ...
- **---------------------------------------
- */
-
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
- pci_mechanism = 1;
- pci_maxdevice = 32;
+ cfgmech = 1;
+ devmax = 32;
- 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_CHK);
+ outb(CONF1_ADDR_PORT +3, 0);
+ mode1res = inl(CONF1_ADDR_PORT);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK);
+ printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK);
if (mode1res) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
- outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+ outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
mode1res = inl(CONF1_ADDR_PORT);
- outl (CONF1_ADDR_PORT, oldval1);
+ outl(CONF1_ADDR_PORT, oldval1);
if (bootverbose)
- printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
- mode1res, CONF1_ENABLE_CHK1);
+ printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
+ mode1res, CONF1_ENABLE_CHK1);
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
- if (pcibus_check())
- return;
- };
+ if (pci_cfgcheck(32))
+ return (cfgmech);
+ }
}
- /*---------------------------------------
- ** Try configuration mechanism 2 ...
- **---------------------------------------
- */
-
- oldval2 = inb (CONF2_ENABLE_PORT);
+ oldval2 = inb(CONF2_ENABLE_PORT);
if (bootverbose) {
- printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
+ printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+ oldval2);
}
if ((oldval2 & 0xf0) == 0) {
- pci_mechanism = 2;
- pci_maxdevice = 16;
-
- outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+ 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, oldval2);
if (bootverbose)
- printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
- mode2res, CONF2_ENABLE_CHK);
+ printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
+ mode2res, CONF2_ENABLE_CHK);
if (mode2res == CONF2_ENABLE_RES) {
- if (bootverbose)
- printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
-
- if (pcibus_check())
- return;
- }
- }
-
- /*---------------------------------------
- ** No PCI bus host bridge found
- **---------------------------------------
- */
-
- pci_mechanism = 0;
- pci_maxdevice = 0;
-}
-
-/*--------------------------------------------------------------------
-**
-** Build a pcitag from bus, device and function number
-**
-**--------------------------------------------------------------------
-*/
-
-static pcici_t
-pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
-{
- pcici_t tag;
-
- tag.cfg1 = 0;
- if (func >= 8) return tag;
-
- switch (pci_mechanism) {
-
- case 1:
- if (device < 32) {
- tag.cfg1 = CONF1_ENABLE
- | (((u_long) bus ) << 16ul)
- | (((u_long) device) << 11ul)
- | (((u_long) func ) << 8ul);
- }
- break;
- case 2:
- if (device < 16) {
- tag.cfg2.port = 0xc000 | (device << 8ul);
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- tag.cfg2.forward = bus;
- }
- break;
- };
- return tag;
-}
-
-static pcici_t
-pcibus_ftag (pcici_t tag, u_char func)
-{
- switch (pci_mechanism) {
-
- case 1:
- tag.cfg1 &= ~0x700ul;
- tag.cfg1 |= (((u_long) func) << 8ul);
- break;
- case 2:
- tag.cfg2.enable = 0xf0 | (func << 1ul);
- break;
- };
- return tag;
-}
-
-/*--------------------------------------------------------------------
-**
-** Read register from configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static u_long
-pcibus_read (pcici_t tag, u_long reg)
-{
- u_long addr, data = 0;
-
- if (!tag.cfg1) return (0xfffffffful);
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(1): addr=%x ", addr);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- data = inl (CONF1_DATA_PORT);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_read(2): addr=%x ", addr);
-#endif
- outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- data = inl ((u_short) addr);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-
-#ifdef PCI_DEBUG
- printf ("data=%x\n", data);
-#endif
-
- return (data);
-}
-
-/*--------------------------------------------------------------------
-**
-** Write register into configuration space.
-**
-**--------------------------------------------------------------------
-*/
-
-static void
-pcibus_write (pcici_t tag, u_long reg, u_long data)
-{
- u_long addr;
-
- if (!tag.cfg1) return;
-
- switch (pci_mechanism) {
-
- case 1:
- addr = tag.cfg1 | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(1): addr=%x data=%x\n",
- addr, data);
-#endif
- outl (CONF1_ADDR_PORT, addr);
- outl (CONF1_DATA_PORT, data);
- outl (CONF1_ADDR_PORT, 0 );
- break;
-
- case 2:
- addr = tag.cfg2.port | (reg & 0xfc);
-#ifdef PCI_DEBUG
- printf ("pci_conf_write(2): addr=%x data=%x\n",
- addr, data);
-#endif
- outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
- outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
-
- outl ((u_short) addr, data);
-
- outb (CONF2_ENABLE_PORT, 0);
- outb (CONF2_FORWARD_PORT, 0);
- break;
- };
-}
-
-/*-----------------------------------------------------------------------
-**
-** Register an interrupt handler for a pci device.
-**
-**-----------------------------------------------------------------------
-*/
-
-static int
-pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
-{
- char buf[16];
- char *cp;
- int free_id, id, result;
+ if (bootverbose)
+ printf("pci_open(2a):\tnow trying mechanism 2\n");
- sprintf(buf, "pci irq%d", irq);
- for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- break;
- if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0')
- ;
- }
- if (id == NR_DEVICES) {
- id = free_id;
- if (id == 0) {
- /*
- * All pci irq counters are in use, perhaps because
- * config is old so there aren't any. Abuse the
- * clk0 counter.
- */
- printf (
- "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
- irq);
+ if (pci_cfgcheck(16))
+ return (cfgmech);
}
}
- result = register_intr(
- irq, /* isa irq */
- id, /* device id */
- 0, /* flags? */
- func, /* handler */
- maskptr, /* mask pointer */
- arg); /* handler arg */
-
- if (result) {
- printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
- return (result);
- };
- update_intr_masks();
-
- INTREN ((1ul<<irq));
- return (0);
-}
-
-static int
-pcibus_ihandler_detach (int irq, inthand2_t *func)
-{
- int result;
-
- INTRDIS ((1ul<<irq));
-
- result = unregister_intr (irq, func);
-
- if (result)
- printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
-
- update_intr_masks();
-
- return (result);
-}
-
-static int
-pcibus_imask_include (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
- mask = 1ul << irq;
-
- if (*maskptr & mask)
- return (-1);
-
- INTRMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
-}
-
-static int
-pcibus_imask_exclude (int irq, unsigned* maskptr)
-{
- unsigned mask;
-
- if (!maskptr) return (0);
-
- mask = 1ul << irq;
-
- if (! (*maskptr & mask))
- return (-1);
-
- INTRUNMASK (*maskptr, mask);
- update_intr_masks();
-
- return (0);
+ cfgmech = 0;
+ devmax = 0;
+ return (cfgmech);
}
diff --git a/sys/pci/pci.c b/sys/pci/pci.c
index 4456fe6..b6f056e 100644
--- a/sys/pci/pci.c
+++ b/sys/pci/pci.c
@@ -1,1893 +1,459 @@
-/**************************************************************************
-**
-** $Id: pci.c,v 1.70 1997/04/26 11:46:18 peter Exp $
-**
-** General subroutines for the PCI bus.
-** pci_configure ()
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
#include "pci.h"
#if NPCI > 0
-/*========================================================
-**
-** #includes and declarations
-**
-**========================================================
-*/
-
-#include "opt_smp.h"
+#include <stddef.h>
+#include <sys/types.h>
#include <sys/param.h>
+#include <sys/time.h>
#include <sys/systm.h>
#include <sys/malloc.h>
-#include <sys/errno.h>
-#include <sys/kernel.h>
-#include <sys/proc.h> /* declaration of wakeup(), used by vm.h */
+#include <sys/fcntl.h>
#include <sys/conf.h>
+#include <sys/kernel.h>
#ifdef DEVFS
#include <sys/devfsext.h>
#endif /* DEVFS */
-#include <sys/fcntl.h>
#include <vm/vm.h>
-#include <vm/vm_param.h>
#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h> /* XXX inthand2_t */
-
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
-#include <pci/pcibus.h>
+#include <pci/pcivar.h>
#include <pci/pci_ioctl.h>
-/*========================================================
-**
-** Structs and Functions
-**
-**========================================================
-*/
-
-struct pcicb {
- struct pcicb *pcicb_next;
- struct pcicb *pcicb_up;
- struct pcicb *pcicb_down;
- pcici_t pcicb_bridge;
-
- u_char pcicb_bus;
- u_char pcicb_subordinate;
- u_int pcicb_mfrom;
- u_int pcicb_mupto;
- u_int pcicb_mamount;
- u_short pcicb_pfrom;
- u_short pcicb_pupto;
- u_short pcicb_pamount;
- u_char pcicb_bfrom;
- u_char pcicb_bupto;
-
- u_long pcicb_iobase;
- u_long pcicb_iolimit;
- u_long pcicb_membase;
- u_long pcicb_memlimit;
- u_long pcicb_p_membase;
- u_long pcicb_p_memlimit;
-};
-
-struct pci_lkm {
- struct pci_device *dvp;
- struct pci_lkm *next;
-};
-
-static void
-not_supported (pcici_t tag, u_long type);
-
-static void
-pci_bus_config (void);
-
-static void
-pci_rescan (void);
-
-static void pci_attach (int bus, int dev, int func,
- struct pci_device *dvp, const char *name);
-
-static int
-pci_bridge_config (void);
+/* return highest PCI bus number known to be used, or -1 if none */
static int
-pci_mfdev (int bus, int device);
-
-static void pci_remember (int bus, int dev, int func, struct pci_device *dvp);
-
-/*========================================================
-**
-** Variables
-**
-**========================================================
-*/
-
-/*
-** log2 of safe burst len (in words)
-*/
-
-unsigned pci_max_burst_len = 3; /* 2=16Byte, 3=32Byte, 4=64Byte, ... */
-unsigned pci_mechanism = 0;
-unsigned pci_maxdevice = 0;
-unsigned pciroots = 0; /* XXX pcisupport.c increments this
- * for the Orion host to PCI bridge
- * UGLY hack ... :( Will be changed :)
- */
-/*--------------------------------------------------------
-**
-** Local variables.
-**
-**--------------------------------------------------------
-*/
-
-static struct pcibus *pcibus;
-
-static int pci_conf_count;
-static int pci_info_done;
-static int pcibusmax;
-static struct pcicb *pcicb;
-
-static struct pci_conf *pci_dev_list;
-static unsigned pci_dev_list_count;
-static unsigned pci_dev_list_size;
-
-static struct pci_lkm *pci_lkm_head;
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided for the device driver
-** to read/write the configuration space.
-**
-** pci_conf_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word alligned one).
-**
-** pci_conf_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word alligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-u_long
-pci_conf_read (pcici_t tag, u_long reg)
-{
- return (pcibus->pb_read (tag, reg));
-}
-
-void
-pci_conf_write (pcici_t tag, u_long reg, u_long data)
-{
- pcibus->pb_write (tag, reg, data);
-}
-
-/*========================================================
-**
-** Subroutines for configuration.
-**
-**========================================================
-*/
-
-static void
-pci_register_io (struct pcicb * cb, u_int base, u_int limit)
+pci_bushigh(void)
{
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("register_io: bus=%d base=%x limit=%x\n",
- cb->pcicb_bus, base, limit);
-#endif
-
- if (!cb->pcicb_pfrom || base < cb->pcicb_pfrom)
- cb->pcicb_pfrom = base;
- if (limit > cb->pcicb_pupto)
- cb->pcicb_pupto = limit;
-
- /*
- ** XXX should set bridge io mapping here
- ** but it can be mapped in 4k blocks only,
- ** leading to conflicts with isa/eisa ..
- */
+ if (pci_cfgopen() == 0)
+ return (-1);
+ return (0);
}
-static void
-pci_register_memory (struct pcicb * cb, u_int base, u_int limit)
-{
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("register_mem: bus=%d base=%x limit=%x\n",
- cb->pcicb_bus, base, limit);
-#endif
+/* return base address of memory or port map */
- if (!cb->pcicb_mfrom || base < cb->pcicb_mfrom)
- cb->pcicb_mfrom = base;
- if (limit > cb->pcicb_mupto)
- cb->pcicb_mupto = limit;
- /*
- ** set the bridges mapping
- **
- ** XXX should handle the 1Mb granularity.
- */
- if (cb->pcicb_bridge.tag) {
- pci_conf_write(cb->pcicb_bridge,
- PCI_PCI_BRIDGE_MEM_REG,
- (cb->pcicb_memlimit & 0xffff0000) |
- (cb->pcicb_membase >> 16));
- if (bootverbose)
- printf ("\t[pci%d uses memory from %x to %x]\n",
- cb->pcicb_bus,
- (unsigned) cb->pcicb_membase,
- (unsigned) cb->pcicb_memlimit);
- }
-}
-
-/*
-** XXX This function is neither complete nor tested.
-** It's only used if the bios hasn't done it's job
-** of mapping the pci devices in the physical memory.
-*/
-
-static u_int
-pci_memalloc (struct pcicb * cb, u_int addr, u_int size)
+static int
+pci_mapbase(unsigned mapreg)
{
- u_int result = 0, limit=0, newbase=0;
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose)
- printf ("memalloc: bus=%d addr=%x size=%x ..\n",
- cb->pcicb_bus, addr, size);
-#endif
-
- if (!cb) goto done;
-
- if (!cb->pcicb_membase) {
- printf ("memalloc: bus%d: membase not set.\n",
- cb->pcicb_bus);
- goto done;
- }
-
- /*
- ** get upper allocation limit
- */
- limit = cb->pcicb_memlimit;
- if (cb->pcicb_mfrom && cb->pcicb_mfrom <= limit)
- limit = cb->pcicb_mfrom-1;
-
- /*
- ** address fixed, and impossible to allocate ?
- */
- if (addr && addr+size-1 > limit)
- goto done;
-
- /*
- ** get possible address
- */
-
- result = addr;
- if (!result) result = ((limit + 1) / size - 1) * size;
-
- /*
- ** if not local available, request from parent.
- */
-
- if (result < cb->pcicb_membase) {
- newbase = pci_memalloc (cb->pcicb_up, result, size);
- if (newbase) cb->pcicb_membase = result;
- else result=0;
- }
-done:
- if (result)
- pci_register_memory (cb, result, result+size-1);
-
-#ifdef PCI_BRIDGE_DEBUG
- printf ("memalloc: bus=%d addr=%x size=%x --> %x (limit=%x).\n",
- cb->pcicb_bus, addr, size, result, limit);
-#endif
-
- return (result);
+ int mask = 0x03;
+ if ((mapreg & 0x01) == 0)
+ mask = 0x0f;
+ return (mapreg & ~mask);
}
-/*========================================================
-**
-** pci_bridge_config()
-**
-** Configuration of a pci bridge.
-**
-**========================================================
-*/
+/* return map type of memory or port map */
static int
-pci_bridge_config (void)
-{
- pcici_t tag;
- struct pcicb* parent;
-
- tag = pcicb->pcicb_bridge;
- if (tag.tag) {
-
- if (!pcicb->pcicb_bus) {
- u_int data;
- /*
- ** Get the lowest available bus number.
- */
- pcicb->pcicb_bus = ++pcibusmax;
-
- /*
- ** and configure the bridge
- */
- data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
- data = PCI_PRIMARY_BUS_INSERT(data, pcicb->pcicb_up->pcicb_bus);
- data = PCI_SECONDARY_BUS_INSERT(data, pcicb->pcicb_bus);
- data = PCI_SUBORDINATE_BUS_INSERT(data, pcicb->pcicb_bus);
- pci_conf_write (tag, PCI_PCI_BRIDGE_BUS_REG, data);
-
- /*
- ** Propagate the new upper bus number limit.
- */
- for (parent = pcicb->pcicb_up; parent != NULL;
- parent = parent->pcicb_up)
- {
- if (parent->pcicb_subordinate >= pcicb->pcicb_bus)
- continue;
- parent->pcicb_subordinate = pcicb->pcicb_bus;
- if (!parent->pcicb_bridge.tag)
- continue;
- data = pci_conf_read
- (parent->pcicb_bridge, PCI_PCI_BRIDGE_BUS_REG);
- data = PCI_SUBORDINATE_BUS_INSERT
- (data, pcicb->pcicb_bus);
- pci_conf_write (parent->pcicb_bridge,
- PCI_PCI_BRIDGE_BUS_REG, data);
- }
- }
-
- if (!pcicb->pcicb_membase) {
- u_int size = 0x100000;
- pcicb->pcicb_membase = pci_memalloc (pcicb->pcicb_up, 0, size);
- if (pcicb->pcicb_membase)
- pcicb->pcicb_memlimit = pcicb->pcicb_membase+size-1;
- }
- }
- return pcicb->pcicb_bus;
-}
-
-/*========================================================
-**
-** pci_attach()
-**
-** Attach one device
-**
-**========================================================
-*/
-
-static void pci_attach (int bus, int dev, int func,
- struct pci_device *dvp, const char *name)
-{
- u_long data;
- int unit;
- u_char reg;
- u_char pciint;
- int irq;
-#if defined(APIC_IO)
- u_char airq = 0xff;
- u_char rirq = 0xff;
-#endif /* APIC_IO */
- pcici_t tag = pcibus->pb_tag (bus, dev, func);
-
- /*
- ** Get and increment the unit.
- */
-
- unit = (*dvp->pd_count)++;
-
- /*
- ** Announce this device
- */
-
- printf ("%s%d <%s> rev %d", dvp->pd_name, unit, name,
- (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff);
-
- /*
- ** Get the int pin number (pci interrupt number a-d)
- ** from the pci configuration space.
- */
-
- data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
-
- if (pciint) {
-
- printf (" int %c irq ", 0x60+pciint);
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(data);
-
- /*
- ** If it's zero, the isa irq number is unknown,
- ** and we cannot bind the pci interrupt.
- */
-
-#if defined(APIC_IO)
- if (irq && (irq != 0xff)) {
- airq = get_pci_apic_irq (bus, dev, pciint);
- if (airq != 0xff) { /* APIC IRQ exists */
- rirq = irq; /* 're-directed' IRQ */
- irq = airq; /* use APIC IRQ */
- }
- printf ("%d", irq);
- }
-#else
- if (irq && (irq != 0xff))
- printf ("%d", irq);
-#endif /* APIC_IO */
- else
- printf ("??");
+pci_maptype(unsigned mapreg)
+{
+ static u_int8_t maptype[0x10] = {
+ PCI_MAPMEM, PCI_MAPPORT,
+ PCI_MAPMEM, 0,
+ PCI_MAPMEM, PCI_MAPPORT,
+ 0, 0,
+ PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT,
+ PCI_MAPMEM|PCI_MAPMEMP, 0,
+ PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT,
+ 0, 0,
};
- printf (" on pci%d:%d:%d\n", bus, dev, func);
-
-#if defined(APIC_IO)
- if (airq != 0xff) { /* APIC IRQ exists */
- data = PCI_INTERRUPT_LINE_INSERT(data, airq);
- pci_conf_write (tag, PCI_INTERRUPT_REG, data);
- undirect_pci_irq (rirq); /* free for ISA card */
- }
-#endif /* APIC_IO */
-
- /*
- ** Read the current mapping,
- ** and update the pcicb fields.
- */
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
- data &= (PCI_CLASS_MASK|PCI_SUBCLASS_MASK);
- switch (data) {
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
- break;
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_CARDBUS: {
- u_int map, addr, size;
- map = pci_conf_read(tag, PCI_CARDBUS_SOCKET_REG);
- pci_conf_write (tag, PCI_CARDBUS_SOCKET_REG, 0xffffffff);
- size = pci_conf_read(tag, PCI_CARDBUS_SOCKET_REG);
- size = (~size) + 1;
- addr = pci_memalloc (pcicb, map, size);
- pci_conf_write (tag, PCI_CARDBUS_SOCKET_REG, addr);
- pcicb->pcicb_mamount += size;
- break;
- }
- default:
- for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4) {
- u_int map, addr, size;
-
-
- map = pci_conf_read (tag, reg);
- if (!(map & PCI_MAP_MEMORY_ADDRESS_MASK))
- continue;
-
- pci_conf_write (tag, reg, 0xffffffff);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, map);
-
- switch (data & 7) {
-
- default:
- continue;
- case 1:
- case 5:
- addr = map & PCI_MAP_IO_ADDRESS_MASK;
- size = -(data & PCI_MAP_IO_ADDRESS_MASK);
- size &= ~(addr ^ -addr);
-
- pci_register_io (pcicb, addr, addr+size-1);
- pcicb->pcicb_pamount += size;
- break;
-
- case 0:
- case 2:
- case 4:
- size = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
- addr = map & PCI_MAP_MEMORY_ADDRESS_MASK;
- if (addr >= 0x100000) {
- pci_register_memory (pcicb, addr, addr+size-1);
- pcicb->pcicb_mamount += size;
- };
- break;
- }
- if (bootverbose)
- printf ("\tmapreg[%02x] type=%d addr=%08x size=%04x.\n",
- reg, map&7, addr, size);
- }
- }
-
- /*
- ** attach device
- ** may produce additional log messages,
- ** i.e. when installing subdevices.
- */
-
- (*dvp->pd_attach) (tag, unit);
-
- /*
- ** Special processing of certain classes
- */
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
-
- switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
- struct pcicb *this, **link;
- unsigned char primary, secondary, subordinate;
- u_int command;
-
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
-
- /*
- ** get current configuration of the bridge.
- */
- data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
- primary = PCI_PRIMARY_BUS_EXTRACT (data);
- secondary = PCI_SECONDARY_BUS_EXTRACT(data);
- subordinate = PCI_SUBORDINATE_BUS_EXTRACT(data);
-#ifndef PCI_QUIET
- if (bootverbose) {
- printf ("\tbridge from pci%d to pci%d through %d.\n",
- primary, secondary, subordinate);
- printf ("\tmapping regs: io:%08lx mem:%08lx pmem:%08lx\n",
- pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG));
- }
-#endif
- /*
- ** check for uninitialized bridge.
- */
- if (!(primary < secondary
- && secondary <= subordinate
- && bus == primary)) {
-
- printf ("\tINCORRECTLY or NEVER CONFIGURED.\n");
- /*
- ** disable this bridge
- */
- pci_conf_write (tag, PCI_COMMAND_STATUS_REG, 0xffff0000);
- secondary = 0;
- subordinate = 0;
- };
-
- /*
- ** allocate bus descriptor for bus behind the bridge
- */
- link = &pcicb->pcicb_down;
- while (*link && (*link)->pcicb_bus < secondary)
- link = &(*link)->pcicb_next;
-
- this = malloc (sizeof (*this), M_DEVBUF, M_WAITOK);
-
- /*
- ** Initialize this descriptor so far.
- ** (the initialization is completed just before
- ** scanning the bus behind the bridge.
- */
- bzero (this, sizeof(*this));
- this->pcicb_next = *link;
- this->pcicb_up = pcicb;
- this->pcicb_bridge = tag;
- this->pcicb_bus = secondary;
- this->pcicb_subordinate = subordinate;
-
- command = pci_conf_read(tag,PCI_COMMAND_STATUS_REG);
-
- if (command & PCI_COMMAND_IO_ENABLE){
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped io region.
- */
- unsigned reg;
-
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG);
- this->pcicb_iobase = PCI_PPB_IOBASE_EXTRACT (reg);
- this->pcicb_iolimit = PCI_PPB_IOLIMIT_EXTRACT(reg);
-
- /*
- ** Note the used io space.
- */
- pci_register_io (pcicb, this->pcicb_iobase,
- this->pcicb_iolimit);
-
- };
-
- if (command & PCI_COMMAND_MEM_ENABLE) {
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped memory regions.
- */
- unsigned reg;
-
- /*
- ** non prefetchable memory
- */
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG);
- this->pcicb_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_membase,
- this->pcicb_memlimit);
-
- /*
- ** prefetchable memory
- */
- reg = pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG);
- this->pcicb_p_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_p_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_p_membase,
- this->pcicb_p_memlimit);
- }
-
- /*
- ** Link it in chain.
- */
- *link=this;
-
- /*
- ** Update mapping info of parent bus.
- */
- if (!pcicb->pcicb_bfrom||secondary< pcicb->pcicb_bfrom)
- pcicb->pcicb_bfrom = secondary;
- if (subordinate > pcicb->pcicb_bupto)
- pcicb->pcicb_bupto = subordinate;
- }
+ return maptype[mapreg & 0x0f];
}
-/*========================================================
-**
-** pci_bus_config()
-**
-** Autoconfiguration of one pci bus.
-**
-**========================================================
-*/
+/* return log2 of map size decoded for memory or port map */
static int
-pci_mfdev (int bus, int device)
+pci_mapsize(unsigned testval)
{
- pcici_t tag0,tag1;
- unsigned pci_id0, pci_id1;
-
- /*
- ** Detect a multi-function device that complies to the PCI 2.0 spec
- */
- tag0 = pcibus->pb_tag (bus, device, 0);
- if (pci_conf_read (tag0, PCI_HEADER_MISC) & PCI_HEADER_MULTIFUNCTION)
- return 1;
-
- /*
- ** Well, as always: Theory and implementation of PCI ...
- **
- ** If there is a valid device ID returned for function 1 AND
- ** the device ID of function 0 and 1 is different OR
- ** the first mapping register of 0 and 1 differs,
- ** then assume a multi-function device anyway ...
- **
- ** Example of such a broken device: ISA and IDE chip i83371FB (Triton)
- */
- tag1 = pcibus->pb_tag (bus, device, 1);
- pci_id1 = pci_conf_read (tag1, PCI_ID_REG);
-
- if (pci_id1 != 0xffffffff) {
-
- pci_id0 = pci_conf_read (tag0, PCI_ID_REG);
-
- if (pci_id0 != pci_id1)
- return 1;
-
- if (pci_conf_read (tag0, PCI_MAP_REG_START)
- != pci_conf_read (tag1, PCI_MAP_REG_START))
- return 1;
- }
- return 0;
-}
+ int ln2size;
-static void
-pci_bus_config (void)
-{
- int bus_no;
- u_char device;
- u_char reg;
- pcici_t tag, mtag;
- pcidi_t type;
-
- struct pci_device *dvp;
-
- /*
- ** first initialize the bridge (bus controller chip)
- */
- bus_no = pci_bridge_config ();
-
- printf ("Probing for devices on PCI bus %d:\n", bus_no);
-#ifndef PCI_QUIET
- if (bootverbose && !pci_info_done) {
- pci_info_done=1;
- printf ("\tconfiguration mode %d allows %d devices.\n",
- pci_mechanism, pci_maxdevice);
- };
-#endif
- for (device=0; device<pci_maxdevice; device ++) {
- char *name = NULL;
- struct pci_device **dvpp;
- int func, maxfunc = 0;
-
- for (func=0; func <= maxfunc; func++) {
- tag = pcibus->pb_tag (bus_no, device, func);
- type = pci_conf_read (tag, PCI_ID_REG);
-
- if ((!type) || (type==0xfffffffful)) continue;
-
- /*
- ** lookup device in ioconfiguration:
- */
-
- dvpp = (struct pci_device **)pcidevice_set.ls_items;
-
- while (dvp = *dvpp++) {
- if (dvp->pd_probe) {
- if (name=(*dvp->pd_probe)(tag, type))
- break;
- }
- };
- /*
- ** check for mirrored devices.
- */
- if (func != 0) {
- goto real_device;
- }
- if (device & 0x10) {
- mtag=pcibus->pb_tag (bus_no,
- (u_char)(device & ~0x10), 0);
- } else if (device & 0x08) {
- mtag=pcibus->pb_tag (bus_no,
- (u_char)(device & ~0x08), 0);
- } else goto real_device;
-
- if (type!=pci_conf_read (mtag, PCI_ID_REG))
- goto real_device;
-
- for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4)
- if (pci_conf_read(tag,reg)!=pci_conf_read(mtag,reg))
- goto real_device;
-
-#ifndef PCI_QUIET
- if (dvp==NULL) continue;
- if (bootverbose)
- printf ("%s? <%s> mirrored on pci%d:%d\n",
- dvp->pd_name, name, bus_no, device);
-#endif
- continue;
-
- real_device:
-
-#ifndef PCI_QUIET
-#ifdef PCI_BRIDGE_DEBUG
- if (bootverbose) {
- printf ("\tconfig header: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- pci_conf_read (tag, 0),
- pci_conf_read (tag, 4),
- pci_conf_read (tag, 8),
- pci_conf_read (tag, 12));
- }
-#endif
-#endif
-
- if (func == 0 && pci_mfdev (bus_no, device)) {
- maxfunc = 7;
- }
-
- pci_remember(bus_no, device, func, dvp);
-
- if (dvp==NULL) {
-#ifndef PCI_QUIET
- if (pci_conf_count)
- continue;
-
- if (maxfunc == 0)
- printf("%s%d:%d: ",
- pcibus->pb_name, bus_no, device);
- else
- printf("%s%d:%d:%d: ",
- pcibus->pb_name, bus_no, device, func);
- not_supported (tag, type);
-#endif
- continue;
- };
-
- if (*name) {
- pci_attach (bus_no, device, func, dvp, name);
- }
- }
- }
-
-#ifndef PCI_QUIET
- if (bootverbose) {
- if (pcicb->pcicb_mamount)
- printf ("%s%d: uses %ud bytes of memory from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_mamount,
- pcicb->pcicb_mfrom, pcicb->pcicb_mupto);
- if (pcicb->pcicb_pamount)
- printf ("%s%d: uses %ud bytes of I/O space from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_pamount,
- pcicb->pcicb_pfrom, pcicb->pcicb_pupto);
- if (pcicb->pcicb_bfrom)
- printf ("%s%d: subordinate busses from %x upto %x.\n",
- pcibus->pb_name, bus_no,
- pcicb->pcicb_bfrom, pcicb->pcicb_bupto);
+ testval = pci_mapbase(testval);
+ ln2size = 32;
+ while ((testval & 0x80000000) != 0)
+ {
+ ln2size--;
+ testval <<= 1;
}
-#endif
+ return (ln2size);
}
-/*========================================================
-**
-** pci_configure ()
-**
-** Autoconfiguration of pci devices.
-**
-** Has to take care of mirrored devices, which are
-** entailed by incomplete decoding of pci address lines.
-**
-**========================================================
-*/
-
-void pci_configure()
-{
- struct pcibus **pbp = (struct pcibus**) pcibus_set.ls_items;
-
- /*
- ** check pci bus present
- */
+/* return log2 of address range supported by map register */
- while (!pci_maxdevice && (pcibus = *pbp++)) {
- (*pcibus->pb_setup)();
- }
-
- if (!pci_maxdevice) return;
-
- /*
- ** hello world ..
- */
-
- pciroots = 1;
- while (pciroots--) {
-
- pcicb = malloc (sizeof (struct pcicb), M_DEVBUF, M_WAITOK);
- if (pcicb == NULL) {
- return;
- }
- bzero (pcicb, sizeof (struct pcicb));
- pcicb->pcicb_bus = pcibusmax;
- pcicb->pcicb_iolimit = 0xffff;
- pcicb->pcicb_membase = 0x02000000;
- pcicb->pcicb_p_membase = 0x02000000;
- pcicb->pcicb_memlimit = 0xffffffff;
- pcicb->pcicb_p_memlimit = 0xffffffff;
-
- while (pcicb != NULL) {
- pci_bus_config ();
-
- if (pcibusmax < pcicb->pcicb_bus)
- (pcibusmax = pcicb->pcicb_bus);
-
- if (pcicb->pcicb_down) {
- pcicb = pcicb->pcicb_down;
- continue;
- };
-
- while (pcicb && !pcicb->pcicb_next)
- pcicb = pcicb->pcicb_up;
-
- if (pcicb)
- pcicb = pcicb->pcicb_next;
- }
- pcibusmax++;
+static int
+pci_maprange(unsigned mapreg)
+{
+ int ln2range = 0;
+ switch (mapreg & 0x07) {
+ case 0x00:
+ case 0x01:
+ case 0x05:
+ ln2range = 32;
+ break;
+ case 0x02:
+ ln2range = 20;
+ break;
+ case 0x04:
+ ln2range = 64;
+ break;
}
- pci_conf_count++;
+ return (ln2range);
}
-/*========================================================
-**
-** pci_rescan ()
-**
-** try to find lkm driver for device
-**
-** May be called more than once.
-** Any device is attached only once.
-**
-**========================================================
-*/
-
-static void pci_rescan()
+/* extract map parameters into newly allocated array of pcimap structures */
+
+static pcimap *
+pci_readmaps(pcicfgregs *cfg, int maxmaps)
{
int i;
- for (i = 0; i < pci_dev_list_count; i++)
- {
- struct pci_lkm *lkm;
- pcici_t tag;
- struct pci_device *dvp;
- pcidi_t type = pci_dev_list[i].pc_devid;
- char *name = NULL;
- int bus, dev, func;
-
- if (pci_dev_list[i].pc_dvp)
- continue;
-
- bus = pci_dev_list[i].pc_sel.pc_bus;
- dev = pci_dev_list[i].pc_sel.pc_dev;
- func = pci_dev_list[i].pc_sel.pc_func;
-
- tag = pcibus->pb_tag (bus, dev, func);
-
- for (lkm = pci_lkm_head; lkm; lkm = lkm->next) {
- dvp = lkm->dvp;
- if (name=(*dvp->pd_probe)(tag, type))
- break;
- }
- if (name && *name) {
- pcicb = pci_dev_list[i].pc_cb;
- pci_attach (bus, dev, func, dvp, name);
- pci_dev_list[i].pc_dvp = dvp;
+ pcimap *map;
+ int map64 = 0;
+
+ while (maxmaps > 0
+ && pci_cfgread(cfg, PCIR_MAPS + (maxmaps -1) *4, 4) == 0)
+ maxmaps--;
+
+ map = malloc(maxmaps * sizeof (pcimap), M_DEVBUF, M_WAITOK);
+ if (map != NULL) {
+ bzero(map, sizeof(pcimap) * maxmaps);
+
+ for (i = 0; i < maxmaps; i++) {
+ int reg = PCIR_MAPS + i*4;
+ u_int32_t base;
+ u_int32_t testval;
+
+ base = pci_cfgread(cfg, reg, 4);
+
+ if (map64 == 0) {
+ pci_cfgwrite(cfg, reg, 0xffffffff, 4);
+ testval = pci_cfgread(cfg, reg, 4);
+ pci_cfgwrite(cfg, reg, base, 4);
+
+ map[i].base = pci_mapbase(base);
+ map[i].type = pci_maptype(base);
+ map[i].ln2size = pci_mapsize(testval);
+ map[i].ln2range = pci_maprange(testval);
+ map64 = map[i].ln2range == 64;
+ } else {
+ /* only fill in base, other fields are 0 */
+ map[i].base = base;
+ map64 = 0;
+ }
+ if (map[i].type == 0) {
+ /*
+ * This indicates, that some config space register
+ * was mistaken to contain a map, while it in fact
+ * contains unrelated information!
+ * Ignore this map and all that might have been
+ * expected to follow ...
+ */
+ maxmaps = i;
+ }
}
+ cfg->nummaps = maxmaps;
}
+ return (map);
}
-/*========================================================
-**
-** pci_register_lkm ()
-**
-** Add LKM PCI driver's struct pci_device to pci_lkm chain
-**
-**========================================================
-*/
+/* adjust some values from PCI 1.0 devices to match 2.0 standards ... */
-int pci_register_lkm (struct pci_device *dvp, int if_revision)
+static void
+pci_fixancient(pcicfgregs *cfg)
{
- struct pci_lkm *lkm;
-
- if (if_revision != 0) {
- return -1;
- }
-
- if (!dvp || !dvp->pd_probe || !dvp->pd_attach) {
- return -1;
- }
-
- lkm = malloc (sizeof (*lkm), M_DEVBUF, M_WAITOK);
- if (!lkm) {
- return -1;
- }
+ if (cfg->hdrtype != 0)
+ return;
- lkm->dvp = dvp;
- lkm->next = pci_lkm_head;
- pci_lkm_head = lkm;
- pci_rescan();
- return 0;
+ /* PCI to PCI bridges use header type 1 */
+ if (cfg->class == PCIC_BRIDGE && cfg->subclass == PCIS_BRIDGE_PCI)
+ cfg->hdrtype = 1;
}
-/*-----------------------------------------------------------------------
-**
-** Map device into port space.
-**
-** Actually the device should have been mapped by the bios.
-** This function only reads and verifies the value.
-**
-** PCI-Specification: 6.2.5.1: address maps
-**
-**-----------------------------------------------------------------------
-*/
-
-int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
+/* read config data specific to header type 1 device (PCI to PCI bridge) */
+
+static void *
+pci_readppb(pcicfgregs *cfg)
{
- unsigned data, ioaddr, iosize;
- struct pcicb *link = pcicb;
+ pcih1cfgregs *p;
- /*
- ** sanity check
- */
+ p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK);
+ if (p == NULL)
+ return (NULL);
- if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
- printf ("pci_map_port failed: bad register=0x%x\n",
- (unsigned)reg);
- return (0);
- };
+ bzero(p, sizeof *p);
- /*
- ** get size and type of port
- **
- ** type is in the lowest two bits.
- ** If device requires 2^n bytes, the next
- ** n-2 bits are hardwired as 0.
- */
-
- ioaddr = pci_conf_read (tag, reg) & PCI_MAP_IO_ADDRESS_MASK;
- if (!ioaddr) {
- printf ("pci_map_port failed: not configured by bios.\n");
- return (0);
- };
+ p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
+ p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
- pci_conf_write (tag, reg, 0xfffffffful);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, ioaddr);
+ p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
- if ((data & 0x03) != PCI_MAP_IO) {
- printf ("pci_map_port failed: bad port type=0x%x\n",
- (unsigned) data);
- return (0);
- };
- iosize = -(data & PCI_MAP_IO_ADDRESS_MASK);
- iosize &= ~(ioaddr ^ -ioaddr);
- if (ioaddr < pcicb->pcicb_iobase
- || ioaddr + iosize -1 > pcicb->pcicb_iolimit) {
- printf ("pci_map_port failed: device's iorange 0x%x-0x%x "
- "is incompatible with its bridge's range 0x%x-0x%x\n",
- (unsigned) ioaddr, (unsigned) ioaddr + iosize - 1,
- (unsigned) pcicb->pcicb_iobase,
- (unsigned) pcicb->pcicb_iolimit);
- return (0);
- }
+ 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));
-#ifndef PCI_QUIET
- if (bootverbose)
- printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
- (unsigned) reg, (unsigned) ioaddr, (unsigned) iosize);
-#endif
- /*
- ** set the configuration register of and
- ** return the address to the driver.
- ** Make sure to enable each upstream bridge
- ** so I/O and DMA can go all the way.
- */
-
- for (;;) {
- data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff;
- data |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE;
- (void) pci_conf_write(tag, PCI_COMMAND_STATUS_REG, data);
- if ((link = link->pcicb_up) == NULL)
- break;
- tag = link->pcicb_bridge;
- }
+ p->membase = PCI_PPBMEMBASE (0,
+ pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
+ p->memlimit = PCI_PPBMEMLIMIT (0,
+ pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
- *pa = ioaddr;
+ p->pmembase = PCI_PPBMEMBASE (
+ (pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
+ pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
- return (1);
+ p->pmemlimit = PCI_PPBMEMLIMIT (
+ (pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
+ pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
+ return (p);
}
-/*-----------------------------------------------------------------------
-**
-** Map device into virtual and physical space
-**
-** Actually the device should have been mapped by the bios.
-** This function only reads and verifies the value.
-**
-** PCI-Specification: 6.2.5.1: address maps
-**
-**-----------------------------------------------------------------------
-*/
-
-int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
-{
- struct pcicb *link = pcicb;
- unsigned data ,paddr;
- vm_size_t psize, poffs;
- vm_offset_t vaddr;
-
- /*
- ** sanity check
- */
-
- if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
- printf ("pci_map_mem failed: bad register=0x%x\n",
- (unsigned)reg);
- return (0);
- };
-
- /*
- ** save old mapping, get size and type of memory
- **
- ** type is in the lowest four bits.
- ** If device requires 2^n bytes, the next
- ** n-4 bits are read as 0.
- */
-
- paddr = pci_conf_read (tag, reg) & PCI_MAP_MEMORY_ADDRESS_MASK;
- pci_conf_write (tag, reg, 0xfffffffful);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, paddr);
-
- /*
- ** check the type
- */
-
- if (!((data & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M
- && (paddr & ~0xfffff) == 0)
- && (data & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT){
- printf ("pci_map_mem failed: bad memory type=0x%x\n",
- (unsigned) data);
- return (0);
- };
-
- /*
- ** get the size.
- */
-
- psize = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
-
- if (!paddr || paddr == PCI_MAP_MEMORY_ADDRESS_MASK) {
- paddr = pci_memalloc (pcicb, 0, psize);
- if (!paddr) {
- printf ("pci_map_mem: not configured by bios.\n");
- return (0);
- };
- pci_register_memory (pcicb, paddr, paddr+psize-1);
- };
+/* read config data specific to header type 2 device (PCI to CardBus bridge) */
- if (paddr < pcicb->pcicb_membase ||
- paddr + psize - 1 > pcicb->pcicb_memlimit) {
- printf ("pci_map_mem failed: device's memrange 0x%x-0x%x is "
- "incompatible with its bridge's memrange 0x%x-0x%x\n",
- (unsigned) paddr,
- (unsigned) (paddr + psize - 1),
- (unsigned) pcicb->pcicb_membase,
- (unsigned) pcicb->pcicb_memlimit);
-/* return (0);*/
-/* ACHTUNG: Ist der Code richtig, wenn eine PCI-PCI-Bridge fuer
- * die PCI-Slots verwendet wird, aber die Onboard-Devices direkt
- * an der CPU-PCI-Bridge haengen (Siehe Compaq Prolinea Problem) ???
- */
- }
- pci_conf_write (tag, reg, paddr);
-
- /*
- ** Truncate paddr to page boundary.
- ** (Or does pmap_mapdev the job?)
- */
+static void *
+pci_readpcb(pcicfgregs *cfg)
+{
+ pcih2cfgregs *p;
- poffs = paddr - trunc_page (paddr);
- vaddr = (vm_offset_t) pmap_mapdev (paddr-poffs, psize+poffs);
+ p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK);
+ if (p == NULL)
+ return (NULL);
- if (!vaddr) return (0);
+ bzero(p, sizeof *p);
- vaddr += poffs;
+ p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
+ p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
+
+ p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
-#ifndef PCI_QUIET
- /*
- ** display values.
- */
+ 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);
- if (bootverbose)
- printf ("\treg%d: virtual=0x%lx physical=0x%lx size=0x%lx\n",
- (unsigned) reg, (u_long)vaddr, (u_long)paddr, (u_long)psize);
-#endif
- /*
- ** set the configuration register and
- ** return the address to the driver
- ** Make sure to enable each upstream bridge
- ** so memory and DMA can go all the way.
- */
-
- for (;;) {
- data = pci_conf_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff;
- data |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
- (void) pci_conf_write(tag, PCI_COMMAND_STATUS_REG, data);
- if ((link = link->pcicb_up) == NULL)
- break;
- tag = link->pcicb_bridge;
- }
+ 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);
- *va = vaddr;
- *pa = paddr;
-
- return (1);
+ p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
+ return p;
}
-/*-----------------------------------------------------------------------
-**
-** Pci meta interrupt handler
-**
-** This handler assumes level triggered interrupts.
-** It's possible to build a kernel which handles shared
-** edge triggered interrupts by the options "PCI_EDGE_INT".
-** But there is a performance penalty.
-**
-** (Of course you can delete the #ifdef PCI_EDGE_INT bracketed
-** code at all :-) :-) :-)
-**
-**-----------------------------------------------------------------------
-*/
-
-static struct pci_int_desc*
- pci_int_desc [PCI_MAX_IRQ];
-
-#ifndef NO_SHARED_IRQ
-
-static inline unsigned
-splq (unsigned mask)
-{
- unsigned temp=cpl;
- cpl |= mask;
- return temp;
-}
+/* extract header type specific config data */
static void
-pci_int (int irq)
+pci_hdrtypedata(pcicfgregs *cfg)
{
- struct pci_int_desc * p;
- int s;
-
- if (irq<0 || irq >= PCI_MAX_IRQ) {
- printf ("pci_int: irq %d out of range, ignored\n", irq);
- return;
- };
- for (p = pci_int_desc[irq]; p!=NULL; p=p->pcid_next) {
- s = splq (*p->pcid_maskptr);
- (*p->pcid_handler) (p->pcid_argument);
- p-> pcid_tally++;
- splx (s);
-#if 0
- if (p->pcid_tally<20)
- printf ("PCI_INT: irq=%d h=%p cpl o=%x n=%x val=%d\n",
- irq, p->pcid_handler, s, cpl, c);
-#endif
- };
-}
-#endif
-
-/*-----------------------------------------------------------------------
-**
-** Auxiliary function for interrupt (un)mapping.
-**
-**-----------------------------------------------------------------------
-*/
-
-static u_int
-getirq (pcici_t tag)
-{
- u_int irq;
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(
- pci_conf_read (tag, PCI_INTERRUPT_REG));
-
- if (irq == 0 || irq == 0xff) {
- printf ("\tint line register not set by bios\n");
- return (0xff);
+ switch (cfg->hdrtype) {
+ case 0:
+ cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
+ cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
+ cfg->map = pci_readmaps(cfg, 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->map = pci_readmaps(cfg, PCI_MAXMAPS_1);
+ cfg->hdrspec = pci_readppb(cfg);
+ 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->map = pci_readmaps(cfg, PCI_MAXMAPS_2);
+ cfg->hdrspec = pci_readpcb(cfg);
+ break;
}
+}
- if (irq >= PCI_MAX_IRQ) {
- printf ("\tirq %d out of bounds (must be < %d).\n",
- irq, PCI_MAX_IRQ);
- return (0xff);
+/* read configuration header into pcicfgrect structure */
+
+static pcicfgregs *
+pci_readcfg(pcicfgregs *probe)
+{
+ pcicfgregs *cfg = NULL;
+
+ if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
+ cfg = malloc(sizeof (pcicfgregs), M_DEVBUF, M_WAITOK);
+ if (cfg == NULL)
+ return (cfg);
+
+ bzero(cfg, sizeof *cfg);
+
+ cfg->bus = probe->bus;
+ cfg->slot = probe->slot;
+ cfg->func = probe->func;
+ cfg->parent = probe->parent;
+
+ 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->class = 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->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
+ cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
+
+ cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
+ cfg->hdrtype &= ~PCIM_MFDEV;
+
+ pci_fixancient(cfg);
+ pci_hdrtypedata(cfg);
}
-
- return (irq);
+ return (cfg);
}
-static struct pci_int_desc **
-getintdescbytag (u_int irq, pcici_t tag)
-{
- struct pci_int_desc *p, **pp;
-
- pp=&pci_int_desc[irq];
- while (((p=*pp)) && !sametag(p->pcid_tag,tag))
- pp=&p->pcid_next;
-
- if (!p) return (NULL);
+/* free pcicfgregs structure and all depending data structures */
- return (pp);
-}
-
-static struct pci_int_desc *
-getintdescbymptr (u_int irq, unsigned * mptr)
+static int
+pci_freecfg(pcicfgregs *cfg)
{
- struct pci_int_desc *p;
-
- for (p=pci_int_desc[irq];p;p=p->pcid_next)
- if (p->pcid_maskptr == mptr) break;
- return (p);
+ if (cfg->hdrspec != NULL)
+ free(cfg->hdrspec, M_DEVBUF);
+ if (cfg->map != NULL)
+ free(cfg->map, M_DEVBUF);
+ free(cfg, M_DEVBUF);
+ return (0);
}
-/*-----------------------------------------------------------------------
-**
-** Map pci interrupt.
-**
-**-----------------------------------------------------------------------
-*/
-
-static unsigned pci_mask0 = 0;
-
-int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg, unsigned *maskptr)
+static void
+pci_addcfg(pcicfgregs *cfg)
{
- u_int irq;
- int result, oldspl;
- unsigned mask;
- struct pci_int_desc *tail, *mdp=NULL, *new=NULL;
-
- /*
- ** Get irq line from configuration space,
- ** and check for consistency.
- */
-
- irq = getirq (tag);
- if (irq == 0xff) {
- return (0);
- };
- mask= 1ul << irq;
-
- /*
- ** disable this interrupt.
- */
-
- oldspl = splq (mask);
-
- /*
- ** If handler for this tag already installed,
- ** remove it first.
- */
-
- if (getintdescbytag (irq, tag) != NULL)
- pci_unmap_int (tag);
-
- /*
- ** If this irq not yet included in the mask, include it.
- */
-
- mdp = getintdescbymptr (irq, maskptr);
- if (!mdp) {
- result = pcibus->pb_imaskinc (irq, maskptr);
- if (result)
- goto conflict;
- };
-
- /*
- ** Allocate descriptor and initialize it.
- */
-
- tail = pci_int_desc[irq];
-
- new = malloc (sizeof (*new), M_DEVBUF, M_WAITOK);
- bzero (new, sizeof (*new));
-
- new->pcid_next = tail;
- new->pcid_tag = tag;
- new->pcid_handler = func;
- new->pcid_argument = arg;
- new->pcid_maskptr = maskptr;
- new->pcid_tally = 0;
- new->pcid_mask = mask;
-
- /*
- ** If first handler: install it.
- ** If second handler: install shared-int-handler.
- */
-
- if (!tail) {
- /*
- ** first handler for this irq.
- */
-
- result = pcibus->pb_iattach
- /*
- * XXX if we get here, then `func' must be pci_int
- * so the bogus casts are almost OK since they just
- * undo the bogus casts that were needed to pass
- * pci_int and its arg to pci_map_int().
- */
- (irq, (inthand2_t *) func, (int) arg, maskptr);
- if (result) goto conflict;
-
-#ifdef NO_SHARED_IRQ
- } else goto conflict;
-#else
- } else if (!tail->pcid_next) {
- /*
- ** Second handler for this irq.
- */
-
- if (bootverbose)
- printf ("\tusing shared irq %d.\n", irq);
-
- /*
- ** replace old handler by shared-int-handler.
- */
-
- result = pcibus->pb_idetach (irq,
- (inthand2_t *) tail->pcid_handler);
- if (result)
- printf ("\tCANNOT DETACH INT HANDLER.\n");
-
- result = pcibus->pb_iattach (irq, pci_int, irq, &pci_mask0);
- if (result) {
- printf ("\tCANNOT ATTACH SHARED INT HANDLER.\n");
- goto fail;
- };
+#ifdef PCI_DEBUG
+ if (bootverbose) {
+ int i;
+ printf("new pci: vendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
+ cfg->vendor, cfg->device, cfg->revid);
+ printf("\t cmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
+ cfg->cmdreg, cfg->statreg, cfg->cachelnsz);
+ printf("\t class=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
+ cfg->class, cfg->subclass, cfg->progif, cfg->hdrtype, cfg->mfdev);
+ printf("\t lattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n",
+ cfg->lattimer, cfg->lattimer * 30,
+ cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250);
+
+ if (cfg->intpin > 0)
+ printf("\t intpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
+
+ for (i = 0; i < cfg->nummaps; i++) {
+ pcimap *m = &cfg->map[i];
+ printf("\t map[%d]: type %x, range %2d, base %08x, size %2d\n",
+ i, m->type, m->ln2range, m->base, m->ln2size);
+ }
}
-#endif
- /*
- ** Link new descriptor, reenable ints and done.
- */
-
- pci_int_desc[irq] = new;
- splx (oldspl);
- return (1);
-
- /*
- ** Handle some problems.
- */
-
-conflict:
- printf ("\tirq %d already in use.\n", irq);
-fail:
- /*
- ** If descriptor allocated, free it.
- ** If included in mask, remove it.
- */
-
- if (new) free(new, M_DEVBUF);
- if (!mdp) (void) pcibus->pb_imaskexc (irq, maskptr);
- splx (oldspl);
- return (0);
+#endif /* PCI_DEBUG */
+ pci_drvattach(cfg); /* XXX currently defined in pci_compat.c */
}
-/*-----------------------------------------------------------------------
-**
-** Unmap pci interrupt.
-**
-**-----------------------------------------------------------------------
-*/
+/* return pointer to device that is a bridge to this bus */
-int pci_unmap_int (pcici_t tag)
+static pcicfgregs *
+pci_bridgeto(int bus)
{
- int result, oldspl;
- struct pci_int_desc *this, **hook, *tail;
- unsigned irq;
-
- /*
- ** Get irq line from configuration space,
- ** and check for consistency.
- */
-
- irq = getirq (tag);
- if (irq == 0xff) {
- return (0);
- };
-
- /*
- ** Search and unlink interrupt descriptor.
- */
-
- hook = getintdescbytag (irq, tag);
- if (hook == NULL) {
- printf ("\tno irq %d handler for pci %x\n",
- irq, tag.tag);
- return (0);
- };
-
- this = *hook;
- *hook= this->pcid_next;
-
- /*
- ** Message
- */
-
- printf ("\tirq %d handler %p(%p) unmapped for pci %x after %d ints.\n",
- irq, this->pcid_handler, this->pcid_argument,
- this->pcid_tag.tag, this->pcid_tally);
-
- /*
- ** If this irq no longer included in the mask, remove it.
- */
-
- if (!getintdescbymptr (irq, this->pcid_maskptr))
- (void) pcibus->pb_imaskexc (irq, this->pcid_maskptr);
-
- tail = pci_int_desc[irq];
-
- if (tail == NULL) {
-
- /*
- ** Remove the old handler.
- */
-
- result = pcibus->pb_idetach (irq,
- (inthand2_t *) this->pcid_handler);
- if (result)
- printf ("\tirq %d: cannot remove handler.\n", irq);
-
- } else if (tail->pcid_next == NULL) {
-
- /*
- ** Remove the shared int handler.
- ** Install the last remaining handler.
- */
-
- oldspl = splq (1ul << irq);
-
- result = pcibus->pb_idetach (irq, pci_int);
- if (result)
- printf ("\tirq %d: cannot remove handler.\n", irq);
-
- result = pcibus->pb_iattach (irq,
- (inthand2_t *) tail->pcid_handler,
- (int) tail->pcid_argument,
- tail->pcid_maskptr);
-
- if (result)
- printf ("\tirq %d: cannot install handler.\n", irq);
-
- splx (oldspl);
- };
-
- free (this, M_DEVBUF);
- return (1);
+ return (NULL); /* XXX not yet implemented */
}
-/*-----------------------------------------------------------
-**
-** Display of unknown devices.
-**
-**-----------------------------------------------------------
-*/
-struct vt {
- u_short ident;
- char* name;
-};
-
-static struct vt VendorTable[] = {
- {0x0e11, "Compaq"},
- {0x1000, "NCR/Symbios"},
- {0x1002, "ATI Technologies Inc."},
- {0x1004, "VLSI"},
- {0x100B, "National Semiconductor"},
- {0x100E, "Weitek"},
- {0x1011, "Digital Equipment Corporation"},
- {0x1013, "Cirrus Logic"},
- {0x101A, "NCR"},
- {0x1022, "AMD"},
- {0x102B, "Matrox"},
- {0x102C, "Chips & Technologies"},
- {0x1039, "Silicon Integrated Systems"},
- {0x1042, "SMC"},
- {0x1044, "DPT"},
- {0x1045, "OPTI"},
- {0x104B, "Bus Logic"},
- {0x104C, "TI"},
- {0x1060, "UMC"},
- {0x1080, "Contaq"},
- {0x1095, "CMD"},
- {0x10b9, "ACER Labs"},
- {0x10c8, "NeoMagic"},
- {0x1106, "VIA Technologies"},
- {0x5333, "S3 Inc."},
- {0x8086, "Intel Corporation"},
- {0x9004, "Adaptec"},
- {0,0}
-};
-
-typedef struct {
- const int subclass;
- const char *name;
-} subclass_name;
-
-/* 0x00 prehistoric subclasses */
-static const subclass_name old_subclasses[] =
-{
- { 0x00, "misc" },
- { 0x01, "vga" },
- { 0x00, NULL }
-};
-
-/* 0x01 mass storage subclasses */
-static const subclass_name storage_subclasses[] =
-{
- { 0x00, "scsi" },
- { 0x01, "ide" },
- { 0x02, "floppy"},
- { 0x03, "ipi" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x02 network subclasses */
-static const subclass_name network_subclasses[] =
-{
- { 0x00, "ethernet" },
- { 0x01, "tokenring" },
- { 0x02, "fddi" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x03 display subclasses */
-static const subclass_name display_subclasses[] =
-{
- { 0x00, "vga" },
- { 0x01, "xga" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x04 multimedia subclasses */
-static const subclass_name multimedia_subclasses[] =
-{
- { 0x00, "video" },
- { 0x01, "audio" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x05 memory subclasses */
-static const subclass_name memory_subclasses[] =
-{
- { 0x00, "ram" },
- { 0x01, "flash" },
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-/* 0x06 bridge subclasses */
-static const subclass_name bridge_subclasses[] =
-{
- { 0x00, "host" },
- { 0x01, "isa" },
- { 0x02, "eisa" },
- { 0x03, "mc" },
- { 0x04, "pci" },
- { 0x05, "pcmcia"},
- { 0x07, "cardbus"},
- { 0x80, "misc" },
- { 0x00, NULL }
-};
-
-static const subclass_name *const subclasses[] = {
- old_subclasses,
- storage_subclasses,
- network_subclasses,
- display_subclasses,
- multimedia_subclasses,
- memory_subclasses,
- bridge_subclasses,
-};
-
-static const char *const majclasses[] = {
- "old",
- "storage",
- "network",
- "display",
- "multimedia",
- "memory",
- "bridge",
- "comms",
- "system",
- "input",
- "docking",
- "processor",
- "serial"
-};
-
-
-void not_supported (pcici_t tag, u_long type)
-{
- u_long reg;
- u_long data;
- u_char class;
- u_char subclass;
- struct vt * vp;
- int pciint;
- int irq;
-
- /*
- ** lookup the names.
- */
-
- for (vp=VendorTable; vp->ident; vp++)
- if (vp->ident == (type & 0xffff))
- break;
+/* scan one PCI bus for devices */
- /*
- ** and display them.
- */
-
- if (vp->ident) printf (vp->name);
- else printf ("vendor=0x%04lx", type & 0xffff);
-
- printf (", device=0x%04lx", type >> 16);
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
- class = (data >> 24) & 0xff;
- subclass = (data >> 16) & 0xff;
-
- if (class < sizeof(majclasses) / sizeof(majclasses[0])) {
- printf(", class=%s", majclasses[class]);
- } else {
- printf(", class=0x%02x", class);
- }
-
- if (class < sizeof(subclasses) / sizeof(subclasses[0])) {
- const subclass_name *p = subclasses[class];
- while (p->name && (p->subclass != subclass))
- p++;
- if (p->name) {
- printf(" (%s)", p->name);
- } else {
- printf(" (unknown subclass 0x%02lx)", subclass);
+static int
+pci_probebus(int bus)
+{
+ pcicfgregs probe;
+ int bushigh = bus;
+
+ bzero(&probe, sizeof probe);
+ probe.parent = pci_bridgeto(bus);
+ probe.bus = bus;
+ for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
+ int pcifunchigh = 0;
+ for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
+ pcicfgregs *cfg = pci_readcfg(&probe);
+ if (cfg != NULL) {
+ if (cfg->mfdev)
+ pcifunchigh = 7;
+
+ if (bushigh < cfg->subordinatebus)
+ bushigh = cfg->subordinatebus;
+
+ pci_addcfg(cfg);
+ cfg = NULL; /* we don't own this anymore ... */
+ }
}
- } else {
- printf(", subclass=0x%02x", subclass);
}
+ return (bushigh);
+}
- data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
-
- if (pciint) {
-
- printf (" int %c irq ", 0x60+pciint);
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(data);
-
- /*
- ** If it's zero, the isa irq number is unknown,
- ** and we cannot bind the pci interrupt.
- */
+/* scan a PCI bus tree reached through one PCI attachment point */
- if (irq && (irq != 0xff))
- printf ("%d", irq);
- else
- printf ("??");
- };
+int
+pci_probe(pciattach *parent)
+{
+ int bushigh;
+ int bus = 0;
- if (class != (PCI_CLASS_BRIDGE >> 24))
- printf (" [no driver assigned]");
- printf ("\n");
+ bushigh = pci_bushigh();
+ while (bus <= bushigh) {
+ int newbushigh;
- if (bootverbose) {
- if (class == (PCI_CLASS_BRIDGE >> 24)) {
- printf ("configuration space registers:");
- for (reg = 0; reg < 0x100; reg+=4) {
- if ((reg & 0x0f) == 0) printf ("\n%02x:\t", reg);
- printf ("%08x ", pci_conf_read (tag, reg));
- }
- printf ("\n");
- } else {
- for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
- data = pci_conf_read (tag, reg);
- if ((data&~7)==0) continue;
- switch (data&7) {
+ printf("Probing for devices on PCI bus %d:\n", bus);
+ newbushigh = pci_probebus(bus);
- case 1:
- case 5:
- printf ("\tmap(%x): io(%04lx)\n",
- reg, data & ~3);
- break;
- case 0:
- printf ("\tmap(%x): mem32(%08lx)\n",
- reg, data & ~7);
- break;
- case 2:
- printf ("\tmap(%x): mem20(%05lx)\n",
- reg, data & ~7);
- break;
- case 4:
- printf ("\tmap(%x): mem64(%08x%08lx)\n",
- reg, pci_conf_read (tag, reg +4), data & ~7);
- reg += 4;
- break;
- }
- }
- }
+ if (bushigh < newbushigh)
+ bushigh = newbushigh;
+ bus++;
}
+ return (bushigh);
}
/*
- * This is the user interface to the PCI configuration space.
+ * This is the user interface to PCI configuration space.
*/
-
-
-static void
-pci_remember(int bus, int dev, int func, struct pci_device *dvp)
-{
- struct pci_conf *p;
- pcici_t tag;
-
- if (++pci_dev_list_count > pci_dev_list_size) {
- struct pci_conf *new;
-
- pci_dev_list_size += 8;
- MALLOC(new, struct pci_conf *, pci_dev_list_size * sizeof *new,
- M_DEVL, M_NOWAIT);
- if (!new) {
- pci_dev_list_size -= 8;
- pci_dev_list_count--;
- return;
- }
-
- if (pci_dev_list) {
- bcopy(pci_dev_list, new, ((pci_dev_list_size - 8) *
- sizeof *new));
- FREE(pci_dev_list, M_DEVL);
- }
- pci_dev_list = new;
- }
-
- p = &pci_dev_list[pci_dev_list_count - 1];
- p->pc_sel.pc_bus = bus;
- p->pc_sel.pc_dev = dev;
- p->pc_sel.pc_func = func;
- p->pc_dvp = dvp;
- p->pc_cb = pcicb;
-
- tag = pcibus->pb_tag (bus, dev, func);
- p->pc_hdr = (pci_conf_read (tag, PCI_HEADER_MISC) >> 16) & 0xff;
- p->pc_devid = pci_conf_read(tag, PCI_ID_REG);
- p->pc_class = pci_conf_read(tag, PCI_CLASS_REG);
- switch (p->pc_hdr & 0x7f) {
- case 0:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG0);
- break;
- case 1:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG1);
- break;
- case 2:
- p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG2);
- break;
- default:
- p->pc_subid = 0;
- }
-}
-
+
static int
pci_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
if ((oflags & FWRITE) && securelevel > 0) {
return EPERM;
}
-
return 0;
}
@@ -1904,79 +470,62 @@ pci_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
struct pci_io *io;
size_t iolen;
int error;
- pcici_t tag;
if (cmd != PCIOCGETCONF && !(flag & FWRITE))
return EPERM;
switch(cmd) {
case PCIOCGETCONF:
+#ifdef NOTYET
+static struct pci_conf *pci_dev_list;
+static unsigned pci_dev_list_count;
+static unsigned pci_dev_list_size;
+
cio = (struct pci_conf_io *)data;
iolen = min(cio->pci_len,
pci_dev_list_count * sizeof(struct pci_conf));
cio->pci_len = pci_dev_list_count * sizeof(struct pci_conf);
error = copyout(pci_dev_list, cio->pci_buf, iolen);
+#else
+ error = ENODEV;
+#endif
break;
case PCIOCREAD:
io = (struct pci_io *)data;
switch(io->pi_width) {
+ pcicfgregs probe;
case 4:
- tag = pcibus->pb_tag (io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func);
- io->pi_data = pci_conf_read(tag, io->pi_reg);
- error = 0;
- break;
case 2:
case 1:
- default:
- error = ENODEV;
- break;
- }
- break;
-
- case PCIOCWRITE:
- io = (struct pci_io *)data;
- switch(io->pi_width) {
- case 4:
- tag = pcibus->pb_tag (io->pi_sel.pc_bus,
- io->pi_sel.pc_dev,
- io->pi_sel.pc_func);
- pci_conf_write(tag, io->pi_reg, io->pi_data);
+ 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;
break;
- case 2:
- case 1:
default:
error = ENODEV;
break;
}
break;
- case PCIOCATTACHED:
+ case PCIOCWRITE:
io = (struct pci_io *)data;
switch(io->pi_width) {
+ pcicfgregs probe;
case 4:
- {
- int i = pci_dev_list_count;
- struct pci_conf *p = pci_dev_list;
- error = ENODEV;
- while (i--) {
- if (io->pi_sel.pc_bus == p->pc_sel.pc_bus &&
- io->pi_sel.pc_dev == p->pc_sel.pc_dev &&
- io->pi_sel.pc_func == p->pc_sel.pc_func) {
- io->pi_data = (u_int32_t)p->pc_dvp;
- error = 0;
- break;
- }
- p++;
- }
- }
- break;
case 2:
case 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;
+ break;
default:
error = ENODEV;
break;
@@ -2017,4 +566,4 @@ pci_cdevinit(void *dummy)
SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL);
-#endif /* NPCI */
+#endif /* NPCI > 0 */
diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c
new file mode 100644
index 0000000..c14d864
--- /dev/null
+++ b/sys/pci/pci_compat.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include "pci.h"
+#if NPCI > 0
+
+/* for compatibility to FreeBSD-2.2 version of PCI code */
+
+#include <stddef.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h> /* for DATA_SET support */
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <i386/isa/isa_device.h>
+#include <sys/interrupt.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#ifdef RESOURCE_CHECK
+#include <sys/drvresource.h>
+#endif
+
+#ifdef PCI_COMPAT
+
+/* ------------------------------------------------------------------------- */
+
+static int
+pci_mapno(pcicfgregs *cfg, int reg)
+{
+ int map = -1;
+
+ if ((reg & 0x03) == 0) {
+ map = (reg -0x10) / 4;
+ if (map < 0 || map >= cfg->nummaps)
+ map = -1;
+ }
+ return (map);
+}
+
+static int
+pci_isportmap(pcicfgregs *cfg, int map)
+{
+ return ((unsigned)map < cfg->nummaps
+ && (cfg->map[map].type & PCI_MAPPORT) != 0);
+}
+
+static int
+pci_ismemmap(pcicfgregs *cfg, int map)
+{
+ return ((unsigned)map < cfg->nummaps
+ && (cfg->map[map].type & PCI_MAPMEM) != 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+u_long
+pci_conf_read(pcici_t tag, u_long reg)
+{
+ return (pci_cfgread(tag, reg, 4));
+}
+
+void
+pci_conf_write(pcici_t tag, u_long reg, u_long data)
+{
+ pci_cfgwrite(tag, reg, data, 4);
+}
+
+int pci_map_port(pcici_t cfg, u_long reg, u_short* pa)
+{
+ int map;
+
+ map = pci_mapno(cfg, reg);
+ if (pci_isportmap(cfg, map)) {
+ u_int32_t iobase;
+ u_int32_t iosize;
+
+ iobase = cfg->map[map].base;
+ iosize = 1 << cfg->map[map].ln2size;
+#ifdef RESOURCE_CHECK
+ if (resource_claim(cfg, REST_PORT, RESF_NONE,
+ iobase, iobase + iosize -1) == 0)
+#endif /* RESOURCE_CHECK */
+ {
+ *pa = iobase;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
+{
+ int map;
+
+ map = pci_mapno(cfg, reg);
+ if (pci_ismemmap(cfg, map)) {
+ u_int32_t paddr;
+ u_int32_t psize;
+
+ paddr = cfg->map[map].base;
+ psize = 1 << cfg->map[map].ln2size;
+#ifdef RESOURCE_CHECK
+ if (resource_claim(cfg, REST_MEM, RESF_NONE,
+ paddr, paddr + psize -1) == 0)
+#endif /* RESOURCE_CHECK */
+ {
+ u_int32_t poffs;
+ vm_offset_t vaddr;
+
+ poffs = paddr - trunc_page(paddr);
+ vaddr = (vm_offset_t)pmap_mapdev(paddr-poffs, psize+poffs);
+ if (vaddr != NULL) {
+ vaddr += poffs;
+ *va = vaddr;
+ *pa = paddr;
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr)
+{
+ if (cfg->intpin != 0) {
+ int irq = cfg->intline;
+ void *dev_instance = (void *)-1; /* XXX use cfg->devdata */
+ intrec *idesc;
+
+ idesc = intr_create(dev_instance, irq, func, arg, maskptr, 0);
+ return (intr_connect(idesc) == 0);
+ }
+ return (1);
+}
+
+int
+pci_unmap_int(pcici_t cfg)
+{
+ return (0); /* not supported, yet, since cfg doesn't know about idesc */
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Preliminary support for "wired" PCI devices.
+ * This code supports currently only devices on PCI bus 0, since the
+ * mapping from PCI BIOS bus numbers to configuration file bus numbers
+ * is not yet maintained, whenever a PCI to PCI bridge is found.
+ * The "bus" field of "pciwirecfg" correlates an PCI bus with the bridge
+ * it is attached to. The "biosbus" field is to be updated for each bus,
+ * whose bridge is probed. An entry with bus != 0 and biosbus == 0 is
+ * invalid and will be skipped in the search for a wired unit, but not
+ * in the test for a free unit number.
+ */
+
+typedef struct {
+ char *name;
+ int unit;
+ u_int8_t bus;
+ u_int8_t slot;
+ u_int8_t func;
+ u_int8_t biosbus;
+} pciwirecfg;
+
+static pciwirecfg pci_wireddevs[] = {
+ /* driver, unit, bus, slot, func, BIOS bus */
+ { "ncr", 2, 1, 4, 0, 0 },
+ { "ed", 2, 1, 5, 0, 0 },
+ /* do not delete the end marker that follows this comment !!! */
+ { NULL }
+};
+
+/* return unit number of wired device, or -1 if no match */
+
+static int
+pci_wiredunit(pcicfgregs *cfg, char *name)
+{
+ pciwirecfg *p;
+
+ p = pci_wireddevs;
+ while (p->name != NULL) {
+ if (p->bus == cfg->bus
+ && p->slot == cfg->slot
+ && p->func == cfg->func
+ && strcmp(p->name, name) == 0)
+ return (p->unit);
+ p++;
+ }
+ return (-1);
+}
+
+/* return free unit number equal or greater to the one supplied as parameter */
+
+static int
+pci_freeunit(pcicfgregs *cfg, char *name, int unit)
+{
+ pciwirecfg *p;
+
+ p = pci_wireddevs;
+ while (p->name != NULL) {
+ if (p->unit == unit && strcmp(p->name, name) == 0) {
+ p = pci_wireddevs;
+ unit++;
+ } else {
+ p++;
+ }
+ }
+ return (unit);
+}
+
+static char *drvname;
+
+static char*
+pci_probedrv(pcicfgregs *cfg, struct pci_device *dvp)
+{
+ if (dvp && dvp->pd_probe) {
+ pcidi_t type = (cfg->device << 16) + cfg->vendor;
+ return (dvp->pd_probe(cfg, type));
+ }
+ return (NULL);
+}
+
+static struct pci_lkm *pci_lkm_head;
+
+static struct pci_device*
+pci_finddrv(pcicfgregs *cfg)
+{
+ struct pci_device **dvpp;
+ struct pci_device *dvp = NULL;
+ struct pci_lkm *lkm;
+
+ drvname = NULL;
+ lkm = pci_lkm_head;
+ while (drvname == NULL && lkm != NULL) {
+ dvp = lkm->dvp;
+ drvname = pci_probedrv(cfg, dvp);
+ lkm = lkm->next;
+ }
+
+ dvpp = (struct pci_device **)pcidevice_set.ls_items;
+ while (drvname == NULL && (dvp = *dvpp++) != NULL)
+ drvname = pci_probedrv(cfg, dvp);
+ return (dvp);
+}
+
+static void
+pci_drvmessage(pcicfgregs *cfg, char *name, int unit)
+{
+ if (drvname == NULL || *drvname == '\0')
+ return;
+ printf("%s%d: <%s> rev 0x%02x", name, unit, drvname, cfg->revid);
+ if (cfg->intpin != 0)
+ printf(" int %c irq %d", cfg->intpin + 'a' -1, cfg->intline);
+ printf(" on pci%d.%d.%d\n", cfg->bus, cfg->slot, cfg->func);
+}
+
+
+void
+pci_drvattach(pcicfgregs *cfg)
+{
+ struct pci_device *dvp;
+
+ dvp = pci_finddrv(cfg);
+ if (dvp != NULL) {
+ int unit;
+
+ unit = pci_wiredunit(cfg, dvp->pd_name);
+ if (unit < 0) {
+ unit = pci_freeunit(cfg, dvp->pd_name, *dvp->pd_count);
+ *dvp->pd_count = unit +1;
+ }
+ pci_drvmessage(cfg, dvp->pd_name, unit);
+ if (dvp->pd_attach)
+ dvp->pd_attach(cfg, unit);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+pci_rescan(void)
+{
+ /* XXX do nothing, currently, soon to come ... */
+}
+
+int pci_register_lkm (struct pci_device *dvp, int if_revision)
+{
+ struct pci_lkm *lkm;
+
+ if (if_revision != 0) {
+ return (-1);
+ }
+ if (dvp == NULL || dvp->pd_probe == NULL || dvp->pd_attach == NULL) {
+ return (-1);
+ }
+ lkm = malloc (sizeof (*lkm), M_DEVBUF, M_WAITOK);
+ if (lkm != NULL) {
+ return (-1);
+ }
+
+ lkm->dvp = dvp;
+ lkm->next = pci_lkm_head;
+ pci_lkm_head = lkm;
+ pci_rescan();
+ return (0);
+}
+
+void
+pci_configure(void)
+{
+ pci_probe(NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* PCI_COMPAT */
+#endif /* NPCI > 0 */
diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h
index 05e3c07..cd5c6e8 100644
--- a/sys/pci/pcireg.h
+++ b/sys/pci/pcireg.h
@@ -1,208 +1,250 @@
-/**************************************************************************
-**
-** $Id: pcireg.h,v 1.13 1997/04/20 06:57:43 phk Exp $
-**
-** Names for PCI configuration space registers.
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#ifndef __PCI_REG_H__
-#define __PCI_REG_H__ "pl2 95/03/21"
-
+#ifndef PCI_COMPAT
+#define PCI_COMPAT
+#endif
/*
-** Device identification register; contains a vendor ID and a device ID.
-** We have little need to distinguish the two parts.
-*/
-#define PCI_ID_REG 0x00
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
/*
-** Command and status register.
-*/
-#define PCI_COMMAND_STATUS_REG 0x04
-
+ * PCIM_xxx: mask to locate subfield in register
+ * PCIR_xxx: config register offset
+ * PCIC_xxx: device class
+ * PCIS_xxx: device subclass
+ * PCIP_xxx: device programming interface
+ * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
+ * PCID_xxx: device ID
+ */
+
+/* some PCI bus constants */
+
+#define PCI_BUSMAX 255
+#define PCI_SLOTMAX 31
+#define PCI_FUNCMAX 7
+#define PCI_REGMAX 255
+
+/* PCI config header registers for all devices */
+
+#define PCIR_DEVVENDOR 0x00
+#define PCIR_VENDOR 0x00
+#define PCIR_DEVICE 0x02
+#define PCIR_COMMAND 0x04
+#define PCIR_STATUS 0x06
+#define PCIR_REVID 0x08
+#define PCIR_PROGIF 0x09
+#define PCIR_SUBCLASS 0x0a
+#define PCIR_CLASS 0x0b
+#define PCIR_CACHELNSZ 0x0c
+#define PCIR_LATTIMER 0x0d
+#define PCIR_HEADERTYPE 0x0e
+#define PCIM_MFDEV 0x80
+#define PCIR_BIST 0x0f
+
+/* config registers for header type 0 devices */
+
+#define PCIR_MAPS 0x10
+#define PCIR_CARDBUSCIS 0x28
+#define PCIR_SUBVEND_0 0x2c
+#define PCIR_SUBDEV_0 0x2e
+#define PCIR_INTLINE 0x3c
+#define PCIR_INTPIN 0x3d
+#define PCIR_MINGNT 0x3e
+#define PCIR_MAXLAT 0x3f
+
+/* config registers for header type 1 devices */
+
+#define PCIR_SECSTAT_1 0 /**/
+
+#define PCIR_PRIBUS_1 0x18
+#define PCIR_SECBUS_1 0x19
+#define PCIR_SUBBUS_1 0x1a
+#define PCIR_SECLAT_1 0x1b
+
+#define PCIR_IOBASEL_1 0x1c
+#define PCIR_IOLIMITL_1 0x1d
+#define PCIR_IOBASEH_1 0 /**/
+#define PCIR_IOLIMITH_1 0 /**/
+
+#define PCIR_MEMBASE_1 0x20
+#define PCIR_MEMLIMIT_1 0x22
+
+#define PCIR_PMBASEL_1 0x24
+#define PCIR_PMLIMITL_1 0x26
+#define PCIR_PMBASEH_1 0 /**/
+#define PCIR_PMLIMITH_1 0 /**/
+
+#define PCIR_BRIDGECTL_1 0 /**/
+
+#define PCIR_SUBVEND_1 0x34
+#define PCIR_SUBDEV_1 0x36
+
+/* config registers for header type 2 devices */
+
+#define PCIR_SECSTAT_2 0x16
+
+#define PCIR_PRIBUS_2 0x18
+#define PCIR_SECBUS_2 0x19
+#define PCIR_SUBBUS_2 0x1a
+#define PCIR_SECLAT_2 0x1b
+
+#define PCIR_MEMBASE0_2 0x1c
+#define PCIR_MEMLIMIT0_2 0x20
+#define PCIR_MEMBASE1_2 0x24
+#define PCIR_MEMLIMIT1_2 0x28
+#define PCIR_IOBASE0_2 0x2c
+#define PCIR_IOLIMIT0_2 0x30
+#define PCIR_IOBASE1_2 0x34
+#define PCIR_IOLIMIT1_2 0x38
+
+#define PCIR_BRIDGECTL_2 0x3e
+
+#define PCIR_SUBVEND_2 0x40
+#define PCIR_SUBDEV_2 0x42
+
+#define PCIR_PCCARDIF_2 0x44
+
+/* PCI device class, subclass and programming interface definitions */
+
+#define PCIC_OLD 0x00
+#define PCIS_OLD_NONVGA 0x00
+#define PCIS_OLD_VGA 0x01
+
+#define PCIC_STORAGE 0x01
+#define PCIS_STORAGE_SCSI 0x00
+#define PCIS_STORAGE_IDE 0x01
+#define PCIP_STORAGE_IDE_MODEPRIM 0x01
+#define PCIP_STORAGE_IDE_PROGINDPRIM 0x02
+#define PCIP_STORAGE_IDE_MODESEC 0x04
+#define PCIP_STORAGE_IDE_PROGINDSEC 0x08
+#define PCIP_STORAGE_IDE_MASTERDEV 0x80
+#define PCIS_STORAGE_FLOPPY 0x02
+#define PCIS_STORAGE_IPI 0x03
+#define PCIS_STORAGE_RAID 0x04
+#define PCIS_STORAGE_OTHER 0x80
+
+#define PCIC_NETWORK 0x02
+#define PCIS_NETWORK_ETHERNET 0x00
+#define PCIS_NETWORK_TOKENRING 0x01
+#define PCIS_NETWORK_FDDI 0x02
+#define PCIS_NETWORK_ATM 0x03
+#define PCIS_NETWORK_OTHER 0x80
+
+#define PCIC_DISPLAY 0x03
+#define PCIS_DISPLAY_VGA 0x00
+#define PCIS_DISPLAY_XGA 0x01
+#define PCIS_DISPLAY_OTHER 0x80
+
+#define PCIC_MULTIMEDIA 0x04
+#define PCIS_MULTIMEDIA_VIDEO 0x00
+#define PCIS_MULTIMEDIA_AUDIO 0x01
+#define PCIS_MULTIMEDIA_OTHER 0x80
+
+#define PCIC_MEMORY 0x05
+#define PCIS_MEMORY_RAM 0x00
+#define PCIS_MEMORY_FLASH 0x01
+#define PCIS_MEMORY_OTHER 0x80
+
+#define PCIC_BRIDGE 0x06
+#define PCIS_BRDIGE_HOST 0x00
+#define PCIS_BRIDGE_ISA 0x01
+#define PCIS_BRIDGE_EISA 0x02
+#define PCIS_BRIDGE_MCA 0x03
+#define PCIS_BRIDGE_PCI 0x04
+#define PCIS_BRIDGE_PCMCIA 0x05
+#define PCIS_BRIDGE_NUBUS 0x06
+#define PCIS_BRIDGE_CARDBUS 0x07
+#define PCIS_BRIDGE_OTHER 0x80
+
+#define PCIC_SIMPLECOMM 0x07
+#define PCIS_SIMPLECOMM_UART 0x00
+#define PCIS_SIMPLECOMM_PAR 0x01
+#define PCIS_SIMPLECOMM_OTHER 0x80
+
+#define PCIC_BASEPERIPH 0x08
+#define PCIS_BASEPERIPH_PIC 0x00
+#define PCIS_BASEPERIPH_DMA 0x01
+#define PCIS_BASEPERIPH_TIMER 0x02
+#define PCIS_BASEPERIPH_RTC 0x03
+#define PCIS_BASEPERIPH_OTHER 0x80
+
+#define PCIC_INPUTDEV 0x09
+#define PCIS_INPUTDEV_KEYBOARD 0x00
+#define PCIS_INPUTDEV_DIGITIZER 0x01
+#define PCIS_INPUTDEV_MOUSE 0x02
+#define PCIS_INPUTDEV_OTHER 0x80
+
+#define PCIC_DOCKING 0x0a
+#define PCIS_DOCKING_GENERIC 0x00
+#define PCIS_DOCKING_OTHER 0x80
+
+#define PCIC_PROCESSOR 0x0b
+#define PCIS_PROCESSOR_386 0x00
+#define PCIS_PROCESSOR_486 0x01
+#define PCIS_PROCESSOR_PENTIUM 0x02
+#define PCIS_PROCESSOR_ALPHA 0x10
+#define PCIS_PROCESSOR_POWERPC 0x20
+#define PCIS_PROCESSOR_COPROC 0x40
+
+#define PCIC_SERIALBUS 0x0c
+#define PCIS_SERIALBUS_FW 0x00
+#define PCIS_SERIALBUS_ACCESS 0x01
+#define PCIS_SERIALBUS_SSA 0x02
+#define PCIS_SERIALBUS_USB 0x03
+#define PCIS_SERIALBUS_FC 0x04
+#define PCIS_SERIALBUS
+#define PCIS_SERIALBUS
+
+#define PCIC_OTHER 0xff
+
+/* some PCI vendor definitions (only used to identify ancient devices !!! */
+
+#define PCIV_INTEL 0x8086
+
+#define PCID_INTEL_SATURN 0x0483
+#define PCID_INTEL_ORION 0x84c4
+
+/* for compatibility to FreeBSD-2.2 version of PCI code */
+
+#ifdef PCI_COMPAT
+
+#define PCI_ID_REG 0x00
+#define PCI_COMMAND_STATUS_REG 0x04
#define PCI_COMMAND_IO_ENABLE 0x00000001
-#define PCI_COMMAND_MEM_ENABLE 0x00000002
-#define PCI_COMMAND_MASTER_ENABLE 0x00000004
-#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008
-#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010
-#define PCI_COMMAND_PALETTE_ENABLE 0x00000020
-#define PCI_COMMAND_PARITY_ENABLE 0x00000040
-#define PCI_COMMAND_STEPPING_ENABLE 0x00000080
-#define PCI_COMMAND_SERR_ENABLE 0x00000100
-#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200
-
-#define PCI_STATUS_BACKTOBACK_OKAY 0x00800000
-#define PCI_STATUS_PARITY_ERROR 0x01000000
-#define PCI_STATUS_DEVSEL_FAST 0x00000000
-#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000
-#define PCI_STATUS_DEVSEL_SLOW 0x04000000
-#define PCI_STATUS_DEVSEL_MASK 0x06000000
-#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000
-#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000
-#define PCI_STATUS_MASTER_ABORT 0x20000000
-#define PCI_STATUS_SPECIAL_ERROR 0x40000000
-#define PCI_STATUS_PARITY_DETECT 0x80000000
-
-/*
-** Class register; defines basic type of device.
-*/
-#define PCI_CLASS_REG 0x08
-
-#define PCI_CLASS_MASK 0xff000000
-#define PCI_SUBCLASS_MASK 0x00ff0000
-
-/* base classes */
-#define PCI_CLASS_PREHISTORIC 0x00000000
-#define PCI_CLASS_MASS_STORAGE 0x01000000
-#define PCI_CLASS_NETWORK 0x02000000
-#define PCI_CLASS_DISPLAY 0x03000000
-#define PCI_CLASS_MULTIMEDIA 0x04000000
-#define PCI_CLASS_MEMORY 0x05000000
-#define PCI_CLASS_BRIDGE 0x06000000
-#define PCI_CLASS_UNDEFINED 0xff000000
-
-/* 0x00 prehistoric subclasses */
-#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00000000
-#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
-
-/* 0x01 mass storage subclasses */
-#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000
-#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x00010000
-#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x00020000
-#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x00030000
-#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x00800000
-
-/* 0x02 network subclasses */
-#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00000000
-#define PCI_SUBCLASS_NETWORK_TOKENRING 0x00010000
-#define PCI_SUBCLASS_NETWORK_FDDI 0x00020000
-#define PCI_SUBCLASS_NETWORK_MISC 0x00800000
-
-/* 0x03 display subclasses */
-#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000
-#define PCI_SUBCLASS_DISPLAY_XGA 0x00010000
-#define PCI_SUBCLASS_DISPLAY_MISC 0x00800000
-
-/* 0x04 multimedia subclasses */
-#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00000000
-#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x00010000
-#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x00800000
-
-/* 0x05 memory subclasses */
-#define PCI_SUBCLASS_MEMORY_RAM 0x00000000
-#define PCI_SUBCLASS_MEMORY_FLASH 0x00010000
-#define PCI_SUBCLASS_MEMORY_MISC 0x00800000
-
-/* 0x06 bridge subclasses */
-#define PCI_SUBCLASS_BRIDGE_HOST 0x00000000
-#define PCI_SUBCLASS_BRIDGE_ISA 0x00010000
-#define PCI_SUBCLASS_BRIDGE_EISA 0x00020000
-#define PCI_SUBCLASS_BRIDGE_MC 0x00030000
-#define PCI_SUBCLASS_BRIDGE_PCI 0x00040000
-#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x00050000
-#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x00070000
-#define PCI_SUBCLASS_BRIDGE_MISC 0x00800000
-
-/*
-** Header registers
-*/
-#define PCI_HEADER_MISC 0x0c
-
-#define PCI_HEADER_MULTIFUNCTION 0x00800000
-
-/*
-** Mapping registers
-*/
-#define PCI_MAP_REG_START 0x10
-#define PCI_MAP_REG_END 0x28
-
-#define PCI_MAP_MEMORY 0x00000000
+#define PCI_CLASS_REG 0x08
+#define PCI_CLASS_MASK 0xff000000
+#define PCI_SUBCLASS_MASK 0x00ff0000
+#define PCI_CLASS_PREHISTORIC 0x00000000
+#define PCI_SUBCLASS_PREHISTORIC_VGA 0x00010000
+#define PCI_CLASS_DISPLAY 0x03000000
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00000000
+#define PCI_CLASS_BRIDGE 0x06000000
+#define PCI_MAP_REG_START 0x10
+#define PCI_MAP_REG_END 0x28
#define PCI_MAP_IO 0x00000001
+#define PCI_INTERRUPT_REG 0x3c
-#define PCI_MAP_MEMORY_TYPE_32BIT 0x00000000
-#define PCI_MAP_MEMORY_TYPE_32BIT_1M 0x00000002
-#define PCI_MAP_MEMORY_TYPE_64BIT 0x00000004
-#define PCI_MAP_MEMORY_TYPE_MASK 0x00000006
-#define PCI_MAP_MEMORY_CACHABLE 0x00000008
-#define PCI_MAP_MEMORY_ADDRESS_MASK 0xfffffff0
-
-#define PCI_MAP_IO_ADDRESS_MASK 0xfffffffc
-/*
-** PCI-PCI bridge mapping registers
-*/
-#define PCI_PCI_BRIDGE_BUS_REG 0x18
-#define PCI_PCI_BRIDGE_IO_REG 0x1c
-#define PCI_PCI_BRIDGE_MEM_REG 0x20
-#define PCI_PCI_BRIDGE_PMEM_REG 0x24
-
-#define PCI_SUBID_REG0 0x2c
-#define PCI_SUBID_REG1 0x34
-#define PCI_SUBID_REG2 0x40
-
-#define PCI_SUBORDINATE_BUS_MASK 0x00ff0000
-#define PCI_SECONDARY_BUS_MASK 0x0000ff00
-#define PCI_PRIMARY_BUS_MASK 0x000000ff
-
-#define PCI_SUBORDINATE_BUS_EXTRACT(x) (((x) >> 16) & 0xff)
-#define PCI_SECONDARY_BUS_EXTRACT(x) (((x) >> 8) & 0xff)
-#define PCI_PRIMARY_BUS_EXTRACT(x) (((x) ) & 0xff)
-
-#define PCI_PRIMARY_BUS_INSERT(x, y) (((x) & ~PCI_PRIMARY_BUS_MASK) | ((y) << 0))
-#define PCI_SECONDARY_BUS_INSERT(x, y) (((x) & ~PCI_SECONDARY_BUS_MASK) | ((y) << 8))
-#define PCI_SUBORDINATE_BUS_INSERT(x, y) (((x) & ~PCI_SUBORDINATE_BUS_MASK) | ((y) << 16))
-
-#define PCI_PPB_IOBASE_EXTRACT(x) (((x) << 8) & 0xF000)
-#define PCI_PPB_IOLIMIT_EXTRACT(x) (((x) << 0) & 0xF000 | 0x0FFF)
-
-#define PCI_PPB_MEMBASE_EXTRACT(x) (((x) << 16) & 0xFFF00000)
-#define PCI_PPB_MEMLIMIT_EXTRACT(x) (((x) << 0) & 0xFFF00000 | 0x000FFFFF)
-
-/*
-** PCI-Cardbus bridge mapping registers
-*/
-#define PCI_CARDBUS_SOCKET_REG 0x10
-
-/*
-** Interrupt configuration register
-*/
-#define PCI_INTERRUPT_REG 0x3c
-
-#define PCI_INTERRUPT_PIN_MASK 0x0000ff00
-#define PCI_INTERRUPT_PIN_EXTRACT(x) ((((x) & PCI_INTERRUPT_PIN_MASK) >> 8) & 0xff)
-#define PCI_INTERRUPT_PIN_NONE 0x00
-#define PCI_INTERRUPT_PIN_A 0x01
-#define PCI_INTERRUPT_PIN_B 0x02
-#define PCI_INTERRUPT_PIN_C 0x03
-#define PCI_INTERRUPT_PIN_D 0x04
-
-#define PCI_INTERRUPT_LINE_MASK 0x000000ff
-#define PCI_INTERRUPT_LINE_EXTRACT(x) ((((x) & PCI_INTERRUPT_LINE_MASK) >> 0) & 0xff)
-#define PCI_INTERRUPT_LINE_INSERT(x,v) (((x) & ~PCI_INTERRUPT_LINE_MASK) | ((v) << 0))
-
-#endif /* __PCI_REG_H__ */
+#endif /* PCI_COMPAT */
diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c
index 313db95..97dfb1e 100644
--- a/sys/pci/pcisupport.c
+++ b/sys/pci/pcisupport.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: pcisupport.c,v 1.44 1997/03/25 19:03:04 se Exp $
+** $Id: pcisupport.c,v 1.45 1997/03/28 18:40:24 phk Exp $
**
** Device driver for DEC/INTEL PCI chipsets.
**
@@ -50,8 +50,6 @@
#include <pci/pcivar.h>
#include <pci/pcireg.h>
-static void config_orion (pcici_t tag);
-
/*---------------------------------------------------------
**
** Intel chipsets for 486 / Pentium processor
@@ -81,9 +79,6 @@ struct condmsg {
const char *text;
};
-/* make sure formats expand to at least as many chars !!! */
-#define PPB_DESCR "generic PCI bridge (vendor=%04x device=%04x subclass=%1.2d)"
-
static char*
generic_pci_bridge (pcici_t tag)
{
@@ -114,7 +109,6 @@ generic_pci_bridge (pcici_t tag)
return 0;
}
-
static char*
chipset_probe (pcici_t tag, pcidi_t type)
{
@@ -163,6 +157,8 @@ chipset_probe (pcici_t tag, pcidi_t type)
case 0x12378086:
return ("Intel 82440FX (Natoma) PCI and memory controller");
case 0x84c48086:
+ tag->secondarybus =
+ tag->subordinatebus = pci_cfgread(tag, 0x4a, 1);
return ("Intel 82450KX (Orion) PCI memory controller");
case 0x84c58086:
return ("Intel 82454GX (Orion) host to PCI bridge");
@@ -672,27 +668,9 @@ dumpconfigspace (pcici_t tag)
#endif /* PCI_QUIET */
-extern unsigned pciroots;
-
-static void
-config_orion (pcici_t tag)
-{
- unsigned busno = (pci_conf_read (tag, 0x48) >> 16) & 0xff;
-
- if (busno > 0) {
- pciroots++;
- }
-}
-
static void
chipset_attach (pcici_t config_id, int unit)
{
- switch (pci_conf_read (config_id, PCI_ID_REG)) {
-
- case 0x84c48086: /* Intel Orion */
- config_orion (config_id);
- break;
- }
#ifndef PCI_QUIET
if (!bootverbose)
return;
diff --git a/sys/pci/pcivar.h b/sys/pci/pcivar.h
index cb85100..4bb8496 100644
--- a/sys/pci/pcivar.h
+++ b/sys/pci/pcivar.h
@@ -1,129 +1,183 @@
-/**************************************************************************
-**
-** $Id$
-**
-** Declarations for pci device drivers.
-**
-** FreeBSD
-**
-**-------------------------------------------------------------------------
-**
-** Copyright (c) 1994 Wolfgang Stanglmeier. 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.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** 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.
-**
-***************************************************************************
-*/
-
-#ifndef __PCI_VAR_H__
-#define __PCI_VAR_H__ "pl2 95/03/21"
-
-/*-----------------------------------------------------------------
-**
-** main pci initialization function.
-** called at boot time from autoconf.c
-**
-**-----------------------------------------------------------------
-*/
-
-void pci_configure (void);
-
-/*-----------------------------------------------------------------
-**
-** The pci configuration id describes a pci device on the bus.
-** It is constructed from: bus, device & function numbers.
-**
-**-----------------------------------------------------------------
-*/
-
-typedef union {
- u_long cfg1;
- struct {
- u_char enable;
- u_char forward;
- u_short port;
- } cfg2;
- unsigned tag;
- } pcici_t;
-
-#define sametag(x,y) ((x).tag == (y).tag)
-
-/*-----------------------------------------------------------------
-**
-** Each pci device has an unique device id.
-** It is used to find a matching driver.
-**
-**-----------------------------------------------------------------
-*/
-
-typedef u_long pcidi_t;
-
-/*-----------------------------------------------------------------
-**
-** The following functions are provided for the device driver
-** to read/write the configuration space.
-**
-** pci_conf_read():
-** Read a long word from the pci configuration space.
-** Requires a tag (from pcitag) and the register
-** number (should be a long word alligned one).
-**
-** pci_conf_write():
-** Writes a long word to the pci configuration space.
-** Requires a tag (from pcitag), the register number
-** (should be a long word alligned one), and a value.
-**
-**-----------------------------------------------------------------
-*/
-
-u_long pci_conf_read (pcici_t tag, u_long reg );
-
-void pci_conf_write (pcici_t tag, u_long reg, u_long data);
-
-/*-----------------------------------------------------------------
-**
-** The pci driver structure.
-**
-** name: The short device name.
-**
-** probe: Checks if the driver can support a device
-** with this type. The tag may be used to get
-** more info with pci_read_conf(). See below.
-** It returns a string with the devices name,
-** or a NULL pointer, if the driver cannot
-** support this device.
-**
-** attach: Allocate a control structure and prepare
-** it. This function may use the pci mapping
-** functions. See below.
-** (configuration id) or type.
-**
-** count: A pointer to a unit counter.
-** It's used by the pci configurator to
-** allocate unit numbers.
-**
-**-----------------------------------------------------------------
-*/
+#ifndef PCI_COMPAT
+#define PCI_COMPAT
+#endif
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+/* some PCI bus constants */
+
+#define PCI_BUSMAX 255 /* highest supported bus number */
+#define PCI_SLOTMAX 31 /* highest supported slot number */
+#define PCI_FUNCMAX 7 /* highest supported function number */
+#define PCI_REGMAX 255 /* highest supported config register addr. */
+
+#define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */
+#define PCI_MAXMAPS_1 2 /* max. no. of maps for PCI to PCI bridge */
+#define PCI_MAXMAPS_2 1 /* max. no. of maps for CardBus bridge */
+
+/* pci_addr_t covers this system's PCI bus address space: 32 or 64 bit */
+
+#ifdef PCI_A64
+typedef u_int64_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
+#else
+typedef u_int32_t pci_addr_t; /* u_int64_t for system with 64bit addresses */
+#endif
+
+/* map register information */
+
+typedef struct {
+ u_int32_t base;
+ u_int8_t type;
+#define PCI_MAPMEM 0x01 /* memory map */
+#define PCI_MAPMEMP 0x02 /* prefetchable memory map */
+#define PCI_MAPPORT 0x04 /* port map */
+ u_int8_t ln2size;
+ u_int8_t ln2range;
+/* u_int8_t dummy;*/
+} pcimap;
+
+/* config header information common to all header types */
+
+typedef struct pcicfg {
+ struct pcicfg *parent;
+ struct pcicfg *next;
+ pcimap *map; /* pointer to array of PCI maps */
+ void *hdrspec; /* pointer to header type specific data */
+
+ u_int16_t subvendor; /* card vendor ID */
+ u_int16_t subdevice; /* card device ID, assigned by card vendor */
+ u_int16_t vendor; /* chip vendor ID */
+ u_int16_t device; /* chip device ID, assigned by chip vendor */
+
+ u_int16_t cmdreg; /* disable/enable chip and PCI options */
+ u_int16_t statreg; /* supported PCI features and error state */
+
+ u_int8_t class; /* chip PCI class */
+ u_int8_t subclass; /* chip PCI subclass */
+ u_int8_t progif; /* chip PCI programming interface */
+ u_int8_t revid; /* chip revision ID */
+
+ u_int8_t hdrtype; /* chip config header type */
+ u_int8_t cachelnsz; /* cache line size in 4byte units */
+ u_int8_t intpin; /* PCI interrupt pin */
+ u_int8_t intline; /* interrupt line (IRQ for PC arch) */
+
+ u_int8_t mingnt; /* min. useful bus grant time in 250ns units */
+ u_int8_t maxlat; /* max. tolerated bus grant latency in 250ns */
+ u_int8_t lattimer; /* latency timer in units of 30ns bus cycles */
+
+ u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
+ u_int8_t nummaps; /* actual number of PCI maps used */
+
+ u_int8_t bus; /* config space bus address */
+ u_int8_t slot; /* config space slot address */
+ u_int8_t func; /* config space function number */
+
+ u_int8_t secondarybus; /* bus on secondary side of bridge, if any */
+ u_int8_t subordinatebus; /* topmost bus number behind bridge, if any */
+} pcicfgregs;
+
+/* additional type 1 device config header information (PCI to PCI bridge) */
+
+#ifdef PCI_A64
+#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
+#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
+#else
+#define PCI_PPBMEMBASE(h,l) (((l)<<16) & ~0xfffff)
+#define PCI_PPBMEMLIMIT(h,l) (((l)<<16) | 0xfffff)
+#endif /* PCI_A64 */
+
+#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff)
+#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff)
+
+typedef struct {
+ pci_addr_t pmembase; /* base address of prefetchable memory */
+ pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
+ u_int32_t membase; /* base address of memory window */
+ u_int32_t memlimit; /* topmost address of memory window */
+ u_int32_t iobase; /* base address of port window */
+ u_int32_t iolimit; /* topmost address of port window */
+ u_int16_t secstat; /* secondary bus status register */
+ u_int16_t bridgectl; /* bridge control register */
+ u_int8_t seclat; /* CardBus latency timer */
+} pcih1cfgregs;
+
+/* additional type 2 device config header information (CardBus bridge) */
+
+typedef struct {
+ u_int32_t membase0; /* base address of memory window */
+ u_int32_t memlimit0; /* topmost address of memory window */
+ u_int32_t membase1; /* base address of memory window */
+ u_int32_t memlimit1; /* topmost address of memory window */
+ u_int32_t iobase0; /* base address of port window */
+ u_int32_t iolimit0; /* topmost address of port window */
+ u_int32_t iobase1; /* base address of port window */
+ u_int32_t iolimit1; /* topmost address of port window */
+ u_int32_t pccardif; /* PC Card 16bit IF legacy more base addr. */
+ u_int16_t secstat; /* secondary bus status register */
+ u_int16_t bridgectl; /* bridge control register */
+ u_int8_t seclat; /* CardBus latency timer */
+} pcih2cfgregs;
+
+/* PCI bus attach definitions (there could be multiple PCI bus *trees* ... */
+
+typedef struct pciattach {
+ int unit;
+ int pcibushigh;
+ struct pciattach *next;
+} pciattach;
+
+/* externally visible functions */
+
+int pci_probe (pciattach *attach);
+void pci_drvattach(pcicfgregs *cfg);
+
+/* low level PCI config register functions provided by pcibus.c */
+
+int pci_cfgopen (void);
+int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
+void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
+
+/* for compatibility to FreeBSD-2.2 version of PCI code */
+
+#ifdef PCI_COMPAT
+
+typedef pcicfgregs *pcici_t;
+typedef unsigned pcidi_t;
+typedef void pci_inthand_t(void *arg);
+
+#define pci_max_burst_len (3)
+
+/* just copied from old PCI code for now ... */
+
+extern struct linker_set pcidevice_set;
+extern int pci_mechanism;
struct pci_device {
char* pd_name;
@@ -133,97 +187,17 @@ struct pci_device {
int (*pd_shutdown) (int, int);
};
-/*-----------------------------------------------------------------
-**
-** This table includes pointers to all pci device drivers.
-** It should be generated by the linker.
-**
-**-----------------------------------------------------------------
-*/
-
-extern struct linker_set pcidevice_set;
-
-extern unsigned pci_max_burst_len; /* log2 of safe burst transfer length */
-extern unsigned pci_mechanism;
-extern unsigned pci_maxdevice;
-
-/*-----------------------------------------------------------------
-**
-** Map a pci device to physical and virtual memory.
-**
-** Entry selects the register in the pci configuration
-** space, which supplies the size of the region, and
-** receives the physical address.
-**
-** In case of success the function sets the addresses
-** in *va and *pa, and returns 1.
-** In case of errors a message is written,
-** and the function returns 0.
-**
-**-----------------------------------------------------------------
-*/
-
-int pci_map_mem (pcici_t tag, u_long entry, vm_offset_t *va, vm_offset_t *pa);
-
-/*-----------------------------------------------------------------
-**
-** Map a pci device to an io port area.
-**
-** Entry selects the register in the pci configuration
-** space, which supplies the size of the region, and
-** receives the port number.
-**
-** In case of success the function sets the port number in pa,
-** and returns 1.
-** In case of errors a message is written,
-** and the function returns 0.
-**
-**-----------------------------------------------------------------
-*/
-
-int pci_map_port (pcici_t tag, u_long entry, u_short * pa);
-
-/*-----------------------------------------------------------------
-**
-** Map a pci interrupt to an isa irq line, and enable the interrupt.
-**
-** -----------------
-**
-** func is the interrupt handler, arg is the argument
-** to the handler (usually a pointer to a softc).
-**
-** The maskptr argument should be &bio_imask,
-** &net_imask etc. or NULL.
-**
-** If there is any error, a message is written, and
-** the function returns with zero.
-** Else it returns with a value different to zero.
-**
-** -----------------
-**
-** The irq number is read from the configuration space.
-** (Should have been set by the bios).
-**
-** Supports multiple handlers per irq (shared interrupts).
-**
-**-----------------------------------------------------------------
-*/
-
-typedef void pci_inthand_t(void *arg);
-
-struct pci_int_desc {
- struct pci_int_desc * pcid_next;
- pcici_t pcid_tag;
- pci_inthand_t *pcid_handler;
- void* pcid_argument;
- unsigned * pcid_maskptr;
- unsigned pcid_tally;
- unsigned pcid_mask;
+struct pci_lkm {
+ struct pci_device *dvp;
+ struct pci_lkm *next;
};
-int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg,
- unsigned *maskptr);
-
+u_long pci_conf_read (pcici_t tag, u_long reg);
+void pci_conf_write (pcici_t tag, u_long reg, u_long data);
+int pci_map_port (pcici_t tag, u_long reg, u_short* pa);
+int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
+int pci_map_int (pcici_t tag, pci_inthand_t *func, void *arg, unsigned *maskptr);
int pci_unmap_int (pcici_t tag);
+int pci_register_lkm (struct pci_device *dvp, int if_revision);
-#endif
+#endif /* PCI_COMPAT */
diff --git a/sys/pci/tek390.c b/sys/pci/tek390.c
index 3d73555..3983ea2 100644
--- a/sys/pci/tek390.c
+++ b/sys/pci/tek390.c
@@ -1231,6 +1231,16 @@ int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index,
}
+#ifdef PCI_COMPAT
+static pcicfgregs *cfg;
+#define DC390_EnableCfg(a,b)
+#define DC390_DisableCfg(a)
+#define DC390_inByte(a,reg) pci_cfgread(cfg,reg,1)
+#define DC390_inWord(a,reg) pci_cfgread(cfg,reg,2)
+#define DC390_inDword(a,reg) pci_cfgread(cfg,reg,4)
+#define DC390_OutB(a,reg,val) pci_cfgwrite(cfg,reg,val,1)
+#else
+
void
DC390_EnableCfg( USHORT mechnum, UCHAR regval )
{
@@ -1366,6 +1376,7 @@ DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
splx(flags);
}
+#endif /PCI_COMPAT */
void
DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
@@ -1527,6 +1538,9 @@ USHORT
DC390_ToMech( USHORT Mechnum, pcici_t config_id )
{
+#ifdef PCI_COMPAT
+ cfg = config_id;
+#else
if(Mechnum == 2)
{
mech2bus = config_id.cfg2.forward; /* Bus num */
@@ -1537,6 +1551,7 @@ DC390_ToMech( USHORT Mechnum, pcici_t config_id )
{
mech1addr = config_id.cfg1;
}
+#endif /* PCI_COMPAT */
return(0);
}
OpenPOWER on IntegriCloud