Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/i2o Rough I2O LAN interface driver. Needs a bit of w...



details:   https://anonhg.NetBSD.org/src/rev/bfab8436ee45
branches:  trunk
changeset: 513639:bfab8436ee45
user:      ad <ad%NetBSD.org@localhost>
date:      Mon Aug 06 12:12:36 2001 +0000

description:
Rough I2O LAN interface driver. Needs a bit of work.

diffstat:

 sys/dev/i2o/iopl.c    |  1566 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/i2o/ioplvar.h |   129 ++++
 2 files changed, 1695 insertions(+), 0 deletions(-)

diffs (truncated from 1703 to 300 lines):

diff -r f9ecf485d68b -r bfab8436ee45 sys/dev/i2o/iopl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/i2o/iopl.c        Mon Aug 06 12:12:36 2001 +0000
@@ -0,0 +1,1566 @@
+/*     $NetBSD: iopl.c,v 1.1 2001/08/06 12:12:36 ad Exp $      */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * 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 by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is a rough and untested driver for I2O LAN interfaces.  It has at
+ * least these issues:
+ *
+ * - Media selection isn't done, although media status is.
+ * - Doesn't handle token-ring or FDDI.
+ * - The multicast filter doesn't get programmed.
+ * - Hardware checksumming on the receive side is never enabled.
+ * - Block I/O and network device driver IPLs differ.
+ * - Will leak descriptors & mbufs on transport failure.
+ */
+
+#include "opt_i2o.h"
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/endian.h>
+#include <sys/proc.h>
+#include <sys/callout.h>
+#include <sys/socket.h>
+#include <sys/malloc.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_ether.h>
+#include <net/if_fddi.h>
+#include <net/if_token.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <dev/i2o/i2o.h>
+#include <dev/i2o/iopio.h>
+#include <dev/i2o/iopvar.h>
+#include <dev/i2o/ioplvar.h>
+
+static void    iopl_attach(struct device *, struct device *, void *);
+static int     iopl_match(struct device *, struct cfdata *, void *);
+
+static void    iopl_error(struct iopl_softc *, u_int);
+static void    iopl_getpg(struct iopl_softc *, int);
+static void    iopl_intr_pg(struct device *, struct iop_msg *, void *);
+static void    iopl_intr_evt(struct device *, struct iop_msg *, void *);
+static void    iopl_intr_null(struct device *, struct iop_msg *, void *);
+static void    iopl_intr_rx(struct device *, struct iop_msg *, void *);
+static void    iopl_intr_tx(struct device *, struct iop_msg *, void *);
+static void    iopl_tick(void *);
+static void    iopl_tick_sched(struct iopl_softc *);
+
+static int     iopl_rx_alloc(struct iopl_softc *, int);
+static void    iopl_rx_free(struct iopl_softc *);
+static void    iopl_rx_post(struct iopl_softc *);
+static int     iopl_tx_alloc(struct iopl_softc *, int);
+static void    iopl_tx_free(struct iopl_softc *);
+
+static int     iopl_ifmedia_change(struct ifnet *);
+static void    iopl_ifmedia_status(struct ifnet *, struct ifmediareq *);
+
+static int     iopl_init(struct ifnet *);
+static int     iopl_ioctl(struct ifnet *, u_long, caddr_t);
+static void    iopl_start(struct ifnet *);
+static void    iopl_stop(struct ifnet *, int);
+
+struct cfattach iopl_ca = {
+       sizeof(struct iopl_softc), iopl_match, iopl_attach,
+};
+
+#ifdef I2OVERBOSE
+static const char * const iopl_errors[] = {
+       "success",
+       "device failure",
+       "destination not found",
+       "transmit error",
+       "transmit aborted",
+       "receive error",
+       "receive aborted",
+       "DMA error",
+       "bad packet detected",
+       "out of memory",
+       "bucket overrun",
+       "IOP internal error",
+       "cancelled",
+       "invalid transaction context",
+       "destination address detected",
+       "destination address omitted",
+       "partial packet returned",
+       "temporarily suspended",
+};
+#endif /* I2OVERBOSE */
+
+static const struct iopl_media iopl_ether_media[] = {
+       { I2O_LAN_CONNECTION_100BASEVG_ETHERNET,        IFM_100_VG },
+       { I2O_LAN_CONNECTION_100BASEVG_TOKEN_RING,      IFM_100_VG },
+       { I2O_LAN_CONNECTION_ETHERNET_AUI,              IFM_10_5 },
+       { I2O_LAN_CONNECTION_ETHERNET_10BASE5,          IFM_10_5 },
+       { I2O_LAN_CONNECTION_ETHERNET_10BASE2,          IFM_10_2 },
+       { I2O_LAN_CONNECTION_ETHERNET_10BASET,          IFM_10_T },
+       { I2O_LAN_CONNECTION_ETHERNET_10BASEFL,         IFM_10_FL },
+       { I2O_LAN_CONNECTION_ETHERNET_100BASETX,        IFM_100_TX },
+       { I2O_LAN_CONNECTION_ETHERNET_100BASEFX,        IFM_100_FX },
+       { I2O_LAN_CONNECTION_ETHERNET_100BASET4,        IFM_100_T4 },
+       { I2O_LAN_CONNECTION_ETHERNET_1000BASESX,       IFM_1000_SX },
+       { I2O_LAN_CONNECTION_ETHERNET_1000BASELX,       IFM_1000_LX },
+       { I2O_LAN_CONNECTION_ETHERNET_1000BASECX,       IFM_1000_CX },
+       { I2O_LAN_CONNECTION_ETHERNET_1000BASET,        IFM_1000_T },
+       { I2O_LAN_CONNECTION_DEFAULT,                   IFM_10_T }
+};
+ 
+/*
+ * Match a supported device.
+ */
+static int
+iopl_match(struct device *parent, struct cfdata *match, void *aux)
+{
+
+       return (((struct iop_attach_args *)aux)->ia_class == I2O_CLASS_LAN);
+}
+
+/*
+ * Attach a supported device.
+ */
+static void
+iopl_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct iop_attach_args *ia;
+       struct iopl_softc *sc;
+       struct iop_softc *iop;
+       struct ifnet *ifp;
+       int rv, iff, ifcap, prepad, orphanlimit, maxpktsize;
+       struct {
+               struct  i2o_param_op_results pr;
+               struct  i2o_param_read_results prr;
+               union {
+                       struct  i2o_param_lan_device_info ldi;
+                       struct  i2o_param_lan_transmit_info ti;
+                       struct  i2o_param_lan_receive_info ri;
+                       struct  i2o_param_lan_operation lo;
+                       struct  i2o_param_lan_batch_control bc;
+               } p;
+       } __attribute__ ((__packed__)) param;
+       const char *typestr, *addrstr;
+       char wwn[20];
+       u_int tmp;
+
+       sc = (struct iopl_softc *)self;
+       iop = (struct iop_softc *)parent;
+       ia = (struct iop_attach_args *)aux;
+       ifp = &sc->sc_if.sci_if;
+       sc->sc_tid = ia->ia_tid;
+       sc->sc_dmat = iop->sc_dmat;
+
+       /* Say what the device is. */
+       printf(": LAN interface");
+       iop_print_ident(iop, ia->ia_tid);
+       printf("\n");
+
+       rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_LAN_DEVICE_INFO,
+           &param, sizeof(param));
+       if (rv != 0) {
+               printf("%s: unable to get parameters (0x%04x; %d)\n",
+                  self->dv_xname, I2O_PARAM_LAN_DEVICE_INFO, rv);
+               return;
+       }
+
+       sc->sc_ms_pg = -1;
+
+       switch (sc->sc_mtype = le16toh(param.p.ldi.lantype)) {
+       case I2O_LAN_TYPE_ETHERNET:
+               typestr = "Ethernet";
+               addrstr = ether_sprintf(param.p.ldi.hwaddr);
+               sc->sc_ms_pg = I2O_PARAM_LAN_802_3_STATS;
+               iff = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+               prepad = 2;
+               orphanlimit = sizeof(struct ether_header);
+               break;
+
+       case I2O_LAN_TYPE_100BASEVG:
+               typestr = "100VG-AnyLAN";
+               addrstr = ether_sprintf(param.p.ldi.hwaddr);
+               sc->sc_ms_pg = I2O_PARAM_LAN_802_3_STATS;
+               iff = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+               prepad = 2;
+               orphanlimit = sizeof(struct ether_header);
+               break;
+
+       case I2O_LAN_TYPE_TOKEN_RING:
+               typestr = "token ring";
+               addrstr = token_sprintf(param.p.ldi.hwaddr);
+               iff = IFF_BROADCAST | IFF_MULTICAST;
+               break;
+
+       case I2O_LAN_TYPE_FDDI:
+               typestr = "FDDI";
+               addrstr = fddi_sprintf(param.p.ldi.hwaddr);
+               iff = IFF_BROADCAST | IFF_MULTICAST;
+               break;
+
+       case I2O_LAN_TYPE_FIBRECHANNEL:
+               typestr = "fibre channel";
+               addrstr = wwn;
+               sprintf(wwn, "%08x%08x",
+                   ((u_int32_t *)param.p.ldi.hwaddr)[0],
+                   ((u_int32_t *)param.p.ldi.hwaddr)[1]);
+               iff = IFF_BROADCAST | IFF_MULTICAST;
+               break;
+
+       default:
+               typestr = "unknown medium";
+               addrstr = "unknown";
+               break;
+       }
+
+       printf("%s: %s, address %s, %d Mb/s maximum\n", self->dv_xname,
+           typestr, addrstr,
+           (int)(le64toh(param.p.ldi.maxrxbps) / 1000*1000));
+       maxpktsize = le32toh(param.p.ldi.maxpktsize);
+
+       if (sc->sc_ms_pg == -1) {
+               printf("%s: medium not supported\n", self->dv_xname);
+               return;
+       }
+
+       /*
+        * Register our initiators.
+        */
+       sc->sc_ii_pg.ii_dv = self;
+       sc->sc_ii_pg.ii_intr = iopl_intr_pg;
+       sc->sc_ii_pg.ii_flags = 0;
+       sc->sc_ii_pg.ii_tid = ia->ia_tid;
+       iop_initiator_register(iop, &sc->sc_ii_pg);
+
+       sc->sc_ii_evt.ii_dv = self;
+       sc->sc_ii_evt.ii_intr = iopl_intr_evt;
+       sc->sc_ii_evt.ii_flags = II_NOTCTX | II_UTILITY;
+       sc->sc_ii_evt.ii_tid = ia->ia_tid;
+       iop_initiator_register(iop, &sc->sc_ii_evt);
+
+       sc->sc_ii_null.ii_dv = self;
+       sc->sc_ii_null.ii_intr = iopl_intr_null;
+       sc->sc_ii_null.ii_flags = II_NOTCTX | II_UTILITY;
+       sc->sc_ii_null.ii_tid = ia->ia_tid;
+       iop_initiator_register(iop, &sc->sc_ii_evt);
+
+       sc->sc_ii_rx.ii_dv = self;
+       sc->sc_ii_rx.ii_intr = iopl_intr_rx;
+       sc->sc_ii_rx.ii_flags = II_NOTCTX | II_UTILITY;
+       sc->sc_ii_rx.ii_tid = ia->ia_tid;



Home | Main Index | Thread Index | Old Index