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/fwiso.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: fwiso.c,v 1.5 2005/02/27 00:27:17 perry Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2001 and 2002
    5  *      HAYAKAWA Koichi.  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. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __KERNEL_RCSID(0, "$NetBSD: fwiso.c,v 1.5 2005/02/27 00:27:17 perry Exp $");
   33 
   34 #include "fwiso.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/conf.h>
   40 #include <sys/ioctl.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/uio.h>
   43 #include <sys/device.h>
   44 #include <sys/errno.h>
   45 #include <sys/signalvar.h>
   46 #include <sys/vnode.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/poll.h>
   49 #include <sys/select.h>
   50 
   51 #include <dev/ieee1394/fwiso_ioctl.h>
   52 #include <dev/ieee1394/ieee1394reg.h>
   53 #include <dev/ieee1394/ieee1394var.h>
   54 #include <dev/ieee1394/fwisovar.h>
   55 
   56 #ifdef DEBUG
   57 #define DPRINTF(x) printf x
   58 #else
   59 #define DPRINTF(x)
   60 #endif
   61 
   62 #define UNIT(dev) minor(dev)&0xff
   63 #define IOCTL(dev) minor(dev)&0x0100
   64 #define DVDEV(dev) minor(dev)&0x0200
   65 #define MPEG2DEV(dev) minor(dev)&0x0300
   66 
   67 /*
   68  * device number rule
   69  *
   70  *      Lower 8-bit of minor number represents fwiso pseudo device.
   71  *      Higher bits represents types of the device.
   72  *
   73  *      0x0000:     raw fwiso device
   74  *      0x0100:     for ioctl (can't read/write)
   75  *      0x0200:     standard DV type
   76  *      0x0300:     MPEG2 TS
   77  */
   78 
   79 
   80 /*
   81  * The movement of data.
   82  *
   83  *      Isochronous data acquired by device is copied in reservoir
   84  *      buffer by fwisohandler.  fwisohandler is a callback function,
   85  *      called in the device drover of an IEEE 1394 host device.  The
   86  *      copied data in reservoir is deriverd to userland by fwisoread.
   87  *      So, at least data copy will happen twice.
   88  */
   89 
   90 
   91 struct fwiso_pktdata {
   92         u_int8_t *pkt_base;     /* Base address: NEVER change */
   93         size_t pkt_len;         /* Length of the data in the buffer */
   94         size_t pkt_buflen;      /* Length of the buffer: NEVER change */
   95 };
   96 
   97 struct fwiso_pkts {
   98         struct fwiso_pktdata *fp_iov;   /* packet data vector: NEVER change */
   99         struct fwiso_pktdata *fp_iov_last; /* end packet data vector: NEVER change  */
  100         /*
  101          * Set members below volatile because they will be changed by
  102          * both intr handler and read routine.
  103          */
  104         volatile struct fwiso_pktdata *fp_iov_start;    /* pkt data vector */
  105         struct fwiso_pktdata *fp_iov_end;               /* pkt data vector */
  106         volatile int fp_iovcnt;                         /* vector length */
  107 };
  108 
  109 #define FWISO_DEVNAMESIZ 12
  110 struct fwiso_data {
  111         char fd_devname[FWISO_DEVNAMESIZ];
  112         struct ieee1394_softc *fd_dev;
  113 
  114         int fd_status;          /* status: share with interrupt hendler */
  115         int fd_overflow;
  116 
  117         struct uio *fd_uio;     /* for interrupt handler */
  118 
  119         struct fwiso_pkts fd_rsv_pkts; /* temporary buffer for packets */
  120         u_int8_t *fd_rsv_buf;
  121         int fd_rsv_size;
  122 
  123         /*
  124          * Should those data (fd_mode, fd_channel, fd_tag) be dedicatd
  125          * for read and write, or be shared with read and write?
  126          */
  127         int fd_mode;
  128         int fd_channel;         /* ISO channel (0 - 63) */
  129         int fd_tag;             /* IEEE1394_ISO_TAG0, _TAG1, _TAG2 */
  130         int fd_threshold;
  131 
  132         u_int32_t fd_cycletimer;
  133 
  134         ieee1394_ir_tag_t fd_irtag; /* tag for isochronous reception */
  135 
  136         ieee1394_it_tag_t fd_ittag; /* tag for isochronous transmission */
  137         struct ieee1394_it_datalist *fd_itlist;
  138         int fd_it_serial;       /* serial number of data block (not packet) */
  139         int fd_it_frame;        /* frame number */
  140         int fd_it_dv_insert_empty;
  141         int fd_it_dv_insert_fraction;
  142         int fd_it_dv_insert_fractional;
  143 
  144         int fd_flags;
  145 #define FWISO_OPEN              0x01
  146 #define FWISO_SETHANDLER        0x02
  147 #define FWISO_IR_SLEEPING       0x04
  148 #define FWISO_WRITE             0x08
  149 #define FWISO_NONBLOCK          0x10
  150 
  151         size_t fd_uioprev;      /* previous uio value: XXX really needed? */
  152 };
  153 
  154 
  155 struct fwiso_data fwiso_data_str[NFWISO];
  156 
  157 static int fwiso_min_space[FWISO_MODE_MAX] = {1, 480, 488, 1};
  158 static int fwiso_head_offset[FWISO_MODE_MAX] = {0, 8, 0, 0};
  159 #define FWISO_MAX_INTERFACE 10
  160         /* I hope all the elements of fwiso_interface is initialised as NULL */
  161 static struct ieee1394_softc *fwiso_interface[FWISO_MAX_INTERFACE] = {NULL};
  162 
  163 static struct evcnt fwiso_drop_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "fwiso", "dropframe");
  164 static struct evcnt fwiso_frame_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "fwiso", "frame");
  165 
  166 void fwisoattach(int);
  167 
  168 static struct ieee1394_softc *fwiso_lookup_if(const char *);
  169 int fwisowrite_dv(struct fwiso_data *, struct uio *, int);
  170 static int fwiso_set_handler(struct fwiso_data *);
  171 
  172 dev_type_open(fwisoopen);
  173 dev_type_close(fwisoclose);
  174 dev_type_read(fwisoread);
  175 dev_type_write(fwisowrite);
  176 dev_type_ioctl(fwisoioctl);
  177 dev_type_poll(fwisopoll);
  178 
  179 const struct cdevsw fwiso_cdevsw = {
  180         fwisoopen, fwisoclose, fwisoread, fwisowrite, fwisoioctl,
  181         nostop, notty, fwisopoll, nommap,
  182 };
  183 
  184 
  185 /* XXX: only for experimental */
  186 extern int fwohci_set_isotx(struct ieee1394_softc *);
  187 struct fwohci_it_ctx;
  188 extern int fwohci_it_ctx_clear(ieee1394_it_tag_t);
  189 extern u_int16_t fwohci_it_cycletimer(ieee1394_it_tag_t);
  190 extern ieee1394_it_tag_t fwohci_it_set(struct ieee1394_softc *, int, int);
  191 extern int fwohci_it_ctx_writedata(ieee1394_it_tag_t, int,
  192     struct ieee1394_it_datalist *, int);
  193 
  194 
  195 
  196 /* ARGSUSED */
  197 void
  198 fwisoattach(int n)
  199 {
  200         int i;
  201 
  202         memset(fwiso_data_str, 0, sizeof(fwiso_data_str));
  203 
  204         for (i = 0; i < NFWISO; ++i) {
  205                 snprintf(fwiso_data_str[i].fd_devname, 10, "fwiso%d", i);
  206                 fwiso_data_str[i].fd_channel = -1;
  207                 fwiso_data_str[i].fd_mode = -1;
  208                 fwiso_data_str[i].fd_threshold = 0;
  209                 fwiso_data_str[i].fd_tag = 0;
  210                 fwiso_data_str[i].fd_uioprev = 0;
  211         }
  212 
  213         evcnt_attach_static(&fwiso_drop_ev);
  214         evcnt_attach_static(&fwiso_frame_ev);
  215 }
  216 
  217 
  218 
  219 
  220 /*
  221  * int fwisoread(dev_t dev, struct uio *uio, int ioflag)
  222  *
  223  *     Read routine
  224  *
  225  *     Algorithm:
  226  *
  227  *       if interrupt handler is not set
  228  *           register interrupt handler
  229  *           prepare reserve buffer;
  230  *       if some data exists in reserve buffer
  231  *           copy data in uio
  232  *           if uio is full
  233  *               return
  234  *       set uio in interrupt handler
  235  *       sleep until interrupt handler wait me
  236  *       set reserve buffer
  237  *       return
  238  */
  239 int
  240 fwisoread(dev_t dev, struct uio *uio, int ioflag)
  241 {
  242         struct fwiso_data *fd;
  243         int unit;
  244         int status = 0;
  245         int s;
  246 
  247         int minspace;
  248         int headoffs;
  249         volatile struct fwiso_pktdata *pkt;
  250         struct fwiso_pktdata *pkt_last;
  251         struct ieee1394_softc *isc;
  252         size_t resid;
  253 
  254         int i;
  255 
  256         unit = UNIT(dev);
  257 
  258         if (unit >= NFWISO) {
  259                 return ENXIO;
  260         }
  261 
  262         if (IOCTL(dev)) {
  263                 DPRINTF(("fwiso%d cannot read\n", unit));
  264                 return ENXIO;
  265         }
  266 
  267         fd = &fwiso_data_str[unit];
  268 
  269         if ((fd->fd_flags & FWISO_OPEN) == 0) {
  270                 return EBUSY;
  271         }
  272 
  273         isc = fd->fd_dev;
  274 
  275         if ((fd->fd_flags & FWISO_SETHANDLER) == 0) {
  276                 int rv;
  277 
  278                 if ((rv = fwiso_set_handler(fd)) != 0) {
  279                         return rv;
  280                 }
  281         }
  282 
  283         minspace = fwiso_min_space[fd->fd_mode];
  284         headoffs = fwiso_head_offset[fd->fd_mode];
  285 
  286         /* This is constant */
  287         pkt_last = fd->fd_rsv_pkts.fp_iov_last;
  288         /* Only fwiso writes.  Others read only */
  289         pkt = fd->fd_rsv_pkts.fp_iov_start;
  290 
  291         s = splbio();
  292 
  293         i = 0;
  294         resid = uio->uio_resid;
  295         DPRINTF(("%s: now reading\n", isc->sc1394_dev.dv_xname));
  296         while ((status = (*isc->sc1394_ir_read)((struct device *)isc,
  297             fd->fd_irtag, uio, headoffs, 0)) == EAGAIN
  298             || (status == 0 && uio->uio_resid == resid)) {
  299                 if (fd->fd_flags & FWISO_NONBLOCK) {
  300                         break;
  301                 }
  302                 if (isc->sc1394_ir_wait == NULL) {
  303                         if (++i > 20) {
  304                                 status = EIO;
  305                                 break;
  306                         }
  307                         delay(100);
  308                 } else {
  309                         status = (*isc->sc1394_ir_wait)((struct device *)isc,
  310                             fd->fd_irtag, (void *)fd, fd->fd_devname);
  311                         if (status != 0) {
  312                                 break;
  313                         }
  314                 }
  315         }
  316 
  317         splx(s);
  318 
  319         return status;
  320 }
  321 
  322 
  323 
  324 
  325 
  326 /*
  327  * int fwisowrite(dev_t dev, struct uio *uio, int ioflag)
  328  *
  329  *      Write routine
  330  */
  331 int
  332 fwisowrite(dev_t dev, struct uio *uio, int ioflag)
  333 {
  334         struct fwiso_data *fd;
  335         int unit;
  336         int rv = ENODEV;
  337 
  338         unit = UNIT(dev);
  339 
  340         if (unit >= NFWISO) {
  341                 return ENXIO;
  342         }
  343 
  344         if (IOCTL(dev)) {
  345                 DPRINTF(("fwiso%d cannot read\n", unit));
  346                 return ENXIO;
  347         }
  348 
  349         fd = &fwiso_data_str[unit];
  350 
  351         if ((fd->fd_flags & FWISO_OPEN) == 0) {
  352                 return EBUSY;
  353         }
  354 
  355         if (fd->fd_ittag == NULL) {
  356                 /* XXX */
  357                 if (fd->fd_channel < 0) {
  358                         fd->fd_channel = 63;
  359                 }
  360                 if (fd->fd_tag <= 0) {
  361                         fd->fd_tag = IEEE1394_ISO_TAG1;
  362                 }
  363                 fd->fd_ittag = fwohci_it_set(fd->fd_dev, fd->fd_channel,
  364                     fd->fd_tag);
  365                 if (fd->fd_ittag == NULL) {
  366                         return EBUSY;
  367                 }
  368                 fd->fd_flags |= FWISO_WRITE;
  369                 printf("fwiso%d: it_set returns %p\n", unit, fd->fd_ittag);
  370 
  371                 fd->fd_it_dv_insert_fractional = 16000;
  372                 fd->fd_it_dv_insert_fraction = 1015;
  373                 fd->fd_it_dv_insert_empty = 0;
  374 
  375 #define ITLISTSIZE sizeof(struct ieee1394_it_datalist)*100
  376                 if ((fd->fd_itlist = malloc(ITLISTSIZE, M_DEVBUF,
  377                     M_WAITOK|M_ZERO)) == NULL) {
  378                         /*  */
  379                         printf("fwiso%d: cannot get memory for it_list\n",
  380                             unit);
  381                         return EBUSY;
  382                 }
  383 
  384                 /* XXX */
  385                 fd->fd_cycletimer = fwohci_it_cycletimer(fd->fd_ittag);
  386                 printf("cycletimer %x %d %d\n", fd->fd_cycletimer,
  387                     fd->fd_cycletimer >> 13, fd->fd_cycletimer&0x1fff);
  388         }
  389 #if 1
  390         switch(fd->fd_mode) {
  391         case FWISO_MODE_DV:
  392                 rv = fwisowrite_dv(fd, uio, 480);
  393                 break;
  394         case FWISO_MODE_DV_RAW:
  395                 break;
  396         case FWISO_MODE_RAW:
  397                 break;
  398         }
  399 
  400 #endif
  401 
  402         return rv;
  403 }
  404 
  405 
  406 
  407 
  408 int
  409 fwisowrite_dv(struct fwiso_data *fd, struct uio *uio, int size)
  410 {
  411         int rv;
  412         struct ieee1394_it_datalist *itlist;
  413         struct ieee1394_it_datalist *loopend;
  414         struct iovec *iov = uio->uio_iov;
  415         int nodeid;
  416         const struct iovec *iov_end = iov + uio->uio_iovcnt;
  417         int iov_offs;           /* offset in iov */
  418         int ndata;
  419         int writesize = 0;
  420         int res = 0;
  421         int serialno;
  422         int i;
  423         int s;
  424 
  425         DPRINTF(("fwisowrite_dv(%p %p %d), resid %d iovcnt %d\n",
  426             fd, uio, size, uio->uio_resid, uio->uio_iovcnt));
  427 
  428         iov_offs = 0;
  429         itlist = fd->fd_itlist;
  430 
  431         if (uio->uio_resid < size) {
  432                 /* Only get rid of small data */
  433                 uio->uio_offset += uio->uio_resid;
  434                 uio->uio_resid = 0;
  435                 return res;
  436         }
  437 
  438         nodeid = 0;
  439 
  440         s = splbio();
  441 
  442         while (uio->uio_resid >= size) {
  443                 if (uio->uio_resid > 90*size) {
  444                         loopend = fd->fd_itlist + 90;
  445                         DPRINTF(("loop 90\n"));
  446                 } else {
  447                         loopend = fd->fd_itlist + uio->uio_resid/size;
  448                         DPRINTF(("loop %d %p\n", uio->uio_resid/size, loopend));
  449                 }
  450 
  451                 serialno = fd->fd_it_serial;
  452 
  453                 /* make data list */
  454                 for (itlist = fd->fd_itlist; itlist < loopend; ++itlist) {
  455                         int psize = size;
  456 
  457                         /* first data is CIP header */
  458                         itlist->it_cmd[0] = IEEE1394_IT_CMD_IMMED | 8;
  459                         itlist->it_u[0].id_data[0]
  460                             = IEEE1394_CIP_SET(SID, nodeid)
  461                             | IEEE1394_CIP_SET(DBS, size)
  462                             | IEEE1394_CIP_SET(DBC, serialno);
  463                         ++serialno;
  464 
  465                         itlist->it_u[0].id_data[1]
  466                             = IEEE1394_CIP_FMT_DV
  467                             | IEEE1394_CIP_SET(FDF_SYT, 0xffff);
  468 
  469                         for (i = 1; i < IEEE1394_IT_CMD_NUM; ++i) {
  470 
  471                                 if (psize == 0) {
  472                                         itlist->it_cmd[i]
  473                                             = IEEE1394_IT_CMD_NOP;
  474                                         continue;
  475                                 }
  476 
  477                                 itlist->it_u[i].id_addr
  478                                     = (u_int8_t *)iov->iov_base + iov_offs;
  479 
  480                                 if (iov->iov_len - iov_offs >= psize) {
  481                                         itlist->it_cmd[i]
  482                                             = IEEE1394_IT_CMD_PTR | psize;
  483                                         iov_offs += psize;
  484                                         psize = 0;
  485                                 } else {
  486                                         itlist->it_cmd[i]
  487                                             = IEEE1394_IT_CMD_PTR | (iov->iov_len - iov_offs);
  488                                         psize -= iov->iov_len - iov_offs;
  489                                         iov_offs = 0;
  490                                         if (++iov == iov_end) {
  491                                                 printf("ERROR iov %d\n",
  492                                                     iov - uio->uio_iov);
  493                                                 res = EFAULT;
  494                                                 goto error_1;
  495                                         }
  496                                 }
  497                         }
  498                 }
  499                 ndata = itlist - fd->fd_itlist;
  500                 DPRINTF(("calling fwohci_it_ctx_writedata(%p %d %p 0)\n",
  501                     fd->fd_ittag, ndata, fd->fd_itlist));
  502                 rv = fwohci_it_ctx_writedata(fd->fd_ittag, ndata,
  503                     fd->fd_itlist, 0);
  504 
  505                 writesize = rv * size;
  506                 /* XXX: decrement for empty packet */
  507 
  508                 uio->uio_resid -= writesize;
  509                 uio->uio_offset += writesize;
  510                 fd->fd_it_serial += rv;
  511                 itlist += rv;
  512 
  513                 if (rv == 0) {
  514                         if (fd->fd_uioprev == uio->uio_resid) {
  515 #if 0
  516                                 printf("umm, I cannot write any more (%d)\n",
  517                                     fd->fd_it_serial);
  518                                 res = EFAULT;
  519                                 goto error_1;
  520 #endif
  521                         }
  522                 }
  523                 fd->fd_uioprev = uio->uio_resid;
  524 
  525                 if (rv < ndata) {
  526                         /* reach at the end of DMA buffer */
  527                         break;
  528                 }
  529         }
  530 
  531  error_1:
  532 
  533         splx(s);
  534 
  535         return res;
  536 }
  537 
  538 
  539 
  540 int
  541 fwisoopen(dev_t dev, int flags, int fmt, struct proc *p)
  542 {
  543         struct fwiso_data *fd;
  544         int unit = UNIT(dev);
  545 
  546         if (unit >= NFWISO) {
  547                 return ENXIO;
  548         }
  549 
  550         if (IOCTL(dev)) {
  551                 return 0;
  552         }
  553 
  554         fd = &fwiso_data_str[unit];
  555 
  556         if (fd->fd_flags &= FWISO_OPEN) {
  557                 return EBUSY;
  558         }
  559 
  560         fd->fd_flags = FWISO_OPEN;
  561         if (flags & O_NONBLOCK) {
  562                 fd->fd_flags |= FWISO_NONBLOCK;
  563         }
  564 
  565         fd->fd_rsv_size = 0;
  566         fd->fd_uio = NULL;
  567         fd->fd_mode = FWISO_MODE_RAW;
  568 
  569         if (DVDEV(dev)) {
  570                 fd->fd_mode = FWISO_MODE_DV;
  571                 fd->fd_channel = 63;
  572                 fd->fd_tag = IEEE1394_ISO_TAG1;
  573         }
  574 
  575         if (fd->fd_dev == NULL) {
  576                 int i;
  577 
  578                 for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
  579                         if (fwiso_interface[i] != NULL) {
  580                                 fd->fd_dev = fwiso_interface[i];
  581                                 printf("%s: using %s\n", fd->fd_devname,
  582                                     fwiso_interface[i]->sc1394_dev.dv_xname);
  583                                 break;
  584                         }
  585                 }
  586         }
  587 
  588         fd->fd_overflow = 0;
  589 
  590         return 0;
  591 }
  592 
  593 
  594 
  595 
  596 
  597 int
  598 fwisoclose(dev_t dev, int flags, int fmt, struct proc *p)
  599 {
  600         struct fwiso_data *fd;
  601         int unit = UNIT(dev);
  602 
  603         if (unit >= NFWISO) {
  604                 return ENXIO;
  605         }
  606 
  607         fd = &fwiso_data_str[unit];
  608 
  609         fd->fd_flags &= ~FWISO_OPEN;
  610 
  611         /* remove interrupt handler */
  612         if (fd->fd_flags & FWISO_SETHANDLER) {
  613                 int s = splbio();
  614                 /* remove handler */
  615                 (*fd->fd_dev->sc1394_ir_close)((struct device *)fd->fd_dev,
  616                      fd->fd_irtag);
  617 
  618                 fd->fd_flags &= ~FWISO_SETHANDLER;
  619                 splx(s);
  620         }
  621 
  622         /* When this is opened for write, cleanup it_tag */
  623         if (fd->fd_flags & FWISO_WRITE) {
  624                 fwohci_it_ctx_clear(fd->fd_ittag);
  625                 fd->fd_ittag = NULL;
  626         }
  627 
  628         if (fd->fd_overflow > 0) {
  629                 printf("%s: %d frame dropped\n", fd->fd_devname, fd->fd_overflow);
  630         }
  631 
  632         fd->fd_flags = 0;
  633         fd->fd_overflow = 0;
  634         /* keep mode and interface */
  635 
  636         return 0;
  637 }
  638 
  639 
  640 
  641 int
  642 fwisoioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
  643 {
  644         int unit = UNIT(dev);
  645         struct fwiso_data *fd;
  646         int error = 0;
  647 
  648         if (unit >= NFWISO) {
  649                 return ENXIO;
  650         }
  651 
  652         fd = &fwiso_data_str[unit];
  653 
  654         if (!data) {
  655                 return EINVAL;
  656         }
  657 
  658         switch(cmd) {
  659 
  660         case FWISOSETIF:
  661             {
  662                 const struct fwiso_if *fi = (struct fwiso_if *)data;
  663 
  664                 if ((fd->fd_dev = fwiso_lookup_if(fi->fi_name)) == NULL) {
  665                         error = EINVAL;
  666                 }
  667                 break;
  668             }
  669         case FWISOGETIF:
  670             {
  671                 struct fwiso_if *fi = (struct fwiso_if *)data;
  672 
  673                 if (fd->fd_dev != NULL) {
  674                         memcpy(fi->fi_name, fd->fd_dev->sc1394_dev.dv_xname,
  675                             FWISO_IFNAMESIZ);
  676                 } else {
  677                         memcpy(fi->fi_name, "---", 3);
  678                 }
  679                 break;
  680             }
  681         case FWISOSETMODE:
  682             {
  683                 const int mode = *(int *)data;
  684 
  685                 if (mode >= 0 && mode < FWISO_MODE_MAX) {
  686                         fd->fd_mode = mode;
  687                 } else {
  688                         error = EINVAL;
  689                 }
  690                 break;
  691             }
  692         case FWISOGETMODE:
  693                 *((int *)data) = fd->fd_mode;
  694                 break;
  695         case FWISOSETCHANNEL:
  696             {
  697                 const int channel = *(int *)data;
  698 
  699                 if (channel >= 0 && channel < 64) {
  700                         fd->fd_channel = channel;
  701                 } else if (channel == FWISO_CHANNEL_ANY) {
  702                         fd->fd_channel = IEEE1394_ISO_CHANNEL_ANY;
  703                 } else {
  704                         error = EINVAL;
  705                 }
  706                 break;
  707             }
  708         case FWISOGETCHANNEL:
  709                 *((int *)data) = fd->fd_channel;
  710                 break;
  711         case FWISOSETTAG:
  712             {
  713                 const int tag = *(int *)data;
  714 
  715 #define FWISO_TAG_MAX (FWISO_TAG0 | FWISO_TAG1 | FWISO_TAG2 | FWISO_TAG3)
  716 
  717                 if (tag >= FWISO_TAG0 || tag <= FWISO_TAG_MAX) {
  718                         /* valid tag */
  719                         fd->fd_tag = tag;
  720                 } else {
  721                         error = EINVAL;
  722                 }
  723             }
  724         case FWISOGETTAG:
  725                 *((int *)data) = fd->fd_tag;
  726                 break;
  727         default:
  728                 error = EINVAL;
  729                 break;
  730         }
  731 
  732         return error;
  733 }
  734 
  735 
  736 
  737 
  738 int
  739 fwisopoll(dev_t dev, int events, struct proc *p)
  740 {
  741         int unit = UNIT(dev);
  742         struct fwiso_data *fd;
  743         int s;
  744         int revents;
  745         int (*ir_select)(struct device *, ieee1394_ir_tag_t, struct proc *);
  746 
  747         if (unit >= NFWISO) {
  748                 return ENXIO;
  749         }
  750 
  751         fd = &fwiso_data_str[unit];
  752 
  753         if ((ir_select = fd->fd_dev->sc1394_ir_select) == NULL) {
  754                 return events;
  755         }
  756 
  757         s = splbio();
  758         /*
  759          * right now, only select for read is supported.
  760          */
  761         revents = events & (POLLOUT | POLLWRNORM);
  762 
  763         if (events & (POLLIN | POLLRDNORM)) {
  764                 if ((fd->fd_flags & FWISO_SETHANDLER) == 0) {
  765                         int errcode;
  766 
  767                         if ((errcode = fwiso_set_handler(fd)) != 0) {
  768                                 splx(s);
  769                                 return errcode;
  770                         }
  771                 }
  772 
  773                 if ((*ir_select)((struct device *)fd->fd_dev,
  774                         fd->fd_irtag, p) > 0) {
  775                         revents |= events & (POLLIN | POLLRDNORM);
  776                 }
  777 #if 0
  778                 if (fd->fd_rsv_pkts.fp_iovcnt > 0) {
  779                         revents |= events & (POLLIN | POLLRDNORM);
  780                 } else {
  781                         selrecord(p, &fd->fd_sel);
  782                 }
  783 #endif
  784         }
  785 
  786         splx(s);
  787         return revents;
  788 }
  789 
  790 
  791 
  792 int
  793 fwiso_register_if(struct ieee1394_softc *interface)
  794 {
  795         int i;
  796 
  797         for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
  798                 if (fwiso_interface[i] == NULL) {
  799                         fwiso_interface[i] = interface;
  800                         break;
  801                 }
  802         }
  803 
  804         if (i == FWISO_MAX_INTERFACE) {
  805                 printf("fwiso: too many interfaces %s\n",
  806                     interface->sc1394_dev.dv_xname);
  807                 return 1;
  808         }
  809 
  810         return 0;
  811 }
  812 
  813 
  814 
  815 
  816 static struct ieee1394_softc *
  817 fwiso_lookup_if(const char *ifname)
  818 {
  819         int i;
  820 
  821         for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
  822                 if (!strncmp(fwiso_interface[i]->sc1394_dev.dv_xname,
  823                     ifname, FWISO_IFNAMESIZ)) {
  824                         return fwiso_interface[i];
  825                 }
  826         }
  827 
  828         return NULL;
  829 }
  830 
  831 
  832 
  833 
  834 /*
  835  * static int fwiso_set_handler(struct fwiso_data *fd)
  836  *
  837  *      This function set interrupt handler for isochronous data read.
  838  */
  839 static int
  840 fwiso_set_handler(struct fwiso_data *fd)
  841 {
  842         int bufsize;
  843         int s;
  844         struct ieee1394_softc *isc = fd->fd_dev;
  845         int flags = 0;
  846 
  847         if (isc == NULL || isc->sc1394_ir_open == NULL) {
  848                 return ENXIO;
  849         }
  850         switch (fd->fd_mode) {
  851         case FWISO_MODE_DV:
  852                 if (fd->fd_threshold == 0) {
  853                         fd->fd_threshold = 30;
  854                 }
  855                 fd->fd_rsv_size = 1024; /* buffer for 256 ms DV data */
  856                 bufsize = 488;
  857                 flags |= IEEE1394_IR_TRIGGER_CIP_SYNC;
  858                 break;
  859         case FWISO_MODE_DV_RAW:
  860                 fd->fd_rsv_size = 128; /* buffer for 16 ms DV data */
  861                 bufsize = 488;
  862                 flags |= IEEE1394_IR_SHORTDELAY;
  863                 break;
  864         case FWISO_MODE_RAW:
  865                 fd->fd_rsv_size = 64;
  866                 bufsize = 4000;
  867                 flags |= IEEE1394_IR_NEEDHEADER | IEEE1394_IR_SHORTDELAY;
  868                 break;
  869         case FWISO_MODE_MPEG2TS:
  870                 fd->fd_rsv_size = 64;
  871                 bufsize = 512;
  872                 break;
  873         default:
  874                 return EINVAL;
  875         }
  876 
  877         s = splbio();
  878 
  879         /* set interrupt handler */
  880         fd->fd_irtag = (*isc->sc1394_ir_open)((struct device *)isc,
  881             fd->fd_channel, fd->fd_tag, fd->fd_rsv_size, bufsize, flags);
  882         if (fd->fd_irtag == NULL) {
  883                 splx(s);
  884                 return ENXIO;
  885         }
  886         fd->fd_flags |= FWISO_SETHANDLER;
  887 
  888         splx(s);
  889 
  890         return 0;
  891 }

Cache object: 1168059cdeb0531b4e15d2dc6f039ade


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