1098ca2bdSWarner Losh /*- 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", 1019950b741SHidetoshi Shimokawa .d_flags = D_MEM 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 { 1110892f4c5SHidetoshi Shimokawa struct firewire_comm *fc; 1126cada79aSHidetoshi Shimokawa struct fw_xferq *ir; 1136cada79aSHidetoshi Shimokawa struct fw_xferq *it; 1146cada79aSHidetoshi Shimokawa struct fw_isobufreq bufreq; 1150892f4c5SHidetoshi Shimokawa STAILQ_HEAD(, fw_bind) binds; 1160892f4c5SHidetoshi Shimokawa STAILQ_HEAD(, fw_xfer) rq; 1176cada79aSHidetoshi Shimokawa }; 1186cada79aSHidetoshi Shimokawa 1196cada79aSHidetoshi Shimokawa static int 1206cada79aSHidetoshi Shimokawa fwdev_allocbuf(struct firewire_comm *fc, struct fw_xferq *q, 1216cada79aSHidetoshi Shimokawa struct fw_bufspec *b) 1226cada79aSHidetoshi Shimokawa { 1236cada79aSHidetoshi Shimokawa int i; 1246cada79aSHidetoshi Shimokawa 1256cada79aSHidetoshi Shimokawa if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF)) 1266cada79aSHidetoshi Shimokawa return(EBUSY); 1276cada79aSHidetoshi Shimokawa 1286cada79aSHidetoshi Shimokawa q->bulkxfer = (struct fw_bulkxfer *) malloc( 1296cada79aSHidetoshi Shimokawa sizeof(struct fw_bulkxfer) * b->nchunk, 1306cada79aSHidetoshi Shimokawa M_FW, M_WAITOK); 1316cada79aSHidetoshi Shimokawa if (q->bulkxfer == NULL) 1326cada79aSHidetoshi Shimokawa return(ENOMEM); 1336cada79aSHidetoshi Shimokawa 13403161bbcSDoug Rabson b->psize = roundup2(b->psize, sizeof(uint32_t)); 13503161bbcSDoug Rabson q->buf = fwdma_malloc_multiseg(fc, sizeof(uint32_t), 1366cada79aSHidetoshi Shimokawa b->psize, b->nchunk * b->npacket, BUS_DMA_WAITOK); 1376cada79aSHidetoshi Shimokawa 1386cada79aSHidetoshi Shimokawa if (q->buf == NULL) { 1396cada79aSHidetoshi Shimokawa free(q->bulkxfer, M_FW); 1406cada79aSHidetoshi Shimokawa q->bulkxfer = NULL; 1416cada79aSHidetoshi Shimokawa return(ENOMEM); 1426cada79aSHidetoshi Shimokawa } 1436cada79aSHidetoshi Shimokawa q->bnchunk = b->nchunk; 1446cada79aSHidetoshi Shimokawa q->bnpacket = b->npacket; 1456cada79aSHidetoshi Shimokawa q->psize = (b->psize + 3) & ~3; 1466cada79aSHidetoshi Shimokawa q->queued = 0; 1476cada79aSHidetoshi Shimokawa 1486cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stvalid); 1496cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stfree); 1506cada79aSHidetoshi Shimokawa STAILQ_INIT(&q->stdma); 1516cada79aSHidetoshi Shimokawa q->stproc = NULL; 1526cada79aSHidetoshi Shimokawa 1536cada79aSHidetoshi Shimokawa for(i = 0 ; i < q->bnchunk; i++){ 1546cada79aSHidetoshi Shimokawa q->bulkxfer[i].poffset = i * q->bnpacket; 1556cada79aSHidetoshi Shimokawa q->bulkxfer[i].mbuf = NULL; 1566cada79aSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&q->stfree, &q->bulkxfer[i], link); 1576cada79aSHidetoshi Shimokawa } 1586cada79aSHidetoshi Shimokawa 1596cada79aSHidetoshi Shimokawa q->flag &= ~FWXFERQ_MODEMASK; 1606cada79aSHidetoshi Shimokawa q->flag |= FWXFERQ_STREAM; 1616cada79aSHidetoshi Shimokawa q->flag |= FWXFERQ_EXTBUF; 1626cada79aSHidetoshi Shimokawa 1636cada79aSHidetoshi Shimokawa return (0); 1646cada79aSHidetoshi Shimokawa } 1656cada79aSHidetoshi Shimokawa 1666cada79aSHidetoshi Shimokawa static int 1676cada79aSHidetoshi Shimokawa fwdev_freebuf(struct fw_xferq *q) 1686cada79aSHidetoshi Shimokawa { 1696cada79aSHidetoshi Shimokawa if (q->flag & FWXFERQ_EXTBUF) { 1706cada79aSHidetoshi Shimokawa if (q->buf != NULL) 1716cada79aSHidetoshi Shimokawa fwdma_free_multiseg(q->buf); 1726cada79aSHidetoshi Shimokawa q->buf = NULL; 1736cada79aSHidetoshi Shimokawa free(q->bulkxfer, M_FW); 1746cada79aSHidetoshi Shimokawa q->bulkxfer = NULL; 1756cada79aSHidetoshi Shimokawa q->flag &= ~FWXFERQ_EXTBUF; 1766cada79aSHidetoshi Shimokawa q->psize = 0; 1776cada79aSHidetoshi Shimokawa q->maxq = FWMAXQUEUE; 1786cada79aSHidetoshi Shimokawa } 1796cada79aSHidetoshi Shimokawa return (0); 1806cada79aSHidetoshi Shimokawa } 1816cada79aSHidetoshi Shimokawa 1826cada79aSHidetoshi Shimokawa 18317821895SHidetoshi Shimokawa static int 18489c9c53dSPoul-Henning Kamp fw_open (struct cdev *dev, int flags, int fmt, fw_proc *td) 18517821895SHidetoshi Shimokawa { 18617821895SHidetoshi Shimokawa int err = 0; 1870892f4c5SHidetoshi Shimokawa int unit = DEV2UNIT(dev); 1880892f4c5SHidetoshi Shimokawa struct fw_drv1 *d; 1890892f4c5SHidetoshi Shimokawa struct firewire_softc *sc; 19017821895SHidetoshi Shimokawa 19117821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 19217821895SHidetoshi Shimokawa return fwmem_open(dev, flags, fmt, td); 19317821895SHidetoshi Shimokawa 1949950b741SHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 1959950b741SHidetoshi Shimokawa if (sc == NULL) 1969950b741SHidetoshi Shimokawa return (ENXIO); 1979950b741SHidetoshi Shimokawa 1989950b741SHidetoshi Shimokawa FW_GLOCK(sc->fc); 1999950b741SHidetoshi Shimokawa if (dev->si_drv1 != NULL) { 2009950b741SHidetoshi Shimokawa FW_GUNLOCK(sc->fc); 2013a927c87SHidetoshi Shimokawa return (EBUSY); 2029950b741SHidetoshi Shimokawa } 2039950b741SHidetoshi Shimokawa /* set dummy value for allocation */ 2049950b741SHidetoshi Shimokawa dev->si_drv1 = (void *)-1; 2059950b741SHidetoshi Shimokawa FW_GUNLOCK(sc->fc); 2069950b741SHidetoshi Shimokawa 2079950b741SHidetoshi Shimokawa dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); 2089950b741SHidetoshi Shimokawa if (dev->si_drv1 == NULL) 2099950b741SHidetoshi Shimokawa return (ENOMEM); 2103a927c87SHidetoshi Shimokawa 21110d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 212a160e00eSHidetoshi Shimokawa if ((dev->si_flags & SI_NAMED) == 0) { 213a160e00eSHidetoshi Shimokawa int unit = DEV2UNIT(dev); 214a160e00eSHidetoshi Shimokawa int sub = DEV2SUB(dev); 215a160e00eSHidetoshi Shimokawa 2166bfa9a2dSEd Schouten make_dev(&firewire_cdevsw, dev2unit(dev), 2176cada79aSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 2186cada79aSHidetoshi Shimokawa "fw%d.%d", unit, sub); 219a160e00eSHidetoshi Shimokawa } 220a160e00eSHidetoshi Shimokawa #endif 2210892f4c5SHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 2220892f4c5SHidetoshi Shimokawa d->fc = sc->fc; 2230892f4c5SHidetoshi Shimokawa STAILQ_INIT(&d->binds); 2240892f4c5SHidetoshi Shimokawa STAILQ_INIT(&d->rq); 2256cada79aSHidetoshi Shimokawa 22617821895SHidetoshi Shimokawa return err; 22717821895SHidetoshi Shimokawa } 22817821895SHidetoshi Shimokawa 22917821895SHidetoshi Shimokawa static int 23089c9c53dSPoul-Henning Kamp fw_close (struct cdev *dev, int flags, int fmt, fw_proc *td) 23117821895SHidetoshi Shimokawa { 2326cada79aSHidetoshi Shimokawa struct firewire_comm *fc; 2336cada79aSHidetoshi Shimokawa struct fw_drv1 *d; 23417821895SHidetoshi Shimokawa struct fw_xfer *xfer; 23517821895SHidetoshi Shimokawa struct fw_bind *fwb; 23617821895SHidetoshi Shimokawa int err = 0; 23717821895SHidetoshi Shimokawa 23817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 23917821895SHidetoshi Shimokawa return fwmem_close(dev, flags, fmt, td); 24017821895SHidetoshi Shimokawa 2416cada79aSHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 2420892f4c5SHidetoshi Shimokawa fc = d->fc; 24317821895SHidetoshi Shimokawa 2440892f4c5SHidetoshi Shimokawa /* remove binding */ 2450892f4c5SHidetoshi Shimokawa for (fwb = STAILQ_FIRST(&d->binds); fwb != NULL; 2460892f4c5SHidetoshi Shimokawa fwb = STAILQ_FIRST(&d->binds)) { 2470892f4c5SHidetoshi Shimokawa fw_bindremove(fc, fwb); 2480892f4c5SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&d->binds, chlist); 2490892f4c5SHidetoshi Shimokawa fw_xferlist_remove(&fwb->xferlist); 2500892f4c5SHidetoshi Shimokawa free(fwb, M_FW); 2510892f4c5SHidetoshi Shimokawa } 2526cada79aSHidetoshi Shimokawa if (d->ir != NULL) { 2536cada79aSHidetoshi Shimokawa struct fw_xferq *ir = d->ir; 2546cada79aSHidetoshi Shimokawa 2556cada79aSHidetoshi Shimokawa if ((ir->flag & FWXFERQ_OPEN) == 0) 2566cada79aSHidetoshi Shimokawa return (EINVAL); 2576cada79aSHidetoshi Shimokawa if (ir->flag & FWXFERQ_RUNNING) { 2586cada79aSHidetoshi Shimokawa ir->flag &= ~FWXFERQ_RUNNING; 2596cada79aSHidetoshi Shimokawa fc->irx_disable(fc, ir->dmach); 26017821895SHidetoshi Shimokawa } 2616cada79aSHidetoshi Shimokawa /* free extbuf */ 2626cada79aSHidetoshi Shimokawa fwdev_freebuf(ir); 2636cada79aSHidetoshi Shimokawa /* drain receiving buffer */ 2646cada79aSHidetoshi Shimokawa for (xfer = STAILQ_FIRST(&ir->q); 2656cada79aSHidetoshi Shimokawa xfer != NULL; xfer = STAILQ_FIRST(&ir->q)) { 2666cada79aSHidetoshi Shimokawa ir->queued --; 2676cada79aSHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->q, link); 26817821895SHidetoshi Shimokawa 26917821895SHidetoshi Shimokawa xfer->resp = 0; 27017821895SHidetoshi Shimokawa fw_xfer_done(xfer); 27117821895SHidetoshi Shimokawa } 2726cada79aSHidetoshi Shimokawa ir->flag &= ~(FWXFERQ_OPEN | 2736cada79aSHidetoshi Shimokawa FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 2746cada79aSHidetoshi Shimokawa d->ir = NULL; 2756cada79aSHidetoshi Shimokawa 2766cada79aSHidetoshi Shimokawa } 2776cada79aSHidetoshi Shimokawa if (d->it != NULL) { 2786cada79aSHidetoshi Shimokawa struct fw_xferq *it = d->it; 2796cada79aSHidetoshi Shimokawa 2806cada79aSHidetoshi Shimokawa if ((it->flag & FWXFERQ_OPEN) == 0) 2816cada79aSHidetoshi Shimokawa return (EINVAL); 2826cada79aSHidetoshi Shimokawa if (it->flag & FWXFERQ_RUNNING) { 2836cada79aSHidetoshi Shimokawa it->flag &= ~FWXFERQ_RUNNING; 2846cada79aSHidetoshi Shimokawa fc->itx_disable(fc, it->dmach); 2856cada79aSHidetoshi Shimokawa } 2866cada79aSHidetoshi Shimokawa /* free extbuf */ 2876cada79aSHidetoshi Shimokawa fwdev_freebuf(it); 2886cada79aSHidetoshi Shimokawa it->flag &= ~(FWXFERQ_OPEN | 2896cada79aSHidetoshi Shimokawa FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 2906cada79aSHidetoshi Shimokawa d->it = NULL; 2916cada79aSHidetoshi Shimokawa } 2926cada79aSHidetoshi Shimokawa free(dev->si_drv1, M_FW); 2936cada79aSHidetoshi Shimokawa dev->si_drv1 = NULL; 2946cada79aSHidetoshi Shimokawa 29517821895SHidetoshi Shimokawa return err; 29617821895SHidetoshi Shimokawa } 29717821895SHidetoshi Shimokawa 2980892f4c5SHidetoshi Shimokawa static int 2990892f4c5SHidetoshi Shimokawa fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag) 3000892f4c5SHidetoshi Shimokawa { 3010892f4c5SHidetoshi Shimokawa int err = 0, s; 3020892f4c5SHidetoshi Shimokawa struct fw_xfer *xfer; 3030892f4c5SHidetoshi Shimokawa struct fw_bind *fwb; 3040892f4c5SHidetoshi Shimokawa struct fw_pkt *fp; 3050892f4c5SHidetoshi Shimokawa struct tcode_info *tinfo; 3060892f4c5SHidetoshi Shimokawa 3079950b741SHidetoshi Shimokawa FW_GLOCK(d->fc); 3080892f4c5SHidetoshi Shimokawa while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0) 3099950b741SHidetoshi Shimokawa err = msleep(&d->rq, FW_GMTX(d->fc), FWPRI, "fwra", 0); 3100892f4c5SHidetoshi Shimokawa 3119950b741SHidetoshi Shimokawa if (err != 0) { 3129950b741SHidetoshi Shimokawa FW_GUNLOCK(d->fc); 3130892f4c5SHidetoshi Shimokawa return (err); 3149950b741SHidetoshi Shimokawa } 3150892f4c5SHidetoshi Shimokawa 3160892f4c5SHidetoshi Shimokawa s = splfw(); 3170892f4c5SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&d->rq, link); 3189950b741SHidetoshi Shimokawa FW_GUNLOCK(xfer->fc); 3190892f4c5SHidetoshi Shimokawa splx(s); 3200892f4c5SHidetoshi Shimokawa fp = &xfer->recv.hdr; 3210892f4c5SHidetoshi Shimokawa #if 0 /* for GASP ?? */ 3220892f4c5SHidetoshi Shimokawa if (fc->irx_post != NULL) 3230892f4c5SHidetoshi Shimokawa fc->irx_post(fc, fp->mode.ld); 3240892f4c5SHidetoshi Shimokawa #endif 3250892f4c5SHidetoshi Shimokawa tinfo = &xfer->fc->tcode[fp->mode.hdr.tcode]; 3260892f4c5SHidetoshi Shimokawa err = uiomove((void *)fp, tinfo->hdr_len, uio); 3270892f4c5SHidetoshi Shimokawa if (err) 3280892f4c5SHidetoshi Shimokawa goto out; 3290892f4c5SHidetoshi Shimokawa err = uiomove((void *)xfer->recv.payload, xfer->recv.pay_len, uio); 3300892f4c5SHidetoshi Shimokawa 3310892f4c5SHidetoshi Shimokawa out: 3320892f4c5SHidetoshi Shimokawa /* recycle this xfer */ 3330892f4c5SHidetoshi Shimokawa fwb = (struct fw_bind *)xfer->sc; 3340892f4c5SHidetoshi Shimokawa fw_xfer_unload(xfer); 3350892f4c5SHidetoshi Shimokawa xfer->recv.pay_len = PAGE_SIZE; 3369950b741SHidetoshi Shimokawa FW_GLOCK(xfer->fc); 3370892f4c5SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link); 3389950b741SHidetoshi Shimokawa FW_GUNLOCK(xfer->fc); 3390892f4c5SHidetoshi Shimokawa return (err); 3400892f4c5SHidetoshi Shimokawa } 3410892f4c5SHidetoshi Shimokawa 34217821895SHidetoshi Shimokawa /* 34317821895SHidetoshi Shimokawa * read request. 34417821895SHidetoshi Shimokawa */ 34517821895SHidetoshi Shimokawa static int 34689c9c53dSPoul-Henning Kamp fw_read (struct cdev *dev, struct uio *uio, int ioflag) 34717821895SHidetoshi Shimokawa { 3480892f4c5SHidetoshi Shimokawa struct fw_drv1 *d; 34917821895SHidetoshi Shimokawa struct fw_xferq *ir; 3500892f4c5SHidetoshi Shimokawa struct firewire_comm *fc; 35117821895SHidetoshi Shimokawa int err = 0, s, slept = 0; 35217821895SHidetoshi Shimokawa struct fw_pkt *fp; 35317821895SHidetoshi Shimokawa 35417821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 3559950b741SHidetoshi Shimokawa return (physio(dev, uio, ioflag)); 35617821895SHidetoshi Shimokawa 3570892f4c5SHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 3580892f4c5SHidetoshi Shimokawa fc = d->fc; 3590892f4c5SHidetoshi Shimokawa ir = d->ir; 3600892f4c5SHidetoshi Shimokawa 3610892f4c5SHidetoshi Shimokawa if (ir == NULL) 3620892f4c5SHidetoshi Shimokawa return (fw_read_async(d, uio, ioflag)); 3630892f4c5SHidetoshi Shimokawa 3640892f4c5SHidetoshi Shimokawa if (ir->buf == NULL) 3656cada79aSHidetoshi Shimokawa return (EIO); 36617821895SHidetoshi Shimokawa 3679950b741SHidetoshi Shimokawa FW_GLOCK(fc); 36817821895SHidetoshi Shimokawa readloop: 36977ee030bSHidetoshi Shimokawa if (ir->stproc == NULL) { 370c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 37117821895SHidetoshi Shimokawa ir->stproc = STAILQ_FIRST(&ir->stvalid); 37217821895SHidetoshi Shimokawa if (ir->stproc != NULL) { 37317821895SHidetoshi Shimokawa s = splfw(); 37417821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&ir->stvalid, link); 37517821895SHidetoshi Shimokawa splx(s); 37617821895SHidetoshi Shimokawa ir->queued = 0; 37717821895SHidetoshi Shimokawa } 37817821895SHidetoshi Shimokawa } 3790892f4c5SHidetoshi Shimokawa if (ir->stproc == NULL) { 380c3e9e255SHidetoshi Shimokawa /* no data avaliable */ 38117821895SHidetoshi Shimokawa if (slept == 0) { 38217821895SHidetoshi Shimokawa slept = 1; 38317821895SHidetoshi Shimokawa ir->flag |= FWXFERQ_WAKEUP; 3849950b741SHidetoshi Shimokawa err = msleep(ir, FW_GMTX(fc), FWPRI, "fw_read", hz); 38517821895SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_WAKEUP; 386c3e9e255SHidetoshi Shimokawa if (err == 0) 38717821895SHidetoshi Shimokawa goto readloop; 388c3e9e255SHidetoshi Shimokawa } else if (slept == 1) 38917821895SHidetoshi Shimokawa err = EIO; 3909950b741SHidetoshi Shimokawa FW_GUNLOCK(fc); 39117821895SHidetoshi Shimokawa return err; 39217821895SHidetoshi Shimokawa } else if(ir->stproc != NULL) { 393c3e9e255SHidetoshi Shimokawa /* iso bulkxfer */ 3949950b741SHidetoshi Shimokawa FW_GUNLOCK(fc); 39577ee030bSHidetoshi Shimokawa fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, 39677ee030bSHidetoshi Shimokawa ir->stproc->poffset + ir->queued); 3970892f4c5SHidetoshi Shimokawa if(fc->irx_post != NULL) 3980892f4c5SHidetoshi Shimokawa fc->irx_post(fc, fp->mode.ld); 39977ee030bSHidetoshi Shimokawa if(fp->mode.stream.len == 0){ 40017821895SHidetoshi Shimokawa err = EIO; 40117821895SHidetoshi Shimokawa return err; 40217821895SHidetoshi Shimokawa } 403c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, 40403161bbcSDoug Rabson fp->mode.stream.len + sizeof(uint32_t), uio); 40517821895SHidetoshi Shimokawa ir->queued ++; 40617821895SHidetoshi Shimokawa if(ir->queued >= ir->bnpacket){ 40717821895SHidetoshi Shimokawa s = splfw(); 40817821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 40917821895SHidetoshi Shimokawa splx(s); 4100892f4c5SHidetoshi Shimokawa fc->irx_enable(fc, ir->dmach); 41117821895SHidetoshi Shimokawa ir->stproc = NULL; 41217821895SHidetoshi Shimokawa } 413c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= ir->psize) { 414c3e9e255SHidetoshi Shimokawa slept = -1; 4159950b741SHidetoshi Shimokawa FW_GLOCK(fc); 416c3e9e255SHidetoshi Shimokawa goto readloop; 417c3e9e255SHidetoshi Shimokawa } 41817821895SHidetoshi Shimokawa } 41917821895SHidetoshi Shimokawa return err; 42017821895SHidetoshi Shimokawa } 42117821895SHidetoshi Shimokawa 42217821895SHidetoshi Shimokawa static int 4230892f4c5SHidetoshi Shimokawa fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag) 4240892f4c5SHidetoshi Shimokawa { 4250892f4c5SHidetoshi Shimokawa struct fw_xfer *xfer; 4260892f4c5SHidetoshi Shimokawa struct fw_pkt pkt; 4270892f4c5SHidetoshi Shimokawa struct tcode_info *tinfo; 4280892f4c5SHidetoshi Shimokawa int err; 4290892f4c5SHidetoshi Shimokawa 4300892f4c5SHidetoshi Shimokawa bzero(&pkt, sizeof(struct fw_pkt)); 4310892f4c5SHidetoshi Shimokawa if ((err = uiomove((caddr_t)&pkt, sizeof(uint32_t), uio))) 4320892f4c5SHidetoshi Shimokawa return (err); 4330892f4c5SHidetoshi Shimokawa tinfo = &d->fc->tcode[pkt.mode.hdr.tcode]; 4340892f4c5SHidetoshi Shimokawa if ((err = uiomove((caddr_t)&pkt + sizeof(uint32_t), 4350892f4c5SHidetoshi Shimokawa tinfo->hdr_len - sizeof(uint32_t), uio))) 4360892f4c5SHidetoshi Shimokawa return (err); 4370892f4c5SHidetoshi Shimokawa 4380892f4c5SHidetoshi Shimokawa if ((xfer = fw_xfer_alloc_buf(M_FWXFER, uio->uio_resid, 4390892f4c5SHidetoshi Shimokawa PAGE_SIZE/*XXX*/)) == NULL) 4400892f4c5SHidetoshi Shimokawa return (ENOMEM); 4410892f4c5SHidetoshi Shimokawa 4420892f4c5SHidetoshi Shimokawa bcopy(&pkt, &xfer->send.hdr, sizeof(struct fw_pkt)); 4430892f4c5SHidetoshi Shimokawa xfer->send.pay_len = uio->uio_resid; 4440892f4c5SHidetoshi Shimokawa if (uio->uio_resid > 0) { 4450892f4c5SHidetoshi Shimokawa if ((err = uiomove((caddr_t)&xfer->send.payload[0], 44603cd51dfSRoman Divacky uio->uio_resid, uio))) 4470892f4c5SHidetoshi Shimokawa goto out; 4480892f4c5SHidetoshi Shimokawa } 4490892f4c5SHidetoshi Shimokawa 4500892f4c5SHidetoshi Shimokawa xfer->fc = d->fc; 4510892f4c5SHidetoshi Shimokawa xfer->sc = NULL; 4529950b741SHidetoshi Shimokawa xfer->hand = fw_xferwake; 4530892f4c5SHidetoshi Shimokawa xfer->send.spd = 2 /* XXX */; 4540892f4c5SHidetoshi Shimokawa 4550892f4c5SHidetoshi Shimokawa if ((err = fw_asyreq(xfer->fc, -1, xfer))) 4560892f4c5SHidetoshi Shimokawa goto out; 4570892f4c5SHidetoshi Shimokawa 4589950b741SHidetoshi Shimokawa if ((err = fw_xferwait(xfer))) 4590892f4c5SHidetoshi Shimokawa goto out; 4600892f4c5SHidetoshi Shimokawa 4610892f4c5SHidetoshi Shimokawa if (xfer->resp != 0) { 4620892f4c5SHidetoshi Shimokawa err = xfer->resp; 4630892f4c5SHidetoshi Shimokawa goto out; 4640892f4c5SHidetoshi Shimokawa } 4650892f4c5SHidetoshi Shimokawa 4669950b741SHidetoshi Shimokawa if (xfer->flag & FWXF_RCVD) { 4679950b741SHidetoshi Shimokawa FW_GLOCK(xfer->fc); 4680892f4c5SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&d->rq, xfer, link); 4699950b741SHidetoshi Shimokawa FW_GUNLOCK(xfer->fc); 4700892f4c5SHidetoshi Shimokawa return (0); 4710892f4c5SHidetoshi Shimokawa } 4720892f4c5SHidetoshi Shimokawa 4730892f4c5SHidetoshi Shimokawa out: 4740892f4c5SHidetoshi Shimokawa fw_xfer_free(xfer); 4750892f4c5SHidetoshi Shimokawa return (err); 4760892f4c5SHidetoshi Shimokawa } 4770892f4c5SHidetoshi Shimokawa 4780892f4c5SHidetoshi Shimokawa static int 47989c9c53dSPoul-Henning Kamp fw_write (struct cdev *dev, struct uio *uio, int ioflag) 48017821895SHidetoshi Shimokawa { 48117821895SHidetoshi Shimokawa int err = 0; 48217821895SHidetoshi Shimokawa int s, slept = 0; 4830892f4c5SHidetoshi Shimokawa struct fw_drv1 *d; 48417821895SHidetoshi Shimokawa struct fw_pkt *fp; 48517821895SHidetoshi Shimokawa struct firewire_comm *fc; 48617821895SHidetoshi Shimokawa struct fw_xferq *it; 48717821895SHidetoshi Shimokawa 48817821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 4899950b741SHidetoshi Shimokawa return (physio(dev, uio, ioflag)); 49017821895SHidetoshi Shimokawa 4910892f4c5SHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 4920892f4c5SHidetoshi Shimokawa fc = d->fc; 4930892f4c5SHidetoshi Shimokawa it = d->it; 4940892f4c5SHidetoshi Shimokawa 4950892f4c5SHidetoshi Shimokawa if (it == NULL) 4960892f4c5SHidetoshi Shimokawa return (fw_write_async(d, uio, ioflag)); 4970892f4c5SHidetoshi Shimokawa 4980892f4c5SHidetoshi Shimokawa if (it->buf == NULL) 4996cada79aSHidetoshi Shimokawa return (EIO); 5009950b741SHidetoshi Shimokawa 5019950b741SHidetoshi Shimokawa FW_GLOCK(fc); 50217821895SHidetoshi Shimokawa isoloop: 50317821895SHidetoshi Shimokawa if (it->stproc == NULL) { 50417821895SHidetoshi Shimokawa it->stproc = STAILQ_FIRST(&it->stfree); 50517821895SHidetoshi Shimokawa if (it->stproc != NULL) { 50617821895SHidetoshi Shimokawa s = splfw(); 50717821895SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&it->stfree, link); 50817821895SHidetoshi Shimokawa splx(s); 50917821895SHidetoshi Shimokawa it->queued = 0; 51017821895SHidetoshi Shimokawa } else if (slept == 0) { 51117821895SHidetoshi Shimokawa slept = 1; 5129950b741SHidetoshi Shimokawa #if 0 /* XXX to avoid lock recursion */ 5130892f4c5SHidetoshi Shimokawa err = fc->itx_enable(fc, it->dmach); 514c3e9e255SHidetoshi Shimokawa if (err) 5159950b741SHidetoshi Shimokawa goto out; 5169950b741SHidetoshi Shimokawa #endif 5179950b741SHidetoshi Shimokawa err = msleep(it, FW_GMTX(fc), FWPRI, "fw_write", hz); 518c3e9e255SHidetoshi Shimokawa if (err) 5199950b741SHidetoshi Shimokawa goto out; 52017821895SHidetoshi Shimokawa goto isoloop; 52117821895SHidetoshi Shimokawa } else { 52217821895SHidetoshi Shimokawa err = EIO; 5239950b741SHidetoshi Shimokawa goto out; 52417821895SHidetoshi Shimokawa } 52517821895SHidetoshi Shimokawa } 5269950b741SHidetoshi Shimokawa FW_GUNLOCK(fc); 52777ee030bSHidetoshi Shimokawa fp = (struct fw_pkt *)fwdma_v_addr(it->buf, 52877ee030bSHidetoshi Shimokawa it->stproc->poffset + it->queued); 529c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 530c3e9e255SHidetoshi Shimokawa err = uiomove((caddr_t)fp->mode.stream.payload, 53177ee030bSHidetoshi Shimokawa fp->mode.stream.len, uio); 53217821895SHidetoshi Shimokawa it->queued ++; 533c3e9e255SHidetoshi Shimokawa if (it->queued >= it->bnpacket) { 53417821895SHidetoshi Shimokawa s = splfw(); 53517821895SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 53617821895SHidetoshi Shimokawa splx(s); 53717821895SHidetoshi Shimokawa it->stproc = NULL; 5380892f4c5SHidetoshi Shimokawa err = fc->itx_enable(fc, it->dmach); 53917821895SHidetoshi Shimokawa } 540c3e9e255SHidetoshi Shimokawa if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 541c3e9e255SHidetoshi Shimokawa slept = 0; 5429950b741SHidetoshi Shimokawa FW_GLOCK(fc); 543c3e9e255SHidetoshi Shimokawa goto isoloop; 544c3e9e255SHidetoshi Shimokawa } 54517821895SHidetoshi Shimokawa return err; 5469950b741SHidetoshi Shimokawa 5479950b741SHidetoshi Shimokawa out: 5489950b741SHidetoshi Shimokawa FW_GUNLOCK(fc); 5499950b741SHidetoshi Shimokawa return err; 5509190691bSHidetoshi Shimokawa } 5510892f4c5SHidetoshi Shimokawa 5520892f4c5SHidetoshi Shimokawa static void 5530892f4c5SHidetoshi Shimokawa fw_hand(struct fw_xfer *xfer) 5540892f4c5SHidetoshi Shimokawa { 5550892f4c5SHidetoshi Shimokawa struct fw_bind *fwb; 5560892f4c5SHidetoshi Shimokawa struct fw_drv1 *d; 5570892f4c5SHidetoshi Shimokawa 5580892f4c5SHidetoshi Shimokawa fwb = (struct fw_bind *)xfer->sc; 5590892f4c5SHidetoshi Shimokawa d = (struct fw_drv1 *)fwb->sc; 5609950b741SHidetoshi Shimokawa FW_GLOCK(xfer->fc); 5610892f4c5SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&d->rq, xfer, link); 5629950b741SHidetoshi Shimokawa FW_GUNLOCK(xfer->fc); 5630892f4c5SHidetoshi Shimokawa wakeup(&d->rq); 5640892f4c5SHidetoshi Shimokawa } 5650892f4c5SHidetoshi Shimokawa 56617821895SHidetoshi Shimokawa /* 56717821895SHidetoshi Shimokawa * ioctl support. 56817821895SHidetoshi Shimokawa */ 56917821895SHidetoshi Shimokawa int 57089c9c53dSPoul-Henning Kamp fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 57117821895SHidetoshi Shimokawa { 5726cada79aSHidetoshi Shimokawa struct firewire_comm *fc; 5736cada79aSHidetoshi Shimokawa struct fw_drv1 *d; 5740892f4c5SHidetoshi Shimokawa int i, len, err = 0; 57517821895SHidetoshi Shimokawa struct fw_device *fwdev; 57617821895SHidetoshi Shimokawa struct fw_bind *fwb; 57717821895SHidetoshi Shimokawa struct fw_xferq *ir, *it; 57817821895SHidetoshi Shimokawa struct fw_xfer *xfer; 57917821895SHidetoshi Shimokawa struct fw_pkt *fp; 580c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 581d7e486b4SHidetoshi Shimokawa void *ptr; 58217821895SHidetoshi Shimokawa 58317821895SHidetoshi Shimokawa struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 58417821895SHidetoshi Shimokawa struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 58517821895SHidetoshi Shimokawa struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 58617821895SHidetoshi Shimokawa struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 58717821895SHidetoshi Shimokawa struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 58817821895SHidetoshi Shimokawa struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 58917821895SHidetoshi Shimokawa 59017821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 59117821895SHidetoshi Shimokawa return fwmem_ioctl(dev, cmd, data, flag, td); 59217821895SHidetoshi Shimokawa 59317821895SHidetoshi Shimokawa if (!data) 59417821895SHidetoshi Shimokawa return(EINVAL); 59517821895SHidetoshi Shimokawa 5966cada79aSHidetoshi Shimokawa d = (struct fw_drv1 *)dev->si_drv1; 5970892f4c5SHidetoshi Shimokawa fc = d->fc; 5986cada79aSHidetoshi Shimokawa ir = d->ir; 5996cada79aSHidetoshi Shimokawa it = d->it; 6006cada79aSHidetoshi Shimokawa 60117821895SHidetoshi Shimokawa switch (cmd) { 60217821895SHidetoshi Shimokawa case FW_STSTREAM: 6036cada79aSHidetoshi Shimokawa if (it == NULL) { 6049950b741SHidetoshi Shimokawa i = fw_open_isodma(fc, /* tx */1); 6059950b741SHidetoshi Shimokawa if (i < 0) { 6066cada79aSHidetoshi Shimokawa err = EBUSY; 6076cada79aSHidetoshi Shimokawa break; 6086cada79aSHidetoshi Shimokawa } 6099950b741SHidetoshi Shimokawa it = fc->it[i]; 6106cada79aSHidetoshi Shimokawa err = fwdev_allocbuf(fc, it, &d->bufreq.tx); 6119950b741SHidetoshi Shimokawa if (err) { 6129950b741SHidetoshi Shimokawa it->flag &= ~FWXFERQ_OPEN; 6136cada79aSHidetoshi Shimokawa break; 6149950b741SHidetoshi Shimokawa } 6156cada79aSHidetoshi Shimokawa } 6166cada79aSHidetoshi Shimokawa it->flag &= ~0xff; 6176cada79aSHidetoshi Shimokawa it->flag |= (0x3f & ichreq->ch); 6186cada79aSHidetoshi Shimokawa it->flag |= ((0x3 & ichreq->tag) << 6); 6196cada79aSHidetoshi Shimokawa d->it = it; 62017821895SHidetoshi Shimokawa break; 62117821895SHidetoshi Shimokawa case FW_GTSTREAM: 6226cada79aSHidetoshi Shimokawa if (it != NULL) { 6236cada79aSHidetoshi Shimokawa ichreq->ch = it->flag & 0x3f; 6246cada79aSHidetoshi Shimokawa ichreq->tag = it->flag >> 2 & 0x3; 6256cada79aSHidetoshi Shimokawa } else 6266cada79aSHidetoshi Shimokawa err = EINVAL; 62717821895SHidetoshi Shimokawa break; 62817821895SHidetoshi Shimokawa case FW_SRSTREAM: 6296cada79aSHidetoshi Shimokawa if (ir == NULL) { 6309950b741SHidetoshi Shimokawa i = fw_open_isodma(fc, /* tx */0); 6319950b741SHidetoshi Shimokawa if (i < 0) { 6326cada79aSHidetoshi Shimokawa err = EBUSY; 6336cada79aSHidetoshi Shimokawa break; 6346cada79aSHidetoshi Shimokawa } 6359950b741SHidetoshi Shimokawa ir = fc->ir[i]; 6366cada79aSHidetoshi Shimokawa err = fwdev_allocbuf(fc, ir, &d->bufreq.rx); 6379950b741SHidetoshi Shimokawa if (err) { 6389950b741SHidetoshi Shimokawa ir->flag &= ~FWXFERQ_OPEN; 6396cada79aSHidetoshi Shimokawa break; 6409950b741SHidetoshi Shimokawa } 6416cada79aSHidetoshi Shimokawa } 6426cada79aSHidetoshi Shimokawa ir->flag &= ~0xff; 6436cada79aSHidetoshi Shimokawa ir->flag |= (0x3f & ichreq->ch); 6446cada79aSHidetoshi Shimokawa ir->flag |= ((0x3 & ichreq->tag) << 6); 6456cada79aSHidetoshi Shimokawa d->ir = ir; 6466cada79aSHidetoshi Shimokawa err = fc->irx_enable(fc, ir->dmach); 64717821895SHidetoshi Shimokawa break; 64817821895SHidetoshi Shimokawa case FW_GRSTREAM: 6496cada79aSHidetoshi Shimokawa if (d->ir != NULL) { 6506cada79aSHidetoshi Shimokawa ichreq->ch = ir->flag & 0x3f; 6516cada79aSHidetoshi Shimokawa ichreq->tag = ir->flag >> 2 & 0x3; 6526cada79aSHidetoshi Shimokawa } else 6536cada79aSHidetoshi Shimokawa err = EINVAL; 65417821895SHidetoshi Shimokawa break; 65517821895SHidetoshi Shimokawa case FW_SSTBUF: 6566cada79aSHidetoshi Shimokawa bcopy(ibufreq, &d->bufreq, sizeof(d->bufreq)); 65717821895SHidetoshi Shimokawa break; 65817821895SHidetoshi Shimokawa case FW_GSTBUF: 6596cada79aSHidetoshi Shimokawa bzero(&ibufreq->rx, sizeof(ibufreq->rx)); 6606cada79aSHidetoshi Shimokawa if (ir != NULL) { 6616cada79aSHidetoshi Shimokawa ibufreq->rx.nchunk = ir->bnchunk; 6626cada79aSHidetoshi Shimokawa ibufreq->rx.npacket = ir->bnpacket; 6636cada79aSHidetoshi Shimokawa ibufreq->rx.psize = ir->psize; 6646cada79aSHidetoshi Shimokawa } 6656cada79aSHidetoshi Shimokawa bzero(&ibufreq->tx, sizeof(ibufreq->tx)); 6666cada79aSHidetoshi Shimokawa if (it != NULL) { 6676cada79aSHidetoshi Shimokawa ibufreq->tx.nchunk = it->bnchunk; 6686cada79aSHidetoshi Shimokawa ibufreq->tx.npacket = it->bnpacket; 6696cada79aSHidetoshi Shimokawa ibufreq->tx.psize = it->psize; 6706cada79aSHidetoshi Shimokawa } 67117821895SHidetoshi Shimokawa break; 67217821895SHidetoshi Shimokawa case FW_ASYREQ: 673c4778b5dSHidetoshi Shimokawa { 674c4778b5dSHidetoshi Shimokawa struct tcode_info *tinfo; 675102ebc1fSHidetoshi Shimokawa int pay_len = 0; 676c4778b5dSHidetoshi Shimokawa 67717821895SHidetoshi Shimokawa fp = &asyreq->pkt; 6780892f4c5SHidetoshi Shimokawa tinfo = &fc->tcode[fp->mode.hdr.tcode]; 679102ebc1fSHidetoshi Shimokawa 680102ebc1fSHidetoshi Shimokawa if ((tinfo->flag & FWTI_BLOCK_ASY) != 0) 681102ebc1fSHidetoshi Shimokawa pay_len = MAX(0, asyreq->req.len - tinfo->hdr_len); 682102ebc1fSHidetoshi Shimokawa 683102ebc1fSHidetoshi Shimokawa xfer = fw_xfer_alloc_buf(M_FWXFER, pay_len, PAGE_SIZE/*XXX*/); 684102ebc1fSHidetoshi Shimokawa if (xfer == NULL) 685102ebc1fSHidetoshi Shimokawa return (ENOMEM); 686102ebc1fSHidetoshi Shimokawa 68717821895SHidetoshi Shimokawa switch (asyreq->req.type) { 68817821895SHidetoshi Shimokawa case FWASREQNODE: 68917821895SHidetoshi Shimokawa break; 69017821895SHidetoshi Shimokawa case FWASREQEUI: 6910892f4c5SHidetoshi Shimokawa fwdev = fw_noderesolve_eui64(fc, 692233b1b97SHidetoshi Shimokawa &asyreq->req.dst.eui); 69317821895SHidetoshi Shimokawa if (fwdev == NULL) { 6940892f4c5SHidetoshi Shimokawa device_printf(fc->bdev, 69517faeefcSHidetoshi Shimokawa "cannot find node\n"); 69617821895SHidetoshi Shimokawa err = EINVAL; 697102ebc1fSHidetoshi Shimokawa goto out; 69817821895SHidetoshi Shimokawa } 699c4778b5dSHidetoshi Shimokawa fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst; 70017821895SHidetoshi Shimokawa break; 70117821895SHidetoshi Shimokawa case FWASRESTL: 70217821895SHidetoshi Shimokawa /* XXX what's this? */ 70317821895SHidetoshi Shimokawa break; 70417821895SHidetoshi Shimokawa case FWASREQSTREAM: 70517821895SHidetoshi Shimokawa /* nothing to do */ 70617821895SHidetoshi Shimokawa break; 70717821895SHidetoshi Shimokawa } 708102ebc1fSHidetoshi Shimokawa 709c4778b5dSHidetoshi Shimokawa bcopy(fp, (void *)&xfer->send.hdr, tinfo->hdr_len); 710102ebc1fSHidetoshi Shimokawa if (pay_len > 0) 711c4778b5dSHidetoshi Shimokawa bcopy((char *)fp + tinfo->hdr_len, 712a832f947SHidetoshi Shimokawa (void *)xfer->send.payload, pay_len); 713102ebc1fSHidetoshi Shimokawa xfer->send.spd = asyreq->req.sped; 7149950b741SHidetoshi Shimokawa xfer->hand = fw_xferwake; 715102ebc1fSHidetoshi Shimokawa 7160892f4c5SHidetoshi Shimokawa if ((err = fw_asyreq(fc, -1, xfer)) != 0) 717102ebc1fSHidetoshi Shimokawa goto out; 7189950b741SHidetoshi Shimokawa if ((err = fw_xferwait(xfer)) != 0) 719102ebc1fSHidetoshi Shimokawa goto out; 720c4778b5dSHidetoshi Shimokawa if (xfer->resp != 0) { 721c4778b5dSHidetoshi Shimokawa err = EIO; 722102ebc1fSHidetoshi Shimokawa goto out; 723c4778b5dSHidetoshi Shimokawa } 724102ebc1fSHidetoshi Shimokawa if ((tinfo->flag & FWTI_TLABEL) == 0) 725102ebc1fSHidetoshi Shimokawa goto out; 726102ebc1fSHidetoshi Shimokawa 727102ebc1fSHidetoshi Shimokawa /* copy response */ 7280892f4c5SHidetoshi Shimokawa tinfo = &fc->tcode[xfer->recv.hdr.mode.hdr.tcode]; 7297b1f6286SDoug Rabson if (xfer->recv.hdr.mode.hdr.tcode == FWTCODE_RRESB || 7307b1f6286SDoug Rabson xfer->recv.hdr.mode.hdr.tcode == FWTCODE_LRES) { 7317b1f6286SDoug Rabson pay_len = xfer->recv.pay_len; 7327b1f6286SDoug Rabson if (asyreq->req.len >= xfer->recv.pay_len + tinfo->hdr_len) { 7337b1f6286SDoug Rabson asyreq->req.len = xfer->recv.pay_len + 7347b1f6286SDoug Rabson tinfo->hdr_len; 7357b1f6286SDoug Rabson } else { 73617821895SHidetoshi Shimokawa err = EINVAL; 7377b1f6286SDoug Rabson pay_len = 0; 7387b1f6286SDoug Rabson } 7397b1f6286SDoug Rabson } else { 7407b1f6286SDoug Rabson pay_len = 0; 7417b1f6286SDoug Rabson } 742c4778b5dSHidetoshi Shimokawa bcopy(&xfer->recv.hdr, fp, tinfo->hdr_len); 7437b1f6286SDoug Rabson bcopy(xfer->recv.payload, (char *)fp + tinfo->hdr_len, pay_len); 744102ebc1fSHidetoshi Shimokawa out: 745c4778b5dSHidetoshi Shimokawa fw_xfer_free_buf(xfer); 74617821895SHidetoshi Shimokawa break; 747c4778b5dSHidetoshi Shimokawa } 74817821895SHidetoshi Shimokawa case FW_IBUSRST: 7490892f4c5SHidetoshi Shimokawa fc->ibr(fc); 75017821895SHidetoshi Shimokawa break; 75117821895SHidetoshi Shimokawa case FW_CBINDADDR: 7520892f4c5SHidetoshi Shimokawa fwb = fw_bindlookup(fc, 75317821895SHidetoshi Shimokawa bindreq->start.hi, bindreq->start.lo); 75417821895SHidetoshi Shimokawa if(fwb == NULL){ 75517821895SHidetoshi Shimokawa err = EINVAL; 75617821895SHidetoshi Shimokawa break; 75717821895SHidetoshi Shimokawa } 7580892f4c5SHidetoshi Shimokawa fw_bindremove(fc, fwb); 7590892f4c5SHidetoshi Shimokawa STAILQ_REMOVE(&d->binds, fwb, fw_bind, chlist); 7600892f4c5SHidetoshi Shimokawa fw_xferlist_remove(&fwb->xferlist); 7615166f1dfSHidetoshi Shimokawa free(fwb, M_FW); 76217821895SHidetoshi Shimokawa break; 76317821895SHidetoshi Shimokawa case FW_SBINDADDR: 76417821895SHidetoshi Shimokawa if(bindreq->len <= 0 ){ 76517821895SHidetoshi Shimokawa err = EINVAL; 76617821895SHidetoshi Shimokawa break; 76717821895SHidetoshi Shimokawa } 76817821895SHidetoshi Shimokawa if(bindreq->start.hi > 0xffff ){ 76917821895SHidetoshi Shimokawa err = EINVAL; 77017821895SHidetoshi Shimokawa break; 77117821895SHidetoshi Shimokawa } 7729950b741SHidetoshi Shimokawa fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_WAITOK); 77317821895SHidetoshi Shimokawa if(fwb == NULL){ 77417821895SHidetoshi Shimokawa err = ENOMEM; 77517821895SHidetoshi Shimokawa break; 77617821895SHidetoshi Shimokawa } 777c4778b5dSHidetoshi Shimokawa fwb->start = ((u_int64_t)bindreq->start.hi << 32) | 778c4778b5dSHidetoshi Shimokawa bindreq->start.lo; 779c4778b5dSHidetoshi Shimokawa fwb->end = fwb->start + bindreq->len; 7800892f4c5SHidetoshi Shimokawa fwb->sc = (void *)d; 78177ee030bSHidetoshi Shimokawa STAILQ_INIT(&fwb->xferlist); 7820892f4c5SHidetoshi Shimokawa err = fw_bindadd(fc, fwb); 7830892f4c5SHidetoshi Shimokawa if (err == 0) { 7840892f4c5SHidetoshi Shimokawa fw_xferlist_add(&fwb->xferlist, M_FWXFER, 7850892f4c5SHidetoshi Shimokawa /* XXX */ 7860892f4c5SHidetoshi Shimokawa PAGE_SIZE, PAGE_SIZE, 5, 7870892f4c5SHidetoshi Shimokawa fc, (void *)fwb, fw_hand); 7880892f4c5SHidetoshi Shimokawa STAILQ_INSERT_TAIL(&d->binds, fwb, chlist); 7890892f4c5SHidetoshi Shimokawa } 79017821895SHidetoshi Shimokawa break; 79117821895SHidetoshi Shimokawa case FW_GDEVLST: 792c547b896SHidetoshi Shimokawa i = len = 1; 793c547b896SHidetoshi Shimokawa /* myself */ 794c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[0]; 7950892f4c5SHidetoshi Shimokawa devinfo->dst = fc->nodeid; 796c547b896SHidetoshi Shimokawa devinfo->status = 0; /* XXX */ 7970892f4c5SHidetoshi Shimokawa devinfo->eui.hi = fc->eui.hi; 7980892f4c5SHidetoshi Shimokawa devinfo->eui.lo = fc->eui.lo; 7990892f4c5SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &fc->devices, link) { 800c547b896SHidetoshi Shimokawa if(len < FW_MAX_DEVLST){ 801c547b896SHidetoshi Shimokawa devinfo = &fwdevlst->dev[len++]; 802c547b896SHidetoshi Shimokawa devinfo->dst = fwdev->dst; 803c547b896SHidetoshi Shimokawa devinfo->status = 804c547b896SHidetoshi Shimokawa (fwdev->status == FWDEVINVAL)?0:1; 805c547b896SHidetoshi Shimokawa devinfo->eui.hi = fwdev->eui.hi; 806c547b896SHidetoshi Shimokawa devinfo->eui.lo = fwdev->eui.lo; 80717821895SHidetoshi Shimokawa } 80817821895SHidetoshi Shimokawa i++; 80917821895SHidetoshi Shimokawa } 81017821895SHidetoshi Shimokawa fwdevlst->n = i; 811c547b896SHidetoshi Shimokawa fwdevlst->info_len = len; 81217821895SHidetoshi Shimokawa break; 81317821895SHidetoshi Shimokawa case FW_GTPMAP: 8140892f4c5SHidetoshi Shimokawa bcopy(fc->topology_map, data, 8150892f4c5SHidetoshi Shimokawa (fc->topology_map->crc_len + 1) * 4); 81617821895SHidetoshi Shimokawa break; 81717821895SHidetoshi Shimokawa case FW_GCROM: 8180892f4c5SHidetoshi Shimokawa STAILQ_FOREACH(fwdev, &fc->devices, link) 8190981f5f0SHidetoshi Shimokawa if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 82017821895SHidetoshi Shimokawa break; 82117821895SHidetoshi Shimokawa if (fwdev == NULL) { 8220892f4c5SHidetoshi Shimokawa if (!FW_EUI64_EQUAL(fc->eui, crom_buf->eui)) { 82317821895SHidetoshi Shimokawa err = FWNODE_INVAL; 82417821895SHidetoshi Shimokawa break; 82517821895SHidetoshi Shimokawa } 826d7e486b4SHidetoshi Shimokawa /* myself */ 827d7e486b4SHidetoshi Shimokawa ptr = malloc(CROMSIZE, M_FW, M_WAITOK); 828d7e486b4SHidetoshi Shimokawa len = CROMSIZE; 829d7e486b4SHidetoshi Shimokawa for (i = 0; i < CROMSIZE/4; i++) 83003161bbcSDoug Rabson ((uint32_t *)ptr)[i] 8310892f4c5SHidetoshi Shimokawa = ntohl(fc->config_rom[i]); 832d7e486b4SHidetoshi Shimokawa } else { 833d7e486b4SHidetoshi Shimokawa /* found */ 834d7e486b4SHidetoshi Shimokawa ptr = (void *)&fwdev->csrrom[0]; 83517821895SHidetoshi Shimokawa if (fwdev->rommax < CSRROMOFF) 83617821895SHidetoshi Shimokawa len = 0; 83717821895SHidetoshi Shimokawa else 83817821895SHidetoshi Shimokawa len = fwdev->rommax - CSRROMOFF + 4; 839d7e486b4SHidetoshi Shimokawa } 840e340a7acSHidetoshi Shimokawa if (crom_buf->len < len) 84117821895SHidetoshi Shimokawa len = crom_buf->len; 84217821895SHidetoshi Shimokawa else 84317821895SHidetoshi Shimokawa crom_buf->len = len; 844d7e486b4SHidetoshi Shimokawa err = copyout(ptr, crom_buf->ptr, len); 845d7e486b4SHidetoshi Shimokawa if (fwdev == NULL) 846d7e486b4SHidetoshi Shimokawa /* myself */ 847d7e486b4SHidetoshi Shimokawa free(ptr, M_FW); 84817821895SHidetoshi Shimokawa break; 84917821895SHidetoshi Shimokawa default: 8500892f4c5SHidetoshi Shimokawa fc->ioctl (dev, cmd, data, flag, td); 85117821895SHidetoshi Shimokawa break; 85217821895SHidetoshi Shimokawa } 85317821895SHidetoshi Shimokawa return err; 85417821895SHidetoshi Shimokawa } 85517821895SHidetoshi Shimokawa int 85689c9c53dSPoul-Henning Kamp fw_poll(struct cdev *dev, int events, fw_proc *td) 85717821895SHidetoshi Shimokawa { 8586cada79aSHidetoshi Shimokawa struct fw_xferq *ir; 85917821895SHidetoshi Shimokawa int revents; 86017821895SHidetoshi Shimokawa int tmp; 86117821895SHidetoshi Shimokawa 86217821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 86317821895SHidetoshi Shimokawa return fwmem_poll(dev, events, td); 86417821895SHidetoshi Shimokawa 8656cada79aSHidetoshi Shimokawa ir = ((struct fw_drv1 *)dev->si_drv1)->ir; 86617821895SHidetoshi Shimokawa revents = 0; 86717821895SHidetoshi Shimokawa tmp = POLLIN | POLLRDNORM; 86817821895SHidetoshi Shimokawa if (events & tmp) { 8696cada79aSHidetoshi Shimokawa if (STAILQ_FIRST(&ir->q) != NULL) 87017821895SHidetoshi Shimokawa revents |= tmp; 87117821895SHidetoshi Shimokawa else 8726cada79aSHidetoshi Shimokawa selrecord(td, &ir->rsel); 87317821895SHidetoshi Shimokawa } 87417821895SHidetoshi Shimokawa tmp = POLLOUT | POLLWRNORM; 87517821895SHidetoshi Shimokawa if (events & tmp) { 87617821895SHidetoshi Shimokawa /* XXX should be fixed */ 87717821895SHidetoshi Shimokawa revents |= tmp; 87817821895SHidetoshi Shimokawa } 87917821895SHidetoshi Shimokawa 88017821895SHidetoshi Shimokawa return revents; 88117821895SHidetoshi Shimokawa } 88217821895SHidetoshi Shimokawa 88317821895SHidetoshi Shimokawa static int 88410d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500102 88589c9c53dSPoul-Henning Kamp fw_mmap (struct cdev *dev, vm_offset_t offset, int nproto) 88645545499SHidetoshi Shimokawa #else 88789c9c53dSPoul-Henning Kamp fw_mmap (struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) 88845545499SHidetoshi Shimokawa #endif 88917821895SHidetoshi Shimokawa { 89017821895SHidetoshi Shimokawa 89117821895SHidetoshi Shimokawa if (DEV_FWMEM(dev)) 89210d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500102 89345545499SHidetoshi Shimokawa return fwmem_mmap(dev, offset, nproto); 89445545499SHidetoshi Shimokawa #else 89507159f9cSMaxime Henrion return fwmem_mmap(dev, offset, paddr, nproto); 89645545499SHidetoshi Shimokawa #endif 89717821895SHidetoshi Shimokawa 89817821895SHidetoshi Shimokawa return EINVAL; 89917821895SHidetoshi Shimokawa } 900a160e00eSHidetoshi Shimokawa 901c4778b5dSHidetoshi Shimokawa static void 902c4778b5dSHidetoshi Shimokawa fw_strategy(struct bio *bp) 903c4778b5dSHidetoshi Shimokawa { 90489c9c53dSPoul-Henning Kamp struct cdev *dev; 905c4778b5dSHidetoshi Shimokawa 906c4778b5dSHidetoshi Shimokawa dev = bp->bio_dev; 907c4778b5dSHidetoshi Shimokawa if (DEV_FWMEM(dev)) { 908c4778b5dSHidetoshi Shimokawa fwmem_strategy(bp); 909c4778b5dSHidetoshi Shimokawa return; 910c4778b5dSHidetoshi Shimokawa } 911c4778b5dSHidetoshi Shimokawa 912c4778b5dSHidetoshi Shimokawa bp->bio_error = EOPNOTSUPP; 913c4778b5dSHidetoshi Shimokawa bp->bio_flags |= BIO_ERROR; 914c4778b5dSHidetoshi Shimokawa bp->bio_resid = bp->bio_bcount; 915c4778b5dSHidetoshi Shimokawa biodone(bp); 916c4778b5dSHidetoshi Shimokawa } 917c4778b5dSHidetoshi Shimokawa 918a160e00eSHidetoshi Shimokawa int 919a160e00eSHidetoshi Shimokawa fwdev_makedev(struct firewire_softc *sc) 920a160e00eSHidetoshi Shimokawa { 921a160e00eSHidetoshi Shimokawa int err = 0; 922a160e00eSHidetoshi Shimokawa 92310d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 92410d3ed64SHidetoshi Shimokawa cdevsw_add(&firewire_cdevsw); 92510d3ed64SHidetoshi Shimokawa #else 92689c9c53dSPoul-Henning Kamp struct cdev *d; 927a160e00eSHidetoshi Shimokawa int unit; 928a160e00eSHidetoshi Shimokawa 929a160e00eSHidetoshi Shimokawa unit = device_get_unit(sc->fc->bdev); 930a160e00eSHidetoshi Shimokawa sc->dev = make_dev(&firewire_cdevsw, MAKEMINOR(0, unit, 0), 931a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 932a160e00eSHidetoshi Shimokawa "fw%d.%d", unit, 0); 933a160e00eSHidetoshi Shimokawa d = make_dev(&firewire_cdevsw, 934a160e00eSHidetoshi Shimokawa MAKEMINOR(FWMEM_FLAG, unit, 0), 935a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 936a160e00eSHidetoshi Shimokawa "fwmem%d.%d", unit, 0); 937a160e00eSHidetoshi Shimokawa dev_depends(sc->dev, d); 938a160e00eSHidetoshi Shimokawa make_dev_alias(sc->dev, "fw%d", unit); 939a160e00eSHidetoshi Shimokawa make_dev_alias(d, "fwmem%d", unit); 940a160e00eSHidetoshi Shimokawa #endif 941a160e00eSHidetoshi Shimokawa 942a160e00eSHidetoshi Shimokawa return (err); 943a160e00eSHidetoshi Shimokawa } 944a160e00eSHidetoshi Shimokawa 945a160e00eSHidetoshi Shimokawa int 946a160e00eSHidetoshi Shimokawa fwdev_destroydev(struct firewire_softc *sc) 947a160e00eSHidetoshi Shimokawa { 948a160e00eSHidetoshi Shimokawa int err = 0; 949a160e00eSHidetoshi Shimokawa 95010d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 951a160e00eSHidetoshi Shimokawa cdevsw_remove(&firewire_cdevsw); 95210d3ed64SHidetoshi Shimokawa #else 95310d3ed64SHidetoshi Shimokawa destroy_dev(sc->dev); 954a160e00eSHidetoshi Shimokawa #endif 955a160e00eSHidetoshi Shimokawa return (err); 956a160e00eSHidetoshi Shimokawa } 957a160e00eSHidetoshi Shimokawa 95810d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 959a160e00eSHidetoshi Shimokawa #define NDEVTYPE 2 960a160e00eSHidetoshi Shimokawa void 9616a113b3dSRobert Watson fwdev_clone(void *arg, struct ucred *cred, char *name, int namelen, 9626a113b3dSRobert Watson struct cdev **dev) 963a160e00eSHidetoshi Shimokawa { 964a160e00eSHidetoshi Shimokawa struct firewire_softc *sc; 965a160e00eSHidetoshi Shimokawa char *devnames[NDEVTYPE] = {"fw", "fwmem"}; 966a160e00eSHidetoshi Shimokawa char *subp = NULL; 967a160e00eSHidetoshi Shimokawa int devflag[NDEVTYPE] = {0, FWMEM_FLAG}; 968a160e00eSHidetoshi Shimokawa int i, unit = 0, sub = 0; 969a160e00eSHidetoshi Shimokawa 970f3732fd1SPoul-Henning Kamp if (*dev != NULL) 971a160e00eSHidetoshi Shimokawa return; 972a160e00eSHidetoshi Shimokawa 973a160e00eSHidetoshi Shimokawa for (i = 0; i < NDEVTYPE; i++) 974c727011aSHidetoshi Shimokawa if (dev_stdclone(name, &subp, devnames[i], &unit) == 2) 975a160e00eSHidetoshi Shimokawa goto found; 976a160e00eSHidetoshi Shimokawa /* not match */ 977a160e00eSHidetoshi Shimokawa return; 978a160e00eSHidetoshi Shimokawa found: 979a160e00eSHidetoshi Shimokawa 980a160e00eSHidetoshi Shimokawa if (subp == NULL || *subp++ != '.') 981a160e00eSHidetoshi Shimokawa return; 982a160e00eSHidetoshi Shimokawa 983a160e00eSHidetoshi Shimokawa /* /dev/fwU.S */ 984a160e00eSHidetoshi Shimokawa while (isdigit(*subp)) { 985a160e00eSHidetoshi Shimokawa sub *= 10; 986a160e00eSHidetoshi Shimokawa sub += *subp++ - '0'; 987a160e00eSHidetoshi Shimokawa } 988a160e00eSHidetoshi Shimokawa if (*subp != '\0') 989a160e00eSHidetoshi Shimokawa return; 990a160e00eSHidetoshi Shimokawa 991a160e00eSHidetoshi Shimokawa sc = devclass_get_softc(firewire_devclass, unit); 992a160e00eSHidetoshi Shimokawa if (sc == NULL) 993a160e00eSHidetoshi Shimokawa return; 994a160e00eSHidetoshi Shimokawa *dev = make_dev(&firewire_cdevsw, MAKEMINOR(devflag[i], unit, sub), 995a160e00eSHidetoshi Shimokawa UID_ROOT, GID_OPERATOR, 0660, 996a160e00eSHidetoshi Shimokawa "%s%d.%d", devnames[i], unit, sub); 997f4f6abcbSPoul-Henning Kamp dev_ref(*dev); 998a160e00eSHidetoshi Shimokawa (*dev)->si_flags |= SI_CHEAPCLONE; 999a160e00eSHidetoshi Shimokawa dev_depends(sc->dev, *dev); 1000a160e00eSHidetoshi Shimokawa return; 1001a160e00eSHidetoshi Shimokawa } 1002a160e00eSHidetoshi Shimokawa #endif 1003