83}; 84 85static int 86fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 87{ 88 struct firewire_softc *sc; 89 int unit = DEV2UNIT(dev); 90 int sub = DEV2DMACH(dev); 91 92 int err = 0; 93 94 if (DEV_FWMEM(dev)) 95 return fwmem_open(dev, flags, fmt, td); 96 97 sc = devclass_get_softc(firewire_devclass, unit); 98 if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 99 err = EBUSY; 100 return err; 101 } 102 if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 103 err = EBUSY; 104 return err; 105 } 106 if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 107 err = EBUSY; 108 return err; 109 } 110/* Default is per packet mode */ 111 sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 112 sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 113 sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 114 return err; 115} 116 117static int 118fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 119{ 120 struct firewire_softc *sc; 121 int unit = DEV2UNIT(dev); 122 int sub = DEV2DMACH(dev); 123 struct fw_xfer *xfer; 124 struct fw_bind *fwb; 125 int err = 0; 126 127 if (DEV_FWMEM(dev)) 128 return fwmem_close(dev, flags, fmt, td); 129 130 sc = devclass_get_softc(firewire_devclass, unit); 131 if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 132 err = EINVAL; 133 return err; 134 } 135 sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 136 if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 137 err = EINVAL; 138 return err; 139 } 140 sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 141 142 if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 143 sc->fc->irx_disable(sc->fc, sub); 144 } 145 if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 146 sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 147 sc->fc->itx_disable(sc->fc, sub); 148 } 149#ifdef FWXFERQ_DV 150 if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 151 struct fw_dvbuf *dvbuf; 152 153 if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 154 free(dvbuf->buf, M_FW); 155 sc->fc->it[sub]->dvproc = NULL; 156 } 157 if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 158 free(dvbuf->buf, M_FW); 159 sc->fc->it[sub]->dvdma = NULL; 160 } 161 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 162 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 163 free(dvbuf->buf, M_FW); 164 } 165 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 166 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 167 free(dvbuf->buf, M_FW); 168 } 169 free(sc->fc->it[sub]->dvbuf, M_FW); 170 sc->fc->it[sub]->dvbuf = NULL; 171 } 172#endif 173 if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 174 free(sc->fc->ir[sub]->buf, M_FW); 175 sc->fc->ir[sub]->buf = NULL; 176 free(sc->fc->ir[sub]->bulkxfer, M_FW); 177 sc->fc->ir[sub]->bulkxfer = NULL; 178 sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 179 sc->fc->ir[sub]->psize = PAGE_SIZE; 180 sc->fc->ir[sub]->maxq = FWMAXQUEUE; 181 } 182 if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 183 free(sc->fc->it[sub]->buf, M_FW); 184 sc->fc->it[sub]->buf = NULL; 185 free(sc->fc->it[sub]->bulkxfer, M_FW); 186 sc->fc->it[sub]->bulkxfer = NULL; 187#ifdef FWXFERQ_DV 188 sc->fc->it[sub]->dvbuf = NULL; 189#endif 190 sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 191 sc->fc->it[sub]->psize = 0; 192 sc->fc->it[sub]->maxq = FWMAXQUEUE; 193 } 194 for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 195 xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 196 sc->fc->ir[sub]->queued--; 197 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 198 199 xfer->resp = 0; 200 switch(xfer->act_type){ 201 case FWACT_XFER: 202 fw_xfer_done(xfer); 203 break; 204 default: 205 break; 206 } 207 fw_xfer_free(xfer); 208 } 209 for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 210 fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 211 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 212 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 213 free(fwb, M_FW); 214 } 215 sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 216 sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 217 return err; 218} 219 220/* 221 * read request. 222 */ 223static int 224fw_read (dev_t dev, struct uio *uio, int ioflag) 225{ 226 struct firewire_softc *sc; 227 struct fw_xferq *ir; 228 struct fw_xfer *xfer; 229 int err = 0, s, slept = 0; 230 int unit = DEV2UNIT(dev); 231 int sub = DEV2DMACH(dev); 232 struct fw_pkt *fp; 233 234 if (DEV_FWMEM(dev)) 235 return fwmem_read(dev, uio, ioflag); 236 237 sc = devclass_get_softc(firewire_devclass, unit); 238 239 ir = sc->fc->ir[sub]; 240 241 if (ir->flag & FWXFERQ_PACKET) { 242 ir->stproc = NULL; 243 } 244readloop: 245 xfer = STAILQ_FIRST(&ir->q); 246 if ((ir->flag & FWXFERQ_PACKET) == 0 && ir->stproc == NULL) { 247 /* iso bulkxfer */ 248 ir->stproc = STAILQ_FIRST(&ir->stvalid); 249 if (ir->stproc != NULL) { 250 s = splfw(); 251 STAILQ_REMOVE_HEAD(&ir->stvalid, link); 252 splx(s); 253 ir->queued = 0; 254 } 255 } 256 if (xfer == NULL && ir->stproc == NULL) { 257 /* no data avaliable */ 258 if (slept == 0) { 259 slept = 1; 260 if ((ir->flag & FWXFERQ_RUNNING) == 0 261 && (ir->flag & FWXFERQ_PACKET)) { 262 err = sc->fc->irx_enable(sc->fc, sub); 263 if (err) 264 return err; 265 } 266 ir->flag |= FWXFERQ_WAKEUP; 267 err = tsleep(ir, FWPRI, "fw_read", hz); 268 ir->flag &= ~FWXFERQ_WAKEUP; 269 if (err == 0) 270 goto readloop; 271 } else if (slept == 1) 272 err = EIO; 273 return err; 274 } else if(xfer != NULL) { 275 /* per packet mode */ 276 s = splfw(); 277 ir->queued --; 278 STAILQ_REMOVE_HEAD(&ir->q, link); 279 splx(s); 280 fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 281 if(sc->fc->irx_post != NULL) 282 sc->fc->irx_post(sc->fc, fp->mode.ld); 283 err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 284 fw_xfer_free( xfer); 285 } else if(ir->stproc != NULL) { 286 /* iso bulkxfer */ 287 fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 288 if(sc->fc->irx_post != NULL) 289 sc->fc->irx_post(sc->fc, fp->mode.ld); 290 if(ntohs(fp->mode.stream.len) == 0){ 291 err = EIO; 292 return err; 293 } 294 err = uiomove((caddr_t)fp, 295 ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 296#if 0 297 fp->mode.stream.len = 0; 298#endif 299 ir->queued ++; 300 if(ir->queued >= ir->bnpacket){ 301 s = splfw(); 302 STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 303 splx(s); 304 sc->fc->irx_enable(sc->fc, sub); 305 ir->stproc = NULL; 306 } 307 if (uio->uio_resid >= ir->psize) { 308 slept = -1; 309 goto readloop; 310 } 311 } 312 return err; 313} 314 315static int 316fw_write (dev_t dev, struct uio *uio, int ioflag) 317{ 318 int err = 0; 319 struct firewire_softc *sc; 320 int unit = DEV2UNIT(dev); 321 int sub = DEV2DMACH(dev); 322 int s, slept = 0; 323 struct fw_pkt *fp; 324 struct fw_xfer *xfer; 325 struct fw_xferq *xferq; 326 struct firewire_comm *fc; 327 struct fw_xferq *it; 328 329 if (DEV_FWMEM(dev)) 330 return fwmem_write(dev, uio, ioflag); 331 332 sc = devclass_get_softc(firewire_devclass, unit); 333 fc = sc->fc; 334 it = sc->fc->it[sub]; 335 336 fp = (struct fw_pkt *)uio->uio_iov->iov_base; 337 switch(fp->mode.common.tcode){ 338 case FWTCODE_RREQQ: 339 case FWTCODE_RREQB: 340 case FWTCODE_LREQ: 341 err = EINVAL; 342 return err; 343 case FWTCODE_WREQQ: 344 case FWTCODE_WREQB: 345 xferq = fc->atq; 346 break; 347 case FWTCODE_STREAM: 348 if(it->flag & FWXFERQ_PACKET){ 349 xferq = fc->atq; 350 }else{ 351 xferq = NULL; 352 } 353 break; 354 case FWTCODE_WRES: 355 case FWTCODE_RRESQ: 356 case FWTCODE_RRESB: 357 case FWTCODE_LRES: 358 xferq = fc->ats; 359 break; 360 default: 361 err = EINVAL; 362 return err; 363 } 364 /* Discard unsent buffered stream packet, when sending Asyrequrst */ 365 if(xferq != NULL && it->stproc != NULL){ 366 s = splfw(); 367 STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 368 splx(s); 369 it->stproc = NULL; 370 } 371#ifdef FWXFERQ_DV 372 if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 373#else 374 if (xferq == NULL) { 375#endif 376isoloop: 377 if (it->stproc == NULL) { 378 it->stproc = STAILQ_FIRST(&it->stfree); 379 if (it->stproc != NULL) { 380 s = splfw(); 381 STAILQ_REMOVE_HEAD(&it->stfree, link); 382 splx(s); 383 it->queued = 0; 384 } else if (slept == 0) { 385 slept = 1; 386 err = sc->fc->itx_enable(sc->fc, sub); 387 if (err) 388 return err; 389 err = tsleep(it, FWPRI, 390 "fw_write", hz); 391 if (err) 392 return err; 393 goto isoloop; 394 } else { 395 err = EIO; 396 return err; 397 } 398 } 399 fp = (struct fw_pkt *) 400 (it->stproc->buf + it->queued * it->psize); 401 err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 402 err = uiomove((caddr_t)fp->mode.stream.payload, 403 ntohs(fp->mode.stream.len), uio); 404 it->queued ++; 405 if (it->queued >= it->bnpacket) { 406 s = splfw(); 407 STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 408 splx(s); 409 it->stproc = NULL; 410 err = sc->fc->itx_enable(sc->fc, sub); 411 } 412 if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 413 slept = 0; 414 goto isoloop; 415 } 416 return err; 417 } 418#ifdef FWXFERQ_DV 419 if(xferq == NULL && it->flag & FWXFERQ_DV){ 420dvloop: 421 if(it->dvproc == NULL){ 422 it->dvproc = STAILQ_FIRST(&it->dvfree); 423 if(it->dvproc != NULL){ 424 s = splfw(); 425 STAILQ_REMOVE_HEAD(&it->dvfree, link); 426 splx(s); 427 it->dvptr = 0; 428 }else if(slept == 0){ 429 slept = 1; 430 err = sc->fc->itx_enable(sc->fc, sub); 431 if(err){ 432 return err; 433 } 434 err = tsleep(it, FWPRI, "fw_write", hz); 435 if(err){ 436 return err; 437 } 438 goto dvloop; 439 }else{ 440 err = EIO; 441 return err; 442 } 443 } 444#if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/ 445 fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 446 fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 447#endif 448 err = uiomove(it->dvproc->buf + it->dvptr, 449 uio->uio_resid, uio); 450 it->dvptr += it->psize; 451 if(err){ 452 return err; 453 } 454 if(it->dvptr >= it->psize * it->dvpacket){ 455 s = splfw(); 456 STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 457 splx(s); 458 it->dvproc = NULL; 459 err = fw_tbuf_update(sc->fc, sub, 0); 460 if(err){ 461 return err; 462 } 463 err = sc->fc->itx_enable(sc->fc, sub); 464 } 465 return err; 466 } 467#endif 468 if(xferq != NULL){ 469 xfer = fw_xfer_alloc(M_FWXFER); 470 if(xfer == NULL){ 471 err = ENOMEM; 472 return err; 473 } 474 xfer->send.buf = malloc(uio->uio_resid, M_FW, M_NOWAIT); 475 if(xfer->send.buf == NULL){ 476 fw_xfer_free( xfer); 477 err = ENOBUFS; 478 return err; 479 } 480 xfer->dst = ntohs(fp->mode.hdr.dst); 481#if 0 482 switch(fp->mode.common.tcode){ 483 case FWTCODE_WREQQ: 484 case FWTCODE_WREQB: 485 if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 486 fw_xfer_free( xfer); 487 err = EAGAIN; 488 return err; 489 } 490 fp->mode.hdr.tlrt = tl << 2; 491 default: 492 break; 493 } 494 495 xfer->tl = fp->mode.hdr.tlrt >> 2; 496 xfer->tcode = fp->mode.common.tcode; 497 xfer->fc = fc; 498 xfer->q = xferq; 499 xfer->act_type = FWACT_XFER; 500 xfer->retry_req = fw_asybusy; 501#endif 502 xfer->send.len = uio->uio_resid; 503 xfer->send.off = 0; 504 xfer->spd = 0;/* XXX: how to setup it */ 505 xfer->act.hand = fw_asy_callback; 506 507 err = uiomove(xfer->send.buf, uio->uio_resid, uio); 508 if(err){ 509 fw_xfer_free( xfer); 510 return err; 511 } 512#if 0 513 fw_asystart(xfer); 514#else 515 fw_asyreq(fc, -1, xfer); 516#endif 517 err = tsleep(xfer, FWPRI, "fw_write", hz); 518 if(xfer->resp == EBUSY) 519 return EBUSY; 520 fw_xfer_free( xfer); 521 return err; 522 } 523 return EINVAL; 524} 525 526/* 527 * ioctl support. 528 */ 529int 530fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 531{ 532 struct firewire_softc *sc; 533 int unit = DEV2UNIT(dev); 534 int sub = DEV2DMACH(dev); 535 int i, len, err = 0; 536 struct fw_device *fwdev; 537 struct fw_bind *fwb; 538 struct fw_xferq *ir, *it; 539 struct fw_xfer *xfer; 540 struct fw_pkt *fp; 541 struct fw_devinfo *devinfo; 542 543 struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 544 struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 545 struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 546 struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 547 struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 548 struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 549 550 if (DEV_FWMEM(dev)) 551 return fwmem_ioctl(dev, cmd, data, flag, td); 552 553 sc = devclass_get_softc(firewire_devclass, unit); 554 if (!data) 555 return(EINVAL); 556 557 switch (cmd) { 558 case FW_STSTREAM: 559 sc->fc->it[sub]->flag &= ~0xff; 560 sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 561 sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 562 err = 0; 563 break; 564 case FW_GTSTREAM: 565 ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 566 ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 567 err = 0; 568 break; 569 case FW_SRSTREAM: 570 sc->fc->ir[sub]->flag &= ~0xff; 571 sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 572 sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 573 err = sc->fc->irx_enable(sc->fc, sub); 574 break; 575 case FW_GRSTREAM: 576 ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 577 ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 578 err = 0; 579 break; 580#ifdef FWXFERQ_DV 581 case FW_SSTDV: 582 ibufreq = (struct fw_isobufreq *) 583 malloc(sizeof(struct fw_isobufreq), M_FW, M_NOWAIT); 584 if(ibufreq == NULL){ 585 err = ENOMEM; 586 break; 587 } 588#if DV_PAL 589#define FWDVPACKET 300 590#else 591#define FWDVPACKET 250 592#endif 593#define FWDVPMAX 512 594 ibufreq->rx.nchunk = 8; 595 ibufreq->rx.npacket = 50; 596 ibufreq->rx.psize = FWDVPMAX; 597 598 ibufreq->tx.nchunk = 5; 599 ibufreq->tx.npacket = FWDVPACKET + 30; /* > 320 or 267 */ 600 ibufreq->tx.psize = FWDVPMAX; 601 602 err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 603 sc->fc->it[sub]->dvpacket = FWDVPACKET; 604 free(ibufreq, M_FW); 605/* reserve a buffer space */ 606#define NDVCHUNK 8 607 sc->fc->it[sub]->dvproc = NULL; 608 sc->fc->it[sub]->dvdma = NULL; 609 sc->fc->it[sub]->flag |= FWXFERQ_DV; 610 /* XXX check malloc failure */ 611 sc->fc->it[sub]->dvbuf 612 = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_FW, M_NOWAIT); 613 STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 614 STAILQ_INIT(&sc->fc->it[sub]->dvfree); 615 for( i = 0 ; i < NDVCHUNK ; i++){ 616 /* XXX check malloc failure */ 617 sc->fc->it[sub]->dvbuf[i].buf 618 = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_FW, M_NOWAIT); 619 STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 620 &sc->fc->it[sub]->dvbuf[i], link); 621 } 622 break; 623#endif 624 case FW_SSTBUF: 625 ir = sc->fc->ir[sub]; 626 it = sc->fc->it[sub]; 627 628 if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 629 return(EBUSY); 630 } 631 if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 632 return(EBUSY); 633 } 634 if((ibufreq->rx.nchunk * 635 ibufreq->rx.psize * ibufreq->rx.npacket) + 636 (ibufreq->tx.nchunk * 637 ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 638 return(EINVAL); 639 } 640 if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 641 ibufreq->tx.nchunk > FWSTMAXCHUNK){ 642 return(EINVAL); 643 } 644 ir->bulkxfer 645 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_FW, 0); 646 if(ir->bulkxfer == NULL){ 647 return(ENOMEM); 648 } 649 it->bulkxfer 650 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_FW, 0); 651 if(it->bulkxfer == NULL){ 652 return(ENOMEM); 653 } 654 ir->buf = malloc( 655 ibufreq->rx.nchunk * ibufreq->rx.npacket 656 /* XXX psize must be 2^n and less or 657 equal to PAGE_SIZE */ 658 * ((ibufreq->rx.psize + 3) &~3), 659 M_FW, 0); 660 if(ir->buf == NULL){ 661 free(ir->bulkxfer, M_FW); 662 free(it->bulkxfer, M_FW); 663 ir->bulkxfer = NULL; 664 it->bulkxfer = NULL; 665 it->buf = NULL; 666 return(ENOMEM); 667 } 668 it->buf = malloc( 669 ibufreq->tx.nchunk * ibufreq->tx.npacket 670 /* XXX psize must be 2^n and less or 671 equal to PAGE_SIZE */ 672 * ((ibufreq->tx.psize + 3) &~3), 673 M_FW, 0); 674 if(it->buf == NULL){ 675 free(ir->bulkxfer, M_FW); 676 free(it->bulkxfer, M_FW); 677 free(ir->buf, M_FW); 678 ir->bulkxfer = NULL; 679 it->bulkxfer = NULL; 680 it->buf = NULL; 681 return(ENOMEM); 682 } 683 684 ir->bnchunk = ibufreq->rx.nchunk; 685 ir->bnpacket = ibufreq->rx.npacket; 686 ir->psize = (ibufreq->rx.psize + 3) & ~3; 687 ir->queued = 0; 688 689 it->bnchunk = ibufreq->tx.nchunk; 690 it->bnpacket = ibufreq->tx.npacket; 691 it->psize = (ibufreq->tx.psize + 3) & ~3; 692 it->queued = 0; 693 694#ifdef FWXFERQ_DV 695 it->dvdbc = 0; 696 it->dvdiff = 0; 697 it->dvsync = 0; 698 it->dvoffset = 0; 699#endif 700 701 STAILQ_INIT(&ir->stvalid); 702 STAILQ_INIT(&ir->stfree); 703 STAILQ_INIT(&ir->stdma); 704 ir->stproc = NULL; 705 706 STAILQ_INIT(&it->stvalid); 707 STAILQ_INIT(&it->stfree); 708 STAILQ_INIT(&it->stdma); 709 it->stproc = NULL; 710 711 for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 712 ir->bulkxfer[i].buf = 713 ir->buf + 714 i * sc->fc->ir[sub]->bnpacket * 715 sc->fc->ir[sub]->psize; 716 STAILQ_INSERT_TAIL(&ir->stfree, 717 &ir->bulkxfer[i], link); 718 ir->bulkxfer[i].npacket = ir->bnpacket; 719 } 720 for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 721 it->bulkxfer[i].buf = 722 it->buf + 723 i * sc->fc->it[sub]->bnpacket * 724 sc->fc->it[sub]->psize; 725 STAILQ_INSERT_TAIL(&it->stfree, 726 &it->bulkxfer[i], link); 727 it->bulkxfer[i].npacket = it->bnpacket; 728 } 729 ir->flag &= ~FWXFERQ_MODEMASK; 730 ir->flag |= FWXFERQ_STREAM; 731 ir->flag |= FWXFERQ_EXTBUF; 732 733 it->flag &= ~FWXFERQ_MODEMASK; 734 it->flag |= FWXFERQ_STREAM; 735 it->flag |= FWXFERQ_EXTBUF; 736 err = 0; 737 break; 738 case FW_GSTBUF: 739 ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 740 ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 741 ibufreq->rx.psize = sc->fc->ir[sub]->psize; 742 743 ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 744 ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 745 ibufreq->tx.psize = sc->fc->it[sub]->psize; 746 break; 747 case FW_ASYREQ: 748 xfer = fw_xfer_alloc(M_FWXFER); 749 if(xfer == NULL){ 750 err = ENOMEM; 751 return err; 752 } 753 fp = &asyreq->pkt; 754 switch (asyreq->req.type) { 755 case FWASREQNODE: 756 xfer->dst = ntohs(fp->mode.hdr.dst); 757 break; 758 case FWASREQEUI: 759 fwdev = fw_noderesolve_eui64(sc->fc, 760 &asyreq->req.dst.eui); 761 if (fwdev == NULL) { 762 device_printf(sc->fc->bdev, 763 "cannot find node\n"); 764 err = EINVAL; 765 goto error; 766 } 767 xfer->dst = fwdev->dst; 768 fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 769 break; 770 case FWASRESTL: 771 /* XXX what's this? */ 772 break; 773 case FWASREQSTREAM: 774 /* nothing to do */ 775 break; 776 } 777 xfer->spd = asyreq->req.sped; 778 xfer->send.len = asyreq->req.len; 779 xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT); 780 if(xfer->send.buf == NULL){ 781 return ENOMEM; 782 } 783 xfer->send.off = 0; 784 bcopy(fp, xfer->send.buf, xfer->send.len); 785 xfer->act.hand = fw_asy_callback; 786 err = fw_asyreq(sc->fc, sub, xfer); 787 if(err){ 788 fw_xfer_free( xfer); 789 return err; 790 } 791 err = tsleep(xfer, FWPRI, "asyreq", hz); 792 if(err == 0){ 793 if(asyreq->req.len >= xfer->recv.len){ 794 asyreq->req.len = xfer->recv.len; 795 }else{ 796 err = EINVAL; 797 } 798 bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 799 } 800error: 801 fw_xfer_free( xfer); 802 break; 803 case FW_IBUSRST: 804 sc->fc->ibr(sc->fc); 805 break; 806 case FW_CBINDADDR: 807 fwb = fw_bindlookup(sc->fc, 808 bindreq->start.hi, bindreq->start.lo); 809 if(fwb == NULL){ 810 err = EINVAL; 811 break; 812 } 813 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 814 STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 815 free(fwb, M_FW); 816 break; 817 case FW_SBINDADDR: 818 if(bindreq->len <= 0 ){ 819 err = EINVAL; 820 break; 821 } 822 if(bindreq->start.hi > 0xffff ){ 823 err = EINVAL; 824 break; 825 } 826 fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 827 if(fwb == NULL){ 828 err = ENOMEM; 829 break; 830 } 831 fwb->start_hi = bindreq->start.hi; 832 fwb->start_lo = bindreq->start.lo; 833 fwb->addrlen = bindreq->len; 834 835 xfer = fw_xfer_alloc(M_FWXFER); 836 if(xfer == NULL){ 837 err = ENOMEM; 838 return err; 839 } 840 xfer->act_type = FWACT_CH; 841 xfer->sub = sub; 842 xfer->fc = sc->fc; 843 844 fwb->xfer = xfer; 845 err = fw_bindadd(sc->fc, fwb); 846 break; 847 case FW_GDEVLST: 848 i = len = 1; 849 /* myself */ 850 devinfo = &fwdevlst->dev[0]; 851 devinfo->dst = sc->fc->nodeid; 852 devinfo->status = 0; /* XXX */ 853 devinfo->eui.hi = sc->fc->eui.hi; 854 devinfo->eui.lo = sc->fc->eui.lo; 855 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 856 if(len < FW_MAX_DEVLST){ 857 devinfo = &fwdevlst->dev[len++]; 858 devinfo->dst = fwdev->dst; 859 devinfo->status = 860 (fwdev->status == FWDEVINVAL)?0:1; 861 devinfo->eui.hi = fwdev->eui.hi; 862 devinfo->eui.lo = fwdev->eui.lo; 863 } 864 i++; 865 } 866 fwdevlst->n = i; 867 fwdevlst->info_len = len; 868 break; 869 case FW_GTPMAP: 870 bcopy(sc->fc->topology_map, data, 871 (sc->fc->topology_map->crc_len + 1) * 4); 872 break; 873 case FW_GCROM: 874 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 875 if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 876 break; 877 if (fwdev == NULL) { 878 err = FWNODE_INVAL; 879 break; 880 } 881#if 0 882 if (fwdev->csrrom[0] >> 24 == 1) 883 len = 4; 884 else 885 len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 886#else 887 if (fwdev->rommax < CSRROMOFF) 888 len = 0; 889 else 890 len = fwdev->rommax - CSRROMOFF + 4; 891#endif 892 if (crom_buf->len < len) 893 len = crom_buf->len; 894 else 895 crom_buf->len = len; 896 err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 897 break; 898 default: 899 sc->fc->ioctl (dev, cmd, data, flag, td); 900 break; 901 } 902 return err; 903} 904int 905fw_poll(dev_t dev, int events, fw_proc *td) 906{ 907 int revents; 908 int tmp; 909 int unit = DEV2UNIT(dev); 910 int sub = DEV2DMACH(dev); 911 struct firewire_softc *sc; 912 913 if (DEV_FWMEM(dev)) 914 return fwmem_poll(dev, events, td); 915 916 sc = devclass_get_softc(firewire_devclass, unit); 917 revents = 0; 918 tmp = POLLIN | POLLRDNORM; 919 if (events & tmp) { 920 if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 921 revents |= tmp; 922 else 923 selrecord(td, &sc->fc->ir[sub]->rsel); 924 } 925 tmp = POLLOUT | POLLWRNORM; 926 if (events & tmp) { 927 /* XXX should be fixed */ 928 revents |= tmp; 929 } 930 931 return revents; 932} 933 934static int 935#if __FreeBSD_version < 500000 936fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 937#else 938fw_mmap (dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nproto) 939#endif 940{ 941 struct firewire_softc *fc; 942 int unit = DEV2UNIT(dev); 943 944 if (DEV_FWMEM(dev)) 945#if __FreeBSD_version < 500000 946 return fwmem_mmap(dev, offset, nproto); 947#else 948 return fwmem_mmap(dev, offset, paddr, nproto); 949#endif 950 951 fc = devclass_get_softc(firewire_devclass, unit); 952 953 return EINVAL; 954}
| 80}; 81 82static int 83fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 84{ 85 struct firewire_softc *sc; 86 int unit = DEV2UNIT(dev); 87 int sub = DEV2DMACH(dev); 88 89 int err = 0; 90 91 if (DEV_FWMEM(dev)) 92 return fwmem_open(dev, flags, fmt, td); 93 94 sc = devclass_get_softc(firewire_devclass, unit); 95 if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 96 err = EBUSY; 97 return err; 98 } 99 if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 100 err = EBUSY; 101 return err; 102 } 103 if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 104 err = EBUSY; 105 return err; 106 } 107/* Default is per packet mode */ 108 sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 109 sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 110 sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 111 return err; 112} 113 114static int 115fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 116{ 117 struct firewire_softc *sc; 118 int unit = DEV2UNIT(dev); 119 int sub = DEV2DMACH(dev); 120 struct fw_xfer *xfer; 121 struct fw_bind *fwb; 122 int err = 0; 123 124 if (DEV_FWMEM(dev)) 125 return fwmem_close(dev, flags, fmt, td); 126 127 sc = devclass_get_softc(firewire_devclass, unit); 128 if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 129 err = EINVAL; 130 return err; 131 } 132 sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 133 if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 134 err = EINVAL; 135 return err; 136 } 137 sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 138 139 if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 140 sc->fc->irx_disable(sc->fc, sub); 141 } 142 if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 143 sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 144 sc->fc->itx_disable(sc->fc, sub); 145 } 146#ifdef FWXFERQ_DV 147 if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 148 struct fw_dvbuf *dvbuf; 149 150 if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 151 free(dvbuf->buf, M_FW); 152 sc->fc->it[sub]->dvproc = NULL; 153 } 154 if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 155 free(dvbuf->buf, M_FW); 156 sc->fc->it[sub]->dvdma = NULL; 157 } 158 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 159 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 160 free(dvbuf->buf, M_FW); 161 } 162 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 163 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 164 free(dvbuf->buf, M_FW); 165 } 166 free(sc->fc->it[sub]->dvbuf, M_FW); 167 sc->fc->it[sub]->dvbuf = NULL; 168 } 169#endif 170 if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 171 free(sc->fc->ir[sub]->buf, M_FW); 172 sc->fc->ir[sub]->buf = NULL; 173 free(sc->fc->ir[sub]->bulkxfer, M_FW); 174 sc->fc->ir[sub]->bulkxfer = NULL; 175 sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 176 sc->fc->ir[sub]->psize = PAGE_SIZE; 177 sc->fc->ir[sub]->maxq = FWMAXQUEUE; 178 } 179 if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 180 free(sc->fc->it[sub]->buf, M_FW); 181 sc->fc->it[sub]->buf = NULL; 182 free(sc->fc->it[sub]->bulkxfer, M_FW); 183 sc->fc->it[sub]->bulkxfer = NULL; 184#ifdef FWXFERQ_DV 185 sc->fc->it[sub]->dvbuf = NULL; 186#endif 187 sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 188 sc->fc->it[sub]->psize = 0; 189 sc->fc->it[sub]->maxq = FWMAXQUEUE; 190 } 191 for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 192 xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 193 sc->fc->ir[sub]->queued--; 194 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 195 196 xfer->resp = 0; 197 switch(xfer->act_type){ 198 case FWACT_XFER: 199 fw_xfer_done(xfer); 200 break; 201 default: 202 break; 203 } 204 fw_xfer_free(xfer); 205 } 206 for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 207 fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 208 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 209 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 210 free(fwb, M_FW); 211 } 212 sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 213 sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 214 return err; 215} 216 217/* 218 * read request. 219 */ 220static int 221fw_read (dev_t dev, struct uio *uio, int ioflag) 222{ 223 struct firewire_softc *sc; 224 struct fw_xferq *ir; 225 struct fw_xfer *xfer; 226 int err = 0, s, slept = 0; 227 int unit = DEV2UNIT(dev); 228 int sub = DEV2DMACH(dev); 229 struct fw_pkt *fp; 230 231 if (DEV_FWMEM(dev)) 232 return fwmem_read(dev, uio, ioflag); 233 234 sc = devclass_get_softc(firewire_devclass, unit); 235 236 ir = sc->fc->ir[sub]; 237 238 if (ir->flag & FWXFERQ_PACKET) { 239 ir->stproc = NULL; 240 } 241readloop: 242 xfer = STAILQ_FIRST(&ir->q); 243 if ((ir->flag & FWXFERQ_PACKET) == 0 && ir->stproc == NULL) { 244 /* iso bulkxfer */ 245 ir->stproc = STAILQ_FIRST(&ir->stvalid); 246 if (ir->stproc != NULL) { 247 s = splfw(); 248 STAILQ_REMOVE_HEAD(&ir->stvalid, link); 249 splx(s); 250 ir->queued = 0; 251 } 252 } 253 if (xfer == NULL && ir->stproc == NULL) { 254 /* no data avaliable */ 255 if (slept == 0) { 256 slept = 1; 257 if ((ir->flag & FWXFERQ_RUNNING) == 0 258 && (ir->flag & FWXFERQ_PACKET)) { 259 err = sc->fc->irx_enable(sc->fc, sub); 260 if (err) 261 return err; 262 } 263 ir->flag |= FWXFERQ_WAKEUP; 264 err = tsleep(ir, FWPRI, "fw_read", hz); 265 ir->flag &= ~FWXFERQ_WAKEUP; 266 if (err == 0) 267 goto readloop; 268 } else if (slept == 1) 269 err = EIO; 270 return err; 271 } else if(xfer != NULL) { 272 /* per packet mode */ 273 s = splfw(); 274 ir->queued --; 275 STAILQ_REMOVE_HEAD(&ir->q, link); 276 splx(s); 277 fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 278 if(sc->fc->irx_post != NULL) 279 sc->fc->irx_post(sc->fc, fp->mode.ld); 280 err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 281 fw_xfer_free( xfer); 282 } else if(ir->stproc != NULL) { 283 /* iso bulkxfer */ 284 fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 285 if(sc->fc->irx_post != NULL) 286 sc->fc->irx_post(sc->fc, fp->mode.ld); 287 if(ntohs(fp->mode.stream.len) == 0){ 288 err = EIO; 289 return err; 290 } 291 err = uiomove((caddr_t)fp, 292 ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 293#if 0 294 fp->mode.stream.len = 0; 295#endif 296 ir->queued ++; 297 if(ir->queued >= ir->bnpacket){ 298 s = splfw(); 299 STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 300 splx(s); 301 sc->fc->irx_enable(sc->fc, sub); 302 ir->stproc = NULL; 303 } 304 if (uio->uio_resid >= ir->psize) { 305 slept = -1; 306 goto readloop; 307 } 308 } 309 return err; 310} 311 312static int 313fw_write (dev_t dev, struct uio *uio, int ioflag) 314{ 315 int err = 0; 316 struct firewire_softc *sc; 317 int unit = DEV2UNIT(dev); 318 int sub = DEV2DMACH(dev); 319 int s, slept = 0; 320 struct fw_pkt *fp; 321 struct fw_xfer *xfer; 322 struct fw_xferq *xferq; 323 struct firewire_comm *fc; 324 struct fw_xferq *it; 325 326 if (DEV_FWMEM(dev)) 327 return fwmem_write(dev, uio, ioflag); 328 329 sc = devclass_get_softc(firewire_devclass, unit); 330 fc = sc->fc; 331 it = sc->fc->it[sub]; 332 333 fp = (struct fw_pkt *)uio->uio_iov->iov_base; 334 switch(fp->mode.common.tcode){ 335 case FWTCODE_RREQQ: 336 case FWTCODE_RREQB: 337 case FWTCODE_LREQ: 338 err = EINVAL; 339 return err; 340 case FWTCODE_WREQQ: 341 case FWTCODE_WREQB: 342 xferq = fc->atq; 343 break; 344 case FWTCODE_STREAM: 345 if(it->flag & FWXFERQ_PACKET){ 346 xferq = fc->atq; 347 }else{ 348 xferq = NULL; 349 } 350 break; 351 case FWTCODE_WRES: 352 case FWTCODE_RRESQ: 353 case FWTCODE_RRESB: 354 case FWTCODE_LRES: 355 xferq = fc->ats; 356 break; 357 default: 358 err = EINVAL; 359 return err; 360 } 361 /* Discard unsent buffered stream packet, when sending Asyrequrst */ 362 if(xferq != NULL && it->stproc != NULL){ 363 s = splfw(); 364 STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 365 splx(s); 366 it->stproc = NULL; 367 } 368#ifdef FWXFERQ_DV 369 if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 370#else 371 if (xferq == NULL) { 372#endif 373isoloop: 374 if (it->stproc == NULL) { 375 it->stproc = STAILQ_FIRST(&it->stfree); 376 if (it->stproc != NULL) { 377 s = splfw(); 378 STAILQ_REMOVE_HEAD(&it->stfree, link); 379 splx(s); 380 it->queued = 0; 381 } else if (slept == 0) { 382 slept = 1; 383 err = sc->fc->itx_enable(sc->fc, sub); 384 if (err) 385 return err; 386 err = tsleep(it, FWPRI, 387 "fw_write", hz); 388 if (err) 389 return err; 390 goto isoloop; 391 } else { 392 err = EIO; 393 return err; 394 } 395 } 396 fp = (struct fw_pkt *) 397 (it->stproc->buf + it->queued * it->psize); 398 err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio); 399 err = uiomove((caddr_t)fp->mode.stream.payload, 400 ntohs(fp->mode.stream.len), uio); 401 it->queued ++; 402 if (it->queued >= it->bnpacket) { 403 s = splfw(); 404 STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 405 splx(s); 406 it->stproc = NULL; 407 err = sc->fc->itx_enable(sc->fc, sub); 408 } 409 if (uio->uio_resid >= sizeof(struct fw_isohdr)) { 410 slept = 0; 411 goto isoloop; 412 } 413 return err; 414 } 415#ifdef FWXFERQ_DV 416 if(xferq == NULL && it->flag & FWXFERQ_DV){ 417dvloop: 418 if(it->dvproc == NULL){ 419 it->dvproc = STAILQ_FIRST(&it->dvfree); 420 if(it->dvproc != NULL){ 421 s = splfw(); 422 STAILQ_REMOVE_HEAD(&it->dvfree, link); 423 splx(s); 424 it->dvptr = 0; 425 }else if(slept == 0){ 426 slept = 1; 427 err = sc->fc->itx_enable(sc->fc, sub); 428 if(err){ 429 return err; 430 } 431 err = tsleep(it, FWPRI, "fw_write", hz); 432 if(err){ 433 return err; 434 } 435 goto dvloop; 436 }else{ 437 err = EIO; 438 return err; 439 } 440 } 441#if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/ 442 fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 443 fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 444#endif 445 err = uiomove(it->dvproc->buf + it->dvptr, 446 uio->uio_resid, uio); 447 it->dvptr += it->psize; 448 if(err){ 449 return err; 450 } 451 if(it->dvptr >= it->psize * it->dvpacket){ 452 s = splfw(); 453 STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 454 splx(s); 455 it->dvproc = NULL; 456 err = fw_tbuf_update(sc->fc, sub, 0); 457 if(err){ 458 return err; 459 } 460 err = sc->fc->itx_enable(sc->fc, sub); 461 } 462 return err; 463 } 464#endif 465 if(xferq != NULL){ 466 xfer = fw_xfer_alloc(M_FWXFER); 467 if(xfer == NULL){ 468 err = ENOMEM; 469 return err; 470 } 471 xfer->send.buf = malloc(uio->uio_resid, M_FW, M_NOWAIT); 472 if(xfer->send.buf == NULL){ 473 fw_xfer_free( xfer); 474 err = ENOBUFS; 475 return err; 476 } 477 xfer->dst = ntohs(fp->mode.hdr.dst); 478#if 0 479 switch(fp->mode.common.tcode){ 480 case FWTCODE_WREQQ: 481 case FWTCODE_WREQB: 482 if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 483 fw_xfer_free( xfer); 484 err = EAGAIN; 485 return err; 486 } 487 fp->mode.hdr.tlrt = tl << 2; 488 default: 489 break; 490 } 491 492 xfer->tl = fp->mode.hdr.tlrt >> 2; 493 xfer->tcode = fp->mode.common.tcode; 494 xfer->fc = fc; 495 xfer->q = xferq; 496 xfer->act_type = FWACT_XFER; 497 xfer->retry_req = fw_asybusy; 498#endif 499 xfer->send.len = uio->uio_resid; 500 xfer->send.off = 0; 501 xfer->spd = 0;/* XXX: how to setup it */ 502 xfer->act.hand = fw_asy_callback; 503 504 err = uiomove(xfer->send.buf, uio->uio_resid, uio); 505 if(err){ 506 fw_xfer_free( xfer); 507 return err; 508 } 509#if 0 510 fw_asystart(xfer); 511#else 512 fw_asyreq(fc, -1, xfer); 513#endif 514 err = tsleep(xfer, FWPRI, "fw_write", hz); 515 if(xfer->resp == EBUSY) 516 return EBUSY; 517 fw_xfer_free( xfer); 518 return err; 519 } 520 return EINVAL; 521} 522 523/* 524 * ioctl support. 525 */ 526int 527fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 528{ 529 struct firewire_softc *sc; 530 int unit = DEV2UNIT(dev); 531 int sub = DEV2DMACH(dev); 532 int i, len, err = 0; 533 struct fw_device *fwdev; 534 struct fw_bind *fwb; 535 struct fw_xferq *ir, *it; 536 struct fw_xfer *xfer; 537 struct fw_pkt *fp; 538 struct fw_devinfo *devinfo; 539 540 struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 541 struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 542 struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 543 struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 544 struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 545 struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 546 547 if (DEV_FWMEM(dev)) 548 return fwmem_ioctl(dev, cmd, data, flag, td); 549 550 sc = devclass_get_softc(firewire_devclass, unit); 551 if (!data) 552 return(EINVAL); 553 554 switch (cmd) { 555 case FW_STSTREAM: 556 sc->fc->it[sub]->flag &= ~0xff; 557 sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 558 sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 559 err = 0; 560 break; 561 case FW_GTSTREAM: 562 ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 563 ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 564 err = 0; 565 break; 566 case FW_SRSTREAM: 567 sc->fc->ir[sub]->flag &= ~0xff; 568 sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 569 sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 570 err = sc->fc->irx_enable(sc->fc, sub); 571 break; 572 case FW_GRSTREAM: 573 ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 574 ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 575 err = 0; 576 break; 577#ifdef FWXFERQ_DV 578 case FW_SSTDV: 579 ibufreq = (struct fw_isobufreq *) 580 malloc(sizeof(struct fw_isobufreq), M_FW, M_NOWAIT); 581 if(ibufreq == NULL){ 582 err = ENOMEM; 583 break; 584 } 585#if DV_PAL 586#define FWDVPACKET 300 587#else 588#define FWDVPACKET 250 589#endif 590#define FWDVPMAX 512 591 ibufreq->rx.nchunk = 8; 592 ibufreq->rx.npacket = 50; 593 ibufreq->rx.psize = FWDVPMAX; 594 595 ibufreq->tx.nchunk = 5; 596 ibufreq->tx.npacket = FWDVPACKET + 30; /* > 320 or 267 */ 597 ibufreq->tx.psize = FWDVPMAX; 598 599 err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 600 sc->fc->it[sub]->dvpacket = FWDVPACKET; 601 free(ibufreq, M_FW); 602/* reserve a buffer space */ 603#define NDVCHUNK 8 604 sc->fc->it[sub]->dvproc = NULL; 605 sc->fc->it[sub]->dvdma = NULL; 606 sc->fc->it[sub]->flag |= FWXFERQ_DV; 607 /* XXX check malloc failure */ 608 sc->fc->it[sub]->dvbuf 609 = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_FW, M_NOWAIT); 610 STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 611 STAILQ_INIT(&sc->fc->it[sub]->dvfree); 612 for( i = 0 ; i < NDVCHUNK ; i++){ 613 /* XXX check malloc failure */ 614 sc->fc->it[sub]->dvbuf[i].buf 615 = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_FW, M_NOWAIT); 616 STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 617 &sc->fc->it[sub]->dvbuf[i], link); 618 } 619 break; 620#endif 621 case FW_SSTBUF: 622 ir = sc->fc->ir[sub]; 623 it = sc->fc->it[sub]; 624 625 if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 626 return(EBUSY); 627 } 628 if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 629 return(EBUSY); 630 } 631 if((ibufreq->rx.nchunk * 632 ibufreq->rx.psize * ibufreq->rx.npacket) + 633 (ibufreq->tx.nchunk * 634 ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 635 return(EINVAL); 636 } 637 if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 638 ibufreq->tx.nchunk > FWSTMAXCHUNK){ 639 return(EINVAL); 640 } 641 ir->bulkxfer 642 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_FW, 0); 643 if(ir->bulkxfer == NULL){ 644 return(ENOMEM); 645 } 646 it->bulkxfer 647 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_FW, 0); 648 if(it->bulkxfer == NULL){ 649 return(ENOMEM); 650 } 651 ir->buf = malloc( 652 ibufreq->rx.nchunk * ibufreq->rx.npacket 653 /* XXX psize must be 2^n and less or 654 equal to PAGE_SIZE */ 655 * ((ibufreq->rx.psize + 3) &~3), 656 M_FW, 0); 657 if(ir->buf == NULL){ 658 free(ir->bulkxfer, M_FW); 659 free(it->bulkxfer, M_FW); 660 ir->bulkxfer = NULL; 661 it->bulkxfer = NULL; 662 it->buf = NULL; 663 return(ENOMEM); 664 } 665 it->buf = malloc( 666 ibufreq->tx.nchunk * ibufreq->tx.npacket 667 /* XXX psize must be 2^n and less or 668 equal to PAGE_SIZE */ 669 * ((ibufreq->tx.psize + 3) &~3), 670 M_FW, 0); 671 if(it->buf == NULL){ 672 free(ir->bulkxfer, M_FW); 673 free(it->bulkxfer, M_FW); 674 free(ir->buf, M_FW); 675 ir->bulkxfer = NULL; 676 it->bulkxfer = NULL; 677 it->buf = NULL; 678 return(ENOMEM); 679 } 680 681 ir->bnchunk = ibufreq->rx.nchunk; 682 ir->bnpacket = ibufreq->rx.npacket; 683 ir->psize = (ibufreq->rx.psize + 3) & ~3; 684 ir->queued = 0; 685 686 it->bnchunk = ibufreq->tx.nchunk; 687 it->bnpacket = ibufreq->tx.npacket; 688 it->psize = (ibufreq->tx.psize + 3) & ~3; 689 it->queued = 0; 690 691#ifdef FWXFERQ_DV 692 it->dvdbc = 0; 693 it->dvdiff = 0; 694 it->dvsync = 0; 695 it->dvoffset = 0; 696#endif 697 698 STAILQ_INIT(&ir->stvalid); 699 STAILQ_INIT(&ir->stfree); 700 STAILQ_INIT(&ir->stdma); 701 ir->stproc = NULL; 702 703 STAILQ_INIT(&it->stvalid); 704 STAILQ_INIT(&it->stfree); 705 STAILQ_INIT(&it->stdma); 706 it->stproc = NULL; 707 708 for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 709 ir->bulkxfer[i].buf = 710 ir->buf + 711 i * sc->fc->ir[sub]->bnpacket * 712 sc->fc->ir[sub]->psize; 713 STAILQ_INSERT_TAIL(&ir->stfree, 714 &ir->bulkxfer[i], link); 715 ir->bulkxfer[i].npacket = ir->bnpacket; 716 } 717 for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 718 it->bulkxfer[i].buf = 719 it->buf + 720 i * sc->fc->it[sub]->bnpacket * 721 sc->fc->it[sub]->psize; 722 STAILQ_INSERT_TAIL(&it->stfree, 723 &it->bulkxfer[i], link); 724 it->bulkxfer[i].npacket = it->bnpacket; 725 } 726 ir->flag &= ~FWXFERQ_MODEMASK; 727 ir->flag |= FWXFERQ_STREAM; 728 ir->flag |= FWXFERQ_EXTBUF; 729 730 it->flag &= ~FWXFERQ_MODEMASK; 731 it->flag |= FWXFERQ_STREAM; 732 it->flag |= FWXFERQ_EXTBUF; 733 err = 0; 734 break; 735 case FW_GSTBUF: 736 ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 737 ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 738 ibufreq->rx.psize = sc->fc->ir[sub]->psize; 739 740 ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 741 ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 742 ibufreq->tx.psize = sc->fc->it[sub]->psize; 743 break; 744 case FW_ASYREQ: 745 xfer = fw_xfer_alloc(M_FWXFER); 746 if(xfer == NULL){ 747 err = ENOMEM; 748 return err; 749 } 750 fp = &asyreq->pkt; 751 switch (asyreq->req.type) { 752 case FWASREQNODE: 753 xfer->dst = ntohs(fp->mode.hdr.dst); 754 break; 755 case FWASREQEUI: 756 fwdev = fw_noderesolve_eui64(sc->fc, 757 &asyreq->req.dst.eui); 758 if (fwdev == NULL) { 759 device_printf(sc->fc->bdev, 760 "cannot find node\n"); 761 err = EINVAL; 762 goto error; 763 } 764 xfer->dst = fwdev->dst; 765 fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 766 break; 767 case FWASRESTL: 768 /* XXX what's this? */ 769 break; 770 case FWASREQSTREAM: 771 /* nothing to do */ 772 break; 773 } 774 xfer->spd = asyreq->req.sped; 775 xfer->send.len = asyreq->req.len; 776 xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT); 777 if(xfer->send.buf == NULL){ 778 return ENOMEM; 779 } 780 xfer->send.off = 0; 781 bcopy(fp, xfer->send.buf, xfer->send.len); 782 xfer->act.hand = fw_asy_callback; 783 err = fw_asyreq(sc->fc, sub, xfer); 784 if(err){ 785 fw_xfer_free( xfer); 786 return err; 787 } 788 err = tsleep(xfer, FWPRI, "asyreq", hz); 789 if(err == 0){ 790 if(asyreq->req.len >= xfer->recv.len){ 791 asyreq->req.len = xfer->recv.len; 792 }else{ 793 err = EINVAL; 794 } 795 bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 796 } 797error: 798 fw_xfer_free( xfer); 799 break; 800 case FW_IBUSRST: 801 sc->fc->ibr(sc->fc); 802 break; 803 case FW_CBINDADDR: 804 fwb = fw_bindlookup(sc->fc, 805 bindreq->start.hi, bindreq->start.lo); 806 if(fwb == NULL){ 807 err = EINVAL; 808 break; 809 } 810 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 811 STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 812 free(fwb, M_FW); 813 break; 814 case FW_SBINDADDR: 815 if(bindreq->len <= 0 ){ 816 err = EINVAL; 817 break; 818 } 819 if(bindreq->start.hi > 0xffff ){ 820 err = EINVAL; 821 break; 822 } 823 fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); 824 if(fwb == NULL){ 825 err = ENOMEM; 826 break; 827 } 828 fwb->start_hi = bindreq->start.hi; 829 fwb->start_lo = bindreq->start.lo; 830 fwb->addrlen = bindreq->len; 831 832 xfer = fw_xfer_alloc(M_FWXFER); 833 if(xfer == NULL){ 834 err = ENOMEM; 835 return err; 836 } 837 xfer->act_type = FWACT_CH; 838 xfer->sub = sub; 839 xfer->fc = sc->fc; 840 841 fwb->xfer = xfer; 842 err = fw_bindadd(sc->fc, fwb); 843 break; 844 case FW_GDEVLST: 845 i = len = 1; 846 /* myself */ 847 devinfo = &fwdevlst->dev[0]; 848 devinfo->dst = sc->fc->nodeid; 849 devinfo->status = 0; /* XXX */ 850 devinfo->eui.hi = sc->fc->eui.hi; 851 devinfo->eui.lo = sc->fc->eui.lo; 852 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) { 853 if(len < FW_MAX_DEVLST){ 854 devinfo = &fwdevlst->dev[len++]; 855 devinfo->dst = fwdev->dst; 856 devinfo->status = 857 (fwdev->status == FWDEVINVAL)?0:1; 858 devinfo->eui.hi = fwdev->eui.hi; 859 devinfo->eui.lo = fwdev->eui.lo; 860 } 861 i++; 862 } 863 fwdevlst->n = i; 864 fwdevlst->info_len = len; 865 break; 866 case FW_GTPMAP: 867 bcopy(sc->fc->topology_map, data, 868 (sc->fc->topology_map->crc_len + 1) * 4); 869 break; 870 case FW_GCROM: 871 STAILQ_FOREACH(fwdev, &sc->fc->devices, link) 872 if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) 873 break; 874 if (fwdev == NULL) { 875 err = FWNODE_INVAL; 876 break; 877 } 878#if 0 879 if (fwdev->csrrom[0] >> 24 == 1) 880 len = 4; 881 else 882 len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 883#else 884 if (fwdev->rommax < CSRROMOFF) 885 len = 0; 886 else 887 len = fwdev->rommax - CSRROMOFF + 4; 888#endif 889 if (crom_buf->len < len) 890 len = crom_buf->len; 891 else 892 crom_buf->len = len; 893 err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 894 break; 895 default: 896 sc->fc->ioctl (dev, cmd, data, flag, td); 897 break; 898 } 899 return err; 900} 901int 902fw_poll(dev_t dev, int events, fw_proc *td) 903{ 904 int revents; 905 int tmp; 906 int unit = DEV2UNIT(dev); 907 int sub = DEV2DMACH(dev); 908 struct firewire_softc *sc; 909 910 if (DEV_FWMEM(dev)) 911 return fwmem_poll(dev, events, td); 912 913 sc = devclass_get_softc(firewire_devclass, unit); 914 revents = 0; 915 tmp = POLLIN | POLLRDNORM; 916 if (events & tmp) { 917 if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 918 revents |= tmp; 919 else 920 selrecord(td, &sc->fc->ir[sub]->rsel); 921 } 922 tmp = POLLOUT | POLLWRNORM; 923 if (events & tmp) { 924 /* XXX should be fixed */ 925 revents |= tmp; 926 } 927 928 return revents; 929} 930 931static int 932#if __FreeBSD_version < 500000 933fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 934#else 935fw_mmap (dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nproto) 936#endif 937{ 938 struct firewire_softc *fc; 939 int unit = DEV2UNIT(dev); 940 941 if (DEV_FWMEM(dev)) 942#if __FreeBSD_version < 500000 943 return fwmem_mmap(dev, offset, nproto); 944#else 945 return fwmem_mmap(dev, offset, paddr, nproto); 946#endif 947 948 fc = devclass_get_softc(firewire_devclass, unit); 949 950 return EINVAL; 951}
|