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/ieee1394/if_fwip.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_fwip.c,v 1.6 2006/11/16 01:32:59 christos Exp $     */
    2 /*-
    3  * Copyright (c) 2004
    4  *      Doug Rabson
    5  * Copyright (c) 2002-2003
    6  *      Hidetoshi Shimokawa. All rights reserved.
    7  * 
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *
   19  *      This product includes software developed by Hidetoshi Shimokawa.
   20  *
   21  * 4. Neither the name of the author nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  * 
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  * 
   37  * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/if_fwip.c,v 1.6 2005/01/06 01:42:41 imp Exp $
   38  */
   39 
   40 #include "opt_inet.h"
   41 
   42 #if defined(__FreeBSD__)
   43 #include <sys/param.h>
   44 #include <sys/kernel.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mbuf.h>
   47 #include <sys/socket.h>
   48 #include <sys/sockio.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/systm.h>
   51 #include <sys/taskqueue.h>
   52 #include <sys/module.h>
   53 #include <sys/bus.h>
   54 #include <machine/bus.h>
   55 
   56 #include <net/bpf.h>
   57 #include <net/if.h>
   58 #include <net/firewire.h>
   59 #include <net/if_arp.h>
   60 #ifdef __DragonFly__
   61 #include <bus/firewire/fw_port.h>
   62 #include <bus/firewire/firewire.h>
   63 #include <bus/firewire/firewirereg.h>
   64 #include "if_fwipvar.h"
   65 #else
   66 #include <dev/firewire/fw_port.h>
   67 #include <dev/firewire/firewire.h>
   68 #include <dev/firewire/firewirereg.h>
   69 #include <dev/firewire/iec13213.h>
   70 #include <dev/firewire/if_fwipvar.h>
   71 #endif
   72 #elif defined(__NetBSD__)
   73 #include <sys/param.h>
   74 #include <sys/device.h>
   75 #include <sys/errno.h>
   76 #include <sys/malloc.h>
   77 #include <sys/mbuf.h>
   78 #include <sys/sysctl.h>
   79 
   80 #include <machine/bus.h>
   81 
   82 #include <net/if.h>
   83 #include <net/if_ieee1394.h>
   84 
   85 #include <dev/ieee1394/fw_port.h>
   86 #include <dev/ieee1394/firewire.h>
   87 #include <dev/ieee1394/firewirereg.h>
   88 #include <dev/ieee1394/iec13213.h>
   89 #include <dev/ieee1394/if_fwipvar.h>
   90 #endif
   91 
   92 /*
   93  * We really need a mechanism for allocating regions in the FIFO
   94  * address space. We pick a address in the OHCI controller's 'middle'
   95  * address space. This means that the controller will automatically
   96  * send responses for us, which is fine since we don't have any
   97  * important information to put in the response anyway.
   98  */
   99 #define INET_FIFO       0xfffe00000000LL
  100 
  101 #if defined(__FreeBSD__)
  102 #define FWIPDEBUG       if (fwipdebug) if_printf
  103 #elif defined(__NetBSD__)
  104 #define FWIPDEBUG(ifp, fmt, ...) \
  105         if (fwipdebug) {\
  106                 aprint_normal("%s: ", (ifp)->if_xname); \
  107                 aprint_normal((fmt) ,##__VA_ARGS__); \
  108         }
  109 #endif
  110 #define TX_MAX_QUEUE    (FWMAXQUEUE - 1)
  111 
  112 #if defined(__NetBSD__)
  113 int fwipmatch (struct device *, struct cfdata *, void *);
  114 void fwipattach (struct device *, struct device *, void *);
  115 int fwipdetach (struct device *, int);
  116 int fwipactivate (struct device *, enum devact);
  117 
  118 #endif  
  119 /* network interface */
  120 static void fwip_start (struct ifnet *);
  121 static int fwip_ioctl (struct ifnet *, u_long, caddr_t);
  122 IF_INIT(fwip);
  123 IF_STOP(fwip);
  124 
  125 static void fwip_post_busreset (void *);
  126 static void fwip_output_callback (struct fw_xfer *);
  127 static void fwip_async_output (struct fwip_softc *, struct ifnet *);
  128 #if defined(__FreeBSD__)
  129 static void fwip_start_send (void *, int);
  130 #endif
  131 static void fwip_stream_input (struct fw_xferq *);
  132 static void fwip_unicast_input(struct fw_xfer *);
  133 
  134 static int fwipdebug = 0;
  135 static int broadcast_channel = 0xc0 | 0x1f; /*  tag | channel(XXX) */
  136 static int tx_speed = 2;
  137 static int rx_queue_len = FWMAXQUEUE;
  138 
  139 #if defined(__FreeBSD__)
  140 MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface");
  141 SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, "");
  142 SYSCTL_DECL(_hw_firewire);
  143 SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0,
  144         "Firewire ip subsystem");
  145 SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len,
  146         0, "Length of the receive queue");
  147 
  148 TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len);
  149 #elif defined(__NetBSD__)
  150 MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over IEEE1394 interface");
  151 /*
  152  * Setup sysctl(3) MIB, hw.fwip.*
  153  *
  154  * TBD condition CTLFLAG_PERMANENT on being an LKM or not
  155  */
  156 SYSCTL_SETUP(sysctl_fwip, "sysctl fwip(4) subtree setup")
  157 {
  158         int rc, fwip_node_num;
  159         const struct sysctlnode *node;
  160 
  161         if ((rc = sysctl_createv(clog, 0, NULL, NULL,
  162             CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
  163             NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
  164                 goto err;
  165         }
  166 
  167         if ((rc = sysctl_createv(clog, 0, NULL, &node,
  168             CTLFLAG_PERMANENT, CTLTYPE_NODE, "fwip",
  169             SYSCTL_DESCR("fwip controls"),
  170             NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
  171                 goto err;
  172         }
  173         fwip_node_num = node->sysctl_num;
  174 
  175         /* fwip RX queue length */
  176         if ((rc = sysctl_createv(clog, 0, NULL, &node,
  177             CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
  178             "rx_queue_len", SYSCTL_DESCR("Length of the receive queue"),
  179             NULL, 0, &rx_queue_len,
  180             0, CTL_HW, fwip_node_num, CTL_CREATE, CTL_EOL)) != 0) {
  181                 goto err;
  182         }
  183 
  184         /* fwip RX queue length */
  185         if ((rc = sysctl_createv(clog, 0, NULL, &node,
  186             CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
  187             "if_fwip_debug", SYSCTL_DESCR("fwip driver debug flag"),
  188             NULL, 0, &fwipdebug,
  189             0, CTL_HW, fwip_node_num, CTL_CREATE, CTL_EOL)) != 0) {
  190                 goto err;
  191         }
  192 
  193         return;
  194 
  195 err:
  196         printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
  197 }
  198 #endif
  199 
  200 #ifdef DEVICE_POLLING
  201 #define FWIP_POLL_REGISTER(func, fwip, ifp)                     \
  202         if (ether_poll_register(func, ifp)) {                   \
  203                 struct firewire_comm *fc = (fwip)->fd.fc;       \
  204                 fc->set_intr(fc, 0);                            \
  205         }
  206 
  207 #define FWIP_POLL_DEREGISTER(fwip, ifp)                         \
  208         do {                                                    \
  209                 struct firewire_comm *fc = (fwip)->fd.fc;       \
  210                 ether_poll_deregister(ifp);                     \
  211                 fc->set_intr(fc, 1);                            \
  212         } while(0)                                              \
  213 
  214 static poll_handler_t fwip_poll;
  215 
  216 static void
  217 fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
  218 {
  219         struct fwip_softc *fwip;
  220         struct firewire_comm *fc;
  221 
  222         fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
  223         fc = fwip->fd.fc;
  224         if (cmd == POLL_DEREGISTER) {
  225                 /* enable interrupts */
  226                 fc->set_intr(fc, 1);
  227                 return;
  228         }
  229         fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
  230 }
  231 #else
  232 #define FWIP_POLL_REGISTER(func, fwip, ifp)
  233 #define FWIP_POLL_DEREGISTER(fwip, ifp)
  234 #endif
  235 #if defined(__FreeBSD__)
  236 static void
  237 fwip_identify(driver_t *driver, device_t parent)
  238 {
  239         BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent));
  240 }
  241 
  242 static int
  243 fwip_probe(device_t dev)
  244 {
  245         device_t pa;
  246 
  247         pa = device_get_parent(dev);
  248         if(device_get_unit(dev) != device_get_unit(pa)){
  249                 return(ENXIO);
  250         }
  251 
  252         device_set_desc(dev, "IP over FireWire");
  253         return (0);
  254 }
  255 #elif defined(__NetBSD__)
  256 int
  257 fwipmatch(struct device *parent, struct cfdata *cf, void *aux)
  258 {
  259         struct fw_attach_args *fwa = aux;
  260 
  261         if (strcmp(fwa->name, "fwip") == 0)
  262                 return (1);
  263         return (0);
  264 }
  265 #endif
  266 
  267 FW_ATTACH(fwip)
  268 {
  269         FW_ATTACH_START(fwip, fwip, fwa);
  270         FWIP_ATTACH_START;
  271         struct ifnet *ifp;
  272         int s;
  273 
  274         FWIP_ATTACH_SETUP;
  275 
  276         /* XXX */
  277         fwip->dma_ch = -1;
  278 
  279         fwip->fd.fc = fwa->fc;
  280         if (tx_speed < 0)
  281                 tx_speed = fwip->fd.fc->speed;
  282 
  283         fwip->fd.post_explore = NULL;
  284         fwip->fd.post_busreset = fwip_post_busreset;
  285         fwip->fw_softc.fwip = fwip;
  286         TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip);
  287 
  288         /*
  289          * Encode our hardware the way that arp likes it.
  290          */
  291         hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi);
  292         hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo);
  293         hwaddr->sender_max_rec = fwip->fd.fc->maxrec;
  294         hwaddr->sspd = fwip->fd.fc->speed;
  295         hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32));
  296         hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO);
  297 
  298         /* fill the rest and attach interface */        
  299         ifp = &fwip->fwip_if;
  300         ifp->if_softc = &fwip->fw_softc;
  301 
  302 #if __FreeBSD_version >= 501113 || defined(__DragonFly__) || defined(__NetBSD__)
  303         IF_INITNAME(ifp, dev, unit);
  304 #else
  305         ifp->if_unit = unit;
  306         ifp->if_name = "fwip";
  307 #endif
  308 #if defined(__NetBSD__)
  309         IFQ_SET_READY(&ifp->if_snd);
  310 #endif
  311         SET_IFFUNC(ifp, fwip_start, fwip_ioctl, fwip_init, fwip_stop);
  312         ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
  313             IFF_NEEDSGIANT);
  314         ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
  315 
  316         s = splfwnet();
  317         FIREWIRE_IFATTACH(ifp, hwaddr);
  318         splx(s);
  319 
  320         FWIPDEBUG(ifp, "interface created\n");
  321         FW_ATTACH_RETURN(0);
  322 }
  323 
  324 IF_STOP(fwip)
  325 {
  326         IF_STOP_START(fwip, ifp, fwip);
  327         struct firewire_comm *fc;
  328         struct fw_xferq *xferq;
  329         struct fw_xfer *xfer, *next;
  330         int i;
  331 
  332         fc = fwip->fd.fc;
  333 
  334         FWIP_POLL_DEREGISTER(fwip, ifp);
  335 
  336         if (fwip->dma_ch >= 0) {
  337                 xferq = fc->ir[fwip->dma_ch];
  338 
  339                 if (xferq->flag & FWXFERQ_RUNNING)
  340                         fc->irx_disable(fc, fwip->dma_ch);
  341                 xferq->flag &= 
  342                         ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM |
  343                         FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK);
  344                 xferq->hand =  NULL;
  345 
  346                 for (i = 0; i < xferq->bnchunk; i ++)
  347                         m_freem(xferq->bulkxfer[i].mbuf);
  348                 free(xferq->bulkxfer, M_FWIP);
  349 
  350                 fw_bindremove(fc, &fwip->fwb);
  351                 for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL;
  352                                         xfer = next) {
  353                         next = STAILQ_NEXT(xfer, link);
  354                         fw_xfer_free(xfer);
  355                 }
  356 
  357                 for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL;
  358                                         xfer = next) {
  359                         next = STAILQ_NEXT(xfer, link);
  360                         fw_xfer_free(xfer);
  361                 }
  362                 STAILQ_INIT(&fwip->xferlist);
  363 
  364                 xferq->bulkxfer =  NULL;
  365                 fwip->dma_ch = -1;
  366         }
  367 
  368         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  369 }
  370 
  371 FW_DETACH(fwip)
  372 {
  373         IF_DETACH_START(fwip, fwip);
  374         int s;
  375 
  376         s = splfwnet();
  377 
  378         FWIP_STOP(fwip);
  379         FIREWIRE_IFDETACH(&fwip->fwip_if);
  380 
  381         splx(s);
  382         return 0;
  383 }
  384 
  385 #if defined(__NetBSD__)
  386 int
  387 fwipactivate(struct device *self, enum devact act)
  388 {
  389         struct fwip_softc *fwip = (struct fwip_softc *)self;
  390         int s, error = 0;
  391 
  392         s = splfwnet();
  393         switch (act) {
  394         case DVACT_ACTIVATE:
  395                 error = EOPNOTSUPP;
  396                 break;
  397 
  398         case DVACT_DEACTIVATE:
  399                 if_deactivate(&fwip->fwip_if);
  400                         break;
  401         }
  402         splx(s);
  403 
  404         return (error);
  405 }
  406 
  407 #endif
  408 IF_INIT(fwip)
  409 {
  410         IF_INIT_START(fwip, fwip, ifp);
  411         struct firewire_comm *fc;
  412         struct fw_xferq *xferq;
  413         struct fw_xfer *xfer;
  414         struct mbuf *m;
  415         int i;
  416 
  417         FWIPDEBUG(ifp, "initializing\n");
  418 
  419         fc = fwip->fd.fc;
  420 #define START 0
  421         if (fwip->dma_ch < 0) {
  422                 for (i = START; i < fc->nisodma; i ++) {
  423                         xferq = fc->ir[i];
  424                         if ((xferq->flag & FWXFERQ_OPEN) == 0)
  425                                 goto found;
  426                 }
  427                 printf("no free dma channel\n");
  428                 IF_INIT_RETURN(ENXIO);
  429 found:
  430                 fwip->dma_ch = i;
  431                 /* allocate DMA channel and init packet mode */
  432                 xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF |
  433                                 FWXFERQ_HANDLER | FWXFERQ_STREAM;
  434                 xferq->flag &= ~0xff;
  435                 xferq->flag |= broadcast_channel & 0xff;
  436                 /* register fwip_input handler */
  437                 xferq->sc = (caddr_t) fwip;
  438                 xferq->hand = fwip_stream_input;
  439                 xferq->bnchunk = rx_queue_len;
  440                 xferq->bnpacket = 1;
  441                 xferq->psize = MCLBYTES;
  442                 xferq->queued = 0;
  443                 xferq->buf = NULL;
  444                 xferq->bulkxfer = (struct fw_bulkxfer *) malloc(
  445                         sizeof(struct fw_bulkxfer) * xferq->bnchunk,
  446                                                         M_FWIP, M_WAITOK);
  447                 if (xferq->bulkxfer == NULL) {
  448                         printf("if_fwip: malloc failed\n");
  449                         IF_INIT_RETURN(ENOMEM);
  450                 }
  451                 STAILQ_INIT(&xferq->stvalid);
  452                 STAILQ_INIT(&xferq->stfree);
  453                 STAILQ_INIT(&xferq->stdma);
  454                 xferq->stproc = NULL;
  455                 for (i = 0; i < xferq->bnchunk; i ++) {
  456                         m =
  457 #if defined(__DragonFly__) || __FreeBSD_version < 500000
  458                                 m_getcl(M_WAIT, MT_DATA, M_PKTHDR);
  459 #else
  460                                 m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
  461 #endif
  462                         xferq->bulkxfer[i].mbuf = m;
  463                         if (m != NULL) {
  464                                 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
  465                                 STAILQ_INSERT_TAIL(&xferq->stfree,
  466                                                 &xferq->bulkxfer[i], link);
  467                         } else
  468                                 printf("fwip_as_input: m_getcl failed\n");
  469                 }
  470 
  471                 fwip->fwb.start = INET_FIFO;
  472                 fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */
  473 
  474                 /* pre-allocate xfer */
  475                 STAILQ_INIT(&fwip->fwb.xferlist);
  476                 for (i = 0; i < rx_queue_len; i ++) {
  477                         xfer = fw_xfer_alloc(M_FWIP);
  478                         if (xfer == NULL)
  479                                 break;
  480                         m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
  481                         xfer->recv.payload = mtod(m, uint32_t *);
  482                         xfer->recv.pay_len = MCLBYTES;
  483                         xfer->hand = fwip_unicast_input;
  484                         xfer->fc = fc;
  485                         xfer->sc = (caddr_t)fwip;
  486                         xfer->mbuf = m;
  487                         STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
  488                 }
  489                 fw_bindadd(fc, &fwip->fwb);
  490 
  491                 STAILQ_INIT(&fwip->xferlist);
  492                 for (i = 0; i < TX_MAX_QUEUE; i++) {
  493                         xfer = fw_xfer_alloc(M_FWIP);
  494                         if (xfer == NULL)
  495                                 break;
  496                         xfer->send.spd = tx_speed;
  497                         xfer->fc = fwip->fd.fc;
  498                         xfer->sc = (caddr_t)fwip;
  499                         xfer->hand = fwip_output_callback;
  500                         STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
  501                 }
  502         } else
  503                 xferq = fc->ir[fwip->dma_ch];
  504 
  505         fwip->last_dest.hi = 0;
  506         fwip->last_dest.lo = 0;
  507 
  508         /* start dma */
  509         if ((xferq->flag & FWXFERQ_RUNNING) == 0)
  510                 fc->irx_enable(fc, fwip->dma_ch);
  511 
  512         ifp->if_flags |= IFF_RUNNING;
  513         ifp->if_flags &= ~IFF_OACTIVE;
  514 
  515         FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
  516 #if 0
  517         /* attempt to start output */
  518         fwip_start(ifp);
  519 #endif
  520         IF_INIT_RETURN(0);
  521 }
  522 
  523 static int
  524 fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  525 {
  526         IF_IOCTL_START(fwip, fwip);
  527         int s, error;
  528 
  529         switch (cmd) {
  530         case SIOCSIFFLAGS:
  531                 s = splfwnet();
  532                 if (ifp->if_flags & IFF_UP) {
  533                         if (!(ifp->if_flags & IFF_RUNNING))
  534                                 FWIP_INIT(fwip);
  535                 } else {
  536                         if (ifp->if_flags & IFF_RUNNING)
  537                                 FWIP_STOP(fwip);
  538                 }
  539                 splx(s);
  540                 break;
  541         case SIOCADDMULTI:
  542         case SIOCDELMULTI:
  543                 break;
  544 
  545 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__NetBSD__)
  546         default:
  547 #else
  548         case SIOCSIFADDR:
  549         case SIOCGIFADDR:
  550         case SIOCSIFMTU:
  551 #endif
  552                 s = splfwnet();
  553                 error = FIREWIRE_IOCTL(ifp, cmd, data);
  554                 splx(s);
  555                 return (error);
  556 #if defined(__DragonFly__) || \
  557     (defined(__FreeBSD__) && __FreeBSD_version < 500000)
  558         default:
  559                 return (EINVAL);
  560 #endif
  561         }
  562 
  563         return (0);
  564 }
  565 
  566 static void
  567 fwip_post_busreset(void *arg)
  568 {
  569         struct fwip_softc *fwip = arg;
  570         struct crom_src *src;
  571         struct crom_chunk *root;
  572 
  573         src = fwip->fd.fc->crom_src;
  574         root = fwip->fd.fc->crom_root;
  575 
  576         /* RFC2734 IPv4 over IEEE1394 */
  577         bzero(&fwip->unit4, sizeof(struct crom_chunk));
  578         crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR);
  579         crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF);
  580         crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA");
  581         crom_add_entry(&fwip->unit4, CSRKEY_VER, 1);
  582         crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4");
  583 
  584         /* RFC3146 IPv6 over IEEE1394 */
  585         bzero(&fwip->unit6, sizeof(struct crom_chunk));
  586         crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR);
  587         crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF);
  588         crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA");
  589         crom_add_entry(&fwip->unit6, CSRKEY_VER, 2);
  590         crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6");
  591 
  592         fwip->last_dest.hi = 0;
  593         fwip->last_dest.lo = 0;
  594         FIREWIRE_BUSRESET(&fwip->fwip_if);
  595 }
  596 
  597 static void
  598 fwip_output_callback(struct fw_xfer *xfer)
  599 {
  600         struct fwip_softc *fwip;
  601         struct ifnet *ifp;
  602         int s;
  603 
  604         GIANT_REQUIRED;
  605 
  606         fwip = (struct fwip_softc *)xfer->sc;
  607         ifp = &fwip->fwip_if;
  608         /* XXX error check */
  609         FWIPDEBUG(ifp, "resp = %d\n", xfer->resp);
  610         if (xfer->resp != 0)
  611                 ifp->if_oerrors ++;
  612                 
  613         m_freem(xfer->mbuf);
  614         fw_xfer_unload(xfer);
  615 
  616         s = splfwnet();
  617         STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
  618         splx(s);
  619 
  620         /* for queue full */
  621         if (ifp->if_snd.ifq_head != NULL)
  622                 fwip_start(ifp);
  623 }
  624 
  625 static void
  626 fwip_start(struct ifnet *ifp)
  627 {
  628         struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
  629         int s;
  630 
  631         GIANT_REQUIRED;
  632 
  633         FWIPDEBUG(ifp, "starting\n");
  634 
  635         if (fwip->dma_ch < 0) {
  636                 struct mbuf     *m = NULL;
  637 
  638                 FWIPDEBUG(ifp, "not ready\n");
  639 
  640                 s = splfwnet();
  641                 do {
  642                         IF_DEQUEUE(&ifp->if_snd, m);
  643                         if (m != NULL)
  644                                 m_freem(m);
  645                         ifp->if_oerrors ++;
  646                 } while (m != NULL);
  647                 splx(s);
  648 
  649                 return;
  650         }
  651 
  652         s = splfwnet();
  653         ifp->if_flags |= IFF_OACTIVE;
  654 
  655         if (ifp->if_snd.ifq_len != 0)
  656                 fwip_async_output(fwip, ifp);
  657 
  658         ifp->if_flags &= ~IFF_OACTIVE;
  659         splx(s);
  660 }
  661 
  662 /* Async. stream output */
  663 static void
  664 fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
  665 {
  666         struct firewire_comm *fc = fwip->fd.fc;
  667         struct mbuf *m;
  668         struct m_tag *mtag;
  669         struct fw_hwaddr *destfw;
  670         struct fw_xfer *xfer;
  671         struct fw_xferq *xferq;
  672         struct fw_pkt *fp;
  673         uint16_t nodeid;
  674         int error;
  675         int i = 0;
  676 
  677         GIANT_REQUIRED;
  678 
  679         xfer = NULL;
  680         xferq = fwip->fd.fc->atq;
  681         while (xferq->queued < xferq->maxq - 1) {
  682                 xfer = STAILQ_FIRST(&fwip->xferlist);
  683                 if (xfer == NULL) {
  684                         printf("if_fwip: lack of xfer\n");
  685                         return;
  686                 }
  687                 IF_DEQUEUE(&ifp->if_snd, m);
  688                 if (m == NULL)
  689                         break;
  690 
  691                 /*
  692                  * Dig out the link-level address which
  693                  * firewire_output got via arp or neighbour
  694                  * discovery. If we don't have a link-level address,
  695                  * just stick the thing on the broadcast channel.
  696                  */
  697                 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0);
  698                 if (mtag == NULL)
  699                         destfw = 0;
  700                 else
  701                         destfw = (struct fw_hwaddr *) (mtag + 1);
  702 
  703                 STAILQ_REMOVE_HEAD(&fwip->xferlist, link);
  704 
  705                 /*
  706                  * We don't do any bpf stuff here - the generic code
  707                  * in firewire_output gives the packet to bpf before
  708                  * it adds the link-level encapsulation.
  709                  */
  710 
  711                 /*
  712                  * Put the mbuf in the xfer early in case we hit an
  713                  * error case below - fwip_output_callback will free
  714                  * the mbuf.
  715                  */
  716                 xfer->mbuf = m;
  717 
  718                 /*
  719                  * We use the arp result (if any) to add a suitable firewire
  720                  * packet header before handing off to the bus.
  721                  */
  722                 fp = &xfer->send.hdr;
  723                 nodeid = FWLOCALBUS | fc->nodeid;
  724                 if ((m->m_flags & M_BCAST) || !destfw) {
  725                         /*
  726                          * Broadcast packets are sent as GASP packets with
  727                          * specifier ID 0x00005e, version 1 on the broadcast
  728                          * channel. To be conservative, we send at the
  729                          * slowest possible speed.
  730                          */
  731                         uint32_t *p;
  732 
  733                         M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT);
  734                         p = mtod(m, uint32_t *);
  735                         fp->mode.stream.len = m->m_pkthdr.len;
  736                         fp->mode.stream.chtag = broadcast_channel;
  737                         fp->mode.stream.tcode = FWTCODE_STREAM;
  738                         fp->mode.stream.sy = 0;
  739                         xfer->send.spd = 0;
  740                         p[0] = htonl(nodeid << 16);
  741                         p[1] = htonl((0x5e << 24) | 1);
  742                 } else {
  743                         /*
  744                          * Unicast packets are sent as block writes to the
  745                          * target's unicast fifo address. If we can't
  746                          * find the node address, we just give up. We
  747                          * could broadcast it but that might overflow
  748                          * the packet size limitations due to the
  749                          * extra GASP header. Note: the hardware
  750                          * address is stored in network byte order to
  751                          * make life easier for ARP.
  752                          */
  753                         struct fw_device *fd;
  754                         struct fw_eui64 eui;
  755 
  756                         eui.hi = ntohl(destfw->sender_unique_ID_hi);
  757                         eui.lo = ntohl(destfw->sender_unique_ID_lo);
  758                         if (fwip->last_dest.hi != eui.hi ||
  759                             fwip->last_dest.lo != eui.lo) {
  760                                 fd = fw_noderesolve_eui64(fc, &eui);
  761                                 if (!fd) {
  762                                         /* error */
  763                                         ifp->if_oerrors ++;
  764                                         /* XXX set error code */
  765                                         fwip_output_callback(xfer);
  766                                         continue;
  767 
  768                                 }
  769                                 fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst;
  770                                 fwip->last_hdr.mode.wreqb.tlrt = 0;
  771                                 fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB;
  772                                 fwip->last_hdr.mode.wreqb.pri = 0;
  773                                 fwip->last_hdr.mode.wreqb.src = nodeid;
  774                                 fwip->last_hdr.mode.wreqb.dest_hi =
  775                                         ntohs(destfw->sender_unicast_FIFO_hi);
  776                                 fwip->last_hdr.mode.wreqb.dest_lo =
  777                                         ntohl(destfw->sender_unicast_FIFO_lo);
  778                                 fwip->last_hdr.mode.wreqb.extcode = 0;
  779                                 fwip->last_dest = eui;
  780                         }
  781 
  782                         fp->mode.wreqb = fwip->last_hdr.mode.wreqb;
  783                         fp->mode.wreqb.len = m->m_pkthdr.len;
  784                         xfer->send.spd = min(destfw->sspd, fc->speed);
  785                 }
  786 
  787                 xfer->send.pay_len = m->m_pkthdr.len;
  788 
  789                 error = fw_asyreq(fc, -1, xfer);
  790                 if (error == EAGAIN) {
  791                         /*
  792                          * We ran out of tlabels - requeue the packet
  793                          * for later transmission.
  794                          */
  795                         xfer->mbuf = 0;
  796                         STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
  797                         IF_PREPEND(&ifp->if_snd, m);
  798                         break;
  799                 }
  800                 if (error) {
  801                         /* error */
  802                         ifp->if_oerrors ++;
  803                         /* XXX set error code */
  804                         fwip_output_callback(xfer);
  805                         continue;
  806                 } else {
  807                         ifp->if_opackets ++;
  808                         i++;
  809                 }
  810         }
  811 #if 0
  812         if (i > 1)
  813                 printf("%d queued\n", i);
  814 #endif
  815         if (i > 0) {
  816 #if 1
  817                 xferq->start(fc);
  818 #else
  819                 taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send);
  820 #endif
  821         }
  822 }
  823 
  824 #if defined(__FreeBSD__)
  825 static void
  826 fwip_start_send (void *arg, int count)
  827 {
  828         struct fwip_softc *fwip = arg;
  829 
  830         GIANT_REQUIRED;
  831         fwip->fd.fc->atq->start(fwip->fd.fc);
  832 }
  833 #endif
  834 
  835 /* Async. stream output */
  836 static void
  837 fwip_stream_input(struct fw_xferq *xferq)
  838 {
  839         struct mbuf *m, *m0;
  840         struct m_tag *mtag;
  841         struct ifnet *ifp;
  842         struct fwip_softc *fwip;
  843         struct fw_bulkxfer *sxfer;
  844         struct fw_pkt *fp;
  845         uint16_t src;
  846         uint32_t *p;
  847 
  848         GIANT_REQUIRED;
  849 
  850         fwip = (struct fwip_softc *)xferq->sc;
  851         ifp = &fwip->fwip_if;
  852 #if 0
  853         FWIP_POLL_REGISTER(fwip_poll, fwip, ifp);
  854 #endif
  855         while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
  856                 STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
  857                 fp = mtod(sxfer->mbuf, struct fw_pkt *);
  858                 if (fwip->fd.fc->irx_post != NULL)
  859                         fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld);
  860                 m = sxfer->mbuf;
  861 
  862                 /* insert new rbuf */
  863                 sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
  864                 if (m0 != NULL) {
  865                         m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size;
  866                         STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link);
  867                 } else
  868                         printf("fwip_as_input: m_getcl failed\n");
  869 
  870                 /*
  871                  * We must have a GASP header - leave the
  872                  * encapsulation sanity checks to the generic
  873                  * code. Remeber that we also have the firewire async
  874                  * stream header even though that isn't accounted for
  875                  * in mode.stream.len.
  876                  */
  877                 if (sxfer->resp != 0 || fp->mode.stream.len <
  878                     2*sizeof(uint32_t)) {
  879                         m_freem(m);
  880                         ifp->if_ierrors ++;
  881                         continue;
  882                 }
  883                 m->m_len = m->m_pkthdr.len = fp->mode.stream.len
  884                         + sizeof(fp->mode.stream);
  885 
  886                 /*
  887                  * If we received the packet on the broadcast channel,
  888                  * mark it as broadcast, otherwise we assume it must
  889                  * be multicast.
  890                  */
  891                 if (fp->mode.stream.chtag == broadcast_channel)
  892                         m->m_flags |= M_BCAST;
  893                 else
  894                         m->m_flags |= M_MCAST;
  895 
  896                 /*
  897                  * Make sure we recognise the GASP specifier and
  898                  * version.
  899                  */
  900                 p = mtod(m, uint32_t *);
  901                 if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e
  902                     || (ntohl(p[2]) & 0xffffff) != 1) {
  903                         FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n",
  904                             ntohl(p[1]), ntohl(p[2]));
  905                         m_freem(m);
  906                         ifp->if_ierrors ++;
  907                         continue;
  908                 }
  909 
  910                 /*
  911                  * Record the sender ID for possible BPF usage.
  912                  */
  913                 src = ntohl(p[1]) >> 16;
  914                 if (ifp->if_bpf) {
  915                         mtag = m_tag_alloc(MTAG_FIREWIRE,
  916                             MTAG_FIREWIRE_SENDER_EUID,
  917                             2*sizeof(uint32_t), M_NOWAIT);
  918                         if (mtag) {
  919                                 /* bpf wants it in network byte order */
  920                                 struct fw_device *fd;
  921                                 uint32_t *p2 = (uint32_t *) (mtag + 1);
  922                                 fd = fw_noderesolve_nodeid(fwip->fd.fc,
  923                                     src & 0x3f);
  924                                 if (fd) {
  925                                         p2[0] = htonl(fd->eui.hi);
  926                                         p2[1] = htonl(fd->eui.lo);
  927                                 } else {
  928                                         p2[0] = 0;
  929                                         p2[1] = 0;
  930                                 }
  931                                 m_tag_prepend(m, mtag);
  932                         }
  933                 }
  934 
  935                 /*
  936                  * Trim off the GASP header
  937                  */
  938                 m_adj(m, 3*sizeof(uint32_t));
  939                 m->m_pkthdr.rcvif = ifp;
  940                 FIREWIRE_INPUT(ifp, m, src);
  941                 ifp->if_ipackets ++;
  942         }
  943         if (STAILQ_FIRST(&xferq->stfree) != NULL)
  944                 fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch);
  945 }
  946 
  947 static inline void
  948 fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer)
  949 {
  950         struct mbuf *m;
  951 
  952         GIANT_REQUIRED;
  953 
  954         /*
  955          * We have finished with a unicast xfer. Allocate a new
  956          * cluster and stick it on the back of the input queue.
  957          */
  958         m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
  959         if (m == NULL)
  960                 printf("fwip_unicast_input_recycle: m_getcl failed\n");
  961         xfer->mbuf = m;
  962         xfer->recv.payload = mtod(m, uint32_t *);
  963         xfer->recv.pay_len = MCLBYTES;
  964         xfer->mbuf = m;
  965         STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link);
  966 }
  967 
  968 static void
  969 fwip_unicast_input(struct fw_xfer *xfer)
  970 {
  971         uint64_t address;
  972         struct mbuf *m;
  973         struct m_tag *mtag;
  974         struct ifnet *ifp;
  975         struct fwip_softc *fwip;
  976         struct fw_pkt *fp;
  977         //struct fw_pkt *sfp;
  978         int rtcode;
  979 
  980         GIANT_REQUIRED;
  981 
  982         fwip = (struct fwip_softc *)xfer->sc;
  983         ifp = &fwip->fwip_if;
  984         m = xfer->mbuf;
  985         xfer->mbuf = 0;
  986         fp = &xfer->recv.hdr;
  987 
  988         /*
  989          * Check the fifo address - we only accept addresses of
  990          * exactly INET_FIFO.
  991          */
  992         address = ((uint64_t)fp->mode.wreqb.dest_hi << 32)
  993                 | fp->mode.wreqb.dest_lo;
  994         if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
  995                 rtcode = FWRCODE_ER_TYPE;
  996         } else if (address != INET_FIFO) {
  997                 rtcode = FWRCODE_ER_ADDR;
  998         } else {
  999                 rtcode = FWRCODE_COMPLETE;
 1000         }
 1001 
 1002         /*
 1003          * Pick up a new mbuf and stick it on the back of the receive
 1004          * queue.
 1005          */
 1006         fwip_unicast_input_recycle(fwip, xfer);
 1007 
 1008         /*
 1009          * If we've already rejected the packet, give up now.
 1010          */
 1011         if (rtcode != FWRCODE_COMPLETE) {
 1012                 m_freem(m);
 1013                 ifp->if_ierrors ++;
 1014                 return;
 1015         }
 1016 
 1017         if (ifp->if_bpf) {
 1018                 /*
 1019                  * Record the sender ID for possible BPF usage.
 1020                  */
 1021                 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID,
 1022                     2*sizeof(uint32_t), M_NOWAIT);
 1023                 if (mtag) {
 1024                         /* bpf wants it in network byte order */
 1025                         struct fw_device *fd;
 1026                         uint32_t *p = (uint32_t *) (mtag + 1);
 1027                         fd = fw_noderesolve_nodeid(fwip->fd.fc,
 1028                             fp->mode.wreqb.src & 0x3f);
 1029                         if (fd) {
 1030                                 p[0] = htonl(fd->eui.hi);
 1031                                 p[1] = htonl(fd->eui.lo);
 1032                         } else {
 1033                                 p[0] = 0;
 1034                                 p[1] = 0;
 1035                         }
 1036                         m_tag_prepend(m, mtag);
 1037                 }
 1038         }
 1039 
 1040         /*
 1041          * Hand off to the generic encapsulation code. We don't use
 1042          * ifp->if_input so that we can pass the source nodeid as an
 1043          * argument to facilitate link-level fragment reassembly.
 1044          */
 1045         m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len;
 1046         m->m_pkthdr.rcvif = ifp;
 1047         FIREWIRE_INPUT(ifp, m, fp->mode.wreqb.src);
 1048         ifp->if_ipackets ++;
 1049 }
 1050 
 1051 #if defined(__FreeBSD__)
 1052 static devclass_t fwip_devclass;
 1053 
 1054 static device_method_t fwip_methods[] = {
 1055         /* device interface */
 1056         DEVMETHOD(device_identify,      fwip_identify),
 1057         DEVMETHOD(device_probe,         fwip_probe),
 1058         DEVMETHOD(device_attach,        fwip_attach),
 1059         DEVMETHOD(device_detach,        fwip_detach),
 1060         { 0, 0 }
 1061 };
 1062 
 1063 static driver_t fwip_driver = {
 1064         "fwip",
 1065         fwip_methods,
 1066         sizeof(struct fwip_softc),
 1067 };
 1068 
 1069 
 1070 #ifdef __DragonFly__
 1071 DECLARE_DUMMY_MODULE(fwip);
 1072 #endif
 1073 DRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0);
 1074 MODULE_VERSION(fwip, 1);
 1075 MODULE_DEPEND(fwip, firewire, 1, 1, 1);
 1076 #elif defined(__NetBSD__)
 1077 CFATTACH_DECL(fwip, sizeof (struct fwip_softc),
 1078     fwipmatch, fwipattach, fwipdetach, NULL);
 1079 #endif

Cache object: 70492aaa22e0d8a9569ba0f65bc24303


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