117821895SHidetoshi Shimokawa /* 277ee030bSHidetoshi Shimokawa * Copyright (c) 2003 Hidetoshi Shimokawa 317821895SHidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 417821895SHidetoshi Shimokawa * All rights reserved. 517821895SHidetoshi Shimokawa * 617821895SHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without 717821895SHidetoshi Shimokawa * modification, are permitted provided that the following conditions 817821895SHidetoshi Shimokawa * are met: 917821895SHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright 1017821895SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer. 1117821895SHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright 1217821895SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the 1317821895SHidetoshi Shimokawa * documentation and/or other materials provided with the distribution. 1417821895SHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software 1517821895SHidetoshi Shimokawa * must display the acknowledgement as bellow: 1617821895SHidetoshi Shimokawa * 1717821895SHidetoshi Shimokawa * This product includes software developed by K. Kobayashi and H. Shimokawa 1817821895SHidetoshi Shimokawa * 1917821895SHidetoshi Shimokawa * 4. The name of the author may not be used to endorse or promote products 2017821895SHidetoshi Shimokawa * derived from this software without specific prior written permission. 2117821895SHidetoshi Shimokawa * 2217821895SHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2317821895SHidetoshi Shimokawa * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2417821895SHidetoshi Shimokawa * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2517821895SHidetoshi Shimokawa * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2617821895SHidetoshi Shimokawa * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2717821895SHidetoshi Shimokawa * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2817821895SHidetoshi Shimokawa * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2917821895SHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3017821895SHidetoshi Shimokawa * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3117821895SHidetoshi Shimokawa * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3217821895SHidetoshi Shimokawa * POSSIBILITY OF SUCH DAMAGE. 3317821895SHidetoshi Shimokawa * 3417821895SHidetoshi Shimokawa * $FreeBSD$ 3517821895SHidetoshi Shimokawa * 3617821895SHidetoshi Shimokawa */ 3717821895SHidetoshi Shimokawa 3817821895SHidetoshi Shimokawa #include <sys/param.h> 3917821895SHidetoshi Shimokawa #include <sys/systm.h> 4017821895SHidetoshi Shimokawa #include <sys/types.h> 4117821895SHidetoshi Shimokawa #include <sys/mbuf.h> 4210d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 43c4778b5dSHidetoshi Shimokawa #include <sys/buf.h> 44c4778b5dSHidetoshi Shimokawa #else 45c4778b5dSHidetoshi Shimokawa #include <sys/bio.h> 46c4778b5dSHidetoshi Shimokawa #endif 4717821895SHidetoshi Shimokawa 4817821895SHidetoshi Shimokawa #include <sys/kernel.h> 4917821895SHidetoshi Shimokawa #include <sys/malloc.h> 5017821895SHidetoshi Shimokawa #include <sys/conf.h> 5117821895SHidetoshi Shimokawa #include <sys/poll.h> 5217821895SHidetoshi Shimokawa 5317821895SHidetoshi Shimokawa #include <sys/bus.h> 54a160e00eSHidetoshi Shimokawa #include <sys/ctype.h> 5577ee030bSHidetoshi Shimokawa #include <machine/bus.h> 5617821895SHidetoshi Shimokawa 5717821895SHidetoshi Shimokawa #include <sys/ioccom.h> 5817821895SHidetoshi Shimokawa 5910d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 6010d3ed64SHidetoshi Shimokawa #include "firewire.h" 6110d3ed64SHidetoshi Shimokawa #include "firewirereg.h" 6210d3ed64SHidetoshi Shimokawa #include "fwdma.h" 6310d3ed64SHidetoshi Shimokawa #include "fwmem.h" 6410d3ed64SHidetoshi Shimokawa #include "iec68113.h" 6510d3ed64SHidetoshi Shimokawa #else 6617821895SHidetoshi Shimokawa #include <dev/firewire/firewire.h> 6717821895SHidetoshi Shimokawa #include <dev/firewire/firewirereg.h> 6877ee030bSHidetoshi Shimokawa #include <dev/firewire/fwdma.h> 6917821895SHidetoshi Shimokawa #include <dev/firewire/fwmem.h> 706d6f7f28SHidetoshi Shimokawa #include <dev/firewire/iec68113.h> 7110d3ed64SHidetoshi Shimokawa #endif 7217821895SHidetoshi Shimokawa 7317821895SHidetoshi Shimokawa #define FWNODE_INVAL 0xffff 7417821895SHidetoshi Shimokawa 7517821895SHidetoshi Shimokawa static d_open_t fw_open; 7617821895SHidetoshi Shimokawa static d_close_t fw_close; 7717821895SHidetoshi Shimokawa static d_ioctl_t fw_ioctl; 7817821895SHidetoshi Shimokawa static d_poll_t fw_poll; 7917821895SHidetoshi Shimokawa static d_read_t fw_read; /* for Isochronous packet */ 8017821895SHidetoshi Shimokawa static d_write_t fw_write; 8117821895SHidetoshi Shimokawa static d_mmap_t fw_mmap; 82c4778b5dSHidetoshi Shimokawa static d_strategy_t fw_strategy; 8317821895SHidetoshi Shimokawa 84dc08ffecSPoul-Henning Kamp struct cdevsw firewire_cdevsw = { 8510d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 8610d3ed64SHidetoshi Shimokawa #define CDEV_MAJOR 127 8710d3ed64SHidetoshi Shimokawa "fw", CDEV_MAJOR, D_MEM, NULL, 0, 8810d3ed64SHidetoshi Shimokawa fw_open, fw_close, fw_read, fw_write, fw_ioctl, 8910d3ed64SHidetoshi Shimokawa fw_poll, fw_mmap, fw_strategy, nodump, nopsize, 9010d3ed64SHidetoshi Shimokawa #elif __FreeBSD_version >= 500104 91dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 927ac40f5fSPoul-Henning Kamp .d_open = fw_open, 937ac40f5fSPoul-Henning Kamp .d_close = fw_close, 947ac40f5fSPoul-Henning Kamp .d_read = fw_read, 957ac40f5fSPoul-Henning Kamp .d_write = fw_write, 967ac40f5fSPoul-Henning Kamp .d_ioctl = fw_ioctl, 977ac40f5fSPoul-Henning Kamp .d_poll = fw_poll, 987ac40f5fSPoul-Henning Kamp .d_mmap = fw_mmap, 99c4778b5dSHidetoshi Shimokawa .d_strategy = fw_strategy, 1007ac40f5fSPoul-Henning Kamp .d_name = "fw", 101dc08ffecSPoul-Henning Kamp .d_flags = D_MEM | D_NEEDGIANT 1022b4601d1SHidetoshi Shimokawa #else 10310d3ed64SHidetoshi Shimokawa #define CDEV_MAJOR 127 1042b4601d1SHidetoshi Shimokawa fw_open, fw_close, fw_read, fw_write, fw_ioctl, 105c4778b5dSHidetoshi Shimokawa fw_poll, fw_mmap, fw_strategy, "fw", CDEV_MAJOR, 106a160e00eSHidetoshi Shimokawa nodump, nopsize, D_MEM, -1 1072b4601d1SHidetoshi Shimokawa #endif 10817821895SHidetoshi Shimokawa }; 10917821895SHidetoshi Shimokawa 1106cada79aSHidetoshi Shimokawa struct fw_drv1 { 1116cada79aSHidetoshi Shimokawa struct fw_xferq *ir; 1126cada79aSHidetoshi Shimokawa struct fw_xferq *it; 1136cada79aSHidetoshi Shimokawa struct fw_isobufreq bufreq; 1146cada79aSHidetoshi Shimokawa }; 1156cada79aSHidetoshi Shimokawa 1166cada79aSHidetoshi Shimokawa static int 1176cada79aSHidetoshi Shimokawa fwdev_allocbuf(struct firewire_comm *fc, struct fw_xferq *q, 1186cada79aSHidetoshi Shimokawa struct fw_bufspec *b) 1196cada79aSHidetoshi Shimokawa { 1206cada79aSHidetoshi Shimokawa int i; 1216cada79aSHidetoshi Shimokawa 1226cada79aSHidetoshi Shimokawa if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF)) 1236cada79aSHidetoshi Shimokawa return(EBUSY); 1246cada79aSHidetoshi Shimokawa 1256cada79aSHidetoshi Shimokawa q->bulkxfer = (struct fw_bulkxfer *) malloc( 1266cada79aSHidetoshi Shimokawa sizeof(struct fw_bulkxfer) * b->nchunk, 1276cada79aSHidetoshi Shimokawa M_FW, M_WAITOK); 1286cada79aSHidetoshi Shimokawa if (q->bulkxfer == NULL) 1296cada79aSHidetoshi Shimokawa return(ENOMEM); 1306cada79aSHidetoshi Shimokawa 13103161bbcSDoug Rabson b->psize = roundup2(b->psize, sizeof(uint32_t)); 13203161bbcSDoug Rabson q->buf = fwdma_malloc_multiseg(fc, sizeof(uint32_t), 1336cada79aSHidetoshi Shimokawa b->psize, b->nchunk * b->npacket, BUS_DMA_WAITOK); 1346cada79aSHidetoshi Shimokawa 1356cada79aSHidetoshi Shimokawa if (q->buf == NULL) { 1366cada79aSHidetoshi Shimokawa free(q->bulkxfer, M_FW); 1376cada79aSHidetoshi Shimokawa q->bulkxfer = NULL; 1386cada79aSHidetoshi Shimokawa return(ENOMEM); 1396cada79aSHidetoshi Shimokawa } 1406cada79aSHidetoshi Shimokawa q->bnchunk = b->nchunk; 1416cada79aSHidetoshi Shimokawa q->bnpacket = b->npacket; 1426cada79aSHidetoshi Shimokawa q->psize = (b->psize + 3) & ~3; 1436cada79aSHidetoshi Shimokawa q->queued = 0; 1446cada79aSHidetoshi Shimokawa 1456cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stvalid); 1466cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stfree); 1476cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stdma); 1486cada79aSHidetoshi Shimokawa q->stproc = NULL; 1496cada79aSHidetoshi Shimokawa 1506cada79aSHidetoshi Shimokawa for(i = 0 ; i < q->bnchunk; i++){ 1516cada79aSHidetoshi Shimokawa q->bulkxfer[i].poffset = i * q->bnpacket; 1526cada79aSHidetoshi Shimokawa q->bulkxfer[i].mbuf = NULL; 1536cada79aSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&q->stfree, &q->bulkxfer[i], link); 1546cada79aSHidetoshi Shimokawa } 1556cada79aSHidetoshi Shimokawa 1566cada79aSHidetoshi Shimokawa q->flag &= ~FWXFERQ_MODEMASK; 1576cada79aSHidetoshi Shimokawa q->flag |= FWXFERQ_STREAM; 1586cada79aSHidetoshi Shimokawa q->flag |= FWXFERQ_EXTBUF; 1596cada79aSHidetoshi Shimokawa 1606cada79aSHidetoshi Shimokawa return (0); 1616cada79aSHidetoshi Shimokawa } 1626cada79aSHidetoshi Shimokawa 1636cada79aSHidetoshi Shimokawa static int 1646cada79aSHidetoshi Shimokawa fwdev_freebuf(struct fw_xferq *q) 1656cada79aSHidetoshi Shimokawa { 1666cada79aSHidetoshi Shimokawa if (q->flag & FWXFERQ_EXTBUF) { 1676cada79aSHidetoshi Shimokawa if (q->buf != NULL) 1686cada79aSHidetoshi Shimokawa fwdma_free_multiseg(q->buf); 1696cada79aSHidetoshi Shimokawa q->buf = NULL; 1706cada79aSHidetoshi Shimokawa free(q->bulkxfer, M_FW); 1716cada79aSHidetoshi Shimokawa q->bulkxfer = NULL; 1726cada79aSHidetoshi Shimokawa q->flag &= ~FWXFERQ_EXTBUF; 1736cada79aSHidetoshi Shimokawa q->psize = 0; 1746cada79aSHidetoshi Shimokawa q->maxq = FWMAXQUEUE; 1756cada79aSHidetoshi Shimokawa } 1766cada79aSHidetoshi Shimokawa return (0); 1776cada79aSHidetoshi Shimokawa } 1786cada79aSHidetoshi Shimokawa 1796cada79aSHidetoshi Shimokawa 18017821895SHidetoshi Shimokawa static int 18117821895SHidetoshi Shimokawa fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 18217821895SHidetoshi Shimokawa { 18317821895SHidetoshi Shimokawa int err = 0; 18417821895SHidetoshi Shimokawa 18517821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 18617821895SHidetoshi Shimokawa return fwmem_open(dev, flags, fmt, td); 18717821895SHidetoshi Shimokawa 1883a927c87SHidetoshi Shimokawa if (dev->si_drv1 != NULL) 1893a927c87SHidetoshi Shimokawa return (EBUSY); 1903a927c87SHidetoshi Shimokawa 19110d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 192a160e00eSHidetoshi Shimokawa if ((dev->si_flags & SI_NAMED) == 0) { 193a160e00eSHidetoshi Shimokawa int unit = DEV2UNIT(dev); 194a160e00eSHidetoshi Shimokawa int sub = DEV2SUB(dev); 195a160e00eSHidetoshi Shimokawa 1966cada79aSHidetoshi Shimokawa make_dev(&firewire_cdevsw, minor(dev), 1976cada79aSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 1986cada79aSHidetoshi Shimokawa "fw%d.%d", unit, sub); 199a160e00eSHidetoshi Shimokawa } 200a160e00eSHidetoshi Shimokawa #endif 2016cada79aSHidetoshi Shimokawa 2026cada79aSHidetoshi Shimokawa dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); 2036cada79aSHidetoshi Shimokawa 20417821895SHidetoshi Shimokawa return err; 20517821895SHidetoshi Shimokawa } 20617821895SHidetoshi Shimokawa 20717821895SHidetoshi Shimokawa static int 20817821895SHidetoshi Shimokawa fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 20917821895SHidetoshi Shimokawa { 21017821895SHidetoshi Shimokawa struct firewire_softc *sc; 2116cada79aSHidetoshi Shimokawa struct firewire_comm *fc; 2126cada79aSHidetoshi Shimokawa struct fw_drv1 *d; 21317821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 21417821895SHidetoshi Shimokawa struct fw_xfer *xfer; 21517821895SHidetoshi Shimokawa struct fw_bind *fwb; 21617821895SHidetoshi Shimokawa int err = 0; 21717821895SHidetoshi Shimokawa 21817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 21917821895SHidetoshi Shimokawa return fwmem_close(dev, flags, fmt, td); 22017821895SHidetoshi Shimokawa 22117821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 2226cada79aSHidetoshi Shimokawa fc = sc->fc; 2236cada79aSHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 22417821895SHidetoshi Shimokawa 2256cada79aSHidetoshi Shimokawa if (d->ir != NULL) { 2266cada79aSHidetoshi Shimokawa struct fw_xferq *ir = d->ir; 2276cada79aSHidetoshi Shimokawa 2286cada79aSHidetoshi Shimokawa if ((ir->flag & FWXFERQ_OPEN) == 0) 2296cada79aSHidetoshi Shimokawa return (EINVAL); 2306cada79aSHidetoshi Shimokawa if (ir->flag & FWXFERQ_RUNNING) { 2316cada79aSHidetoshi Shimokawa ir->flag &= ~FWXFERQ_RUNNING; 2326cada79aSHidetoshi Shimokawa fc->irx_disable(fc, ir->dmach); 23317821895SHidetoshi Shimokawa } 2346cada79aSHidetoshi Shimokawa /* free extbuf */ 2356cada79aSHidetoshi Shimokawa fwdev_freebuf(ir); 2366cada79aSHidetoshi Shimokawa /* drain receiving buffer */ 2376cada79aSHidetoshi Shimokawa for (xfer = STAILQ_FIRST(&ir->q); 2386cada79aSHidetoshi Shimokawa xfer != NULL; xfer = STAILQ_FIRST(&ir->q)) { 2396cada79aSHidetoshi Shimokawa ir->queued --; 2406cada79aSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->q, link); 24117821895SHidetoshi Shimokawa 24217821895SHidetoshi Shimokawa xfer->resp = 0; 24317821895SHidetoshi Shimokawa fw_xfer_done(xfer); 24417821895SHidetoshi Shimokawa } 2456cada79aSHidetoshi Shimokawa /* remove binding */ 2466cada79aSHidetoshi Shimokawa for (fwb = STAILQ_FIRST(&ir->binds); fwb != NULL; 2476cada79aSHidetoshi Shimokawa fwb = STAILQ_FIRST(&ir->binds)) { 2486cada79aSHidetoshi Shimokawa STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); 2496cada79aSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->binds, chlist); 2505166f1dfSHidetoshi Shimokawa free(fwb, M_FW); 25117821895SHidetoshi Shimokawa } 2526cada79aSHidetoshi Shimokawa ir->flag &= ~(FWXFERQ_OPEN | 2536cada79aSHidetoshi Shimokawa FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 2546cada79aSHidetoshi Shimokawa d->ir = NULL; 2556cada79aSHidetoshi Shimokawa 2566cada79aSHidetoshi Shimokawa } 2576cada79aSHidetoshi Shimokawa if (d->it != NULL) { 2586cada79aSHidetoshi Shimokawa struct fw_xferq *it = d->it; 2596cada79aSHidetoshi Shimokawa 2606cada79aSHidetoshi Shimokawa if ((it->flag & FWXFERQ_OPEN) == 0) 2616cada79aSHidetoshi Shimokawa return (EINVAL); 2626cada79aSHidetoshi Shimokawa if (it->flag & FWXFERQ_RUNNING) { 2636cada79aSHidetoshi Shimokawa it->flag &= ~FWXFERQ_RUNNING; 2646cada79aSHidetoshi Shimokawa fc->itx_disable(fc, it->dmach); 2656cada79aSHidetoshi Shimokawa } 2666cada79aSHidetoshi Shimokawa /* free extbuf */ 2676cada79aSHidetoshi Shimokawa fwdev_freebuf(it); 2686cada79aSHidetoshi Shimokawa it->flag &= ~(FWXFERQ_OPEN | 2696cada79aSHidetoshi Shimokawa FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 2706cada79aSHidetoshi Shimokawa d->it = NULL; 2716cada79aSHidetoshi Shimokawa } 2726cada79aSHidetoshi Shimokawa free(dev->si_drv1, M_FW); 2736cada79aSHidetoshi Shimokawa dev->si_drv1 = NULL; 2746cada79aSHidetoshi Shimokawa 27517821895SHidetoshi Shimokawa return err; 27617821895SHidetoshi Shimokawa } 27717821895SHidetoshi Shimokawa 27817821895SHidetoshi Shimokawa /* 27917821895SHidetoshi Shimokawa * read request. 28017821895SHidetoshi Shimokawa */ 28117821895SHidetoshi Shimokawa static int 28217821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag) 28317821895SHidetoshi Shimokawa { 28417821895SHidetoshi Shimokawa struct firewire_softc *sc; 28517821895SHidetoshi Shimokawa struct fw_xferq *ir; 28617821895SHidetoshi Shimokawa struct fw_xfer *xfer; 28717821895SHidetoshi Shimokawa int err = 0, s, slept = 0; 28817821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 28917821895SHidetoshi Shimokawa struct fw_pkt *fp; 29017821895SHidetoshi Shimokawa 29117821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 292c4778b5dSHidetoshi Shimokawa return physio(dev, uio, ioflag); 29317821895SHidetoshi Shimokawa 29417821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 29517821895SHidetoshi Shimokawa 2966cada79aSHidetoshi Shimokawa ir = ((struct fw_drv1 *)dev->si_drv1)->ir; 2976cada79aSHidetoshi Shimokawa if (ir == NULL || ir->buf == NULL) 2986cada79aSHidetoshi Shimokawa return (EIO); 29917821895SHidetoshi Shimokawa 30017821895SHidetoshi Shimokawa readloop: 30117821895SHidetoshi Shimokawa xfer = STAILQ_FIRST(&ir->q); 30277ee030bSHidetoshi Shimokawa if (ir->stproc == NULL) { 303c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 30417821895SHidetoshi Shimokawa ir->stproc = STAILQ_FIRST(&ir->stvalid); 30517821895SHidetoshi Shimokawa if (ir->stproc != NULL) { 30617821895SHidetoshi Shimokawa s = splfw(); 30717821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stvalid, link); 30817821895SHidetoshi Shimokawa splx(s); 30917821895SHidetoshi Shimokawa ir->queued = 0; 31017821895SHidetoshi Shimokawa } 31117821895SHidetoshi Shimokawa } 31217821895SHidetoshi Shimokawa if (xfer == NULL && ir->stproc == NULL) { 313c3e9e255SHidetoshi Shimokawa /* no data avaliable */ 31417821895SHidetoshi Shimokawa if (slept == 0) { 31517821895SHidetoshi Shimokawa slept = 1; 31617821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_WAKEUP; 317521f364bSDag-Erling Smørgrav err = tsleep(ir, FWPRI, "fw_read", hz); 31817821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_WAKEUP; 319c3e9e255SHidetoshi Shimokawa if (err == 0) 32017821895SHidetoshi Shimokawa goto readloop; 321c3e9e255SHidetoshi Shimokawa } else if (slept == 1) 32217821895SHidetoshi Shimokawa err = EIO; 32317821895SHidetoshi Shimokawa return err; 32417821895SHidetoshi Shimokawa } else if(xfer != NULL) { 325c4778b5dSHidetoshi Shimokawa #if 0 /* XXX broken */ 32677ee030bSHidetoshi Shimokawa /* per packet mode or FWACT_CH bind?*/ 32717821895SHidetoshi Shimokawa s = splfw(); 32817821895SHidetoshi Shimokawa ir->queued --; 32917821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->q, link); 33017821895SHidetoshi Shimokawa splx(s); 331c4778b5dSHidetoshi Shimokawa fp = &xfer->recv.hdr; 33217821895SHidetoshi Shimokawa if (sc->fc->irx_post != NULL) 33317821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 334c4778b5dSHidetoshi Shimokawa err = uiomove((void *)fp, 1 /* XXX header size */, uio); 335c4778b5dSHidetoshi Shimokawa /* XXX copy payload too */ 33677ee030bSHidetoshi Shimokawa /* XXX we should recycle this xfer */ 337c4778b5dSHidetoshi Shimokawa #endif 33817821895SHidetoshi Shimokawa fw_xfer_free( xfer); 33917821895SHidetoshi Shimokawa } else if(ir->stproc != NULL) { 340c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 34177ee030bSHidetoshi Shimokawa fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, 34277ee030bSHidetoshi Shimokawa ir->stproc->poffset + ir->queued); 34317821895SHidetoshi Shimokawa if(sc->fc->irx_post != NULL) 34417821895SHidetoshi Shimokawa sc->fc->irx_post(sc->fc, fp->mode.ld); 34577ee030bSHidetoshi Shimokawa if(fp->mode.stream.len == 0){ 34617821895SHidetoshi Shimokawa err = EIO; 34717821895SHidetoshi Shimokawa return err; 34817821895SHidetoshi Shimokawa } 349c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, 35003161bbcSDoug Rabson fp->mode.stream.len + sizeof(uint32_t), uio); 35117821895SHidetoshi Shimokawa ir->queued ++; 35217821895SHidetoshi Shimokawa if(ir->queued >= ir->bnpacket){ 35317821895SHidetoshi Shimokawa s = splfw(); 35417821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 35517821895SHidetoshi Shimokawa splx(s); 3566cada79aSHidetoshi Shimokawa sc->fc->irx_enable(sc->fc, ir->dmach); 35717821895SHidetoshi Shimokawa ir->stproc = NULL; 35817821895SHidetoshi Shimokawa } 359c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= ir->psize) { 360c3e9e255SHidetoshi Shimokawa slept = -1; 361c3e9e255SHidetoshi Shimokawa goto readloop; 362c3e9e255SHidetoshi Shimokawa } 36317821895SHidetoshi Shimokawa } 36417821895SHidetoshi Shimokawa return err; 36517821895SHidetoshi Shimokawa } 36617821895SHidetoshi Shimokawa 36717821895SHidetoshi Shimokawa static int 36817821895SHidetoshi Shimokawa fw_write (dev_t dev, struct uio *uio, int ioflag) 36917821895SHidetoshi Shimokawa { 37017821895SHidetoshi Shimokawa int err = 0; 37117821895SHidetoshi Shimokawa struct firewire_softc *sc; 37217821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 37317821895SHidetoshi Shimokawa int s, slept = 0; 37417821895SHidetoshi Shimokawa struct fw_pkt *fp; 37517821895SHidetoshi Shimokawa struct firewire_comm *fc; 37617821895SHidetoshi Shimokawa struct fw_xferq *it; 37717821895SHidetoshi Shimokawa 37817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 379c4778b5dSHidetoshi Shimokawa return physio(dev, uio, ioflag); 38017821895SHidetoshi Shimokawa 38117821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 38217821895SHidetoshi Shimokawa fc = sc->fc; 3836cada79aSHidetoshi Shimokawa it = ((struct fw_drv1 *)dev->si_drv1)->it; 3846cada79aSHidetoshi Shimokawa if (it == NULL || it->buf == NULL) 3856cada79aSHidetoshi Shimokawa return (EIO); 38617821895SHidetoshi Shimokawa isoloop: 38717821895SHidetoshi Shimokawa if (it->stproc == NULL) { 38817821895SHidetoshi Shimokawa it->stproc = STAILQ_FIRST(&it->stfree); 38917821895SHidetoshi Shimokawa if (it->stproc != NULL) { 39017821895SHidetoshi Shimokawa s = splfw(); 39117821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stfree, link); 39217821895SHidetoshi Shimokawa splx(s); 39317821895SHidetoshi Shimokawa it->queued = 0; 39417821895SHidetoshi Shimokawa } else if (slept == 0) { 39517821895SHidetoshi Shimokawa slept = 1; 3966cada79aSHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, it->dmach); 397c3e9e255SHidetoshi Shimokawa if (err) 39817821895SHidetoshi Shimokawa return err; 399e863fbcdSHidetoshi Shimokawa err = tsleep(it, FWPRI, "fw_write", hz); 400c3e9e255SHidetoshi Shimokawa if (err) 40117821895SHidetoshi Shimokawa return err; 40217821895SHidetoshi Shimokawa goto isoloop; 40317821895SHidetoshi Shimokawa } else { 40417821895SHidetoshi Shimokawa err = EIO; 40517821895SHidetoshi Shimokawa return err; 40617821895SHidetoshi Shimokawa } 40717821895SHidetoshi Shimokawa } 40877ee030bSHidetoshi Shimokawa fp = (struct fw_pkt *)fwdma_v_addr(it->buf, 40977ee030bSHidetoshi Shimokawa it->stproc->poffset + it->queued); 410c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 411c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp->mode.stream.payload, 41277ee030bSHidetoshi Shimokawa fp->mode.stream.len, uio); 41317821895SHidetoshi Shimokawa it->queued ++; 414c3e9e255SHidetoshi Shimokawa if (it->queued >= it->bnpacket) { 41517821895SHidetoshi Shimokawa s = splfw(); 41617821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 41717821895SHidetoshi Shimokawa splx(s); 41817821895SHidetoshi Shimokawa it->stproc = NULL; 4196cada79aSHidetoshi Shimokawa err = sc->fc->itx_enable(sc->fc, it->dmach); 42017821895SHidetoshi Shimokawa } 421c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 422c3e9e255SHidetoshi Shimokawa slept = 0; 423c3e9e255SHidetoshi Shimokawa goto isoloop; 424c3e9e255SHidetoshi Shimokawa } 42517821895SHidetoshi Shimokawa return err; 4269190691bSHidetoshi Shimokawa } 42717821895SHidetoshi Shimokawa /* 42817821895SHidetoshi Shimokawa * ioctl support. 42917821895SHidetoshi Shimokawa */ 43017821895SHidetoshi Shimokawa int 43117821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 43217821895SHidetoshi Shimokawa { 43317821895SHidetoshi Shimokawa struct firewire_softc *sc; 4346cada79aSHidetoshi Shimokawa struct firewire_comm *fc; 4356cada79aSHidetoshi Shimokawa struct fw_drv1 *d; 43617821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 43777ee030bSHidetoshi Shimokawa int s, i, len, err = 0; 43817821895SHidetoshi Shimokawa struct fw_device *fwdev; 43917821895SHidetoshi Shimokawa struct fw_bind *fwb; 44017821895SHidetoshi Shimokawa struct fw_xferq *ir, *it; 44117821895SHidetoshi Shimokawa struct fw_xfer *xfer; 44217821895SHidetoshi Shimokawa struct fw_pkt *fp; 443c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 444d7e486b4SHidetoshi Shimokawa void *ptr; 44517821895SHidetoshi Shimokawa 44617821895SHidetoshi Shimokawa struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 44717821895SHidetoshi Shimokawa struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 44817821895SHidetoshi Shimokawa struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 44917821895SHidetoshi Shimokawa struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 45017821895SHidetoshi Shimokawa struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 45117821895SHidetoshi Shimokawa struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 45217821895SHidetoshi Shimokawa 45317821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 45417821895SHidetoshi Shimokawa return fwmem_ioctl(dev, cmd, data, flag, td); 45517821895SHidetoshi Shimokawa 45617821895SHidetoshi Shimokawa if (!data) 45717821895SHidetoshi Shimokawa return(EINVAL); 45817821895SHidetoshi Shimokawa 4596cada79aSHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 4606cada79aSHidetoshi Shimokawa fc = sc->fc; 4616cada79aSHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 4626cada79aSHidetoshi Shimokawa ir = d->ir; 4636cada79aSHidetoshi Shimokawa it = d->it; 4646cada79aSHidetoshi Shimokawa 46517821895SHidetoshi Shimokawa switch (cmd) { 46617821895SHidetoshi Shimokawa case FW_STSTREAM: 4676cada79aSHidetoshi Shimokawa if (it == NULL) { 4686cada79aSHidetoshi Shimokawa for (i = 0; i < fc->nisodma; i ++) { 4696cada79aSHidetoshi Shimokawa it = fc->it[i]; 4706cada79aSHidetoshi Shimokawa if ((it->flag & FWXFERQ_OPEN) == 0) 4716cada79aSHidetoshi Shimokawa break; 4726cada79aSHidetoshi Shimokawa } 4736cada79aSHidetoshi Shimokawa if (i >= fc->nisodma) { 4746cada79aSHidetoshi Shimokawa err = EBUSY; 4756cada79aSHidetoshi Shimokawa break; 4766cada79aSHidetoshi Shimokawa } 4776cada79aSHidetoshi Shimokawa err = fwdev_allocbuf(fc, it, &d->bufreq.tx); 4786cada79aSHidetoshi Shimokawa if (err) 4796cada79aSHidetoshi Shimokawa break; 4806cada79aSHidetoshi Shimokawa it->flag |= FWXFERQ_OPEN; 4816cada79aSHidetoshi Shimokawa } 4826cada79aSHidetoshi Shimokawa it->flag &= ~0xff; 4836cada79aSHidetoshi Shimokawa it->flag |= (0x3f & ichreq->ch); 4846cada79aSHidetoshi Shimokawa it->flag |= ((0x3 & ichreq->tag) << 6); 4856cada79aSHidetoshi Shimokawa d->it = it; 48617821895SHidetoshi Shimokawa break; 48717821895SHidetoshi Shimokawa case FW_GTSTREAM: 4886cada79aSHidetoshi Shimokawa if (it != NULL) { 4896cada79aSHidetoshi Shimokawa ichreq->ch = it->flag & 0x3f; 4906cada79aSHidetoshi Shimokawa ichreq->tag = it->flag >> 2 & 0x3; 4916cada79aSHidetoshi Shimokawa } else 4926cada79aSHidetoshi Shimokawa err = EINVAL; 49317821895SHidetoshi Shimokawa break; 49417821895SHidetoshi Shimokawa case FW_SRSTREAM: 4956cada79aSHidetoshi Shimokawa if (ir == NULL) { 4966cada79aSHidetoshi Shimokawa for (i = 0; i < fc->nisodma; i ++) { 4976cada79aSHidetoshi Shimokawa ir = fc->ir[i]; 4986cada79aSHidetoshi Shimokawa if ((ir->flag & FWXFERQ_OPEN) == 0) 4996cada79aSHidetoshi Shimokawa break; 5006cada79aSHidetoshi Shimokawa } 5016cada79aSHidetoshi Shimokawa if (i >= fc->nisodma) { 5026cada79aSHidetoshi Shimokawa err = EBUSY; 5036cada79aSHidetoshi Shimokawa break; 5046cada79aSHidetoshi Shimokawa } 5056cada79aSHidetoshi Shimokawa err = fwdev_allocbuf(fc, ir, &d->bufreq.rx); 5066cada79aSHidetoshi Shimokawa if (err) 5076cada79aSHidetoshi Shimokawa break; 5086cada79aSHidetoshi Shimokawa ir->flag |= FWXFERQ_OPEN; 5096cada79aSHidetoshi Shimokawa } 5106cada79aSHidetoshi Shimokawa ir->flag &= ~0xff; 5116cada79aSHidetoshi Shimokawa ir->flag |= (0x3f & ichreq->ch); 5126cada79aSHidetoshi Shimokawa ir->flag |= ((0x3 & ichreq->tag) << 6); 5136cada79aSHidetoshi Shimokawa d->ir = ir; 5146cada79aSHidetoshi Shimokawa err = fc->irx_enable(fc, ir->dmach); 51517821895SHidetoshi Shimokawa break; 51617821895SHidetoshi Shimokawa case FW_GRSTREAM: 5176cada79aSHidetoshi Shimokawa if (d->ir != NULL) { 5186cada79aSHidetoshi Shimokawa ichreq->ch = ir->flag & 0x3f; 5196cada79aSHidetoshi Shimokawa ichreq->tag = ir->flag >> 2 & 0x3; 5206cada79aSHidetoshi Shimokawa } else 5216cada79aSHidetoshi Shimokawa err = EINVAL; 52217821895SHidetoshi Shimokawa break; 52317821895SHidetoshi Shimokawa case FW_SSTBUF: 5246cada79aSHidetoshi Shimokawa bcopy(ibufreq, &d->bufreq, sizeof(d->bufreq)); 52517821895SHidetoshi Shimokawa break; 52617821895SHidetoshi Shimokawa case FW_GSTBUF: 5276cada79aSHidetoshi Shimokawa bzero(&ibufreq->rx, sizeof(ibufreq->rx)); 5286cada79aSHidetoshi Shimokawa if (ir != NULL) { 5296cada79aSHidetoshi Shimokawa ibufreq->rx.nchunk = ir->bnchunk; 5306cada79aSHidetoshi Shimokawa ibufreq->rx.npacket = ir->bnpacket; 5316cada79aSHidetoshi Shimokawa ibufreq->rx.psize = ir->psize; 5326cada79aSHidetoshi Shimokawa } 5336cada79aSHidetoshi Shimokawa bzero(&ibufreq->tx, sizeof(ibufreq->tx)); 5346cada79aSHidetoshi Shimokawa if (it != NULL) { 5356cada79aSHidetoshi Shimokawa ibufreq->tx.nchunk = it->bnchunk; 5366cada79aSHidetoshi Shimokawa ibufreq->tx.npacket = it->bnpacket; 5376cada79aSHidetoshi Shimokawa ibufreq->tx.psize = it->psize; 5386cada79aSHidetoshi Shimokawa } 53917821895SHidetoshi Shimokawa break; 54017821895SHidetoshi Shimokawa case FW_ASYREQ: 541c4778b5dSHidetoshi Shimokawa { 542c4778b5dSHidetoshi Shimokawa struct tcode_info *tinfo; 543102ebc1fSHidetoshi Shimokawa int pay_len = 0; 544c4778b5dSHidetoshi Shimokawa 54517821895SHidetoshi Shimokawa fp = &asyreq->pkt; 546102ebc1fSHidetoshi Shimokawa tinfo = &sc->fc->tcode[fp->mode.hdr.tcode]; 547102ebc1fSHidetoshi Shimokawa 548102ebc1fSHidetoshi Shimokawa if ((tinfo->flag & FWTI_BLOCK_ASY) != 0) 549102ebc1fSHidetoshi Shimokawa pay_len = MAX(0, asyreq->req.len - tinfo->hdr_len); 550102ebc1fSHidetoshi Shimokawa 551102ebc1fSHidetoshi Shimokawa xfer = fw_xfer_alloc_buf(M_FWXFER, pay_len, PAGE_SIZE/*XXX*/); 552102ebc1fSHidetoshi Shimokawa if (xfer == NULL) 553102ebc1fSHidetoshi Shimokawa return (ENOMEM); 554102ebc1fSHidetoshi Shimokawa 55517821895SHidetoshi Shimokawa switch (asyreq->req.type) { 55617821895SHidetoshi Shimokawa case FWASREQNODE: 55717821895SHidetoshi Shimokawa break; 55817821895SHidetoshi Shimokawa case FWASREQEUI: 559958c7749SHidetoshi Shimokawa fwdev = fw_noderesolve_eui64(sc->fc, 560233b1b97SHidetoshi Shimokawa &asyreq->req.dst.eui); 56117821895SHidetoshi Shimokawa if (fwdev == NULL) { 56217faeefcSHidetoshi Shimokawa device_printf(sc->fc->bdev, 56317faeefcSHidetoshi Shimokawa "cannot find node\n"); 56417821895SHidetoshi Shimokawa err = EINVAL; 565102ebc1fSHidetoshi Shimokawa goto out; 56617821895SHidetoshi Shimokawa } 567c4778b5dSHidetoshi Shimokawa fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst; 56817821895SHidetoshi Shimokawa break; 56917821895SHidetoshi Shimokawa case FWASRESTL: 57017821895SHidetoshi Shimokawa /* XXX what's this? */ 57117821895SHidetoshi Shimokawa break; 57217821895SHidetoshi Shimokawa case FWASREQSTREAM: 57317821895SHidetoshi Shimokawa /* nothing to do */ 57417821895SHidetoshi Shimokawa break; 57517821895SHidetoshi Shimokawa } 576102ebc1fSHidetoshi Shimokawa 577c4778b5dSHidetoshi Shimokawa bcopy(fp, (void *)&xfer->send.hdr, tinfo->hdr_len); 578102ebc1fSHidetoshi Shimokawa if (pay_len > 0) 579c4778b5dSHidetoshi Shimokawa bcopy((char *)fp + tinfo->hdr_len, 580a832f947SHidetoshi Shimokawa (void *)xfer->send.payload, pay_len); 581102ebc1fSHidetoshi Shimokawa xfer->send.spd = asyreq->req.sped; 58217821895SHidetoshi Shimokawa xfer->act.hand = fw_asy_callback; 583102ebc1fSHidetoshi Shimokawa 584102ebc1fSHidetoshi Shimokawa if ((err = fw_asyreq(sc->fc, -1, xfer)) != 0) 585102ebc1fSHidetoshi Shimokawa goto out; 586102ebc1fSHidetoshi Shimokawa if ((err = tsleep(xfer, FWPRI, "asyreq", hz)) != 0) 587102ebc1fSHidetoshi Shimokawa goto out; 588c4778b5dSHidetoshi Shimokawa if (xfer->resp != 0) { 589c4778b5dSHidetoshi Shimokawa err = EIO; 590102ebc1fSHidetoshi Shimokawa goto out; 591c4778b5dSHidetoshi Shimokawa } 592102ebc1fSHidetoshi Shimokawa if ((tinfo->flag & FWTI_TLABEL) == 0) 593102ebc1fSHidetoshi Shimokawa goto out; 594102ebc1fSHidetoshi Shimokawa 595102ebc1fSHidetoshi Shimokawa /* copy response */ 596c4778b5dSHidetoshi Shimokawa tinfo = &sc->fc->tcode[xfer->recv.hdr.mode.hdr.tcode]; 597102ebc1fSHidetoshi Shimokawa if (asyreq->req.len >= xfer->recv.pay_len + tinfo->hdr_len) 598c4778b5dSHidetoshi Shimokawa asyreq->req.len = xfer->recv.pay_len; 599102ebc1fSHidetoshi Shimokawa else 60017821895SHidetoshi Shimokawa err = EINVAL; 601c4778b5dSHidetoshi Shimokawa bcopy(&xfer->recv.hdr, fp, tinfo->hdr_len); 602102ebc1fSHidetoshi Shimokawa bcopy(xfer->recv.payload, (char *)fp + tinfo->hdr_len, 603102ebc1fSHidetoshi Shimokawa MAX(0, asyreq->req.len - tinfo->hdr_len)); 604102ebc1fSHidetoshi Shimokawa out: 605c4778b5dSHidetoshi Shimokawa fw_xfer_free_buf(xfer); 60617821895SHidetoshi Shimokawa break; 607c4778b5dSHidetoshi Shimokawa } 60817821895SHidetoshi Shimokawa case FW_IBUSRST: 60917821895SHidetoshi Shimokawa sc->fc->ibr(sc->fc); 61017821895SHidetoshi Shimokawa break; 61117821895SHidetoshi Shimokawa case FW_CBINDADDR: 61217821895SHidetoshi Shimokawa fwb = fw_bindlookup(sc->fc, 61317821895SHidetoshi Shimokawa bindreq->start.hi, bindreq->start.lo); 61417821895SHidetoshi Shimokawa if(fwb == NULL){ 61517821895SHidetoshi Shimokawa err = EINVAL; 61617821895SHidetoshi Shimokawa break; 61717821895SHidetoshi Shimokawa } 61817821895SHidetoshi Shimokawa STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 6196cada79aSHidetoshi Shimokawa STAILQ_REMOVE(&ir->binds, fwb, fw_bind, chlist); 6205166f1dfSHidetoshi Shimokawa free(fwb, M_FW); 62117821895SHidetoshi Shimokawa break; 62217821895SHidetoshi Shimokawa case FW_SBINDADDR: 62317821895SHidetoshi Shimokawa if(bindreq->len <= 0 ){ 62417821895SHidetoshi Shimokawa err = EINVAL; 62517821895SHidetoshi Shimokawa break; 62617821895SHidetoshi Shimokawa } 62717821895SHidetoshi Shimokawa if(bindreq->start.hi > 0xffff ){ 62817821895SHidetoshi Shimokawa err = EINVAL; 62917821895SHidetoshi Shimokawa break; 63017821895SHidetoshi Shimokawa } 6315166f1dfSHidetoshi Shimokawa fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 63217821895SHidetoshi Shimokawa if(fwb == NULL){ 63317821895SHidetoshi Shimokawa err = ENOMEM; 63417821895SHidetoshi Shimokawa break; 63517821895SHidetoshi Shimokawa } 636c4778b5dSHidetoshi Shimokawa fwb->start = ((u_int64_t)bindreq->start.hi << 32) | 637c4778b5dSHidetoshi Shimokawa bindreq->start.lo; 638c4778b5dSHidetoshi Shimokawa fwb->end = fwb->start + bindreq->len; 6396cada79aSHidetoshi Shimokawa /* XXX */ 6406cada79aSHidetoshi Shimokawa fwb->sub = ir->dmach; 64177ee030bSHidetoshi Shimokawa fwb->act_type = FWACT_CH; 64217821895SHidetoshi Shimokawa 643c4778b5dSHidetoshi Shimokawa /* XXX alloc buf */ 64448249fe0SHidetoshi Shimokawa xfer = fw_xfer_alloc(M_FWXFER); 64517821895SHidetoshi Shimokawa if(xfer == NULL){ 6464c790222SHidetoshi Shimokawa free(fwb, M_FW); 6474c790222SHidetoshi Shimokawa return (ENOMEM); 64817821895SHidetoshi Shimokawa } 64917821895SHidetoshi Shimokawa xfer->fc = sc->fc; 65017821895SHidetoshi Shimokawa 65177ee030bSHidetoshi Shimokawa s = splfw(); 65277ee030bSHidetoshi Shimokawa /* XXX broken. need multiple xfer */ 65377ee030bSHidetoshi Shimokawa STAILQ_INIT(&fwb->xferlist); 65477ee030bSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link); 65577ee030bSHidetoshi Shimokawa splx(s); 65617821895SHidetoshi Shimokawa err = fw_bindadd(sc->fc, fwb); 65717821895SHidetoshi Shimokawa break; 65817821895SHidetoshi Shimokawa case FW_GDEVLST: 659c547b896SHidetoshi Shimokawa i = len = 1; 660c547b896SHidetoshi Shimokawa /* myself */ 661c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[0]; 662c547b896SHidetoshi Shimokawa devinfo->dst = sc->fc->nodeid; 663c547b896SHidetoshi Shimokawa devinfo->status = 0; /* XXX */ 664c547b896SHidetoshi Shimokawa devinfo->eui.hi = sc->fc->eui.hi; 665c547b896SHidetoshi Shimokawa devinfo->eui.lo = sc->fc->eui.lo; 6660981f5f0SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 667c547b896SHidetoshi Shimokawa if(len < FW_MAX_DEVLST){ 668c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[len++]; 669c547b896SHidetoshi Shimokawa devinfo->dst = fwdev->dst; 670c547b896SHidetoshi Shimokawa devinfo->status = 671c547b896SHidetoshi Shimokawa (fwdev->status == FWDEVINVAL)?0:1; 672c547b896SHidetoshi Shimokawa devinfo->eui.hi = fwdev->eui.hi; 673c547b896SHidetoshi Shimokawa devinfo->eui.lo = fwdev->eui.lo; 67417821895SHidetoshi Shimokawa } 67517821895SHidetoshi Shimokawa i++; 67617821895SHidetoshi Shimokawa } 67717821895SHidetoshi Shimokawa fwdevlst->n = i; 678c547b896SHidetoshi Shimokawa fwdevlst->info_len = len; 67917821895SHidetoshi Shimokawa break; 68017821895SHidetoshi Shimokawa case FW_GTPMAP: 68117821895SHidetoshi Shimokawa bcopy(sc->fc->topology_map, data, 68217821895SHidetoshi Shimokawa (sc->fc->topology_map->crc_len + 1) * 4); 68317821895SHidetoshi Shimokawa break; 68417821895SHidetoshi Shimokawa case FW_GCROM: 6850981f5f0SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 6860981f5f0SHidetoshi Shimokawa if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 68717821895SHidetoshi Shimokawa break; 68817821895SHidetoshi Shimokawa if (fwdev == NULL) { 689d7e486b4SHidetoshi Shimokawa if (!FW_EUI64_EQUAL(sc->fc->eui, crom_buf->eui)) { 69017821895SHidetoshi Shimokawa err = FWNODE_INVAL; 69117821895SHidetoshi Shimokawa break; 69217821895SHidetoshi Shimokawa } 693d7e486b4SHidetoshi Shimokawa /* myself */ 694d7e486b4SHidetoshi Shimokawa ptr = malloc(CROMSIZE, M_FW, M_WAITOK); 695d7e486b4SHidetoshi Shimokawa len = CROMSIZE; 696d7e486b4SHidetoshi Shimokawa for (i = 0; i < CROMSIZE/4; i++) 69703161bbcSDoug Rabson ((uint32_t *)ptr)[i] 698d7e486b4SHidetoshi Shimokawa = ntohl(sc->fc->config_rom[i]); 699d7e486b4SHidetoshi Shimokawa } else { 700d7e486b4SHidetoshi Shimokawa /* found */ 701d7e486b4SHidetoshi Shimokawa ptr = (void *)&fwdev->csrrom[0]; 70217821895SHidetoshi Shimokawa if (fwdev->rommax < CSRROMOFF) 70317821895SHidetoshi Shimokawa len = 0; 70417821895SHidetoshi Shimokawa else 70517821895SHidetoshi Shimokawa len = fwdev->rommax - CSRROMOFF + 4; 706d7e486b4SHidetoshi Shimokawa } 70717821895SHidetoshi Shimokawa if (crom_buf->len < len) 70817821895SHidetoshi Shimokawa len = crom_buf->len; 70917821895SHidetoshi Shimokawa else 71017821895SHidetoshi Shimokawa crom_buf->len = len; 711d7e486b4SHidetoshi Shimokawa err = copyout(ptr, crom_buf->ptr, len); 712d7e486b4SHidetoshi Shimokawa if (fwdev == NULL) 713d7e486b4SHidetoshi Shimokawa /* myself */ 714d7e486b4SHidetoshi Shimokawa free(ptr, M_FW); 71517821895SHidetoshi Shimokawa break; 71617821895SHidetoshi Shimokawa default: 71717821895SHidetoshi Shimokawa sc->fc->ioctl (dev, cmd, data, flag, td); 71817821895SHidetoshi Shimokawa break; 71917821895SHidetoshi Shimokawa } 72017821895SHidetoshi Shimokawa return err; 72117821895SHidetoshi Shimokawa } 72217821895SHidetoshi Shimokawa int 72317821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td) 72417821895SHidetoshi Shimokawa { 7256cada79aSHidetoshi Shimokawa struct firewire_softc *sc; 7266cada79aSHidetoshi Shimokawa struct fw_xferq *ir; 72717821895SHidetoshi Shimokawa int revents; 72817821895SHidetoshi Shimokawa int tmp; 72917821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 73017821895SHidetoshi Shimokawa 73117821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 73217821895SHidetoshi Shimokawa return fwmem_poll(dev, events, td); 73317821895SHidetoshi Shimokawa 73417821895SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 7356cada79aSHidetoshi Shimokawa ir = ((struct fw_drv1 *)dev->si_drv1)->ir; 73617821895SHidetoshi Shimokawa revents = 0; 73717821895SHidetoshi Shimokawa tmp = POLLIN | POLLRDNORM; 73817821895SHidetoshi Shimokawa if (events & tmp) { 7396cada79aSHidetoshi Shimokawa if (STAILQ_FIRST(&ir->q) != NULL) 74017821895SHidetoshi Shimokawa revents |= tmp; 74117821895SHidetoshi Shimokawa else 7426cada79aSHidetoshi Shimokawa selrecord(td, &ir->rsel); 74317821895SHidetoshi Shimokawa } 74417821895SHidetoshi Shimokawa tmp = POLLOUT | POLLWRNORM; 74517821895SHidetoshi Shimokawa if (events & tmp) { 74617821895SHidetoshi Shimokawa /* XXX should be fixed */ 74717821895SHidetoshi Shimokawa revents |= tmp; 74817821895SHidetoshi Shimokawa } 74917821895SHidetoshi Shimokawa 75017821895SHidetoshi Shimokawa return revents; 75117821895SHidetoshi Shimokawa } 75217821895SHidetoshi Shimokawa 75317821895SHidetoshi Shimokawa static int 75410d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500102 75545545499SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 75645545499SHidetoshi Shimokawa #else 75777ee030bSHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) 75845545499SHidetoshi Shimokawa #endif 75917821895SHidetoshi Shimokawa { 760a160e00eSHidetoshi Shimokawa struct firewire_softc *sc; 76117821895SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 76217821895SHidetoshi Shimokawa 76317821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 76410d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500102 76545545499SHidetoshi Shimokawa return fwmem_mmap(dev, offset, nproto); 76645545499SHidetoshi Shimokawa #else 76707159f9cSMaxime Henrion return fwmem_mmap(dev, offset, paddr, nproto); 76845545499SHidetoshi Shimokawa #endif 76917821895SHidetoshi Shimokawa 770a160e00eSHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 77117821895SHidetoshi Shimokawa 77217821895SHidetoshi Shimokawa return EINVAL; 77317821895SHidetoshi Shimokawa } 774a160e00eSHidetoshi Shimokawa 775c4778b5dSHidetoshi Shimokawa static void 776c4778b5dSHidetoshi Shimokawa fw_strategy(struct bio *bp) 777c4778b5dSHidetoshi Shimokawa { 778c4778b5dSHidetoshi Shimokawa dev_t dev; 779c4778b5dSHidetoshi Shimokawa 780c4778b5dSHidetoshi Shimokawa dev = bp->bio_dev; 781c4778b5dSHidetoshi Shimokawa if (DEV_FWMEM(dev)) { 782c4778b5dSHidetoshi Shimokawa fwmem_strategy(bp); 783c4778b5dSHidetoshi Shimokawa return; 784c4778b5dSHidetoshi Shimokawa } 785c4778b5dSHidetoshi Shimokawa 786c4778b5dSHidetoshi Shimokawa bp->bio_error = EOPNOTSUPP; 787c4778b5dSHidetoshi Shimokawa bp->bio_flags |= BIO_ERROR; 788c4778b5dSHidetoshi Shimokawa bp->bio_resid = bp->bio_bcount; 789c4778b5dSHidetoshi Shimokawa biodone(bp); 790c4778b5dSHidetoshi Shimokawa } 791c4778b5dSHidetoshi Shimokawa 792a160e00eSHidetoshi Shimokawa int 793a160e00eSHidetoshi Shimokawa fwdev_makedev(struct firewire_softc *sc) 794a160e00eSHidetoshi Shimokawa { 795a160e00eSHidetoshi Shimokawa int err = 0; 796a160e00eSHidetoshi Shimokawa 79710d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 79810d3ed64SHidetoshi Shimokawa cdevsw_add(&firewire_cdevsw); 79910d3ed64SHidetoshi Shimokawa #else 800a160e00eSHidetoshi Shimokawa dev_t d; 801a160e00eSHidetoshi Shimokawa int unit; 802a160e00eSHidetoshi Shimokawa 803a160e00eSHidetoshi Shimokawa unit = device_get_unit(sc->fc->bdev); 804a160e00eSHidetoshi Shimokawa sc->dev = make_dev(&firewire_cdevsw, MAKEMINOR(0, unit, 0), 805a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 806a160e00eSHidetoshi Shimokawa "fw%d.%d", unit, 0); 807a160e00eSHidetoshi Shimokawa d = make_dev(&firewire_cdevsw, 808a160e00eSHidetoshi Shimokawa MAKEMINOR(FWMEM_FLAG, unit, 0), 809a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 810a160e00eSHidetoshi Shimokawa "fwmem%d.%d", unit, 0); 811a160e00eSHidetoshi Shimokawa dev_depends(sc->dev, d); 812a160e00eSHidetoshi Shimokawa make_dev_alias(sc->dev, "fw%d", unit); 813a160e00eSHidetoshi Shimokawa make_dev_alias(d, "fwmem%d", unit); 814a160e00eSHidetoshi Shimokawa #endif 815a160e00eSHidetoshi Shimokawa 816a160e00eSHidetoshi Shimokawa return (err); 817a160e00eSHidetoshi Shimokawa } 818a160e00eSHidetoshi Shimokawa 819a160e00eSHidetoshi Shimokawa int 820a160e00eSHidetoshi Shimokawa fwdev_destroydev(struct firewire_softc *sc) 821a160e00eSHidetoshi Shimokawa { 822a160e00eSHidetoshi Shimokawa int err = 0; 823a160e00eSHidetoshi Shimokawa 82410d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 825a160e00eSHidetoshi Shimokawa cdevsw_remove(&firewire_cdevsw); 82610d3ed64SHidetoshi Shimokawa #else 82710d3ed64SHidetoshi Shimokawa destroy_dev(sc->dev); 828a160e00eSHidetoshi Shimokawa #endif 829a160e00eSHidetoshi Shimokawa return (err); 830a160e00eSHidetoshi Shimokawa } 831a160e00eSHidetoshi Shimokawa 83210d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 833a160e00eSHidetoshi Shimokawa #define NDEVTYPE 2 834a160e00eSHidetoshi Shimokawa void 835a160e00eSHidetoshi Shimokawa fwdev_clone(void *arg, char *name, int namelen, dev_t *dev) 836a160e00eSHidetoshi Shimokawa { 837a160e00eSHidetoshi Shimokawa struct firewire_softc *sc; 838a160e00eSHidetoshi Shimokawa char *devnames[NDEVTYPE] = {"fw", "fwmem"}; 839a160e00eSHidetoshi Shimokawa char *subp = NULL; 840a160e00eSHidetoshi Shimokawa int devflag[NDEVTYPE] = {0, FWMEM_FLAG}; 841a160e00eSHidetoshi Shimokawa int i, unit = 0, sub = 0; 842a160e00eSHidetoshi Shimokawa 843a160e00eSHidetoshi Shimokawa if (*dev != NODEV) 844a160e00eSHidetoshi Shimokawa return; 845a160e00eSHidetoshi Shimokawa 846a160e00eSHidetoshi Shimokawa for (i = 0; i < NDEVTYPE; i++) 847c727011aSHidetoshi Shimokawa if (dev_stdclone(name, &subp, devnames[i], &unit) == 2) 848a160e00eSHidetoshi Shimokawa goto found; 849a160e00eSHidetoshi Shimokawa /* not match */ 850a160e00eSHidetoshi Shimokawa return; 851a160e00eSHidetoshi Shimokawa found: 852a160e00eSHidetoshi Shimokawa 853a160e00eSHidetoshi Shimokawa if (subp == NULL || *subp++ != '.') 854a160e00eSHidetoshi Shimokawa return; 855a160e00eSHidetoshi Shimokawa 856a160e00eSHidetoshi Shimokawa /* /dev/fwU.S */ 857a160e00eSHidetoshi Shimokawa while (isdigit(*subp)) { 858a160e00eSHidetoshi Shimokawa sub *= 10; 859a160e00eSHidetoshi Shimokawa sub += *subp++ - '0'; 860a160e00eSHidetoshi Shimokawa } 861a160e00eSHidetoshi Shimokawa if (*subp != '\0') 862a160e00eSHidetoshi Shimokawa return; 863a160e00eSHidetoshi Shimokawa 864a160e00eSHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 865a160e00eSHidetoshi Shimokawa if (sc == NULL) 866a160e00eSHidetoshi Shimokawa return; 867a160e00eSHidetoshi Shimokawa *dev = make_dev(&firewire_cdevsw, MAKEMINOR(devflag[i], unit, sub), 868a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 869a160e00eSHidetoshi Shimokawa "%s%d.%d", devnames[i], unit, sub); 870a160e00eSHidetoshi Shimokawa (*dev)->si_flags |= SI_CHEAPCLONE; 871a160e00eSHidetoshi Shimokawa dev_depends(sc->dev, *dev); 872a160e00eSHidetoshi Shimokawa return; 873a160e00eSHidetoshi Shimokawa } 874a160e00eSHidetoshi Shimokawa #endif 875