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){ 14317821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 14417821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 14517821895SHidetoshi Shimokawa } 14617821895SHidetoshi Shimokawa if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 14717821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 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); 15217821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 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); 15617821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 15717821895SHidetoshi Shimokawa } 15817821895SHidetoshi Shimokawa free(sc->fc->it[sub]->dvbuf, M_DEVBUF); 15917821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 16017821895SHidetoshi Shimokawa } 1619190691bSHidetoshi Shimokawa #endif 16217821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 16317821895SHidetoshi Shimokawa free(sc->fc->ir[sub]->buf, M_DEVBUF); 16417821895SHidetoshi Shimokawa sc->fc->ir[sub]->buf = NULL; 16517821895SHidetoshi Shimokawa free(sc->fc->ir[sub]->bulkxfer, M_DEVBUF); 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){ 17217821895SHidetoshi Shimokawa free(sc->fc->it[sub]->buf, M_DEVBUF); 17317821895SHidetoshi Shimokawa sc->fc->it[sub]->buf = NULL; 17417821895SHidetoshi Shimokawa free(sc->fc->it[sub]->bulkxfer, M_DEVBUF); 17517821895SHidetoshi Shimokawa sc->fc->it[sub]->bulkxfer = NULL; 17617821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 17717821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 178e2ad5d6eSHidetoshi Shimokawa sc->fc->it[sub]->psize = 0; 17917821895SHidetoshi Shimokawa sc->fc->it[sub]->maxq = FWMAXQUEUE; 18017821895SHidetoshi Shimokawa } 18117821895SHidetoshi Shimokawa for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 18217821895SHidetoshi Shimokawa xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 18317821895SHidetoshi Shimokawa sc->fc->ir[sub]->queued--; 18417821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 18517821895SHidetoshi Shimokawa 18617821895SHidetoshi Shimokawa xfer->resp = 0; 18717821895SHidetoshi Shimokawa switch(xfer->act_type){ 18817821895SHidetoshi Shimokawa case FWACT_XFER: 18917821895SHidetoshi Shimokawa fw_xfer_done(xfer); 19017821895SHidetoshi Shimokawa break; 19117821895SHidetoshi Shimokawa default: 19217821895SHidetoshi Shimokawa break; 19317821895SHidetoshi Shimokawa } 19417821895SHidetoshi Shimokawa fw_xfer_free(xfer); 19517821895SHidetoshi Shimokawa } 19617821895SHidetoshi Shimokawa for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 19717821895SHidetoshi Shimokawa fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 19817821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 19917821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 20017821895SHidetoshi Shimokawa free(fwb, M_DEVBUF); 20117821895SHidetoshi Shimokawa } 20217821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 20317821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 20417821895SHidetoshi Shimokawa return err; 20517821895SHidetoshi Shimokawa } 20617821895SHidetoshi Shimokawa 20717821895SHidetoshi Shimokawa /* 20817821895SHidetoshi Shimokawa * read request. 20917821895SHidetoshi Shimokawa */ 21017821895SHidetoshi Shimokawa static int 21117821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag) 21217821895SHidetoshi Shimokawa { 21317821895SHidetoshi Shimokawa struct firewire_softc *sc; 21417821895SHidetoshi Shimokawa struct fw_xferq *ir; 21517821895SHidetoshi Shimokawa struct fw_xfer *xfer; 21617821895SHidetoshi Shimokawa int err = 0, s, slept = 0; 21717821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 21817821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 21917821895SHidetoshi Shimokawa struct fw_pkt *fp; 22017821895SHidetoshi Shimokawa 22117821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 22217821895SHidetoshi Shimokawa return fwmem_read(dev, uio, ioflag); 22317821895SHidetoshi Shimokawa 22417821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 22517821895SHidetoshi Shimokawa 22617821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 22717821895SHidetoshi Shimokawa 22817821895SHidetoshi Shimokawa if(ir->flag & FWXFERQ_PACKET){ 22917821895SHidetoshi Shimokawa ir->stproc = NULL; 23017821895SHidetoshi Shimokawa } 23117821895SHidetoshi Shimokawa readloop: 23217821895SHidetoshi Shimokawa xfer = STAILQ_FIRST(&ir->q); 23317821895SHidetoshi Shimokawa if(!(ir->flag & FWXFERQ_PACKET) && ir->stproc == NULL){ 23417821895SHidetoshi Shimokawa ir->stproc = STAILQ_FIRST(&ir->stvalid); 23517821895SHidetoshi Shimokawa if(ir->stproc != NULL){ 23617821895SHidetoshi Shimokawa s = splfw(); 23717821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stvalid, link); 23817821895SHidetoshi Shimokawa splx(s); 23917821895SHidetoshi Shimokawa ir->queued = 0; 24017821895SHidetoshi Shimokawa } 24117821895SHidetoshi Shimokawa } 24217821895SHidetoshi Shimokawa 24317821895SHidetoshi Shimokawa if(xfer == NULL && ir->stproc == NULL){ 24417821895SHidetoshi Shimokawa if(slept == 0){ 24517821895SHidetoshi Shimokawa slept = 1; 24617821895SHidetoshi Shimokawa if(!(ir->flag & FWXFERQ_RUNNING) 24717821895SHidetoshi Shimokawa && (ir->flag & FWXFERQ_PACKET)){ 24817821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 24917821895SHidetoshi Shimokawa } 25017821895SHidetoshi Shimokawa if(err){ 25117821895SHidetoshi Shimokawa return err; 25217821895SHidetoshi Shimokawa } 25317821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_WAKEUP; 25417821895SHidetoshi Shimokawa err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz); 25517821895SHidetoshi Shimokawa if(err){ 25617821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_WAKEUP; 25717821895SHidetoshi Shimokawa return err; 25817821895SHidetoshi Shimokawa } 25917821895SHidetoshi Shimokawa goto readloop; 26017821895SHidetoshi Shimokawa }else{ 26117821895SHidetoshi Shimokawa err = EIO; 26217821895SHidetoshi Shimokawa return err; 26317821895SHidetoshi Shimokawa } 26417821895SHidetoshi Shimokawa }else if(xfer != NULL){ 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){ 27517821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 27617821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 27717821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 27817821895SHidetoshi Shimokawa if(ntohs(fp->mode.stream.len) == 0){ 27917821895SHidetoshi Shimokawa err = EIO; 28017821895SHidetoshi Shimokawa return err; 28117821895SHidetoshi Shimokawa } 28217821895SHidetoshi Shimokawa err = uiomove((caddr_t)fp, ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 28317821895SHidetoshi Shimokawa fp->mode.stream.len = 0; 28417821895SHidetoshi Shimokawa ir->queued ++; 28517821895SHidetoshi Shimokawa if(ir->queued >= ir->bnpacket){ 28617821895SHidetoshi Shimokawa s = splfw(); 28717821895SHidetoshi Shimokawa ir->stproc->flag = 0; 28817821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 28917821895SHidetoshi Shimokawa splx(s); 29017821895SHidetoshi Shimokawa ir->stproc = NULL; 29117821895SHidetoshi Shimokawa } 29217821895SHidetoshi Shimokawa } 29317821895SHidetoshi Shimokawa #if 0 29417821895SHidetoshi Shimokawa if(STAILQ_FIRST(&ir->q) == NULL && 29517821895SHidetoshi Shimokawa (ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){ 29617821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 29717821895SHidetoshi Shimokawa } 29817821895SHidetoshi Shimokawa #endif 29917821895SHidetoshi Shimokawa #if 0 30017821895SHidetoshi Shimokawa if(STAILQ_FIRST(&ir->stvalid) == NULL && 30117821895SHidetoshi Shimokawa (ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){ 30217821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 30317821895SHidetoshi Shimokawa } 30417821895SHidetoshi Shimokawa #endif 30517821895SHidetoshi Shimokawa return err; 30617821895SHidetoshi Shimokawa } 30717821895SHidetoshi Shimokawa 30817821895SHidetoshi Shimokawa static int 30917821895SHidetoshi Shimokawa fw_write (dev_t dev, struct uio *uio, int ioflag) 31017821895SHidetoshi Shimokawa { 31117821895SHidetoshi Shimokawa int err = 0; 31217821895SHidetoshi Shimokawa struct firewire_softc *sc; 31317821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 31417821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 31517821895SHidetoshi Shimokawa int s, slept = 0; 31617821895SHidetoshi Shimokawa struct fw_pkt *fp; 31717821895SHidetoshi Shimokawa struct fw_xfer *xfer; 31817821895SHidetoshi Shimokawa struct fw_xferq *xferq; 31917821895SHidetoshi Shimokawa struct firewire_comm *fc; 32017821895SHidetoshi Shimokawa struct fw_xferq *it; 32117821895SHidetoshi Shimokawa 32217821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 32317821895SHidetoshi Shimokawa return fwmem_write(dev, uio, ioflag); 32417821895SHidetoshi Shimokawa 32517821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 32617821895SHidetoshi Shimokawa fc = sc->fc; 32717821895SHidetoshi Shimokawa it = sc->fc->it[sub]; 32817821895SHidetoshi Shimokawa 32917821895SHidetoshi Shimokawa fp = (struct fw_pkt *)uio->uio_iov->iov_base; 33017821895SHidetoshi Shimokawa switch(fp->mode.common.tcode){ 33117821895SHidetoshi Shimokawa case FWTCODE_RREQQ: 33217821895SHidetoshi Shimokawa case FWTCODE_RREQB: 33317821895SHidetoshi Shimokawa case FWTCODE_LREQ: 33417821895SHidetoshi Shimokawa err = EINVAL; 33517821895SHidetoshi Shimokawa return err; 33617821895SHidetoshi Shimokawa case FWTCODE_WREQQ: 33717821895SHidetoshi Shimokawa case FWTCODE_WREQB: 33817821895SHidetoshi Shimokawa xferq = fc->atq; 33917821895SHidetoshi Shimokawa break; 34017821895SHidetoshi Shimokawa case FWTCODE_STREAM: 34117821895SHidetoshi Shimokawa if(it->flag & FWXFERQ_PACKET){ 34217821895SHidetoshi Shimokawa xferq = fc->atq; 34317821895SHidetoshi Shimokawa }else{ 34417821895SHidetoshi Shimokawa xferq = NULL; 34517821895SHidetoshi Shimokawa } 34617821895SHidetoshi Shimokawa break; 34717821895SHidetoshi Shimokawa case FWTCODE_WRES: 34817821895SHidetoshi Shimokawa case FWTCODE_RRESQ: 34917821895SHidetoshi Shimokawa case FWTCODE_RRESB: 35017821895SHidetoshi Shimokawa case FWTCODE_LRES: 35117821895SHidetoshi Shimokawa xferq = fc->ats; 35217821895SHidetoshi Shimokawa break; 35317821895SHidetoshi Shimokawa default: 35417821895SHidetoshi Shimokawa err = EINVAL; 35517821895SHidetoshi Shimokawa return err; 35617821895SHidetoshi Shimokawa } 35717821895SHidetoshi Shimokawa /* Discard unsent buffered stream packet, when sending Asyrequrst */ 35817821895SHidetoshi Shimokawa if(xferq != NULL && it->stproc != NULL){ 35917821895SHidetoshi Shimokawa s = splfw(); 36017821895SHidetoshi Shimokawa it->stproc->flag = 0; 36117821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 36217821895SHidetoshi Shimokawa splx(s); 36317821895SHidetoshi Shimokawa it->stproc = NULL; 36417821895SHidetoshi Shimokawa } 3659190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 36617821895SHidetoshi Shimokawa if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 3679190691bSHidetoshi Shimokawa #else 3689190691bSHidetoshi Shimokawa if (xferq == NULL) { 3699190691bSHidetoshi Shimokawa #endif 37017821895SHidetoshi Shimokawa isoloop: 37117821895SHidetoshi Shimokawa if(it->stproc == NULL){ 37217821895SHidetoshi Shimokawa it->stproc = STAILQ_FIRST(&it->stfree); 37317821895SHidetoshi Shimokawa if(it->stproc != NULL){ 37417821895SHidetoshi Shimokawa s = splfw(); 37517821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stfree, link); 37617821895SHidetoshi Shimokawa splx(s); 37717821895SHidetoshi Shimokawa it->queued = 0; 37817821895SHidetoshi Shimokawa }else if(slept == 0){ 37917821895SHidetoshi Shimokawa slept = 1; 38017821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 38117821895SHidetoshi Shimokawa if(err){ 38217821895SHidetoshi Shimokawa return err; 38317821895SHidetoshi Shimokawa } 38417821895SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 38517821895SHidetoshi Shimokawa if(err){ 38617821895SHidetoshi Shimokawa return err; 38717821895SHidetoshi Shimokawa } 38817821895SHidetoshi Shimokawa goto isoloop; 38917821895SHidetoshi Shimokawa }else{ 39017821895SHidetoshi Shimokawa err = EIO; 39117821895SHidetoshi Shimokawa return err; 39217821895SHidetoshi Shimokawa } 39317821895SHidetoshi Shimokawa } 3940aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (overwritten by the following uiomove)*/ 39517821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize); 39617821895SHidetoshi Shimokawa fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 3970aaa9a23SHidetoshi Shimokawa #endif 39817821895SHidetoshi Shimokawa err = uiomove(it->stproc->buf + it->queued * it->psize, 39917821895SHidetoshi Shimokawa uio->uio_resid, uio); 40017821895SHidetoshi Shimokawa it->queued ++; 40117821895SHidetoshi Shimokawa if(it->queued >= it->btpacket){ 40217821895SHidetoshi Shimokawa s = splfw(); 40317821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 40417821895SHidetoshi Shimokawa splx(s); 40517821895SHidetoshi Shimokawa it->stproc = NULL; 40617821895SHidetoshi Shimokawa fw_tbuf_update(sc->fc, sub, 0); 40717821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 40817821895SHidetoshi Shimokawa } 40917821895SHidetoshi Shimokawa return err; 4109190691bSHidetoshi Shimokawa } 4119190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 4129190691bSHidetoshi Shimokawa if(xferq == NULL && it->flag & FWXFERQ_DV){ 41317821895SHidetoshi Shimokawa dvloop: 41417821895SHidetoshi Shimokawa if(it->dvproc == NULL){ 41517821895SHidetoshi Shimokawa it->dvproc = STAILQ_FIRST(&it->dvfree); 41617821895SHidetoshi Shimokawa if(it->dvproc != NULL){ 41717821895SHidetoshi Shimokawa s = splfw(); 41817821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->dvfree, link); 41917821895SHidetoshi Shimokawa splx(s); 42017821895SHidetoshi Shimokawa it->dvptr = 0; 42117821895SHidetoshi Shimokawa }else if(slept == 0){ 42217821895SHidetoshi Shimokawa slept = 1; 42317821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 42417821895SHidetoshi Shimokawa if(err){ 42517821895SHidetoshi Shimokawa return err; 42617821895SHidetoshi Shimokawa } 42717821895SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 42817821895SHidetoshi Shimokawa if(err){ 42917821895SHidetoshi Shimokawa return err; 43017821895SHidetoshi Shimokawa } 43117821895SHidetoshi Shimokawa goto dvloop; 43217821895SHidetoshi Shimokawa }else{ 43317821895SHidetoshi Shimokawa err = EIO; 43417821895SHidetoshi Shimokawa return err; 43517821895SHidetoshi Shimokawa } 43617821895SHidetoshi Shimokawa } 4370aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/ 43817821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 43917821895SHidetoshi Shimokawa fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 4400aaa9a23SHidetoshi Shimokawa #endif 44117821895SHidetoshi Shimokawa err = uiomove(it->dvproc->buf + it->dvptr, 44217821895SHidetoshi Shimokawa uio->uio_resid, uio); 44317821895SHidetoshi Shimokawa it->dvptr += it->psize; 44417821895SHidetoshi Shimokawa if(err){ 44517821895SHidetoshi Shimokawa return err; 44617821895SHidetoshi Shimokawa } 44717821895SHidetoshi Shimokawa if(it->dvptr >= it->psize * it->dvpacket){ 44817821895SHidetoshi Shimokawa s = splfw(); 44917821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 45017821895SHidetoshi Shimokawa splx(s); 45117821895SHidetoshi Shimokawa it->dvproc = NULL; 45217821895SHidetoshi Shimokawa err = fw_tbuf_update(sc->fc, sub, 0); 45317821895SHidetoshi Shimokawa if(err){ 45417821895SHidetoshi Shimokawa return err; 45517821895SHidetoshi Shimokawa } 45617821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 45717821895SHidetoshi Shimokawa } 45817821895SHidetoshi Shimokawa return err; 45917821895SHidetoshi Shimokawa } 4609190691bSHidetoshi Shimokawa #endif 46117821895SHidetoshi Shimokawa if(xferq != NULL){ 46217821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 46317821895SHidetoshi Shimokawa if(xfer == NULL){ 46417821895SHidetoshi Shimokawa err = ENOMEM; 46517821895SHidetoshi Shimokawa return err; 46617821895SHidetoshi Shimokawa } 46717821895SHidetoshi Shimokawa xfer->send.buf = malloc(uio->uio_resid, M_DEVBUF, M_NOWAIT); 46817821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 46917821895SHidetoshi Shimokawa fw_xfer_free( xfer); 47017821895SHidetoshi Shimokawa err = ENOBUFS; 47117821895SHidetoshi Shimokawa return err; 47217821895SHidetoshi Shimokawa } 47317821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 47417821895SHidetoshi Shimokawa #if 0 47517821895SHidetoshi Shimokawa switch(fp->mode.common.tcode){ 47617821895SHidetoshi Shimokawa case FWTCODE_WREQQ: 47717821895SHidetoshi Shimokawa case FWTCODE_WREQB: 47817821895SHidetoshi Shimokawa if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 47917821895SHidetoshi Shimokawa fw_xfer_free( xfer); 48017821895SHidetoshi Shimokawa err = EAGAIN; 48117821895SHidetoshi Shimokawa return err; 48217821895SHidetoshi Shimokawa } 48317821895SHidetoshi Shimokawa fp->mode.hdr.tlrt = tl << 2; 48417821895SHidetoshi Shimokawa default: 48517821895SHidetoshi Shimokawa break; 48617821895SHidetoshi Shimokawa } 48717821895SHidetoshi Shimokawa 48817821895SHidetoshi Shimokawa xfer->tl = fp->mode.hdr.tlrt >> 2; 48917821895SHidetoshi Shimokawa xfer->tcode = fp->mode.common.tcode; 49017821895SHidetoshi Shimokawa xfer->fc = fc; 49117821895SHidetoshi Shimokawa xfer->q = xferq; 49217821895SHidetoshi Shimokawa xfer->act_type = FWACT_XFER; 49317821895SHidetoshi Shimokawa xfer->retry_req = fw_asybusy; 49417821895SHidetoshi Shimokawa #endif 49517821895SHidetoshi Shimokawa xfer->send.len = uio->uio_resid; 49617821895SHidetoshi Shimokawa xfer->send.off = 0; 49717821895SHidetoshi Shimokawa xfer->spd = 0;/* XXX: how to setup it */ 49817821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 49917821895SHidetoshi Shimokawa 50017821895SHidetoshi Shimokawa err = uiomove(xfer->send.buf, uio->uio_resid, uio); 50117821895SHidetoshi Shimokawa if(err){ 50217821895SHidetoshi Shimokawa fw_xfer_free( xfer); 50317821895SHidetoshi Shimokawa return err; 50417821895SHidetoshi Shimokawa } 50517821895SHidetoshi Shimokawa #if 0 50617821895SHidetoshi Shimokawa fw_asystart(xfer); 50717821895SHidetoshi Shimokawa #else 50817821895SHidetoshi Shimokawa fw_asyreq(fc, -1, xfer); 50917821895SHidetoshi Shimokawa #endif 51017821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz); 51117821895SHidetoshi Shimokawa if(xfer->resp == EBUSY) 51217821895SHidetoshi Shimokawa return EBUSY; 51317821895SHidetoshi Shimokawa fw_xfer_free( xfer); 51417821895SHidetoshi Shimokawa return err; 51517821895SHidetoshi Shimokawa } 51617821895SHidetoshi Shimokawa return EINVAL; 51717821895SHidetoshi Shimokawa } 51817821895SHidetoshi Shimokawa 51917821895SHidetoshi Shimokawa /* 52017821895SHidetoshi Shimokawa * ioctl support. 52117821895SHidetoshi Shimokawa */ 52217821895SHidetoshi Shimokawa int 52317821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 52417821895SHidetoshi Shimokawa { 52517821895SHidetoshi Shimokawa struct firewire_softc *sc; 52617821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 52717821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 52817821895SHidetoshi Shimokawa int i, len, err = 0; 52917821895SHidetoshi Shimokawa struct fw_device *fwdev; 53017821895SHidetoshi Shimokawa struct fw_bind *fwb; 53117821895SHidetoshi Shimokawa struct fw_xferq *ir, *it; 53217821895SHidetoshi Shimokawa struct fw_xfer *xfer; 53317821895SHidetoshi Shimokawa struct fw_pkt *fp; 534c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 53517821895SHidetoshi Shimokawa 53617821895SHidetoshi Shimokawa struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 53717821895SHidetoshi Shimokawa struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 53817821895SHidetoshi Shimokawa struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 53917821895SHidetoshi Shimokawa struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 54017821895SHidetoshi Shimokawa struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 54117821895SHidetoshi Shimokawa struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 54217821895SHidetoshi Shimokawa 54317821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 54417821895SHidetoshi Shimokawa return fwmem_ioctl(dev, cmd, data, flag, td); 54517821895SHidetoshi Shimokawa 54617821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 54717821895SHidetoshi Shimokawa if (!data) 54817821895SHidetoshi Shimokawa return(EINVAL); 54917821895SHidetoshi Shimokawa 55017821895SHidetoshi Shimokawa switch (cmd) { 55117821895SHidetoshi Shimokawa case FW_STSTREAM: 55217821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~0xff; 55317821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 55417821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 55517821895SHidetoshi Shimokawa err = 0; 55617821895SHidetoshi Shimokawa break; 55717821895SHidetoshi Shimokawa case FW_GTSTREAM: 55817821895SHidetoshi Shimokawa ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 55917821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 56017821895SHidetoshi Shimokawa err = 0; 56117821895SHidetoshi Shimokawa break; 56217821895SHidetoshi Shimokawa case FW_SRSTREAM: 56317821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~0xff; 56417821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 56517821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 56617821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 56717821895SHidetoshi Shimokawa break; 56817821895SHidetoshi Shimokawa case FW_GRSTREAM: 56917821895SHidetoshi Shimokawa ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 57017821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 57117821895SHidetoshi Shimokawa err = 0; 57217821895SHidetoshi Shimokawa break; 5739190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV 57417821895SHidetoshi Shimokawa case FW_SSTDV: 57517821895SHidetoshi Shimokawa ibufreq = (struct fw_isobufreq *) 57617821895SHidetoshi Shimokawa malloc(sizeof(struct fw_isobufreq), M_DEVBUF, M_NOWAIT); 57717821895SHidetoshi Shimokawa if(ibufreq == NULL){ 57817821895SHidetoshi Shimokawa err = ENOMEM; 57917821895SHidetoshi Shimokawa break; 58017821895SHidetoshi Shimokawa } 5816d6f7f28SHidetoshi Shimokawa #if DV_PAL 5826d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 300 5836d6f7f28SHidetoshi Shimokawa #else 5846d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 250 5856d6f7f28SHidetoshi Shimokawa #endif 58617821895SHidetoshi Shimokawa #define FWDVPMAX 512 58717821895SHidetoshi Shimokawa ibufreq->rx.nchunk = 8; 58817821895SHidetoshi Shimokawa ibufreq->rx.npacket = 50; 58917821895SHidetoshi Shimokawa ibufreq->rx.psize = FWDVPMAX; 59017821895SHidetoshi Shimokawa 59117821895SHidetoshi Shimokawa ibufreq->tx.nchunk = 5; 5926d6f7f28SHidetoshi Shimokawa ibufreq->tx.npacket = FWDVPACKET + 30; /* > 320 or 267 */ 59317821895SHidetoshi Shimokawa ibufreq->tx.psize = FWDVPMAX; 59417821895SHidetoshi Shimokawa 59517821895SHidetoshi Shimokawa err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 59617821895SHidetoshi Shimokawa sc->fc->it[sub]->dvpacket = FWDVPACKET; 59717821895SHidetoshi Shimokawa free(ibufreq, M_DEVBUF); 59817821895SHidetoshi Shimokawa /* reserve a buffer space */ 59917821895SHidetoshi Shimokawa #define NDVCHUNK 8 60017821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 60117821895SHidetoshi Shimokawa sc->fc->it[sub]->dvdma = NULL; 60217821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= FWXFERQ_DV; 6030aaa9a23SHidetoshi Shimokawa /* XXX check malloc failure */ 60417821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf 605ae8c82bbSHidetoshi Shimokawa = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_DEVBUF, M_NOWAIT); 60617821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 60717821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvfree); 60817821895SHidetoshi Shimokawa for( i = 0 ; i < NDVCHUNK ; i++){ 6090aaa9a23SHidetoshi Shimokawa /* XXX check malloc failure */ 61017821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf[i].buf 611ae8c82bbSHidetoshi Shimokawa = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_DEVBUF, M_NOWAIT); 61217821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 61317821895SHidetoshi Shimokawa &sc->fc->it[sub]->dvbuf[i], link); 61417821895SHidetoshi Shimokawa } 61517821895SHidetoshi Shimokawa break; 6169190691bSHidetoshi Shimokawa #endif 61717821895SHidetoshi Shimokawa case FW_SSTBUF: 61817821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 61917821895SHidetoshi Shimokawa it = sc->fc->it[sub]; 62017821895SHidetoshi Shimokawa 62117821895SHidetoshi Shimokawa if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 62217821895SHidetoshi Shimokawa return(EBUSY); 62317821895SHidetoshi Shimokawa } 62417821895SHidetoshi Shimokawa if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 62517821895SHidetoshi Shimokawa return(EBUSY); 62617821895SHidetoshi Shimokawa } 62717821895SHidetoshi Shimokawa if((ibufreq->rx.nchunk * 62817821895SHidetoshi Shimokawa ibufreq->rx.psize * ibufreq->rx.npacket) + 62917821895SHidetoshi Shimokawa (ibufreq->tx.nchunk * 63017821895SHidetoshi Shimokawa ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 63117821895SHidetoshi Shimokawa return(EINVAL); 63217821895SHidetoshi Shimokawa } 63317821895SHidetoshi Shimokawa if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 63417821895SHidetoshi Shimokawa ibufreq->tx.nchunk > FWSTMAXCHUNK){ 63517821895SHidetoshi Shimokawa return(EINVAL); 63617821895SHidetoshi Shimokawa } 63717821895SHidetoshi Shimokawa ir->bulkxfer 638ae8c82bbSHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_DEVBUF, M_NOWAIT); 63917821895SHidetoshi Shimokawa if(ir->bulkxfer == NULL){ 64017821895SHidetoshi Shimokawa return(ENOMEM); 64117821895SHidetoshi Shimokawa } 64217821895SHidetoshi Shimokawa it->bulkxfer 643ae8c82bbSHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_DEVBUF, M_NOWAIT); 64417821895SHidetoshi Shimokawa if(it->bulkxfer == NULL){ 64517821895SHidetoshi Shimokawa return(ENOMEM); 64617821895SHidetoshi Shimokawa } 64717821895SHidetoshi Shimokawa ir->buf = malloc( 64817821895SHidetoshi Shimokawa ibufreq->rx.nchunk * ibufreq->rx.npacket 6497643dc18SHidetoshi Shimokawa /* XXX psize must be 2^n and less or 6507643dc18SHidetoshi Shimokawa equal to PAGE_SIZE */ 65117821895SHidetoshi Shimokawa * ((ibufreq->rx.psize + 3) &~3), 652ae8c82bbSHidetoshi Shimokawa M_DEVBUF, M_NOWAIT); 65317821895SHidetoshi Shimokawa if(ir->buf == NULL){ 65417821895SHidetoshi Shimokawa free(ir->bulkxfer, M_DEVBUF); 65517821895SHidetoshi Shimokawa free(it->bulkxfer, M_DEVBUF); 65617821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 65717821895SHidetoshi Shimokawa it->bulkxfer = NULL; 65817821895SHidetoshi Shimokawa it->buf = NULL; 65917821895SHidetoshi Shimokawa return(ENOMEM); 66017821895SHidetoshi Shimokawa } 66117821895SHidetoshi Shimokawa it->buf = malloc( 66217821895SHidetoshi Shimokawa ibufreq->tx.nchunk * ibufreq->tx.npacket 6637643dc18SHidetoshi Shimokawa /* XXX psize must be 2^n and less or 6647643dc18SHidetoshi Shimokawa equal to PAGE_SIZE */ 66517821895SHidetoshi Shimokawa * ((ibufreq->tx.psize + 3) &~3), 666ae8c82bbSHidetoshi Shimokawa M_DEVBUF, M_NOWAIT); 66717821895SHidetoshi Shimokawa if(it->buf == NULL){ 66817821895SHidetoshi Shimokawa free(ir->bulkxfer, M_DEVBUF); 66917821895SHidetoshi Shimokawa free(it->bulkxfer, M_DEVBUF); 67017821895SHidetoshi Shimokawa free(ir->buf, M_DEVBUF); 67117821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 67217821895SHidetoshi Shimokawa it->bulkxfer = NULL; 67317821895SHidetoshi Shimokawa it->buf = NULL; 67417821895SHidetoshi Shimokawa return(ENOMEM); 67517821895SHidetoshi Shimokawa } 67617821895SHidetoshi Shimokawa 67717821895SHidetoshi Shimokawa ir->bnchunk = ibufreq->rx.nchunk; 67817821895SHidetoshi Shimokawa ir->bnpacket = ibufreq->rx.npacket; 67917821895SHidetoshi Shimokawa ir->btpacket = ibufreq->rx.npacket; 68017821895SHidetoshi Shimokawa ir->psize = (ibufreq->rx.psize + 3) & ~3; 68117821895SHidetoshi Shimokawa ir->queued = 0; 68217821895SHidetoshi Shimokawa 68317821895SHidetoshi Shimokawa it->bnchunk = ibufreq->tx.nchunk; 68417821895SHidetoshi Shimokawa it->bnpacket = ibufreq->tx.npacket; 68517821895SHidetoshi Shimokawa it->btpacket = ibufreq->tx.npacket; 68617821895SHidetoshi Shimokawa it->psize = (ibufreq->tx.psize + 3) & ~3; 68717821895SHidetoshi Shimokawa ir->queued = 0; 68817821895SHidetoshi Shimokawa it->dvdbc = 0; 68917821895SHidetoshi Shimokawa it->dvdiff = 0; 69017821895SHidetoshi Shimokawa it->dvsync = 0; 6910aaa9a23SHidetoshi Shimokawa it->dvoffset = 0; 69217821895SHidetoshi Shimokawa 69317821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stvalid); 69417821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stfree); 69517821895SHidetoshi Shimokawa ir->stdma = NULL; 69617821895SHidetoshi Shimokawa ir->stdma2 = NULL; 69717821895SHidetoshi Shimokawa ir->stproc = NULL; 69817821895SHidetoshi Shimokawa 69917821895SHidetoshi Shimokawa STAILQ_INIT(&it->stvalid); 70017821895SHidetoshi Shimokawa STAILQ_INIT(&it->stfree); 70117821895SHidetoshi Shimokawa it->stdma = NULL; 70217821895SHidetoshi Shimokawa it->stdma2 = NULL; 70317821895SHidetoshi Shimokawa it->stproc = NULL; 70417821895SHidetoshi Shimokawa 70517821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 70617821895SHidetoshi Shimokawa ir->bulkxfer[i].buf = 70717821895SHidetoshi Shimokawa ir->buf + 70817821895SHidetoshi Shimokawa i * sc->fc->ir[sub]->bnpacket * 70917821895SHidetoshi Shimokawa sc->fc->ir[sub]->psize; 71017821895SHidetoshi Shimokawa ir->bulkxfer[i].flag = 0; 71117821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, 71217821895SHidetoshi Shimokawa &ir->bulkxfer[i], link); 71317821895SHidetoshi Shimokawa ir->bulkxfer[i].npacket = ir->bnpacket; 71417821895SHidetoshi Shimokawa } 71517821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 71617821895SHidetoshi Shimokawa it->bulkxfer[i].buf = 71717821895SHidetoshi Shimokawa it->buf + 71817821895SHidetoshi Shimokawa i * sc->fc->it[sub]->bnpacket * 71917821895SHidetoshi Shimokawa sc->fc->it[sub]->psize; 72017821895SHidetoshi Shimokawa it->bulkxfer[i].flag = 0; 72117821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, 72217821895SHidetoshi Shimokawa &it->bulkxfer[i], link); 72317821895SHidetoshi Shimokawa it->bulkxfer[i].npacket = it->bnpacket; 72417821895SHidetoshi Shimokawa } 72517821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_MODEMASK; 72617821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_STREAM; 72717821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_EXTBUF; 72817821895SHidetoshi Shimokawa 72917821895SHidetoshi Shimokawa it->flag &= ~FWXFERQ_MODEMASK; 73017821895SHidetoshi Shimokawa it->flag |= FWXFERQ_STREAM; 73117821895SHidetoshi Shimokawa it->flag |= FWXFERQ_EXTBUF; 73217821895SHidetoshi Shimokawa err = 0; 73317821895SHidetoshi Shimokawa break; 73417821895SHidetoshi Shimokawa case FW_GSTBUF: 73517821895SHidetoshi Shimokawa ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 73617821895SHidetoshi Shimokawa ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 73717821895SHidetoshi Shimokawa ibufreq->rx.psize = sc->fc->ir[sub]->psize; 73817821895SHidetoshi Shimokawa 73917821895SHidetoshi Shimokawa ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 74017821895SHidetoshi Shimokawa ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 74117821895SHidetoshi Shimokawa ibufreq->tx.psize = sc->fc->it[sub]->psize; 74217821895SHidetoshi Shimokawa break; 74317821895SHidetoshi Shimokawa case FW_ASYREQ: 74417821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 74517821895SHidetoshi Shimokawa if(xfer == NULL){ 74617821895SHidetoshi Shimokawa err = ENOMEM; 74717821895SHidetoshi Shimokawa return err; 74817821895SHidetoshi Shimokawa } 74917821895SHidetoshi Shimokawa fp = &asyreq->pkt; 75017821895SHidetoshi Shimokawa switch (asyreq->req.type) { 75117821895SHidetoshi Shimokawa case FWASREQNODE: 75217821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 75317821895SHidetoshi Shimokawa break; 75417821895SHidetoshi Shimokawa case FWASREQEUI: 75517821895SHidetoshi Shimokawa fwdev = fw_noderesolve(sc->fc, asyreq->req.dst.eui); 75617821895SHidetoshi Shimokawa if (fwdev == NULL) { 75717faeefcSHidetoshi Shimokawa device_printf(sc->fc->bdev, 75817faeefcSHidetoshi Shimokawa "cannot find node\n"); 75917821895SHidetoshi Shimokawa err = EINVAL; 76017821895SHidetoshi Shimokawa goto error; 76117821895SHidetoshi Shimokawa } 76217821895SHidetoshi Shimokawa xfer->dst = fwdev->dst; 76317821895SHidetoshi Shimokawa fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 76417821895SHidetoshi Shimokawa break; 76517821895SHidetoshi Shimokawa case FWASRESTL: 76617821895SHidetoshi Shimokawa /* XXX what's this? */ 76717821895SHidetoshi Shimokawa break; 76817821895SHidetoshi Shimokawa case FWASREQSTREAM: 76917821895SHidetoshi Shimokawa /* nothing to do */ 77017821895SHidetoshi Shimokawa break; 77117821895SHidetoshi Shimokawa } 77217821895SHidetoshi Shimokawa xfer->spd = asyreq->req.sped; 77317821895SHidetoshi Shimokawa xfer->send.len = asyreq->req.len; 77417821895SHidetoshi Shimokawa xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 77517821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 77617821895SHidetoshi Shimokawa return ENOMEM; 77717821895SHidetoshi Shimokawa } 77817821895SHidetoshi Shimokawa xfer->send.off = 0; 77917821895SHidetoshi Shimokawa bcopy(fp, xfer->send.buf, xfer->send.len); 78017821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 78117821895SHidetoshi Shimokawa err = fw_asyreq(sc->fc, sub, xfer); 78217821895SHidetoshi Shimokawa if(err){ 78317821895SHidetoshi Shimokawa fw_xfer_free( xfer); 78417821895SHidetoshi Shimokawa return err; 78517821895SHidetoshi Shimokawa } 78617821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz); 78717821895SHidetoshi Shimokawa if(err == 0){ 78817821895SHidetoshi Shimokawa if(asyreq->req.len >= xfer->recv.len){ 78917821895SHidetoshi Shimokawa asyreq->req.len = xfer->recv.len; 79017821895SHidetoshi Shimokawa }else{ 79117821895SHidetoshi Shimokawa err = EINVAL; 79217821895SHidetoshi Shimokawa } 79317821895SHidetoshi Shimokawa bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 79417821895SHidetoshi Shimokawa } 79517821895SHidetoshi Shimokawa error: 79617821895SHidetoshi Shimokawa fw_xfer_free( xfer); 79717821895SHidetoshi Shimokawa break; 79817821895SHidetoshi Shimokawa case FW_IBUSRST: 79917821895SHidetoshi Shimokawa sc->fc->ibr(sc->fc); 80017821895SHidetoshi Shimokawa break; 80117821895SHidetoshi Shimokawa case FW_CBINDADDR: 80217821895SHidetoshi Shimokawa fwb = fw_bindlookup(sc->fc, 80317821895SHidetoshi Shimokawa bindreq->start.hi, bindreq->start.lo); 80417821895SHidetoshi Shimokawa if(fwb == NULL){ 80517821895SHidetoshi Shimokawa err = EINVAL; 80617821895SHidetoshi Shimokawa break; 80717821895SHidetoshi Shimokawa } 80817821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 80917821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 81017821895SHidetoshi Shimokawa free(fwb, M_DEVBUF); 81117821895SHidetoshi Shimokawa break; 81217821895SHidetoshi Shimokawa case FW_SBINDADDR: 81317821895SHidetoshi Shimokawa if(bindreq->len <= 0 ){ 81417821895SHidetoshi Shimokawa err = EINVAL; 81517821895SHidetoshi Shimokawa break; 81617821895SHidetoshi Shimokawa } 81717821895SHidetoshi Shimokawa if(bindreq->start.hi > 0xffff ){ 81817821895SHidetoshi Shimokawa err = EINVAL; 81917821895SHidetoshi Shimokawa break; 82017821895SHidetoshi Shimokawa } 821ae8c82bbSHidetoshi Shimokawa fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_NOWAIT); 82217821895SHidetoshi Shimokawa if(fwb == NULL){ 82317821895SHidetoshi Shimokawa err = ENOMEM; 82417821895SHidetoshi Shimokawa break; 82517821895SHidetoshi Shimokawa } 82617821895SHidetoshi Shimokawa fwb->start_hi = bindreq->start.hi; 82717821895SHidetoshi Shimokawa fwb->start_lo = bindreq->start.lo; 82817821895SHidetoshi Shimokawa fwb->addrlen = bindreq->len; 82917821895SHidetoshi Shimokawa 83017821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 83117821895SHidetoshi Shimokawa if(xfer == NULL){ 83217821895SHidetoshi Shimokawa err = ENOMEM; 83317821895SHidetoshi Shimokawa return err; 83417821895SHidetoshi Shimokawa } 83517821895SHidetoshi Shimokawa xfer->act_type = FWACT_CH; 83617821895SHidetoshi Shimokawa xfer->sub = sub; 83717821895SHidetoshi Shimokawa xfer->fc = sc->fc; 83817821895SHidetoshi Shimokawa 83917821895SHidetoshi Shimokawa fwb->xfer = xfer; 84017821895SHidetoshi Shimokawa err = fw_bindadd(sc->fc, fwb); 84117821895SHidetoshi Shimokawa break; 84217821895SHidetoshi Shimokawa case FW_GDEVLST: 843c547b896SHidetoshi Shimokawa i = len = 1; 844c547b896SHidetoshi Shimokawa /* myself */ 845c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[0]; 846c547b896SHidetoshi Shimokawa devinfo->dst = sc->fc->nodeid; 847c547b896SHidetoshi Shimokawa devinfo->status = 0; /* XXX */ 848c547b896SHidetoshi Shimokawa devinfo->eui.hi = sc->fc->eui.hi; 849c547b896SHidetoshi Shimokawa devinfo->eui.lo = sc->fc->eui.lo; 85017821895SHidetoshi Shimokawa for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 85117821895SHidetoshi Shimokawa fwdev = TAILQ_NEXT(fwdev, link)) { 852c547b896SHidetoshi Shimokawa if(len < FW_MAX_DEVLST){ 853c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[len++]; 854c547b896SHidetoshi Shimokawa devinfo->dst = fwdev->dst; 855c547b896SHidetoshi Shimokawa devinfo->status = 856c547b896SHidetoshi Shimokawa (fwdev->status == FWDEVINVAL)?0:1; 857c547b896SHidetoshi Shimokawa devinfo->eui.hi = fwdev->eui.hi; 858c547b896SHidetoshi Shimokawa devinfo->eui.lo = fwdev->eui.lo; 85917821895SHidetoshi Shimokawa } 86017821895SHidetoshi Shimokawa i++; 86117821895SHidetoshi Shimokawa } 86217821895SHidetoshi Shimokawa fwdevlst->n = i; 863c547b896SHidetoshi Shimokawa fwdevlst->info_len = len; 86417821895SHidetoshi Shimokawa break; 86517821895SHidetoshi Shimokawa case FW_GTPMAP: 86617821895SHidetoshi Shimokawa bcopy(sc->fc->topology_map, data, 86717821895SHidetoshi Shimokawa (sc->fc->topology_map->crc_len + 1) * 4); 86817821895SHidetoshi Shimokawa break; 86917821895SHidetoshi Shimokawa case FW_GCROM: 87017821895SHidetoshi Shimokawa for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 87117821895SHidetoshi Shimokawa fwdev = TAILQ_NEXT(fwdev, link)) { 87217821895SHidetoshi Shimokawa if (fwdev->eui.hi == crom_buf->eui.hi && 87317821895SHidetoshi Shimokawa fwdev->eui.lo == crom_buf->eui.lo) 87417821895SHidetoshi Shimokawa break; 87517821895SHidetoshi Shimokawa } 87617821895SHidetoshi Shimokawa if (fwdev == NULL) { 87717821895SHidetoshi Shimokawa err = FWNODE_INVAL; 87817821895SHidetoshi Shimokawa break; 87917821895SHidetoshi Shimokawa } 88017821895SHidetoshi Shimokawa #if 0 88117821895SHidetoshi Shimokawa if (fwdev->csrrom[0] >> 24 == 1) 88217821895SHidetoshi Shimokawa len = 4; 88317821895SHidetoshi Shimokawa else 88417821895SHidetoshi Shimokawa len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 88517821895SHidetoshi Shimokawa #else 88617821895SHidetoshi Shimokawa if (fwdev->rommax < CSRROMOFF) 88717821895SHidetoshi Shimokawa len = 0; 88817821895SHidetoshi Shimokawa else 88917821895SHidetoshi Shimokawa len = fwdev->rommax - CSRROMOFF + 4; 89017821895SHidetoshi Shimokawa #endif 89117821895SHidetoshi Shimokawa if (crom_buf->len < len) 89217821895SHidetoshi Shimokawa len = crom_buf->len; 89317821895SHidetoshi Shimokawa else 89417821895SHidetoshi Shimokawa crom_buf->len = len; 89517821895SHidetoshi Shimokawa err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 89617821895SHidetoshi Shimokawa break; 89717821895SHidetoshi Shimokawa default: 89817821895SHidetoshi Shimokawa sc->fc->ioctl (dev, cmd, data, flag, td); 89917821895SHidetoshi Shimokawa break; 90017821895SHidetoshi Shimokawa } 90117821895SHidetoshi Shimokawa return err; 90217821895SHidetoshi Shimokawa } 90317821895SHidetoshi Shimokawa int 90417821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td) 90517821895SHidetoshi Shimokawa { 90617821895SHidetoshi Shimokawa int revents; 90717821895SHidetoshi Shimokawa int tmp; 90817821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 90917821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 91017821895SHidetoshi Shimokawa struct firewire_softc *sc; 91117821895SHidetoshi Shimokawa 91217821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 91317821895SHidetoshi Shimokawa return fwmem_poll(dev, events, td); 91417821895SHidetoshi Shimokawa 91517821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 91617821895SHidetoshi Shimokawa revents = 0; 91717821895SHidetoshi Shimokawa tmp = POLLIN | POLLRDNORM; 91817821895SHidetoshi Shimokawa if (events & tmp) { 91917821895SHidetoshi Shimokawa if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 92017821895SHidetoshi Shimokawa revents |= tmp; 92117821895SHidetoshi Shimokawa else 92217821895SHidetoshi Shimokawa selrecord(td, &sc->fc->ir[sub]->rsel); 92317821895SHidetoshi Shimokawa } 92417821895SHidetoshi Shimokawa tmp = POLLOUT | POLLWRNORM; 92517821895SHidetoshi Shimokawa if (events & tmp) { 92617821895SHidetoshi Shimokawa /* XXX should be fixed */ 92717821895SHidetoshi Shimokawa revents |= tmp; 92817821895SHidetoshi Shimokawa } 92917821895SHidetoshi Shimokawa 93017821895SHidetoshi Shimokawa return revents; 93117821895SHidetoshi Shimokawa } 93217821895SHidetoshi Shimokawa 93317821895SHidetoshi Shimokawa static int 93417821895SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 93517821895SHidetoshi Shimokawa { 93617821895SHidetoshi Shimokawa struct firewire_softc *fc; 93717821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 93817821895SHidetoshi Shimokawa 93917821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 94017821895SHidetoshi Shimokawa return fwmem_mmap(dev, offset, nproto); 94117821895SHidetoshi Shimokawa 94217821895SHidetoshi Shimokawa fc = devclass_get_softc(firewire_devclass, unit); 94317821895SHidetoshi Shimokawa 94417821895SHidetoshi Shimokawa return EINVAL; 94517821895SHidetoshi Shimokawa } 946