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.62 2006/09/07 02:40:33 dogcow 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.62 2006/09/07 02:40:33 dogcow 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, val) \
  154         static const struct scsi_ctron_ether_generic name = val
  155 
  156 #define PROTOCMD_DECL_SPECIAL(name, val) \
  157         static const struct __CONCAT(scsi_,name) name = val
  158 
  159 /* Command initializers for commands using scsi_ctron_ether_generic */
  160 PROTOCMD_DECL(ctron_ether_send, {CTRON_ETHER_SEND});
  161 PROTOCMD_DECL(ctron_ether_add_proto, {CTRON_ETHER_ADD_PROTO});
  162 PROTOCMD_DECL(ctron_ether_get_addr, {CTRON_ETHER_GET_ADDR});
  163 PROTOCMD_DECL(ctron_ether_set_media, {CTRON_ETHER_SET_MEDIA});
  164 PROTOCMD_DECL(ctron_ether_set_addr, {CTRON_ETHER_SET_ADDR});
  165 PROTOCMD_DECL(ctron_ether_set_multi, {CTRON_ETHER_SET_MULTI});
  166 PROTOCMD_DECL(ctron_ether_remove_multi, {CTRON_ETHER_REMOVE_MULTI});
  167 
  168 /* Command initializers for commands using their own structures */
  169 PROTOCMD_DECL_SPECIAL(ctron_ether_recv, {CTRON_ETHER_RECV});
  170 PROTOCMD_DECL_SPECIAL(ctron_ether_set_mode, {CTRON_ETHER_SET_MODE});
  171 
  172 struct se_softc {
  173         struct device sc_dev;
  174         struct ethercom sc_ethercom;    /* Ethernet common part */
  175         struct scsipi_periph *sc_periph;/* contains our targ, lun, etc. */
  176 
  177         struct callout sc_ifstart_ch;
  178         struct callout sc_recv_ch;
  179 
  180         char *sc_tbuf;
  181         char *sc_rbuf;
  182         int protos;
  183 #define PROTO_IP        0x01
  184 #define PROTO_ARP       0x02
  185 #define PROTO_REVARP    0x04
  186 #define PROTO_AT        0x08
  187 #define PROTO_AARP      0x10
  188         int sc_debug;
  189         int sc_flags;
  190 #define SE_NEED_RECV 0x1
  191         int sc_last_timeout;
  192         int sc_enabled;
  193 };
  194 
  195 static int      sematch(struct device *, struct cfdata *, void *);
  196 static void     seattach(struct device *, struct device *, void *);
  197 
  198 static void     se_ifstart(struct ifnet *);
  199 static void     sestart(struct scsipi_periph *);
  200 
  201 static void     sedone(struct scsipi_xfer *, int);
  202 static int      se_ioctl(struct ifnet *, u_long, caddr_t);
  203 static void     sewatchdog(struct ifnet *);
  204 
  205 static inline u_int16_t ether_cmp(void *, void *);
  206 static void     se_recv(void *);
  207 static struct mbuf *se_get(struct se_softc *, char *, int);
  208 static int      se_read(struct se_softc *, char *, int);
  209 static int      se_reset(struct se_softc *);
  210 static int      se_add_proto(struct se_softc *, int);
  211 static int      se_get_addr(struct se_softc *, u_int8_t *);
  212 static int      se_set_media(struct se_softc *, int);
  213 static int      se_init(struct se_softc *);
  214 static int      se_set_multi(struct se_softc *, u_int8_t *);
  215 static int      se_remove_multi(struct se_softc *, u_int8_t *);
  216 #if 0
  217 static int      sc_set_all_multi(struct se_softc *, int);
  218 #endif
  219 static void     se_stop(struct se_softc *);
  220 static inline int se_scsipi_cmd(struct scsipi_periph *periph,
  221                         struct scsipi_generic *scsipi_cmd,
  222                         int cmdlen, u_char *data_addr, int datalen,
  223                         int retries, int timeout, struct buf *bp,
  224                         int flags);
  225 static void     se_delayed_ifstart(void *);
  226 static int      se_set_mode(struct se_softc *, int, int);
  227 
  228 int     se_enable(struct se_softc *);
  229 void    se_disable(struct se_softc *);
  230 
  231 CFATTACH_DECL(se, sizeof(struct se_softc),
  232     sematch, seattach, NULL, NULL);
  233 
  234 extern struct cfdriver se_cd;
  235 
  236 dev_type_open(seopen);
  237 dev_type_close(seclose);
  238 dev_type_ioctl(seioctl);
  239 
  240 const struct cdevsw se_cdevsw = {
  241         seopen, seclose, noread, nowrite, seioctl,
  242         nostop, notty, nopoll, nommap, nokqfilter,
  243 };
  244 
  245 const struct scsipi_periphsw se_switch = {
  246         NULL,                   /* Use default error handler */
  247         sestart,                /* have a queue, served by this */
  248         NULL,                   /* have no async handler */
  249         sedone,                 /* deal with stats at interrupt time */
  250 };
  251 
  252 const struct scsipi_inquiry_pattern se_patterns[] = {
  253         {T_PROCESSOR, T_FIXED,
  254          "CABLETRN",         "EA412",                 ""},
  255         {T_PROCESSOR, T_FIXED,
  256          "Cabletrn",         "EA412",                 ""},
  257 };
  258 
  259 /*
  260  * Compare two Ether/802 addresses for equality, inlined and
  261  * unrolled for speed.
  262  * Note: use this like memcmp()
  263  */
  264 static inline u_int16_t
  265 ether_cmp(one, two)
  266         void *one, *two;
  267 {
  268         u_int16_t *a = (u_int16_t *) one;
  269         u_int16_t *b = (u_int16_t *) two;
  270         u_int16_t diff;
  271 
  272         diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
  273 
  274         return (diff);
  275 }
  276 
  277 #define ETHER_CMP       ether_cmp
  278 
  279 static int
  280 sematch(parent, match, aux)
  281         struct device *parent;
  282         struct cfdata *match;
  283         void *aux;
  284 {
  285         struct scsipibus_attach_args *sa = aux;
  286         int priority;
  287 
  288         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  289             se_patterns, sizeof(se_patterns) / sizeof(se_patterns[0]),
  290             sizeof(se_patterns[0]), &priority);
  291         return (priority);
  292 }
  293 
  294 /*
  295  * The routine called by the low level scsi routine when it discovers
  296  * a device suitable for this driver.
  297  */
  298 static void
  299 seattach(parent, self, aux)
  300         struct device *parent, *self;
  301         void *aux;
  302 {
  303         struct se_softc *sc = device_private(self);
  304         struct scsipibus_attach_args *sa = aux;
  305         struct scsipi_periph *periph = sa->sa_periph;
  306         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  307         u_int8_t myaddr[ETHER_ADDR_LEN];
  308 
  309         printf("\n");
  310         SC_DEBUG(periph, SCSIPI_DB2, ("seattach: "));
  311 
  312         callout_init(&sc->sc_ifstart_ch);
  313         callout_init(&sc->sc_recv_ch);
  314 
  315 
  316         /*
  317          * Store information needed to contact our base driver
  318          */
  319         sc->sc_periph = periph;
  320         periph->periph_dev = &sc->sc_dev;
  321         periph->periph_switch = &se_switch;
  322 
  323         /* XXX increase openings? */
  324 
  325         se_poll = (SE_POLL * hz) / 1000;
  326         se_poll = se_poll? se_poll: 1;
  327         se_poll0 = (SE_POLL0 * hz) / 1000;
  328         se_poll0 = se_poll0? se_poll0: 1;
  329 
  330         /*
  331          * Initialize and attach a buffer
  332          */
  333         sc->sc_tbuf = malloc(ETHERMTU + sizeof(struct ether_header),
  334                              M_DEVBUF, M_NOWAIT);
  335         if (sc->sc_tbuf == 0)
  336                 panic("seattach: can't allocate transmit buffer");
  337 
  338         sc->sc_rbuf = malloc(RBUF_LEN, M_DEVBUF, M_NOWAIT);/* A Guess */
  339         if (sc->sc_rbuf == 0)
  340                 panic("seattach: can't allocate receive buffer");
  341 
  342         se_get_addr(sc, myaddr);
  343 
  344         /* Initialize ifnet structure. */
  345         strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof(ifp->if_xname));
  346         ifp->if_softc = sc;
  347         ifp->if_start = se_ifstart;
  348         ifp->if_ioctl = se_ioctl;
  349         ifp->if_watchdog = sewatchdog;
  350         ifp->if_flags =
  351             IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
  352         IFQ_SET_READY(&ifp->if_snd);
  353 
  354         /* Attach the interface. */
  355         if_attach(ifp);
  356         ether_ifattach(ifp, myaddr);
  357 }
  358 
  359 
  360 static inline int
  361 se_scsipi_cmd(periph, cmd, cmdlen, data_addr, datalen,
  362                        retries, timeout, bp, flags)
  363         struct scsipi_periph *periph;
  364         struct scsipi_generic *cmd;
  365         int cmdlen;
  366         u_char *data_addr;
  367         int datalen;
  368         int retries;
  369         int timeout;
  370         struct buf *bp;
  371         int flags;
  372 {
  373         int error;
  374         int s = splbio();
  375 
  376         error = scsipi_command(periph, cmd, cmdlen, data_addr,
  377             datalen, retries, timeout, bp, flags);
  378         splx(s);
  379         return (error);
  380 }
  381 
  382 /* Start routine for calling from scsi sub system */
  383 static void
  384 sestart(periph)
  385         struct scsipi_periph *periph;
  386 {
  387         struct se_softc *sc = (void *)periph->periph_dev;
  388         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  389         int s = splnet();
  390 
  391         se_ifstart(ifp);
  392         (void) splx(s);
  393 }
  394 
  395 static void
  396 se_delayed_ifstart(v)
  397         void *v;
  398 {
  399         struct ifnet *ifp = v;
  400         struct se_softc *sc = ifp->if_softc;
  401         int s;
  402 
  403         s = splnet();
  404         if (sc->sc_enabled) {
  405                 ifp->if_flags &= ~IFF_OACTIVE;
  406                 se_ifstart(ifp);
  407         }
  408         splx(s);
  409 }
  410 
  411 /*
  412  * Start transmission on the interface.
  413  * Always called at splnet().
  414  */
  415 static void
  416 se_ifstart(ifp)
  417         struct ifnet *ifp;
  418 {
  419         struct se_softc *sc = ifp->if_softc;
  420         struct scsi_ctron_ether_generic send_cmd;
  421         struct mbuf *m, *m0;
  422         int len, error;
  423         u_char *cp;
  424 
  425         /* Don't transmit if interface is busy or not running */
  426         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  427                 return;
  428 
  429         IFQ_DEQUEUE(&ifp->if_snd, m0);
  430         if (m0 == 0)
  431                 return;
  432 #if NBPFILTER > 0
  433         /* If BPF is listening on this interface, let it see the
  434          * packet before we commit it to the wire.
  435          */
  436         if (ifp->if_bpf)
  437                 bpf_mtap(ifp->if_bpf, m0);
  438 #endif
  439 
  440         /* We need to use m->m_pkthdr.len, so require the header */
  441         if ((m0->m_flags & M_PKTHDR) == 0)
  442                 panic("ctscstart: no header mbuf");
  443         len = m0->m_pkthdr.len;
  444 
  445         /* Mark the interface busy. */
  446         ifp->if_flags |= IFF_OACTIVE;
  447 
  448         /* Chain; copy into linear buffer we allocated at attach time. */
  449         cp = sc->sc_tbuf;
  450         for (m = m0; m != NULL; ) {
  451                 memcpy(cp, mtod(m, u_char *), m->m_len);
  452                 cp += m->m_len;
  453                 MFREE(m, m0);
  454                 m = m0;
  455         }
  456         if (len < SEMINSIZE) {
  457 #ifdef SEDEBUG
  458                 if (sc->sc_debug)
  459                         printf("se: packet size %d (%d) < %d\n", len,
  460                             cp - (u_char *)sc->sc_tbuf, SEMINSIZE);
  461 #endif
  462                 memset(cp, 0, SEMINSIZE - len);
  463                 len = SEMINSIZE;
  464         }
  465 
  466         /* Fill out SCSI command. */
  467         PROTOCMD(ctron_ether_send, send_cmd);
  468         _lto2b(len, send_cmd.length);
  469 
  470         /* Send command to device. */
  471         error = se_scsipi_cmd(sc->sc_periph,
  472             (void *)&send_cmd, sizeof(send_cmd),
  473             sc->sc_tbuf, len, SERETRIES,
  474             SETIMEOUT, NULL, XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_OUT);
  475         if (error) {
  476                 printf("%s: not queued, error %d\n",
  477                     sc->sc_dev.dv_xname, error);
  478                 ifp->if_oerrors++;
  479                 ifp->if_flags &= ~IFF_OACTIVE;
  480         } else
  481                 ifp->if_opackets++;
  482         if (sc->sc_flags & SE_NEED_RECV) {
  483                 sc->sc_flags &= ~SE_NEED_RECV;
  484                 se_recv((void *) sc);
  485         }
  486 }
  487 
  488 
  489 /*
  490  * Called from the scsibus layer via our scsi device switch.
  491  */
  492 static void
  493 sedone(xs, error)
  494         struct scsipi_xfer *xs;
  495         int error;
  496 {
  497         struct se_softc *sc = (void *)xs->xs_periph->periph_dev;
  498         struct scsipi_generic *cmd = xs->cmd;
  499         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  500         int s;
  501 
  502         s = splnet();
  503         if(IS_SEND(cmd)) {
  504                 if (xs->error == XS_BUSY) {
  505                         printf("se: busy, retry txmit\n");
  506                         callout_reset(&sc->sc_ifstart_ch, hz,
  507                             se_delayed_ifstart, ifp);
  508                 } else {
  509                         ifp->if_flags &= ~IFF_OACTIVE;
  510                         /* the generic scsipi_done will call
  511                          * sestart (through scsipi_free_xs).
  512                          */
  513                 }
  514         } else if(IS_RECV(cmd)) {
  515                 /* RECV complete */
  516                 /* pass data up. reschedule a recv */
  517                 /* scsipi_free_xs will call start. Harmless. */
  518                 if (error) {
  519                         /* Reschedule after a delay */
  520                         callout_reset(&sc->sc_recv_ch, se_poll,
  521                             se_recv, (void *)sc);
  522                 } else {
  523                         int n, ntimeo;
  524                         n = se_read(sc, xs->data, xs->datalen - xs->resid);
  525                         if (n > se_max_received)
  526                                 se_max_received = n;
  527                         if (n == 0)
  528                                 ntimeo = se_poll;
  529                         else if (n >= RDATA_MAX)
  530                                 ntimeo = se_poll0;
  531                         else {
  532                                 ntimeo = sc->sc_last_timeout;
  533                                 ntimeo = (ntimeo * RDATA_GOAL)/n;
  534                                 ntimeo = (ntimeo < se_poll0?
  535                                           se_poll0: ntimeo);
  536                                 ntimeo = (ntimeo > se_poll?
  537                                           se_poll: ntimeo);
  538                         }
  539                         sc->sc_last_timeout = ntimeo;
  540                         if (ntimeo == se_poll0  &&
  541                             IFQ_IS_EMPTY(&ifp->if_snd) == 0)
  542                                 /* Output is pending. Do next recv
  543                                  * after the next send.  */
  544                                 sc->sc_flags |= SE_NEED_RECV;
  545                         else {
  546                                 callout_reset(&sc->sc_recv_ch, ntimeo,
  547                                     se_recv, (void *)sc);
  548                         }
  549                 }
  550         }
  551         splx(s);
  552 }
  553 
  554 static void
  555 se_recv(v)
  556         void *v;
  557 {
  558         /* do a recv command */
  559         struct se_softc *sc = (struct se_softc *) v;
  560         struct scsi_ctron_ether_recv recv_cmd;
  561         int error;
  562 
  563         if (sc->sc_enabled == 0)
  564                 return;
  565 
  566         PROTOCMD(ctron_ether_recv, recv_cmd);
  567 
  568         error = se_scsipi_cmd(sc->sc_periph,
  569             (void *)&recv_cmd, sizeof(recv_cmd),
  570             sc->sc_rbuf, RBUF_LEN, SERETRIES, SETIMEOUT, NULL,
  571             XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_IN);
  572         if (error)
  573                 callout_reset(&sc->sc_recv_ch, se_poll, se_recv, (void *)sc);
  574 }
  575 
  576 /*
  577  * We copy the data into mbufs.  When full cluster sized units are present
  578  * we copy into clusters.
  579  */
  580 static struct mbuf *
  581 se_get(sc, data, totlen)
  582         struct se_softc *sc;
  583         char *data;
  584         int totlen;
  585 {
  586         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  587         struct mbuf *m, *m0, *newm;
  588         int len;
  589 
  590         MGETHDR(m0, M_DONTWAIT, MT_DATA);
  591         if (m0 == 0)
  592                 return (0);
  593         m0->m_pkthdr.rcvif = ifp;
  594         m0->m_pkthdr.len = totlen;
  595         len = MHLEN;
  596         m = m0;
  597 
  598         while (totlen > 0) {
  599                 if (totlen >= MINCLSIZE) {
  600                         MCLGET(m, M_DONTWAIT);
  601                         if ((m->m_flags & M_EXT) == 0)
  602                                 goto bad;
  603                         len = MCLBYTES;
  604                 }
  605 
  606                 if (m == m0) {
  607                         caddr_t newdata = (caddr_t)
  608                             ALIGN(m->m_data + sizeof(struct ether_header)) -
  609                             sizeof(struct ether_header);
  610                         len -= newdata - m->m_data;
  611                         m->m_data = newdata;
  612                 }
  613 
  614                 m->m_len = len = min(totlen, len);
  615                 memcpy(mtod(m, caddr_t), data, len);
  616                 data += len;
  617 
  618                 totlen -= len;
  619                 if (totlen > 0) {
  620                         MGET(newm, M_DONTWAIT, MT_DATA);
  621                         if (newm == 0)
  622                                 goto bad;
  623                         len = MLEN;
  624                         m = m->m_next = newm;
  625                 }
  626         }
  627 
  628         return (m0);
  629 
  630 bad:
  631         m_freem(m0);
  632         return (0);
  633 }
  634 
  635 /*
  636  * Pass packets to higher levels.
  637  */
  638 static int
  639 se_read(sc, data, datalen)
  640         struct se_softc *sc;
  641         char *data;
  642         int datalen;
  643 {
  644         struct mbuf *m;
  645         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  646         int n;
  647 
  648         n = 0;
  649         while (datalen >= 2) {
  650                 int len = _2btol(data);
  651                 data += 2;
  652                 datalen -= 2;
  653 
  654                 if (len == 0)
  655                         break;
  656 #ifdef SEDEBUG
  657                 if (sc->sc_debug) {
  658                         printf("se_read: datalen = %d, packetlen = %d, proto = 0x%04x\n", datalen, len,
  659                          ntohs(((struct ether_header *)data)->ether_type));
  660                 }
  661 #endif
  662                 if (len <= sizeof(struct ether_header) ||
  663                     len > MAX_SNAP) {
  664 #ifdef SEDEBUG
  665                         printf("%s: invalid packet size %d; dropping\n",
  666                                sc->sc_dev.dv_xname, len);
  667 #endif
  668                         ifp->if_ierrors++;
  669                         goto next_packet;
  670                 }
  671 
  672                 /* Don't need crc. Must keep ether header for BPF */
  673                 m = se_get(sc, data, len - ETHER_CRC);
  674                 if (m == 0) {
  675 #ifdef SEDEBUG
  676                         if (sc->sc_debug)
  677                                 printf("se_read: se_get returned null\n");
  678 #endif
  679                         ifp->if_ierrors++;
  680                         goto next_packet;
  681                 }
  682                 if ((ifp->if_flags & IFF_PROMISC) != 0) {
  683                         m_adj(m, SE_PREFIX);
  684                 }
  685                 ifp->if_ipackets++;
  686 
  687 #if NBPFILTER > 0
  688                 /*
  689                  * Check if there's a BPF listener on this interface.
  690                  * If so, hand off the raw packet to BPF.
  691                  */
  692                 if (ifp->if_bpf)
  693                         bpf_mtap(ifp->if_bpf, m);
  694 #endif
  695 
  696                 /* Pass the packet up. */
  697                 (*ifp->if_input)(ifp, m);
  698 
  699         next_packet:
  700                 data += len;
  701                 datalen -= len;
  702                 n++;
  703         }
  704         return (n);
  705 }
  706 
  707 
  708 static void
  709 sewatchdog(ifp)
  710         struct ifnet *ifp;
  711 {
  712         struct se_softc *sc = ifp->if_softc;
  713 
  714         log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
  715         ++ifp->if_oerrors;
  716 
  717         se_reset(sc);
  718 }
  719 
  720 static int
  721 se_reset(sc)
  722         struct se_softc *sc;
  723 {
  724         int error;
  725         int s = splnet();
  726 #if 0
  727         /* Maybe we don't *really* want to reset the entire bus
  728          * because the ctron isn't working. We would like to send a
  729          * "BUS DEVICE RESET" message, but don't think the ctron
  730          * understands it.
  731          */
  732         error = se_scsipi_cmd(sc->sc_periph, 0, 0, 0, 0, SERETRIES, 2000, NULL,
  733             XS_CTL_RESET);
  734 #endif
  735         error = se_init(sc);
  736         splx(s);
  737         return (error);
  738 }
  739 
  740 static int
  741 se_add_proto(sc, proto)
  742         struct se_softc *sc;
  743         int proto;
  744 {
  745         int error;
  746         struct scsi_ctron_ether_generic add_proto_cmd;
  747         u_int8_t data[2];
  748         _lto2b(proto, data);
  749 #ifdef SEDEBUG
  750         if (sc->sc_debug)
  751                 printf("se: adding proto 0x%02x%02x\n", data[0], data[1]);
  752 #endif
  753 
  754         PROTOCMD(ctron_ether_add_proto, add_proto_cmd);
  755         _lto2b(sizeof(data), add_proto_cmd.length);
  756         error = se_scsipi_cmd(sc->sc_periph,
  757             (void *)&add_proto_cmd, sizeof(add_proto_cmd),
  758             data, sizeof(data), SERETRIES, SETIMEOUT, NULL,
  759             XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK);
  760         return (error);
  761 }
  762 
  763 static int
  764 se_get_addr(sc, myaddr)
  765         struct se_softc *sc;
  766         u_int8_t *myaddr;
  767 {
  768         int error;
  769         struct scsi_ctron_ether_generic get_addr_cmd;
  770 
  771         PROTOCMD(ctron_ether_get_addr, get_addr_cmd);
  772         _lto2b(ETHER_ADDR_LEN, get_addr_cmd.length);
  773         error = se_scsipi_cmd(sc->sc_periph,
  774             (void *)&get_addr_cmd, sizeof(get_addr_cmd),
  775             myaddr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  776             XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
  777         printf("%s: ethernet address %s\n", sc->sc_dev.dv_xname,
  778             ether_sprintf(myaddr));
  779         return (error);
  780 }
  781 
  782 
  783 static int
  784 se_set_media(sc, type)
  785         struct se_softc *sc;
  786         int type;
  787 {
  788         int error;
  789         struct scsi_ctron_ether_generic set_media_cmd;
  790 
  791         PROTOCMD(ctron_ether_set_media, set_media_cmd);
  792         set_media_cmd.byte3 = type;
  793         error = se_scsipi_cmd(sc->sc_periph,
  794             (void *)&set_media_cmd, sizeof(set_media_cmd),
  795             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  796         return (error);
  797 }
  798 
  799 static int
  800 se_set_mode(sc, len, mode)
  801         struct se_softc *sc;
  802         int len;
  803         int mode;
  804 {
  805         int error;
  806         struct scsi_ctron_ether_set_mode set_mode_cmd;
  807 
  808         PROTOCMD(ctron_ether_set_mode, set_mode_cmd);
  809         set_mode_cmd.mode = mode;
  810         _lto2b(len, set_mode_cmd.length);
  811         error = se_scsipi_cmd(sc->sc_periph,
  812             (void *)&set_mode_cmd, sizeof(set_mode_cmd),
  813             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  814         return (error);
  815 }
  816 
  817 
  818 static int
  819 se_init(sc)
  820         struct se_softc *sc;
  821 {
  822         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  823         struct scsi_ctron_ether_generic set_addr_cmd;
  824         int error;
  825 
  826 #if NBPFILTER > 0
  827         if (ifp->if_flags & IFF_PROMISC) {
  828                 error = se_set_mode(sc, MAX_SNAP, 1);
  829         }
  830         else
  831 #endif
  832                 error = se_set_mode(sc, ETHERMTU + sizeof(struct ether_header),
  833                     0);
  834         if (error != 0)
  835                 return (error);
  836 
  837         PROTOCMD(ctron_ether_set_addr, set_addr_cmd);
  838         _lto2b(ETHER_ADDR_LEN, set_addr_cmd.length);
  839         error = se_scsipi_cmd(sc->sc_periph,
  840             (void *)&set_addr_cmd, sizeof(set_addr_cmd),
  841             LLADDR(ifp->if_sadl), ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  842             XS_CTL_DATA_OUT);
  843         if (error != 0)
  844                 return (error);
  845 
  846         if ((sc->protos & PROTO_IP) &&
  847             (error = se_add_proto(sc, ETHERTYPE_IP)) != 0)
  848                 return (error);
  849         if ((sc->protos & PROTO_ARP) &&
  850             (error = se_add_proto(sc, ETHERTYPE_ARP)) != 0)
  851                 return (error);
  852         if ((sc->protos & PROTO_REVARP) &&
  853             (error = se_add_proto(sc, ETHERTYPE_REVARP)) != 0)
  854                 return (error);
  855 #ifdef NETATALK
  856         if ((sc->protos & PROTO_AT) &&
  857             (error = se_add_proto(sc, ETHERTYPE_ATALK)) != 0)
  858                 return (error);
  859         if ((sc->protos & PROTO_AARP) &&
  860             (error = se_add_proto(sc, ETHERTYPE_AARP)) != 0)
  861                 return (error);
  862 #endif
  863 
  864         if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) == IFF_UP) {
  865                 ifp->if_flags |= IFF_RUNNING;
  866                 se_recv(sc);
  867                 ifp->if_flags &= ~IFF_OACTIVE;
  868                 se_ifstart(ifp);
  869         }
  870         return (error);
  871 }
  872 
  873 static int
  874 se_set_multi(sc, addr)
  875         struct se_softc *sc;
  876         u_int8_t *addr;
  877 {
  878         struct scsi_ctron_ether_generic set_multi_cmd;
  879         int error;
  880 
  881         if (sc->sc_debug)
  882                 printf("%s: set_set_multi: %s\n", sc->sc_dev.dv_xname,
  883                     ether_sprintf(addr));
  884 
  885         PROTOCMD(ctron_ether_set_multi, set_multi_cmd);
  886         _lto2b(sizeof(addr), set_multi_cmd.length);
  887         error = se_scsipi_cmd(sc->sc_periph,
  888             (void *)&set_multi_cmd, sizeof(set_multi_cmd),
  889             addr, sizeof(addr), SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  890         return (error);
  891 }
  892 
  893 static int
  894 se_remove_multi(sc, addr)
  895         struct se_softc *sc;
  896         u_int8_t *addr;
  897 {
  898         struct scsi_ctron_ether_generic remove_multi_cmd;
  899         int error;
  900 
  901         if (sc->sc_debug)
  902                 printf("%s: se_remove_multi: %s\n", sc->sc_dev.dv_xname,
  903                     ether_sprintf(addr));
  904 
  905         PROTOCMD(ctron_ether_remove_multi, remove_multi_cmd);
  906         _lto2b(sizeof(addr), remove_multi_cmd.length);
  907         error = se_scsipi_cmd(sc->sc_periph,
  908             (void *)&remove_multi_cmd, sizeof(remove_multi_cmd),
  909             addr, sizeof(addr), SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  910         return (error);
  911 }
  912 
  913 #if 0   /* not used  --thorpej */
  914 static int
  915 sc_set_all_multi(sc, set)
  916         struct se_softc *sc;
  917         int set;
  918 {
  919         int error = 0;
  920         u_int8_t *addr;
  921         struct ethercom *ac = &sc->sc_ethercom;
  922         struct ether_multi *enm;
  923         struct ether_multistep step;
  924 
  925         ETHER_FIRST_MULTI(step, ac, enm);
  926         while (enm != NULL) {
  927                 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
  928                         /*
  929                          * We must listen to a range of multicast addresses.
  930                          * For now, just accept all multicasts, rather than
  931                          * trying to set only those filter bits needed to match
  932                          * the range.  (At this time, the only use of address
  933                          * ranges is for IP multicast routing, for which the
  934                          * range is big enough to require all bits set.)
  935                          */
  936                         /* We have no way of adding a range to this device.
  937                          * stepping through all addresses in the range is
  938                          * typically not possible. The only real alternative
  939                          * is to go into promicuous mode and filter by hand.
  940                          */
  941                         return (ENODEV);
  942 
  943                 }
  944 
  945                 addr = enm->enm_addrlo;
  946                 if ((error = set ? se_set_multi(sc, addr) :
  947                     se_remove_multi(sc, addr)) != 0)
  948                         return (error);
  949                 ETHER_NEXT_MULTI(step, enm);
  950         }
  951         return (error);
  952 }
  953 #endif /* not used */
  954 
  955 static void
  956 se_stop(sc)
  957         struct se_softc *sc;
  958 {
  959 
  960         /* Don't schedule any reads */
  961         callout_stop(&sc->sc_recv_ch);
  962 
  963         /* How can we abort any scsi cmds in progress? */
  964 }
  965 
  966 
  967 /*
  968  * Process an ioctl request.
  969  */
  970 static int
  971 se_ioctl(ifp, cmd, data)
  972         struct ifnet *ifp;
  973         u_long cmd;
  974         caddr_t data;
  975 {
  976         struct se_softc *sc = ifp->if_softc;
  977         struct ifaddr *ifa = (struct ifaddr *)data;
  978         struct ifreq *ifr = (struct ifreq *)data;
  979         int s, error = 0;
  980 
  981         s = splnet();
  982 
  983         switch (cmd) {
  984 
  985         case SIOCSIFADDR:
  986                 if ((error = se_enable(sc)) != 0)
  987                         break;
  988                 ifp->if_flags |= IFF_UP;
  989 
  990                 if ((error = se_set_media(sc, CMEDIA_AUTOSENSE) != 0))
  991                         break;
  992 
  993                 switch (ifa->ifa_addr->sa_family) {
  994 #ifdef INET
  995                 case AF_INET:
  996                         sc->protos |= (PROTO_IP | PROTO_ARP | PROTO_REVARP);
  997                         if ((error = se_init(sc)) != 0)
  998                                 break;
  999                         arp_ifinit(ifp, ifa);
 1000                         break;
 1001 #endif
 1002 #ifdef NETATALK
 1003                 case AF_APPLETALK:
 1004                         sc->protos |= (PROTO_AT | PROTO_AARP);
 1005                         if ((error = se_init(sc)) != 0)
 1006                                 break;
 1007                         break;
 1008 #endif
 1009                 default:
 1010                         error = se_init(sc);
 1011                         break;
 1012                 }
 1013                 break;
 1014 
 1015 
 1016         case SIOCSIFFLAGS:
 1017                 if ((ifp->if_flags & IFF_UP) == 0 &&
 1018                     (ifp->if_flags & IFF_RUNNING) != 0) {
 1019                         /*
 1020                          * If interface is marked down and it is running, then
 1021                          * stop it.
 1022                          */
 1023                         se_stop(sc);
 1024                         ifp->if_flags &= ~IFF_RUNNING;
 1025                         se_disable(sc);
 1026                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
 1027                            (ifp->if_flags & IFF_RUNNING) == 0) {
 1028                         /*
 1029                          * If interface is marked up and it is stopped, then
 1030                          * start it.
 1031                          */
 1032                         if ((error = se_enable(sc)) != 0)
 1033                                 break;
 1034                         error = se_init(sc);
 1035                 } else if (sc->sc_enabled) {
 1036                         /*
 1037                          * Reset the interface to pick up changes in any other
 1038                          * flags that affect hardware registers.
 1039                          */
 1040                         error = se_init(sc);
 1041                 }
 1042 #ifdef SEDEBUG
 1043                 if (ifp->if_flags & IFF_DEBUG)
 1044                         sc->sc_debug = 1;
 1045                 else
 1046                         sc->sc_debug = 0;
 1047 #endif
 1048                 break;
 1049 
 1050         case SIOCADDMULTI:
 1051         case SIOCDELMULTI:
 1052                 error = (cmd == SIOCADDMULTI) ?
 1053                     ether_addmulti(ifr, &sc->sc_ethercom) :
 1054                     ether_delmulti(ifr, &sc->sc_ethercom);
 1055                 if (error == ENETRESET) {
 1056                         if (ifp->if_flags & IFF_RUNNING) {
 1057                                 error = (cmd == SIOCADDMULTI) ?
 1058                                    se_set_multi(sc, ifr->ifr_addr.sa_data) :
 1059                                    se_remove_multi(sc, ifr->ifr_addr.sa_data);
 1060                         } else
 1061                                 error = 0;
 1062                 }
 1063                 break;
 1064 
 1065         default:
 1066 
 1067                 error = EINVAL;
 1068                 break;
 1069         }
 1070 
 1071         splx(s);
 1072         return (error);
 1073 }
 1074 
 1075 /*
 1076  * Enable the network interface.
 1077  */
 1078 int
 1079 se_enable(sc)
 1080         struct se_softc *sc;
 1081 {
 1082         struct scsipi_periph *periph = sc->sc_periph;
 1083         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1084         int error = 0;
 1085 
 1086         if (sc->sc_enabled == 0 &&
 1087             (error = scsipi_adapter_addref(adapt)) == 0)
 1088                 sc->sc_enabled = 1;
 1089         else
 1090                 printf("%s: device enable failed\n",
 1091                     sc->sc_dev.dv_xname);
 1092 
 1093         return (error);
 1094 }
 1095 
 1096 /*
 1097  * Disable the network interface.
 1098  */
 1099 void
 1100 se_disable(sc)
 1101         struct se_softc *sc;
 1102 {
 1103         struct scsipi_periph *periph = sc->sc_periph;
 1104         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1105 
 1106         if (sc->sc_enabled != 0) {
 1107                 scsipi_adapter_delref(adapt);
 1108                 sc->sc_enabled = 0;
 1109         }
 1110 }
 1111 
 1112 #define SEUNIT(z)       (minor(z))
 1113 /*
 1114  * open the device.
 1115  */
 1116 int
 1117 seopen(dev, flag, fmt, l)
 1118         dev_t dev;
 1119         int flag, fmt;
 1120         struct lwp *l;
 1121 {
 1122         int unit, error;
 1123         struct se_softc *sc;
 1124         struct scsipi_periph *periph;
 1125         struct scsipi_adapter *adapt;
 1126 
 1127         unit = SEUNIT(dev);
 1128         if (unit >= se_cd.cd_ndevs)
 1129                 return (ENXIO);
 1130         sc = se_cd.cd_devs[unit];
 1131         if (sc == NULL)
 1132                 return (ENXIO);
 1133 
 1134         periph = sc->sc_periph;
 1135         adapt = periph->periph_channel->chan_adapter;
 1136 
 1137         if ((error = scsipi_adapter_addref(adapt)) != 0)
 1138                 return (error);
 1139 
 1140         SC_DEBUG(periph, SCSIPI_DB1,
 1141             ("scopen: dev=0x%x (unit %d (of %d))\n", dev, unit,
 1142             se_cd.cd_ndevs));
 1143 
 1144         periph->periph_flags |= PERIPH_OPEN;
 1145 
 1146         SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
 1147         return (0);
 1148 }
 1149 
 1150 /*
 1151  * close the device.. only called if we are the LAST
 1152  * occurence of an open device
 1153  */
 1154 int
 1155 seclose(dev, flag, fmt, l)
 1156         dev_t dev;
 1157         int flag, fmt;
 1158         struct lwp *l;
 1159 {
 1160         struct se_softc *sc = se_cd.cd_devs[SEUNIT(dev)];
 1161         struct scsipi_periph *periph = sc->sc_periph;
 1162         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1163 
 1164         SC_DEBUG(sc->sc_periph, SCSIPI_DB1, ("closing\n"));
 1165 
 1166         scsipi_wait_drain(periph);
 1167 
 1168         scsipi_adapter_delref(adapt);
 1169         periph->periph_flags &= ~PERIPH_OPEN;
 1170 
 1171         return (0);
 1172 }
 1173 
 1174 /*
 1175  * Perform special action on behalf of the user
 1176  * Only does generic scsi ioctls.
 1177  */
 1178 int
 1179 seioctl(dev, cmd, addr, flag, l)
 1180         dev_t dev;
 1181         u_long cmd;
 1182         caddr_t addr;
 1183         int flag;
 1184         struct lwp *l;
 1185 {
 1186         struct se_softc *sc = se_cd.cd_devs[SEUNIT(dev)];
 1187 
 1188         return (scsipi_do_ioctl(sc->sc_periph, dev, cmd, addr, flag, l));
 1189 }

Cache object: 7f4992544b70ffb34d2a8d9be41f0b55


[ 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.