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

Cache object: 15cf5d8b68ea45185e024b7340974bdd


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