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

Cache object: a8091453252bb81cc88dcbffd46a1d74


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