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,
+ ¶m, 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