The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/scsipi/if_se.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_se.c,v 1.72 2008/06/08 18:18:34 tsutsui Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1997 Ian W. Dall <ian.dall@dsto.defence.gov.au>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Ian W. Dall.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Driver for Cabletron EA41x scsi ethernet adaptor.
   35  *
   36  * Written by Ian Dall <ian.dall@dsto.defence.gov.au> Feb 3, 1997
   37  *
   38  * Acknowledgement: Thanks are due to Philip L. Budne <budd@cs.bu.edu>
   39  * who reverse engineered the EA41x. In developing this code,
   40  * Phil's userland daemon "etherd", was refered to extensively in lieu
   41  * of accurate documentation for the device.
   42  *
   43  * This is a weird device! It doesn't conform to the scsi spec in much
   44  * at all. About the only standard command supported is inquiry. Most
   45  * commands are 6 bytes long, but the recv data is only 1 byte.  Data
   46  * must be received by periodically polling the device with the recv
   47  * command.
   48  *
   49  * This driver is also a bit unusual. It must look like a network
   50  * interface and it must also appear to be a scsi device to the scsi
   51  * system. Hence there are cases where there are two entry points. eg
   52  * sestart is to be called from the scsi subsytem and se_ifstart from
   53  * the network interface subsystem.  In addition, to facilitate scsi
   54  * commands issued by userland programs, there are open, close and
   55  * ioctl entry points. This allows a user program to, for example,
   56  * display the ea41x stats and download new code into the adaptor ---
   57  * functions which can't be performed through the ifconfig interface.
   58  * Normal operation does not require any special userland program.
   59  */
   60 
   61 #include <sys/cdefs.h>
   62 __KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.72 2008/06/08 18:18:34 tsutsui Exp $");
   63 
   64 #include "opt_inet.h"
   65 #include "opt_atalk.h"
   66 #include "bpfilter.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/callout.h>
   71 #include <sys/syslog.h>
   72 #include <sys/kernel.h>
   73 #include <sys/file.h>
   74 #include <sys/stat.h>
   75 #include <sys/ioctl.h>
   76 #include <sys/buf.h>
   77 #include <sys/uio.h>
   78 #include <sys/malloc.h>
   79 #include <sys/errno.h>
   80 #include <sys/device.h>
   81 #include <sys/disklabel.h>
   82 #include <sys/disk.h>
   83 #include <sys/proc.h>
   84 #include <sys/conf.h>
   85 
   86 #include <dev/scsipi/scsipi_all.h>
   87 #include <dev/scsipi/scsi_ctron_ether.h>
   88 #include <dev/scsipi/scsiconf.h>
   89 
   90 #include <sys/mbuf.h>
   91 
   92 #include <sys/socket.h>
   93 #include <net/if.h>
   94 #include <net/if_dl.h>
   95 #include <net/if_ether.h>
   96 #include <net/if_media.h>
   97 
   98 #ifdef INET
   99 #include <netinet/in.h>
  100 #include <netinet/if_inarp.h>
  101 #endif
  102 
  103 
  104 #ifdef NETATALK
  105 #include <netatalk/at.h>
  106 #endif
  107 
  108 
  109 #if NBPFILTER > 0
  110 #include <net/bpf.h>
  111 #include <net/bpfdesc.h>
  112 #endif
  113 
  114 #define SETIMEOUT       1000
  115 #define SEOUTSTANDING   4
  116 #define SERETRIES       4
  117 #define SE_PREFIX       4
  118 #define ETHER_CRC       4
  119 #define SEMINSIZE       60
  120 
  121 /* Make this big enough for an ETHERMTU packet in promiscuous mode. */
  122 #define MAX_SNAP        (ETHERMTU + sizeof(struct ether_header) + \
  123                          SE_PREFIX + ETHER_CRC)
  124 
  125 /* 10 full length packets appears to be the max ever returned. 16k is OK */
  126 #define RBUF_LEN        (16 * 1024)
  127 
  128 /* Tuning parameters:
  129  * The EA41x only returns a maximum of 10 packets (regardless of size).
  130  * We will attempt to adapt to polling fast enough to get RDATA_GOAL packets
  131  * per read
  132  */
  133 #define RDATA_MAX 10
  134 #define RDATA_GOAL 8
  135 
  136 /* se_poll and se_poll0 are the normal polling rate and the minimum
  137  * polling rate respectively. se_poll0 should be chosen so that at
  138  * maximum ethernet speed, we will read nearly RDATA_MAX packets. se_poll
  139  * should be chosen for reasonable maximum latency.
  140  * In practice, if we are being saturated with min length packets, we
  141  * can't poll fast enough. Polling with zero delay actually
  142  * worsens performance. se_poll0 is enforced to be always at least 1
  143  */
  144 #define SE_POLL 40              /* default in milliseconds */
  145 #define SE_POLL0 10             /* default in milliseconds */
  146 int se_poll = 0;                /* Delay in ticks set at attach time */
  147 int se_poll0 = 0;
  148 int se_max_received = 0;        /* Instrumentation */
  149 
  150 #define PROTOCMD(p, d) \
  151         ((d) = (p))
  152 
  153 #define PROTOCMD_DECL(name) \
  154         static const struct scsi_ctron_ether_generic name
  155 
  156 #define PROTOCMD_DECL_SPECIAL(name) \
  157         static const struct __CONCAT(scsi_,name) name
  158 
  159 /* Command initializers for commands using scsi_ctron_ether_generic */
  160 PROTOCMD_DECL(ctron_ether_send)  = {CTRON_ETHER_SEND, 0, {0,0}, 0};
  161 PROTOCMD_DECL(ctron_ether_add_proto) = {CTRON_ETHER_ADD_PROTO, 0, {0,0}, 0};
  162 PROTOCMD_DECL(ctron_ether_get_addr) = {CTRON_ETHER_GET_ADDR, 0, {0,0}, 0};
  163 PROTOCMD_DECL(ctron_ether_set_media) = {CTRON_ETHER_SET_MEDIA, 0, {0,0}, 0};
  164 PROTOCMD_DECL(ctron_ether_set_addr) = {CTRON_ETHER_SET_ADDR, 0, {0,0}, 0};
  165 PROTOCMD_DECL(ctron_ether_set_multi) = {CTRON_ETHER_SET_MULTI, 0, {0,0}, 0};
  166 PROTOCMD_DECL(ctron_ether_remove_multi) =
  167     {CTRON_ETHER_REMOVE_MULTI, 0, {0,0}, 0};
  168 
  169 /* Command initializers for commands using their own structures */
  170 PROTOCMD_DECL_SPECIAL(ctron_ether_recv) = {CTRON_ETHER_RECV};
  171 PROTOCMD_DECL_SPECIAL(ctron_ether_set_mode) =
  172     {CTRON_ETHER_SET_MODE, 0, {0,0}, 0};
  173 
  174 struct se_softc {
  175         struct device sc_dev;
  176         struct ethercom sc_ethercom;    /* Ethernet common part */
  177         struct scsipi_periph *sc_periph;/* contains our targ, lun, etc. */
  178 
  179         struct callout sc_ifstart_ch;
  180         struct callout sc_recv_ch;
  181 
  182         char *sc_tbuf;
  183         char *sc_rbuf;
  184         int protos;
  185 #define PROTO_IP        0x01
  186 #define PROTO_ARP       0x02
  187 #define PROTO_REVARP    0x04
  188 #define PROTO_AT        0x08
  189 #define PROTO_AARP      0x10
  190         int sc_debug;
  191         int sc_flags;
  192 #define SE_NEED_RECV 0x1
  193         int sc_last_timeout;
  194         int sc_enabled;
  195 };
  196 
  197 static int      sematch(struct device *, struct cfdata *, void *);
  198 static void     seattach(struct device *, struct device *, void *);
  199 
  200 static void     se_ifstart(struct ifnet *);
  201 static void     sestart(struct scsipi_periph *);
  202 
  203 static void     sedone(struct scsipi_xfer *, int);
  204 static int      se_ioctl(struct ifnet *, u_long, void *);
  205 static void     sewatchdog(struct ifnet *);
  206 
  207 static inline u_int16_t ether_cmp(void *, void *);
  208 static void     se_recv(void *);
  209 static struct mbuf *se_get(struct se_softc *, char *, int);
  210 static int      se_read(struct se_softc *, char *, int);
  211 static int      se_reset(struct se_softc *);
  212 static int      se_add_proto(struct se_softc *, int);
  213 static int      se_get_addr(struct se_softc *, u_int8_t *);
  214 static int      se_set_media(struct se_softc *, int);
  215 static int      se_init(struct se_softc *);
  216 static int      se_set_multi(struct se_softc *, u_int8_t *);
  217 static int      se_remove_multi(struct se_softc *, u_int8_t *);
  218 #if 0
  219 static int      sc_set_all_multi(struct se_softc *, int);
  220 #endif
  221 static void     se_stop(struct se_softc *);
  222 static inline int se_scsipi_cmd(struct scsipi_periph *periph,
  223                         struct scsipi_generic *scsipi_cmd,
  224                         int cmdlen, u_char *data_addr, int datalen,
  225                         int retries, int timeout, struct buf *bp,
  226                         int flags);
  227 static void     se_delayed_ifstart(void *);
  228 static int      se_set_mode(struct se_softc *, int, int);
  229 
  230 int     se_enable(struct se_softc *);
  231 void    se_disable(struct se_softc *);
  232 
  233 CFATTACH_DECL(se, sizeof(struct se_softc),
  234     sematch, seattach, NULL, NULL);
  235 
  236 extern struct cfdriver se_cd;
  237 
  238 dev_type_open(seopen);
  239 dev_type_close(seclose);
  240 dev_type_ioctl(seioctl);
  241 
  242 const struct cdevsw se_cdevsw = {
  243         seopen, seclose, noread, nowrite, seioctl,
  244         nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
  245 };
  246 
  247 const struct scsipi_periphsw se_switch = {
  248         NULL,                   /* Use default error handler */
  249         sestart,                /* have a queue, served by this */
  250         NULL,                   /* have no async handler */
  251         sedone,                 /* deal with stats at interrupt time */
  252 };
  253 
  254 const struct scsipi_inquiry_pattern se_patterns[] = {
  255         {T_PROCESSOR, T_FIXED,
  256          "CABLETRN",         "EA412",                 ""},
  257         {T_PROCESSOR, T_FIXED,
  258          "Cabletrn",         "EA412",                 ""},
  259 };
  260 
  261 /*
  262  * Compare two Ether/802 addresses for equality, inlined and
  263  * unrolled for speed.
  264  * Note: use this like memcmp()
  265  */
  266 static inline u_int16_t
  267 ether_cmp(one, two)
  268         void *one, *two;
  269 {
  270         u_int16_t *a = (u_int16_t *) one;
  271         u_int16_t *b = (u_int16_t *) two;
  272         u_int16_t diff;
  273 
  274         diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
  275 
  276         return (diff);
  277 }
  278 
  279 #define ETHER_CMP       ether_cmp
  280 
  281 static int
  282 sematch(parent, match, aux)
  283         struct device *parent;
  284         struct cfdata *match;
  285         void *aux;
  286 {
  287         struct scsipibus_attach_args *sa = aux;
  288         int priority;
  289 
  290         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  291             se_patterns, sizeof(se_patterns) / sizeof(se_patterns[0]),
  292             sizeof(se_patterns[0]), &priority);
  293         return (priority);
  294 }
  295 
  296 /*
  297  * The routine called by the low level scsi routine when it discovers
  298  * a device suitable for this driver.
  299  */
  300 static void
  301 seattach(parent, self, aux)
  302         struct device *parent, *self;
  303         void *aux;
  304 {
  305         struct se_softc *sc = device_private(self);
  306         struct scsipibus_attach_args *sa = aux;
  307         struct scsipi_periph *periph = sa->sa_periph;
  308         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  309         u_int8_t myaddr[ETHER_ADDR_LEN];
  310 
  311         printf("\n");
  312         SC_DEBUG(periph, SCSIPI_DB2, ("seattach: "));
  313 
  314         callout_init(&sc->sc_ifstart_ch, 0);
  315         callout_init(&sc->sc_recv_ch, 0);
  316 
  317 
  318         /*
  319          * Store information needed to contact our base driver
  320          */
  321         sc->sc_periph = periph;
  322         periph->periph_dev = &sc->sc_dev;
  323         periph->periph_switch = &se_switch;
  324 
  325         /* XXX increase openings? */
  326 
  327         se_poll = (SE_POLL * hz) / 1000;
  328         se_poll = se_poll? se_poll: 1;
  329         se_poll0 = (SE_POLL0 * hz) / 1000;
  330         se_poll0 = se_poll0? se_poll0: 1;
  331 
  332         /*
  333          * Initialize and attach a buffer
  334          */
  335         sc->sc_tbuf = malloc(ETHERMTU + sizeof(struct ether_header),
  336                              M_DEVBUF, M_NOWAIT);
  337         if (sc->sc_tbuf == 0)
  338                 panic("seattach: can't allocate transmit buffer");
  339 
  340         sc->sc_rbuf = malloc(RBUF_LEN, M_DEVBUF, M_NOWAIT);/* A Guess */
  341         if (sc->sc_rbuf == 0)
  342                 panic("seattach: can't allocate receive buffer");
  343 
  344         se_get_addr(sc, myaddr);
  345 
  346         /* Initialize ifnet structure. */
  347         strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), sizeof(ifp->if_xname));
  348         ifp->if_softc = sc;
  349         ifp->if_start = se_ifstart;
  350         ifp->if_ioctl = se_ioctl;
  351         ifp->if_watchdog = sewatchdog;
  352         ifp->if_flags =
  353             IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
  354         IFQ_SET_READY(&ifp->if_snd);
  355 
  356         /* Attach the interface. */
  357         if_attach(ifp);
  358         ether_ifattach(ifp, myaddr);
  359 }
  360 
  361 
  362 static inline int
  363 se_scsipi_cmd(periph, cmd, cmdlen, data_addr, datalen,
  364                        retries, timeout, bp, flags)
  365         struct scsipi_periph *periph;
  366         struct scsipi_generic *cmd;
  367         int cmdlen;
  368         u_char *data_addr;
  369         int datalen;
  370         int retries;
  371         int timeout;
  372         struct buf *bp;
  373         int flags;
  374 {
  375         int error;
  376         int s = splbio();
  377 
  378         error = scsipi_command(periph, cmd, cmdlen, data_addr,
  379             datalen, retries, timeout, bp, flags);
  380         splx(s);
  381         return (error);
  382 }
  383 
  384 /* Start routine for calling from scsi sub system */
  385 static void
  386 sestart(periph)
  387         struct scsipi_periph *periph;
  388 {
  389         struct se_softc *sc = (void *)periph->periph_dev;
  390         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  391         int s = splnet();
  392 
  393         se_ifstart(ifp);
  394         (void) splx(s);
  395 }
  396 
  397 static void
  398 se_delayed_ifstart(v)
  399         void *v;
  400 {
  401         struct ifnet *ifp = v;
  402         struct se_softc *sc = ifp->if_softc;
  403         int s;
  404 
  405         s = splnet();
  406         if (sc->sc_enabled) {
  407                 ifp->if_flags &= ~IFF_OACTIVE;
  408                 se_ifstart(ifp);
  409         }
  410         splx(s);
  411 }
  412 
  413 /*
  414  * Start transmission on the interface.
  415  * Always called at splnet().
  416  */
  417 static void
  418 se_ifstart(ifp)
  419         struct ifnet *ifp;
  420 {
  421         struct se_softc *sc = ifp->if_softc;
  422         struct scsi_ctron_ether_generic send_cmd;
  423         struct mbuf *m, *m0;
  424         int len, error;
  425         u_char *cp;
  426 
  427         /* Don't transmit if interface is busy or not running */
  428         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  429                 return;
  430 
  431         IFQ_DEQUEUE(&ifp->if_snd, m0);
  432         if (m0 == 0)
  433                 return;
  434 #if NBPFILTER > 0
  435         /* If BPF is listening on this interface, let it see the
  436          * packet before we commit it to the wire.
  437          */
  438         if (ifp->if_bpf)
  439                 bpf_mtap(ifp->if_bpf, m0);
  440 #endif
  441 
  442         /* We need to use m->m_pkthdr.len, so require the header */
  443         if ((m0->m_flags & M_PKTHDR) == 0)
  444                 panic("ctscstart: no header mbuf");
  445         len = m0->m_pkthdr.len;
  446 
  447         /* Mark the interface busy. */
  448         ifp->if_flags |= IFF_OACTIVE;
  449 
  450         /* Chain; copy into linear buffer we allocated at attach time. */
  451         cp = sc->sc_tbuf;
  452         for (m = m0; m != NULL; ) {
  453                 memcpy(cp, mtod(m, u_char *), m->m_len);
  454                 cp += m->m_len;
  455                 MFREE(m, m0);
  456                 m = m0;
  457         }
  458         if (len < SEMINSIZE) {
  459 #ifdef SEDEBUG
  460                 if (sc->sc_debug)
  461                         printf("se: packet size %d (%d) < %d\n", len,
  462                             cp - (u_char *)sc->sc_tbuf, SEMINSIZE);
  463 #endif
  464                 memset(cp, 0, SEMINSIZE - len);
  465                 len = SEMINSIZE;
  466         }
  467 
  468         /* Fill out SCSI command. */
  469         PROTOCMD(ctron_ether_send, send_cmd);
  470         _lto2b(len, send_cmd.length);
  471 
  472         /* Send command to device. */
  473         error = se_scsipi_cmd(sc->sc_periph,
  474             (void *)&send_cmd, sizeof(send_cmd),
  475             sc->sc_tbuf, len, SERETRIES,
  476             SETIMEOUT, NULL, XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_OUT);
  477         if (error) {
  478                 aprint_error_dev(&sc->sc_dev, "not queued, error %d\n", error);
  479                 ifp->if_oerrors++;
  480                 ifp->if_flags &= ~IFF_OACTIVE;
  481         } else
  482                 ifp->if_opackets++;
  483         if (sc->sc_flags & SE_NEED_RECV) {
  484                 sc->sc_flags &= ~SE_NEED_RECV;
  485                 se_recv((void *) sc);
  486         }
  487 }
  488 
  489 
  490 /*
  491  * Called from the scsibus layer via our scsi device switch.
  492  */
  493 static void
  494 sedone(xs, error)
  495         struct scsipi_xfer *xs;
  496         int error;
  497 {
  498         struct se_softc *sc = (void *)xs->xs_periph->periph_dev;
  499         struct scsipi_generic *cmd = xs->cmd;
  500         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  501         int s;
  502 
  503         s = splnet();
  504         if(IS_SEND(cmd)) {
  505                 if (xs->error == XS_BUSY) {
  506                         printf("se: busy, retry txmit\n");
  507                         callout_reset(&sc->sc_ifstart_ch, hz,
  508                             se_delayed_ifstart, ifp);
  509                 } else {
  510                         ifp->if_flags &= ~IFF_OACTIVE;
  511                         /* the generic scsipi_done will call
  512                          * sestart (through scsipi_free_xs).
  513                          */
  514                 }
  515         } else if(IS_RECV(cmd)) {
  516                 /* RECV complete */
  517                 /* pass data up. reschedule a recv */
  518                 /* scsipi_free_xs will call start. Harmless. */
  519                 if (error) {
  520                         /* Reschedule after a delay */
  521                         callout_reset(&sc->sc_recv_ch, se_poll,
  522                             se_recv, (void *)sc);
  523                 } else {
  524                         int n, ntimeo;
  525                         n = se_read(sc, xs->data, xs->datalen - xs->resid);
  526                         if (n > se_max_received)
  527                                 se_max_received = n;
  528                         if (n == 0)
  529                                 ntimeo = se_poll;
  530                         else if (n >= RDATA_MAX)
  531                                 ntimeo = se_poll0;
  532                         else {
  533                                 ntimeo = sc->sc_last_timeout;
  534                                 ntimeo = (ntimeo * RDATA_GOAL)/n;
  535                                 ntimeo = (ntimeo < se_poll0?
  536                                           se_poll0: ntimeo);
  537                                 ntimeo = (ntimeo > se_poll?
  538                                           se_poll: ntimeo);
  539                         }
  540                         sc->sc_last_timeout = ntimeo;
  541                         if (ntimeo == se_poll0  &&
  542                             IFQ_IS_EMPTY(&ifp->if_snd) == 0)
  543                                 /* Output is pending. Do next recv
  544                                  * after the next send.  */
  545                                 sc->sc_flags |= SE_NEED_RECV;
  546                         else {
  547                                 callout_reset(&sc->sc_recv_ch, ntimeo,
  548                                     se_recv, (void *)sc);
  549                         }
  550                 }
  551         }
  552         splx(s);
  553 }
  554 
  555 static void
  556 se_recv(v)
  557         void *v;
  558 {
  559         /* do a recv command */
  560         struct se_softc *sc = (struct se_softc *) v;
  561         struct scsi_ctron_ether_recv recv_cmd;
  562         int error;
  563 
  564         if (sc->sc_enabled == 0)
  565                 return;
  566 
  567         PROTOCMD(ctron_ether_recv, recv_cmd);
  568 
  569         error = se_scsipi_cmd(sc->sc_periph,
  570             (void *)&recv_cmd, sizeof(recv_cmd),
  571             sc->sc_rbuf, RBUF_LEN, SERETRIES, SETIMEOUT, NULL,
  572             XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_IN);
  573         if (error)
  574                 callout_reset(&sc->sc_recv_ch, se_poll, se_recv, (void *)sc);
  575 }
  576 
  577 /*
  578  * We copy the data into mbufs.  When full cluster sized units are present
  579  * we copy into clusters.
  580  */
  581 static struct mbuf *
  582 se_get(sc, data, totlen)
  583         struct se_softc *sc;
  584         char *data;
  585         int totlen;
  586 {
  587         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  588         struct mbuf *m, *m0, *newm;
  589         int len;
  590 
  591         MGETHDR(m0, M_DONTWAIT, MT_DATA);
  592         if (m0 == 0)
  593                 return (0);
  594         m0->m_pkthdr.rcvif = ifp;
  595         m0->m_pkthdr.len = totlen;
  596         len = MHLEN;
  597         m = m0;
  598 
  599         while (totlen > 0) {
  600                 if (totlen >= MINCLSIZE) {
  601                         MCLGET(m, M_DONTWAIT);
  602                         if ((m->m_flags & M_EXT) == 0)
  603                                 goto bad;
  604                         len = MCLBYTES;
  605                 }
  606 
  607                 if (m == m0) {
  608                         char *newdata = (char *)
  609                             ALIGN(m->m_data + sizeof(struct ether_header)) -
  610                             sizeof(struct ether_header);
  611                         len -= newdata - m->m_data;
  612                         m->m_data = newdata;
  613                 }
  614 
  615                 m->m_len = len = min(totlen, len);
  616                 memcpy(mtod(m, void *), data, len);
  617                 data += len;
  618 
  619                 totlen -= len;
  620                 if (totlen > 0) {
  621                         MGET(newm, M_DONTWAIT, MT_DATA);
  622                         if (newm == 0)
  623                                 goto bad;
  624                         len = MLEN;
  625                         m = m->m_next = newm;
  626                 }
  627         }
  628 
  629         return (m0);
  630 
  631 bad:
  632         m_freem(m0);
  633         return (0);
  634 }
  635 
  636 /*
  637  * Pass packets to higher levels.
  638  */
  639 static int
  640 se_read(sc, data, datalen)
  641         struct se_softc *sc;
  642         char *data;
  643         int datalen;
  644 {
  645         struct mbuf *m;
  646         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  647         int n;
  648 
  649         n = 0;
  650         while (datalen >= 2) {
  651                 int len = _2btol(data);
  652                 data += 2;
  653                 datalen -= 2;
  654 
  655                 if (len == 0)
  656                         break;
  657 #ifdef SEDEBUG
  658                 if (sc->sc_debug) {
  659                         printf("se_read: datalen = %d, packetlen = %d, proto = 0x%04x\n", datalen, len,
  660                          ntohs(((struct ether_header *)data)->ether_type));
  661                 }
  662 #endif
  663                 if (len <= sizeof(struct ether_header) ||
  664                     len > MAX_SNAP) {
  665 #ifdef SEDEBUG
  666                         printf("%s: invalid packet size %d; dropping\n",
  667                                device_xname(&sc->sc_dev), len);
  668 #endif
  669                         ifp->if_ierrors++;
  670                         goto next_packet;
  671                 }
  672 
  673                 /* Don't need crc. Must keep ether header for BPF */
  674                 m = se_get(sc, data, len - ETHER_CRC);
  675                 if (m == 0) {
  676 #ifdef SEDEBUG
  677                         if (sc->sc_debug)
  678                                 printf("se_read: se_get returned null\n");
  679 #endif
  680                         ifp->if_ierrors++;
  681                         goto next_packet;
  682                 }
  683                 if ((ifp->if_flags & IFF_PROMISC) != 0) {
  684                         m_adj(m, SE_PREFIX);
  685                 }
  686                 ifp->if_ipackets++;
  687 
  688 #if NBPFILTER > 0
  689                 /*
  690                  * Check if there's a BPF listener on this interface.
  691                  * If so, hand off the raw packet to BPF.
  692                  */
  693                 if (ifp->if_bpf)
  694                         bpf_mtap(ifp->if_bpf, m);
  695 #endif
  696 
  697                 /* Pass the packet up. */
  698                 (*ifp->if_input)(ifp, m);
  699 
  700         next_packet:
  701                 data += len;
  702                 datalen -= len;
  703                 n++;
  704         }
  705         return (n);
  706 }
  707 
  708 
  709 static void
  710 sewatchdog(ifp)
  711         struct ifnet *ifp;
  712 {
  713         struct se_softc *sc = ifp->if_softc;
  714 
  715         log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev));
  716         ++ifp->if_oerrors;
  717 
  718         se_reset(sc);
  719 }
  720 
  721 static int
  722 se_reset(sc)
  723         struct se_softc *sc;
  724 {
  725         int error;
  726         int s = splnet();
  727 #if 0
  728         /* Maybe we don't *really* want to reset the entire bus
  729          * because the ctron isn't working. We would like to send a
  730          * "BUS DEVICE RESET" message, but don't think the ctron
  731          * understands it.
  732          */
  733         error = se_scsipi_cmd(sc->sc_periph, 0, 0, 0, 0, SERETRIES, 2000, NULL,
  734             XS_CTL_RESET);
  735 #endif
  736         error = se_init(sc);
  737         splx(s);
  738         return (error);
  739 }
  740 
  741 static int
  742 se_add_proto(sc, proto)
  743         struct se_softc *sc;
  744         int proto;
  745 {
  746         int error;
  747         struct scsi_ctron_ether_generic add_proto_cmd;
  748         u_int8_t data[2];
  749         _lto2b(proto, data);
  750 #ifdef SEDEBUG
  751         if (sc->sc_debug)
  752                 printf("se: adding proto 0x%02x%02x\n", data[0], data[1]);
  753 #endif
  754 
  755         PROTOCMD(ctron_ether_add_proto, add_proto_cmd);
  756         _lto2b(sizeof(data), add_proto_cmd.length);
  757         error = se_scsipi_cmd(sc->sc_periph,
  758             (void *)&add_proto_cmd, sizeof(add_proto_cmd),
  759             data, sizeof(data), SERETRIES, SETIMEOUT, NULL,
  760             XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK);
  761         return (error);
  762 }
  763 
  764 static int
  765 se_get_addr(sc, myaddr)
  766         struct se_softc *sc;
  767         u_int8_t *myaddr;
  768 {
  769         int error;
  770         struct scsi_ctron_ether_generic get_addr_cmd;
  771 
  772         PROTOCMD(ctron_ether_get_addr, get_addr_cmd);
  773         _lto2b(ETHER_ADDR_LEN, get_addr_cmd.length);
  774         error = se_scsipi_cmd(sc->sc_periph,
  775             (void *)&get_addr_cmd, sizeof(get_addr_cmd),
  776             myaddr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  777             XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
  778         printf("%s: ethernet address %s\n", device_xname(&sc->sc_dev),
  779             ether_sprintf(myaddr));
  780         return (error);
  781 }
  782 
  783 
  784 static int
  785 se_set_media(sc, type)
  786         struct se_softc *sc;
  787         int type;
  788 {
  789         int error;
  790         struct scsi_ctron_ether_generic set_media_cmd;
  791 
  792         PROTOCMD(ctron_ether_set_media, set_media_cmd);
  793         set_media_cmd.byte3 = type;
  794         error = se_scsipi_cmd(sc->sc_periph,
  795             (void *)&set_media_cmd, sizeof(set_media_cmd),
  796             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  797         return (error);
  798 }
  799 
  800 static int
  801 se_set_mode(sc, len, mode)
  802         struct se_softc *sc;
  803         int len;
  804         int mode;
  805 {
  806         int error;
  807         struct scsi_ctron_ether_set_mode set_mode_cmd;
  808 
  809         PROTOCMD(ctron_ether_set_mode, set_mode_cmd);
  810         set_mode_cmd.mode = mode;
  811         _lto2b(len, set_mode_cmd.length);
  812         error = se_scsipi_cmd(sc->sc_periph,
  813             (void *)&set_mode_cmd, sizeof(set_mode_cmd),
  814             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  815         return (error);
  816 }
  817 
  818 
  819 static int
  820 se_init(sc)
  821         struct se_softc *sc;
  822 {
  823         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  824         struct scsi_ctron_ether_generic set_addr_cmd;
  825         uint8_t enaddr[ETHER_ADDR_LEN];
  826         int error;
  827 
  828 #if NBPFILTER > 0
  829         if (ifp->if_flags & IFF_PROMISC) {
  830                 error = se_set_mode(sc, MAX_SNAP, 1);
  831         }
  832         else
  833 #endif
  834                 error = se_set_mode(sc, ETHERMTU + sizeof(struct ether_header),
  835                     0);
  836         if (error != 0)
  837                 return (error);
  838 
  839         PROTOCMD(ctron_ether_set_addr, set_addr_cmd);
  840         _lto2b(ETHER_ADDR_LEN, set_addr_cmd.length);
  841         memcpy(enaddr, CLLADDR(ifp->if_sadl), sizeof(enaddr));
  842         error = se_scsipi_cmd(sc->sc_periph,
  843             (void *)&set_addr_cmd, sizeof(set_addr_cmd),
  844             enaddr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  845             XS_CTL_DATA_OUT);
  846         if (error != 0)
  847                 return (error);
  848 
  849         if ((sc->protos & PROTO_IP) &&
  850             (error = se_add_proto(sc, ETHERTYPE_IP)) != 0)
  851                 return (error);
  852         if ((sc->protos & PROTO_ARP) &&
  853             (error = se_add_proto(sc, ETHERTYPE_ARP)) != 0)
  854                 return (error);
  855         if ((sc->protos & PROTO_REVARP) &&
  856             (error = se_add_proto(sc, ETHERTYPE_REVARP)) != 0)
  857                 return (error);
  858 #ifdef NETATALK
  859         if ((sc->protos & PROTO_AT) &&
  860             (error = se_add_proto(sc, ETHERTYPE_ATALK)) != 0)
  861                 return (error);
  862         if ((sc->protos & PROTO_AARP) &&
  863             (error = se_add_proto(sc, ETHERTYPE_AARP)) != 0)
  864                 return (error);
  865 #endif
  866 
  867         if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) == IFF_UP) {
  868                 ifp->if_flags |= IFF_RUNNING;
  869                 se_recv(sc);
  870                 ifp->if_flags &= ~IFF_OACTIVE;
  871                 se_ifstart(ifp);
  872         }
  873         return (error);
  874 }
  875 
  876 static int
  877 se_set_multi(sc, addr)
  878         struct se_softc *sc;
  879         u_int8_t *addr;
  880 {
  881         struct scsi_ctron_ether_generic set_multi_cmd;
  882         int error;
  883 
  884         if (sc->sc_debug)
  885                 printf("%s: set_set_multi: %s\n", device_xname(&sc->sc_dev),
  886                     ether_sprintf(addr));
  887 
  888         PROTOCMD(ctron_ether_set_multi, set_multi_cmd);
  889         _lto2b(sizeof(addr), set_multi_cmd.length);
  890         /* XXX sizeof(addr) is the size of the pointer.  Surely it
  891          * is too small? --dyoung
  892          */
  893         error = se_scsipi_cmd(sc->sc_periph,
  894             (void *)&set_multi_cmd, sizeof(set_multi_cmd),
  895             addr, sizeof(addr), SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  896         return (error);
  897 }
  898 
  899 static int
  900 se_remove_multi(sc, addr)
  901         struct se_softc *sc;
  902         u_int8_t *addr;
  903 {
  904         struct scsi_ctron_ether_generic remove_multi_cmd;
  905         int error;
  906 
  907         if (sc->sc_debug)
  908                 printf("%s: se_remove_multi: %s\n", device_xname(&sc->sc_dev),
  909                     ether_sprintf(addr));
  910 
  911         PROTOCMD(ctron_ether_remove_multi, remove_multi_cmd);
  912         _lto2b(sizeof(addr), remove_multi_cmd.length);
  913         /* XXX sizeof(addr) is the size of the pointer.  Surely it
  914          * is too small? --dyoung
  915          */
  916         error = se_scsipi_cmd(sc->sc_periph,
  917             (void *)&remove_multi_cmd, sizeof(remove_multi_cmd),
  918             addr, sizeof(addr), SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  919         return (error);
  920 }
  921 
  922 #if 0   /* not used  --thorpej */
  923 static int
  924 sc_set_all_multi(sc, set)
  925         struct se_softc *sc;
  926         int set;
  927 {
  928         int error = 0;
  929         u_int8_t *addr;
  930         struct ethercom *ac = &sc->sc_ethercom;
  931         struct ether_multi *enm;
  932         struct ether_multistep step;
  933 
  934         ETHER_FIRST_MULTI(step, ac, enm);
  935         while (enm != NULL) {
  936                 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
  937                         /*
  938                          * We must listen to a range of multicast addresses.
  939                          * For now, just accept all multicasts, rather than
  940                          * trying to set only those filter bits needed to match
  941                          * the range.  (At this time, the only use of address
  942                          * ranges is for IP multicast routing, for which the
  943                          * range is big enough to require all bits set.)
  944                          */
  945                         /* We have no way of adding a range to this device.
  946                          * stepping through all addresses in the range is
  947                          * typically not possible. The only real alternative
  948                          * is to go into promicuous mode and filter by hand.
  949                          */
  950                         return (ENODEV);
  951 
  952                 }
  953 
  954                 addr = enm->enm_addrlo;
  955                 if ((error = set ? se_set_multi(sc, addr) :
  956                     se_remove_multi(sc, addr)) != 0)
  957                         return (error);
  958                 ETHER_NEXT_MULTI(step, enm);
  959         }
  960         return (error);
  961 }
  962 #endif /* not used */
  963 
  964 static void
  965 se_stop(sc)
  966         struct se_softc *sc;
  967 {
  968 
  969         /* Don't schedule any reads */
  970         callout_stop(&sc->sc_recv_ch);
  971 
  972         /* How can we abort any scsi cmds in progress? */
  973 }
  974 
  975 
  976 /*
  977  * Process an ioctl request.
  978  */
  979 static int
  980 se_ioctl(ifp, cmd, data)
  981         struct ifnet *ifp;
  982         u_long cmd;
  983         void *data;
  984 {
  985         struct se_softc *sc = ifp->if_softc;
  986         struct ifaddr *ifa = (struct ifaddr *)data;
  987         struct ifreq *ifr = (struct ifreq *)data;
  988         struct sockaddr *sa;
  989         int s, error = 0;
  990 
  991         s = splnet();
  992 
  993         switch (cmd) {
  994 
  995         case SIOCSIFADDR:
  996                 if ((error = se_enable(sc)) != 0)
  997                         break;
  998                 ifp->if_flags |= IFF_UP;
  999 
 1000                 if ((error = se_set_media(sc, CMEDIA_AUTOSENSE) != 0))
 1001                         break;
 1002 
 1003                 switch (ifa->ifa_addr->sa_family) {
 1004 #ifdef INET
 1005                 case AF_INET:
 1006                         sc->protos |= (PROTO_IP | PROTO_ARP | PROTO_REVARP);
 1007                         if ((error = se_init(sc)) != 0)
 1008                                 break;
 1009                         arp_ifinit(ifp, ifa);
 1010                         break;
 1011 #endif
 1012 #ifdef NETATALK
 1013                 case AF_APPLETALK:
 1014                         sc->protos |= (PROTO_AT | PROTO_AARP);
 1015                         if ((error = se_init(sc)) != 0)
 1016                                 break;
 1017                         break;
 1018 #endif
 1019                 default:
 1020                         error = se_init(sc);
 1021                         break;
 1022                 }
 1023                 break;
 1024 
 1025 
 1026         case SIOCSIFFLAGS:
 1027                 if ((ifp->if_flags & IFF_UP) == 0 &&
 1028                     (ifp->if_flags & IFF_RUNNING) != 0) {
 1029                         /*
 1030                          * If interface is marked down and it is running, then
 1031                          * stop it.
 1032                          */
 1033                         se_stop(sc);
 1034                         ifp->if_flags &= ~IFF_RUNNING;
 1035                         se_disable(sc);
 1036                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
 1037                            (ifp->if_flags & IFF_RUNNING) == 0) {
 1038                         /*
 1039                          * If interface is marked up and it is stopped, then
 1040                          * start it.
 1041                          */
 1042                         if ((error = se_enable(sc)) != 0)
 1043                                 break;
 1044                         error = se_init(sc);
 1045                 } else if (sc->sc_enabled) {
 1046                         /*
 1047                          * Reset the interface to pick up changes in any other
 1048                          * flags that affect hardware registers.
 1049                          */
 1050                         error = se_init(sc);
 1051                 }
 1052 #ifdef SEDEBUG
 1053                 if (ifp->if_flags & IFF_DEBUG)
 1054                         sc->sc_debug = 1;
 1055                 else
 1056                         sc->sc_debug = 0;
 1057 #endif
 1058                 break;
 1059 
 1060         case SIOCADDMULTI:
 1061         case SIOCDELMULTI:
 1062                 sa = sockaddr_dup(ifreq_getaddr(cmd, ifr), M_NOWAIT);
 1063                 if (sa == NULL) {
 1064                         error = ENOBUFS;
 1065                         break;
 1066                 }
 1067                 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
 1068                         if (ifp->if_flags & IFF_RUNNING) {
 1069                                 error = (cmd == SIOCADDMULTI) ?
 1070                                    se_set_multi(sc, sa->sa_data) :
 1071                                    se_remove_multi(sc, sa->sa_data);
 1072                         } else
 1073                                 error = 0;
 1074                 }
 1075                 sockaddr_free(sa);
 1076                 break;
 1077 
 1078         default:
 1079 
 1080                 error = EINVAL;
 1081                 break;
 1082         }
 1083 
 1084         splx(s);
 1085         return (error);
 1086 }
 1087 
 1088 /*
 1089  * Enable the network interface.
 1090  */
 1091 int
 1092 se_enable(sc)
 1093         struct se_softc *sc;
 1094 {
 1095         struct scsipi_periph *periph = sc->sc_periph;
 1096         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1097         int error = 0;
 1098 
 1099         if (sc->sc_enabled == 0 &&
 1100             (error = scsipi_adapter_addref(adapt)) == 0)
 1101                 sc->sc_enabled = 1;
 1102         else
 1103                 aprint_error_dev(&sc->sc_dev, "device enable failed\n");
 1104 
 1105         return (error);
 1106 }
 1107 
 1108 /*
 1109  * Disable the network interface.
 1110  */
 1111 void
 1112 se_disable(sc)
 1113         struct se_softc *sc;
 1114 {
 1115         struct scsipi_periph *periph = sc->sc_periph;
 1116         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1117 
 1118         if (sc->sc_enabled != 0) {
 1119                 scsipi_adapter_delref(adapt);
 1120                 sc->sc_enabled = 0;
 1121         }
 1122 }
 1123 
 1124 #define SEUNIT(z)       (minor(z))
 1125 /*
 1126  * open the device.
 1127  */
 1128 int
 1129 seopen(dev, flag, fmt, l)
 1130         dev_t dev;
 1131         int flag, fmt;
 1132         struct lwp *l;
 1133 {
 1134         int unit, error;
 1135         struct se_softc *sc;
 1136         struct scsipi_periph *periph;
 1137         struct scsipi_adapter *adapt;
 1138 
 1139         unit = SEUNIT(dev);
 1140         sc = device_lookup_private(&se_cd, unit);
 1141         if (sc == NULL)
 1142                 return (ENXIO);
 1143 
 1144         periph = sc->sc_periph;
 1145         adapt = periph->periph_channel->chan_adapter;
 1146 
 1147         if ((error = scsipi_adapter_addref(adapt)) != 0)
 1148                 return (error);
 1149 
 1150         SC_DEBUG(periph, SCSIPI_DB1,
 1151             ("scopen: dev=0x%x (unit %d (of %d))\n", dev, unit,
 1152             se_cd.cd_ndevs));
 1153 
 1154         periph->periph_flags |= PERIPH_OPEN;
 1155 
 1156         SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
 1157         return (0);
 1158 }
 1159 
 1160 /*
 1161  * close the device.. only called if we are the LAST
 1162  * occurence of an open device
 1163  */
 1164 int
 1165 seclose(dev, flag, fmt, l)
 1166         dev_t dev;
 1167         int flag, fmt;
 1168         struct lwp *l;
 1169 {
 1170         struct se_softc *sc = device_lookup_private(&se_cd, SEUNIT(dev));
 1171         struct scsipi_periph *periph = sc->sc_periph;
 1172         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1173 
 1174         SC_DEBUG(sc->sc_periph, SCSIPI_DB1, ("closing\n"));
 1175 
 1176         scsipi_wait_drain(periph);
 1177 
 1178         scsipi_adapter_delref(adapt);
 1179         periph->periph_flags &= ~PERIPH_OPEN;
 1180 
 1181         return (0);
 1182 }
 1183 
 1184 /*
 1185  * Perform special action on behalf of the user
 1186  * Only does generic scsi ioctls.
 1187  */
 1188 int
 1189 seioctl(dev, cmd, addr, flag, l)
 1190         dev_t dev;
 1191         u_long cmd;
 1192         void *addr;
 1193         int flag;
 1194         struct lwp *l;
 1195 {
 1196         struct se_softc *sc = device_lookup_private(&se_cd, SEUNIT(dev));
 1197 
 1198         return (scsipi_do_ioctl(sc->sc_periph, dev, cmd, addr, flag, l));
 1199 }

Cache object: 00887cc4c6f8eff6d9455a8612f0fb14


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.