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.118 2022/08/29 07:32:46 skrll 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 referred 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  * sedone is to be called from the scsi subsystem 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.118 2022/08/29 07:32:46 skrll Exp $");
   63 
   64 #ifdef _KERNEL_OPT
   65 #include "opt_inet.h"
   66 #include "opt_net_mpsafe.h"
   67 #include "opt_atalk.h"
   68 #endif
   69 
   70 #include <sys/param.h>
   71 #include <sys/types.h>
   72 
   73 #include <sys/buf.h>
   74 #include <sys/callout.h>
   75 #include <sys/conf.h>
   76 #include <sys/device.h>
   77 #include <sys/disk.h>
   78 #include <sys/disklabel.h>
   79 #include <sys/errno.h>
   80 #include <sys/file.h>
   81 #include <sys/ioctl.h>
   82 #include <sys/kernel.h>
   83 #include <sys/malloc.h>
   84 #include <sys/mbuf.h>
   85 #include <sys/mutex.h>
   86 #include <sys/proc.h>
   87 #include <sys/socket.h>
   88 #include <sys/stat.h>
   89 #include <sys/syslog.h>
   90 #include <sys/systm.h>
   91 #include <sys/uio.h>
   92 #include <sys/workqueue.h>
   93 
   94 #include <dev/scsipi/scsi_ctron_ether.h>
   95 #include <dev/scsipi/scsiconf.h>
   96 #include <dev/scsipi/scsipi_all.h>
   97 
   98 #include <net/bpf.h>
   99 #include <net/if.h>
  100 #include <net/if_dl.h>
  101 #include <net/if_ether.h>
  102 #include <net/if_media.h>
  103 
  104 #ifdef INET
  105 #include <netinet/if_inarp.h>
  106 #include <netinet/in.h>
  107 #endif
  108 
  109 #ifdef NETATALK
  110 #include <netatalk/at.h>
  111 #endif
  112 
  113 #define SETIMEOUT       1000
  114 #define SEOUTSTANDING   4
  115 #define SERETRIES       4
  116 #define SE_PREFIX       4
  117 #define ETHER_CRC       4
  118 #define SEMINSIZE       60
  119 
  120 /* Make this big enough for an ETHERMTU packet in promiscuous mode. */
  121 #define MAX_SNAP        (ETHERMTU + sizeof(struct ether_header) + \
  122                          SE_PREFIX + ETHER_CRC)
  123 
  124 /* 10 full length packets appears to be the max ever returned. 16k is OK */
  125 #define RBUF_LEN        (16 * 1024)
  126 
  127 /* Tuning parameters:
  128  * The EA41x only returns a maximum of 10 packets (regardless of size).
  129  * We will attempt to adapt to polling fast enough to get RDATA_GOAL packets
  130  * per read
  131  */
  132 #define RDATA_MAX 10
  133 #define RDATA_GOAL 8
  134 
  135 /* se_poll and se_poll0 are the normal polling rate and the minimum
  136  * polling rate respectively. se_poll0 should be chosen so that at
  137  * maximum ethernet speed, we will read nearly RDATA_MAX packets. se_poll
  138  * should be chosen for reasonable maximum latency.
  139  * In practice, if we are being saturated with min length packets, we
  140  * can't poll fast enough. Polling with zero delay actually
  141  * worsens performance. se_poll0 is enforced to be always at least 1
  142  */
  143 #define SE_POLL 40              /* default in milliseconds */
  144 #define SE_POLL0 10             /* default in milliseconds */
  145 int se_poll = 0;                /* Delay in ticks set at attach time */
  146 int se_poll0 = 0;
  147 #ifdef SE_DEBUG
  148 int se_max_received = 0;        /* Instrumentation */
  149 #endif
  150 
  151 #define PROTOCMD(p, d) \
  152         ((d) = (p))
  153 
  154 #define PROTOCMD_DECL(name) \
  155         static const struct scsi_ctron_ether_generic name
  156 
  157 #define PROTOCMD_DECL_SPECIAL(name) \
  158         static const struct __CONCAT(scsi_, name) name
  159 
  160 /* Command initializers for commands using scsi_ctron_ether_generic */
  161 PROTOCMD_DECL(ctron_ether_send)  = {CTRON_ETHER_SEND, 0, {0,0}, 0};
  162 PROTOCMD_DECL(ctron_ether_add_proto) = {CTRON_ETHER_ADD_PROTO, 0, {0,0}, 0};
  163 PROTOCMD_DECL(ctron_ether_get_addr) = {CTRON_ETHER_GET_ADDR, 0, {0,0}, 0};
  164 PROTOCMD_DECL(ctron_ether_set_media) = {CTRON_ETHER_SET_MEDIA, 0, {0,0}, 0};
  165 PROTOCMD_DECL(ctron_ether_set_addr) = {CTRON_ETHER_SET_ADDR, 0, {0,0}, 0};
  166 PROTOCMD_DECL(ctron_ether_set_multi) = {CTRON_ETHER_SET_MULTI, 0, {0,0}, 0};
  167 PROTOCMD_DECL(ctron_ether_remove_multi) =
  168     {CTRON_ETHER_REMOVE_MULTI, 0, {0,0}, 0};
  169 
  170 /* Command initializers for commands using their own structures */
  171 PROTOCMD_DECL_SPECIAL(ctron_ether_recv) = {CTRON_ETHER_RECV};
  172 PROTOCMD_DECL_SPECIAL(ctron_ether_set_mode) =
  173     {CTRON_ETHER_SET_MODE, 0, {0,0}, 0};
  174 
  175 struct se_softc {
  176         device_t sc_dev;
  177         struct ethercom sc_ethercom;    /* Ethernet common part */
  178         struct scsipi_periph *sc_periph;/* contains our targ, lun, etc. */
  179 
  180         struct callout sc_recv_ch;
  181         struct kmutex sc_iflock;
  182         struct if_percpuq *sc_ipq;
  183         struct workqueue *sc_recv_wq, *sc_send_wq;
  184         struct work sc_recv_work, sc_send_work;
  185         int sc_recv_work_pending, sc_send_work_pending;
  186 
  187         char *sc_tbuf;
  188         char *sc_rbuf;
  189         int protos;
  190 #define PROTO_IP        0x01
  191 #define PROTO_ARP       0x02
  192 #define PROTO_REVARP    0x04
  193 #define PROTO_AT        0x08
  194 #define PROTO_AARP      0x10
  195         int sc_debug;
  196         int sc_flags;
  197         int sc_last_timeout;
  198         int sc_enabled;
  199         int sc_attach_state;
  200 };
  201 
  202 static int      sematch(device_t, cfdata_t, void *);
  203 static void     seattach(device_t, device_t, void *);
  204 static int      sedetach(device_t, int);
  205 
  206 static void     se_ifstart(struct ifnet *);
  207 
  208 static void     sedone(struct scsipi_xfer *, int);
  209 static int      se_ioctl(struct ifnet *, u_long, void *);
  210 #if 0
  211 static void     sewatchdog(struct ifnet *);
  212 #endif
  213 
  214 #if 0
  215 static inline uint16_t ether_cmp(void *, void *);
  216 #endif
  217 static void     se_recv_callout(void *);
  218 static void     se_recv_worker(struct work *wk, void *cookie);
  219 static void     se_recv(struct se_softc *);
  220 static struct mbuf *se_get(struct se_softc *, char *, int);
  221 static int      se_read(struct se_softc *, char *, int);
  222 #if 0
  223 static void     se_reset(struct se_softc *);
  224 #endif
  225 static int      se_add_proto(struct se_softc *, int);
  226 static int      se_get_addr(struct se_softc *, uint8_t *);
  227 static int      se_set_media(struct se_softc *, int);
  228 static int      se_init(struct se_softc *);
  229 static int      se_set_multi(struct se_softc *, uint8_t *);
  230 static int      se_remove_multi(struct se_softc *, uint8_t *);
  231 #if 0
  232 static int      sc_set_all_multi(struct se_softc *, int);
  233 #endif
  234 static void     se_stop(struct se_softc *);
  235 static inline int se_scsipi_cmd(struct scsipi_periph *periph,
  236                         struct scsipi_generic *scsipi_cmd,
  237                         int cmdlen, u_char *data_addr, int datalen,
  238                         int retries, int timeout, struct buf *bp,
  239                         int flags);
  240 static void     se_send_worker(struct work *wk, void *cookie);
  241 static int      se_set_mode(struct se_softc *, int, int);
  242 
  243 int     se_enable(struct se_softc *);
  244 void    se_disable(struct se_softc *);
  245 
  246 CFATTACH_DECL_NEW(se, sizeof(struct se_softc),
  247     sematch, seattach, sedetach, NULL);
  248 
  249 extern struct cfdriver se_cd;
  250 
  251 dev_type_open(seopen);
  252 dev_type_close(seclose);
  253 dev_type_ioctl(seioctl);
  254 
  255 const struct cdevsw se_cdevsw = {
  256         .d_open = seopen,
  257         .d_close = seclose,
  258         .d_read = noread,
  259         .d_write = nowrite,
  260         .d_ioctl = seioctl,
  261         .d_stop = nostop,
  262         .d_tty = notty,
  263         .d_poll = nopoll,
  264         .d_mmap = nommap,
  265         .d_kqfilter = nokqfilter,
  266         .d_discard = nodiscard,
  267         .d_flag = D_OTHER | D_MPSAFE
  268 };
  269 
  270 const struct scsipi_periphsw se_switch = {
  271         NULL,                   /* Use default error handler */
  272         NULL,                   /* have no queue */
  273         NULL,                   /* have no async handler */
  274         sedone,                 /* deal with send/recv completion */
  275 };
  276 
  277 const struct scsipi_inquiry_pattern se_patterns[] = {
  278         {T_PROCESSOR, T_FIXED,
  279          "CABLETRN",         "EA412",                 ""},
  280         {T_PROCESSOR, T_FIXED,
  281          "Cabletrn",         "EA412",                 ""},
  282 };
  283 
  284 #if 0
  285 /*
  286  * Compare two Ether/802 addresses for equality, inlined and
  287  * unrolled for speed.
  288  * Note: use this like memcmp()
  289  */
  290 static inline uint16_t
  291 ether_cmp(void *one, void *two)
  292 {
  293         uint16_t *a = (uint16_t *) one;
  294         uint16_t *b = (uint16_t *) two;
  295         uint16_t diff;
  296 
  297         diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
  298 
  299         return (diff);
  300 }
  301 
  302 #define ETHER_CMP       ether_cmp
  303 #endif
  304 
  305 static int
  306 sematch(device_t parent, cfdata_t match, void *aux)
  307 {
  308         struct scsipibus_attach_args *sa = aux;
  309         int priority;
  310 
  311         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  312             se_patterns, sizeof(se_patterns) / sizeof(se_patterns[0]),
  313             sizeof(se_patterns[0]), &priority);
  314         return (priority);
  315 }
  316 
  317 /*
  318  * The routine called by the low level scsi routine when it discovers
  319  * a device suitable for this driver.
  320  */
  321 static void
  322 seattach(device_t parent, device_t self, void *aux)
  323 {
  324         struct se_softc *sc = device_private(self);
  325         struct scsipibus_attach_args *sa = aux;
  326         struct scsipi_periph *periph = sa->sa_periph;
  327         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  328         uint8_t myaddr[ETHER_ADDR_LEN];
  329         char wqname[MAXCOMLEN];
  330         int rv;
  331 
  332         sc->sc_dev = self;
  333 
  334         printf("\n");
  335         SC_DEBUG(periph, SCSIPI_DB2, ("seattach: "));
  336 
  337         sc->sc_attach_state = 0;
  338         callout_init(&sc->sc_recv_ch, CALLOUT_MPSAFE);
  339         callout_setfunc(&sc->sc_recv_ch, se_recv_callout, (void *)sc);
  340         mutex_init(&sc->sc_iflock, MUTEX_DEFAULT, IPL_SOFTNET);
  341 
  342         /*
  343          * Store information needed to contact our base driver
  344          */
  345         sc->sc_periph = periph;
  346         periph->periph_dev = sc->sc_dev;
  347         periph->periph_switch = &se_switch;
  348 
  349         se_poll = (SE_POLL * hz) / 1000;
  350         se_poll = se_poll? se_poll: 1;
  351         se_poll0 = (SE_POLL0 * hz) / 1000;
  352         se_poll0 = se_poll0? se_poll0: 1;
  353 
  354         /*
  355          * Initialize and attach send and receive buffers
  356          */
  357         sc->sc_tbuf = malloc(ETHERMTU + sizeof(struct ether_header),
  358                              M_DEVBUF, M_WAITOK);
  359         sc->sc_rbuf = malloc(RBUF_LEN, M_DEVBUF, M_WAITOK);
  360 
  361         /* Initialize ifnet structure. */
  362         strlcpy(ifp->if_xname, device_xname(sc->sc_dev), sizeof(ifp->if_xname));
  363         ifp->if_softc = sc;
  364         ifp->if_start = se_ifstart;
  365         ifp->if_ioctl = se_ioctl;
  366         ifp->if_watchdog = NULL;
  367         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  368         ifp->if_extflags = IFEF_MPSAFE;
  369         IFQ_SET_READY(&ifp->if_snd);
  370 
  371         se_get_addr(sc, myaddr);
  372         sc->sc_attach_state = 1;
  373 
  374         /* Attach the interface. */
  375         if_initialize(ifp);
  376 
  377         snprintf(wqname, sizeof(wqname), "%sRx", device_xname(sc->sc_dev));
  378         rv = workqueue_create(&sc->sc_recv_wq, wqname, se_recv_worker, sc,
  379             PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
  380         if (rv != 0) {
  381                 aprint_error_dev(sc->sc_dev,
  382                     "unable to create recv Rx workqueue\n");
  383                 sedetach(sc->sc_dev, 0);
  384                 return; /* Error */
  385         }
  386         sc->sc_recv_work_pending = false;
  387         sc->sc_attach_state = 2;
  388 
  389         snprintf(wqname, sizeof(wqname), "%sTx", device_xname(sc->sc_dev));
  390         rv = workqueue_create(&sc->sc_send_wq, wqname, se_send_worker, ifp,
  391             PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
  392         if (rv != 0) {
  393                 aprint_error_dev(sc->sc_dev,
  394                     "unable to create send Tx workqueue\n");
  395                 sedetach(sc->sc_dev, 0);
  396                 return; /* Error */
  397         }
  398         sc->sc_send_work_pending = false;
  399         sc->sc_attach_state = 3;
  400 
  401         sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if);
  402         ether_ifattach(ifp, myaddr);
  403         if_register(ifp);
  404         sc->sc_attach_state = 4;
  405 }
  406 
  407 static int
  408 sedetach(device_t self, int flags)
  409 {
  410         struct se_softc *sc = device_private(self);
  411         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  412 
  413         switch(sc->sc_attach_state) {
  414         case 4:
  415                 se_stop(sc);
  416                 mutex_enter(&sc->sc_iflock);
  417                 ifp->if_flags &= ~IFF_RUNNING;
  418                 se_disable(sc);
  419                 ether_ifdetach(ifp);
  420                 if_detach(ifp);
  421                 mutex_exit(&sc->sc_iflock);
  422                 if_percpuq_destroy(sc->sc_ipq);
  423                 /*FALLTHROUGH*/
  424         case 3:
  425                 workqueue_destroy(sc->sc_send_wq);
  426                 /*FALLTHROUGH*/
  427         case 2:
  428                 workqueue_destroy(sc->sc_recv_wq);
  429                 /*FALLTHROUGH*/
  430         case 1:
  431                 free(sc->sc_rbuf, M_DEVBUF);
  432                 free(sc->sc_tbuf, M_DEVBUF);
  433                 callout_destroy(&sc->sc_recv_ch);
  434                 mutex_destroy(&sc->sc_iflock);
  435                 break;
  436         default:
  437                 aprint_error_dev(sc->sc_dev, "detach failed (state %d)\n",
  438                     sc->sc_attach_state);
  439                 return 1;
  440                 break;
  441         }
  442         return 0;
  443 }
  444 
  445 /*
  446  * Send a command to the device
  447  */
  448 static inline int
  449 se_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_generic *cmd,
  450     int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
  451     struct buf *bp, int flags)
  452 {
  453         int error;
  454 
  455         error = scsipi_command(periph, cmd, cmdlen, data_addr,
  456             datalen, retries, timeout, bp, flags);
  457         return (error);
  458 }
  459 
  460 /*
  461  * Start routine for calling from network sub system
  462  */
  463 static void
  464 se_ifstart(struct ifnet *ifp)
  465 {
  466         struct se_softc *sc = ifp->if_softc;
  467 
  468         mutex_enter(&sc->sc_iflock);
  469         if (!sc->sc_send_work_pending)  {
  470                 sc->sc_send_work_pending = true;
  471                 workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work, NULL);
  472         }
  473         /* else: nothing to do - work is already queued */
  474         mutex_exit(&sc->sc_iflock);
  475 }
  476 
  477 /*
  478  * Invoke the transmit workqueue and transmission on the interface.
  479  */
  480 static void
  481 se_send_worker(struct work *wk, void *cookie)
  482 {
  483         struct ifnet *ifp = cookie;
  484         struct se_softc *sc = ifp->if_softc;
  485         struct scsi_ctron_ether_generic send_cmd;
  486         struct mbuf *m, *m0;
  487         int len, error;
  488         u_char *cp;
  489 
  490         mutex_enter(&sc->sc_iflock);
  491         sc->sc_send_work_pending = false;
  492         mutex_exit(&sc->sc_iflock);
  493 
  494         KASSERT(if_is_mpsafe(ifp));
  495 
  496         /* Don't transmit if interface is busy or not running */
  497         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  498                 return;
  499 
  500         while (1) {
  501                 IFQ_DEQUEUE(&ifp->if_snd, m0);
  502                 if (m0 == 0)
  503                         break;
  504 
  505                 /* If BPF is listening on this interface, let it see the
  506                  * packet before we commit it to the wire.
  507                  */
  508                 bpf_mtap(ifp, m0, BPF_D_OUT);
  509 
  510                 /* We need to use m->m_pkthdr.len, so require the header */
  511                 if ((m0->m_flags & M_PKTHDR) == 0)
  512                         panic("ctscstart: no header mbuf");
  513                 len = m0->m_pkthdr.len;
  514 
  515                 /* Mark the interface busy. */
  516                 ifp->if_flags |= IFF_OACTIVE;
  517 
  518                 /* Chain; copy into linear buffer allocated at attach time. */
  519                 cp = sc->sc_tbuf;
  520                 for (m = m0; m != NULL; ) {
  521                         memcpy(cp, mtod(m, u_char *), m->m_len);
  522                         cp += m->m_len;
  523                         m = m0 = m_free(m);
  524                 }
  525                 if (len < SEMINSIZE) {
  526 #ifdef SEDEBUG
  527                         if (sc->sc_debug)
  528                                 printf("se: packet size %d (%zu) < %d\n", len,
  529                                     cp - (u_char *)sc->sc_tbuf, SEMINSIZE);
  530 #endif
  531                         memset(cp, 0, SEMINSIZE - len);
  532                         len = SEMINSIZE;
  533                 }
  534 
  535                 /* Fill out SCSI command. */
  536                 PROTOCMD(ctron_ether_send, send_cmd);
  537                 _lto2b(len, send_cmd.length);
  538 
  539                 /* Send command to device. */
  540                 error = se_scsipi_cmd(sc->sc_periph,
  541                     (void *)&send_cmd, sizeof(send_cmd),
  542                     sc->sc_tbuf, len, SERETRIES,
  543                     SETIMEOUT, NULL, XS_CTL_NOSLEEP | XS_CTL_DATA_OUT);
  544                 if (error) {
  545                         aprint_error_dev(sc->sc_dev,
  546                             "not queued, error %d\n", error);
  547                         if_statinc(ifp, if_oerrors);
  548                         ifp->if_flags &= ~IFF_OACTIVE;
  549                 } else
  550                         if_statinc(ifp, if_opackets);
  551         }
  552 }
  553 
  554 
  555 /*
  556  * Called from the scsibus layer via our scsi device switch.
  557  */
  558 static void
  559 sedone(struct scsipi_xfer *xs, int error)
  560 {
  561         struct se_softc *sc = device_private(xs->xs_periph->periph_dev);
  562         struct scsipi_generic *cmd = xs->cmd;
  563         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  564 
  565         if (IS_SEND(cmd)) {
  566                 ifp->if_flags &= ~IFF_OACTIVE;
  567         } else if (IS_RECV(cmd)) {
  568                 /* RECV complete */
  569                 /* pass data up. reschedule a recv */
  570                 /* scsipi_free_xs will call start. Harmless. */
  571                 if (error) {
  572                         /* Reschedule after a delay */
  573                         callout_schedule(&sc->sc_recv_ch, se_poll);
  574                 } else {
  575                         int n, ntimeo;
  576                         n = se_read(sc, xs->data, xs->datalen - xs->resid);
  577 #ifdef SE_DEBUG
  578                         if (n > se_max_received)
  579                                 se_max_received = n;
  580 #endif
  581                         if (n == 0)
  582                                 ntimeo = se_poll;
  583                         else if (n >= RDATA_MAX)
  584                                 ntimeo = se_poll0;
  585                         else {
  586                                 ntimeo = sc->sc_last_timeout;
  587                                 ntimeo = (ntimeo * RDATA_GOAL)/n;
  588                                 ntimeo = (ntimeo < se_poll0?
  589                                           se_poll0: ntimeo);
  590                                 ntimeo = (ntimeo > se_poll?
  591                                           se_poll: ntimeo);
  592                         }
  593                         sc->sc_last_timeout = ntimeo;
  594                         callout_schedule(&sc->sc_recv_ch, ntimeo);
  595                 }
  596         }
  597 }
  598 
  599 /*
  600  * Setup a receive command by queuing the work.
  601  * Usually called from a callout, but also from se_init().
  602  */
  603 static void
  604 se_recv_callout(void *v)
  605 {
  606         /* do a recv command */
  607         struct se_softc *sc = (struct se_softc *) v;
  608 
  609         if (sc->sc_enabled == 0)
  610                 return;
  611 
  612         mutex_enter(&sc->sc_iflock);
  613         if (sc->sc_recv_work_pending == true) {
  614                 callout_schedule(&sc->sc_recv_ch, se_poll);
  615                 mutex_exit(&sc->sc_iflock);
  616                 return;
  617         }
  618 
  619         sc->sc_recv_work_pending = true;
  620         workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work, NULL);
  621         mutex_exit(&sc->sc_iflock);
  622 }
  623 
  624 /*
  625  * Invoke the receive workqueue
  626  */
  627 static void
  628 se_recv_worker(struct work *wk, void *cookie)
  629 {
  630         struct se_softc *sc = (struct se_softc *) cookie;
  631 
  632         mutex_enter(&sc->sc_iflock);
  633         sc->sc_recv_work_pending = false;
  634         mutex_exit(&sc->sc_iflock);
  635         se_recv(sc);
  636 
  637 }
  638 
  639 /*
  640  * Do the actual work of receiving data.
  641  */
  642 static void
  643 se_recv(struct se_softc *sc)
  644 {
  645         struct scsi_ctron_ether_recv recv_cmd;
  646         int error;
  647 
  648         /* do a recv command */
  649         PROTOCMD(ctron_ether_recv, recv_cmd);
  650 
  651         error = se_scsipi_cmd(sc->sc_periph,
  652             (void *)&recv_cmd, sizeof(recv_cmd),
  653             sc->sc_rbuf, RBUF_LEN, SERETRIES, SETIMEOUT, NULL,
  654             XS_CTL_NOSLEEP | XS_CTL_DATA_IN);
  655         if (error)
  656                 callout_schedule(&sc->sc_recv_ch, se_poll);
  657 }
  658 
  659 /*
  660  * We copy the data into mbufs.  When full cluster sized units are present
  661  * we copy into clusters.
  662  */
  663 static struct mbuf *
  664 se_get(struct se_softc *sc, char *data, int totlen)
  665 {
  666         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  667         struct mbuf *m, *m0, *newm;
  668         int len;
  669 
  670         MGETHDR(m0, M_DONTWAIT, MT_DATA);
  671         if (m0 == 0)
  672                 return (0);
  673         m_set_rcvif(m0, ifp);
  674         m0->m_pkthdr.len = totlen;
  675         len = MHLEN;
  676         m = m0;
  677 
  678         while (totlen > 0) {
  679                 if (totlen >= MINCLSIZE) {
  680                         MCLGET(m, M_DONTWAIT);
  681                         if ((m->m_flags & M_EXT) == 0)
  682                                 goto bad;
  683                         len = MCLBYTES;
  684                 }
  685 
  686                 if (m == m0) {
  687                         char *newdata = (char *)
  688                             ALIGN(m->m_data + sizeof(struct ether_header)) -
  689                             sizeof(struct ether_header);
  690                         len -= newdata - m->m_data;
  691                         m->m_data = newdata;
  692                 }
  693 
  694                 m->m_len = len = uimin(totlen, len);
  695                 memcpy(mtod(m, void *), data, len);
  696                 data += len;
  697 
  698                 totlen -= len;
  699                 if (totlen > 0) {
  700                         MGET(newm, M_DONTWAIT, MT_DATA);
  701                         if (newm == 0)
  702                                 goto bad;
  703                         len = MLEN;
  704                         m = m->m_next = newm;
  705                 }
  706         }
  707 
  708         return (m0);
  709 
  710 bad:
  711         m_freem(m0);
  712         return (0);
  713 }
  714 
  715 /*
  716  * Pass packets to higher levels.
  717  */
  718 static int
  719 se_read(struct se_softc *sc, char *data, int datalen)
  720 {
  721         struct mbuf *m;
  722         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  723         int n;
  724 
  725         n = 0;
  726         while (datalen >= 2) {
  727                 int len = _2btol(data);
  728                 data += 2;
  729                 datalen -= 2;
  730 
  731                 if (len == 0)
  732                         break;
  733 #ifdef SEDEBUG
  734                 if (sc->sc_debug) {
  735                         printf("se_read: datalen = %d, packetlen = %d, proto = 0x%04x\n", datalen, len,
  736                          ntohs(((struct ether_header *)data)->ether_type));
  737                 }
  738 #endif
  739                 if (len <= sizeof(struct ether_header) ||
  740                     len > MAX_SNAP) {
  741 #ifdef SEDEBUG
  742                         printf("%s: invalid packet size %d; dropping\n",
  743                                device_xname(sc->sc_dev), len);
  744 #endif
  745                         if_statinc(ifp, if_ierrors);
  746                         goto next_packet;
  747                 }
  748 
  749                 /* Don't need crc. Must keep ether header for BPF */
  750                 m = se_get(sc, data, len - ETHER_CRC);
  751                 if (m == 0) {
  752 #ifdef SEDEBUG
  753                         if (sc->sc_debug)
  754                                 printf("se_read: se_get returned null\n");
  755 #endif
  756                         if_statinc(ifp, if_ierrors);
  757                         goto next_packet;
  758                 }
  759                 if ((ifp->if_flags & IFF_PROMISC) != 0) {
  760                         m_adj(m, SE_PREFIX);
  761                 }
  762 
  763                 /* Pass the packet up. */
  764                 if_percpuq_enqueue(sc->sc_ipq, m);
  765 
  766         next_packet:
  767                 data += len;
  768                 datalen -= len;
  769                 n++;
  770         }
  771         return (n);
  772 }
  773 
  774 #if 0
  775 static void
  776 sewatchdog(struct ifnet *ifp)
  777 {
  778         struct se_softc *sc = ifp->if_softc;
  779 
  780         log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
  781         if_statinc(ifp, if_oerrors);
  782 
  783         se_reset(sc);
  784 }
  785 
  786 static void
  787 se_reset(struct se_softc *sc)
  788 {
  789 #if 0
  790         /* Maybe we don't *really* want to reset the entire bus
  791          * because the ctron isn't working. We would like to send a
  792          * "BUS DEVICE RESET" message, but don't think the ctron
  793          * understands it.
  794          */
  795         se_scsipi_cmd(sc->sc_periph, 0, 0, 0, 0, SERETRIES, 2000, NULL,
  796             XS_CTL_RESET);
  797 #endif
  798         se_init(sc);
  799 }
  800 #endif
  801 
  802 static int
  803 se_add_proto(struct se_softc *sc, int proto)
  804 {
  805         int error;
  806         struct scsi_ctron_ether_generic add_proto_cmd;
  807         uint8_t data[2];
  808         _lto2b(proto, data);
  809 #ifdef SEDEBUG
  810         if (sc->sc_debug)
  811                 printf("se: adding proto 0x%02x%02x\n", data[0], data[1]);
  812 #endif
  813 
  814         PROTOCMD(ctron_ether_add_proto, add_proto_cmd);
  815         _lto2b(sizeof(data), add_proto_cmd.length);
  816         error = se_scsipi_cmd(sc->sc_periph,
  817             (void *)&add_proto_cmd, sizeof(add_proto_cmd),
  818             data, sizeof(data), SERETRIES, SETIMEOUT, NULL,
  819             XS_CTL_DATA_OUT);
  820         return (error);
  821 }
  822 
  823 static int
  824 se_get_addr(struct se_softc *sc, uint8_t *myaddr)
  825 {
  826         int error;
  827         struct scsi_ctron_ether_generic get_addr_cmd;
  828 
  829         PROTOCMD(ctron_ether_get_addr, get_addr_cmd);
  830         _lto2b(ETHER_ADDR_LEN, get_addr_cmd.length);
  831         error = se_scsipi_cmd(sc->sc_periph,
  832             (void *)&get_addr_cmd, sizeof(get_addr_cmd),
  833             myaddr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  834             XS_CTL_DATA_IN);
  835         printf("%s: ethernet address %s\n", device_xname(sc->sc_dev),
  836             ether_sprintf(myaddr));
  837         return (error);
  838 }
  839 
  840 
  841 static int
  842 se_set_media(struct se_softc *sc, int type)
  843 {
  844         int error;
  845         struct scsi_ctron_ether_generic set_media_cmd;
  846 
  847         PROTOCMD(ctron_ether_set_media, set_media_cmd);
  848         set_media_cmd.byte3 = type;
  849         error = se_scsipi_cmd(sc->sc_periph,
  850             (void *)&set_media_cmd, sizeof(set_media_cmd),
  851             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  852         return (error);
  853 }
  854 
  855 static int
  856 se_set_mode(struct se_softc *sc, int len, int mode)
  857 {
  858         int error;
  859         struct scsi_ctron_ether_set_mode set_mode_cmd;
  860 
  861         PROTOCMD(ctron_ether_set_mode, set_mode_cmd);
  862         set_mode_cmd.mode = mode;
  863         _lto2b(len, set_mode_cmd.length);
  864         error = se_scsipi_cmd(sc->sc_periph,
  865             (void *)&set_mode_cmd, sizeof(set_mode_cmd),
  866             0, 0, SERETRIES, SETIMEOUT, NULL, 0);
  867         return (error);
  868 }
  869 
  870 
  871 static int
  872 se_init(struct se_softc *sc)
  873 {
  874         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  875         struct scsi_ctron_ether_generic set_addr_cmd;
  876         uint8_t enaddr[ETHER_ADDR_LEN];
  877         int error;
  878 
  879         if (ifp->if_flags & IFF_PROMISC) {
  880                 error = se_set_mode(sc, MAX_SNAP, 1);
  881         }
  882         else
  883                 error = se_set_mode(sc, ETHERMTU + sizeof(struct ether_header),
  884                     0);
  885         if (error != 0)
  886                 return (error);
  887 
  888         PROTOCMD(ctron_ether_set_addr, set_addr_cmd);
  889         _lto2b(ETHER_ADDR_LEN, set_addr_cmd.length);
  890         memcpy(enaddr, CLLADDR(ifp->if_sadl), sizeof(enaddr));
  891         error = se_scsipi_cmd(sc->sc_periph,
  892             (void *)&set_addr_cmd, sizeof(set_addr_cmd),
  893             enaddr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL,
  894             XS_CTL_DATA_OUT);
  895         if (error != 0)
  896                 return (error);
  897 
  898         if ((sc->protos & PROTO_IP) &&
  899             (error = se_add_proto(sc, ETHERTYPE_IP)) != 0)
  900                 return (error);
  901         if ((sc->protos & PROTO_ARP) &&
  902             (error = se_add_proto(sc, ETHERTYPE_ARP)) != 0)
  903                 return (error);
  904         if ((sc->protos & PROTO_REVARP) &&
  905             (error = se_add_proto(sc, ETHERTYPE_REVARP)) != 0)
  906                 return (error);
  907 #ifdef NETATALK
  908         if ((sc->protos & PROTO_AT) &&
  909             (error = se_add_proto(sc, ETHERTYPE_ATALK)) != 0)
  910                 return (error);
  911         if ((sc->protos & PROTO_AARP) &&
  912             (error = se_add_proto(sc, ETHERTYPE_AARP)) != 0)
  913                 return (error);
  914 #endif
  915 
  916         if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_UP) {
  917                 ifp->if_flags |= IFF_RUNNING;
  918                 mutex_enter(&sc->sc_iflock);
  919                 if (!sc->sc_recv_work_pending)  {
  920                         sc->sc_recv_work_pending = true;
  921                         workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work,
  922                             NULL);
  923                 }
  924                 mutex_exit(&sc->sc_iflock);
  925                 ifp->if_flags &= ~IFF_OACTIVE;
  926                 mutex_enter(&sc->sc_iflock);
  927                 if (!sc->sc_send_work_pending)  {
  928                         sc->sc_send_work_pending = true;
  929                         workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work,
  930                             NULL);
  931                 }
  932                 mutex_exit(&sc->sc_iflock);
  933         }
  934         return (error);
  935 }
  936 
  937 static int
  938 se_set_multi(struct se_softc *sc, uint8_t *addr)
  939 {
  940         struct scsi_ctron_ether_generic set_multi_cmd;
  941         int error;
  942 
  943         if (sc->sc_debug)
  944                 printf("%s: set_set_multi: %s\n", device_xname(sc->sc_dev),
  945                     ether_sprintf(addr));
  946 
  947         PROTOCMD(ctron_ether_set_multi, set_multi_cmd);
  948         _lto2b(ETHER_ADDR_LEN, set_multi_cmd.length);
  949         error = se_scsipi_cmd(sc->sc_periph,
  950             (void *)&set_multi_cmd, sizeof(set_multi_cmd),
  951             addr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  952         return (error);
  953 }
  954 
  955 static int
  956 se_remove_multi(struct se_softc *sc, uint8_t *addr)
  957 {
  958         struct scsi_ctron_ether_generic remove_multi_cmd;
  959         int error;
  960 
  961         if (sc->sc_debug)
  962                 printf("%s: se_remove_multi: %s\n", device_xname(sc->sc_dev),
  963                     ether_sprintf(addr));
  964 
  965         PROTOCMD(ctron_ether_remove_multi, remove_multi_cmd);
  966         _lto2b(ETHER_ADDR_LEN, remove_multi_cmd.length);
  967         error = se_scsipi_cmd(sc->sc_periph,
  968             (void *)&remove_multi_cmd, sizeof(remove_multi_cmd),
  969             addr, ETHER_ADDR_LEN, SERETRIES, SETIMEOUT, NULL, XS_CTL_DATA_OUT);
  970         return (error);
  971 }
  972 
  973 #if 0   /* not used  --thorpej */
  974 static int
  975 sc_set_all_multi(struct se_softc *sc, int set)
  976 {
  977         int error = 0;
  978         uint8_t *addr;
  979         struct ethercom *ec = &sc->sc_ethercom;
  980         struct ether_multi *enm;
  981         struct ether_multistep step;
  982 
  983         ETHER_LOCK(ec);
  984         ETHER_FIRST_MULTI(step, ec, enm);
  985         while (enm != NULL) {
  986                 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
  987                         /*
  988                          * We must listen to a range of multicast addresses.
  989                          * For now, just accept all multicasts, rather than
  990                          * trying to set only those filter bits needed to match
  991                          * the range.  (At this time, the only use of address
  992                          * ranges is for IP multicast routing, for which the
  993                          * range is big enough to require all bits set.)
  994                          */
  995                         /* We have no way of adding a range to this device.
  996                          * stepping through all addresses in the range is
  997                          * typically not possible. The only real alternative
  998                          * is to go into promicuous mode and filter by hand.
  999                          */
 1000                         ETHER_UNLOCK(ec);
 1001                         return (ENODEV);
 1002 
 1003                 }
 1004 
 1005                 addr = enm->enm_addrlo;
 1006                 if ((error = set ? se_set_multi(sc, addr) :
 1007                     se_remove_multi(sc, addr)) != 0)
 1008                         return (error);
 1009                 ETHER_NEXT_MULTI(step, enm);
 1010         }
 1011         ETHER_UNLOCK(ec);
 1012 
 1013         return (error);
 1014 }
 1015 #endif /* not used */
 1016 
 1017 static void
 1018 se_stop(struct se_softc *sc)
 1019 {
 1020 
 1021         /* Don't schedule any reads */
 1022         callout_halt(&sc->sc_recv_ch, &sc->sc_iflock);
 1023 
 1024         /* Wait for the workqueues to finish */
 1025         mutex_enter(&sc->sc_iflock);
 1026         workqueue_wait(sc->sc_recv_wq, &sc->sc_recv_work);
 1027         workqueue_wait(sc->sc_send_wq, &sc->sc_send_work);
 1028         mutex_exit(&sc->sc_iflock);
 1029 
 1030         /* Abort any scsi cmds in progress */
 1031         mutex_enter(chan_mtx(sc->sc_periph->periph_channel));
 1032         scsipi_kill_pending(sc->sc_periph);
 1033         mutex_exit(chan_mtx(sc->sc_periph->periph_channel));
 1034 }
 1035 
 1036 
 1037 /*
 1038  * Process an ioctl request.
 1039  */
 1040 static int
 1041 se_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 1042 {
 1043         struct se_softc *sc = ifp->if_softc;
 1044         struct ifaddr *ifa = (struct ifaddr *)data;
 1045         struct ifreq *ifr = (struct ifreq *)data;
 1046         struct sockaddr *sa;
 1047         int error = 0;
 1048 
 1049 
 1050         switch (cmd) {
 1051 
 1052         case SIOCINITIFADDR:
 1053                 mutex_enter(&sc->sc_iflock);
 1054                 if ((error = se_enable(sc)) != 0)
 1055                         break;
 1056                 ifp->if_flags |= IFF_UP;
 1057                 mutex_exit(&sc->sc_iflock);
 1058 
 1059                 if ((error = se_set_media(sc, CMEDIA_AUTOSENSE)) != 0)
 1060                         break;
 1061 
 1062                 switch (ifa->ifa_addr->sa_family) {
 1063 #ifdef INET
 1064                 case AF_INET:
 1065                         sc->protos |= (PROTO_IP | PROTO_ARP | PROTO_REVARP);
 1066                         if ((error = se_init(sc)) != 0)
 1067                                 break;
 1068                         arp_ifinit(ifp, ifa);
 1069                         break;
 1070 #endif
 1071 #ifdef NETATALK
 1072                 case AF_APPLETALK:
 1073                         sc->protos |= (PROTO_AT | PROTO_AARP);
 1074                         if ((error = se_init(sc)) != 0)
 1075                                 break;
 1076                         break;
 1077 #endif
 1078                 default:
 1079                         error = se_init(sc);
 1080                         break;
 1081                 }
 1082                 break;
 1083 
 1084 
 1085         case SIOCSIFFLAGS:
 1086                 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
 1087                         break;
 1088                 /* XXX re-use ether_ioctl() */
 1089                 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
 1090                 case IFF_RUNNING:
 1091                         /*
 1092                          * If interface is marked down and it is running, then
 1093                          * stop it.
 1094                          */
 1095                         se_stop(sc);
 1096                         mutex_enter(&sc->sc_iflock);
 1097                         ifp->if_flags &= ~IFF_RUNNING;
 1098                         se_disable(sc);
 1099                         mutex_exit(&sc->sc_iflock);
 1100                         break;
 1101                 case IFF_UP:
 1102                         /*
 1103                          * If interface is marked up and it is stopped, then
 1104                          * start it.
 1105                          */
 1106                         mutex_enter(&sc->sc_iflock);
 1107                         error = se_enable(sc);
 1108                         mutex_exit(&sc->sc_iflock);
 1109                         if (error)
 1110                                 break;
 1111                         error = se_init(sc);
 1112                         break;
 1113                 default:
 1114                         /*
 1115                          * Reset the interface to pick up changes in any other
 1116                          * flags that affect hardware registers.
 1117                          */
 1118                         if (sc->sc_enabled)
 1119                                 error = se_init(sc);
 1120                         break;
 1121                 }
 1122 #ifdef SEDEBUG
 1123                 if (ifp->if_flags & IFF_DEBUG)
 1124                         sc->sc_debug = 1;
 1125                 else
 1126                         sc->sc_debug = 0;
 1127 #endif
 1128                 break;
 1129 
 1130         case SIOCADDMULTI:
 1131         case SIOCDELMULTI:
 1132                 mutex_enter(&sc->sc_iflock);
 1133                 sa = sockaddr_dup(ifreq_getaddr(cmd, ifr), M_WAITOK);
 1134                 mutex_exit(&sc->sc_iflock);
 1135                 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
 1136                         if (ifp->if_flags & IFF_RUNNING) {
 1137                                 error = (cmd == SIOCADDMULTI) ?
 1138                                    se_set_multi(sc, sa->sa_data) :
 1139                                    se_remove_multi(sc, sa->sa_data);
 1140                         } else
 1141                                 error = 0;
 1142                 }
 1143                 mutex_enter(&sc->sc_iflock);
 1144                 sockaddr_free(sa);
 1145                 mutex_exit(&sc->sc_iflock);
 1146                 break;
 1147 
 1148         default:
 1149 
 1150                 error = ether_ioctl(ifp, cmd, data);
 1151                 break;
 1152         }
 1153 
 1154         return (error);
 1155 }
 1156 
 1157 /*
 1158  * Enable the network interface.
 1159  */
 1160 int
 1161 se_enable(struct se_softc *sc)
 1162 {
 1163         struct scsipi_periph *periph = sc->sc_periph;
 1164         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1165         int error = 0;
 1166 
 1167         if (sc->sc_enabled == 0) {
 1168                 if ((error = scsipi_adapter_addref(adapt)) == 0)
 1169                         sc->sc_enabled = 1;
 1170                 else
 1171                         aprint_error_dev(sc->sc_dev, "device enable failed\n");
 1172         }
 1173         return (error);
 1174 }
 1175 
 1176 /*
 1177  * Disable the network interface.
 1178  */
 1179 void
 1180 se_disable(struct se_softc *sc)
 1181 {
 1182         struct scsipi_periph *periph = sc->sc_periph;
 1183         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1184 
 1185         if (sc->sc_enabled != 0) {
 1186                 scsipi_adapter_delref(adapt);
 1187                 sc->sc_enabled = 0;
 1188         }
 1189 }
 1190 
 1191 #define SEUNIT(z)       (minor(z))
 1192 /*
 1193  * open the device.
 1194  */
 1195 int
 1196 seopen(dev_t dev, int flag, int fmt, struct lwp *l)
 1197 {
 1198         int unit, error;
 1199         struct se_softc *sc;
 1200         struct scsipi_periph *periph;
 1201         struct scsipi_adapter *adapt;
 1202 
 1203         unit = SEUNIT(dev);
 1204         sc = device_lookup_private(&se_cd, unit);
 1205         if (sc == NULL)
 1206                 return (ENXIO);
 1207 
 1208         periph = sc->sc_periph;
 1209         adapt = periph->periph_channel->chan_adapter;
 1210 
 1211         if ((error = scsipi_adapter_addref(adapt)) != 0)
 1212                 return (error);
 1213 
 1214         SC_DEBUG(periph, SCSIPI_DB1,
 1215             ("scopen: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
 1216             se_cd.cd_ndevs));
 1217 
 1218         periph->periph_flags |= PERIPH_OPEN;
 1219 
 1220         SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
 1221         return (0);
 1222 }
 1223 
 1224 /*
 1225  * close the device.. only called if we are the LAST
 1226  * occurrence of an open device
 1227  */
 1228 int
 1229 seclose(dev_t dev, int flag, int fmt, struct lwp *l)
 1230 {
 1231         struct se_softc *sc = device_lookup_private(&se_cd, SEUNIT(dev));
 1232         struct scsipi_periph *periph = sc->sc_periph;
 1233         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 1234 
 1235         SC_DEBUG(sc->sc_periph, SCSIPI_DB1, ("closing\n"));
 1236 
 1237         scsipi_wait_drain(periph);
 1238 
 1239         scsipi_adapter_delref(adapt);
 1240         periph->periph_flags &= ~PERIPH_OPEN;
 1241 
 1242         return (0);
 1243 }
 1244 
 1245 /*
 1246  * Perform special action on behalf of the user
 1247  * Only does generic scsi ioctls.
 1248  */
 1249 int
 1250 seioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
 1251 {
 1252         struct se_softc *sc = device_lookup_private(&se_cd, SEUNIT(dev));
 1253 
 1254         return (scsipi_do_ioctl(sc->sc_periph, dev, cmd, addr, flag, l));
 1255 }

Cache object: a88f4e65c739fae349e19be946a9da6d


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