Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Add an option (defopt) PCI_NETBSD_CONFIGURE that...
details: https://anonhg.NetBSD.org/src/rev/defafd12da2a
branches: trunk
changeset: 503580:defafd12da2a
user: briggs <briggs%NetBSD.org@localhost>
date: Fri Feb 09 14:33:15 2001 +0000
description:
Add an option (defopt) PCI_NETBSD_CONFIGURE that provides PCI bus
configuration (assignment of bus numbers, BARs, timer values,
interrupt lines, etc.).
The interface must be called from m.d. code prior to probing the bus.
It is meant to be called once for each primary (bus == 0) PCI bus in
the system. It will configure any busses behind PCI-PCI bridges.
Section 9 man page for pci_configure_bus() will come soon.
In the meantime, sample usage is in arch/sandpoint/sandpoint/mainbus.c.
[ Reviewed by thorpej ]
diffstat:
sys/dev/pci/files.pci | 5 +-
sys/dev/pci/pciconf.c | 917 ++++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/pci/pciconf.h | 49 ++
sys/dev/pci/pcireg.h | 67 +++-
4 files changed, 1035 insertions(+), 3 deletions(-)
diffs (truncated from 1098 to 300 lines):
diff -r 1656321cd6ac -r defafd12da2a sys/dev/pci/files.pci
--- a/sys/dev/pci/files.pci Fri Feb 09 14:27:06 2001 +0000
+++ b/sys/dev/pci/files.pci Fri Feb 09 14:33:15 2001 +0000
@@ -1,10 +1,10 @@
-# $NetBSD: files.pci,v 1.120 2001/02/07 14:41:12 tacha Exp $
+# $NetBSD: files.pci,v 1.121 2001/02/09 14:33:15 briggs Exp $
#
# Config file and device description for machine-independent PCI code.
# Included by ports that need it. Requires that the SCSI files be
# defined first.
-defopt opt_pci.h PCIVERBOSE PCI_CONFIG_DUMP
+defopt opt_pci.h PCIVERBOSE PCI_CONFIG_DUMP PCI_NETBSD_CONFIGURE
defopt opt_bktr.h BKTR_OVERRIDE_CARD BKTR_OVERRIDE_TUNER BKTR_OVERRIDE_DBX
BKTR_OVERRIDE_MSP BKTR_SYSTEM_DEFAULT
@@ -20,6 +20,7 @@
file dev/pci/pci_map.c pci
file dev/pci/pci_quirks.c pci
file dev/pci/pci_subr.c pci
+file dev/pci/pciconf.c pci_netbsd_configure
# Cypress 82c693 hyperCache(tm) Stand-Alone PCI Peripheral Controller
# with USB. This is a combo chip:
diff -r 1656321cd6ac -r defafd12da2a sys/dev/pci/pciconf.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/pciconf.c Fri Feb 09 14:33:15 2001 +0000
@@ -0,0 +1,917 @@
+/* $NetBSD: pciconf.c,v 1.1 2001/02/09 14:33:15 briggs Exp $ */
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Allen Briggs for Wasabi Systems, Inc.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+/*
+ * Derived in part from code from PMON/2000 (http://pmon.groupbsd.org/).
+ */
+
+#include "opt_pci.h"
+
+#include <sys/param.h>
+#include <sys/extent.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciconf.h>
+#include <dev/pci/pcidevs.h>
+
+#ifdef PCI_CONFIGURATION_DEBUG
+int pci_conf_debug = 0;
+#endif
+
+#if !defined(MIN)
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
+/* per-bus constants. */
+#define MAX_CONF_DEV 8 /* Arbitrary */
+#define MAX_CONF_MEM (3 * MAX_CONF_DEV) /* Avg. 3 per device -- Arb. */
+#define MAX_CONF_IO (1 * MAX_CONF_DEV) /* Avg. 1 per device -- Arb. */
+
+#define PCI_BUSNO_SPACING (1 << 5)
+
+struct _s_pciconf_bus_t; /* Forward declaration */
+
+typedef struct _s_pciconf_dev_t {
+ int ipin;
+ int iline;
+ int min_gnt;
+ int max_lat;
+ pcitag_t tag;
+ pci_chipset_tag_t pc;
+ struct _s_pciconf_bus_t *ppb; /* I am really a bridge */
+} pciconf_dev_t;
+
+typedef struct _s_pciconf_win_t {
+ pciconf_dev_t *dev;
+ int reg; /* 0 for busses */
+ int align;
+ int prefetch;
+ u_int64_t size;
+ u_int64_t address;
+} pciconf_win_t;
+
+typedef struct _s_pciconf_bus_t {
+ int busno;
+ int next_busno;
+ int last_busno;
+ int busno_spacing;
+ int max_mingnt;
+ int min_maxlat;
+ int prefetch;
+ int fast_b2b;
+ int freq_66;
+ int def_ltim;
+ int max_ltim;
+ int bandwidth_used;
+ int swiz;
+
+ int ndevs;
+ pciconf_dev_t device[MAX_CONF_DEV];
+
+ /* These should be sorted in order of decreasing size */
+ int nmemwin;
+ pciconf_win_t pcimemwin[MAX_CONF_MEM];
+ int niowin;
+ pciconf_win_t pciiowin[MAX_CONF_IO];
+
+ bus_size_t io_total;
+ bus_size_t mem_total;
+ bus_size_t pmem_total;
+
+ struct extent *ioext;
+ struct extent *memext;
+ struct extent *pmemext;
+
+ pci_chipset_tag_t pc;
+ struct _s_pciconf_bus_t *parent_bus;
+} pciconf_bus_t;
+
+static int probe_bus(pciconf_bus_t *);
+static void alloc_busno(pciconf_bus_t *, pciconf_bus_t *);
+static int pci_do_device_query(pciconf_bus_t *, pcitag_t, int, int);
+static int setup_iowins(pciconf_bus_t *);
+static int setup_memwins(pciconf_bus_t *);
+static int configure_bridge(pciconf_dev_t *);
+static int configure_bus(pciconf_bus_t *);
+static u_int64_t pci_allocate_range(struct extent *, u_int64_t, int);
+static pciconf_win_t *get_io_desc(pciconf_bus_t *, bus_size_t);
+static pciconf_win_t *get_mem_desc(pciconf_bus_t *, bus_size_t);
+static pciconf_bus_t *query_bus(pciconf_bus_t *, pciconf_dev_t *, int);
+
+#ifdef PCI_CONFIGURATION_DEBUG
+static void print_tag(pci_chipset_tag_t, pcitag_t);
+
+static void
+print_tag(pci_chipset_tag_t pc, pcitag_t tag)
+{
+ int bus, dev, func;
+
+ pci_decompose_tag(pc, tag, &bus, &dev, &func);
+ printf("PCI: bus %d, device %d, function %d: ", bus, dev, func);
+}
+#endif
+
+/************************************************************************/
+/************************************************************************/
+/*********************** Bus probing routines ***********************/
+/************************************************************************/
+/************************************************************************/
+static pciconf_win_t *
+get_io_desc(pciconf_bus_t *pb, bus_size_t size)
+{
+ int i, n;
+
+ n = pb->niowin;
+ for (i=n; i > 0 && size > pb->pciiowin[i-1].size; i--)
+ pb->pciiowin[i] = pb->pciiowin[i-1]; /* struct copy */
+ return &pb->pciiowin[i];
+}
+
+static pciconf_win_t *
+get_mem_desc(pciconf_bus_t *pb, bus_size_t size)
+{
+ int i, n;
+
+ n = pb->nmemwin;
+ for (i=n; i > 0 && size > pb->pcimemwin[i-1].size; i--)
+ pb->pcimemwin[i] = pb->pcimemwin[i-1]; /* struct copy */
+ return &pb->pcimemwin[i];
+}
+
+/*
+ * Set up bus common stuff, then loop over devices & functions.
+ * If we find something, call pci_do_device_query()).
+ */
+static int
+probe_bus(pciconf_bus_t *pb)
+{
+ int device, maxdevs;
+
+ maxdevs = pci_bus_maxdevs(pb->pc, pb->busno);
+ pb->ndevs = 0;
+ pb->niowin = 0;
+ pb->nmemwin = 0;
+ pb->freq_66 = 1;
+ pb->fast_b2b = 1;
+ pb->prefetch = 1;
+ pb->max_mingnt = 0; /* we are looking for the maximum */
+ pb->min_maxlat = 0x100; /* we are looking for the minimum */
+ pb->bandwidth_used = 0;
+ for (device=0; device < maxdevs; device++) {
+ pcitag_t tag;
+ pcireg_t id, bhlcr;
+ int function, nfunction;
+
+ tag = pci_make_tag(pb->pc, pb->busno, device, 0);
+#ifdef PCI_CONFIGURATION_DEBUG
+ if (pci_conf_debug) {
+ print_tag(pb->pc, tag);
+ printf("probing.\n");
+ }
+#endif
+ id = pci_conf_read(pb->pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+
+ bhlcr = pci_conf_read(pb->pc, tag, PCI_BHLC_REG);
+ nfunction = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
+ for (function = 0 ; function < nfunction ; function++) {
+ tag = pci_make_tag(pb->pc, pb->busno, device, function);
+ id = pci_conf_read(pb->pc, tag, PCI_ID_REG);
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ if (pb->ndevs+1 < MAX_CONF_DEV) {
+#ifdef PCI_CONFIGURATION_DEBUG
+ if (pci_conf_debug) {
+ print_tag(pb->pc, tag);
+ printf("Found dev--really probing.\n");
+ }
+#endif
+ if (pci_do_device_query(pb, tag, device,
+ function))
+ return -1;
+ pb->ndevs++;
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+alloc_busno(pciconf_bus_t *parent, pciconf_bus_t *pb)
+{
+ pb->busno = parent->next_busno;
+ if (parent->next_busno + parent->busno_spacing > parent->last_busno)
+ panic("Too many PCI busses on bus %d", parent->busno);
+ parent->next_busno = parent->next_busno + parent->busno_spacing;
+ pb->next_busno = pb->busno+1;
+ pb->busno_spacing = parent->busno_spacing >> 1;
+ if (!pb->busno_spacing)
+ panic("PCI busses nested too deep.");
+ pb->last_busno = parent->next_busno - 1;
+}
+
+static pciconf_bus_t *
+query_bus(pciconf_bus_t *parent, pciconf_dev_t *pd, int dev)
+{
+ pciconf_bus_t *pb;
+ pcireg_t busreg;
+ pciconf_win_t *pi, *pm;
+
+ pb = malloc (sizeof (pciconf_bus_t), M_DEVBUF, M_NOWAIT);
+ if (!pb)
+ panic("Unable to allocate memory for PCI configuration.");
+
+ pb->parent_bus = parent;
+ alloc_busno(parent, pb);
+#ifdef PCI_CONFIGURATION_DEBUG
+ if (pci_conf_debug)
+ printf("PCI bus bridge covers busses %d-%d\n",
+ pb->busno, pb->last_busno);
+#endif
+
+ busreg = parent->busno << PCI_BRIDGE_BUS_PRIMARY_SHIFT;
Home |
Main Index |
Thread Index |
Old Index