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> 5517821895SHidetoshi Shimokawa 5617821895SHidetoshi Shimokawa #define CDEV_MAJOR 127 5717821895SHidetoshi Shimokawa #define FWNODE_INVAL 0xffff 5817821895SHidetoshi Shimokawa 5917821895SHidetoshi Shimokawa static d_open_t fw_open; 6017821895SHidetoshi Shimokawa static d_close_t fw_close; 6117821895SHidetoshi Shimokawa static d_ioctl_t fw_ioctl; 6217821895SHidetoshi Shimokawa static d_poll_t fw_poll; 6317821895SHidetoshi Shimokawa static d_read_t fw_read; /* for Isochronous packet */ 6417821895SHidetoshi Shimokawa static d_write_t fw_write; 6517821895SHidetoshi Shimokawa static d_mmap_t fw_mmap; 6617821895SHidetoshi Shimokawa 6717821895SHidetoshi Shimokawa struct cdevsw firewire_cdevsw = 6817821895SHidetoshi Shimokawa { 6917821895SHidetoshi Shimokawa fw_open, fw_close, fw_read, fw_write, fw_ioctl, 7017821895SHidetoshi Shimokawa fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 7117821895SHidetoshi Shimokawa }; 7217821895SHidetoshi Shimokawa 7317821895SHidetoshi Shimokawa static int 7417821895SHidetoshi Shimokawa fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 7517821895SHidetoshi Shimokawa { 7617821895SHidetoshi Shimokawa struct firewire_softc *sc; 7717821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 7817821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 7917821895SHidetoshi Shimokawa 8017821895SHidetoshi Shimokawa int err = 0; 8117821895SHidetoshi Shimokawa 8217821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 8317821895SHidetoshi Shimokawa return fwmem_open(dev, flags, fmt, td); 8417821895SHidetoshi Shimokawa 8517821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 8617821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 8717821895SHidetoshi Shimokawa err = EBUSY; 8817821895SHidetoshi Shimokawa return err; 8917821895SHidetoshi Shimokawa } 9017821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 9117821895SHidetoshi Shimokawa err = EBUSY; 9217821895SHidetoshi Shimokawa return err; 9317821895SHidetoshi Shimokawa } 9417821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 9517821895SHidetoshi Shimokawa err = EBUSY; 9617821895SHidetoshi Shimokawa return err; 9717821895SHidetoshi Shimokawa } 9817821895SHidetoshi Shimokawa /* Default is per packet mode */ 9917821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 10017821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 10117821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 10217821895SHidetoshi Shimokawa return err; 10317821895SHidetoshi Shimokawa } 10417821895SHidetoshi Shimokawa 10517821895SHidetoshi Shimokawa static int 10617821895SHidetoshi Shimokawa fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 10717821895SHidetoshi Shimokawa { 10817821895SHidetoshi Shimokawa struct firewire_softc *sc; 10917821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 11017821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 11117821895SHidetoshi Shimokawa struct fw_xfer *xfer; 11217821895SHidetoshi Shimokawa struct fw_dvbuf *dvbuf; 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 } 13817821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 13917821895SHidetoshi Shimokawa if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 14017821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 14117821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 14217821895SHidetoshi Shimokawa } 14317821895SHidetoshi Shimokawa if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 14417821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 14517821895SHidetoshi Shimokawa sc->fc->it[sub]->dvdma = NULL; 14617821895SHidetoshi Shimokawa } 14717821895SHidetoshi Shimokawa while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 14817821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 14917821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 15017821895SHidetoshi Shimokawa } 15117821895SHidetoshi Shimokawa while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 15217821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 15317821895SHidetoshi Shimokawa free(dvbuf->buf, M_DEVBUF); 15417821895SHidetoshi Shimokawa } 15517821895SHidetoshi Shimokawa free(sc->fc->it[sub]->dvbuf, M_DEVBUF); 15617821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 15717821895SHidetoshi Shimokawa } 15817821895SHidetoshi Shimokawa if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 15917821895SHidetoshi Shimokawa free(sc->fc->ir[sub]->buf, M_DEVBUF); 16017821895SHidetoshi Shimokawa sc->fc->ir[sub]->buf = NULL; 16117821895SHidetoshi Shimokawa free(sc->fc->ir[sub]->bulkxfer, M_DEVBUF); 16217821895SHidetoshi Shimokawa sc->fc->ir[sub]->bulkxfer = NULL; 16317821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 16417821895SHidetoshi Shimokawa sc->fc->ir[sub]->psize = FWPMAX_S400; 16517821895SHidetoshi Shimokawa sc->fc->ir[sub]->maxq = FWMAXQUEUE; 16617821895SHidetoshi Shimokawa } 16717821895SHidetoshi Shimokawa if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 16817821895SHidetoshi Shimokawa free(sc->fc->it[sub]->buf, M_DEVBUF); 16917821895SHidetoshi Shimokawa sc->fc->it[sub]->buf = NULL; 17017821895SHidetoshi Shimokawa free(sc->fc->it[sub]->bulkxfer, M_DEVBUF); 17117821895SHidetoshi Shimokawa sc->fc->it[sub]->bulkxfer = NULL; 17217821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf = NULL; 17317821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 17417821895SHidetoshi Shimokawa sc->fc->it[sub]->psize = FWPMAX_S400; 17517821895SHidetoshi Shimokawa sc->fc->it[sub]->maxq = FWMAXQUEUE; 17617821895SHidetoshi Shimokawa } 17717821895SHidetoshi Shimokawa for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 17817821895SHidetoshi Shimokawa xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 17917821895SHidetoshi Shimokawa sc->fc->ir[sub]->queued--; 18017821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 18117821895SHidetoshi Shimokawa 18217821895SHidetoshi Shimokawa xfer->resp = 0; 18317821895SHidetoshi Shimokawa switch(xfer->act_type){ 18417821895SHidetoshi Shimokawa case FWACT_XFER: 18517821895SHidetoshi Shimokawa fw_xfer_done(xfer); 18617821895SHidetoshi Shimokawa break; 18717821895SHidetoshi Shimokawa default: 18817821895SHidetoshi Shimokawa break; 18917821895SHidetoshi Shimokawa } 19017821895SHidetoshi Shimokawa fw_xfer_free(xfer); 19117821895SHidetoshi Shimokawa } 19217821895SHidetoshi Shimokawa for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 19317821895SHidetoshi Shimokawa fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 19417821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 19517821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 19617821895SHidetoshi Shimokawa free(fwb, M_DEVBUF); 19717821895SHidetoshi Shimokawa } 19817821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 19917821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 20017821895SHidetoshi Shimokawa return err; 20117821895SHidetoshi Shimokawa } 20217821895SHidetoshi Shimokawa 20317821895SHidetoshi Shimokawa /* 20417821895SHidetoshi Shimokawa * read request. 20517821895SHidetoshi Shimokawa */ 20617821895SHidetoshi Shimokawa static int 20717821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag) 20817821895SHidetoshi Shimokawa { 20917821895SHidetoshi Shimokawa struct firewire_softc *sc; 21017821895SHidetoshi Shimokawa struct fw_xferq *ir; 21117821895SHidetoshi Shimokawa struct fw_xfer *xfer; 21217821895SHidetoshi Shimokawa int err = 0, s, slept = 0; 21317821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 21417821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 21517821895SHidetoshi Shimokawa struct fw_pkt *fp; 21617821895SHidetoshi Shimokawa 21717821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 21817821895SHidetoshi Shimokawa return fwmem_read(dev, uio, ioflag); 21917821895SHidetoshi Shimokawa 22017821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 22117821895SHidetoshi Shimokawa 22217821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 22317821895SHidetoshi Shimokawa 22417821895SHidetoshi Shimokawa if(ir->flag & FWXFERQ_PACKET){ 22517821895SHidetoshi Shimokawa ir->stproc = NULL; 22617821895SHidetoshi Shimokawa } 22717821895SHidetoshi Shimokawa readloop: 22817821895SHidetoshi Shimokawa xfer = STAILQ_FIRST(&ir->q); 22917821895SHidetoshi Shimokawa if(!(ir->flag & FWXFERQ_PACKET) && ir->stproc == NULL){ 23017821895SHidetoshi Shimokawa ir->stproc = STAILQ_FIRST(&ir->stvalid); 23117821895SHidetoshi Shimokawa if(ir->stproc != NULL){ 23217821895SHidetoshi Shimokawa s = splfw(); 23317821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stvalid, link); 23417821895SHidetoshi Shimokawa splx(s); 23517821895SHidetoshi Shimokawa ir->queued = 0; 23617821895SHidetoshi Shimokawa } 23717821895SHidetoshi Shimokawa } 23817821895SHidetoshi Shimokawa 23917821895SHidetoshi Shimokawa if(xfer == NULL && ir->stproc == NULL){ 24017821895SHidetoshi Shimokawa if(slept == 0){ 24117821895SHidetoshi Shimokawa slept = 1; 24217821895SHidetoshi Shimokawa if(!(ir->flag & FWXFERQ_RUNNING) 24317821895SHidetoshi Shimokawa && (ir->flag & FWXFERQ_PACKET)){ 24417821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 24517821895SHidetoshi Shimokawa } 24617821895SHidetoshi Shimokawa if(err){ 24717821895SHidetoshi Shimokawa return err; 24817821895SHidetoshi Shimokawa } 24917821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_WAKEUP; 25017821895SHidetoshi Shimokawa err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz); 25117821895SHidetoshi Shimokawa if(err){ 25217821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_WAKEUP; 25317821895SHidetoshi Shimokawa return err; 25417821895SHidetoshi Shimokawa } 25517821895SHidetoshi Shimokawa goto readloop; 25617821895SHidetoshi Shimokawa }else{ 25717821895SHidetoshi Shimokawa err = EIO; 25817821895SHidetoshi Shimokawa return err; 25917821895SHidetoshi Shimokawa } 26017821895SHidetoshi Shimokawa }else if(xfer != NULL){ 26117821895SHidetoshi Shimokawa s = splfw(); 26217821895SHidetoshi Shimokawa ir->queued --; 26317821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->q, link); 26417821895SHidetoshi Shimokawa splx(s); 26517821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 26617821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 26717821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 26817821895SHidetoshi Shimokawa err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 26917821895SHidetoshi Shimokawa fw_xfer_free( xfer); 27017821895SHidetoshi Shimokawa }else if(ir->stproc != NULL){ 27117821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 27217821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 27317821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 27417821895SHidetoshi Shimokawa if(ntohs(fp->mode.stream.len) == 0){ 27517821895SHidetoshi Shimokawa err = EIO; 27617821895SHidetoshi Shimokawa return err; 27717821895SHidetoshi Shimokawa } 27817821895SHidetoshi Shimokawa err = uiomove((caddr_t)fp, ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 27917821895SHidetoshi Shimokawa fp->mode.stream.len = 0; 28017821895SHidetoshi Shimokawa ir->queued ++; 28117821895SHidetoshi Shimokawa if(ir->queued >= ir->bnpacket){ 28217821895SHidetoshi Shimokawa s = splfw(); 28317821895SHidetoshi Shimokawa ir->stproc->flag = 0; 28417821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 28517821895SHidetoshi Shimokawa splx(s); 28617821895SHidetoshi Shimokawa ir->stproc = NULL; 28717821895SHidetoshi Shimokawa } 28817821895SHidetoshi Shimokawa } 28917821895SHidetoshi Shimokawa #if 0 29017821895SHidetoshi Shimokawa if(STAILQ_FIRST(&ir->q) == NULL && 29117821895SHidetoshi Shimokawa (ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){ 29217821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 29317821895SHidetoshi Shimokawa } 29417821895SHidetoshi Shimokawa #endif 29517821895SHidetoshi Shimokawa #if 0 29617821895SHidetoshi Shimokawa if(STAILQ_FIRST(&ir->stvalid) == NULL && 29717821895SHidetoshi Shimokawa (ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){ 29817821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 29917821895SHidetoshi Shimokawa } 30017821895SHidetoshi Shimokawa #endif 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 it->stproc->flag = 0; 35717821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 35817821895SHidetoshi Shimokawa splx(s); 35917821895SHidetoshi Shimokawa it->stproc = NULL; 36017821895SHidetoshi Shimokawa } 36117821895SHidetoshi Shimokawa if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 36217821895SHidetoshi Shimokawa isoloop: 36317821895SHidetoshi Shimokawa if(it->stproc == NULL){ 36417821895SHidetoshi Shimokawa it->stproc = STAILQ_FIRST(&it->stfree); 36517821895SHidetoshi Shimokawa if(it->stproc != NULL){ 36617821895SHidetoshi Shimokawa s = splfw(); 36717821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stfree, link); 36817821895SHidetoshi Shimokawa splx(s); 36917821895SHidetoshi Shimokawa it->queued = 0; 37017821895SHidetoshi Shimokawa }else if(slept == 0){ 37117821895SHidetoshi Shimokawa slept = 1; 37217821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 37317821895SHidetoshi Shimokawa if(err){ 37417821895SHidetoshi Shimokawa return err; 37517821895SHidetoshi Shimokawa } 37617821895SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 37717821895SHidetoshi Shimokawa if(err){ 37817821895SHidetoshi Shimokawa return err; 37917821895SHidetoshi Shimokawa } 38017821895SHidetoshi Shimokawa goto isoloop; 38117821895SHidetoshi Shimokawa }else{ 38217821895SHidetoshi Shimokawa err = EIO; 38317821895SHidetoshi Shimokawa return err; 38417821895SHidetoshi Shimokawa } 38517821895SHidetoshi Shimokawa } 38617821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize); 38717821895SHidetoshi Shimokawa fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 38817821895SHidetoshi Shimokawa err = uiomove(it->stproc->buf + it->queued * it->psize, 38917821895SHidetoshi Shimokawa uio->uio_resid, uio); 39017821895SHidetoshi Shimokawa it->queued ++; 39117821895SHidetoshi Shimokawa if(it->queued >= it->btpacket){ 39217821895SHidetoshi Shimokawa s = splfw(); 39317821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 39417821895SHidetoshi Shimokawa splx(s); 39517821895SHidetoshi Shimokawa it->stproc = NULL; 39617821895SHidetoshi Shimokawa fw_tbuf_update(sc->fc, sub, 0); 39717821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 39817821895SHidetoshi Shimokawa } 39917821895SHidetoshi Shimokawa return err; 40017821895SHidetoshi Shimokawa } if(xferq == NULL && it->flag & FWXFERQ_DV){ 40117821895SHidetoshi Shimokawa dvloop: 40217821895SHidetoshi Shimokawa if(it->dvproc == NULL){ 40317821895SHidetoshi Shimokawa it->dvproc = STAILQ_FIRST(&it->dvfree); 40417821895SHidetoshi Shimokawa if(it->dvproc != NULL){ 40517821895SHidetoshi Shimokawa s = splfw(); 40617821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->dvfree, link); 40717821895SHidetoshi Shimokawa splx(s); 40817821895SHidetoshi Shimokawa it->dvptr = 0; 40917821895SHidetoshi Shimokawa }else if(slept == 0){ 41017821895SHidetoshi Shimokawa slept = 1; 41117821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 41217821895SHidetoshi Shimokawa if(err){ 41317821895SHidetoshi Shimokawa return err; 41417821895SHidetoshi Shimokawa } 41517821895SHidetoshi Shimokawa err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 41617821895SHidetoshi Shimokawa if(err){ 41717821895SHidetoshi Shimokawa return err; 41817821895SHidetoshi Shimokawa } 41917821895SHidetoshi Shimokawa goto dvloop; 42017821895SHidetoshi Shimokawa }else{ 42117821895SHidetoshi Shimokawa err = EIO; 42217821895SHidetoshi Shimokawa return err; 42317821895SHidetoshi Shimokawa } 42417821895SHidetoshi Shimokawa } 42517821895SHidetoshi Shimokawa fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 42617821895SHidetoshi Shimokawa fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 42717821895SHidetoshi Shimokawa err = uiomove(it->dvproc->buf + it->dvptr, 42817821895SHidetoshi Shimokawa uio->uio_resid, uio); 42917821895SHidetoshi Shimokawa it->dvptr += it->psize; 43017821895SHidetoshi Shimokawa if(err){ 43117821895SHidetoshi Shimokawa return err; 43217821895SHidetoshi Shimokawa } 43317821895SHidetoshi Shimokawa if(it->dvptr >= it->psize * it->dvpacket){ 43417821895SHidetoshi Shimokawa s = splfw(); 43517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 43617821895SHidetoshi Shimokawa splx(s); 43717821895SHidetoshi Shimokawa it->dvproc = NULL; 43817821895SHidetoshi Shimokawa err = fw_tbuf_update(sc->fc, sub, 0); 43917821895SHidetoshi Shimokawa if(err){ 44017821895SHidetoshi Shimokawa return err; 44117821895SHidetoshi Shimokawa } 44217821895SHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, sub); 44317821895SHidetoshi Shimokawa } 44417821895SHidetoshi Shimokawa return err; 44517821895SHidetoshi Shimokawa } 44617821895SHidetoshi Shimokawa if(xferq != NULL){ 44717821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 44817821895SHidetoshi Shimokawa if(xfer == NULL){ 44917821895SHidetoshi Shimokawa err = ENOMEM; 45017821895SHidetoshi Shimokawa return err; 45117821895SHidetoshi Shimokawa } 45217821895SHidetoshi Shimokawa xfer->send.buf = malloc(uio->uio_resid, M_DEVBUF, M_NOWAIT); 45317821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 45417821895SHidetoshi Shimokawa fw_xfer_free( xfer); 45517821895SHidetoshi Shimokawa err = ENOBUFS; 45617821895SHidetoshi Shimokawa return err; 45717821895SHidetoshi Shimokawa } 45817821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 45917821895SHidetoshi Shimokawa #if 0 46017821895SHidetoshi Shimokawa switch(fp->mode.common.tcode){ 46117821895SHidetoshi Shimokawa case FWTCODE_WREQQ: 46217821895SHidetoshi Shimokawa case FWTCODE_WREQB: 46317821895SHidetoshi Shimokawa if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 46417821895SHidetoshi Shimokawa fw_xfer_free( xfer); 46517821895SHidetoshi Shimokawa err = EAGAIN; 46617821895SHidetoshi Shimokawa return err; 46717821895SHidetoshi Shimokawa } 46817821895SHidetoshi Shimokawa fp->mode.hdr.tlrt = tl << 2; 46917821895SHidetoshi Shimokawa default: 47017821895SHidetoshi Shimokawa break; 47117821895SHidetoshi Shimokawa } 47217821895SHidetoshi Shimokawa 47317821895SHidetoshi Shimokawa xfer->tl = fp->mode.hdr.tlrt >> 2; 47417821895SHidetoshi Shimokawa xfer->tcode = fp->mode.common.tcode; 47517821895SHidetoshi Shimokawa xfer->fc = fc; 47617821895SHidetoshi Shimokawa xfer->q = xferq; 47717821895SHidetoshi Shimokawa xfer->act_type = FWACT_XFER; 47817821895SHidetoshi Shimokawa xfer->retry_req = fw_asybusy; 47917821895SHidetoshi Shimokawa #endif 48017821895SHidetoshi Shimokawa xfer->send.len = uio->uio_resid; 48117821895SHidetoshi Shimokawa xfer->send.off = 0; 48217821895SHidetoshi Shimokawa xfer->spd = 0;/* XXX: how to setup it */ 48317821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 48417821895SHidetoshi Shimokawa 48517821895SHidetoshi Shimokawa err = uiomove(xfer->send.buf, uio->uio_resid, uio); 48617821895SHidetoshi Shimokawa if(err){ 48717821895SHidetoshi Shimokawa fw_xfer_free( xfer); 48817821895SHidetoshi Shimokawa return err; 48917821895SHidetoshi Shimokawa } 49017821895SHidetoshi Shimokawa #if 0 49117821895SHidetoshi Shimokawa fw_asystart(xfer); 49217821895SHidetoshi Shimokawa #else 49317821895SHidetoshi Shimokawa fw_asyreq(fc, -1, xfer); 49417821895SHidetoshi Shimokawa #endif 49517821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz); 49617821895SHidetoshi Shimokawa if(xfer->resp == EBUSY) 49717821895SHidetoshi Shimokawa return EBUSY; 49817821895SHidetoshi Shimokawa fw_xfer_free( xfer); 49917821895SHidetoshi Shimokawa return err; 50017821895SHidetoshi Shimokawa } 50117821895SHidetoshi Shimokawa return EINVAL; 50217821895SHidetoshi Shimokawa } 50317821895SHidetoshi Shimokawa 50417821895SHidetoshi Shimokawa /* 50517821895SHidetoshi Shimokawa * ioctl support. 50617821895SHidetoshi Shimokawa */ 50717821895SHidetoshi Shimokawa int 50817821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 50917821895SHidetoshi Shimokawa { 51017821895SHidetoshi Shimokawa struct firewire_softc *sc; 51117821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 51217821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 51317821895SHidetoshi Shimokawa int i, len, err = 0; 51417821895SHidetoshi Shimokawa struct fw_device *fwdev; 51517821895SHidetoshi Shimokawa struct fw_bind *fwb; 51617821895SHidetoshi Shimokawa struct fw_xferq *ir, *it; 51717821895SHidetoshi Shimokawa struct fw_xfer *xfer; 51817821895SHidetoshi Shimokawa struct fw_pkt *fp; 51917821895SHidetoshi Shimokawa 52017821895SHidetoshi Shimokawa struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 52117821895SHidetoshi Shimokawa struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 52217821895SHidetoshi Shimokawa struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 52317821895SHidetoshi Shimokawa struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 52417821895SHidetoshi Shimokawa struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 52517821895SHidetoshi Shimokawa #if 0 52617821895SHidetoshi Shimokawa struct fw_map_buf *map_buf = (struct fw_map_buf *)data; 52717821895SHidetoshi Shimokawa #endif 52817821895SHidetoshi Shimokawa struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 52917821895SHidetoshi Shimokawa 53017821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 53117821895SHidetoshi Shimokawa return fwmem_ioctl(dev, cmd, data, flag, td); 53217821895SHidetoshi Shimokawa 53317821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 53417821895SHidetoshi Shimokawa if (!data) 53517821895SHidetoshi Shimokawa return(EINVAL); 53617821895SHidetoshi Shimokawa 53717821895SHidetoshi Shimokawa switch (cmd) { 53817821895SHidetoshi Shimokawa case FW_STSTREAM: 53917821895SHidetoshi Shimokawa sc->fc->it[sub]->flag &= ~0xff; 54017821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 54117821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 54217821895SHidetoshi Shimokawa err = 0; 54317821895SHidetoshi Shimokawa break; 54417821895SHidetoshi Shimokawa case FW_GTSTREAM: 54517821895SHidetoshi Shimokawa ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 54617821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 54717821895SHidetoshi Shimokawa err = 0; 54817821895SHidetoshi Shimokawa break; 54917821895SHidetoshi Shimokawa case FW_SRSTREAM: 55017821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag &= ~0xff; 55117821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 55217821895SHidetoshi Shimokawa sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 55317821895SHidetoshi Shimokawa err = sc->fc->irx_enable(sc->fc, sub); 55417821895SHidetoshi Shimokawa break; 55517821895SHidetoshi Shimokawa case FW_GRSTREAM: 55617821895SHidetoshi Shimokawa ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 55717821895SHidetoshi Shimokawa ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 55817821895SHidetoshi Shimokawa err = 0; 55917821895SHidetoshi Shimokawa break; 56017821895SHidetoshi Shimokawa case FW_SSTDV: 56117821895SHidetoshi Shimokawa ibufreq = (struct fw_isobufreq *) 56217821895SHidetoshi Shimokawa malloc(sizeof(struct fw_isobufreq), M_DEVBUF, M_NOWAIT); 56317821895SHidetoshi Shimokawa if(ibufreq == NULL){ 56417821895SHidetoshi Shimokawa err = ENOMEM; 56517821895SHidetoshi Shimokawa break; 56617821895SHidetoshi Shimokawa } 56717821895SHidetoshi Shimokawa #define FWDVPACKET 250 56817821895SHidetoshi Shimokawa #define FWDVPMAX 512 56917821895SHidetoshi Shimokawa ibufreq->rx.nchunk = 8; 57017821895SHidetoshi Shimokawa ibufreq->rx.npacket = 50; 57117821895SHidetoshi Shimokawa ibufreq->rx.psize = FWDVPMAX; 57217821895SHidetoshi Shimokawa 57317821895SHidetoshi Shimokawa ibufreq->tx.nchunk = 5; 57417821895SHidetoshi Shimokawa ibufreq->tx.npacket = 300; 57517821895SHidetoshi Shimokawa ibufreq->tx.psize = FWDVPMAX; 57617821895SHidetoshi Shimokawa 57717821895SHidetoshi Shimokawa err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 57817821895SHidetoshi Shimokawa sc->fc->it[sub]->dvpacket = FWDVPACKET; 57917821895SHidetoshi Shimokawa free(ibufreq, M_DEVBUF); 58017821895SHidetoshi Shimokawa /* reserve a buffer space */ 58117821895SHidetoshi Shimokawa #define NDVCHUNK 8 58217821895SHidetoshi Shimokawa sc->fc->it[sub]->dvproc = NULL; 58317821895SHidetoshi Shimokawa sc->fc->it[sub]->dvdma = NULL; 58417821895SHidetoshi Shimokawa sc->fc->it[sub]->flag |= FWXFERQ_DV; 58517821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf 58617821895SHidetoshi Shimokawa = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_DEVBUF, M_DONTWAIT); 58717821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 58817821895SHidetoshi Shimokawa STAILQ_INIT(&sc->fc->it[sub]->dvfree); 58917821895SHidetoshi Shimokawa for( i = 0 ; i < NDVCHUNK ; i++){ 59017821895SHidetoshi Shimokawa sc->fc->it[sub]->dvbuf[i].buf 59117821895SHidetoshi Shimokawa = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_DEVBUF, M_DONTWAIT); 59217821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 59317821895SHidetoshi Shimokawa &sc->fc->it[sub]->dvbuf[i], link); 59417821895SHidetoshi Shimokawa } 59517821895SHidetoshi Shimokawa break; 59617821895SHidetoshi Shimokawa case FW_SSTBUF: 59717821895SHidetoshi Shimokawa ir = sc->fc->ir[sub]; 59817821895SHidetoshi Shimokawa it = sc->fc->it[sub]; 59917821895SHidetoshi Shimokawa 60017821895SHidetoshi Shimokawa if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 60117821895SHidetoshi Shimokawa return(EBUSY); 60217821895SHidetoshi Shimokawa } 60317821895SHidetoshi Shimokawa if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 60417821895SHidetoshi Shimokawa return(EBUSY); 60517821895SHidetoshi Shimokawa } 60617821895SHidetoshi Shimokawa if((ibufreq->rx.nchunk * 60717821895SHidetoshi Shimokawa ibufreq->rx.psize * ibufreq->rx.npacket) + 60817821895SHidetoshi Shimokawa (ibufreq->tx.nchunk * 60917821895SHidetoshi Shimokawa ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 61017821895SHidetoshi Shimokawa return(EINVAL); 61117821895SHidetoshi Shimokawa } 61217821895SHidetoshi Shimokawa if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 61317821895SHidetoshi Shimokawa ibufreq->tx.nchunk > FWSTMAXCHUNK){ 61417821895SHidetoshi Shimokawa return(EINVAL); 61517821895SHidetoshi Shimokawa } 61617821895SHidetoshi Shimokawa ir->bulkxfer 61717821895SHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_DEVBUF, M_DONTWAIT); 61817821895SHidetoshi Shimokawa if(ir->bulkxfer == NULL){ 61917821895SHidetoshi Shimokawa return(ENOMEM); 62017821895SHidetoshi Shimokawa } 62117821895SHidetoshi Shimokawa it->bulkxfer 62217821895SHidetoshi Shimokawa = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_DEVBUF, M_DONTWAIT); 62317821895SHidetoshi Shimokawa if(it->bulkxfer == NULL){ 62417821895SHidetoshi Shimokawa return(ENOMEM); 62517821895SHidetoshi Shimokawa } 62617821895SHidetoshi Shimokawa ir->buf = malloc( 62717821895SHidetoshi Shimokawa ibufreq->rx.nchunk * ibufreq->rx.npacket 62817821895SHidetoshi Shimokawa * ((ibufreq->rx.psize + 3) &~3), 62917821895SHidetoshi Shimokawa M_DEVBUF, M_DONTWAIT); 63017821895SHidetoshi Shimokawa if(ir->buf == NULL){ 63117821895SHidetoshi Shimokawa free(ir->bulkxfer, M_DEVBUF); 63217821895SHidetoshi Shimokawa free(it->bulkxfer, M_DEVBUF); 63317821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 63417821895SHidetoshi Shimokawa it->bulkxfer = NULL; 63517821895SHidetoshi Shimokawa it->buf = NULL; 63617821895SHidetoshi Shimokawa return(ENOMEM); 63717821895SHidetoshi Shimokawa } 63817821895SHidetoshi Shimokawa it->buf = malloc( 63917821895SHidetoshi Shimokawa ibufreq->tx.nchunk * ibufreq->tx.npacket 64017821895SHidetoshi Shimokawa * ((ibufreq->tx.psize + 3) &~3), 64117821895SHidetoshi Shimokawa M_DEVBUF, M_DONTWAIT); 64217821895SHidetoshi Shimokawa if(it->buf == NULL){ 64317821895SHidetoshi Shimokawa free(ir->bulkxfer, M_DEVBUF); 64417821895SHidetoshi Shimokawa free(it->bulkxfer, M_DEVBUF); 64517821895SHidetoshi Shimokawa free(ir->buf, M_DEVBUF); 64617821895SHidetoshi Shimokawa ir->bulkxfer = NULL; 64717821895SHidetoshi Shimokawa it->bulkxfer = NULL; 64817821895SHidetoshi Shimokawa it->buf = NULL; 64917821895SHidetoshi Shimokawa return(ENOMEM); 65017821895SHidetoshi Shimokawa } 65117821895SHidetoshi Shimokawa 65217821895SHidetoshi Shimokawa ir->bnchunk = ibufreq->rx.nchunk; 65317821895SHidetoshi Shimokawa ir->bnpacket = ibufreq->rx.npacket; 65417821895SHidetoshi Shimokawa ir->btpacket = ibufreq->rx.npacket; 65517821895SHidetoshi Shimokawa ir->psize = (ibufreq->rx.psize + 3) & ~3; 65617821895SHidetoshi Shimokawa ir->queued = 0; 65717821895SHidetoshi Shimokawa 65817821895SHidetoshi Shimokawa it->bnchunk = ibufreq->tx.nchunk; 65917821895SHidetoshi Shimokawa it->bnpacket = ibufreq->tx.npacket; 66017821895SHidetoshi Shimokawa it->btpacket = ibufreq->tx.npacket; 66117821895SHidetoshi Shimokawa it->psize = (ibufreq->tx.psize + 3) & ~3; 66217821895SHidetoshi Shimokawa ir->queued = 0; 66317821895SHidetoshi Shimokawa it->dvdbc = 0; 66417821895SHidetoshi Shimokawa it->dvdiff = 0; 66517821895SHidetoshi Shimokawa it->dvsync = 0; 66617821895SHidetoshi Shimokawa 66717821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stvalid); 66817821895SHidetoshi Shimokawa STAILQ_INIT(&ir->stfree); 66917821895SHidetoshi Shimokawa ir->stdma = NULL; 67017821895SHidetoshi Shimokawa ir->stdma2 = NULL; 67117821895SHidetoshi Shimokawa ir->stproc = NULL; 67217821895SHidetoshi Shimokawa 67317821895SHidetoshi Shimokawa STAILQ_INIT(&it->stvalid); 67417821895SHidetoshi Shimokawa STAILQ_INIT(&it->stfree); 67517821895SHidetoshi Shimokawa it->stdma = NULL; 67617821895SHidetoshi Shimokawa it->stdma2 = NULL; 67717821895SHidetoshi Shimokawa it->stproc = NULL; 67817821895SHidetoshi Shimokawa 67917821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 68017821895SHidetoshi Shimokawa ir->bulkxfer[i].buf = 68117821895SHidetoshi Shimokawa ir->buf + 68217821895SHidetoshi Shimokawa i * sc->fc->ir[sub]->bnpacket * 68317821895SHidetoshi Shimokawa sc->fc->ir[sub]->psize; 68417821895SHidetoshi Shimokawa ir->bulkxfer[i].flag = 0; 68517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, 68617821895SHidetoshi Shimokawa &ir->bulkxfer[i], link); 68717821895SHidetoshi Shimokawa ir->bulkxfer[i].npacket = ir->bnpacket; 68817821895SHidetoshi Shimokawa } 68917821895SHidetoshi Shimokawa for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 69017821895SHidetoshi Shimokawa it->bulkxfer[i].buf = 69117821895SHidetoshi Shimokawa it->buf + 69217821895SHidetoshi Shimokawa i * sc->fc->it[sub]->bnpacket * 69317821895SHidetoshi Shimokawa sc->fc->it[sub]->psize; 69417821895SHidetoshi Shimokawa it->bulkxfer[i].flag = 0; 69517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stfree, 69617821895SHidetoshi Shimokawa &it->bulkxfer[i], link); 69717821895SHidetoshi Shimokawa it->bulkxfer[i].npacket = it->bnpacket; 69817821895SHidetoshi Shimokawa } 69917821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_MODEMASK; 70017821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_STREAM; 70117821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_EXTBUF; 70217821895SHidetoshi Shimokawa 70317821895SHidetoshi Shimokawa it->flag &= ~FWXFERQ_MODEMASK; 70417821895SHidetoshi Shimokawa it->flag |= FWXFERQ_STREAM; 70517821895SHidetoshi Shimokawa it->flag |= FWXFERQ_EXTBUF; 70617821895SHidetoshi Shimokawa err = 0; 70717821895SHidetoshi Shimokawa break; 70817821895SHidetoshi Shimokawa case FW_GSTBUF: 70917821895SHidetoshi Shimokawa ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 71017821895SHidetoshi Shimokawa ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 71117821895SHidetoshi Shimokawa ibufreq->rx.psize = sc->fc->ir[sub]->psize; 71217821895SHidetoshi Shimokawa 71317821895SHidetoshi Shimokawa ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 71417821895SHidetoshi Shimokawa ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 71517821895SHidetoshi Shimokawa ibufreq->tx.psize = sc->fc->it[sub]->psize; 71617821895SHidetoshi Shimokawa break; 71717821895SHidetoshi Shimokawa case FW_ASYREQ: 71817821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 71917821895SHidetoshi Shimokawa if(xfer == NULL){ 72017821895SHidetoshi Shimokawa err = ENOMEM; 72117821895SHidetoshi Shimokawa return err; 72217821895SHidetoshi Shimokawa } 72317821895SHidetoshi Shimokawa fp = &asyreq->pkt; 72417821895SHidetoshi Shimokawa switch (asyreq->req.type) { 72517821895SHidetoshi Shimokawa case FWASREQNODE: 72617821895SHidetoshi Shimokawa xfer->dst = ntohs(fp->mode.hdr.dst); 72717821895SHidetoshi Shimokawa break; 72817821895SHidetoshi Shimokawa case FWASREQEUI: 72917821895SHidetoshi Shimokawa fwdev = fw_noderesolve(sc->fc, asyreq->req.dst.eui); 73017821895SHidetoshi Shimokawa if (fwdev == NULL) { 73117faeefcSHidetoshi Shimokawa device_printf(sc->fc->bdev, 73217faeefcSHidetoshi Shimokawa "cannot find node\n"); 73317821895SHidetoshi Shimokawa err = EINVAL; 73417821895SHidetoshi Shimokawa goto error; 73517821895SHidetoshi Shimokawa } 73617821895SHidetoshi Shimokawa xfer->dst = fwdev->dst; 73717821895SHidetoshi Shimokawa fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 73817821895SHidetoshi Shimokawa break; 73917821895SHidetoshi Shimokawa case FWASRESTL: 74017821895SHidetoshi Shimokawa /* XXX what's this? */ 74117821895SHidetoshi Shimokawa break; 74217821895SHidetoshi Shimokawa case FWASREQSTREAM: 74317821895SHidetoshi Shimokawa /* nothing to do */ 74417821895SHidetoshi Shimokawa break; 74517821895SHidetoshi Shimokawa } 74617821895SHidetoshi Shimokawa xfer->spd = asyreq->req.sped; 74717821895SHidetoshi Shimokawa xfer->send.len = asyreq->req.len; 74817821895SHidetoshi Shimokawa xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 74917821895SHidetoshi Shimokawa if(xfer->send.buf == NULL){ 75017821895SHidetoshi Shimokawa return ENOMEM; 75117821895SHidetoshi Shimokawa } 75217821895SHidetoshi Shimokawa xfer->send.off = 0; 75317821895SHidetoshi Shimokawa bcopy(fp, xfer->send.buf, xfer->send.len); 75417821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 75517821895SHidetoshi Shimokawa err = fw_asyreq(sc->fc, sub, xfer); 75617821895SHidetoshi Shimokawa if(err){ 75717821895SHidetoshi Shimokawa fw_xfer_free( xfer); 75817821895SHidetoshi Shimokawa return err; 75917821895SHidetoshi Shimokawa } 76017821895SHidetoshi Shimokawa err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz); 76117821895SHidetoshi Shimokawa if(err == 0){ 76217821895SHidetoshi Shimokawa if(asyreq->req.len >= xfer->recv.len){ 76317821895SHidetoshi Shimokawa asyreq->req.len = xfer->recv.len; 76417821895SHidetoshi Shimokawa }else{ 76517821895SHidetoshi Shimokawa err = EINVAL; 76617821895SHidetoshi Shimokawa } 76717821895SHidetoshi Shimokawa bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 76817821895SHidetoshi Shimokawa } 76917821895SHidetoshi Shimokawa error: 77017821895SHidetoshi Shimokawa fw_xfer_free( xfer); 77117821895SHidetoshi Shimokawa break; 77217821895SHidetoshi Shimokawa case FW_IBUSRST: 77317821895SHidetoshi Shimokawa sc->fc->ibr(sc->fc); 77417821895SHidetoshi Shimokawa break; 77517821895SHidetoshi Shimokawa case FW_CBINDADDR: 77617821895SHidetoshi Shimokawa fwb = fw_bindlookup(sc->fc, 77717821895SHidetoshi Shimokawa bindreq->start.hi, bindreq->start.lo); 77817821895SHidetoshi Shimokawa if(fwb == NULL){ 77917821895SHidetoshi Shimokawa err = EINVAL; 78017821895SHidetoshi Shimokawa break; 78117821895SHidetoshi Shimokawa } 78217821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 78317821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 78417821895SHidetoshi Shimokawa free(fwb, M_DEVBUF); 78517821895SHidetoshi Shimokawa break; 78617821895SHidetoshi Shimokawa case FW_SBINDADDR: 78717821895SHidetoshi Shimokawa if(bindreq->len <= 0 ){ 78817821895SHidetoshi Shimokawa err = EINVAL; 78917821895SHidetoshi Shimokawa break; 79017821895SHidetoshi Shimokawa } 79117821895SHidetoshi Shimokawa if(bindreq->start.hi > 0xffff ){ 79217821895SHidetoshi Shimokawa err = EINVAL; 79317821895SHidetoshi Shimokawa break; 79417821895SHidetoshi Shimokawa } 79517821895SHidetoshi Shimokawa fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_DONTWAIT); 79617821895SHidetoshi Shimokawa if(fwb == NULL){ 79717821895SHidetoshi Shimokawa err = ENOMEM; 79817821895SHidetoshi Shimokawa break; 79917821895SHidetoshi Shimokawa } 80017821895SHidetoshi Shimokawa fwb->start_hi = bindreq->start.hi; 80117821895SHidetoshi Shimokawa fwb->start_lo = bindreq->start.lo; 80217821895SHidetoshi Shimokawa fwb->addrlen = bindreq->len; 80317821895SHidetoshi Shimokawa 80417821895SHidetoshi Shimokawa xfer = fw_xfer_alloc(); 80517821895SHidetoshi Shimokawa if(xfer == NULL){ 80617821895SHidetoshi Shimokawa err = ENOMEM; 80717821895SHidetoshi Shimokawa return err; 80817821895SHidetoshi Shimokawa } 80917821895SHidetoshi Shimokawa xfer->act_type = FWACT_CH; 81017821895SHidetoshi Shimokawa xfer->sub = sub; 81117821895SHidetoshi Shimokawa xfer->fc = sc->fc; 81217821895SHidetoshi Shimokawa 81317821895SHidetoshi Shimokawa fwb->xfer = xfer; 81417821895SHidetoshi Shimokawa err = fw_bindadd(sc->fc, fwb); 81517821895SHidetoshi Shimokawa break; 81617821895SHidetoshi Shimokawa case FW_GDEVLST: 81717821895SHidetoshi Shimokawa i = 0; 81817821895SHidetoshi Shimokawa for(fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 81917821895SHidetoshi Shimokawa fwdev = TAILQ_NEXT(fwdev, link)){ 82017821895SHidetoshi Shimokawa if(i < fwdevlst->n){ 82117821895SHidetoshi Shimokawa fwdevlst->dst[i] = fwdev->dst; 82217821895SHidetoshi Shimokawa fwdevlst->status[i] = 82317821895SHidetoshi Shimokawa (fwdev->status == FWDEVATTACHED)?1:0; 82417821895SHidetoshi Shimokawa fwdevlst->eui[i].hi = fwdev->eui.hi; 82517821895SHidetoshi Shimokawa fwdevlst->eui[i].lo = fwdev->eui.lo; 82617821895SHidetoshi Shimokawa } 82717821895SHidetoshi Shimokawa i++; 82817821895SHidetoshi Shimokawa } 82917821895SHidetoshi Shimokawa fwdevlst->n = i; 83017821895SHidetoshi Shimokawa break; 83117821895SHidetoshi Shimokawa case FW_GTPMAP: 83217821895SHidetoshi Shimokawa bcopy(sc->fc->topology_map, data, 83317821895SHidetoshi Shimokawa (sc->fc->topology_map->crc_len + 1) * 4); 83417821895SHidetoshi Shimokawa break; 83517821895SHidetoshi Shimokawa case FW_GCROM: 83617821895SHidetoshi Shimokawa for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 83717821895SHidetoshi Shimokawa fwdev = TAILQ_NEXT(fwdev, link)) { 83817821895SHidetoshi Shimokawa if (fwdev->eui.hi == crom_buf->eui.hi && 83917821895SHidetoshi Shimokawa fwdev->eui.lo == crom_buf->eui.lo) 84017821895SHidetoshi Shimokawa break; 84117821895SHidetoshi Shimokawa } 84217821895SHidetoshi Shimokawa if (fwdev == NULL) { 84317821895SHidetoshi Shimokawa err = FWNODE_INVAL; 84417821895SHidetoshi Shimokawa break; 84517821895SHidetoshi Shimokawa } 84617821895SHidetoshi Shimokawa #if 0 84717821895SHidetoshi Shimokawa if (fwdev->csrrom[0] >> 24 == 1) 84817821895SHidetoshi Shimokawa len = 4; 84917821895SHidetoshi Shimokawa else 85017821895SHidetoshi Shimokawa len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 85117821895SHidetoshi Shimokawa #else 85217821895SHidetoshi Shimokawa if (fwdev->rommax < CSRROMOFF) 85317821895SHidetoshi Shimokawa len = 0; 85417821895SHidetoshi Shimokawa else 85517821895SHidetoshi Shimokawa len = fwdev->rommax - CSRROMOFF + 4; 85617821895SHidetoshi Shimokawa #endif 85717821895SHidetoshi Shimokawa if (crom_buf->len < len) 85817821895SHidetoshi Shimokawa len = crom_buf->len; 85917821895SHidetoshi Shimokawa else 86017821895SHidetoshi Shimokawa crom_buf->len = len; 86117821895SHidetoshi Shimokawa err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 86217821895SHidetoshi Shimokawa break; 86317821895SHidetoshi Shimokawa default: 86417821895SHidetoshi Shimokawa sc->fc->ioctl (dev, cmd, data, flag, td); 86517821895SHidetoshi Shimokawa break; 86617821895SHidetoshi Shimokawa } 86717821895SHidetoshi Shimokawa return err; 86817821895SHidetoshi Shimokawa } 86917821895SHidetoshi Shimokawa int 87017821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td) 87117821895SHidetoshi Shimokawa { 87217821895SHidetoshi Shimokawa int revents; 87317821895SHidetoshi Shimokawa int tmp; 87417821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 87517821895SHidetoshi Shimokawa int sub = DEV2DMACH(dev); 87617821895SHidetoshi Shimokawa struct firewire_softc *sc; 87717821895SHidetoshi Shimokawa 87817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 87917821895SHidetoshi Shimokawa return fwmem_poll(dev, events, td); 88017821895SHidetoshi Shimokawa 88117821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 88217821895SHidetoshi Shimokawa revents = 0; 88317821895SHidetoshi Shimokawa tmp = POLLIN | POLLRDNORM; 88417821895SHidetoshi Shimokawa if (events & tmp) { 88517821895SHidetoshi Shimokawa if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 88617821895SHidetoshi Shimokawa revents |= tmp; 88717821895SHidetoshi Shimokawa else 88817821895SHidetoshi Shimokawa selrecord(td, &sc->fc->ir[sub]->rsel); 88917821895SHidetoshi Shimokawa } 89017821895SHidetoshi Shimokawa tmp = POLLOUT | POLLWRNORM; 89117821895SHidetoshi Shimokawa if (events & tmp) { 89217821895SHidetoshi Shimokawa /* XXX should be fixed */ 89317821895SHidetoshi Shimokawa revents |= tmp; 89417821895SHidetoshi Shimokawa } 89517821895SHidetoshi Shimokawa 89617821895SHidetoshi Shimokawa return revents; 89717821895SHidetoshi Shimokawa } 89817821895SHidetoshi Shimokawa 89917821895SHidetoshi Shimokawa static int 90017821895SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 90117821895SHidetoshi Shimokawa { 90217821895SHidetoshi Shimokawa struct firewire_softc *fc; 90317821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 90417821895SHidetoshi Shimokawa 90517821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 90617821895SHidetoshi Shimokawa return fwmem_mmap(dev, offset, nproto); 90717821895SHidetoshi Shimokawa 90817821895SHidetoshi Shimokawa fc = devclass_get_softc(firewire_devclass, unit); 90917821895SHidetoshi Shimokawa 91017821895SHidetoshi Shimokawa return EINVAL; 91117821895SHidetoshi Shimokawa } 912