117821895SHidetoshi Shimokawa /* 217821895SHidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 317821895SHidetoshi Shimokawa * All rights reserved. 417821895SHidetoshi Shimokawa * 517821895SHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without 617821895SHidetoshi Shimokawa * modification, are permitted provided that the following conditions 717821895SHidetoshi Shimokawa * are met: 817821895SHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright 917821895SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer. 1017821895SHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright 1117821895SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the 1217821895SHidetoshi Shimokawa * documentation and/or other materials provided with the distribution. 1317821895SHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software 1417821895SHidetoshi Shimokawa * must display the acknowledgement as bellow: 1517821895SHidetoshi Shimokawa * 1617821895SHidetoshi Shimokawa * This product includes software developed by K. Kobayashi and H. Shimokawa 1717821895SHidetoshi Shimokawa * 1817821895SHidetoshi Shimokawa * 4. The name of the author may not be used to endorse or promote products 1917821895SHidetoshi Shimokawa * derived from this software without specific prior written permission. 2017821895SHidetoshi Shimokawa * 2117821895SHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2217821895SHidetoshi Shimokawa * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2317821895SHidetoshi Shimokawa * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2417821895SHidetoshi Shimokawa * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2517821895SHidetoshi Shimokawa * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2617821895SHidetoshi Shimokawa * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2717821895SHidetoshi Shimokawa * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2817821895SHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2917821895SHidetoshi Shimokawa * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3017821895SHidetoshi Shimokawa * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3117821895SHidetoshi Shimokawa * POSSIBILITY OF SUCH DAMAGE. 3217821895SHidetoshi Shimokawa * 3317821895SHidetoshi Shimokawa * $FreeBSD$ 3417821895SHidetoshi Shimokawa * 3517821895SHidetoshi Shimokawa */ 3617821895SHidetoshi Shimokawa 3717821895SHidetoshi Shimokawa #include <sys/param.h> 3817821895SHidetoshi Shimokawa #include <sys/systm.h> 3917821895SHidetoshi Shimokawa #include <sys/types.h> 4017821895SHidetoshi Shimokawa #include <sys/mbuf.h> 4117821895SHidetoshi Shimokawa 4217821895SHidetoshi Shimokawa #include <sys/kernel.h> 4317821895SHidetoshi Shimokawa #include <sys/malloc.h> 4417821895SHidetoshi Shimokawa #include <sys/conf.h> 4517821895SHidetoshi Shimokawa #include <sys/uio.h> 4617821895SHidetoshi Shimokawa #include <sys/poll.h> 4717821895SHidetoshi Shimokawa 4817821895SHidetoshi Shimokawa #include <sys/bus.h> 4917821895SHidetoshi Shimokawa 5017821895SHidetoshi Shimokawa #include <sys/ioccom.h> 5117821895SHidetoshi Shimokawa 5217821895SHidetoshi Shimokawa #include <dev/firewire/firewire.h> 5317821895SHidetoshi Shimokawa #include <dev/firewire/firewirereg.h> 5417821895SHidetoshi Shimokawa #include <dev/firewire/fwmem.h> 556d6f7f28SHidetoshi Shimokawa #include <dev/firewire/iec68113.h> 5617821895SHidetoshi Shimokawa 5717821895SHidetoshi Shimokawa #define CDEV_MAJOR 127 5817821895SHidetoshi Shimokawa #define FWNODE_INVAL 0xffff 5917821895SHidetoshi Shimokawa 6017821895SHidetoshi Shimokawa static d_open_t fw_open; 6117821895SHidetoshi Shimokawa static d_close_t fw_close; 6217821895SHidetoshi Shimokawa static d_ioctl_t fw_ioctl; 6317821895SHidetoshi Shimokawa static d_poll_t fw_poll; 6417821895SHidetoshi Shimokawa static d_read_t fw_read; /* for Isochronous packet */ 6517821895SHidetoshi Shimokawa static d_write_t fw_write; 6617821895SHidetoshi Shimokawa static d_mmap_t fw_mmap; 6717821895SHidetoshi Shimokawa 6817821895SHidetoshi Shimokawa struct cdevsw firewire_cdevsw = 6917821895SHidetoshi Shimokawa { 7017821895SHidetoshi Shimokawa fw_open, fw_close, fw_read, fw_write, fw_ioctl, 7117821895SHidetoshi Shimokawa fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 7217821895SHidetoshi Shimokawa }; 7317821895SHidetoshi Shimokawa 7417821895SHidetoshi Shimokawa static int 7517821895SHidetoshi Shimokawa fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 7617821895SHidetoshi Shimokawa { 7717821895SHidetoshi Shimokawa struct firewire_softc *sc; 7817821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 7917821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 8017821895SHidetoshi Shimokawa 8117821895SHidetoshi Shimokawa int err = 0; 8217821895SHidetoshi Shimokawa 8317821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 8417821895SHidetoshi Shimokawa return fwmem_open(dev, flags, fmt, td); 8517821895SHidetoshi Shimokawa 8617821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 8717821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 8817821895SHidetoshi Shimokawa err = EBUSY; 8917821895SHidetoshi Shimokawa return err; 9017821895SHidetoshi Shimokawa } 9117821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 9217821895SHidetoshi Shimokawa err = EBUSY; 9317821895SHidetoshi Shimokawa return err; 9417821895SHidetoshi Shimokawa } 9517821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 9617821895SHidetoshi Shimokawa err = EBUSY; 9717821895SHidetoshi Shimokawa return err; 9817821895SHidetoshi Shimokawa } 9917821895SHidetoshi Shimokawa /* Default is per packet mode */ 10017821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 10117821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 10217821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 10317821895SHidetoshi Shimokawa return err; 10417821895SHidetoshi Shimokawa } 10517821895SHidetoshi Shimokawa 10617821895SHidetoshi Shimokawa static int 10717821895SHidetoshi Shimokawa fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 10817821895SHidetoshi Shimokawa { 10917821895SHidetoshi Shimokawa struct firewire_softc *sc; 11017821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 11117821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 11217821895SHidetoshi Shimokawa struct fw_xfer *xfer; 11317821895SHidetoshi Shimokawa struct fw_bind *fwb; 11417821895SHidetoshi Shimokawa int err = 0; 11517821895SHidetoshi Shimokawa 11617821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 11717821895SHidetoshi Shimokawa return fwmem_close(dev, flags, fmt, td); 11817821895SHidetoshi Shimokawa 11917821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 12017821895SHidetoshi Shimokawa if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 12117821895SHidetoshi Shimokawa err = EINVAL; 12217821895SHidetoshi Shimokawa return err; 12317821895SHidetoshi Shimokawa } 12417821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 12517821895SHidetoshi Shimokawa if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 12617821895SHidetoshi Shimokawa err = EINVAL; 12717821895SHidetoshi Shimokawa return err; 12817821895SHidetoshi Shimokawa } 12917821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 13017821895SHidetoshi Shimokawa 13117821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 13217821895SHidetoshi Shimokawa sc->fc->irx_disable(sc->fc, sub); 13317821895SHidetoshi Shimokawa } 13417821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 13517821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 13617821895SHidetoshi Shimokawa sc->fc->itx_disable(sc->fc, sub); 13717821895SHidetoshi Shimokawa } 1389190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 13917821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 1409190691bSHidetoshi Shimokawa struct fw_dvbuf *dvbuf; 1419190691bSHidetoshi Shimokawa 14217821895SHidetoshi Shimokawa if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 1435166f1dfSHidetoshi Shimokawa free(dvbuf->buf, M_FW); 14417821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 14517821895SHidetoshi Shimokawa } 14617821895SHidetoshi Shimokawa if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 1475166f1dfSHidetoshi Shimokawa free(dvbuf->buf, M_FW); 14817821895SHidetoshi Shimokawa sc->fc->it[sub]->dvdma = NULL; 14917821895SHidetoshi Shimokawa } 15017821895SHidetoshi Shimokawa while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 15117821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 1525166f1dfSHidetoshi Shimokawa free(dvbuf->buf, M_FW); 15317821895SHidetoshi Shimokawa } 15417821895SHidetoshi Shimokawa while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 15517821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 1565166f1dfSHidetoshi Shimokawa free(dvbuf->buf, M_FW); 15717821895SHidetoshi Shimokawa } 1585166f1dfSHidetoshi Shimokawa free(sc->fc->it[sub]->dvbuf, M_FW); 15917821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 16017821895SHidetoshi Shimokawa } 1619190691bSHidetoshi Shimokawa #endif 16217821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 1635166f1dfSHidetoshi Shimokawa free(sc->fc->ir[sub]->buf, M_FW); 16417821895SHidetoshi Shimokawa sc->fc->ir[sub]->buf = NULL; 1655166f1dfSHidetoshi Shimokawa free(sc->fc->ir[sub]->bulkxfer, M_FW); 16617821895SHidetoshi Shimokawa sc->fc->ir[sub]->bulkxfer = NULL; 16717821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 168e2ad5d6eSHidetoshi Shimokawa sc->fc->ir[sub]->psize = PAGE_SIZE; 16917821895SHidetoshi Shimokawa sc->fc->ir[sub]->maxq = FWMAXQUEUE; 17017821895SHidetoshi Shimokawa } 17117821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 1725166f1dfSHidetoshi Shimokawa free(sc->fc->it[sub]->buf, M_FW); 17317821895SHidetoshi Shimokawa sc->fc->it[sub]->buf = NULL; 1745166f1dfSHidetoshi Shimokawa free(sc->fc->it[sub]->bulkxfer, M_FW); 17517821895SHidetoshi Shimokawa sc->fc->it[sub]->bulkxfer = NULL; 1765a7ba74dSHidetoshi Shimokawa #ifdef FWXFERQ_DV 17717821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 1785a7ba74dSHidetoshi Shimokawa #endif 17917821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 180e2ad5d6eSHidetoshi Shimokawa sc->fc->it[sub]->psize = 0; 18117821895SHidetoshi Shimokawa sc->fc->it[sub]->maxq = FWMAXQUEUE; 18217821895SHidetoshi Shimokawa } 18317821895SHidetoshi Shimokawa for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 18417821895SHidetoshi Shimokawa xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 18517821895SHidetoshi Shimokawa sc->fc->ir[sub]->queued--; 18617821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 18717821895SHidetoshi Shimokawa 18817821895SHidetoshi Shimokawa xfer->resp = 0; 18917821895SHidetoshi Shimokawa switch(xfer->act_type){ 19017821895SHidetoshi Shimokawa case FWACT_XFER: 19117821895SHidetoshi Shimokawa fw_xfer_done(xfer); 19217821895SHidetoshi Shimokawa break; 19317821895SHidetoshi Shimokawa default: 19417821895SHidetoshi Shimokawa break; 19517821895SHidetoshi Shimokawa } 19617821895SHidetoshi Shimokawa fw_xfer_free(xfer); 19717821895SHidetoshi Shimokawa } 19817821895SHidetoshi Shimokawa for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 19917821895SHidetoshi Shimokawa fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 20017821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 20117821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 2025166f1dfSHidetoshi Shimokawa free(fwb, M_FW); 20317821895SHidetoshi Shimokawa } 20417821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 20517821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 20617821895SHidetoshi Shimokawa return err; 20717821895SHidetoshi Shimokawa } 20817821895SHidetoshi Shimokawa 20917821895SHidetoshi Shimokawa /* 21017821895SHidetoshi Shimokawa * read request. 21117821895SHidetoshi Shimokawa */ 21217821895SHidetoshi Shimokawa static int 21317821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag) 21417821895SHidetoshi Shimokawa { 21517821895SHidetoshi Shimokawa struct firewire_softc *sc; 21617821895SHidetoshi Shimokawa struct fw_xferq *ir; 21717821895SHidetoshi Shimokawa struct fw_xfer *xfer; 21817821895SHidetoshi Shimokawa int err = 0, s, slept = 0; 21917821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 22017821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 22117821895SHidetoshi Shimokawa struct fw_pkt *fp; 22217821895SHidetoshi Shimokawa 22317821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 22417821895SHidetoshi Shimokawa return fwmem_read(dev, uio, ioflag); 22517821895SHidetoshi Shimokawa 22617821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 22717821895SHidetoshi Shimokawa 22817821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 22917821895SHidetoshi Shimokawa 23017821895SHidetoshi Shimokawa if (ir->flag & FWXFERQ_PACKET) { 23117821895SHidetoshi Shimokawa ir->stproc = NULL; 23217821895SHidetoshi Shimokawa } 23317821895SHidetoshi Shimokawa readloop: 23417821895SHidetoshi Shimokawa xfer = STAILQ_FIRST(&ir->q); 235c3e9e255SHidetoshi Shimokawa if ((ir->flag & FWXFERQ_PACKET) == 0 && ir->stproc == NULL) { 236c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 23717821895SHidetoshi Shimokawa ir->stproc = STAILQ_FIRST(&ir->stvalid); 23817821895SHidetoshi Shimokawa if (ir->stproc != NULL) { 23917821895SHidetoshi Shimokawa s = splfw(); 24017821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stvalid, link); 24117821895SHidetoshi Shimokawa splx(s); 24217821895SHidetoshi Shimokawa ir->queued = 0; 24317821895SHidetoshi Shimokawa } 24417821895SHidetoshi Shimokawa } 24517821895SHidetoshi Shimokawa if (xfer == NULL && ir->stproc == NULL) { 246c3e9e255SHidetoshi Shimokawa /* no data avaliable */ 24717821895SHidetoshi Shimokawa if (slept == 0) { 24817821895SHidetoshi Shimokawa slept = 1; 249c3e9e255SHidetoshi Shimokawa if ((ir->flag & FWXFERQ_RUNNING) == 0 25017821895SHidetoshi Shimokawa && (ir->flag & FWXFERQ_PACKET)) { 25117821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 252c3e9e255SHidetoshi Shimokawa if (err) 25317821895SHidetoshi Shimokawa return err; 25417821895SHidetoshi Shimokawa } 25517821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_WAKEUP; 25617821895SHidetoshi Shimokawa err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz); 25717821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_WAKEUP; 258c3e9e255SHidetoshi Shimokawa if (err == 0) 25917821895SHidetoshi Shimokawa goto readloop; 260c3e9e255SHidetoshi Shimokawa } else if (slept == 1) 26117821895SHidetoshi Shimokawa err = EIO; 26217821895SHidetoshi Shimokawa return err; 26317821895SHidetoshi Shimokawa } else if(xfer != NULL) { 264c3e9e255SHidetoshi Shimokawa /* per packet mode */ 26517821895SHidetoshi Shimokawa s = splfw(); 26617821895SHidetoshi Shimokawa ir->queued --; 26717821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->q, link); 26817821895SHidetoshi Shimokawa splx(s); 26917821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 27017821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 27117821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 27217821895SHidetoshi Shimokawa err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 27317821895SHidetoshi Shimokawa fw_xfer_free( xfer); 27417821895SHidetoshi Shimokawa } else if(ir->stproc != NULL) { 275c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 27617821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 27717821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 27817821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 27917821895SHidetoshi Shimokawa if(ntohs(fp->mode.stream.len) == 0){ 28017821895SHidetoshi Shimokawa err = EIO; 28117821895SHidetoshi Shimokawa return err; 28217821895SHidetoshi Shimokawa } 283c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, 284c3e9e255SHidetoshi Shimokawa ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 285c3e9e255SHidetoshi Shimokawa #if 0 28617821895SHidetoshi Shimokawa fp->mode.stream.len = 0; 287c3e9e255SHidetoshi Shimokawa #endif 28817821895SHidetoshi Shimokawa ir->queued ++; 28917821895SHidetoshi Shimokawa if(ir->queued >= ir->bnpacket){ 29017821895SHidetoshi Shimokawa s = splfw(); 29117821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 29217821895SHidetoshi Shimokawa splx(s); 2935a7ba74dSHidetoshi Shimokawa sc->fc->irx_enable(sc->fc, sub); 29417821895SHidetoshi Shimokawa ir->stproc = NULL; 29517821895SHidetoshi Shimokawa } 296c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= ir->psize) { 297c3e9e255SHidetoshi Shimokawa slept = -1; 298c3e9e255SHidetoshi Shimokawa goto readloop; 299c3e9e255SHidetoshi Shimokawa } 30017821895SHidetoshi Shimokawa } 30117821895SHidetoshi Shimokawa return err; 30217821895SHidetoshi Shimokawa } 30317821895SHidetoshi Shimokawa 30417821895SHidetoshi Shimokawa static int 30517821895SHidetoshi Shimokawa fw_write (dev_t dev, struct uio *uio, int ioflag) 30617821895SHidetoshi Shimokawa { 30717821895SHidetoshi Shimokawa int err = 0; 30817821895SHidetoshi Shimokawa struct firewire_softc *sc; 30917821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 31017821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 31117821895SHidetoshi Shimokawa int s, slept = 0; 31217821895SHidetoshi Shimokawa struct fw_pkt *fp; 31317821895SHidetoshi Shimokawa struct fw_xfer *xfer; 31417821895SHidetoshi Shimokawa struct fw_xferq *xferq; 31517821895SHidetoshi Shimokawa struct firewire_comm *fc; 31617821895SHidetoshi Shimokawa struct fw_xferq *it; 31717821895SHidetoshi Shimokawa 31817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 31917821895SHidetoshi Shimokawa return fwmem_write(dev, uio, ioflag); 32017821895SHidetoshi Shimokawa 32117821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 32217821895SHidetoshi Shimokawa fc = sc->fc; 32317821895SHidetoshi Shimokawa it = sc->fc->it[sub]; 32417821895SHidetoshi Shimokawa 32517821895SHidetoshi Shimokawa fp = (struct fw_pkt *)uio->uio_iov->iov_base; 32617821895SHidetoshi Shimokawa switch(fp->mode.common.tcode){ 32717821895SHidetoshi Shimokawa case FWTCODE_RREQQ: 32817821895SHidetoshi Shimokawa case FWTCODE_RREQB: 32917821895SHidetoshi Shimokawa case FWTCODE_LREQ: 33017821895SHidetoshi Shimokawa err = EINVAL; 33117821895SHidetoshi Shimokawa return err; 33217821895SHidetoshi Shimokawa case FWTCODE_WREQQ: 33317821895SHidetoshi Shimokawa case FWTCODE_WREQB: 33417821895SHidetoshi Shimokawa xferq = fc->atq; 33517821895SHidetoshi Shimokawa break; 33617821895SHidetoshi Shimokawa case FWTCODE_STREAM: 33717821895SHidetoshi Shimokawa if(it->flag & FWXFERQ_PACKET){ 33817821895SHidetoshi Shimokawa xferq = fc->atq; 33917821895SHidetoshi Shimokawa }else{ 34017821895SHidetoshi Shimokawa xferq = NULL; 34117821895SHidetoshi Shimokawa } 34217821895SHidetoshi Shimokawa break; 34317821895SHidetoshi Shimokawa case FWTCODE_WRES: 34417821895SHidetoshi Shimokawa case FWTCODE_RRESQ: 34517821895SHidetoshi Shimokawa case FWTCODE_RRESB: 34617821895SHidetoshi Shimokawa case FWTCODE_LRES: 34717821895SHidetoshi Shimokawa xferq = fc->ats; 34817821895SHidetoshi Shimokawa break; 34917821895SHidetoshi Shimokawa default: 35017821895SHidetoshi Shimokawa err = EINVAL; 35117821895SHidetoshi Shimokawa return err; 35217821895SHidetoshi Shimokawa } 35317821895SHidetoshi Shimokawa /* Discard unsent buffered stream packet, when sending Asyrequrst */ 35417821895SHidetoshi Shimokawa if(xferq != NULL && it->stproc != NULL){ 35517821895SHidetoshi Shimokawa s = splfw(); 35617821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 35717821895SHidetoshi Shimokawa splx(s); 35817821895SHidetoshi Shimokawa it->stproc = NULL; 35917821895SHidetoshi Shimokawa } 3609190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 36117821895SHidetoshi Shimokawa if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 3629190691bSHidetoshi Shimokawa #else 3639190691bSHidetoshi Shimokawa if (xferq == NULL) { 3649190691bSHidetoshi Shimokawa #endif 36517821895SHidetoshi Shimokawa isoloop: 36617821895SHidetoshi Shimokawa if (it->stproc == NULL) { 36717821895SHidetoshi Shimokawa it->stproc = STAILQ_FIRST(&it->stfree); 36817821895SHidetoshi Shimokawa if (it->stproc != NULL) { 36917821895SHidetoshi Shimokawa s = splfw(); 37017821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stfree, link); 37117821895SHidetoshi Shimokawa splx(s); 37217821895SHidetoshi Shimokawa it->queued = 0; 37317821895SHidetoshi Shimokawa } else if (slept == 0) { 37417821895SHidetoshi Shimokawa slept = 1; 37517821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 376c3e9e255SHidetoshi Shimokawa if (err) 37717821895SHidetoshi Shimokawa return err; 378c3e9e255SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, 379c3e9e255SHidetoshi Shimokawa "fw_write", hz); 380c3e9e255SHidetoshi Shimokawa if (err) 38117821895SHidetoshi Shimokawa return err; 38217821895SHidetoshi Shimokawa goto isoloop; 38317821895SHidetoshi Shimokawa } else { 38417821895SHidetoshi Shimokawa err = EIO; 38517821895SHidetoshi Shimokawa return err; 38617821895SHidetoshi Shimokawa } 38717821895SHidetoshi Shimokawa } 388c3e9e255SHidetoshi Shimokawa fp = (struct fw_pkt *) 389c3e9e255SHidetoshi Shimokawa (it->stproc->buf + it->queued * it->psize); 390c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 391c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp->mode.stream.payload, 392c3e9e255SHidetoshi Shimokawa ntohs(fp->mode.stream.len), uio); 39317821895SHidetoshi Shimokawa it->queued ++; 394c3e9e255SHidetoshi Shimokawa if (it->queued >= it->bnpacket) { 39517821895SHidetoshi Shimokawa s = splfw(); 39617821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 39717821895SHidetoshi Shimokawa splx(s); 39817821895SHidetoshi Shimokawa it->stproc = NULL; 39917821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 40017821895SHidetoshi Shimokawa } 401c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 402c3e9e255SHidetoshi Shimokawa slept = 0; 403c3e9e255SHidetoshi Shimokawa goto isoloop; 404c3e9e255SHidetoshi Shimokawa } 40517821895SHidetoshi Shimokawa return err; 4069190691bSHidetoshi Shimokawa } 4079190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 4089190691bSHidetoshi Shimokawa if(xferq == NULL && it->flag & FWXFERQ_DV){ 40917821895SHidetoshi Shimokawa dvloop: 41017821895SHidetoshi Shimokawa if(it->dvproc == NULL){ 41117821895SHidetoshi Shimokawa it->dvproc = STAILQ_FIRST(&it->dvfree); 41217821895SHidetoshi Shimokawa if(it->dvproc != NULL){ 41317821895SHidetoshi Shimokawa s = splfw(); 41417821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->dvfree, link); 41517821895SHidetoshi Shimokawa splx(s); 41617821895SHidetoshi Shimokawa it->dvptr = 0; 41717821895SHidetoshi Shimokawa }else if(slept == 0){ 41817821895SHidetoshi Shimokawa slept = 1; 41917821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 42017821895SHidetoshi Shimokawa if(err){ 42117821895SHidetoshi Shimokawa return err; 42217821895SHidetoshi Shimokawa } 42317821895SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 42417821895SHidetoshi Shimokawa if(err){ 42517821895SHidetoshi Shimokawa return err; 42617821895SHidetoshi Shimokawa } 42717821895SHidetoshi Shimokawa goto dvloop; 42817821895SHidetoshi Shimokawa }else{ 42917821895SHidetoshi Shimokawa err = EIO; 43017821895SHidetoshi Shimokawa return err; 43117821895SHidetoshi Shimokawa } 43217821895SHidetoshi Shimokawa } 4330aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/ 43417821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 43517821895SHidetoshi Shimokawa fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 4360aaa9a23SHidetoshi Shimokawa #endif 43717821895SHidetoshi Shimokawa err = uiomove(it->dvproc->buf + it->dvptr, 43817821895SHidetoshi Shimokawa uio->uio_resid, uio); 43917821895SHidetoshi Shimokawa it->dvptr += it->psize; 44017821895SHidetoshi Shimokawa if(err){ 44117821895SHidetoshi Shimokawa return err; 44217821895SHidetoshi Shimokawa } 44317821895SHidetoshi Shimokawa if(it->dvptr >= it->psize * it->dvpacket){ 44417821895SHidetoshi Shimokawa s = splfw(); 44517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 44617821895SHidetoshi Shimokawa splx(s); 44717821895SHidetoshi Shimokawa it->dvproc = NULL; 44817821895SHidetoshi Shimokawa err = fw_tbuf_update(sc->fc, sub, 0); 44917821895SHidetoshi Shimokawa if(err){ 45017821895SHidetoshi Shimokawa return err; 45117821895SHidetoshi Shimokawa } 45217821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 45317821895SHidetoshi Shimokawa } 45417821895SHidetoshi Shimokawa return err; 45517821895SHidetoshi Shimokawa } 4569190691bSHidetoshi Shimokawa #endif 45717821895SHidetoshi Shimokawa if(xferq != NULL){ 45848249fe0SHidetoshi Shimokawa xfer = fw_xfer_alloc(M_FWXFER); 45917821895SHidetoshi Shimokawa if(xfer == NULL){ 46017821895SHidetoshi Shimokawa err = ENOMEM; 46117821895SHidetoshi Shimokawa return err; 46217821895SHidetoshi Shimokawa } 4635166f1dfSHidetoshi Shimokawa xfer->send.buf = malloc(uio->uio_resid, M_FW, M_NOWAIT); 46417821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 46517821895SHidetoshi Shimokawa fw_xfer_free( xfer); 46617821895SHidetoshi Shimokawa err = ENOBUFS; 46717821895SHidetoshi Shimokawa return err; 46817821895SHidetoshi Shimokawa } 46917821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 47017821895SHidetoshi Shimokawa #if 0 47117821895SHidetoshi Shimokawa switch(fp->mode.common.tcode){ 47217821895SHidetoshi Shimokawa case FWTCODE_WREQQ: 47317821895SHidetoshi Shimokawa case FWTCODE_WREQB: 47417821895SHidetoshi Shimokawa if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 47517821895SHidetoshi Shimokawa fw_xfer_free( xfer); 47617821895SHidetoshi Shimokawa err = EAGAIN; 47717821895SHidetoshi Shimokawa return err; 47817821895SHidetoshi Shimokawa } 47917821895SHidetoshi Shimokawa fp->mode.hdr.tlrt = tl << 2; 48017821895SHidetoshi Shimokawa default: 48117821895SHidetoshi Shimokawa break; 48217821895SHidetoshi Shimokawa } 48317821895SHidetoshi Shimokawa 48417821895SHidetoshi Shimokawa xfer->tl = fp->mode.hdr.tlrt >> 2; 48517821895SHidetoshi Shimokawa xfer->tcode = fp->mode.common.tcode; 48617821895SHidetoshi Shimokawa xfer->fc = fc; 48717821895SHidetoshi Shimokawa xfer->q = xferq; 48817821895SHidetoshi Shimokawa xfer->act_type = FWACT_XFER; 48917821895SHidetoshi Shimokawa xfer->retry_req = fw_asybusy; 49017821895SHidetoshi Shimokawa #endif 49117821895SHidetoshi Shimokawa xfer->send.len = uio->uio_resid; 49217821895SHidetoshi Shimokawa xfer->send.off = 0; 49317821895SHidetoshi Shimokawa xfer->spd = 0;/* XXX: how to setup it */ 49417821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 49517821895SHidetoshi Shimokawa 49617821895SHidetoshi Shimokawa err = uiomove(xfer->send.buf, uio->uio_resid, uio); 49717821895SHidetoshi Shimokawa if(err){ 49817821895SHidetoshi Shimokawa fw_xfer_free( xfer); 49917821895SHidetoshi Shimokawa return err; 50017821895SHidetoshi Shimokawa } 50117821895SHidetoshi Shimokawa #if 0 50217821895SHidetoshi Shimokawa fw_asystart(xfer); 50317821895SHidetoshi Shimokawa #else 50417821895SHidetoshi Shimokawa fw_asyreq(fc, -1, xfer); 50517821895SHidetoshi Shimokawa #endif 50617821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz); 50717821895SHidetoshi Shimokawa if(xfer->resp == EBUSY) 50817821895SHidetoshi Shimokawa return EBUSY; 50917821895SHidetoshi Shimokawa fw_xfer_free( xfer); 51017821895SHidetoshi Shimokawa return err; 51117821895SHidetoshi Shimokawa } 51217821895SHidetoshi Shimokawa return EINVAL; 51317821895SHidetoshi Shimokawa } 51417821895SHidetoshi Shimokawa 51517821895SHidetoshi Shimokawa /* 51617821895SHidetoshi Shimokawa * ioctl support. 51717821895SHidetoshi Shimokawa */ 51817821895SHidetoshi Shimokawa int 51917821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 52017821895SHidetoshi Shimokawa { 52117821895SHidetoshi Shimokawa struct firewire_softc *sc; 52217821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 52317821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 52417821895SHidetoshi Shimokawa int i, len, err = 0; 52517821895SHidetoshi Shimokawa struct fw_device *fwdev; 52617821895SHidetoshi Shimokawa struct fw_bind *fwb; 52717821895SHidetoshi Shimokawa struct fw_xferq *ir, *it; 52817821895SHidetoshi Shimokawa struct fw_xfer *xfer; 52917821895SHidetoshi Shimokawa struct fw_pkt *fp; 530c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 53117821895SHidetoshi Shimokawa 53217821895SHidetoshi Shimokawa struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 53317821895SHidetoshi Shimokawa struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 53417821895SHidetoshi Shimokawa struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 53517821895SHidetoshi Shimokawa struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 53617821895SHidetoshi Shimokawa struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 53717821895SHidetoshi Shimokawa struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 53817821895SHidetoshi Shimokawa 53917821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 54017821895SHidetoshi Shimokawa return fwmem_ioctl(dev, cmd, data, flag, td); 54117821895SHidetoshi Shimokawa 54217821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 54317821895SHidetoshi Shimokawa if (!data) 54417821895SHidetoshi Shimokawa return(EINVAL); 54517821895SHidetoshi Shimokawa 54617821895SHidetoshi Shimokawa switch (cmd) { 54717821895SHidetoshi Shimokawa case FW_STSTREAM: 54817821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~0xff; 54917821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 55017821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 55117821895SHidetoshi Shimokawa err = 0; 55217821895SHidetoshi Shimokawa break; 55317821895SHidetoshi Shimokawa case FW_GTSTREAM: 55417821895SHidetoshi Shimokawa ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 55517821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 55617821895SHidetoshi Shimokawa err = 0; 55717821895SHidetoshi Shimokawa break; 55817821895SHidetoshi Shimokawa case FW_SRSTREAM: 55917821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~0xff; 56017821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 56117821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 56217821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 56317821895SHidetoshi Shimokawa break; 56417821895SHidetoshi Shimokawa case FW_GRSTREAM: 56517821895SHidetoshi Shimokawa ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 56617821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 56717821895SHidetoshi Shimokawa err = 0; 56817821895SHidetoshi Shimokawa break; 5699190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 57017821895SHidetoshi Shimokawa case FW_SSTDV: 57117821895SHidetoshi Shimokawa ibufreq = (struct fw_isobufreq *) 5725166f1dfSHidetoshi Shimokawa malloc(sizeof(struct fw_isobufreq), M_FW, M_NOWAIT); 57317821895SHidetoshi Shimokawa if(ibufreq == NULL){ 57417821895SHidetoshi Shimokawa err = ENOMEM; 57517821895SHidetoshi Shimokawa break; 57617821895SHidetoshi Shimokawa } 5776d6f7f28SHidetoshi Shimokawa #if DV_PAL 5786d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 300 5796d6f7f28SHidetoshi Shimokawa #else 5806d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 250 5816d6f7f28SHidetoshi Shimokawa #endif 58217821895SHidetoshi Shimokawa #define FWDVPMAX 512 58317821895SHidetoshi Shimokawa ibufreq->rx.nchunk = 8; 58417821895SHidetoshi Shimokawa ibufreq->rx.npacket = 50; 58517821895SHidetoshi Shimokawa ibufreq->rx.psize = FWDVPMAX; 58617821895SHidetoshi Shimokawa 58717821895SHidetoshi Shimokawa ibufreq->tx.nchunk = 5; 5886d6f7f28SHidetoshi Shimokawa ibufreq->tx.npacket = FWDVPACKET + 30; /* > 320 or 267 */ 58917821895SHidetoshi Shimokawa ibufreq->tx.psize = FWDVPMAX; 59017821895SHidetoshi Shimokawa 59117821895SHidetoshi Shimokawa err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 59217821895SHidetoshi Shimokawa sc->fc->it[sub]->dvpacket = FWDVPACKET; 5935166f1dfSHidetoshi Shimokawa free(ibufreq, M_FW); 59417821895SHidetoshi Shimokawa /* reserve a buffer space */ 59517821895SHidetoshi Shimokawa #define NDVCHUNK 8 59617821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 59717821895SHidetoshi Shimokawa sc->fc->it[sub]->dvdma = NULL; 59817821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= FWXFERQ_DV; 5990aaa9a23SHidetoshi Shimokawa /* XXX check malloc failure */ 60017821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf 6015166f1dfSHidetoshi Shimokawa = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_FW, M_NOWAIT); 60217821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 60317821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvfree); 60417821895SHidetoshi Shimokawa for( i = 0 ; i < NDVCHUNK ; i++){ 6050aaa9a23SHidetoshi Shimokawa /* XXX check malloc failure */ 60617821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf[i].buf 6075166f1dfSHidetoshi Shimokawa = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_FW, M_NOWAIT); 60817821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 60917821895SHidetoshi Shimokawa &sc->fc->it[sub]->dvbuf[i], link); 61017821895SHidetoshi Shimokawa } 61117821895SHidetoshi Shimokawa break; 6129190691bSHidetoshi Shimokawa #endif 61317821895SHidetoshi Shimokawa case FW_SSTBUF: 61417821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 61517821895SHidetoshi Shimokawa it = sc->fc->it[sub]; 61617821895SHidetoshi Shimokawa 61717821895SHidetoshi Shimokawa if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 61817821895SHidetoshi Shimokawa return(EBUSY); 61917821895SHidetoshi Shimokawa } 62017821895SHidetoshi Shimokawa if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 62117821895SHidetoshi Shimokawa return(EBUSY); 62217821895SHidetoshi Shimokawa } 62317821895SHidetoshi Shimokawa if((ibufreq->rx.nchunk * 62417821895SHidetoshi Shimokawa ibufreq->rx.psize * ibufreq->rx.npacket) + 62517821895SHidetoshi Shimokawa (ibufreq->tx.nchunk * 62617821895SHidetoshi Shimokawa ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 62717821895SHidetoshi Shimokawa return(EINVAL); 62817821895SHidetoshi Shimokawa } 62917821895SHidetoshi Shimokawa if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 63017821895SHidetoshi Shimokawa ibufreq->tx.nchunk > FWSTMAXCHUNK){ 63117821895SHidetoshi Shimokawa return(EINVAL); 63217821895SHidetoshi Shimokawa } 63317821895SHidetoshi Shimokawa ir->bulkxfer 634beb19fc5SHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_FW, 0); 63517821895SHidetoshi Shimokawa if(ir->bulkxfer == NULL){ 63617821895SHidetoshi Shimokawa return(ENOMEM); 63717821895SHidetoshi Shimokawa } 63817821895SHidetoshi Shimokawa it->bulkxfer 639beb19fc5SHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_FW, 0); 64017821895SHidetoshi Shimokawa if(it->bulkxfer == NULL){ 64117821895SHidetoshi Shimokawa return(ENOMEM); 64217821895SHidetoshi Shimokawa } 64317821895SHidetoshi Shimokawa ir->buf = malloc( 64417821895SHidetoshi Shimokawa ibufreq->rx.nchunk * ibufreq->rx.npacket 6457643dc18SHidetoshi Shimokawa /* XXX psize must be 2^n and less or 6467643dc18SHidetoshi Shimokawa equal to PAGE_SIZE */ 64717821895SHidetoshi Shimokawa * ((ibufreq->rx.psize + 3) &~3), 648beb19fc5SHidetoshi Shimokawa M_FW, 0); 64917821895SHidetoshi Shimokawa if(ir->buf == NULL){ 6505166f1dfSHidetoshi Shimokawa free(ir->bulkxfer, M_FW); 6515166f1dfSHidetoshi Shimokawa free(it->bulkxfer, M_FW); 65217821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 65317821895SHidetoshi Shimokawa it->bulkxfer = NULL; 65417821895SHidetoshi Shimokawa it->buf = NULL; 65517821895SHidetoshi Shimokawa return(ENOMEM); 65617821895SHidetoshi Shimokawa } 65717821895SHidetoshi Shimokawa it->buf = malloc( 65817821895SHidetoshi Shimokawa ibufreq->tx.nchunk * ibufreq->tx.npacket 6597643dc18SHidetoshi Shimokawa /* XXX psize must be 2^n and less or 6607643dc18SHidetoshi Shimokawa equal to PAGE_SIZE */ 66117821895SHidetoshi Shimokawa * ((ibufreq->tx.psize + 3) &~3), 662beb19fc5SHidetoshi Shimokawa M_FW, 0); 66317821895SHidetoshi Shimokawa if(it->buf == NULL){ 6645166f1dfSHidetoshi Shimokawa free(ir->bulkxfer, M_FW); 6655166f1dfSHidetoshi Shimokawa free(it->bulkxfer, M_FW); 6665166f1dfSHidetoshi Shimokawa free(ir->buf, M_FW); 66717821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 66817821895SHidetoshi Shimokawa it->bulkxfer = NULL; 66917821895SHidetoshi Shimokawa it->buf = NULL; 67017821895SHidetoshi Shimokawa return(ENOMEM); 67117821895SHidetoshi Shimokawa } 67217821895SHidetoshi Shimokawa 67317821895SHidetoshi Shimokawa ir->bnchunk = ibufreq->rx.nchunk; 67417821895SHidetoshi Shimokawa ir->bnpacket = ibufreq->rx.npacket; 67517821895SHidetoshi Shimokawa ir->psize = (ibufreq->rx.psize + 3) & ~3; 67617821895SHidetoshi Shimokawa ir->queued = 0; 67717821895SHidetoshi Shimokawa 67817821895SHidetoshi Shimokawa it->bnchunk = ibufreq->tx.nchunk; 67917821895SHidetoshi Shimokawa it->bnpacket = ibufreq->tx.npacket; 68017821895SHidetoshi Shimokawa it->psize = (ibufreq->tx.psize + 3) & ~3; 6815a7ba74dSHidetoshi Shimokawa it->queued = 0; 6825a7ba74dSHidetoshi Shimokawa 6835a7ba74dSHidetoshi Shimokawa #ifdef FWXFERQ_DV 68417821895SHidetoshi Shimokawa it->dvdbc = 0; 68517821895SHidetoshi Shimokawa it->dvdiff = 0; 68617821895SHidetoshi Shimokawa it->dvsync = 0; 6870aaa9a23SHidetoshi Shimokawa it->dvoffset = 0; 6885a7ba74dSHidetoshi Shimokawa #endif 68917821895SHidetoshi Shimokawa 69017821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stvalid); 69117821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stfree); 6925a7ba74dSHidetoshi Shimokawa STAILQ_INIT(&ir->stdma); 69317821895SHidetoshi Shimokawa ir->stproc = NULL; 69417821895SHidetoshi Shimokawa 69517821895SHidetoshi Shimokawa STAILQ_INIT(&it->stvalid); 69617821895SHidetoshi Shimokawa STAILQ_INIT(&it->stfree); 6975a7ba74dSHidetoshi Shimokawa STAILQ_INIT(&it->stdma); 69817821895SHidetoshi Shimokawa it->stproc = NULL; 69917821895SHidetoshi Shimokawa 70017821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 70117821895SHidetoshi Shimokawa ir->bulkxfer[i].buf = 70217821895SHidetoshi Shimokawa ir->buf + 70317821895SHidetoshi Shimokawa i * sc->fc->ir[sub]->bnpacket * 70417821895SHidetoshi Shimokawa sc->fc->ir[sub]->psize; 70517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, 70617821895SHidetoshi Shimokawa &ir->bulkxfer[i], link); 70717821895SHidetoshi Shimokawa ir->bulkxfer[i].npacket = ir->bnpacket; 70817821895SHidetoshi Shimokawa } 70917821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 71017821895SHidetoshi Shimokawa it->bulkxfer[i].buf = 71117821895SHidetoshi Shimokawa it->buf + 71217821895SHidetoshi Shimokawa i * sc->fc->it[sub]->bnpacket * 71317821895SHidetoshi Shimokawa sc->fc->it[sub]->psize; 71417821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, 71517821895SHidetoshi Shimokawa &it->bulkxfer[i], link); 71617821895SHidetoshi Shimokawa it->bulkxfer[i].npacket = it->bnpacket; 71717821895SHidetoshi Shimokawa } 71817821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_MODEMASK; 71917821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_STREAM; 72017821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_EXTBUF; 72117821895SHidetoshi Shimokawa 72217821895SHidetoshi Shimokawa it->flag &= ~FWXFERQ_MODEMASK; 72317821895SHidetoshi Shimokawa it->flag |= FWXFERQ_STREAM; 72417821895SHidetoshi Shimokawa it->flag |= FWXFERQ_EXTBUF; 72517821895SHidetoshi Shimokawa err = 0; 72617821895SHidetoshi Shimokawa break; 72717821895SHidetoshi Shimokawa case FW_GSTBUF: 72817821895SHidetoshi Shimokawa ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 72917821895SHidetoshi Shimokawa ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 73017821895SHidetoshi Shimokawa ibufreq->rx.psize = sc->fc->ir[sub]->psize; 73117821895SHidetoshi Shimokawa 73217821895SHidetoshi Shimokawa ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 73317821895SHidetoshi Shimokawa ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 73417821895SHidetoshi Shimokawa ibufreq->tx.psize = sc->fc->it[sub]->psize; 73517821895SHidetoshi Shimokawa break; 73617821895SHidetoshi Shimokawa case FW_ASYREQ: 73748249fe0SHidetoshi Shimokawa xfer = fw_xfer_alloc(M_FWXFER); 73817821895SHidetoshi Shimokawa if(xfer == NULL){ 73917821895SHidetoshi Shimokawa err = ENOMEM; 74017821895SHidetoshi Shimokawa return err; 74117821895SHidetoshi Shimokawa } 74217821895SHidetoshi Shimokawa fp = &asyreq->pkt; 74317821895SHidetoshi Shimokawa switch (asyreq->req.type) { 74417821895SHidetoshi Shimokawa case FWASREQNODE: 74517821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 74617821895SHidetoshi Shimokawa break; 74717821895SHidetoshi Shimokawa case FWASREQEUI: 748958c7749SHidetoshi Shimokawa fwdev = fw_noderesolve_eui64(sc->fc, 749233b1b97SHidetoshi Shimokawa &asyreq->req.dst.eui); 75017821895SHidetoshi Shimokawa if (fwdev == NULL) { 75117faeefcSHidetoshi Shimokawa device_printf(sc->fc->bdev, 75217faeefcSHidetoshi Shimokawa "cannot find node\n"); 75317821895SHidetoshi Shimokawa err = EINVAL; 75417821895SHidetoshi Shimokawa goto error; 75517821895SHidetoshi Shimokawa } 75617821895SHidetoshi Shimokawa xfer->dst = fwdev->dst; 75717821895SHidetoshi Shimokawa fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 75817821895SHidetoshi Shimokawa break; 75917821895SHidetoshi Shimokawa case FWASRESTL: 76017821895SHidetoshi Shimokawa /* XXX what's this? */ 76117821895SHidetoshi Shimokawa break; 76217821895SHidetoshi Shimokawa case FWASREQSTREAM: 76317821895SHidetoshi Shimokawa /* nothing to do */ 76417821895SHidetoshi Shimokawa break; 76517821895SHidetoshi Shimokawa } 76617821895SHidetoshi Shimokawa xfer->spd = asyreq->req.sped; 76717821895SHidetoshi Shimokawa xfer->send.len = asyreq->req.len; 7685166f1dfSHidetoshi Shimokawa xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT); 76917821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 77017821895SHidetoshi Shimokawa return ENOMEM; 77117821895SHidetoshi Shimokawa } 77217821895SHidetoshi Shimokawa xfer->send.off = 0; 77317821895SHidetoshi Shimokawa bcopy(fp, xfer->send.buf, xfer->send.len); 77417821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 77517821895SHidetoshi Shimokawa err = fw_asyreq(sc->fc, sub, xfer); 77617821895SHidetoshi Shimokawa if(err){ 77717821895SHidetoshi Shimokawa fw_xfer_free( xfer); 77817821895SHidetoshi Shimokawa return err; 77917821895SHidetoshi Shimokawa } 78017821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz); 78117821895SHidetoshi Shimokawa if(err == 0){ 78217821895SHidetoshi Shimokawa if(asyreq->req.len >= xfer->recv.len){ 78317821895SHidetoshi Shimokawa asyreq->req.len = xfer->recv.len; 78417821895SHidetoshi Shimokawa }else{ 78517821895SHidetoshi Shimokawa err = EINVAL; 78617821895SHidetoshi Shimokawa } 78717821895SHidetoshi Shimokawa bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 78817821895SHidetoshi Shimokawa } 78917821895SHidetoshi Shimokawa error: 79017821895SHidetoshi Shimokawa fw_xfer_free( xfer); 79117821895SHidetoshi Shimokawa break; 79217821895SHidetoshi Shimokawa case FW_IBUSRST: 79317821895SHidetoshi Shimokawa sc->fc->ibr(sc->fc); 79417821895SHidetoshi Shimokawa break; 79517821895SHidetoshi Shimokawa case FW_CBINDADDR: 79617821895SHidetoshi Shimokawa fwb = fw_bindlookup(sc->fc, 79717821895SHidetoshi Shimokawa bindreq->start.hi, bindreq->start.lo); 79817821895SHidetoshi Shimokawa if(fwb == NULL){ 79917821895SHidetoshi Shimokawa err = EINVAL; 80017821895SHidetoshi Shimokawa break; 80117821895SHidetoshi Shimokawa } 80217821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 80317821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 8045166f1dfSHidetoshi Shimokawa free(fwb, M_FW); 80517821895SHidetoshi Shimokawa break; 80617821895SHidetoshi Shimokawa case FW_SBINDADDR: 80717821895SHidetoshi Shimokawa if(bindreq->len <= 0 ){ 80817821895SHidetoshi Shimokawa err = EINVAL; 80917821895SHidetoshi Shimokawa break; 81017821895SHidetoshi Shimokawa } 81117821895SHidetoshi Shimokawa if(bindreq->start.hi > 0xffff ){ 81217821895SHidetoshi Shimokawa err = EINVAL; 81317821895SHidetoshi Shimokawa break; 81417821895SHidetoshi Shimokawa } 8155166f1dfSHidetoshi Shimokawa fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 81617821895SHidetoshi Shimokawa if(fwb == NULL){ 81717821895SHidetoshi Shimokawa err = ENOMEM; 81817821895SHidetoshi Shimokawa break; 81917821895SHidetoshi Shimokawa } 82017821895SHidetoshi Shimokawa fwb->start_hi = bindreq->start.hi; 82117821895SHidetoshi Shimokawa fwb->start_lo = bindreq->start.lo; 82217821895SHidetoshi Shimokawa fwb->addrlen = bindreq->len; 82317821895SHidetoshi Shimokawa 82448249fe0SHidetoshi Shimokawa xfer = fw_xfer_alloc(M_FWXFER); 82517821895SHidetoshi Shimokawa if(xfer == NULL){ 82617821895SHidetoshi Shimokawa err = ENOMEM; 82717821895SHidetoshi Shimokawa return err; 82817821895SHidetoshi Shimokawa } 82917821895SHidetoshi Shimokawa xfer->act_type = FWACT_CH; 83017821895SHidetoshi Shimokawa xfer->sub = sub; 83117821895SHidetoshi Shimokawa xfer->fc = sc->fc; 83217821895SHidetoshi Shimokawa 83317821895SHidetoshi Shimokawa fwb->xfer = xfer; 83417821895SHidetoshi Shimokawa err = fw_bindadd(sc->fc, fwb); 83517821895SHidetoshi Shimokawa break; 83617821895SHidetoshi Shimokawa case FW_GDEVLST: 837c547b896SHidetoshi Shimokawa i = len = 1; 838c547b896SHidetoshi Shimokawa /* myself */ 839c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[0]; 840c547b896SHidetoshi Shimokawa devinfo->dst = sc->fc->nodeid; 841c547b896SHidetoshi Shimokawa devinfo->status = 0; /* XXX */ 842c547b896SHidetoshi Shimokawa devinfo->eui.hi = sc->fc->eui.hi; 843c547b896SHidetoshi Shimokawa devinfo->eui.lo = sc->fc->eui.lo; 8440981f5f0SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 845c547b896SHidetoshi Shimokawa if(len < FW_MAX_DEVLST){ 846c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[len++]; 847c547b896SHidetoshi Shimokawa devinfo->dst = fwdev->dst; 848c547b896SHidetoshi Shimokawa devinfo->status = 849c547b896SHidetoshi Shimokawa (fwdev->status == FWDEVINVAL)?0:1; 850c547b896SHidetoshi Shimokawa devinfo->eui.hi = fwdev->eui.hi; 851c547b896SHidetoshi Shimokawa devinfo->eui.lo = fwdev->eui.lo; 85217821895SHidetoshi Shimokawa } 85317821895SHidetoshi Shimokawa i++; 85417821895SHidetoshi Shimokawa } 85517821895SHidetoshi Shimokawa fwdevlst->n = i; 856c547b896SHidetoshi Shimokawa fwdevlst->info_len = len; 85717821895SHidetoshi Shimokawa break; 85817821895SHidetoshi Shimokawa case FW_GTPMAP: 85917821895SHidetoshi Shimokawa bcopy(sc->fc->topology_map, data, 86017821895SHidetoshi Shimokawa (sc->fc->topology_map->crc_len + 1) * 4); 86117821895SHidetoshi Shimokawa break; 86217821895SHidetoshi Shimokawa case FW_GCROM: 8630981f5f0SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 8640981f5f0SHidetoshi Shimokawa if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 86517821895SHidetoshi Shimokawa break; 86617821895SHidetoshi Shimokawa if (fwdev == NULL) { 86717821895SHidetoshi Shimokawa err = FWNODE_INVAL; 86817821895SHidetoshi Shimokawa break; 86917821895SHidetoshi Shimokawa } 87017821895SHidetoshi Shimokawa #if 0 87117821895SHidetoshi Shimokawa if (fwdev->csrrom[0] >> 24 == 1) 87217821895SHidetoshi Shimokawa len = 4; 87317821895SHidetoshi Shimokawa else 87417821895SHidetoshi Shimokawa len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 87517821895SHidetoshi Shimokawa #else 87617821895SHidetoshi Shimokawa if (fwdev->rommax < CSRROMOFF) 87717821895SHidetoshi Shimokawa len = 0; 87817821895SHidetoshi Shimokawa else 87917821895SHidetoshi Shimokawa len = fwdev->rommax - CSRROMOFF + 4; 88017821895SHidetoshi Shimokawa #endif 88117821895SHidetoshi Shimokawa if (crom_buf->len < len) 88217821895SHidetoshi Shimokawa len = crom_buf->len; 88317821895SHidetoshi Shimokawa else 88417821895SHidetoshi Shimokawa crom_buf->len = len; 88517821895SHidetoshi Shimokawa err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 88617821895SHidetoshi Shimokawa break; 88717821895SHidetoshi Shimokawa default: 88817821895SHidetoshi Shimokawa sc->fc->ioctl (dev, cmd, data, flag, td); 88917821895SHidetoshi Shimokawa break; 89017821895SHidetoshi Shimokawa } 89117821895SHidetoshi Shimokawa return err; 89217821895SHidetoshi Shimokawa } 89317821895SHidetoshi Shimokawa int 89417821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td) 89517821895SHidetoshi Shimokawa { 89617821895SHidetoshi Shimokawa int revents; 89717821895SHidetoshi Shimokawa int tmp; 89817821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 89917821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 90017821895SHidetoshi Shimokawa struct firewire_softc *sc; 90117821895SHidetoshi Shimokawa 90217821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 90317821895SHidetoshi Shimokawa return fwmem_poll(dev, events, td); 90417821895SHidetoshi Shimokawa 90517821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 90617821895SHidetoshi Shimokawa revents = 0; 90717821895SHidetoshi Shimokawa tmp = POLLIN | POLLRDNORM; 90817821895SHidetoshi Shimokawa if (events & tmp) { 90917821895SHidetoshi Shimokawa if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 91017821895SHidetoshi Shimokawa revents |= tmp; 91117821895SHidetoshi Shimokawa else 91217821895SHidetoshi Shimokawa selrecord(td, &sc->fc->ir[sub]->rsel); 91317821895SHidetoshi Shimokawa } 91417821895SHidetoshi Shimokawa tmp = POLLOUT | POLLWRNORM; 91517821895SHidetoshi Shimokawa if (events & tmp) { 91617821895SHidetoshi Shimokawa /* XXX should be fixed */ 91717821895SHidetoshi Shimokawa revents |= tmp; 91817821895SHidetoshi Shimokawa } 91917821895SHidetoshi Shimokawa 92017821895SHidetoshi Shimokawa return revents; 92117821895SHidetoshi Shimokawa } 92217821895SHidetoshi Shimokawa 92317821895SHidetoshi Shimokawa static int 92417821895SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 92517821895SHidetoshi Shimokawa { 92617821895SHidetoshi Shimokawa struct firewire_softc *fc; 92717821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 92817821895SHidetoshi Shimokawa 92917821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 93017821895SHidetoshi Shimokawa return fwmem_mmap(dev, offset, nproto); 93117821895SHidetoshi Shimokawa 93217821895SHidetoshi Shimokawa fc = devclass_get_softc(firewire_devclass, unit); 93317821895SHidetoshi Shimokawa 93417821895SHidetoshi Shimokawa return EINVAL; 93517821895SHidetoshi Shimokawa } 936