Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-6]: src/sys/dev/pci Pull up revision 1.1 (requested by mrg in t...
details: https://anonhg.NetBSD.org/src/rev/3ddff5fa56a7
branches: netbsd-1-6
changeset: 530819:3ddff5fa56a7
user: tron <tron%NetBSD.org@localhost>
date: Sun Oct 05 11:47:15 2003 +0000
description:
Pull up revision 1.1 (requested by mrg in ticket #1486):
add new driver for broadcom BCM4401 chipset (as seen on recent dell
laptops) written by Cliff Wright <cliff%snipe444.org@localhost> and tested by
yours truly.
XXX: missing mcast filter support.
thanks cliff!
diffstat:
sys/dev/pci/if_bce.c | 1439 +++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/pci/if_bcereg.h | 208 ++++++
2 files changed, 1647 insertions(+), 0 deletions(-)
diffs (truncated from 1655 to 300 lines):
diff -r 2c040b9570be -r 3ddff5fa56a7 sys/dev/pci/if_bce.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/if_bce.c Sun Oct 05 11:47:15 2003 +0000
@@ -0,0 +1,1439 @@
+/* $NetBSD: if_bce.c,v 1.3.2.2 2003/10/05 11:47:15 tron Exp $ */
+
+/*
+ * Copyright (c) 2003 Clifford Wright. 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.
+ */
+
+/*
+ * Broadcom BCM440x 10/100 ethernet (broadcom.com)
+ * SiliconBackplane is technology from Sonics, Inc.(sonicsinc.com)
+ *
+ * Cliff Wright cliff%snipe444.org@localhost
+ */
+
+#include "bpfilter.h"
+#include "vlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_ether.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+#include <dev/mii/brgphyreg.h>
+
+#include <dev/pci/if_bcereg.h>
+
+#include <uvm/uvm_extern.h>
+
+static int bce_probe(struct device *, struct cfdata *, void *);
+static void bce_attach(struct device *, struct device *, void *);
+static int bce_ioctl(struct ifnet *, u_long, caddr_t);
+static void bce_start __P((struct ifnet *));
+static void bce_watchdog __P((struct ifnet *));
+static int bce_intr(void *);
+static void bce_rxintr __P((struct bce_softc *));
+static void bce_txintr __P((struct bce_softc *));
+static int bce_init __P((struct ifnet *));
+static void bce_add_mac
+ __P((struct bce_softc *, unsigned char *, unsigned long));
+static int bce_add_rxbuf __P((struct bce_softc *, int));
+static void bce_rxdrain __P((struct bce_softc *));
+static void bce_stop __P((struct ifnet *, int));
+static void bce_reset __P((struct bce_softc *));
+static void bce_set_filter __P((struct ifnet *));
+static int bce_mii_read __P((struct device *, int, int));
+static void bce_mii_write __P((struct device *, int, int, int));
+static void bce_statchg __P((struct device *));
+static int bce_mediachange __P((struct ifnet *));
+static void bce_mediastatus __P((struct ifnet *, struct ifmediareq *));
+static void bce_tick __P((void *));
+
+#define BCE_DEBUG
+#ifdef BCE_DEBUG
+#define DPRINTF(x) if (bcedebug) printf x
+#define DPRINTFN(n,x) if (bcedebug >= (n)) printf x
+int bcedebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+/* for ring descriptors */
+#define BCE_RXBUF_LEN (MCLBYTES - 4)
+#define BCE_INIT_RXDESC(sc, x) \
+do { \
+ struct bce_dma_slot *__bced = &sc->bce_rx_ring[x]; \
+ \
+ *mtod(sc->bce_cdata.bce_rx_chain[x], long *) = 0; \
+ __bced->addr = \
+ htole32(sc->bce_cdata.bce_rx_map[x]->dm_segs[0].ds_addr \
+ + 0x40000000); \
+ if (x != (BCE_NRXDESC - 1)) \
+ __bced->ctrl = htole32(BCE_RXBUF_LEN); \
+ else \
+ __bced->ctrl = htole32(BCE_RXBUF_LEN | CTRL_EOT); \
+ bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map, \
+ sizeof(struct bce_dma_slot) * x, \
+ sizeof(struct bce_dma_slot), \
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
+} while(0)
+
+#ifdef OLDNETBSD
+struct cfattach bce_ca = {
+ sizeof(struct bce_softc), bce_probe, bce_attach
+};
+#else
+CFATTACH_DECL(bce, sizeof(struct bce_softc),
+ bce_probe, bce_attach, NULL, NULL);
+#endif
+
+static const struct bce_product {
+ pci_vendor_id_t bp_vendor;
+ pci_product_id_t bp_product;
+ const char *bp_name;
+} bce_products[] = {
+ {
+ PCI_VENDOR_BROADCOM,
+ PCI_PRODUCT_BROADCOM_BCM4401,
+ "Broadcom BCM4401 10/100 Ethernet"
+ },
+ {
+ 0,
+ 0,
+ NULL
+ },
+};
+
+static const struct bce_product *
+bce_lookup(const struct pci_attach_args * pa)
+{
+ const struct bce_product *bp;
+
+ for (bp = bce_products; bp->bp_name != NULL; bp++) {
+ if (PCI_VENDOR(pa->pa_id) == bp->bp_vendor &&
+ PCI_PRODUCT(pa->pa_id) == bp->bp_product)
+ return (bp);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Probe for a Broadcom chip. Check the PCI vendor and device IDs
+ * against drivers product list, and return its name if a match is found.
+ */
+int
+bce_probe(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pci_attach_args *pa = (struct pci_attach_args *) aux;
+
+ if (bce_lookup(pa) != NULL)
+ return (1);
+
+ return (0);
+}
+
+void
+bce_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct bce_softc *sc = (struct bce_softc *) self;
+ struct pci_attach_args *pa = aux;
+ const struct bce_product *bp;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pci_intr_handle_t ih;
+ const char *intrstr = NULL;
+ caddr_t kva;
+ bus_dma_segment_t seg;
+ int rseg;
+ u_int32_t command;
+ struct ifnet *ifp;
+ pcireg_t memtype;
+ bus_addr_t memaddr;
+ bus_size_t memsize;
+ int pmreg;
+ pcireg_t pmode;
+ int error;
+ int i;
+
+ bp = bce_lookup(pa);
+ KASSERT(bp != NULL);
+
+ sc->bce_pa = *pa;
+ sc->bce_dmatag = pa->pa_dmat;
+
+ printf(": %s\n", bp->bp_name);
+ /*
+ * following is for new aprint_naive(": Ethernet controller\n");
+ * aprint_normal(": %s\n", bp->bp_name);
+ */
+
+ /*
+ * Map control/status registers.
+ */
+ command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+ command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
+ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
+ command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+
+ if (!(command & PCI_COMMAND_MEM_ENABLE)) {
+ printf("%s: failed to enable memory mapping!\n",
+ /*
+ * following line for new aprint_error("%s: failed to enable
+ * memory mapping!\n",
+ */
+ sc->bce_dev.dv_xname);
+ return;
+ }
+ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0);
+ switch (memtype) {
+ case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
+ if (pci_mapreg_map(pa, BCE_PCI_BAR0,
+ memtype, 0, &sc->bce_btag, &sc->bce_bhandle,
+ &memaddr, &memsize) == 0)
+ break;
+ default:
+ printf("%s: unable to find mem space\n",
+ /*
+ * following for new aprint_error("%s: unable to find mem
+ * space\n",
+ */
+ sc->bce_dev.dv_xname);
+ return;
+ }
+
+ /* Get it out of power save mode if needed. */
+ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
+ pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3;
+ if (pmode == 3) {
+ /*
+ * The card has lost all configuration data in
+ * this state, so punt.
+ */
+ printf("%s: unable to wake up from power state D3\n",
+ sc->bce_dev.dv_xname);
+ return;
+ }
+ if (pmode != 0) {
+ printf("%s: waking up from power state D%d\n",
+ sc->bce_dev.dv_xname, pmode);
+ pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0);
+ }
+ }
+ if (pci_intr_map(pa, &ih)) {
+ printf("%s: couldn't map interrupt\n",
+ /*
+ * following for new aprint_error("%s: couldn't map
+ * interrupt\n",
+ */
+ sc->bce_dev.dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, ih);
+
+ sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc);
+
+ if (sc->bce_intrhand == NULL) {
+ printf("%s: couldn't establish interrupt",
+ /*
+ * following for new aprint_error("%s: couldn't establish
+ * interrupt",
Home |
Main Index |
Thread Index |
Old Index