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_fwe.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  * SPDX-License-Identifier: BSD-4-Clause
    3  *
    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/module.h>
   53 #include <sys/bus.h>
   54 #include <machine/bus.h>
   55 
   56 #include <net/bpf.h>
   57 #include <net/ethernet.h>
   58 #include <net/if.h>
   59 #include <net/if_var.h>
   60 #include <net/if_arp.h>
   61 #include <net/if_types.h>
   62 #include <net/if_vlan_var.h>
   63 
   64 #include <dev/firewire/firewire.h>
   65 #include <dev/firewire/firewirereg.h>
   66 #include <dev/firewire/if_fwevar.h>
   67 
   68 #define FWEDEBUG        if (fwedebug) if_printf
   69 #define TX_MAX_QUEUE    (FWMAXQUEUE - 1)
   70 
   71 /* network interface */
   72 static void fwe_start (struct ifnet *);
   73 static int fwe_ioctl (struct ifnet *, u_long, caddr_t);
   74 static void fwe_init (void *);
   75 
   76 static void fwe_output_callback (struct fw_xfer *);
   77 static void fwe_as_output (struct fwe_softc *, struct ifnet *);
   78 static void fwe_as_input (struct fw_xferq *);
   79 
   80 static int fwedebug = 0;
   81 static int stream_ch = 1;
   82 static int tx_speed = 2;
   83 static int rx_queue_len = FWMAXQUEUE;
   84 
   85 static MALLOC_DEFINE(M_FWE, "if_fwe", "Ethernet over FireWire interface");
   86 SYSCTL_INT(_debug, OID_AUTO, if_fwe_debug, CTLFLAG_RWTUN, &fwedebug, 0, "");
   87 SYSCTL_DECL(_hw_firewire);
   88 static SYSCTL_NODE(_hw_firewire, OID_AUTO, fwe, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
   89     "Ethernet emulation subsystem");
   90 SYSCTL_INT(_hw_firewire_fwe, OID_AUTO, stream_ch, CTLFLAG_RWTUN, &stream_ch, 0,
   91         "Stream channel to use");
   92 SYSCTL_INT(_hw_firewire_fwe, OID_AUTO, tx_speed, CTLFLAG_RWTUN, &tx_speed, 0,
   93         "Transmission speed");
   94 SYSCTL_INT(_hw_firewire_fwe, OID_AUTO, rx_queue_len, CTLFLAG_RWTUN, &rx_queue_len,
   95         0, "Length of the receive queue");
   96 
   97 #ifdef DEVICE_POLLING
   98 static poll_handler_t fwe_poll;
   99 
  100 static int
  101 fwe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
  102 {
  103         struct fwe_softc *fwe;
  104         struct firewire_comm *fc;
  105 
  106         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
  107                 return (0);
  108 
  109         fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
  110         fc = fwe->fd.fc;
  111         fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count);
  112         return (0);
  113 }
  114 #endif /* DEVICE_POLLING */
  115 
  116 static void
  117 fwe_identify(driver_t *driver, device_t parent)
  118 {
  119         BUS_ADD_CHILD(parent, 0, "fwe", device_get_unit(parent));
  120 }
  121 
  122 static int
  123 fwe_probe(device_t dev)
  124 {
  125         device_t pa;
  126 
  127         pa = device_get_parent(dev);
  128         if (device_get_unit(dev) != device_get_unit(pa)) {
  129                 return (ENXIO);
  130         }
  131 
  132         device_set_desc(dev, "Ethernet over FireWire");
  133         return (0);
  134 }
  135 
  136 static int
  137 fwe_attach(device_t dev)
  138 {
  139         struct fwe_softc *fwe;
  140         struct ifnet *ifp;
  141         int unit, s;
  142         u_char eaddr[6];
  143         struct fw_eui64 *eui;
  144 
  145         fwe = ((struct fwe_softc *)device_get_softc(dev));
  146         unit = device_get_unit(dev);
  147 
  148         bzero(fwe, sizeof(struct fwe_softc));
  149         mtx_init(&fwe->mtx, "fwe", NULL, MTX_DEF);
  150         /* XXX */
  151         fwe->stream_ch = stream_ch;
  152         fwe->dma_ch = -1;
  153 
  154         fwe->fd.fc = device_get_ivars(dev);
  155         if (tx_speed < 0)
  156                 tx_speed = fwe->fd.fc->speed;
  157 
  158         fwe->fd.dev = dev;
  159         fwe->fd.post_explore = NULL;
  160         fwe->eth_softc.fwe = fwe;
  161 
  162         fwe->pkt_hdr.mode.stream.tcode = FWTCODE_STREAM;
  163         fwe->pkt_hdr.mode.stream.sy = 0;
  164         fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;
  165 
  166         /* generate fake MAC address: first and last 3bytes from eui64 */
  167 #define LOCAL (0x02)
  168 #define GROUP (0x01)
  169 
  170         eui = &fwe->fd.fc->eui;
  171         eaddr[0] = (FW_EUI64_BYTE(eui, 0) | LOCAL) & ~GROUP;
  172         eaddr[1] = FW_EUI64_BYTE(eui, 1);
  173         eaddr[2] = FW_EUI64_BYTE(eui, 2);
  174         eaddr[3] = FW_EUI64_BYTE(eui, 5);
  175         eaddr[4] = FW_EUI64_BYTE(eui, 6);
  176         eaddr[5] = FW_EUI64_BYTE(eui, 7);
  177         printf("if_fwe%d: Fake Ethernet address: "
  178                 "%02x:%02x:%02x:%02x:%02x:%02x\n", unit,
  179                 eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
  180 
  181         /* fill the rest and attach interface */
  182         ifp = fwe->eth_softc.ifp = if_alloc(IFT_ETHER);
  183         if (ifp == NULL) {
  184                 device_printf(dev, "can not if_alloc()\n");
  185                 return (ENOSPC);
  186         }
  187         ifp->if_softc = &fwe->eth_softc;
  188 
  189         if_initname(ifp, device_get_name(dev), unit);
  190         ifp->if_init = fwe_init;
  191         ifp->if_start = fwe_start;
  192         ifp->if_ioctl = fwe_ioctl;
  193         ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
  194         ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
  195 
  196         s = splimp();
  197         ether_ifattach(ifp, eaddr);
  198         splx(s);
  199 
  200         /* Tell the upper layer(s) we support long frames. */
  201         ifp->if_hdrlen = sizeof(struct ether_vlan_header);
  202         ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_POLLING;
  203         ifp->if_capenable |= IFCAP_VLAN_MTU;
  204 
  205         FWEDEBUG(ifp, "interface created\n");
  206         return 0;
  207 }
  208 
  209 static void
  210 fwe_stop(struct fwe_softc *fwe)
  211 {
  212         struct firewire_comm *fc;
  213         struct fw_xferq *xferq;
  214         struct ifnet *ifp = fwe->eth_softc.ifp;
  215         struct fw_xfer *xfer, *next;
  216         int i;
  217 
  218         fc = fwe->fd.fc;
  219 
  220         if (fwe->dma_ch >= 0) {
  221                 xferq = fc->ir[fwe->dma_ch];
  222 
  223                 if (xferq->flag & FWXFERQ_RUNNING)
  224                         fc->irx_disable(fc, fwe->dma_ch);
  225                 xferq->flag &=
  226                         ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM |
  227                         FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK);
  228                 xferq->hand =  NULL;
  229 
  230                 for (i = 0; i < xferq->bnchunk; i++)
  231                         m_freem(xferq->bulkxfer[i].mbuf);
  232                 free(xferq->bulkxfer, M_FWE);
  233 
  234                 for (xfer = STAILQ_FIRST(&fwe->xferlist); xfer != NULL;
  235                                         xfer = next) {
  236                         next = STAILQ_NEXT(xfer, link);
  237                         fw_xfer_free(xfer);
  238                 }
  239                 STAILQ_INIT(&fwe->xferlist);
  240 
  241                 xferq->bulkxfer =  NULL;
  242                 fwe->dma_ch = -1;
  243         }
  244 
  245         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
  246 }
  247 
  248 static int
  249 fwe_detach(device_t dev)
  250 {
  251         struct fwe_softc *fwe;
  252         struct ifnet *ifp;
  253         int s;
  254 
  255         fwe = device_get_softc(dev);
  256         ifp = fwe->eth_softc.ifp;
  257 
  258 #ifdef DEVICE_POLLING
  259         if (ifp->if_capenable & IFCAP_POLLING)
  260                 ether_poll_deregister(ifp);
  261 #endif
  262         s = splimp();
  263 
  264         fwe_stop(fwe);
  265         ether_ifdetach(ifp);
  266         if_free(ifp);
  267 
  268         splx(s);
  269         mtx_destroy(&fwe->mtx);
  270         return 0;
  271 }
  272 
  273 static void
  274 fwe_init(void *arg)
  275 {
  276         struct fwe_softc *fwe = ((struct fwe_eth_softc *)arg)->fwe;
  277         struct firewire_comm *fc;
  278         struct ifnet *ifp = fwe->eth_softc.ifp;
  279         struct fw_xferq *xferq;
  280         struct fw_xfer *xfer;
  281         struct mbuf *m;
  282         int i;
  283 
  284         FWEDEBUG(ifp, "initializing\n");
  285 
  286         /* XXX keep promiscoud mode */
  287         ifp->if_flags |= IFF_PROMISC;
  288 
  289         fc = fwe->fd.fc;
  290         if (fwe->dma_ch < 0) {
  291                 fwe->dma_ch = fw_open_isodma(fc, /* tx */0);
  292                 if (fwe->dma_ch < 0)
  293                         return;
  294                 xferq = fc->ir[fwe->dma_ch];
  295                 xferq->flag |= FWXFERQ_EXTBUF |
  296                                 FWXFERQ_HANDLER | FWXFERQ_STREAM;
  297                 fwe->stream_ch = stream_ch;
  298                 fwe->pkt_hdr.mode.stream.chtag = fwe->stream_ch;
  299                 xferq->flag &= ~0xff;
  300                 xferq->flag |= fwe->stream_ch & 0xff;
  301                 /* register fwe_input handler */
  302                 xferq->sc = (caddr_t) fwe;
  303                 xferq->hand = fwe_as_input;
  304                 xferq->bnchunk = rx_queue_len;
  305                 xferq->bnpacket = 1;
  306                 xferq->psize = MCLBYTES;
  307                 xferq->queued = 0;
  308                 xferq->buf = NULL;
  309                 xferq->bulkxfer = (struct fw_bulkxfer *) malloc(
  310                         sizeof(struct fw_bulkxfer) * xferq->bnchunk,
  311                                                         M_FWE, M_WAITOK);
  312                 STAILQ_INIT(&xferq->stvalid);
  313                 STAILQ_INIT(&xferq->stfree);
  314                 STAILQ_INIT(&xferq->stdma);
  315                 xferq->stproc = NULL;
  316                 for (i = 0; i < xferq->bnchunk; i++) {
  317                         m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
  318                         xferq->bulkxfer[i].mbuf = m;
  319                         m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
  320                         STAILQ_INSERT_TAIL(&xferq->stfree,
  321                                         &xferq->bulkxfer[i], link);
  322                 }
  323                 STAILQ_INIT(&fwe->xferlist);
  324                 for (i = 0; i < TX_MAX_QUEUE; i++) {
  325                         xfer = fw_xfer_alloc(M_FWE);
  326                         if (xfer == NULL)
  327                                 break;
  328                         xfer->send.spd = tx_speed;
  329                         xfer->fc = fwe->fd.fc;
  330                         xfer->sc = (caddr_t)fwe;
  331                         xfer->hand = fwe_output_callback;
  332                         STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
  333                 }
  334         } else
  335                 xferq = fc->ir[fwe->dma_ch];
  336 
  337 
  338         /* start dma */
  339         if ((xferq->flag & FWXFERQ_RUNNING) == 0)
  340                 fc->irx_enable(fc, fwe->dma_ch);
  341 
  342         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  343         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  344 
  345 #if 0
  346         /* attempt to start output */
  347         fwe_start(ifp);
  348 #endif
  349 }
  350 
  351 
  352 static int
  353 fwe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  354 {
  355         struct fwe_softc *fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
  356         struct ifstat *ifs = NULL;
  357         int s, error;
  358 
  359         switch (cmd) {
  360                 case SIOCSIFFLAGS:
  361                         s = splimp();
  362                         if (ifp->if_flags & IFF_UP) {
  363                                 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
  364                                         fwe_init(&fwe->eth_softc);
  365                         } else {
  366                                 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
  367                                         fwe_stop(fwe);
  368                         }
  369                         /* XXX keep promiscoud mode */
  370                         ifp->if_flags |= IFF_PROMISC;
  371                         splx(s);
  372                         break;
  373                 case SIOCADDMULTI:
  374                 case SIOCDELMULTI:
  375                         break;
  376 
  377                 case SIOCGIFSTATUS:
  378                         s = splimp();
  379                         ifs = (struct ifstat *)data;
  380                         snprintf(ifs->ascii, sizeof(ifs->ascii),
  381                             "\tch %d dma %d\n", fwe->stream_ch, fwe->dma_ch);
  382                         splx(s);
  383                         break;
  384                 case SIOCSIFCAP:
  385 #ifdef DEVICE_POLLING
  386                     {
  387                         struct ifreq *ifr = (struct ifreq *) data;
  388                         struct firewire_comm *fc = fwe->fd.fc;
  389 
  390                         if (ifr->ifr_reqcap & IFCAP_POLLING &&
  391                             !(ifp->if_capenable & IFCAP_POLLING)) {
  392                                 error = ether_poll_register(fwe_poll, ifp);
  393                                 if (error)
  394                                         return (error);
  395                                 /* Disable interrupts */
  396                                 fc->set_intr(fc, 0);
  397                                 ifp->if_capenable |= IFCAP_POLLING;
  398                                 return (error);
  399                         }
  400                         if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
  401                             ifp->if_capenable & IFCAP_POLLING) {
  402                                 error = ether_poll_deregister(ifp);
  403                                 /* Enable interrupts. */
  404                                 fc->set_intr(fc, 1);
  405                                 ifp->if_capenable &= ~IFCAP_POLLING;
  406                                 return (error);
  407                         }
  408                     }
  409 #endif /* DEVICE_POLLING */
  410                         break;
  411                 default:
  412                         s = splimp();
  413                         error = ether_ioctl(ifp, cmd, data);
  414                         splx(s);
  415                         return (error);
  416         }
  417 
  418         return (0);
  419 }
  420 
  421 static void
  422 fwe_output_callback(struct fw_xfer *xfer)
  423 {
  424         struct fwe_softc *fwe;
  425         struct ifnet *ifp;
  426         int s;
  427 
  428         fwe = (struct fwe_softc *)xfer->sc;
  429         ifp = fwe->eth_softc.ifp;
  430         /* XXX error check */
  431         FWEDEBUG(ifp, "resp = %d\n", xfer->resp);
  432         if (xfer->resp != 0)
  433                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  434         m_freem(xfer->mbuf);
  435         fw_xfer_unload(xfer);
  436 
  437         s = splimp();
  438         FWE_LOCK(fwe);
  439         STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
  440         FWE_UNLOCK(fwe);
  441         splx(s);
  442 
  443         /* for queue full */
  444         if (ifp->if_snd.ifq_head != NULL)
  445                 fwe_start(ifp);
  446 }
  447 
  448 static void
  449 fwe_start(struct ifnet *ifp)
  450 {
  451         struct fwe_softc *fwe = ((struct fwe_eth_softc *)ifp->if_softc)->fwe;
  452         int s;
  453 
  454         FWEDEBUG(ifp, "starting\n");
  455 
  456         if (fwe->dma_ch < 0) {
  457                 struct mbuf     *m = NULL;
  458 
  459                 FWEDEBUG(ifp, "not ready\n");
  460 
  461                 s = splimp();
  462                 do {
  463                         IF_DEQUEUE(&ifp->if_snd, m);
  464                         if (m != NULL)
  465                                 m_freem(m);
  466                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  467                 } while (m != NULL);
  468                 splx(s);
  469 
  470                 return;
  471         }
  472 
  473         s = splimp();
  474         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  475 
  476         if (ifp->if_snd.ifq_len != 0)
  477                 fwe_as_output(fwe, ifp);
  478 
  479         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  480         splx(s);
  481 }
  482 
  483 #define HDR_LEN 4
  484 #ifndef ETHER_ALIGN
  485 #define ETHER_ALIGN 2
  486 #endif
  487 /* Async. stream output */
  488 static void
  489 fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp)
  490 {
  491         struct mbuf *m;
  492         struct fw_xfer *xfer;
  493         struct fw_xferq *xferq;
  494         struct fw_pkt *fp;
  495         int i = 0;
  496 
  497         xfer = NULL;
  498         xferq = fwe->fd.fc->atq;
  499         while ((xferq->queued < xferq->maxq - 1) &&
  500                         (ifp->if_snd.ifq_head != NULL)) {
  501                 FWE_LOCK(fwe);
  502                 xfer = STAILQ_FIRST(&fwe->xferlist);
  503                 if (xfer == NULL) {
  504 #if 0
  505                         printf("if_fwe: lack of xfer\n");
  506 #endif
  507                         FWE_UNLOCK(fwe);
  508                         break;
  509                 }
  510                 STAILQ_REMOVE_HEAD(&fwe->xferlist, link);
  511                 FWE_UNLOCK(fwe);
  512 
  513                 IF_DEQUEUE(&ifp->if_snd, m);
  514                 if (m == NULL) {
  515                         FWE_LOCK(fwe);
  516                         STAILQ_INSERT_HEAD(&fwe->xferlist, xfer, link);
  517                         FWE_UNLOCK(fwe);
  518                         break;
  519                 }
  520                 BPF_MTAP(ifp, m);
  521 
  522                 /* keep ip packet alignment for alpha */
  523                 M_PREPEND(m, ETHER_ALIGN, M_NOWAIT);
  524                 fp = &xfer->send.hdr;
  525                 *(uint32_t *)&xfer->send.hdr = *(int32_t *)&fwe->pkt_hdr;
  526                 fp->mode.stream.len = m->m_pkthdr.len;
  527                 xfer->mbuf = m;
  528                 xfer->send.pay_len = m->m_pkthdr.len;
  529 
  530                 if (fw_asyreq(fwe->fd.fc, -1, xfer) != 0) {
  531                         /* error */
  532                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  533                         /* XXX set error code */
  534                         fwe_output_callback(xfer);
  535                 } else {
  536                         if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
  537                         i++;
  538                 }
  539         }
  540 #if 0
  541         if (i > 1)
  542                 printf("%d queued\n", i);
  543 #endif
  544         if (i > 0)
  545                 xferq->start(fwe->fd.fc);
  546 }
  547 
  548 /* Async. stream output */
  549 static void
  550 fwe_as_input(struct fw_xferq *xferq)
  551 {
  552         struct mbuf *m, *m0;
  553         struct ifnet *ifp;
  554         struct fwe_softc *fwe;
  555         struct fw_bulkxfer *sxfer;
  556         struct fw_pkt *fp;
  557 #if 0
  558         u_char *c;
  559 #endif
  560 
  561         fwe = (struct fwe_softc *)xferq->sc;
  562         ifp = fwe->eth_softc.ifp;
  563 
  564         /* We do not need a lock here because the bottom half is serialized */
  565         while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) {
  566                 STAILQ_REMOVE_HEAD(&xferq->stvalid, link);
  567                 fp = mtod(sxfer->mbuf, struct fw_pkt *);
  568                 if (fwe->fd.fc->irx_post != NULL)
  569                         fwe->fd.fc->irx_post(fwe->fd.fc, fp->mode.ld);
  570                 m = sxfer->mbuf;
  571 
  572                 /* insert new rbuf */
  573                 sxfer->mbuf = m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  574                 if (m0 != NULL) {
  575                         m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size;
  576                         STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link);
  577                 } else
  578                         printf("%s: m_getcl failed\n", __FUNCTION__);
  579 
  580                 if (sxfer->resp != 0 || fp->mode.stream.len <
  581                     ETHER_ALIGN + sizeof(struct ether_header)) {
  582                         m_freem(m);
  583                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  584                         continue;
  585                 }
  586 
  587                 m->m_data += HDR_LEN + ETHER_ALIGN;
  588 #if 0
  589                 c = mtod(m, u_char *);
  590 #endif
  591                 m->m_len = m->m_pkthdr.len = fp->mode.stream.len - ETHER_ALIGN;
  592                 m->m_pkthdr.rcvif = ifp;
  593 #if 0
  594                 FWEDEBUG(ifp, "%02x %02x %02x %02x %02x %02x\n"
  595                          "%02x %02x %02x %02x %02x %02x\n"
  596                          "%02x %02x %02x %02x\n"
  597                          "%02x %02x %02x %02x\n"
  598                          "%02x %02x %02x %02x\n"
  599                          "%02x %02x %02x %02x\n",
  600                          c[0], c[1], c[2], c[3], c[4], c[5],
  601                          c[6], c[7], c[8], c[9], c[10], c[11],
  602                          c[12], c[13], c[14], c[15],
  603                          c[16], c[17], c[18], c[19],
  604                          c[20], c[21], c[22], c[23],
  605                          c[20], c[21], c[22], c[23]
  606                 );
  607 #endif
  608                 (*ifp->if_input)(ifp, m);
  609                 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
  610         }
  611         if (STAILQ_FIRST(&xferq->stfree) != NULL)
  612                 fwe->fd.fc->irx_enable(fwe->fd.fc, fwe->dma_ch);
  613 }
  614 
  615 
  616 static device_method_t fwe_methods[] = {
  617         /* device interface */
  618         DEVMETHOD(device_identify,      fwe_identify),
  619         DEVMETHOD(device_probe,         fwe_probe),
  620         DEVMETHOD(device_attach,        fwe_attach),
  621         DEVMETHOD(device_detach,        fwe_detach),
  622         { 0, 0 }
  623 };
  624 
  625 static driver_t fwe_driver = {
  626         "fwe",
  627         fwe_methods,
  628         sizeof(struct fwe_softc),
  629 };
  630 
  631 
  632 DRIVER_MODULE(fwe, firewire, fwe_driver, 0, 0);
  633 MODULE_VERSION(fwe, 1);
  634 MODULE_DEPEND(fwe, firewire, 1, 1, 1);

Cache object: 14079fab3688dc962b330c60492cdd6c


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