fwdev.c revision 111942
1219820Sjeff/* 2219820Sjeff * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 3219820Sjeff * All rights reserved. 4219820Sjeff * 5219820Sjeff * Redistribution and use in source and binary forms, with or without 6219820Sjeff * modification, are permitted provided that the following conditions 7219820Sjeff * are met: 8219820Sjeff * 1. Redistributions of source code must retain the above copyright 9219820Sjeff * notice, this list of conditions and the following disclaimer. 10219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11219820Sjeff * notice, this list of conditions and the following disclaimer in the 12219820Sjeff * documentation and/or other materials provided with the distribution. 13219820Sjeff * 3. All advertising materials mentioning features or use of this software 14219820Sjeff * must display the acknowledgement as bellow: 15219820Sjeff * 16219820Sjeff * This product includes software developed by K. Kobayashi and H. Shimokawa 17219820Sjeff * 18219820Sjeff * 4. The name of the author may not be used to endorse or promote products 19219820Sjeff * derived from this software without specific prior written permission. 20219820Sjeff * 21219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23219820Sjeff * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24219820Sjeff * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25219820Sjeff * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26219820Sjeff * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27219820Sjeff * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29219820Sjeff * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30219820Sjeff * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31219820Sjeff * POSSIBILITY OF SUCH DAMAGE. 32219820Sjeff * 33219820Sjeff * $FreeBSD: head/sys/dev/firewire/fwdev.c 111942 2003-03-06 05:06:44Z simokawa $ 34219820Sjeff * 35255932Salfred */ 36255932Salfred 37219820Sjeff#include <sys/param.h> 38255932Salfred#include <sys/systm.h> 39306486Shselasky#include <sys/types.h> 40255932Salfred#include <sys/mbuf.h> 41255932Salfred 42219820Sjeff#include <sys/kernel.h> 43219820Sjeff#include <sys/malloc.h> 44219820Sjeff#include <sys/conf.h> 45219820Sjeff#include <sys/uio.h> 46219820Sjeff#include <sys/poll.h> 47219820Sjeff 48219820Sjeff#include <sys/bus.h> 49219820Sjeff 50255932Salfred#include <sys/ioccom.h> 51255932Salfred 52255932Salfred#include <dev/firewire/firewire.h> 53255932Salfred#include <dev/firewire/firewirereg.h> 54255932Salfred#include <dev/firewire/fwmem.h> 55255932Salfred#include <dev/firewire/iec68113.h> 56255932Salfred 57255932Salfred#define CDEV_MAJOR 127 58255932Salfred#define FWNODE_INVAL 0xffff 59255932Salfred 60255932Salfredstatic d_open_t fw_open; 61255932Salfredstatic d_close_t fw_close; 62255932Salfredstatic d_ioctl_t fw_ioctl; 63255932Salfredstatic d_poll_t fw_poll; 64255932Salfredstatic d_read_t fw_read; /* for Isochronous packet */ 65255932Salfredstatic d_write_t fw_write; 66255932Salfredstatic d_mmap_t fw_mmap; 67255932Salfred 68255932Salfredstruct cdevsw firewire_cdevsw = 69255932Salfred{ 70255932Salfred#if __FreeBSD_version >= 500104 71255932Salfred .d_open = fw_open, 72255932Salfred .d_close = fw_close, 73255932Salfred .d_read = fw_read, 74255932Salfred .d_write = fw_write, 75255932Salfred .d_ioctl = fw_ioctl, 76255932Salfred .d_poll = fw_poll, 77255932Salfred .d_mmap = fw_mmap, 78255932Salfred .d_name = "fw", 79255932Salfred .d_maj = CDEV_MAJOR, 80255932Salfred .d_flags = D_MEM 81255932Salfred#else 82255932Salfred fw_open, fw_close, fw_read, fw_write, fw_ioctl, 83255932Salfred fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 84255932Salfred#endif 85255932Salfred}; 86255932Salfred 87255932Salfredstatic int 88255932Salfredfw_open (dev_t dev, int flags, int fmt, fw_proc *td) 89255932Salfred{ 90255932Salfred struct firewire_softc *sc; 91255932Salfred int unit = DEV2UNIT(dev); 92255932Salfred int sub = DEV2DMACH(dev); 93255932Salfred 94255932Salfred int err = 0; 95255932Salfred 96255932Salfred if (DEV_FWMEM(dev)) 97255932Salfred return fwmem_open(dev, flags, fmt, td); 98255932Salfred 99255932Salfred sc = devclass_get_softc(firewire_devclass, unit); 100255932Salfred if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 101255932Salfred err = EBUSY; 102255932Salfred return err; 103255932Salfred } 104255932Salfred if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 105255932Salfred err = EBUSY; 106219820Sjeff return err; 107219820Sjeff } 108219820Sjeff if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 109219820Sjeff err = EBUSY; 110219820Sjeff return err; 111219820Sjeff } 112219820Sjeff/* Default is per packet mode */ 113219820Sjeff sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 114219820Sjeff sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 115219820Sjeff sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 116219820Sjeff return err; 117219820Sjeff} 118219820Sjeff 119219820Sjeffstatic int 120219820Sjefffw_close (dev_t dev, int flags, int fmt, fw_proc *td) 121219820Sjeff{ 122219820Sjeff struct firewire_softc *sc; 123219820Sjeff int unit = DEV2UNIT(dev); 124219820Sjeff int sub = DEV2DMACH(dev); 125219820Sjeff struct fw_xfer *xfer; 126219820Sjeff struct fw_bind *fwb; 127219820Sjeff int err = 0; 128219820Sjeff 129219820Sjeff if (DEV_FWMEM(dev)) 130219820Sjeff return fwmem_close(dev, flags, fmt, td); 131219820Sjeff 132255932Salfred sc = devclass_get_softc(firewire_devclass, unit); 133219820Sjeff if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 134255932Salfred err = EINVAL; 135219820Sjeff return err; 136255932Salfred } 137255932Salfred sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 138255932Salfred if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 139219820Sjeff err = EINVAL; 140219820Sjeff return err; 141219820Sjeff } 142219820Sjeff sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 143219820Sjeff 144219820Sjeff if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 145219820Sjeff sc->fc->irx_disable(sc->fc, sub); 146219820Sjeff } 147219820Sjeff if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 148219820Sjeff sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 149219820Sjeff sc->fc->itx_disable(sc->fc, sub); 150219820Sjeff } 151219820Sjeff#ifdef FWXFERQ_DV 152219820Sjeff if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 153219820Sjeff struct fw_dvbuf *dvbuf; 154219820Sjeff 155219820Sjeff if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 156219820Sjeff free(dvbuf->buf, M_FW); 157219820Sjeff sc->fc->it[sub]->dvproc = NULL; 158219820Sjeff } 159219820Sjeff if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 160219820Sjeff free(dvbuf->buf, M_FW); 161219820Sjeff sc->fc->it[sub]->dvdma = NULL; 162219820Sjeff } 163219820Sjeff while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 164219820Sjeff STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 165219820Sjeff free(dvbuf->buf, M_FW); 166219820Sjeff } 167219820Sjeff while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 168219820Sjeff STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 169219820Sjeff free(dvbuf->buf, M_FW); 170219820Sjeff } 171255932Salfred free(sc->fc->it[sub]->dvbuf, M_FW); 172255932Salfred sc->fc->it[sub]->dvbuf = NULL; 173255932Salfred } 174255932Salfred#endif 175219820Sjeff if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 176219820Sjeff free(sc->fc->ir[sub]->buf, M_FW); 177219820Sjeff sc->fc->ir[sub]->buf = NULL; 178219820Sjeff free(sc->fc->ir[sub]->bulkxfer, M_FW); 179219820Sjeff sc->fc->ir[sub]->bulkxfer = NULL; 180219820Sjeff sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 181219820Sjeff sc->fc->ir[sub]->psize = PAGE_SIZE; 182219820Sjeff sc->fc->ir[sub]->maxq = FWMAXQUEUE; 183219820Sjeff } 184219820Sjeff if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 185219820Sjeff free(sc->fc->it[sub]->buf, M_FW); 186219820Sjeff sc->fc->it[sub]->buf = NULL; 187219820Sjeff free(sc->fc->it[sub]->bulkxfer, M_FW); 188219820Sjeff sc->fc->it[sub]->bulkxfer = NULL; 189255932Salfred#ifdef FWXFERQ_DV 190219820Sjeff sc->fc->it[sub]->dvbuf = NULL; 191219820Sjeff#endif 192219820Sjeff sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 193219820Sjeff sc->fc->it[sub]->psize = 0; 194219820Sjeff sc->fc->it[sub]->maxq = FWMAXQUEUE; 195219820Sjeff } 196219820Sjeff for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 197219820Sjeff xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 198219820Sjeff sc->fc->ir[sub]->queued--; 199219820Sjeff STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 200219820Sjeff 201219820Sjeff xfer->resp = 0; 202219820Sjeff switch(xfer->act_type){ 203219820Sjeff case FWACT_XFER: 204255932Salfred fw_xfer_done(xfer); 205219820Sjeff break; 206219820Sjeff default: 207219820Sjeff break; 208255932Salfred } 209219820Sjeff fw_xfer_free(xfer); 210219820Sjeff } 211219820Sjeff for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 212255932Salfred fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 213255932Salfred STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 214219820Sjeff STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 215219820Sjeff free(fwb, M_FW); 216255932Salfred } 217219820Sjeff sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 218255932Salfred sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 219255932Salfred return err; 220255932Salfred} 221255932Salfred 222255932Salfred/* 223219820Sjeff * read request. 224255932Salfred */ 225255932Salfredstatic int 226219820Sjefffw_read (dev_t dev, struct uio *uio, int ioflag) 227219820Sjeff{ 228255932Salfred struct firewire_softc *sc; 229255932Salfred struct fw_xferq *ir; 230255932Salfred struct fw_xfer *xfer; 231255932Salfred int err = 0, s, slept = 0; 232255932Salfred int unit = DEV2UNIT(dev); 233219820Sjeff int sub = DEV2DMACH(dev); 234255932Salfred struct fw_pkt *fp; 235219820Sjeff 236219820Sjeff if (DEV_FWMEM(dev)) 237219820Sjeff return fwmem_read(dev, uio, ioflag); 238255932Salfred 239255932Salfred sc = devclass_get_softc(firewire_devclass, unit); 240219820Sjeff 241255932Salfred ir = sc->fc->ir[sub]; 242255932Salfred 243255932Salfred if (ir->flag & FWXFERQ_PACKET) { 244255932Salfred ir->stproc = NULL; 245255932Salfred } 246255932Salfredreadloop: 247255932Salfred xfer = STAILQ_FIRST(&ir->q); 248255932Salfred if ((ir->flag & FWXFERQ_PACKET) == 0 && ir->stproc == NULL) { 249255932Salfred /* iso bulkxfer */ 250219820Sjeff ir->stproc = STAILQ_FIRST(&ir->stvalid); 251219820Sjeff if (ir->stproc != NULL) { 252255932Salfred s = splfw(); 253255932Salfred STAILQ_REMOVE_HEAD(&ir->stvalid, link); 254255932Salfred splx(s); 255255932Salfred ir->queued = 0; 256255932Salfred } 257255932Salfred } 258255932Salfred if (xfer == NULL && ir->stproc == NULL) { 259255932Salfred /* no data avaliable */ 260255932Salfred if (slept == 0) { 261255932Salfred slept = 1; 262255932Salfred if ((ir->flag & FWXFERQ_RUNNING) == 0 263255932Salfred && (ir->flag & FWXFERQ_PACKET)) { 264255932Salfred err = sc->fc->irx_enable(sc->fc, sub); 265255932Salfred if (err) 266255932Salfred return err; 267219820Sjeff } 268255932Salfred ir->flag |= FWXFERQ_WAKEUP; 269255932Salfred err = tsleep(ir, FWPRI, "fw_read", hz); 270255932Salfred ir->flag &= ~FWXFERQ_WAKEUP; 271255932Salfred if (err == 0) 272255932Salfred goto readloop; 273255932Salfred } else if (slept == 1) 274255932Salfred err = EIO; 275255932Salfred return err; 276255932Salfred } else if(xfer != NULL) { 277255932Salfred /* per packet mode */ 278255932Salfred s = splfw(); 279255932Salfred ir->queued --; 280255932Salfred STAILQ_REMOVE_HEAD(&ir->q, link); 281255932Salfred splx(s); 282255932Salfred fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 283255932Salfred if(sc->fc->irx_post != NULL) 284255932Salfred sc->fc->irx_post(sc->fc, fp->mode.ld); 285255932Salfred err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 286255932Salfred fw_xfer_free( xfer); 287255932Salfred } else if(ir->stproc != NULL) { 288255932Salfred /* iso bulkxfer */ 289255932Salfred fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 290255932Salfred if(sc->fc->irx_post != NULL) 291255932Salfred sc->fc->irx_post(sc->fc, fp->mode.ld); 292255932Salfred if(ntohs(fp->mode.stream.len) == 0){ 293255932Salfred err = EIO; 294255932Salfred return err; 295255932Salfred } 296255932Salfred err = uiomove((caddr_t)fp, 297255932Salfred ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 298255932Salfred#if 0 299219820Sjeff fp->mode.stream.len = 0; 300255932Salfred#endif 301219820Sjeff ir->queued ++; 302255932Salfred if(ir->queued >= ir->bnpacket){ 303255932Salfred s = splfw(); 304255932Salfred STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 305255932Salfred splx(s); 306255932Salfred sc->fc->irx_enable(sc->fc, sub); 307255932Salfred ir->stproc = NULL; 308255932Salfred } 309255932Salfred if (uio->uio_resid >= ir->psize) { 310255932Salfred slept = -1; 311255932Salfred goto readloop; 312255932Salfred } 313255932Salfred } 314255932Salfred return err; 315255932Salfred} 316255932Salfred 317255932Salfredstatic int 318255932Salfredfw_write (dev_t dev, struct uio *uio, int ioflag) 319255932Salfred{ 320255932Salfred int err = 0; 321255932Salfred struct firewire_softc *sc; 322255932Salfred int unit = DEV2UNIT(dev); 323255932Salfred int sub = DEV2DMACH(dev); 324255932Salfred int s, slept = 0; 325255932Salfred struct fw_pkt *fp; 326255932Salfred struct fw_xfer *xfer; 327255932Salfred struct fw_xferq *xferq; 328255932Salfred struct firewire_comm *fc; 329255932Salfred struct fw_xferq *it; 330255932Salfred 331255932Salfred if (DEV_FWMEM(dev)) 332219820Sjeff return fwmem_write(dev, uio, ioflag); 333219820Sjeff 334219820Sjeff sc = devclass_get_softc(firewire_devclass, unit); 335219820Sjeff fc = sc->fc; 336219820Sjeff it = sc->fc->it[sub]; 337219820Sjeff 338219820Sjeff fp = (struct fw_pkt *)uio->uio_iov->iov_base; 339255932Salfred switch(fp->mode.common.tcode){ 340255932Salfred case FWTCODE_RREQQ: 341219820Sjeff case FWTCODE_RREQB: 342219820Sjeff case FWTCODE_LREQ: 343219820Sjeff err = EINVAL; 344219820Sjeff return err; 345255932Salfred case FWTCODE_WREQQ: 346219820Sjeff case FWTCODE_WREQB: 347255932Salfred xferq = fc->atq; 348219820Sjeff break; 349219820Sjeff case FWTCODE_STREAM: 350219820Sjeff if(it->flag & FWXFERQ_PACKET){ 351219820Sjeff xferq = fc->atq; 352219820Sjeff }else{ 353219820Sjeff xferq = NULL; 354219820Sjeff } 355219820Sjeff break; 356219820Sjeff case FWTCODE_WRES: 357255932Salfred case FWTCODE_RRESQ: 358219820Sjeff case FWTCODE_RRESB: 359219820Sjeff case FWTCODE_LRES: 360219820Sjeff xferq = fc->ats; 361219820Sjeff break; 362255932Salfred default: 363255932Salfred err = EINVAL; 364219820Sjeff return err; 365219820Sjeff } 366219820Sjeff /* Discard unsent buffered stream packet, when sending Asyrequrst */ 367219820Sjeff if(xferq != NULL && it->stproc != NULL){ 368219820Sjeff s = splfw(); 369219820Sjeff STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 370255932Salfred splx(s); 371219820Sjeff it->stproc = NULL; 372219820Sjeff } 373219820Sjeff#ifdef FWXFERQ_DV 374219820Sjeff if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 375219820Sjeff#else 376255932Salfred if (xferq == NULL) { 377219820Sjeff#endif 378219820Sjeffisoloop: 379219820Sjeff if (it->stproc == NULL) { 380219820Sjeff it->stproc = STAILQ_FIRST(&it->stfree); 381219820Sjeff if (it->stproc != NULL) { 382219820Sjeff s = splfw(); 383255932Salfred STAILQ_REMOVE_HEAD(&it->stfree, link); 384255932Salfred splx(s); 385219820Sjeff it->queued = 0; 386255932Salfred } else if (slept == 0) { 387255932Salfred slept = 1; 388255932Salfred err = sc->fc->itx_enable(sc->fc, sub); 389255932Salfred if (err) 390255932Salfred return err; 391255932Salfred err = tsleep(it, FWPRI, 392255932Salfred "fw_write", hz); 393255932Salfred if (err) 394255932Salfred return err; 395255932Salfred goto isoloop; 396255932Salfred } else { 397219820Sjeff err = EIO; 398219820Sjeff return err; 399255932Salfred } 400219820Sjeff } 401255932Salfred fp = (struct fw_pkt *) 402255932Salfred (it->stproc->buf + it->queued * it->psize); 403255932Salfred err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 404255932Salfred err = uiomove((caddr_t)fp->mode.stream.payload, 405255932Salfred ntohs(fp->mode.stream.len), uio); 406255932Salfred it->queued ++; 407255932Salfred if (it->queued >= it->bnpacket) { 408255932Salfred s = splfw(); 409219820Sjeff STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 410219820Sjeff splx(s); 411255932Salfred it->stproc = NULL; 412255932Salfred err = sc->fc->itx_enable(sc->fc, sub); 413255932Salfred } 414255932Salfred if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 415255932Salfred slept = 0; 416255932Salfred goto isoloop; 417255932Salfred } 418255932Salfred return err; 419255932Salfred } 420255932Salfred#ifdef FWXFERQ_DV 421255932Salfred if(xferq == NULL && it->flag & FWXFERQ_DV){ 422255932Salfreddvloop: 423255932Salfred if(it->dvproc == NULL){ 424255932Salfred it->dvproc = STAILQ_FIRST(&it->dvfree); 425255932Salfred if(it->dvproc != NULL){ 426255932Salfred s = splfw(); 427255932Salfred STAILQ_REMOVE_HEAD(&it->dvfree, link); 428255932Salfred splx(s); 429255932Salfred it->dvptr = 0; 430255932Salfred }else if(slept == 0){ 431255932Salfred slept = 1; 432255932Salfred err = sc->fc->itx_enable(sc->fc, sub); 433255932Salfred if(err){ 434255932Salfred return err; 435255932Salfred } 436255932Salfred err = tsleep(it, FWPRI, "fw_write", hz); 437255932Salfred if(err){ 438255932Salfred return err; 439255932Salfred } 440255932Salfred goto dvloop; 441255932Salfred }else{ 442255932Salfred err = EIO; 443255932Salfred return err; 444255932Salfred } 445255932Salfred } 446255932Salfred#if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/ 447255932Salfred fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 448255932Salfred fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 449255932Salfred#endif 450255932Salfred err = uiomove(it->dvproc->buf + it->dvptr, 451255932Salfred uio->uio_resid, uio); 452255932Salfred it->dvptr += it->psize; 453255932Salfred if(err){ 454255932Salfred return err; 455255932Salfred } 456255932Salfred if(it->dvptr >= it->psize * it->dvpacket){ 457255932Salfred s = splfw(); 458255932Salfred STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 459255932Salfred splx(s); 460255932Salfred it->dvproc = NULL; 461255932Salfred err = fw_tbuf_update(sc->fc, sub, 0); 462255932Salfred if(err){ 463255932Salfred return err; 464255932Salfred } 465255932Salfred err = sc->fc->itx_enable(sc->fc, sub); 466255932Salfred } 467255932Salfred return err; 468255932Salfred } 469255932Salfred#endif 470255932Salfred if(xferq != NULL){ 471255932Salfred xfer = fw_xfer_alloc(M_FWXFER); 472255932Salfred if(xfer == NULL){ 473255932Salfred err = ENOMEM; 474255932Salfred return err; 475255932Salfred } 476255932Salfred xfer->send.buf = malloc(uio->uio_resid, M_FW, M_NOWAIT); 477255932Salfred if(xfer->send.buf == NULL){ 478255932Salfred fw_xfer_free( xfer); 479255932Salfred err = ENOBUFS; 480255932Salfred return err; 481255932Salfred } 482255932Salfred xfer->dst = ntohs(fp->mode.hdr.dst); 483255932Salfred#if 0 484255932Salfred switch(fp->mode.common.tcode){ 485255932Salfred case FWTCODE_WREQQ: 486255932Salfred case FWTCODE_WREQB: 487255932Salfred if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 488255932Salfred fw_xfer_free( xfer); 489255932Salfred err = EAGAIN; 490255932Salfred return err; 491255932Salfred } 492255932Salfred fp->mode.hdr.tlrt = tl << 2; 493255932Salfred default: 494255932Salfred break; 495255932Salfred } 496255932Salfred 497255932Salfred xfer->tl = fp->mode.hdr.tlrt >> 2; 498255932Salfred xfer->tcode = fp->mode.common.tcode; 499255932Salfred xfer->fc = fc; 500255932Salfred xfer->q = xferq; 501255932Salfred xfer->act_type = FWACT_XFER; 502255932Salfred xfer->retry_req = fw_asybusy; 503255932Salfred#endif 504255932Salfred xfer->send.len = uio->uio_resid; 505255932Salfred xfer->send.off = 0; 506255932Salfred xfer->spd = 0;/* XXX: how to setup it */ 507255932Salfred xfer->act.hand = fw_asy_callback; 508255932Salfred 509255932Salfred err = uiomove(xfer->send.buf, uio->uio_resid, uio); 510255932Salfred if(err){ 511255932Salfred fw_xfer_free( xfer); 512255932Salfred return err; 513255932Salfred } 514255932Salfred#if 0 515255932Salfred fw_asystart(xfer); 516255932Salfred#else 517255932Salfred fw_asyreq(fc, -1, xfer); 518255932Salfred#endif 519255932Salfred err = tsleep(xfer, FWPRI, "fw_write", hz); 520255932Salfred if(xfer->resp == EBUSY) 521255932Salfred return EBUSY; 522255932Salfred fw_xfer_free( xfer); 523255932Salfred return err; 524255932Salfred } 525255932Salfred return EINVAL; 526255932Salfred} 527255932Salfred 528255932Salfred/* 529255932Salfred * ioctl support. 530255932Salfred */ 531255932Salfredint 532255932Salfredfw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 533255932Salfred{ 534255932Salfred struct firewire_softc *sc; 535255932Salfred int unit = DEV2UNIT(dev); 536255932Salfred int sub = DEV2DMACH(dev); 537255932Salfred int i, len, err = 0; 538255932Salfred struct fw_device *fwdev; 539255932Salfred struct fw_bind *fwb; 540255932Salfred struct fw_xferq *ir, *it; 541255932Salfred struct fw_xfer *xfer; 542255932Salfred struct fw_pkt *fp; 543255932Salfred struct fw_devinfo *devinfo; 544255932Salfred 545255932Salfred struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 546255932Salfred struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 547255932Salfred struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 548255932Salfred struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 549255932Salfred struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 550255932Salfred struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 551278886Shselasky 552278886Shselasky if (DEV_FWMEM(dev)) 553278886Shselasky return fwmem_ioctl(dev, cmd, data, flag, td); 554278886Shselasky 555278886Shselasky sc = devclass_get_softc(firewire_devclass, unit); 556278886Shselasky if (!data) 557278886Shselasky return(EINVAL); 558278886Shselasky 559278886Shselasky switch (cmd) { 560278886Shselasky case FW_STSTREAM: 561278886Shselasky sc->fc->it[sub]->flag &= ~0xff; 562278886Shselasky sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 563278886Shselasky sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 564278886Shselasky err = 0; 565278886Shselasky break; 566278886Shselasky case FW_GTSTREAM: 567278886Shselasky ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 568278886Shselasky ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 569278886Shselasky err = 0; 570278886Shselasky break; 571278886Shselasky case FW_SRSTREAM: 572278886Shselasky sc->fc->ir[sub]->flag &= ~0xff; 573278886Shselasky sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 574255932Salfred sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 575255932Salfred err = sc->fc->irx_enable(sc->fc, sub); 576255932Salfred break; 577255932Salfred case FW_GRSTREAM: 578255932Salfred ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 579255932Salfred ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 580255932Salfred err = 0; 581255932Salfred break; 582255932Salfred#ifdef FWXFERQ_DV 583255932Salfred case FW_SSTDV: 584255932Salfred ibufreq = (struct fw_isobufreq *) 585255932Salfred malloc(sizeof(struct fw_isobufreq), M_FW, M_NOWAIT); 586255932Salfred if(ibufreq == NULL){ 587255932Salfred err = ENOMEM; 588255932Salfred break; 589255932Salfred } 590255932Salfred#if DV_PAL 591255932Salfred#define FWDVPACKET 300 592255932Salfred#else 593255932Salfred#define FWDVPACKET 250 594255932Salfred#endif 595255932Salfred#define FWDVPMAX 512 596255932Salfred ibufreq->rx.nchunk = 8; 597255932Salfred ibufreq->rx.npacket = 50; 598255932Salfred ibufreq->rx.psize = FWDVPMAX; 599255932Salfred 600255932Salfred ibufreq->tx.nchunk = 5; 601255932Salfred ibufreq->tx.npacket = FWDVPACKET + 30; /* > 320 or 267 */ 602255932Salfred ibufreq->tx.psize = FWDVPMAX; 603255932Salfred 604255932Salfred err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 605255932Salfred sc->fc->it[sub]->dvpacket = FWDVPACKET; 606255932Salfred free(ibufreq, M_FW); 607255932Salfred/* reserve a buffer space */ 608255932Salfred#define NDVCHUNK 8 609255932Salfred sc->fc->it[sub]->dvproc = NULL; 610255932Salfred sc->fc->it[sub]->dvdma = NULL; 611255932Salfred sc->fc->it[sub]->flag |= FWXFERQ_DV; 612255932Salfred /* XXX check malloc failure */ 613255932Salfred sc->fc->it[sub]->dvbuf 614255932Salfred = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_FW, M_NOWAIT); 615255932Salfred STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 616255932Salfred STAILQ_INIT(&sc->fc->it[sub]->dvfree); 617255932Salfred for( i = 0 ; i < NDVCHUNK ; i++){ 618255932Salfred /* XXX check malloc failure */ 619255932Salfred sc->fc->it[sub]->dvbuf[i].buf 620255932Salfred = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_FW, M_NOWAIT); 621255932Salfred STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 622255932Salfred &sc->fc->it[sub]->dvbuf[i], link); 623255932Salfred } 624255932Salfred break; 625255932Salfred#endif 626255932Salfred case FW_SSTBUF: 627255932Salfred ir = sc->fc->ir[sub]; 628255932Salfred it = sc->fc->it[sub]; 629255932Salfred 630255932Salfred if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 631255932Salfred return(EBUSY); 632255932Salfred } 633255932Salfred if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 634255932Salfred return(EBUSY); 635255932Salfred } 636255932Salfred if((ibufreq->rx.nchunk * 637255932Salfred ibufreq->rx.psize * ibufreq->rx.npacket) + 638255932Salfred (ibufreq->tx.nchunk * 639255932Salfred ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 640255932Salfred return(EINVAL); 641255932Salfred } 642255932Salfred if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 643255932Salfred ibufreq->tx.nchunk > FWSTMAXCHUNK){ 644255932Salfred return(EINVAL); 645255932Salfred } 646255932Salfred ir->bulkxfer 647255932Salfred = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_FW, 0); 648255932Salfred if(ir->bulkxfer == NULL){ 649255932Salfred return(ENOMEM); 650255932Salfred } 651255932Salfred it->bulkxfer 652255932Salfred = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_FW, 0); 653255932Salfred if(it->bulkxfer == NULL){ 654255932Salfred return(ENOMEM); 655255932Salfred } 656255932Salfred ir->buf = malloc( 657255932Salfred ibufreq->rx.nchunk * ibufreq->rx.npacket 658255932Salfred /* XXX psize must be 2^n and less or 659255932Salfred equal to PAGE_SIZE */ 660255932Salfred * ((ibufreq->rx.psize + 3) &~3), 661255932Salfred M_FW, 0); 662255932Salfred if(ir->buf == NULL){ 663255932Salfred free(ir->bulkxfer, M_FW); 664255932Salfred free(it->bulkxfer, M_FW); 665255932Salfred ir->bulkxfer = NULL; 666255932Salfred it->bulkxfer = NULL; 667255932Salfred it->buf = NULL; 668255932Salfred return(ENOMEM); 669255932Salfred } 670255932Salfred it->buf = malloc( 671255932Salfred ibufreq->tx.nchunk * ibufreq->tx.npacket 672255932Salfred /* XXX psize must be 2^n and less or 673255932Salfred equal to PAGE_SIZE */ 674255932Salfred * ((ibufreq->tx.psize + 3) &~3), 675255932Salfred M_FW, 0); 676255932Salfred if(it->buf == NULL){ 677255932Salfred free(ir->bulkxfer, M_FW); 678255932Salfred free(it->bulkxfer, M_FW); 679255932Salfred free(ir->buf, M_FW); 680255932Salfred ir->bulkxfer = NULL; 681255932Salfred it->bulkxfer = NULL; 682255932Salfred it->buf = NULL; 683255932Salfred return(ENOMEM); 684255932Salfred } 685255932Salfred 686255932Salfred ir->bnchunk = ibufreq->rx.nchunk; 687255932Salfred ir->bnpacket = ibufreq->rx.npacket; 688255932Salfred ir->psize = (ibufreq->rx.psize + 3) & ~3; 689255932Salfred ir->queued = 0; 690255932Salfred 691255932Salfred it->bnchunk = ibufreq->tx.nchunk; 692255932Salfred it->bnpacket = ibufreq->tx.npacket; 693255932Salfred it->psize = (ibufreq->tx.psize + 3) & ~3; 694255932Salfred it->queued = 0; 695255932Salfred 696255932Salfred#ifdef FWXFERQ_DV 697255932Salfred it->dvdbc = 0; 698255932Salfred it->dvdiff = 0; 699255932Salfred it->dvsync = 0; 700255932Salfred it->dvoffset = 0; 701219820Sjeff#endif 702255932Salfred 703255932Salfred STAILQ_INIT(&ir->stvalid); 704219820Sjeff STAILQ_INIT(&ir->stfree); 705219820Sjeff STAILQ_INIT(&ir->stdma); 706219820Sjeff ir->stproc = NULL; 707219820Sjeff 708219820Sjeff STAILQ_INIT(&it->stvalid); 709255932Salfred STAILQ_INIT(&it->stfree); 710255932Salfred STAILQ_INIT(&it->stdma); 711255932Salfred it->stproc = NULL; 712255932Salfred 713255932Salfred for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 714255932Salfred ir->bulkxfer[i].buf = 715255932Salfred ir->buf + i * ir->bnpacket * ir->psize; 716255932Salfred STAILQ_INSERT_TAIL(&ir->stfree, 717255932Salfred &ir->bulkxfer[i], link); 718255932Salfred ir->bulkxfer[i].npacket = ir->bnpacket; 719255932Salfred } 720278886Shselasky for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 721278886Shselasky it->bulkxfer[i].buf = 722255932Salfred it->buf + i * it->bnpacket * it->psize; 723278886Shselasky STAILQ_INSERT_TAIL(&it->stfree, 724278886Shselasky &it->bulkxfer[i], link); 725255932Salfred it->bulkxfer[i].npacket = it->bnpacket; 726255932Salfred } 727255932Salfred ir->flag &= ~FWXFERQ_MODEMASK; 728219820Sjeff ir->flag |= FWXFERQ_STREAM; 729219820Sjeff ir->flag |= FWXFERQ_EXTBUF; 730219820Sjeff 731219820Sjeff it->flag &= ~FWXFERQ_MODEMASK; 732219820Sjeff it->flag |= FWXFERQ_STREAM; 733219820Sjeff it->flag |= FWXFERQ_EXTBUF; 734219820Sjeff err = 0; 735219820Sjeff break; 736219820Sjeff case FW_GSTBUF: 737219820Sjeff ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 738219820Sjeff ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 739219820Sjeff ibufreq->rx.psize = sc->fc->ir[sub]->psize; 740219820Sjeff 741219820Sjeff ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 742219820Sjeff ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 743255932Salfred ibufreq->tx.psize = sc->fc->it[sub]->psize; 744219820Sjeff break; 745255932Salfred case FW_ASYREQ: 746219820Sjeff xfer = fw_xfer_alloc(M_FWXFER); 747219820Sjeff if(xfer == NULL){ 748219820Sjeff err = ENOMEM; 749219820Sjeff return err; 750219820Sjeff } 751219820Sjeff fp = &asyreq->pkt; 752219820Sjeff switch (asyreq->req.type) { 753219820Sjeff case FWASREQNODE: 754219820Sjeff xfer->dst = ntohs(fp->mode.hdr.dst); 755219820Sjeff break; 756219820Sjeff case FWASREQEUI: 757219820Sjeff fwdev = fw_noderesolve_eui64(sc->fc, 758219820Sjeff &asyreq->req.dst.eui); 759219820Sjeff if (fwdev == NULL) { 760219820Sjeff device_printf(sc->fc->bdev, 761219820Sjeff "cannot find node\n"); 762219820Sjeff err = EINVAL; 763219820Sjeff goto error; 764219820Sjeff } 765255932Salfred xfer->dst = fwdev->dst; 766255932Salfred fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 767255932Salfred break; 768219820Sjeff case FWASRESTL: 769219820Sjeff /* XXX what's this? */ 770219820Sjeff break; 771219820Sjeff case FWASREQSTREAM: 772219820Sjeff /* nothing to do */ 773255932Salfred break; 774255932Salfred } 775255932Salfred xfer->spd = asyreq->req.sped; 776255932Salfred xfer->send.len = asyreq->req.len; 777255932Salfred xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT); 778219820Sjeff if(xfer->send.buf == NULL){ 779219820Sjeff return ENOMEM; 780219820Sjeff } 781219820Sjeff xfer->send.off = 0; 782219820Sjeff bcopy(fp, xfer->send.buf, xfer->send.len); 783219820Sjeff xfer->act.hand = fw_asy_callback; 784219820Sjeff err = fw_asyreq(sc->fc, sub, xfer); 785219820Sjeff if(err){ 786219820Sjeff fw_xfer_free( xfer); 787219820Sjeff return err; 788219820Sjeff } 789219820Sjeff err = tsleep(xfer, FWPRI, "asyreq", hz); 790219820Sjeff if(err == 0){ 791255932Salfred if(asyreq->req.len >= xfer->recv.len){ 792255932Salfred asyreq->req.len = xfer->recv.len; 793219820Sjeff }else{ 794255932Salfred err = EINVAL; 795255932Salfred } 796255932Salfred bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 797255932Salfred } 798255932Salfrederror: 799255932Salfred fw_xfer_free( xfer); 800255932Salfred break; 801255932Salfred case FW_IBUSRST: 802255932Salfred sc->fc->ibr(sc->fc); 803255932Salfred break; 804255932Salfred case FW_CBINDADDR: 805255932Salfred fwb = fw_bindlookup(sc->fc, 806255932Salfred bindreq->start.hi, bindreq->start.lo); 807255932Salfred if(fwb == NULL){ 808255932Salfred err = EINVAL; 809255932Salfred break; 810255932Salfred } 811255932Salfred STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 812255932Salfred STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 813255932Salfred free(fwb, M_FW); 814255932Salfred break; 815255932Salfred case FW_SBINDADDR: 816255932Salfred if(bindreq->len <= 0 ){ 817255932Salfred err = EINVAL; 818255932Salfred break; 819255932Salfred } 820255932Salfred if(bindreq->start.hi > 0xffff ){ 821255932Salfred err = EINVAL; 822255932Salfred break; 823255932Salfred } 824255932Salfred fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 825255932Salfred if(fwb == NULL){ 826255932Salfred err = ENOMEM; 827255932Salfred break; 828255932Salfred } 829255932Salfred fwb->start_hi = bindreq->start.hi; 830255932Salfred fwb->start_lo = bindreq->start.lo; 831255932Salfred fwb->addrlen = bindreq->len; 832255932Salfred 833255932Salfred xfer = fw_xfer_alloc(M_FWXFER); 834255932Salfred if(xfer == NULL){ 835255932Salfred err = ENOMEM; 836255932Salfred return err; 837255932Salfred } 838255932Salfred xfer->act_type = FWACT_CH; 839255932Salfred xfer->sub = sub; 840255932Salfred xfer->fc = sc->fc; 841255932Salfred 842255932Salfred fwb->xfer = xfer; 843255932Salfred err = fw_bindadd(sc->fc, fwb); 844255932Salfred break; 845255932Salfred case FW_GDEVLST: 846255932Salfred i = len = 1; 847255932Salfred /* myself */ 848255932Salfred devinfo = &fwdevlst->dev[0]; 849255932Salfred devinfo->dst = sc->fc->nodeid; 850255932Salfred devinfo->status = 0; /* XXX */ 851255932Salfred devinfo->eui.hi = sc->fc->eui.hi; 852255932Salfred devinfo->eui.lo = sc->fc->eui.lo; 853255932Salfred STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 854255932Salfred if(len < FW_MAX_DEVLST){ 855255932Salfred devinfo = &fwdevlst->dev[len++]; 856255932Salfred devinfo->dst = fwdev->dst; 857255932Salfred devinfo->status = 858255932Salfred (fwdev->status == FWDEVINVAL)?0:1; 859255932Salfred devinfo->eui.hi = fwdev->eui.hi; 860255932Salfred devinfo->eui.lo = fwdev->eui.lo; 861255932Salfred } 862255932Salfred i++; 863255932Salfred } 864255932Salfred fwdevlst->n = i; 865255932Salfred fwdevlst->info_len = len; 866255932Salfred break; 867255932Salfred case FW_GTPMAP: 868255932Salfred bcopy(sc->fc->topology_map, data, 869255932Salfred (sc->fc->topology_map->crc_len + 1) * 4); 870255932Salfred break; 871255932Salfred case FW_GCROM: 872255932Salfred STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 873255932Salfred if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 874255932Salfred break; 875255932Salfred if (fwdev == NULL) { 876255932Salfred err = FWNODE_INVAL; 877255932Salfred break; 878255932Salfred } 879255932Salfred#if 0 880255932Salfred if (fwdev->csrrom[0] >> 24 == 1) 881255932Salfred len = 4; 882255932Salfred else 883255932Salfred len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 884255932Salfred#else 885255932Salfred if (fwdev->rommax < CSRROMOFF) 886255932Salfred len = 0; 887255932Salfred else 888255932Salfred len = fwdev->rommax - CSRROMOFF + 4; 889255932Salfred#endif 890255932Salfred if (crom_buf->len < len) 891255932Salfred len = crom_buf->len; 892255932Salfred else 893255932Salfred crom_buf->len = len; 894255932Salfred err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 895255932Salfred break; 896255932Salfred default: 897255932Salfred sc->fc->ioctl (dev, cmd, data, flag, td); 898255932Salfred break; 899255932Salfred } 900255932Salfred return err; 901255932Salfred} 902255932Salfredint 903255932Salfredfw_poll(dev_t dev, int events, fw_proc *td) 904255932Salfred{ 905255932Salfred int revents; 906255932Salfred int tmp; 907255932Salfred int unit = DEV2UNIT(dev); 908255932Salfred int sub = DEV2DMACH(dev); 909255932Salfred struct firewire_softc *sc; 910255932Salfred 911255932Salfred if (DEV_FWMEM(dev)) 912255932Salfred return fwmem_poll(dev, events, td); 913219820Sjeff 914219820Sjeff sc = devclass_get_softc(firewire_devclass, unit); 915255932Salfred revents = 0; 916255932Salfred tmp = POLLIN | POLLRDNORM; 917219820Sjeff if (events & tmp) { 918255932Salfred if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 919255932Salfred revents |= tmp; 920255932Salfred else 921255932Salfred selrecord(td, &sc->fc->ir[sub]->rsel); 922255932Salfred } 923255932Salfred tmp = POLLOUT | POLLWRNORM; 924255932Salfred if (events & tmp) { 925255932Salfred /* XXX should be fixed */ 926255932Salfred revents |= tmp; 927255932Salfred } 928255932Salfred 929255932Salfred return revents; 930255932Salfred} 931255932Salfred 932255932Salfredstatic int 933255932Salfred#if __FreeBSD_version < 500000 934255932Salfredfw_mmap (dev_t dev, vm_offset_t offset, int nproto) 935255932Salfred#else 936255932Salfredfw_mmap (dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nproto) 937255932Salfred#endif 938255932Salfred{ 939219820Sjeff struct firewire_softc *fc; 940255932Salfred int unit = DEV2UNIT(dev); 941255932Salfred 942255932Salfred if (DEV_FWMEM(dev)) 943255932Salfred#if __FreeBSD_version < 500000 944255932Salfred return fwmem_mmap(dev, offset, nproto); 945255932Salfred#else 946255932Salfred return fwmem_mmap(dev, offset, paddr, nproto); 947255932Salfred#endif 948255932Salfred 949255932Salfred fc = devclass_get_softc(firewire_devclass, unit); 950255932Salfred 951255932Salfred return EINVAL; 952255932Salfred} 953255932Salfred