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