fwdev.c revision 118293
1/* 2 * Copyright (c) 2003 Hidetoshi Shimokawa 3 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the acknowledgement as bellow: 16 * 17 * This product includes software developed by K. Kobayashi and H. Shimokawa 18 * 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: head/sys/dev/firewire/fwdev.c 118293 2003-08-01 04:51:21Z simokawa $ 35 * 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/types.h> 41#include <sys/mbuf.h> 42 43#include <sys/kernel.h> 44#include <sys/malloc.h> 45#include <sys/conf.h> 46#include <sys/poll.h> 47 48#include <sys/bus.h> 49#include <machine/bus.h> 50 51#include <sys/ioccom.h> 52 53#include <dev/firewire/firewire.h> 54#include <dev/firewire/firewirereg.h> 55#include <dev/firewire/fwdma.h> 56#include <dev/firewire/fwmem.h> 57#include <dev/firewire/iec68113.h> 58 59#define CDEV_MAJOR 127 60#define FWNODE_INVAL 0xffff 61 62static d_open_t fw_open; 63static d_close_t fw_close; 64static d_ioctl_t fw_ioctl; 65static d_poll_t fw_poll; 66static d_read_t fw_read; /* for Isochronous packet */ 67static d_write_t fw_write; 68static d_mmap_t fw_mmap; 69 70struct cdevsw firewire_cdevsw = 71{ 72#if __FreeBSD_version >= 500104 73 .d_open = fw_open, 74 .d_close = fw_close, 75 .d_read = fw_read, 76 .d_write = fw_write, 77 .d_ioctl = fw_ioctl, 78 .d_poll = fw_poll, 79 .d_mmap = fw_mmap, 80 .d_name = "fw", 81 .d_maj = CDEV_MAJOR, 82 .d_flags = D_MEM 83#else 84 fw_open, fw_close, fw_read, fw_write, fw_ioctl, 85 fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 86#endif 87}; 88 89struct fw_drv1 { 90 struct fw_xferq *ir; 91 struct fw_xferq *it; 92 struct fw_isobufreq bufreq; 93}; 94 95static int 96fwdev_allocbuf(struct firewire_comm *fc, struct fw_xferq *q, 97 struct fw_bufspec *b) 98{ 99 int i; 100 101 if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF)) 102 return(EBUSY); 103 104 q->bulkxfer = (struct fw_bulkxfer *) malloc( 105 sizeof(struct fw_bulkxfer) * b->nchunk, 106 M_FW, M_WAITOK); 107 if (q->bulkxfer == NULL) 108 return(ENOMEM); 109 110 b->psize = roundup2(b->psize, sizeof(u_int32_t)); 111 q->buf = fwdma_malloc_multiseg(fc, sizeof(u_int32_t), 112 b->psize, b->nchunk * b->npacket, BUS_DMA_WAITOK); 113 114 if (q->buf == NULL) { 115 free(q->bulkxfer, M_FW); 116 q->bulkxfer = NULL; 117 return(ENOMEM); 118 } 119 q->bnchunk = b->nchunk; 120 q->bnpacket = b->npacket; 121 q->psize = (b->psize + 3) & ~3; 122 q->queued = 0; 123 124 STAILQ_INIT(&q->stvalid); 125 STAILQ_INIT(&q->stfree); 126 STAILQ_INIT(&q->stdma); 127 q->stproc = NULL; 128 129 for(i = 0 ; i < q->bnchunk; i++){ 130 q->bulkxfer[i].poffset = i * q->bnpacket; 131 q->bulkxfer[i].mbuf = NULL; 132 STAILQ_INSERT_TAIL(&q->stfree, &q->bulkxfer[i], link); 133 } 134 135 q->flag &= ~FWXFERQ_MODEMASK; 136 q->flag |= FWXFERQ_STREAM; 137 q->flag |= FWXFERQ_EXTBUF; 138 139 return (0); 140} 141 142static int 143fwdev_freebuf(struct fw_xferq *q) 144{ 145 if (q->flag & FWXFERQ_EXTBUF) { 146 if (q->buf != NULL) 147 fwdma_free_multiseg(q->buf); 148 q->buf = NULL; 149 free(q->bulkxfer, M_FW); 150 q->bulkxfer = NULL; 151 q->flag &= ~FWXFERQ_EXTBUF; 152 q->psize = 0; 153 q->maxq = FWMAXQUEUE; 154 } 155 return (0); 156} 157 158 159static int 160fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 161{ 162 int unit = DEV2UNIT(dev); 163 int sub = DEV2SUB(dev); 164 165 int err = 0; 166 167 if (dev->si_drv1 != NULL) 168 return (EBUSY); 169 170 if (DEV_FWMEM(dev)) 171 return fwmem_open(dev, flags, fmt, td); 172 173#if __FreeBSD_version >= 500000 174 if ((dev->si_flags & SI_NAMED) == 0) 175#endif 176 make_dev(&firewire_cdevsw, minor(dev), 177 UID_ROOT, GID_OPERATOR, 0660, 178 "fw%d.%d", unit, sub); 179 180 dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); 181 182 return err; 183} 184 185static int 186fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 187{ 188 struct firewire_softc *sc; 189 struct firewire_comm *fc; 190 struct fw_drv1 *d; 191 int unit = DEV2UNIT(dev); 192 struct fw_xfer *xfer; 193 struct fw_bind *fwb; 194 int err = 0; 195 196 if (DEV_FWMEM(dev)) 197 return fwmem_close(dev, flags, fmt, td); 198 199 sc = devclass_get_softc(firewire_devclass, unit); 200 fc = sc->fc; 201 d = (struct fw_drv1 *)dev->si_drv1; 202 203 if (d->ir != NULL) { 204 struct fw_xferq *ir = d->ir; 205 206 if ((ir->flag & FWXFERQ_OPEN) == 0) 207 return (EINVAL); 208 if (ir->flag & FWXFERQ_RUNNING) { 209 ir->flag &= ~FWXFERQ_RUNNING; 210 fc->irx_disable(fc, ir->dmach); 211 } 212 /* free extbuf */ 213 fwdev_freebuf(ir); 214 /* drain receiving buffer */ 215 for (xfer = STAILQ_FIRST(&ir->q); 216 xfer != NULL; xfer = STAILQ_FIRST(&ir->q)) { 217 ir->queued --; 218 STAILQ_REMOVE_HEAD(&ir->q, link); 219 220 xfer->resp = 0; 221 fw_xfer_done(xfer); 222 } 223 /* remove binding */ 224 for (fwb = STAILQ_FIRST(&ir->binds); fwb != NULL; 225 fwb = STAILQ_FIRST(&ir->binds)) { 226 STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); 227 STAILQ_REMOVE_HEAD(&ir->binds, chlist); 228 free(fwb, M_FW); 229 } 230 ir->flag &= ~(FWXFERQ_OPEN | 231 FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 232 d->ir = NULL; 233 234 } 235 if (d->it != NULL) { 236 struct fw_xferq *it = d->it; 237 238 if ((it->flag & FWXFERQ_OPEN) == 0) 239 return (EINVAL); 240 if (it->flag & FWXFERQ_RUNNING) { 241 it->flag &= ~FWXFERQ_RUNNING; 242 fc->itx_disable(fc, it->dmach); 243 } 244 /* free extbuf */ 245 fwdev_freebuf(it); 246 it->flag &= ~(FWXFERQ_OPEN | 247 FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); 248 d->it = NULL; 249 } 250 free(dev->si_drv1, M_FW); 251 dev->si_drv1 = NULL; 252 253 return err; 254} 255 256/* 257 * read request. 258 */ 259static int 260fw_read (dev_t dev, struct uio *uio, int ioflag) 261{ 262 struct firewire_softc *sc; 263 struct fw_xferq *ir; 264 struct fw_xfer *xfer; 265 int err = 0, s, slept = 0; 266 int unit = DEV2UNIT(dev); 267 struct fw_pkt *fp; 268 269 if (DEV_FWMEM(dev)) 270 return fwmem_read(dev, uio, ioflag); 271 272 sc = devclass_get_softc(firewire_devclass, unit); 273 274 ir = ((struct fw_drv1 *)dev->si_drv1)->ir; 275 if (ir == NULL || ir->buf == NULL) 276 return (EIO); 277 278readloop: 279 xfer = STAILQ_FIRST(&ir->q); 280 if (ir->stproc == NULL) { 281 /* iso bulkxfer */ 282 ir->stproc = STAILQ_FIRST(&ir->stvalid); 283 if (ir->stproc != NULL) { 284 s = splfw(); 285 STAILQ_REMOVE_HEAD(&ir->stvalid, link); 286 splx(s); 287 ir->queued = 0; 288 } 289 } 290 if (xfer == NULL && ir->stproc == NULL) { 291 /* no data avaliable */ 292 if (slept == 0) { 293 slept = 1; 294 ir->flag |= FWXFERQ_WAKEUP; 295 err = tsleep(ir, FWPRI, "fw_read", hz); 296 ir->flag &= ~FWXFERQ_WAKEUP; 297 if (err == 0) 298 goto readloop; 299 } else if (slept == 1) 300 err = EIO; 301 return err; 302 } else if(xfer != NULL) { 303 /* per packet mode or FWACT_CH bind?*/ 304 s = splfw(); 305 ir->queued --; 306 STAILQ_REMOVE_HEAD(&ir->q, link); 307 splx(s); 308 fp = (struct fw_pkt *)xfer->recv.buf; 309 if(sc->fc->irx_post != NULL) 310 sc->fc->irx_post(sc->fc, fp->mode.ld); 311 err = uiomove(xfer->recv.buf, xfer->recv.len, uio); 312 /* XXX we should recycle this xfer */ 313 fw_xfer_free( xfer); 314 } else if(ir->stproc != NULL) { 315 /* iso bulkxfer */ 316 fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, 317 ir->stproc->poffset + ir->queued); 318 if(sc->fc->irx_post != NULL) 319 sc->fc->irx_post(sc->fc, fp->mode.ld); 320 if(fp->mode.stream.len == 0){ 321 err = EIO; 322 return err; 323 } 324 err = uiomove((caddr_t)fp, 325 fp->mode.stream.len + sizeof(u_int32_t), uio); 326 ir->queued ++; 327 if(ir->queued >= ir->bnpacket){ 328 s = splfw(); 329 STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 330 splx(s); 331 sc->fc->irx_enable(sc->fc, ir->dmach); 332 ir->stproc = NULL; 333 } 334 if (uio->uio_resid >= ir->psize) { 335 slept = -1; 336 goto readloop; 337 } 338 } 339 return err; 340} 341 342static int 343fw_write (dev_t dev, struct uio *uio, int ioflag) 344{ 345 int err = 0; 346 struct firewire_softc *sc; 347 int unit = DEV2UNIT(dev); 348 int s, slept = 0; 349 struct fw_pkt *fp; 350 struct firewire_comm *fc; 351 struct fw_xferq *it; 352 353 if (DEV_FWMEM(dev)) 354 return fwmem_write(dev, uio, ioflag); 355 356 sc = devclass_get_softc(firewire_devclass, unit); 357 fc = sc->fc; 358 it = ((struct fw_drv1 *)dev->si_drv1)->it; 359 if (it == NULL || it->buf == NULL) 360 return (EIO); 361isoloop: 362 if (it->stproc == NULL) { 363 it->stproc = STAILQ_FIRST(&it->stfree); 364 if (it->stproc != NULL) { 365 s = splfw(); 366 STAILQ_REMOVE_HEAD(&it->stfree, link); 367 splx(s); 368 it->queued = 0; 369 } else if (slept == 0) { 370 slept = 1; 371 err = sc->fc->itx_enable(sc->fc, it->dmach); 372 if (err) 373 return err; 374 err = tsleep(it, FWPRI, "fw_write", hz); 375 if (err) 376 return err; 377 goto isoloop; 378 } else { 379 err = EIO; 380 return err; 381 } 382 } 383 fp = (struct fw_pkt *)fwdma_v_addr(it->buf, 384 it->stproc->poffset + it->queued); 385 err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 386 err = uiomove((caddr_t)fp->mode.stream.payload, 387 fp->mode.stream.len, uio); 388 it->queued ++; 389 if (it->queued >= it->bnpacket) { 390 s = splfw(); 391 STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 392 splx(s); 393 it->stproc = NULL; 394 err = sc->fc->itx_enable(sc->fc, it->dmach); 395 } 396 if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 397 slept = 0; 398 goto isoloop; 399 } 400 return err; 401} 402/* 403 * ioctl support. 404 */ 405int 406fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 407{ 408 struct firewire_softc *sc; 409 struct firewire_comm *fc; 410 struct fw_drv1 *d; 411 int unit = DEV2UNIT(dev); 412 int s, i, len, err = 0; 413 struct fw_device *fwdev; 414 struct fw_bind *fwb; 415 struct fw_xferq *ir, *it; 416 struct fw_xfer *xfer; 417 struct fw_pkt *fp; 418 struct fw_devinfo *devinfo; 419 void *ptr; 420 421 struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 422 struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 423 struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 424 struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 425 struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 426 struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 427 428 if (DEV_FWMEM(dev)) 429 return fwmem_ioctl(dev, cmd, data, flag, td); 430 431 if (!data) 432 return(EINVAL); 433 434 sc = devclass_get_softc(firewire_devclass, unit); 435 fc = sc->fc; 436 d = (struct fw_drv1 *)dev->si_drv1; 437 ir = d->ir; 438 it = d->it; 439 440 switch (cmd) { 441 case FW_STSTREAM: 442 if (it == NULL) { 443 for (i = 0; i < fc->nisodma; i ++) { 444 it = fc->it[i]; 445 if ((it->flag & FWXFERQ_OPEN) == 0) 446 break; 447 } 448 if (i >= fc->nisodma) { 449 err = EBUSY; 450 break; 451 } 452 err = fwdev_allocbuf(fc, it, &d->bufreq.tx); 453 if (err) 454 break; 455 it->flag |= FWXFERQ_OPEN; 456 } 457 it->flag &= ~0xff; 458 it->flag |= (0x3f & ichreq->ch); 459 it->flag |= ((0x3 & ichreq->tag) << 6); 460 d->it = it; 461 err = 0; 462 break; 463 case FW_GTSTREAM: 464 if (it != NULL) { 465 ichreq->ch = it->flag & 0x3f; 466 ichreq->tag = it->flag >> 2 & 0x3; 467 err = 0; 468 } else 469 err = EINVAL; 470 break; 471 case FW_SRSTREAM: 472 if (ir == NULL) { 473 for (i = 0; i < fc->nisodma; i ++) { 474 ir = fc->ir[i]; 475 if ((ir->flag & FWXFERQ_OPEN) == 0) 476 break; 477 } 478 if (i >= fc->nisodma) { 479 err = EBUSY; 480 break; 481 } 482 err = fwdev_allocbuf(fc, ir, &d->bufreq.rx); 483 if (err) 484 break; 485 ir->flag |= FWXFERQ_OPEN; 486 } 487 ir->flag &= ~0xff; 488 ir->flag |= (0x3f & ichreq->ch); 489 ir->flag |= ((0x3 & ichreq->tag) << 6); 490 d->ir = ir; 491 err = fc->irx_enable(fc, ir->dmach); 492 break; 493 case FW_GRSTREAM: 494 if (d->ir != NULL) { 495 ichreq->ch = ir->flag & 0x3f; 496 ichreq->tag = ir->flag >> 2 & 0x3; 497 err = 0; 498 } else 499 err = EINVAL; 500 break; 501 case FW_SSTBUF: 502 bcopy(ibufreq, &d->bufreq, sizeof(d->bufreq)); 503 err = 0; 504 break; 505 case FW_GSTBUF: 506 bzero(&ibufreq->rx, sizeof(ibufreq->rx)); 507 if (ir != NULL) { 508 ibufreq->rx.nchunk = ir->bnchunk; 509 ibufreq->rx.npacket = ir->bnpacket; 510 ibufreq->rx.psize = ir->psize; 511 } 512 bzero(&ibufreq->tx, sizeof(ibufreq->tx)); 513 if (it != NULL) { 514 ibufreq->tx.nchunk = it->bnchunk; 515 ibufreq->tx.npacket = it->bnpacket; 516 ibufreq->tx.psize = it->psize; 517 } 518 break; 519 case FW_ASYREQ: 520 xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len, 521 PAGE_SIZE /* XXX */); 522 if(xfer == NULL){ 523 err = ENOMEM; 524 return err; 525 } 526 fp = &asyreq->pkt; 527 switch (asyreq->req.type) { 528 case FWASREQNODE: 529 xfer->dst = fp->mode.hdr.dst; 530 break; 531 case FWASREQEUI: 532 fwdev = fw_noderesolve_eui64(sc->fc, 533 &asyreq->req.dst.eui); 534 if (fwdev == NULL) { 535 device_printf(sc->fc->bdev, 536 "cannot find node\n"); 537 err = EINVAL; 538 goto error; 539 } 540 xfer->dst = FWLOCALBUS | fwdev->dst; 541 fp->mode.hdr.dst = xfer->dst; 542 break; 543 case FWASRESTL: 544 /* XXX what's this? */ 545 break; 546 case FWASREQSTREAM: 547 /* nothing to do */ 548 break; 549 } 550 xfer->spd = asyreq->req.sped; 551 bcopy(fp, xfer->send.buf, xfer->send.len); 552 xfer->act.hand = fw_asy_callback; 553 err = fw_asyreq(sc->fc, -1, xfer); 554 if(err){ 555 fw_xfer_free( xfer); 556 return err; 557 } 558 err = tsleep(xfer, FWPRI, "asyreq", hz); 559 if(err == 0){ 560 if(asyreq->req.len >= xfer->recv.len){ 561 asyreq->req.len = xfer->recv.len; 562 }else{ 563 err = EINVAL; 564 } 565 bcopy(xfer->recv.buf, fp, asyreq->req.len); 566 } 567error: 568 fw_xfer_free( xfer); 569 break; 570 case FW_IBUSRST: 571 sc->fc->ibr(sc->fc); 572 break; 573 case FW_CBINDADDR: 574 fwb = fw_bindlookup(sc->fc, 575 bindreq->start.hi, bindreq->start.lo); 576 if(fwb == NULL){ 577 err = EINVAL; 578 break; 579 } 580 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 581 STAILQ_REMOVE(&ir->binds, fwb, fw_bind, chlist); 582 free(fwb, M_FW); 583 break; 584 case FW_SBINDADDR: 585 if(bindreq->len <= 0 ){ 586 err = EINVAL; 587 break; 588 } 589 if(bindreq->start.hi > 0xffff ){ 590 err = EINVAL; 591 break; 592 } 593 fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 594 if(fwb == NULL){ 595 err = ENOMEM; 596 break; 597 } 598 fwb->start_hi = bindreq->start.hi; 599 fwb->start_lo = bindreq->start.lo; 600 fwb->addrlen = bindreq->len; 601 /* XXX */ 602 fwb->sub = ir->dmach; 603 fwb->act_type = FWACT_CH; 604 605 xfer = fw_xfer_alloc(M_FWXFER); 606 if(xfer == NULL){ 607 err = ENOMEM; 608 return err; 609 } 610 xfer->fc = sc->fc; 611 612 s = splfw(); 613 /* XXX broken. need multiple xfer */ 614 STAILQ_INIT(&fwb->xferlist); 615 STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link); 616 splx(s); 617 err = fw_bindadd(sc->fc, fwb); 618 break; 619 case FW_GDEVLST: 620 i = len = 1; 621 /* myself */ 622 devinfo = &fwdevlst->dev[0]; 623 devinfo->dst = sc->fc->nodeid; 624 devinfo->status = 0; /* XXX */ 625 devinfo->eui.hi = sc->fc->eui.hi; 626 devinfo->eui.lo = sc->fc->eui.lo; 627 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 628 if(len < FW_MAX_DEVLST){ 629 devinfo = &fwdevlst->dev[len++]; 630 devinfo->dst = fwdev->dst; 631 devinfo->status = 632 (fwdev->status == FWDEVINVAL)?0:1; 633 devinfo->eui.hi = fwdev->eui.hi; 634 devinfo->eui.lo = fwdev->eui.lo; 635 } 636 i++; 637 } 638 fwdevlst->n = i; 639 fwdevlst->info_len = len; 640 break; 641 case FW_GTPMAP: 642 bcopy(sc->fc->topology_map, data, 643 (sc->fc->topology_map->crc_len + 1) * 4); 644 break; 645 case FW_GCROM: 646 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 647 if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 648 break; 649 if (fwdev == NULL) { 650 if (!FW_EUI64_EQUAL(sc->fc->eui, crom_buf->eui)) { 651 err = FWNODE_INVAL; 652 break; 653 } 654 /* myself */ 655 ptr = malloc(CROMSIZE, M_FW, M_WAITOK); 656 len = CROMSIZE; 657 for (i = 0; i < CROMSIZE/4; i++) 658 ((u_int32_t *)ptr)[i] 659 = ntohl(sc->fc->config_rom[i]); 660 } else { 661 /* found */ 662 ptr = (void *)&fwdev->csrrom[0]; 663 if (fwdev->rommax < CSRROMOFF) 664 len = 0; 665 else 666 len = fwdev->rommax - CSRROMOFF + 4; 667 } 668 if (crom_buf->len < len) 669 len = crom_buf->len; 670 else 671 crom_buf->len = len; 672 err = copyout(ptr, crom_buf->ptr, len); 673 if (fwdev == NULL) 674 /* myself */ 675 free(ptr, M_FW); 676 break; 677 default: 678 sc->fc->ioctl (dev, cmd, data, flag, td); 679 break; 680 } 681 return err; 682} 683int 684fw_poll(dev_t dev, int events, fw_proc *td) 685{ 686 struct firewire_softc *sc; 687 struct fw_xferq *ir; 688 int revents; 689 int tmp; 690 int unit = DEV2UNIT(dev); 691 692 if (DEV_FWMEM(dev)) 693 return fwmem_poll(dev, events, td); 694 695 sc = devclass_get_softc(firewire_devclass, unit); 696 ir = ((struct fw_drv1 *)dev->si_drv1)->ir; 697 revents = 0; 698 tmp = POLLIN | POLLRDNORM; 699 if (events & tmp) { 700 if (STAILQ_FIRST(&ir->q) != NULL) 701 revents |= tmp; 702 else 703 selrecord(td, &ir->rsel); 704 } 705 tmp = POLLOUT | POLLWRNORM; 706 if (events & tmp) { 707 /* XXX should be fixed */ 708 revents |= tmp; 709 } 710 711 return revents; 712} 713 714static int 715#if __FreeBSD_version < 500102 716fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 717#else 718fw_mmap (dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) 719#endif 720{ 721 struct firewire_softc *fc; 722 int unit = DEV2UNIT(dev); 723 724 if (DEV_FWMEM(dev)) 725#if __FreeBSD_version < 500102 726 return fwmem_mmap(dev, offset, nproto); 727#else 728 return fwmem_mmap(dev, offset, paddr, nproto); 729#endif 730 731 fc = devclass_get_softc(firewire_devclass, unit); 732 733 return EINVAL; 734} 735