firewire.c revision 106543
1/* 2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the acknowledgement as bellow: 15 * 16 * This product includes software developed by K. Kobayashi and H. Shimokawa 17 * 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD: head/sys/dev/firewire/firewire.c 106543 2002-11-07 02:13:40Z simokawa $ 34 * 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/types.h> 40#include <sys/mbuf.h> 41#include <sys/socket.h> 42#include <sys/socketvar.h> 43 44#include <sys/kernel.h> 45#include <sys/malloc.h> 46#include <sys/conf.h> 47#include <sys/uio.h> 48#include <sys/sysctl.h> 49#include <sys/poll.h> 50 51#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */ 52#include <machine/clock.h> 53#include <pci/pcivar.h> 54#include <pci/pcireg.h> 55 56#include <vm/vm.h> 57#include <vm/pmap.h> /* for vtophys proto */ 58#include <vm/vm_extern.h> 59 60#include <sys/bus.h> /* used by smbus and newbus */ 61 62#include <machine/bus.h> /* used by newbus */ 63#include <sys/rman.h> /* used by newbus */ 64#include <machine/resource.h> /* used by newbus */ 65 66#include <sys/signal.h> 67#include <sys/mman.h> 68#include <sys/ioccom.h> 69 70#include <dev/firewire/firewire.h> 71#include <dev/firewire/firewirereg.h> 72#include <dev/firewire/fwmem.h> 73#include <dev/firewire/iec13213.h> 74#include <dev/firewire/iec68113.h> 75 76int firewire_debug=0; 77SYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "Firewire Subsystem"); 78SYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0, 79 "Firewire driver debug flag"); 80 81#define CDEV_MAJOR 127 82#define FW_MAXASYRTY 4 83#define FW_MAXDEVRCNT 4 84#define FWNODE_INVAL 0xffff 85 86#define XFER_TIMEOUT 0 87 88static d_open_t fw_open; 89static d_close_t fw_close; 90static d_ioctl_t fw_ioctl; 91static d_poll_t fw_poll; 92static d_read_t fw_read; /* for Isochronous packet */ 93static d_write_t fw_write; 94static d_mmap_t fw_mmap; 95 96devclass_t firewire_devclass; 97 98 99static int firewire_match __P((device_t)); 100static int firewire_attach __P((device_t)); 101static int firewire_detach __P((device_t)); 102#if 0 103static int firewire_shutdown __P((device_t)); 104#endif 105static device_t firewire_add_child __P((device_t, int, const char *, int)); 106static struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int32_t, u_int32_t)); 107static void fw_try_bmr __P((void *)); 108static void fw_try_bmr_callback __P((struct fw_xfer *)); 109static u_int16_t fw_noderesolve __P((struct firewire_comm *, struct fw_eui64)); 110static void fw_asystart __P((struct fw_xfer *)); 111static int fw_get_tlabel __P((struct firewire_comm *, struct fw_xfer *)); 112static void fw_bus_probe __P((struct firewire_comm *)); 113static void fw_bus_explore __P((struct firewire_comm *)); 114static void fw_bus_explore_callback __P((struct fw_xfer *)); 115static void fw_attach_dev __P((struct firewire_comm *)); 116#ifdef FW_VMACCESS 117static void fw_vmaccess __P((struct fw_xfer *)); 118#endif 119struct fw_xfer *asyreqq __P((struct firewire_comm *, u_int8_t, u_int8_t, u_int8_t, 120 u_int32_t, u_int32_t, void (*)__P((struct fw_xfer *)))); 121 122static device_method_t firewire_methods[] = { 123 /* Device interface */ 124 DEVMETHOD(device_probe, firewire_match), 125 DEVMETHOD(device_attach, firewire_attach), 126 DEVMETHOD(device_detach, firewire_detach), 127 DEVMETHOD(device_shutdown, bus_generic_shutdown), 128 129 /* Bus interface */ 130 DEVMETHOD(bus_add_child, firewire_add_child), 131 DEVMETHOD(bus_print_child, bus_generic_print_child), 132 133 { 0, 0 } 134}; 135char linkspeed[7][0x10]={"S100","S200","S400","S800","S1600","S3200","Unknown"}; 136u_int maxrec[6]={512,1024,2048,4096,8192,0}; 137 138#define MAX_GAPHOP 16 139u_int gap_cnt[] = {1, 1, 4, 6, 9, 12, 14, 17, 140 20, 23, 25, 28, 31, 33, 36, 39, 42}; 141/* 142 * The probe routine. 143 */ 144struct cdevsw firewire_cdevsw = 145{ 146 fw_open, fw_close, fw_read, fw_write, fw_ioctl, 147 fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM 148}; 149static driver_t firewire_driver = { 150 "firewire", 151 firewire_methods, 152 sizeof(struct firewire_softc), 153}; 154 155static int 156fw_open (dev_t dev, int flags, int fmt, fw_proc *td) 157{ 158 struct firewire_softc *sc; 159 int unit = DEV2UNIT(dev); 160 int sub = DEV2DMACH(dev); 161 162 int err = 0; 163 164 if (DEV_FWMEM(dev)) 165 return fwmem_open(dev, flags, fmt, td); 166 167 sc = devclass_get_softc(firewire_devclass, unit); 168 if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){ 169 err = EBUSY; 170 return err; 171 } 172 if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){ 173 err = EBUSY; 174 return err; 175 } 176 if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){ 177 err = EBUSY; 178 return err; 179 } 180/* Default is per packet mode */ 181 sc->fc->ir[sub]->flag |= FWXFERQ_OPEN; 182 sc->fc->it[sub]->flag |= FWXFERQ_OPEN; 183 sc->fc->ir[sub]->flag |= FWXFERQ_PACKET; 184 return err; 185} 186static int 187fw_close (dev_t dev, int flags, int fmt, fw_proc *td) 188{ 189 struct firewire_softc *sc; 190 int unit = DEV2UNIT(dev); 191 int sub = DEV2DMACH(dev); 192 struct fw_xfer *xfer; 193 struct fw_dvbuf *dvbuf; 194 struct fw_bind *fwb; 195 int err = 0; 196 197 if (DEV_FWMEM(dev)) 198 return fwmem_close(dev, flags, fmt, td); 199 200 sc = devclass_get_softc(firewire_devclass, unit); 201 if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){ 202 err = EINVAL; 203 return err; 204 } 205 sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN; 206 if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){ 207 err = EINVAL; 208 return err; 209 } 210 sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN; 211 212 if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){ 213 sc->fc->irx_disable(sc->fc, sub); 214 } 215 if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){ 216 sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING; 217 sc->fc->itx_disable(sc->fc, sub); 218 } 219 if(sc->fc->it[sub]->flag & FWXFERQ_DV){ 220 if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){ 221 free(dvbuf->buf, M_DEVBUF); 222 sc->fc->it[sub]->dvproc = NULL; 223 } 224 if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){ 225 free(dvbuf->buf, M_DEVBUF); 226 sc->fc->it[sub]->dvdma = NULL; 227 } 228 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){ 229 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link); 230 free(dvbuf->buf, M_DEVBUF); 231 } 232 while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){ 233 STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link); 234 free(dvbuf->buf, M_DEVBUF); 235 } 236 free(sc->fc->it[sub]->dvbuf, M_DEVBUF); 237 sc->fc->it[sub]->dvbuf = NULL; 238 } 239 if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){ 240 free(sc->fc->ir[sub]->buf, M_DEVBUF); 241 sc->fc->ir[sub]->buf = NULL; 242 free(sc->fc->ir[sub]->bulkxfer, M_DEVBUF); 243 sc->fc->ir[sub]->bulkxfer = NULL; 244 sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF; 245 sc->fc->ir[sub]->psize = FWPMAX_S400; 246 sc->fc->ir[sub]->maxq = FWMAXQUEUE; 247 } 248 if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){ 249 free(sc->fc->it[sub]->buf, M_DEVBUF); 250 sc->fc->it[sub]->buf = NULL; 251 free(sc->fc->it[sub]->bulkxfer, M_DEVBUF); 252 sc->fc->it[sub]->bulkxfer = NULL; 253 sc->fc->it[sub]->dvbuf = NULL; 254 sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF; 255 sc->fc->it[sub]->psize = FWPMAX_S400; 256 sc->fc->it[sub]->maxq = FWMAXQUEUE; 257 } 258 for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q); 259 xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){ 260 sc->fc->ir[sub]->queued--; 261 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link); 262 263 xfer->resp = 0; 264 switch(xfer->act_type){ 265 case FWACT_XFER: 266 fw_xfer_done(xfer); 267 break; 268 default: 269 break; 270 } 271 fw_xfer_free(xfer); 272 } 273 for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL; 274 fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){ 275 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 276 STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist); 277 free(fwb, M_DEVBUF); 278 } 279 sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK; 280 sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK; 281 return err; 282} 283/* 284 * read request. 285 */ 286static int 287fw_read (dev_t dev, struct uio *uio, int ioflag) 288{ 289 struct firewire_softc *sc; 290 struct fw_xferq *ir; 291 struct fw_xfer *xfer; 292 int err = 0, s, slept = 0; 293 int unit = DEV2UNIT(dev); 294 int sub = DEV2DMACH(dev); 295 struct fw_pkt *fp; 296 297 if (DEV_FWMEM(dev)) 298 return fwmem_read(dev, uio, ioflag); 299 300 sc = devclass_get_softc(firewire_devclass, unit); 301 302 ir = sc->fc->ir[sub]; 303 304 if(ir->flag & FWXFERQ_PACKET){ 305 ir->stproc = NULL; 306 } 307readloop: 308 xfer = STAILQ_FIRST(&ir->q); 309 if(!(ir->flag & FWXFERQ_PACKET) && ir->stproc == NULL){ 310 ir->stproc = STAILQ_FIRST(&ir->stvalid); 311 if(ir->stproc != NULL){ 312 s = splfw(); 313 STAILQ_REMOVE_HEAD(&ir->stvalid, link); 314 splx(s); 315 ir->queued = 0; 316 } 317 } 318 319 if(xfer == NULL && ir->stproc == NULL){ 320 if(slept == 0){ 321 slept = 1; 322 if(!(ir->flag & FWXFERQ_RUNNING) 323 && (ir->flag & FWXFERQ_PACKET)){ 324 err = sc->fc->irx_enable(sc->fc, sub); 325 } 326 if(err){ 327 return err; 328 } 329 ir->flag |= FWXFERQ_WAKEUP; 330 err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz); 331 if(err){ 332 ir->flag &= ~FWXFERQ_WAKEUP; 333 return err; 334 } 335 goto readloop; 336 }else{ 337 err = EIO; 338 return err; 339 } 340 }else if(xfer != NULL){ 341 s = splfw(); 342 ir->queued --; 343 STAILQ_REMOVE_HEAD(&ir->q, link); 344 splx(s); 345 fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off); 346 if(sc->fc->irx_post != NULL) 347 sc->fc->irx_post(sc->fc, fp->mode.ld); 348 err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio); 349 fw_xfer_free( xfer); 350 }else if(ir->stproc != NULL){ 351 fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize); 352 if(sc->fc->irx_post != NULL) 353 sc->fc->irx_post(sc->fc, fp->mode.ld); 354 if(ntohs(fp->mode.stream.len) == 0){ 355 err = EIO; 356 return err; 357 } 358 err = uiomove((caddr_t)fp, ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio); 359 fp->mode.stream.len = 0; 360 ir->queued ++; 361 if(ir->queued >= ir->bnpacket){ 362 s = splfw(); 363 ir->stproc->flag = 0; 364 STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); 365 splx(s); 366 ir->stproc = NULL; 367 } 368 } 369#if 0 370 if(STAILQ_FIRST(&ir->q) == NULL && 371 (ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){ 372 err = sc->fc->irx_enable(sc->fc, sub); 373 } 374#endif 375#if 0 376 if(STAILQ_FIRST(&ir->stvalid) == NULL && 377 (ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){ 378 err = sc->fc->irx_enable(sc->fc, sub); 379 } 380#endif 381 return err; 382} 383static int 384fw_write (dev_t dev, struct uio *uio, int ioflag) 385{ 386 int err = 0; 387 struct firewire_softc *sc; 388 int unit = DEV2UNIT(dev); 389 int sub = DEV2DMACH(dev); 390 int tl, s, slept = 0; 391 struct fw_pkt *fp; 392 struct fw_xfer *xfer; 393 struct fw_xferq *xferq; 394 struct firewire_comm *fc; 395 struct fw_xferq *it; 396 397 if (DEV_FWMEM(dev)) 398 return fwmem_write(dev, uio, ioflag); 399 400 sc = devclass_get_softc(firewire_devclass, unit); 401 fc = sc->fc; 402 it = sc->fc->it[sub]; 403 404 fp = (struct fw_pkt *)uio->uio_iov->iov_base; 405 switch(fp->mode.common.tcode){ 406 case FWTCODE_RREQQ: 407 case FWTCODE_RREQB: 408 case FWTCODE_LREQ: 409 err = EINVAL; 410 return err; 411 case FWTCODE_WREQQ: 412 case FWTCODE_WREQB: 413 xferq = fc->atq; 414 break; 415 case FWTCODE_STREAM: 416 if(it->flag & FWXFERQ_PACKET){ 417 xferq = fc->atq; 418 }else{ 419 xferq = NULL; 420 } 421 break; 422 case FWTCODE_WRES: 423 case FWTCODE_RRESQ: 424 case FWTCODE_RRESB: 425 case FWTCODE_LRES: 426 xferq = fc->ats; 427 break; 428 default: 429 err = EINVAL; 430 return err; 431 } 432 /* Discard unsent buffered stream packet, when sending Asyrequrst */ 433 if(xferq != NULL && it->stproc != NULL){ 434 s = splfw(); 435 it->stproc->flag = 0; 436 STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link); 437 splx(s); 438 it->stproc = NULL; 439 } 440 if(xferq == NULL && !(it->flag & FWXFERQ_DV)){ 441isoloop: 442 if(it->stproc == NULL){ 443 it->stproc = STAILQ_FIRST(&it->stfree); 444 if(it->stproc != NULL){ 445 s = splfw(); 446 STAILQ_REMOVE_HEAD(&it->stfree, link); 447 splx(s); 448 it->queued = 0; 449 }else if(slept == 0){ 450 slept = 1; 451 err = sc->fc->itx_enable(sc->fc, sub); 452 if(err){ 453 return err; 454 } 455 err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 456 if(err){ 457 return err; 458 } 459 goto isoloop; 460 }else{ 461 err = EIO; 462 return err; 463 } 464 } 465 fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize); 466 fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 467 err = uiomove(it->stproc->buf + it->queued * it->psize, 468 uio->uio_resid, uio); 469 it->queued ++; 470 if(it->queued >= it->btpacket){ 471 s = splfw(); 472 STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 473 splx(s); 474 it->stproc = NULL; 475 fw_tbuf_update(sc->fc, sub, 0); 476 err = sc->fc->itx_enable(sc->fc, sub); 477 } 478 return err; 479 } if(xferq == NULL && it->flag & FWXFERQ_DV){ 480dvloop: 481 if(it->dvproc == NULL){ 482 it->dvproc = STAILQ_FIRST(&it->dvfree); 483 if(it->dvproc != NULL){ 484 s = splfw(); 485 STAILQ_REMOVE_HEAD(&it->dvfree, link); 486 splx(s); 487 it->dvptr = 0; 488 }else if(slept == 0){ 489 slept = 1; 490 err = sc->fc->itx_enable(sc->fc, sub); 491 if(err){ 492 return err; 493 } 494 err = tsleep((caddr_t)it, FWPRI, "fw_write", hz); 495 if(err){ 496 return err; 497 } 498 goto dvloop; 499 }else{ 500 err = EIO; 501 return err; 502 } 503 } 504 fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize); 505 fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t)); 506 err = uiomove(it->dvproc->buf + it->dvptr, 507 uio->uio_resid, uio); 508 it->dvptr += it->psize; 509 if(err){ 510 return err; 511 } 512 if(it->dvptr >= it->psize * it->dvpacket){ 513 s = splfw(); 514 STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link); 515 splx(s); 516 it->dvproc = NULL; 517 err = fw_tbuf_update(sc->fc, sub, 0); 518 if(err){ 519 return err; 520 } 521 err = sc->fc->itx_enable(sc->fc, sub); 522 } 523 return err; 524 } 525 if(xferq != NULL){ 526 xfer = fw_xfer_alloc(); 527 if(xfer == NULL){ 528 err = ENOMEM; 529 return err; 530 } 531 xfer->send.buf = malloc(uio->uio_resid, M_DEVBUF, M_NOWAIT); 532 if(xfer->send.buf == NULL){ 533 fw_xfer_free( xfer); 534 err = ENOBUFS; 535 return err; 536 } 537 xfer->dst = ntohs(fp->mode.hdr.dst); 538 539 switch(fp->mode.common.tcode){ 540 case FWTCODE_WREQQ: 541 case FWTCODE_WREQB: 542 if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 543 fw_xfer_free( xfer); 544 err = EAGAIN; 545 return err; 546 } 547 fp->mode.hdr.tlrt = tl << 2; 548 default: 549 break; 550 } 551 552 xfer->tl = fp->mode.hdr.tlrt >> 2; 553 xfer->send.len = uio->uio_resid; 554 xfer->send.off = 0; 555 xfer->tcode = fp->mode.common.tcode; 556 xfer->spd = 0;/* XXX: how to setup it */ 557 xfer->fc = fc; 558 xfer->q = xferq; 559 xfer->act_type = FWACT_XFER; 560 xfer->act.hand = fw_asy_callback; 561 xfer->retry_req = fw_asybusy; 562 563 err = uiomove(xfer->send.buf, uio->uio_resid, uio); 564 if(err){ 565 return err; 566 } 567 fw_asystart(xfer); 568 err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz); 569 if(xfer->resp == EBUSY) 570 return EBUSY; 571 fw_xfer_free( xfer); 572 return err; 573 } 574 return EINVAL; 575} 576/* 577 * transmitter buffer update. 578 */ 579int 580fw_tbuf_update(struct firewire_comm *fc, int sub, int flag){ 581 struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL; 582 struct fw_dvbuf *dvbuf = NULL; 583 struct fw_xferq *it; 584 int s, err = 0, i, j, chtag; 585 struct fw_pkt *fp; 586 u_int64_t tmpsync, dvsync; 587 588 it = fc->it[sub]; 589 590 s = splfw(); 591 if(it->stdma == NULL){ 592 bulkxfer = STAILQ_FIRST(&it->stvalid); 593 }else if(flag != 0){ 594 bulkxfer = STAILQ_FIRST(&it->stvalid); 595 if(bulkxfer == it->stdma){ 596 STAILQ_REMOVE_HEAD(&it->stvalid, link); 597 it->stdma->flag = 0; 598 STAILQ_INSERT_TAIL(&it->stfree, it->stdma, link); 599 if(!(it->flag & FWXFERQ_DV)) 600 wakeup(it); 601 } 602 bulkxfer = STAILQ_FIRST(&it->stvalid); 603 }else{ 604 bulkxfer = it->stdma; 605 } 606 splx(s); 607 if(bulkxfer != NULL){ 608 s = splfw(); 609 bulkxfer2 = STAILQ_NEXT(bulkxfer, link); 610#if 0 611 if(it->flag & FWXFERQ_DV && bulkxfer2 == NULL){ 612 bulkxfer2 = STAILQ_FIRST(&it->stfree); 613 STAILQ_REMOVE_HEAD(&it->stfree, link); 614 splx(s); 615 bcopy(bulkxfer->buf, bulkxfer2->buf, 616 it->psize * it->btpacket); 617 s = splfw(); 618 STAILQ_INSERT_TAIL(&it->stvalid, bulkxfer2, link); 619 } 620#endif 621 splx(s); 622 } 623 it->stdma = bulkxfer; 624 it->stdma2 = bulkxfer2; 625 626 if(it->flag & FWXFERQ_DV){ 627 chtag = it->flag & 0xff; 628dvloop: 629 if(it->dvdma == NULL){ 630 dvbuf = STAILQ_FIRST(&it->dvvalid); 631 if(dvbuf != NULL){ 632 s = splfw(); 633 STAILQ_REMOVE_HEAD(&it->dvvalid, link); 634 it->dvdma = dvbuf; 635 splx(s); 636 it->queued = 0; 637 } 638 } 639 if(it->dvdma == NULL) 640 return err; 641 642 it->stproc = STAILQ_FIRST(&it->stfree); 643 if(it->stproc != NULL){ 644 s = splfw(); 645 STAILQ_REMOVE_HEAD(&it->stfree, link); 646 splx(s); 647 }else{ 648 return err; 649 } 650/* 651 * Insert least significant 12 bits timestamp value by computation. 652 * Highest significant 4 bits is insert at just before packet sending. 653 */ 654 fp = (struct fw_pkt *)(it->stproc->buf); 655/* XXX: Parameter relies on NTSC type DV video */ 656 tmpsync = (u_int64_t)3072 * 8000 * 100 / 2997; 657 tmpsync *= it->dvsync; 658 dvsync = tmpsync; 659 dvsync %= 0xc00; 660 fp->mode.ld[2] = htonl(0x80000000 | (dvsync % 0xc00)); 661 it->dvsync ++; 662 it->dvsync %= 2997; 663 664 for( i = 0, j = 0 ; i < it->dvpacket ; i++){ 665 bcopy(it->dvdma->buf + it->queued * it->psize, 666 it->stproc->buf + j * it->psize, it->psize); 667 fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize); 668 fp->mode.stream.len = htons(488); 669 fp->mode.stream.chtag = chtag; 670 fp->mode.stream.tcode = FWTCODE_STREAM; 671 fp->mode.ld[1] = htonl((fc->nodeid << 24) | 0x00780000 | it->dvdbc); 672 it->dvdbc++; 673 it->dvdbc %= 256; 674 it->queued ++; 675 j++; 676/* XXX: Parameter relies on NTSC type DV video */ 677#if 1 678#define DVDIFF 203 679#define DVFRAC 2997 680#else 681#define DVDIFF 127 682#define DVFRAC 1875 683#endif 684 it->dvdiff += DVDIFF; 685 if(it->dvdiff >= DVFRAC){ 686 it->dvdiff %= DVFRAC; 687 fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize); 688 689 fp->mode.stream.len = htons(0x8); 690 fp->mode.stream.chtag = chtag; 691 fp->mode.stream.tcode = FWTCODE_STREAM; 692 fp->mode.ld[1] = htonl((fc->nodeid << 24) | 693 0x00780000 | it->dvdbc); 694 j++; 695 } 696 } 697 it->stproc->npacket = j; 698 s = splfw(); 699 STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); 700 splx(s); 701 if(it->queued >= it->dvpacket){ 702 s = splfw(); 703 STAILQ_INSERT_TAIL(&it->dvfree, it->dvdma, link); 704 it->dvdma = NULL; 705 splx(s); 706 wakeup(it); 707 goto dvloop; 708 } 709 } 710 return err; 711} 712/* 713 * receving buffer update. 714 */ 715int 716fw_rbuf_update(struct firewire_comm *fc, int sub, int flag){ 717 struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL; 718 struct fw_xferq *ir; 719 int s, err = 0; 720 721 ir = fc->ir[sub]; 722 s = splfw(); 723 if(ir->stdma != NULL){ 724 if(flag != 0){ 725 STAILQ_INSERT_TAIL(&ir->stvalid, ir->stdma, link); 726 }else{ 727 ir->stdma->flag = 0; 728 STAILQ_INSERT_TAIL(&ir->stfree, ir->stdma, link); 729 } 730 } 731 if(ir->stdma2 != NULL){ 732 bulkxfer = ir->stdma2; 733 bulkxfer2 = STAILQ_FIRST(&ir->stfree); 734 if(bulkxfer2 != NULL){ 735 STAILQ_REMOVE_HEAD(&ir->stfree, link); 736 } 737 }else{ 738 bulkxfer = STAILQ_FIRST(&ir->stfree); 739 if(bulkxfer != NULL){ 740 STAILQ_REMOVE_HEAD(&ir->stfree, link); 741 bulkxfer2 = STAILQ_FIRST(&ir->stfree); 742 if(bulkxfer2 != NULL){ 743 STAILQ_REMOVE_HEAD(&ir->stfree, link); 744 } 745 }else{ 746 bulkxfer = STAILQ_FIRST(&ir->stvalid); 747 STAILQ_REMOVE_HEAD(&ir->stvalid, link); 748 } 749 } 750 splx(s); 751 ir->stdma = bulkxfer; 752 ir->stdma2 = bulkxfer2; 753 return err; 754} 755/* 756 * ioctl support. 757 */ 758int 759fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 760{ 761 struct firewire_softc *sc; 762 int unit = DEV2UNIT(dev); 763 int sub = DEV2DMACH(dev); 764 int i, len, err = 0; 765 struct fw_device *fwdev; 766 struct fw_bind *fwb; 767 struct fw_xferq *ir, *it; 768 struct fw_xfer *xfer; 769 struct fw_pkt *fp; 770 771 struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; 772 struct fw_asyreq *asyreq = (struct fw_asyreq *)data; 773 struct fw_isochreq *ichreq = (struct fw_isochreq *)data; 774 struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; 775 struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; 776#if 0 777 struct fw_map_buf *map_buf = (struct fw_map_buf *)data; 778#endif 779 struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; 780 781 if (DEV_FWMEM(dev)) 782 return fwmem_ioctl(dev, cmd, data, flag, td); 783 784 sc = devclass_get_softc(firewire_devclass, unit); 785 if (!data) 786 return(EINVAL); 787 788 switch (cmd) { 789 case FW_STSTREAM: 790 sc->fc->it[sub]->flag &= ~0xff; 791 sc->fc->it[sub]->flag |= (0x3f & ichreq->ch); 792 sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6); 793 err = 0; 794 break; 795 case FW_GTSTREAM: 796 ichreq->ch = sc->fc->it[sub]->flag & 0x3f; 797 ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3; 798 err = 0; 799 break; 800 case FW_SRSTREAM: 801 sc->fc->ir[sub]->flag &= ~0xff; 802 sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch); 803 sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6); 804 err = sc->fc->irx_enable(sc->fc, sub); 805 break; 806 case FW_GRSTREAM: 807 ichreq->ch = sc->fc->ir[sub]->flag & 0x3f; 808 ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3; 809 err = 0; 810 break; 811 case FW_SSTDV: 812 ibufreq = (struct fw_isobufreq *) 813 malloc(sizeof(struct fw_isobufreq), M_DEVBUF, M_NOWAIT); 814 if(ibufreq == NULL){ 815 err = ENOMEM; 816 break; 817 } 818#define FWDVPACKET 250 819#define FWDVPMAX 512 820 ibufreq->rx.nchunk = 8; 821 ibufreq->rx.npacket = 50; 822 ibufreq->rx.psize = FWDVPMAX; 823 824 ibufreq->tx.nchunk = 5; 825 ibufreq->tx.npacket = 300; 826 ibufreq->tx.psize = FWDVPMAX; 827 828 err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td); 829 sc->fc->it[sub]->dvpacket = FWDVPACKET; 830 free(ibufreq, M_DEVBUF); 831/* reserve a buffer space */ 832#define NDVCHUNK 8 833 sc->fc->it[sub]->dvproc = NULL; 834 sc->fc->it[sub]->dvdma = NULL; 835 sc->fc->it[sub]->flag |= FWXFERQ_DV; 836 sc->fc->it[sub]->dvbuf 837 = (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_DEVBUF, M_DONTWAIT); 838 STAILQ_INIT(&sc->fc->it[sub]->dvvalid); 839 STAILQ_INIT(&sc->fc->it[sub]->dvfree); 840 for( i = 0 ; i < NDVCHUNK ; i++){ 841 sc->fc->it[sub]->dvbuf[i].buf 842 = malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_DEVBUF, M_DONTWAIT); 843 STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree, 844 &sc->fc->it[sub]->dvbuf[i], link); 845 } 846 break; 847 case FW_SSTBUF: 848 ir = sc->fc->ir[sub]; 849 it = sc->fc->it[sub]; 850 851 if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){ 852 return(EBUSY); 853 } 854 if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){ 855 return(EBUSY); 856 } 857 if((ibufreq->rx.nchunk * 858 ibufreq->rx.psize * ibufreq->rx.npacket) + 859 (ibufreq->tx.nchunk * 860 ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){ 861 return(EINVAL); 862 } 863 if(ibufreq->rx.nchunk > FWSTMAXCHUNK || 864 ibufreq->tx.nchunk > FWSTMAXCHUNK){ 865 return(EINVAL); 866 } 867 ir->bulkxfer 868 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_DEVBUF, M_DONTWAIT); 869 if(ir->bulkxfer == NULL){ 870 return(ENOMEM); 871 } 872 it->bulkxfer 873 = (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_DEVBUF, M_DONTWAIT); 874 if(it->bulkxfer == NULL){ 875 return(ENOMEM); 876 } 877 ir->buf = malloc( 878 ibufreq->rx.nchunk * ibufreq->rx.npacket 879 * ((ibufreq->rx.psize + 3) &~3), 880 M_DEVBUF, M_DONTWAIT); 881 if(ir->buf == NULL){ 882 free(ir->bulkxfer, M_DEVBUF); 883 free(it->bulkxfer, M_DEVBUF); 884 ir->bulkxfer = NULL; 885 it->bulkxfer = NULL; 886 it->buf = NULL; 887 return(ENOMEM); 888 } 889 it->buf = malloc( 890 ibufreq->tx.nchunk * ibufreq->tx.npacket 891 * ((ibufreq->tx.psize + 3) &~3), 892 M_DEVBUF, M_DONTWAIT); 893 if(it->buf == NULL){ 894 free(ir->bulkxfer, M_DEVBUF); 895 free(it->bulkxfer, M_DEVBUF); 896 free(ir->buf, M_DEVBUF); 897 ir->bulkxfer = NULL; 898 it->bulkxfer = NULL; 899 it->buf = NULL; 900 return(ENOMEM); 901 } 902 903 ir->bnchunk = ibufreq->rx.nchunk; 904 ir->bnpacket = ibufreq->rx.npacket; 905 ir->btpacket = ibufreq->rx.npacket; 906 ir->psize = (ibufreq->rx.psize + 3) & ~3; 907 ir->queued = 0; 908 909 it->bnchunk = ibufreq->tx.nchunk; 910 it->bnpacket = ibufreq->tx.npacket; 911 it->btpacket = ibufreq->tx.npacket; 912 it->psize = (ibufreq->tx.psize + 3) & ~3; 913 ir->queued = 0; 914 it->dvdbc = 0; 915 it->dvdiff = 0; 916 it->dvsync = 0; 917 918 STAILQ_INIT(&ir->stvalid); 919 STAILQ_INIT(&ir->stfree); 920 ir->stdma = NULL; 921 ir->stdma2 = NULL; 922 ir->stproc = NULL; 923 924 STAILQ_INIT(&it->stvalid); 925 STAILQ_INIT(&it->stfree); 926 it->stdma = NULL; 927 it->stdma2 = NULL; 928 it->stproc = NULL; 929 930 for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){ 931 ir->bulkxfer[i].buf = 932 ir->buf + 933 i * sc->fc->ir[sub]->bnpacket * 934 sc->fc->ir[sub]->psize; 935 ir->bulkxfer[i].flag = 0; 936 STAILQ_INSERT_TAIL(&ir->stfree, 937 &ir->bulkxfer[i], link); 938 ir->bulkxfer[i].npacket = ir->bnpacket; 939 } 940 for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){ 941 it->bulkxfer[i].buf = 942 it->buf + 943 i * sc->fc->it[sub]->bnpacket * 944 sc->fc->it[sub]->psize; 945 it->bulkxfer[i].flag = 0; 946 STAILQ_INSERT_TAIL(&it->stfree, 947 &it->bulkxfer[i], link); 948 it->bulkxfer[i].npacket = it->bnpacket; 949 } 950 ir->flag &= ~FWXFERQ_MODEMASK; 951 ir->flag |= FWXFERQ_STREAM; 952 ir->flag |= FWXFERQ_EXTBUF; 953 954 it->flag &= ~FWXFERQ_MODEMASK; 955 it->flag |= FWXFERQ_STREAM; 956 it->flag |= FWXFERQ_EXTBUF; 957 err = 0; 958 break; 959 case FW_GSTBUF: 960 ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk; 961 ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket; 962 ibufreq->rx.psize = sc->fc->ir[sub]->psize; 963 964 ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk; 965 ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket; 966 ibufreq->tx.psize = sc->fc->it[sub]->psize; 967 break; 968 case FW_ASYREQ: 969 xfer = fw_xfer_alloc(); 970 if(xfer == NULL){ 971 err = ENOMEM; 972 return err; 973 } 974 fp = &asyreq->pkt; 975 switch (asyreq->req.type) { 976 case FWASREQNODE: 977 xfer->dst = ntohs(fp->mode.hdr.dst); 978 break; 979 case FWASREQEUI: 980 xfer->dst = fw_noderesolve(sc->fc, asyreq->req.dst.eui); 981 if(xfer->dst == FWNODE_INVAL ){ 982 printf("%s:cannot found node\n", 983 device_get_nameunit(sc->fc->dev)); 984 err = EINVAL; 985 goto error; 986 } 987 fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst); 988 break; 989 case FWASRESTL: 990 /* XXX what's this? */ 991 break; 992 case FWASREQSTREAM: 993 /* nothing to do */ 994 break; 995 } 996 xfer->spd = asyreq->req.sped; 997 xfer->send.len = asyreq->req.len; 998 xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 999 if(xfer->send.buf == NULL){ 1000 return ENOMEM; 1001 } 1002 xfer->send.off = 0; 1003 bcopy(fp, xfer->send.buf, xfer->send.len); 1004 xfer->act.hand = fw_asy_callback; 1005 err = fw_asyreq(sc->fc, sub, xfer); 1006 if(err){ 1007 fw_xfer_free( xfer); 1008 return err; 1009 } 1010 err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz); 1011 if(err == 0){ 1012 if(asyreq->req.len >= xfer->recv.len){ 1013 asyreq->req.len = xfer->recv.len; 1014 }else{ 1015 err = EINVAL; 1016 } 1017 bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len); 1018 } 1019error: 1020 fw_xfer_free( xfer); 1021 break; 1022 case FW_IBUSRST: 1023 sc->fc->ibr(sc->fc); 1024 break; 1025 case FW_CBINDADDR: 1026 fwb = fw_bindlookup(sc->fc, 1027 bindreq->start.hi, bindreq->start.lo); 1028 if(fwb == NULL){ 1029 err = EINVAL; 1030 break; 1031 } 1032 STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist); 1033 STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist); 1034 free(fwb, M_DEVBUF); 1035 break; 1036 case FW_SBINDADDR: 1037 if(bindreq->len <= 0 ){ 1038 err = EINVAL; 1039 break; 1040 } 1041 if(bindreq->start.hi > 0xffff ){ 1042 err = EINVAL; 1043 break; 1044 } 1045 fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_DONTWAIT); 1046 if(fwb == NULL){ 1047 err = ENOMEM; 1048 break; 1049 } 1050 fwb->start_hi = bindreq->start.hi; 1051 fwb->start_lo = bindreq->start.lo; 1052 fwb->addrlen = bindreq->len; 1053 1054 xfer = fw_xfer_alloc(); 1055 if(xfer == NULL){ 1056 err = ENOMEM; 1057 return err; 1058 } 1059 xfer->act_type = FWACT_CH; 1060 xfer->sub = sub; 1061 xfer->fc = sc->fc; 1062 1063 fwb->xfer = xfer; 1064 err = fw_bindadd(sc->fc, fwb); 1065 break; 1066 case FW_GDEVLST: 1067 i = 0; 1068 for(fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 1069 fwdev = TAILQ_NEXT(fwdev, link)){ 1070 if(i < fwdevlst->n){ 1071 fwdevlst->dst[i] = fwdev->dst; 1072 fwdevlst->status[i] = 1073 (fwdev->status == FWDEVATTACHED)?1:0; 1074 fwdevlst->eui[i].hi = fwdev->eui.hi; 1075 fwdevlst->eui[i].lo = fwdev->eui.lo; 1076 } 1077 i++; 1078 } 1079 fwdevlst->n = i; 1080 break; 1081 case FW_GTPMAP: 1082 bcopy(sc->fc->topology_map, data, 1083 (sc->fc->topology_map->crc_len + 1) * 4); 1084 break; 1085 case FW_GSPMAP: 1086 /* speed_map is larger than a page */ 1087 err = copyout(sc->fc->speed_map, *(void **)data, 1088 (sc->fc->speed_map->crc_len + 1) * 4); 1089 break; 1090 case FW_GCROM: 1091 for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; 1092 fwdev = TAILQ_NEXT(fwdev, link)) { 1093 if (fwdev->eui.hi == crom_buf->eui.hi && 1094 fwdev->eui.lo == crom_buf->eui.lo) 1095 break; 1096 } 1097 if (fwdev == NULL) { 1098 err = FWNODE_INVAL; 1099 break; 1100 } 1101#if 0 1102 if (fwdev->csrrom[0] >> 24 == 1) 1103 len = 4; 1104 else 1105 len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4; 1106#else 1107 if (fwdev->rommax < CSRROMOFF) 1108 len = 0; 1109 else 1110 len = fwdev->rommax - CSRROMOFF + 4; 1111#endif 1112 if (crom_buf->len < len) 1113 len = crom_buf->len; 1114 else 1115 crom_buf->len = len; 1116 err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len); 1117 break; 1118 default: 1119 sc->fc->ioctl (dev, cmd, data, flag, td); 1120 break; 1121 } 1122 return err; 1123} 1124int 1125fw_poll(dev_t dev, int events, fw_proc *td) 1126{ 1127 int revents; 1128 int tmp; 1129 int unit = DEV2UNIT(dev); 1130 int sub = DEV2DMACH(dev); 1131 struct firewire_softc *sc; 1132 1133 if (DEV_FWMEM(dev)) 1134 return fwmem_poll(dev, events, td); 1135 1136 sc = devclass_get_softc(firewire_devclass, unit); 1137 revents = 0; 1138 tmp = POLLIN | POLLRDNORM; 1139 if (events & tmp) { 1140 if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL) 1141 revents |= tmp; 1142 else 1143 selrecord(td, &sc->fc->ir[sub]->rsel); 1144 } 1145 tmp = POLLOUT | POLLWRNORM; 1146 if (events & tmp) { 1147 /* XXX should be fixed */ 1148 revents |= tmp; 1149 } 1150 1151 return revents; 1152} 1153 1154/* 1155 * To lookup node id. from EUI64. 1156 */ 1157u_int16_t fw_noderesolve(struct firewire_comm *fc, struct fw_eui64 eui) 1158{ 1159 struct fw_device *fwdev; 1160 for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 1161 fwdev = TAILQ_NEXT(fwdev, link)){ 1162 if(fwdev->eui.hi == eui.hi && fwdev->eui.lo == eui.lo){ 1163 break; 1164 } 1165 } 1166 if(fwdev == NULL) return FWNODE_INVAL; 1167 if(fwdev->status != FWDEVATTACHED) return FWNODE_INVAL; 1168 return fwdev->dst; 1169} 1170/* 1171 * Async. request procedure for userland application. 1172 */ 1173int 1174fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) 1175{ 1176 int err = 0; 1177 struct fw_xferq *xferq; 1178 int tl = 0, len; 1179 struct fw_pkt *fp; 1180 int tcode; 1181 struct tcode_info *info; 1182 1183 if(xfer == NULL) return EINVAL; 1184 if(xfer->send.len > fc->maxrec){ 1185 printf("send.len > maxrec\n"); 1186 return EINVAL; 1187 } 1188 if(xfer->act.hand == NULL){ 1189 printf("act.hand == NULL\n"); 1190 return EINVAL; 1191 } 1192 fp = (struct fw_pkt *)xfer->send.buf; 1193 1194#if 0 1195 switch(fp->mode.common.tcode){ 1196 case FWTCODE_STREAM: 1197 len = ntohs(fp->mode.stream.len) + 4; 1198 break; 1199 case FWTCODE_RREQQ: 1200 case FWTCODE_WRES: 1201 case FWTCODE_PHY: 1202 len = 12; 1203 break; 1204 case FWTCODE_WREQQ: 1205 case FWTCODE_RRESQ: 1206 len = 16; 1207 break; 1208 default: 1209 len = ntohs(fp->mode.rresb.len) + 16; 1210 break; 1211 } 1212 if( len > xfer->send.len ){ 1213 printf("len > send.len\n"); 1214 return EINVAL; 1215 } 1216 switch(fp->mode.common.tcode){ 1217 case FWTCODE_WREQQ: 1218 case FWTCODE_WREQB: 1219 case FWTCODE_RREQQ: 1220 case FWTCODE_RREQB: 1221 case FWTCODE_LREQ: 1222 case FWTCODE_PHY: 1223 case FWTCODE_STREAM: 1224 xferq = fc->atq; 1225 break; 1226 case FWTCODE_WRES: 1227 case FWTCODE_RRESQ: 1228 case FWTCODE_RRESB: 1229 case FWTCODE_LRES: 1230 xferq = fc->ats; 1231 break; 1232 default: 1233 return EINVAL; 1234 } 1235#else 1236 tcode = fp->mode.common.tcode & 0xf; 1237 info = &fc->tcode[tcode]; 1238 if (info->flag == 0) { 1239 printf("invalid tcode=%d\n", tcode); 1240 return EINVAL; 1241 } 1242 if (info->flag & FWTI_REQ) 1243 xferq = fc->atq; 1244 else 1245 xferq = fc->ats; 1246 len = info->hdr_len; 1247 if (info->flag & FWTI_BLOCK_STR) 1248 len += ntohs(fp->mode.stream.len); 1249 else if (info->flag & FWTI_BLOCK_ASY) 1250 len += ntohs(fp->mode.rresb.len); 1251 if( len > xfer->send.len ){ 1252 printf("len(%d) > send.len(%d) (tcode=%d)\n", 1253 len, xfer->send.len, tcode); 1254 return EINVAL; 1255 } 1256 xfer->send.len = len; 1257#endif 1258 if(xferq->start == NULL){ 1259 printf("xferq->start == NULL\n"); 1260 return EINVAL; 1261 } 1262 if(!(xferq->queued < xferq->maxq)){ 1263 printf("%s:Discard a packet (queued=%d)\n", 1264 device_get_nameunit(fc->dev), xferq->queued); 1265 return EINVAL; 1266 } 1267 1268 1269#if 0 1270 switch(tcode){ 1271 case FWTCODE_WREQQ: 1272 case FWTCODE_WREQB: 1273 case FWTCODE_RREQQ: 1274 case FWTCODE_RREQB: 1275 case FWTCODE_LREQ: 1276 if((tl = fw_get_tlabel(fc, xfer)) == -1 ){ 1277 return EIO; 1278 } 1279 fp->mode.hdr.tlrt = tl << 2; 1280 break; 1281 default: 1282 break; 1283 } 1284#else 1285 if (info->flag & FWTI_TLABEL) { 1286 if((tl = fw_get_tlabel(fc, xfer)) == -1 ) 1287 return EIO; 1288 fp->mode.hdr.tlrt = tl << 2; 1289 } 1290#endif 1291 1292 xfer->tl = tl; 1293 xfer->tcode = tcode; 1294 xfer->resp = 0; 1295 xfer->fc = fc; 1296 xfer->q = xferq; 1297 xfer->act_type = FWACT_XFER; 1298 xfer->retry_req = fw_asybusy; 1299 1300 fw_asystart(xfer); 1301 return err; 1302} 1303/* 1304 * Wakeup blocked process. 1305 */ 1306void 1307fw_asy_callback(struct fw_xfer *xfer){ 1308 wakeup(xfer); 1309 return; 1310} 1311/* 1312 * Postpone to later retry. 1313 */ 1314void fw_asybusy(struct fw_xfer *xfer){ 1315#if 0 1316 printf("fw_asybusy\n"); 1317#endif 1318#if XFER_TIMEOUT 1319 untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch); 1320#endif 1321/* 1322 xfer->ch = timeout((timeout_t *)fw_asystart, (void *)xfer, 20000); 1323*/ 1324 DELAY(20000); 1325 fw_asystart(xfer); 1326 return; 1327} 1328#if XFER_TIMEOUT 1329/* 1330 * Post timeout for async. request. 1331 */ 1332void 1333fw_xfer_timeout(void *arg) 1334{ 1335 int s; 1336 struct fw_xfer *xfer; 1337 1338 xfer = (struct fw_xfer *)arg; 1339 printf("fw_xfer_timeout status=%d resp=%d\n", xfer->state, xfer->resp); 1340 /* XXX set error code */ 1341 s = splfw(); 1342 xfer->act.hand(xfer); 1343 splx(s); 1344} 1345#endif 1346/* 1347 * Async. request with given xfer structure. 1348 */ 1349static void fw_asystart(struct fw_xfer *xfer){ 1350 struct firewire_comm *fc = xfer->fc; 1351 int s; 1352 if(xfer->retry++ >= fc->max_asyretry){ 1353 xfer->resp = EBUSY; 1354 xfer->state = FWXF_BUSY; 1355 xfer->act.hand(xfer); 1356 return; 1357 } 1358#if 0 /* XXX allow bus explore packets only after bus rest */ 1359 if (fc->status < FWBUSEXPLORE) { 1360 xfer->resp = EAGAIN; 1361 xfer->state = FWXF_BUSY; 1362 if (xfer->act.hand != NULL) 1363 xfer->act.hand(xfer); 1364 return; 1365 } 1366#endif 1367 s = splfw(); 1368 xfer->state = FWXF_INQ; 1369 STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link); 1370 xfer->q->queued ++; 1371 splx(s); 1372 /* XXX just queue for mbuf */ 1373 if (xfer->mbuf == NULL) 1374 xfer->q->start(fc); 1375#if XFER_TIMEOUT 1376 if (xfer->act.hand != NULL) 1377 xfer->ch = timeout(fw_xfer_timeout, (void *)xfer, hz); 1378#endif 1379 return; 1380} 1381static int 1382fw_mmap (dev_t dev, vm_offset_t offset, int nproto) 1383{ 1384 struct firewire_softc *fc; 1385 int unit = DEV2UNIT(dev); 1386 1387 if (DEV_FWMEM(dev)) 1388 return fwmem_mmap(dev, offset, nproto); 1389 1390 fc = devclass_get_softc(firewire_devclass, unit); 1391 1392 return EINVAL; 1393} 1394static int 1395firewire_match( device_t dev ) 1396{ 1397 device_set_desc(dev, "IEEE1394(Firewire) bus"); 1398 return -140; 1399} 1400/* 1401 * The attach routine. 1402 */ 1403static int 1404firewire_attach( device_t dev ) 1405{ 1406 int i, unitmask, mn; 1407 struct firewire_softc *sc = device_get_softc(dev); 1408 device_t pa = device_get_parent(dev); 1409 struct firewire_comm *fc; 1410 dev_t d; 1411 1412 fc = (struct firewire_comm *)device_get_softc(pa); 1413 sc->fc = fc; 1414 sc->fc->dev = dev; 1415 1416 unitmask = UNIT2MIN(device_get_unit(dev)); 1417 1418 if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA; 1419 for ( i = 0 ; i < fc->nisodma ; i++ ){ 1420 mn = unitmask | i; 1421 /* XXX device name should be improved */ 1422 d = make_dev(&firewire_cdevsw, unit2minor(mn), 1423 UID_ROOT, GID_OPERATOR, 0770, 1424 "fw%x", mn); 1425#if __FreeBSD_version >= 500000 1426 if (i == 0) 1427 sc->dev = d; 1428 else 1429 dev_depends(sc->dev, d); 1430#else 1431 sc->dev[i] = d; 1432#endif 1433 } 1434 d = make_dev(&firewire_cdevsw, unit2minor(unitmask | FWMEM_FLAG), 1435 UID_ROOT, GID_OPERATOR, 0770, 1436 "fwmem%d", device_get_unit(dev)); 1437#if __FreeBSD_version >= 500000 1438 dev_depends(sc->dev, d); 1439#else 1440 sc->dev[i] = d; 1441#endif 1442 printf("%s: firewire bus attach\n", device_get_nameunit(sc->fc->dev)); 1443 sc->fc->timeouthandle = timeout((timeout_t *)sc->fc->timeout, (void *)sc->fc, hz * 10); 1444 1445 /* Locate our children */ 1446 bus_generic_probe(dev); 1447 1448 /* launch attachement of the added children */ 1449 bus_generic_attach(dev); 1450 1451 /* bus_reset */ 1452 fc->ibr(fc); 1453 1454 return 0; 1455} 1456 1457/* 1458 * Attach it as child. 1459 */ 1460static device_t 1461firewire_add_child(device_t dev, int order, const char *name, int unit) 1462{ 1463 device_t child; 1464 struct firewire_softc *sc; 1465 1466 sc = (struct firewire_softc *)device_get_softc(dev); 1467 child = device_add_child(dev, name, unit); 1468 if (child) { 1469 device_set_ivars(child, sc->fc); 1470 device_probe_and_attach(child); 1471 } 1472 1473 return child; 1474} 1475/* 1476 * Dettach it. 1477 */ 1478static int 1479firewire_detach( device_t dev ) 1480{ 1481 struct firewire_softc *sc; 1482 1483 sc = (struct firewire_softc *)device_get_softc(dev); 1484#if 0 1485 printf("%s:dettach prevented", device_get_nameunit(dev)); 1486 return(EINVAL); 1487#endif 1488#if __FreeBSD_version >= 500000 1489 destroy_dev(sc->dev); 1490#else 1491 { 1492 int j; 1493 for (j = 0 ; j < sc->fc->nisodma + 1; j++) 1494 destroy_dev(sc->dev[j]); 1495 } 1496#endif 1497 /* XXX xfree_free and untimeout on all xfers */ 1498 untimeout((timeout_t *)sc->fc->timeout, sc->fc, sc->fc->timeouthandle); 1499 free(sc->fc->topology_map, M_DEVBUF); 1500 free(sc->fc->speed_map, M_DEVBUF); 1501 bus_generic_detach(dev); 1502 return(0); 1503} 1504#if 0 1505static int 1506firewire_shutdown( device_t dev ) 1507{ 1508 return 0; 1509} 1510#endif 1511/* 1512 * Call ater bus reset. 1513 */ 1514void fw_busreset(struct firewire_comm *fc) 1515{ 1516 int i; 1517 struct fw_xfer *xfer; 1518 1519 switch(fc->status){ 1520 case FWBUSMGRELECT: 1521 untimeout((timeout_t *)fw_try_bmr, (void *)fc, fc->bmrhandle); 1522 break; 1523 default: 1524 break; 1525 } 1526 fc->status = FWBUSRESET; 1527/* XXX: discard all queued packet */ 1528 while((xfer = STAILQ_FIRST(&fc->atq->q)) != NULL){ 1529 STAILQ_REMOVE_HEAD(&fc->atq->q, link); 1530 xfer->resp = EAGAIN; 1531 switch(xfer->act_type){ 1532 case FWACT_XFER: 1533 fw_xfer_done(xfer); 1534 break; 1535 default: 1536 break; 1537 } 1538 fw_xfer_free( xfer); 1539 } 1540 while((xfer = STAILQ_FIRST(&fc->ats->q)) != NULL){ 1541 STAILQ_REMOVE_HEAD(&fc->ats->q, link); 1542 xfer->resp = EAGAIN; 1543 switch(xfer->act_type){ 1544 case FWACT_XFER: 1545 fw_xfer_done(xfer); 1546 default: 1547 break; 1548 } 1549 fw_xfer_free( xfer); 1550 } 1551 for(i = 0; i < fc->nisodma; i++) 1552 while((xfer = STAILQ_FIRST(&fc->it[i]->q)) != NULL){ 1553 STAILQ_REMOVE_HEAD(&fc->it[i]->q, link); 1554 xfer->resp = 0; 1555 switch(xfer->act_type){ 1556 case FWACT_XFER: 1557 fw_xfer_done(xfer); 1558 break; 1559 default: 1560 break; 1561 } 1562 fw_xfer_free( xfer); 1563 } 1564 1565 CSRARC(fc, STATE_CLEAR) 1566 = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; 1567 CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1568 CSRARC(fc, NODE_IDS) = 0x3f; 1569 1570 CSRARC(fc, TOPO_MAP + 8) = 0; 1571 fc->irm = -1; 1572 1573 fc->max_node = -1; 1574 1575 for(i = 2; i < 0x100/4 - 2 ; i++){ 1576 CSRARC(fc, SPED_MAP + i * 4) = 0; 1577 } 1578 CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; 1579 CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1580 CSRARC(fc, RESET_START) = 0; 1581 CSRARC(fc, SPLIT_TIMEOUT_HI) = 0; 1582 CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19; 1583 CSRARC(fc, CYCLE_TIME) = 0x0; 1584 CSRARC(fc, BUS_TIME) = 0x0; 1585 CSRARC(fc, BUS_MGR_ID) = 0x3f; 1586 CSRARC(fc, BANDWIDTH_AV) = 4915; 1587 CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff; 1588 CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff; 1589 CSRARC(fc, IP_CHANNELS) = (1 << 31); 1590 1591 CSRARC(fc, CONF_ROM) = 0x04 << 24; 1592 CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */ 1593 CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 | 1594 1 << 28 | 0xff << 16 | 0x09 << 8; 1595 CSRARC(fc, CONF_ROM + 0xc) = 0; 1596 1597/* DV depend CSRs see blue book */ 1598 CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON; 1599 CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON; 1600 1601 CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 ); 1602 CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); 1603} 1604/* Call once after reboot */ 1605void fw_init(fc) 1606 struct firewire_comm *fc; 1607{ 1608 int i; 1609 struct csrdir *csrd; 1610#ifdef FW_VMACCESS 1611 struct fw_xfer *xfer; 1612 struct fw_bind *fwb; 1613#endif 1614 1615 fc->max_asyretry = FW_MAXASYRTY; 1616 1617 fc->arq->queued = 0; 1618 fc->ars->queued = 0; 1619 fc->atq->queued = 0; 1620 fc->ats->queued = 0; 1621 1622 fc->arq->psize = FWPMAX_S400; 1623 fc->ars->psize = FWPMAX_S400; 1624 fc->atq->psize = FWPMAX_S400; 1625 fc->ats->psize = FWPMAX_S400; 1626 1627 1628 fc->arq->buf = NULL; 1629 fc->ars->buf = NULL; 1630 fc->atq->buf = NULL; 1631 fc->ats->buf = NULL; 1632 1633 fc->arq->flag = FWXFERQ_PACKET; 1634 fc->ars->flag = FWXFERQ_PACKET; 1635 fc->atq->flag = FWXFERQ_PACKET; 1636 fc->ats->flag = FWXFERQ_PACKET; 1637 1638 STAILQ_INIT(&fc->atq->q); 1639 STAILQ_INIT(&fc->ats->q); 1640 1641 for( i = 0 ; i < fc->nisodma ; i ++ ){ 1642 fc->it[i]->queued = 0; 1643 fc->ir[i]->queued = 0; 1644 1645 fc->it[i]->start = NULL; 1646 fc->ir[i]->start = NULL; 1647 1648 fc->it[i]->buf = NULL; 1649 fc->ir[i]->buf = NULL; 1650 1651 fc->it[i]->flag = FWXFERQ_STREAM; 1652 fc->ir[i]->flag = FWXFERQ_STREAM; 1653 1654 STAILQ_INIT(&fc->it[i]->q); 1655 STAILQ_INIT(&fc->ir[i]->q); 1656 1657 STAILQ_INIT(&fc->it[i]->binds); 1658 STAILQ_INIT(&fc->ir[i]->binds); 1659 } 1660 1661 fc->arq->maxq = FWMAXQUEUE; 1662 fc->ars->maxq = FWMAXQUEUE; 1663 fc->atq->maxq = FWMAXQUEUE; 1664 fc->ats->maxq = FWMAXQUEUE; 1665 1666 for( i = 0 ; i < fc->nisodma ; i++){ 1667 fc->ir[i]->maxq = FWMAXQUEUE; 1668 fc->it[i]->maxq = FWMAXQUEUE; 1669 } 1670/* Initialize csr registers */ 1671 fc->topology_map = (struct fw_topology_map *)malloc( 1672 sizeof(struct fw_topology_map), 1673 M_DEVBUF, M_DONTWAIT | M_ZERO); 1674 fc->speed_map = (struct fw_speed_map *)malloc( 1675 sizeof(struct fw_speed_map), 1676 M_DEVBUF, M_DONTWAIT | M_ZERO); 1677 CSRARC(fc, TOPO_MAP) = 0x3f1 << 16; 1678 CSRARC(fc, TOPO_MAP + 4) = 1; 1679 CSRARC(fc, SPED_MAP) = 0x3f1 << 16; 1680 CSRARC(fc, SPED_MAP + 4) = 1; 1681 1682 TAILQ_INIT(&fc->devices); 1683 STAILQ_INIT(&fc->pending); 1684 1685/* Initialize csr ROM work space */ 1686 SLIST_INIT(&fc->ongocsr); 1687 SLIST_INIT(&fc->csrfree); 1688 for( i = 0 ; i < FWMAXCSRDIR ; i++){ 1689 csrd = (struct csrdir *) malloc(sizeof(struct csrdir), M_DEVBUF,M_DONTWAIT); 1690 if(csrd == NULL) break; 1691 SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 1692 } 1693 1694/* Initialize Async handlers */ 1695 STAILQ_INIT(&fc->binds); 1696 for( i = 0 ; i < 0x40 ; i++){ 1697 STAILQ_INIT(&fc->tlabels[i]); 1698 } 1699 1700/* DV depend CSRs see blue book */ 1701#if 0 1702 CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */ 1703 CSRARC(fc, oPCR) = 0x8000007a; 1704 for(i = 4 ; i < 0x7c/4 ; i+=4){ 1705 CSRARC(fc, i + oPCR) = 0x8000007a; 1706 } 1707 1708 CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */ 1709 CSRARC(fc, iPCR) = 0x803f0000; 1710 for(i = 4 ; i < 0x7c/4 ; i+=4){ 1711 CSRARC(fc, i + iPCR) = 0x0; 1712 } 1713#endif 1714 1715 1716#ifdef FW_VMACCESS 1717 xfer = fw_xfer_alloc(); 1718 if(xfer == NULL) return; 1719 1720 fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_DONTWAIT); 1721 if(fwb == NULL){ 1722 fw_xfer_free(xfer); 1723 } 1724 xfer->act.hand = fw_vmaccess; 1725 xfer->act_type = FWACT_XFER; 1726 xfer->fc = fc; 1727 xfer->sc = NULL; 1728 1729 fwb->start_hi = 0x2; 1730 fwb->start_lo = 0; 1731 fwb->addrlen = 0xffffffff; 1732 fwb->xfer = xfer; 1733 fw_bindadd(fc, fwb); 1734#endif 1735} 1736/* 1737 * To lookup binded process from IEEE1394 address. 1738 */ 1739static struct fw_bind * 1740fw_bindlookup(fc, dest_hi, dest_lo) 1741struct firewire_comm *fc; 1742u_int32_t dest_lo, dest_hi; 1743{ 1744 struct fw_bind *tfw; 1745 for(tfw = STAILQ_FIRST(&fc->binds) ; tfw != NULL ; 1746 tfw = STAILQ_NEXT(tfw, fclist)){ 1747 if(tfw->xfer->act_type != FWACT_NULL && 1748 tfw->start_hi == dest_hi && 1749 tfw->start_lo <= dest_lo && 1750 (tfw->start_lo + tfw->addrlen) > dest_lo){ 1751 return(tfw); 1752 } 1753 } 1754 return(NULL); 1755} 1756/* 1757 * To bind IEEE1394 address block to process. 1758 */ 1759int fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) 1760{ 1761 struct fw_bind *tfw, *tfw2 = NULL; 1762 int err = 0; 1763 tfw = STAILQ_FIRST(&fc->binds); 1764 if(tfw == NULL){ 1765 STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist); 1766 goto out; 1767 } 1768 if((tfw->start_hi > fwb->start_hi) || 1769 (tfw->start_hi == fwb->start_hi && 1770 (tfw->start_lo > (fwb->start_lo + fwb->addrlen)))){ 1771 STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist); 1772 goto out; 1773 } 1774 for(; tfw != NULL; tfw = STAILQ_NEXT(tfw, fclist)){ 1775 if((tfw->start_hi < fwb->start_hi) || 1776 (tfw->start_hi == fwb->start_hi && 1777 (tfw->start_lo + tfw->addrlen) < fwb->start_lo)){ 1778 tfw2 = STAILQ_NEXT(tfw, fclist); 1779 if(tfw2 == NULL) 1780 break; 1781 if((tfw2->start_hi > fwb->start_hi) || 1782 (tfw2->start_hi == fwb->start_hi && 1783 tfw2->start_lo > (fwb->start_lo + fwb->addrlen))){ 1784 break; 1785 }else{ 1786 err = EBUSY; 1787 goto out; 1788 } 1789 } 1790 } 1791 if(tfw != NULL){ 1792 STAILQ_INSERT_AFTER(&fc->binds, tfw, fwb, fclist); 1793 }else{ 1794 STAILQ_INSERT_TAIL(&fc->binds, fwb, fclist); 1795 } 1796out: 1797 if(!err && fwb->xfer->act_type == FWACT_CH){ 1798 STAILQ_INSERT_HEAD(&fc->ir[fwb->xfer->sub]->binds, fwb, chlist); 1799 } 1800 return err; 1801} 1802 1803/* 1804 * To free IEEE1394 address block. 1805 */ 1806int fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) 1807{ 1808 int s; 1809 1810 s = splfw(); 1811 /* shall we check the existance? */ 1812 STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); 1813 splx(s); 1814 if (fwb->xfer) 1815 fw_xfer_free(fwb->xfer); 1816 1817 return 0; 1818} 1819 1820/* 1821 * To free transaction label. 1822 */ 1823static void fw_tl_free ( struct firewire_comm *fc, struct fw_xfer *xfer ) 1824{ 1825 struct tlabel *tl; 1826 int s = splfw(); 1827 1828 for( tl = STAILQ_FIRST(&fc->tlabels[xfer->tl]); tl != NULL; 1829 tl = STAILQ_NEXT(tl, link)){ 1830 if(tl->xfer == xfer){ 1831 STAILQ_REMOVE(&fc->tlabels[xfer->tl], tl, tlabel, link); 1832 free(tl, M_DEVBUF); 1833 splx(s); 1834 return; 1835 } 1836 } 1837 splx(s); 1838 return; 1839} 1840/* 1841 * To obtain XFER structure by transaction label. 1842 */ 1843static struct fw_xfer *fw_tl2xfer ( struct firewire_comm *fc, int node, int tlabel ) 1844{ 1845 struct fw_xfer *xfer; 1846 struct tlabel *tl; 1847 int s = splfw(); 1848 1849 for( tl = STAILQ_FIRST(&fc->tlabels[tlabel]); tl != NULL; 1850 tl = STAILQ_NEXT(tl, link)){ 1851 if(tl->xfer->dst == node){ 1852 xfer = tl->xfer; 1853#if 0 1854 STAILQ_REMOVE(&fc->tlabels[tlabel], tl, tlabel, link); 1855 free(tl, M_DEVBUF); 1856#endif 1857 splx(s); 1858 return(xfer); 1859 } 1860 } 1861 splx(s); 1862 return(NULL); 1863} 1864/* 1865 * To allocate IEEE1394 XFER structure. 1866 */ 1867struct fw_xfer *fw_xfer_alloc() 1868{ 1869 struct fw_xfer *xfer; 1870#if 0 1871 xfer = malloc(sizeof(struct fw_xfer), M_DEVBUF, M_DONTWAIT); 1872#else 1873 xfer = malloc(sizeof(struct fw_xfer), M_DEVBUF, M_DONTWAIT | M_ZERO); 1874#endif 1875 if(xfer == NULL) return xfer; 1876#if 0 /* xfer->tl = 0 was missing.. */ 1877 xfer->act_type = FWACT_NULL; 1878 xfer->fc = NULL; 1879 xfer->retry = 0; 1880 xfer->resp = 0; 1881 xfer->state = FWXF_INIT; 1882 xfer->time = time_second; 1883 xfer->sub = -1; 1884 xfer->send.buf = NULL; 1885 xfer->send.off = 0; 1886 xfer->send.len = 0; 1887 xfer->recv.buf = NULL; 1888 xfer->recv.off = 0; 1889 xfer->recv.len = 0; 1890 xfer->retry_req = NULL; 1891 xfer->act.hand = NULL; 1892 xfer->sc = NULL; 1893#else 1894 xfer->time = time_second; 1895 xfer->sub = -1; 1896#endif 1897 return xfer; 1898} 1899/* 1900 * IEEE1394 XFER post process. 1901 */ 1902void 1903fw_xfer_done(struct fw_xfer *xfer) 1904{ 1905 if (xfer->act.hand == NULL) 1906 return; 1907 1908#if XFER_TIMEOUT 1909 untimeout(fw_xfer_timeout, (void *)xfer, xfer->ch); 1910#endif 1911 1912 if (xfer->fc->status != FWBUSRESET) 1913 xfer->act.hand(xfer); 1914 else { 1915 printf("fw_xfer_done: pending\n"); 1916 if (xfer->fc != NULL) 1917 STAILQ_INSERT_TAIL(&xfer->fc->pending, xfer, link); 1918 else 1919 panic("fw_xfer_done: why xfer->fc is NULL?"); 1920 } 1921} 1922 1923/* 1924 * To free IEEE1394 XFER structure. 1925 */ 1926void fw_xfer_free( struct fw_xfer* xfer) 1927{ 1928 int s; 1929 if(xfer == NULL ) return; 1930 if(xfer->state == FWXF_INQ){ 1931 printf("fw_xfer_free FWXF_INQ\n"); 1932 s = splfw(); 1933 STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link); 1934 xfer->q->queued --; 1935 splx(s); 1936 } 1937 if(xfer->fc != NULL){ 1938 if(xfer->state == FWXF_START){ 1939#if 0 /* this could happen if we call fwohci_arcv() before fwohci_txd() */ 1940 printf("fw_xfer_free FWXF_START\n"); 1941#endif 1942 s = splfw(); 1943 xfer->q->drain(xfer->fc, xfer); 1944 splx(s); 1945 } 1946 } 1947 if(xfer->send.buf != NULL){ 1948 free(xfer->send.buf, M_DEVBUF); 1949 } 1950 if(xfer->recv.buf != NULL){ 1951 free(xfer->recv.buf, M_DEVBUF); 1952 } 1953 if(xfer->fc != NULL){ 1954 fw_tl_free(xfer->fc, xfer); 1955 } 1956 free(xfer, M_DEVBUF); 1957} 1958 1959/* 1960 * Callback for PHY configuration. 1961 */ 1962static void 1963fw_phy_config_callback(struct fw_xfer *xfer) 1964{ 1965#if 0 1966 printf("phy_config done state=%d resp=%d\n", 1967 xfer->state, xfer->resp); 1968#endif 1969 fw_xfer_free(xfer); 1970 /* XXX need bus reset ?? */ 1971 /* sc->fc->ibr(xfer->fc); LOOP */ 1972} 1973 1974/* 1975 * To configure PHY. 1976 */ 1977static void 1978fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count) 1979{ 1980 struct fw_xfer *xfer; 1981 struct fw_pkt *fp; 1982 1983 fc->status = FWBUSPHYCONF; 1984 1985 DELAY(100000); 1986 xfer = fw_xfer_alloc(); 1987 xfer->send.len = 12; 1988 xfer->send.off = 0; 1989 xfer->fc = fc; 1990 xfer->retry_req = fw_asybusy; 1991 xfer->act.hand = fw_phy_config_callback; 1992 1993 xfer->send.buf = malloc(sizeof(u_int32_t), 1994 M_DEVBUF, M_DONTWAIT | M_ZERO); 1995 fp = (struct fw_pkt *)xfer->send.buf; 1996 fp->mode.ld[1] = 0; 1997 if (root_node >= 0) 1998 fp->mode.ld[1] |= htonl((root_node & 0x3f) << 24 | 1 << 23); 1999 if (gap_count >= 0) 2000 fp->mode.ld[1] |= htonl(1 << 22 | (gap_count & 0x3f) << 16); 2001 fp->mode.ld[2] = ~fp->mode.ld[1]; 2002/* XXX Dangerous, how to pass PHY packet to device driver */ 2003 fp->mode.common.tcode |= FWTCODE_PHY; 2004 2005 printf("send phy_config root_node=%d gap_count=%d\n", 2006 root_node, gap_count); 2007 fw_asyreq(fc, -1, xfer); 2008} 2009 2010#if 0 2011/* 2012 * Dump self ID. 2013 */ 2014static void 2015fw_print_sid(u_int32_t sid) 2016{ 2017#if 0 2018 printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d" 2019 " p0:%d p1:%d p2:%d i:%d m:%d\n", 2020 FWPHYSIDNODE(sid), FWPHYSIDLINK(sid), FWPHYSIDGAP(sid), 2021 FWPHYSIDSPD(sid), FWPHYSIDDEL(sid), FWPHYSIDCON(sid), 2022 FWPHYSIDPWR(sid), FWPHYSIDP0(sid), FWPHYSIDP1(sid), 2023 FWPHYSIDP2(sid), FWPHYSIDIR(sid), FWPHYSIDMORE(sid)); 2024#else 2025 union fw_self_id *s; 2026 s = (union fw_self_id *) &sid; 2027 printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d" 2028 " p0:%d p1:%d p2:%d i:%d m:%d\n", 2029 s->p0.phy_id, s->p0.link_active, s->p0.gap_count, 2030 s->p0.phy_speed, s->p0.phy_delay, s->p0.contender, 2031 s->p0.power_class, s->p0.port0, s->p0.port1, 2032 s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); 2033#endif 2034} 2035#endif 2036 2037/* 2038 * To receive self ID. 2039 */ 2040void fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off) 2041{ 2042 u_int32_t *p, *sid = (u_int32_t *)(buf + off); 2043 union fw_self_id *self_id; 2044 u_int i, j, node, c_port = 0, i_branch = 0; 2045 2046 fc->sid_cnt = len /(sizeof(u_int32_t) * 2); 2047 fc->status = FWBUSINIT; 2048 fc->max_node = fc->nodeid & 0x3f; 2049 CSRARC(fc, NODE_IDS) = ((u_int32_t)fc->nodeid) << 16; 2050 fc->status = FWBUSCYMELECT; 2051 fc->topology_map->crc_len = 2; 2052 fc->topology_map->generation ++; 2053 fc->topology_map->self_id_count = 0; 2054 fc->topology_map->node_count = 0; 2055 fc->speed_map->generation ++; 2056 fc->speed_map->crc_len = 1 + (64*64 + 3) / 4; 2057 self_id = &fc->topology_map->self_id[0]; 2058 for(i = 0; i < fc->sid_cnt; i ++){ 2059 if (sid[1] != ~sid[0]) { 2060 printf("fw_sidrcv: invalid self-id packet\n"); 2061 sid += 2; 2062 continue; 2063 } 2064 *self_id = *((union fw_self_id *)sid); 2065 fc->topology_map->crc_len++; 2066 if(self_id->p0.sequel == 0){ 2067 fc->topology_map->node_count ++; 2068 c_port = 0; 2069#if 0 2070 fw_print_sid(sid[0]); 2071#endif 2072 node = self_id->p0.phy_id; 2073 if(fc->max_node < node){ 2074 fc->max_node = self_id->p0.phy_id; 2075 } 2076 /* XXX I'm not sure this is the right speed_map */ 2077 fc->speed_map->speed[node][node] 2078 = self_id->p0.phy_speed; 2079 for (j = 0; j < node; j ++) { 2080 fc->speed_map->speed[j][node] 2081 = fc->speed_map->speed[node][j] 2082 = min(fc->speed_map->speed[j][j], 2083 self_id->p0.phy_speed); 2084 } 2085 if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) && 2086 (self_id->p0.link_active && self_id->p0.contender)) { 2087 fc->irm = self_id->p0.phy_id; 2088 } 2089 if(self_id->p0.port0 >= 0x2){ 2090 c_port++; 2091 } 2092 if(self_id->p0.port1 >= 0x2){ 2093 c_port++; 2094 } 2095 if(self_id->p0.port2 >= 0x2){ 2096 c_port++; 2097 } 2098 } 2099 if(c_port > 2){ 2100 i_branch += (c_port - 2); 2101 } 2102 sid += 2; 2103 self_id++; 2104 fc->topology_map->self_id_count ++; 2105 } 2106 printf("%s: %d nodes", device_get_nameunit(fc->dev), fc->max_node + 1); 2107 /* CRC */ 2108 fc->topology_map->crc = fw_crc16( 2109 (u_int32_t *)&fc->topology_map->generation, 2110 fc->topology_map->crc_len * 4); 2111 fc->speed_map->crc = fw_crc16( 2112 (u_int32_t *)&fc->speed_map->generation, 2113 fc->speed_map->crc_len * 4); 2114 /* byteswap and copy to CSR */ 2115 p = (u_int32_t *)fc->topology_map; 2116 for (i = 0; i <= fc->topology_map->crc_len; i++) 2117 CSRARC(fc, TOPO_MAP + i * 4) = htonl(*p++); 2118 p = (u_int32_t *)fc->speed_map; 2119 CSRARC(fc, SPED_MAP) = htonl(*p++); 2120 CSRARC(fc, SPED_MAP + 4) = htonl(*p++); 2121 /* don't byte-swap u_int8_t array */ 2122 bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4); 2123 2124 fc->max_hop = fc->max_node - i_branch; 2125#if 1 2126 printf(", maxhop <= %d", fc->max_hop); 2127#endif 2128 2129 if(fc->irm == -1 ){ 2130 printf(", Not found IRM capable node"); 2131 }else{ 2132 printf(", cable IRM = %d", fc->irm); 2133 if (fc->irm == fc->nodeid) 2134 printf(" (me)\n"); 2135 else 2136 printf("\n"); 2137 } 2138 2139 if((fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f) ){ 2140 if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){ 2141 fc->status = FWBUSMGRDONE; 2142 CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm); 2143 }else{ 2144 fc->status = FWBUSMGRELECT; 2145 fc->bmrhandle = timeout((timeout_t *)fw_try_bmr,(void *)fc, hz / 8); 2146 } 2147 }else{ 2148 fc->status = FWBUSMGRDONE; 2149 printf("%s: BMR = %x\n", device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); 2150 } 2151 free(buf, M_DEVBUF); 2152#if 1 2153 /* XXX optimize gap_count, if I am BMGR */ 2154 if(fc->irm == ((CSRARC(fc, NODE_IDS) >> 16 ) & 0x3f)){ 2155 fw_phy_config(fc, -1, gap_cnt[fc->max_hop]); 2156 } 2157#endif 2158#if 1 2159 timeout((timeout_t *)fw_bus_probe, (void *)fc, hz/4); 2160#else 2161 fw_bus_probe(fc); 2162#endif 2163} 2164/* 2165 * To probe devices on the IEEE1394 bus. 2166 */ 2167static void fw_bus_probe(struct firewire_comm *fc) 2168{ 2169 int s; 2170 struct fw_device *fwdev, *next; 2171 2172 s = splfw(); 2173 fc->status = FWBUSEXPLORE; 2174 fc->retry_count = 0; 2175 2176/* 2177 * Invalidate all devices, just after bus reset. Devices 2178 * to be removed has not been seen longer time. 2179 */ 2180 for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) { 2181 next = TAILQ_NEXT(fwdev, link); 2182 if(fwdev->status != FWDEVINVAL){ 2183 fwdev->status = FWDEVINVAL; 2184 fwdev->rcnt = 0; 2185 }else if(fwdev->rcnt < FW_MAXDEVRCNT){ 2186 fwdev->rcnt ++; 2187 }else{ 2188 TAILQ_REMOVE(&fc->devices, fwdev, link); 2189 free(fwdev, M_DEVBUF); 2190 } 2191 } 2192 fc->ongonode = 0; 2193 fc->ongoaddr = CSRROMOFF; 2194 fc->ongodev = NULL; 2195 fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2196 fw_bus_explore(fc); 2197 splx(s); 2198} 2199/* 2200 * To collect device informations on the IEEE1394 bus. 2201 */ 2202static void fw_bus_explore(struct firewire_comm *fc ) 2203{ 2204 int err = 0; 2205 struct fw_device *fwdev, *tfwdev; 2206 u_int32_t addr; 2207 struct fw_xfer *xfer; 2208 struct fw_pkt *fp; 2209 2210 if(fc->status != FWBUSEXPLORE) 2211 return; 2212 2213loop: 2214 if(fc->ongonode == fc->nodeid) fc->ongonode++; 2215 2216 if(fc->ongonode > fc->max_node) goto done; 2217 if(fc->ongonode >= 0x3f) goto done; 2218 2219 /* check link */ 2220 /* XXX we need to check phy_id first */ 2221 if (!fc->topology_map->self_id[fc->ongonode].p0.link_active) { 2222 printf("fw_bus_explore: node %d link down\n", fc->ongonode); 2223 fc->ongonode++; 2224 goto loop; 2225 } 2226 2227 if(fc->ongoaddr <= CSRROMOFF && 2228 fc->ongoeui.hi == 0xffffffff && 2229 fc->ongoeui.lo == 0xffffffff ){ 2230 fc->ongoaddr = CSRROMOFF; 2231 addr = 0xf0000000 | fc->ongoaddr; 2232 }else if(fc->ongoeui.hi == 0xffffffff ){ 2233 fc->ongoaddr = CSRROMOFF + 0xc; 2234 addr = 0xf0000000 | fc->ongoaddr; 2235 }else if(fc->ongoeui.lo == 0xffffffff ){ 2236 fc->ongoaddr = CSRROMOFF + 0x10; 2237 addr = 0xf0000000 | fc->ongoaddr; 2238 }else if(fc->ongodev == NULL){ 2239 for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 2240 fwdev = TAILQ_NEXT(fwdev, link)){ 2241 if(fwdev->eui.hi == fc->ongoeui.hi && fwdev->eui.lo == fc->ongoeui.lo){ 2242 break; 2243 } 2244 } 2245 if(fwdev != NULL){ 2246 fwdev->dst = fc->ongonode; 2247 fwdev->status = FWDEVATTACHED; 2248 fc->ongonode++; 2249 fc->ongoaddr = CSRROMOFF; 2250 fc->ongodev = NULL; 2251 fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2252 goto loop; 2253 } 2254 fwdev = malloc(sizeof(struct fw_device), M_DEVBUF, M_DONTWAIT); 2255 if(fwdev == NULL) 2256 return; 2257 fwdev->rommax = 0; 2258 fwdev->dst = fc->ongonode; 2259 fwdev->eui.hi = fc->ongoeui.hi; fwdev->eui.lo = fc->ongoeui.lo; 2260 fwdev->status = FWDEVINIT; 2261#if 0 2262 fwdev->speed = CSRARC(fc, SPED_MAP + 8 + fc->ongonode / 4) 2263 >> ((3 - (fc->ongonode % 4)) * 8); 2264#else 2265 fwdev->speed = fc->speed_map->speed[fc->nodeid][fc->ongonode]; 2266#endif 2267 2268#if 0 2269 TAILQ_INSERT_TAIL(&fc->devices, fwdev, link); 2270#else 2271 tfwdev = TAILQ_FIRST(&fc->devices); 2272 while( tfwdev != NULL && 2273 (tfwdev->eui.hi > fwdev->eui.hi) && 2274 ((tfwdev->eui.hi == fwdev->eui.hi) && 2275 tfwdev->eui.lo > fwdev->eui.lo)){ 2276 tfwdev = TAILQ_NEXT( tfwdev, link); 2277 } 2278 if(tfwdev == NULL){ 2279 TAILQ_INSERT_TAIL(&fc->devices, fwdev, link); 2280 }else{ 2281 TAILQ_INSERT_BEFORE(tfwdev, fwdev, link); 2282 } 2283#endif 2284 2285 printf("%s:Discover new %s device ID:%08x%08x\n", device_get_nameunit(fc->dev), linkspeed[fwdev->speed], fc->ongoeui.hi, fc->ongoeui.lo); 2286 2287 fc->ongodev = fwdev; 2288 fc->ongoaddr = CSRROMOFF; 2289 addr = 0xf0000000 | fc->ongoaddr; 2290 }else{ 2291 addr = 0xf0000000 | fc->ongoaddr; 2292 } 2293#if 0 2294 xfer = asyreqq(fc, FWSPD_S100, 0, 0, 2295 ((FWLOCALBUS | fc->ongonode) << 16) | 0xffff , addr, 2296 fw_bus_explore_callback); 2297 if(xfer == NULL) goto done; 2298#else 2299 xfer = fw_xfer_alloc(); 2300 if(xfer == NULL){ 2301 goto done; 2302 } 2303 xfer->send.len = 16; 2304 xfer->spd = 0; 2305 xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2306 if(xfer->send.buf == NULL){ 2307 fw_xfer_free( xfer); 2308 return; 2309 } 2310 2311 xfer->send.off = 0; 2312 fp = (struct fw_pkt *)xfer->send.buf; 2313 fp->mode.rreqq.dest_hi = htons(0xffff); 2314 fp->mode.rreqq.tlrt = 0; 2315 fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2316 fp->mode.rreqq.pri = 0; 2317 fp->mode.rreqq.src = 0; 2318 xfer->dst = FWLOCALBUS | fc->ongonode; 2319 fp->mode.rreqq.dst = htons(xfer->dst); 2320 fp->mode.rreqq.dest_lo = htonl(addr); 2321 xfer->act.hand = fw_bus_explore_callback; 2322 2323 err = fw_asyreq(fc, -1, xfer); 2324 if(err){ 2325 fw_xfer_free( xfer); 2326 return; 2327 } 2328#endif 2329 return; 2330done: 2331 /* fw_attach_devs */ 2332 fc->status = FWBUSEXPDONE; 2333 printf("bus_explore done\n"); 2334 fw_attach_dev(fc); 2335 return; 2336 2337} 2338/* Portable Async. request read quad */ 2339struct fw_xfer *asyreqq(struct firewire_comm *fc, 2340 u_int8_t spd, u_int8_t tl, u_int8_t rt, 2341 u_int32_t addr_hi, u_int32_t addr_lo, 2342 void (*hand) __P((struct fw_xfer*))) 2343{ 2344 struct fw_xfer *xfer; 2345 struct fw_pkt *fp; 2346 int err; 2347 2348 xfer = fw_xfer_alloc(); 2349 if(xfer == NULL){ 2350 return NULL; 2351 } 2352 xfer->send.len = 16; 2353 xfer->spd = spd; /* XXX:min(spd, fc->spd) */ 2354 xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2355 if(xfer->send.buf == NULL){ 2356 fw_xfer_free( xfer); 2357 return NULL; 2358 } 2359 2360 xfer->send.off = 0; 2361 fp = (struct fw_pkt *)xfer->send.buf; 2362 fp->mode.rreqq.dest_hi = htons(addr_hi & 0xffff); 2363 if(tl & FWP_TL_VALID){ 2364 fp->mode.rreqq.tlrt = (tl & 0x3f) << 2; 2365 }else{ 2366 fp->mode.rreqq.tlrt = 0; 2367 } 2368 fp->mode.rreqq.tlrt |= rt & 0x3; 2369 fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2370 fp->mode.rreqq.pri = 0; 2371 fp->mode.rreqq.src = 0; 2372 xfer->dst = addr_hi >> 16; 2373 fp->mode.rreqq.dst = htons(xfer->dst); 2374 fp->mode.rreqq.dest_lo = htonl(addr_lo); 2375 xfer->act.hand = hand; 2376 2377 err = fw_asyreq(fc, -1, xfer); 2378 if(err){ 2379 fw_xfer_free( xfer); 2380 return NULL; 2381 } 2382 return xfer; 2383} 2384/* 2385 * Callback for the IEEE1394 bus information collection. 2386 */ 2387static void fw_bus_explore_callback(struct fw_xfer *xfer){ 2388 struct firewire_comm *fc; 2389 struct fw_pkt *sfp,*rfp; 2390 struct csrhdr *chdr; 2391 struct csrdir *csrd; 2392 struct csrreg *csrreg; 2393 u_int32_t offset; 2394 2395 2396 if(xfer == NULL) return; 2397 fc = xfer->fc; 2398 if(xfer->resp != 0){ 2399 printf("resp != 0: node=%d addr=0x%x\n", 2400 fc->ongonode, fc->ongoaddr); 2401 fc->retry_count++; 2402 goto nextnode; 2403 } 2404 2405 if(xfer->send.buf == NULL){ 2406 printf("send.buf == NULL: node=%d addr=0x%x\n", 2407 fc->ongonode, fc->ongoaddr); 2408 printf("send.buf == NULL\n"); 2409 fc->retry_count++; 2410 goto nextnode; 2411 } 2412 sfp = (struct fw_pkt *)xfer->send.buf; 2413 2414 if(xfer->recv.buf == NULL){ 2415 printf("recv.buf == NULL: node=%d addr=0x%x\n", 2416 fc->ongonode, fc->ongoaddr); 2417 fc->retry_count++; 2418 goto nextnode; 2419 } 2420 rfp = (struct fw_pkt *)xfer->recv.buf; 2421#if 0 2422 { 2423 u_int32_t *qld; 2424 int i; 2425 qld = (u_int32_t *)xfer->recv.buf; 2426 printf("len:%d\n", xfer->recv.len); 2427 for( i = 0 ; i <= xfer->recv.len && i < 32; i+= 4){ 2428 printf("0x%08x ", ntohl(rfp->mode.ld[i/4])); 2429 if((i % 16) == 15) printf("\n"); 2430 } 2431 if((i % 16) != 15) printf("\n"); 2432 } 2433#endif 2434 if(fc->ongodev == NULL){ 2435 if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 | CSRROMOFF))){ 2436 rfp->mode.rresq.data = ntohl(rfp->mode.rresq.data); 2437 chdr = (struct csrhdr *)(&rfp->mode.rresq.data); 2438/* If CSR is minimul confinguration, more investgation is not needed. */ 2439 if(chdr->info_len == 1){ 2440 goto nextnode; 2441 }else{ 2442 fc->ongoaddr = CSRROMOFF + 0xc; 2443 } 2444 }else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0xc)))){ 2445 fc->ongoeui.hi = ntohl(rfp->mode.rresq.data); 2446 fc->ongoaddr = CSRROMOFF + 0x10; 2447 }else if(sfp->mode.rreqq.dest_lo == htonl((0xf0000000 |(CSRROMOFF + 0x10)))){ 2448 fc->ongoeui.lo = ntohl(rfp->mode.rresq.data); 2449 if (fc->ongoeui.hi == 0 && fc->ongoeui.lo == 0) 2450 goto nextnode; 2451 fc->ongoaddr = CSRROMOFF; 2452 } 2453 }else{ 2454 fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data); 2455 if(fc->ongoaddr > fc->ongodev->rommax){ 2456 fc->ongodev->rommax = fc->ongoaddr; 2457 } 2458 csrd = SLIST_FIRST(&fc->ongocsr); 2459 if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){ 2460 chdr = (struct csrhdr *)(fc->ongodev->csrrom); 2461 offset = CSRROMOFF; 2462 }else{ 2463 chdr = (struct csrhdr *)&fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]; 2464 offset = csrd->off; 2465 } 2466 if(fc->ongoaddr > (CSRROMOFF + 0x14) && fc->ongoaddr != offset){ 2467 csrreg = (struct csrreg *)&fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4]; 2468 if( csrreg->key == 0x81 || csrreg->key == 0xd1){ 2469 csrd = SLIST_FIRST(&fc->csrfree); 2470 if(csrd == NULL){ 2471 goto nextnode; 2472 }else{ 2473 csrd->ongoaddr = fc->ongoaddr; 2474 fc->ongoaddr += csrreg->val * 4; 2475 csrd->off = fc->ongoaddr; 2476 SLIST_REMOVE_HEAD(&fc->csrfree, link); 2477 SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link); 2478 goto nextaddr; 2479 } 2480 } 2481 } 2482 fc->ongoaddr += 4; 2483 if(((fc->ongoaddr - offset)/4 > chdr->crc_len) && 2484 (fc->ongodev->rommax < 0x414)){ 2485 if(fc->ongodev->rommax <= 0x414){ 2486 csrd = SLIST_FIRST(&fc->csrfree); 2487 if(csrd == NULL) goto nextnode; 2488 csrd->off = fc->ongoaddr; 2489 csrd->ongoaddr = fc->ongoaddr; 2490 SLIST_REMOVE_HEAD(&fc->csrfree, link); 2491 SLIST_INSERT_HEAD(&fc->ongocsr, csrd, link); 2492 } 2493 goto nextaddr; 2494 } 2495 2496 while(((fc->ongoaddr - offset)/4 > chdr->crc_len)){ 2497 if(csrd == NULL){ 2498 goto nextnode; 2499 }; 2500 fc->ongoaddr = csrd->ongoaddr + 4; 2501 SLIST_REMOVE_HEAD(&fc->ongocsr, link); 2502 SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 2503 csrd = SLIST_FIRST(&fc->ongocsr); 2504 if((csrd = SLIST_FIRST(&fc->ongocsr)) == NULL){ 2505 chdr = (struct csrhdr *)(fc->ongodev->csrrom); 2506 offset = CSRROMOFF; 2507 }else{ 2508 chdr = (struct csrhdr *)&(fc->ongodev->csrrom[(csrd->off - CSRROMOFF)/4]); 2509 offset = csrd->off; 2510 } 2511 } 2512 if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE){ 2513 goto nextnode; 2514 } 2515 } 2516nextaddr: 2517 fw_xfer_free( xfer); 2518 fw_bus_explore(fc); 2519 return; 2520nextnode: 2521 fw_xfer_free( xfer); 2522 fc->ongonode++; 2523/* housekeeping work space */ 2524 fc->ongoaddr = CSRROMOFF; 2525 fc->ongodev = NULL; 2526 fc->ongoeui.hi = 0xffffffff; fc->ongoeui.lo = 0xffffffff; 2527 while((csrd = SLIST_FIRST(&fc->ongocsr)) != NULL){ 2528 SLIST_REMOVE_HEAD(&fc->ongocsr, link); 2529 SLIST_INSERT_HEAD(&fc->csrfree, csrd, link); 2530 } 2531 fw_bus_explore(fc); 2532 return; 2533} 2534/* 2535 * Async. write responce support for kernel internal use. 2536 */ 2537int fw_writeres(struct firewire_comm *fc, u_int32_t dst, u_int32_t tlrt){ 2538 int err = 0; 2539 struct fw_xfer *xfer; 2540 struct fw_pkt *fp; 2541 2542 xfer = fw_xfer_alloc(); 2543 if(xfer == NULL){ 2544 err = ENOMEM; 2545 return err; 2546 } 2547 xfer->send.len = 12; 2548 xfer->spd = 0; 2549 xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT); 2550 if(xfer->send.buf == NULL){ 2551 return ENOMEM; 2552 } 2553 xfer->send.off = 0; 2554 fp = (struct fw_pkt *)xfer->send.buf; 2555 2556 fp->mode.wres.tlrt = tlrt; 2557 fp->mode.wres.tcode = FWTCODE_WRES; 2558 fp->mode.wres.pri = 0; 2559 fp->mode.wres.dst = htons(dst); 2560 2561 xfer->act.hand = fw_asy_callback; 2562 err = fw_asyreq(fc, -1, xfer); 2563 if(err){ 2564 fw_xfer_free( xfer); 2565 return err; 2566 } 2567 err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2568 fw_xfer_free( xfer); 2569 2570 return err; 2571} 2572/* 2573 * Async. read responce block support for kernel internal use. 2574 */ 2575int fw_readresb(struct firewire_comm *fc, u_int32_t dst, u_int32_t tlrt, u_int32_t len, u_int32_t *buf){ 2576 int err = 0; 2577 struct fw_xfer *xfer ; 2578 struct fw_pkt *fp; 2579 2580 xfer = fw_xfer_alloc(); 2581 if(xfer == NULL){ 2582 err = ENOMEM; 2583 return err; 2584 } 2585 xfer->send.len = sizeof(struct fw_pkt) + len; 2586 xfer->spd = 0; 2587 xfer->send.buf = malloc(sizeof(struct fw_pkt) + 1024, M_DEVBUF, M_DONTWAIT); 2588 if(xfer->send.buf == NULL){ 2589 return ENOMEM; 2590 } 2591 xfer->send.off = 0; 2592 fp = (struct fw_pkt *)xfer->send.buf; 2593 fp->mode.rresb.tlrt = tlrt; 2594 fp->mode.rresb.tcode = FWTCODE_RRESB; 2595 fp->mode.rresb.pri = 0; 2596 fp->mode.rresb.dst = htons(dst); 2597 fp->mode.rresb.rtcode = 0; 2598 fp->mode.rresb.extcode = 0; 2599 fp->mode.rresb.len = htons(len); 2600 bcopy(buf, fp->mode.rresb.payload, len); 2601 xfer->act.hand = fw_asy_callback; 2602 err = fw_asyreq(fc, -1, xfer); 2603 if(err){ 2604 fw_xfer_free( xfer); 2605 return err; 2606 } 2607 err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2608 2609 fw_xfer_free( xfer); 2610 return err; 2611} 2612/* 2613 * Async. write request block support for kernel internal use. 2614 */ 2615int fw_writereqb(struct firewire_comm *fc, u_int32_t addr_hi, u_int32_t addr_lo, u_int len, u_int32_t *buf){ 2616 int err = 0; 2617 struct fw_xfer *xfer ; 2618 struct fw_pkt *fp; 2619 2620 xfer = fw_xfer_alloc(); 2621 if(xfer == NULL){ 2622 err = ENOMEM; 2623 return err; 2624 } 2625 xfer->send.len = sizeof(struct fw_pkt) + len; 2626 xfer->spd = 0; 2627 xfer->send.buf = malloc(sizeof(struct fw_pkt) + 1024, M_DEVBUF, M_DONTWAIT); 2628 if(xfer->send.buf == NULL){ 2629 return ENOMEM; 2630 } 2631 xfer->send.off = 0; 2632 fp = (struct fw_pkt *)xfer->send.buf; 2633 fp->mode.wreqb.dest_hi = htonl(addr_hi & 0xffff); 2634 fp->mode.wreqb.tlrt = 0; 2635 fp->mode.wreqb.tcode = FWTCODE_WREQB; 2636 fp->mode.wreqb.pri = 0; 2637 fp->mode.wreqb.dst = htons(addr_hi >> 16); 2638 fp->mode.wreqb.dest_lo = htonl(addr_lo); 2639 fp->mode.wreqb.len = htons(len); 2640 fp->mode.wreqb.extcode = 0; 2641 bcopy(buf, fp->mode.wreqb.payload, len); 2642 xfer->act.hand = fw_asy_callback; 2643 err = fw_asyreq(fc, -1, xfer); 2644 if(err){ 2645 fw_xfer_free( xfer); 2646 return err; 2647 } 2648 err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2649 2650 fw_xfer_free( xfer); 2651 return err; 2652} 2653/* 2654 * Async. read request support for kernel internal use. 2655 */ 2656int fw_readreqq(struct firewire_comm *fc, u_int32_t addr_hi, u_int32_t addr_lo, u_int32_t *ret){ 2657 int err = 0; 2658 struct fw_xfer *xfer ; 2659 struct fw_pkt *fp, *rfp; 2660 2661 xfer = fw_xfer_alloc(); 2662 if(xfer == NULL){ 2663 err = ENOMEM; 2664 return err; 2665 } 2666 xfer->send.len = 16; 2667 xfer->spd = 0; 2668 xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2669 if(xfer->send.buf == NULL){ 2670 return ENOMEM; 2671 } 2672 xfer->send.off = 0; 2673 fp = (struct fw_pkt *)xfer->send.buf; 2674 fp->mode.rreqq.dest_hi = htonl(addr_hi & 0xffff); 2675 fp->mode.rreqq.tlrt = 0; 2676 fp->mode.rreqq.tcode = FWTCODE_RREQQ; 2677 fp->mode.rreqq.pri = 0; 2678 xfer->dst = addr_hi >> 16; 2679 fp->mode.rreqq.dst = htons(xfer->dst); 2680 fp->mode.rreqq.dest_lo = htonl(addr_lo); 2681 xfer->act.hand = fw_asy_callback; 2682 err = fw_asyreq(fc, -1, xfer); 2683 if(err){ 2684 fw_xfer_free( xfer); 2685 return err; 2686 } 2687 err = tsleep((caddr_t)xfer, FWPRI, "asyreq", 0); 2688 2689 if(err == 0 && xfer->recv.buf != NULL){ 2690 rfp = (struct fw_pkt *)xfer->recv.buf; 2691 *ret = ntohl(rfp->mode.rresq.data); 2692 } 2693 fw_xfer_free( xfer); 2694 return err; 2695} 2696/* 2697 * To obtain CSR register values. 2698 */ 2699u_int32_t getcsrdata(struct fw_device *fwdev, u_int8_t key) 2700{ 2701 int i; 2702 struct csrhdr *chdr; 2703 struct csrreg *creg; 2704 chdr = (struct csrhdr *)&fwdev->csrrom[0]; 2705 for( i = chdr->info_len + 4; i <= fwdev->rommax - CSRROMOFF; i+=4){ 2706 creg = (struct csrreg *)&fwdev->csrrom[i/4]; 2707 if(creg->key == key){ 2708 return (u_int32_t)creg->val; 2709 } 2710 } 2711 return 0; 2712} 2713/* 2714 * To attach sub-devices layer onto IEEE1394 bus. 2715 */ 2716static void fw_attach_dev(struct firewire_comm *fc) 2717{ 2718 struct fw_device *fwdev; 2719 struct fw_xfer *xfer; 2720 int i, err; 2721 device_t *devlistp; 2722 int devcnt; 2723 struct firewire_dev_comm *fdc; 2724 2725 for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; 2726 fwdev = TAILQ_NEXT(fwdev, link)){ 2727 if(fwdev->status == FWDEVINIT){ 2728 fwdev->spec = getcsrdata(fwdev, CSRKEY_SPEC); 2729 if(fwdev->spec == 0) 2730 continue; 2731 fwdev->ver = getcsrdata(fwdev, CSRKEY_VER); 2732 if(fwdev->ver == 0) 2733 continue; 2734 fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf; 2735 2736 switch(fwdev->spec){ 2737 case CSRVAL_ANSIT10: 2738 switch(fwdev->ver){ 2739 case CSRVAL_T10SBP2: 2740 printf("Device SBP-II"); 2741 break; 2742 default: 2743 break; 2744 } 2745 break; 2746 case CSRVAL_1394TA: 2747 switch(fwdev->ver){ 2748 case CSR_PROTAVC: 2749 printf("Device AV/C"); 2750 break; 2751 case CSR_PROTCAL: 2752 printf("Device CAL"); 2753 break; 2754 case CSR_PROTEHS: 2755 printf("Device EHS"); 2756 break; 2757 case CSR_PROTHAVI: 2758 printf("Device HAVi"); 2759 break; 2760 case CSR_PROTCAM104: 2761 printf("Device 1394 Cam 1.04"); 2762 break; 2763 case CSR_PROTCAM120: 2764 printf("Device 1394 Cam 1.20"); 2765 break; 2766 case CSR_PROTCAM130: 2767 printf("Device 1394 Cam 1.30"); 2768 break; 2769 case CSR_PROTDPP: 2770 printf("Device 1394 Direct print"); 2771 break; 2772 case CSR_PROTIICP: 2773 printf("Device Industrial & Instrument"); 2774 break; 2775 default: 2776 printf("Device unkwon 1394TA"); 2777 break; 2778 } 2779 break; 2780 default: 2781 break; 2782 } 2783 fwdev->status = FWDEVATTACHED; 2784 printf("\n"); 2785 } 2786 } 2787 err = device_get_children(fc->dev, &devlistp, &devcnt); 2788 if( err != 0 ) 2789 return; 2790 for( i = 0 ; i < devcnt ; i++){ 2791 if (device_get_state(devlistp[i]) >= DS_ATTACHED) { 2792 fdc = device_get_softc(devlistp[i]); 2793 if (fdc->post_explore != NULL) 2794 fdc->post_explore(fdc); 2795 } 2796 } 2797 free(devlistp, M_TEMP); 2798 2799 /* call pending handlers */ 2800 i = 0; 2801 while ((xfer = STAILQ_FIRST(&fc->pending))) { 2802 STAILQ_REMOVE_HEAD(&fc->pending, link); 2803 i++; 2804 if (xfer->act.hand) 2805 xfer->act.hand(xfer); 2806 } 2807 if (i > 0) 2808 printf("fw_attach_dev: %d pending handlers called\n", i); 2809 if (fc->retry_count > 0) { 2810 printf("retry_count = %d\n", fc->retry_count); 2811 fc->retry_probe_handle = timeout((timeout_t *)fc->ibr, 2812 (void *)fc, hz*2); 2813 } 2814 return; 2815} 2816/* 2817 * To allocate uniq transaction label. 2818 */ 2819static int fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer) 2820{ 2821 u_int i; 2822 struct tlabel *tl, *tmptl; 2823 int s; 2824 static u_int32_t label = 0; 2825 2826 s = splfw(); 2827 for( i = 0 ; i < 0x40 ; i ++){ 2828 label = (label + 1) & 0x3f; 2829 for(tmptl = STAILQ_FIRST(&fc->tlabels[label]); 2830 tmptl != NULL; tmptl = STAILQ_NEXT(tmptl, link)){ 2831 if(tmptl->xfer->dst == xfer->dst) break; 2832 } 2833 if(tmptl == NULL) { 2834 tl = malloc(sizeof(struct tlabel),M_DEVBUF,M_DONTWAIT); 2835 if (tl == NULL) { 2836 splx(s); 2837 return (-1); 2838 } 2839 tl->xfer = xfer; 2840 STAILQ_INSERT_TAIL(&fc->tlabels[label], tl, link); 2841 splx(s); 2842 return(label); 2843 } 2844 } 2845 splx(s); 2846 2847 printf("fw_get_tlabel: no free tlabel\n"); 2848 return(-1); 2849} 2850/* 2851 * Generic packet receving process. 2852 */ 2853void fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u_int spd) 2854{ 2855 struct fw_pkt *fp, *resfp; 2856 struct fw_xfer *xfer; 2857 struct fw_bind *bind; 2858 struct firewire_softc *sc; 2859 int s; 2860#if 0 2861 { 2862 u_int32_t *qld; 2863 int i; 2864 qld = (u_int32_t *)buf; 2865 printf("spd %d len:%d\n", spd, len); 2866 for( i = 0 ; i <= len && i < 32; i+= 4){ 2867 printf("0x%08x ", ntohl(qld[i/4])); 2868 if((i % 16) == 15) printf("\n"); 2869 } 2870 if((i % 16) != 15) printf("\n"); 2871 } 2872#endif 2873 fp = (struct fw_pkt *)(buf + off); 2874 switch(fp->mode.common.tcode){ 2875 case FWTCODE_WRES: 2876 case FWTCODE_RRESQ: 2877 case FWTCODE_RRESB: 2878 case FWTCODE_LRES: 2879 xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src), 2880 fp->mode.hdr.tlrt >> 2); 2881 if(xfer == NULL) { 2882 printf("fw_rcv: unknown response " 2883 "tcode=%d src=0x%x tl=%x rt=%d data=0x%x\n", 2884 fp->mode.common.tcode, 2885 ntohs(fp->mode.hdr.src), 2886 fp->mode.hdr.tlrt >> 2, 2887 fp->mode.hdr.tlrt & 3, 2888 fp->mode.rresq.data); 2889#if 1 2890 printf("try ad-hoc work around!!\n"); 2891 xfer = fw_tl2xfer(fc, ntohs(fp->mode.hdr.src), 2892 (fp->mode.hdr.tlrt >> 2)^3); 2893 if (xfer == NULL) { 2894 printf("no use...\n"); 2895 goto err; 2896 } 2897#else 2898 goto err; 2899#endif 2900 } 2901 switch(xfer->act_type){ 2902 case FWACT_XFER: 2903 if((xfer->sub >= 0) && 2904 ((fc->ir[xfer->sub]->flag & FWXFERQ_MODEMASK ) == 0)){ 2905 xfer->resp = EINVAL; 2906 fw_xfer_done(xfer); 2907 goto err; 2908 } 2909 xfer->recv.len = len; 2910 xfer->recv.off = off; 2911 xfer->recv.buf = buf; 2912 xfer->resp = 0; 2913 fw_xfer_done(xfer); 2914 return; 2915 break; 2916 case FWACT_CH: 2917 default: 2918 goto err; 2919 break; 2920 } 2921 break; 2922 case FWTCODE_WREQQ: 2923 case FWTCODE_WREQB: 2924 case FWTCODE_RREQQ: 2925 case FWTCODE_RREQB: 2926 case FWTCODE_LREQ: 2927 bind = fw_bindlookup(fc, ntohs(fp->mode.rreqq.dest_hi), 2928 ntohl(fp->mode.rreqq.dest_lo)); 2929 if(bind == NULL){ 2930 printf("Unknown service addr 0x%08x:0x%08x tcode=%x\n", 2931 ntohs(fp->mode.rreqq.dest_hi), 2932 ntohl(fp->mode.rreqq.dest_lo), 2933 fp->mode.common.tcode); 2934 if (fc->status == FWBUSRESET) { 2935 printf("fw_rcv: cannot response(bus reset)!\n"); 2936 goto err; 2937 } 2938 xfer = fw_xfer_alloc(); 2939 if(xfer == NULL){ 2940 return; 2941 } 2942 xfer->spd = spd; 2943 xfer->send.buf = malloc(16, M_DEVBUF, M_DONTWAIT); 2944 resfp = (struct fw_pkt *)xfer->send.buf; 2945 switch(fp->mode.common.tcode){ 2946 case FWTCODE_WREQQ: 2947 case FWTCODE_WREQB: 2948 resfp->mode.hdr.tcode = FWTCODE_WRES; 2949 xfer->send.len = 12; 2950 break; 2951 case FWTCODE_RREQQ: 2952 resfp->mode.hdr.tcode = FWTCODE_RRESQ; 2953 xfer->send.len = 16; 2954 break; 2955 case FWTCODE_RREQB: 2956 resfp->mode.hdr.tcode = FWTCODE_RRESB; 2957 xfer->send.len = 16; 2958 break; 2959 case FWTCODE_LREQ: 2960 resfp->mode.hdr.tcode = FWTCODE_LRES; 2961 xfer->send.len = 16; 2962 break; 2963 } 2964 resfp->mode.hdr.dst = fp->mode.hdr.src; 2965 resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt; 2966 resfp->mode.hdr.pri = fp->mode.hdr.pri; 2967 resfp->mode.rresb.rtcode = 7; 2968 resfp->mode.rresb.extcode = 0; 2969 resfp->mode.rresb.len = 0; 2970/* 2971 xfer->act.hand = fw_asy_callback; 2972*/ 2973 xfer->act.hand = fw_xfer_free; 2974 if(fw_asyreq(fc, -1, xfer)){ 2975 fw_xfer_free( xfer); 2976 return; 2977 } 2978 goto err; 2979 } 2980 switch(bind->xfer->act_type){ 2981 case FWACT_XFER: 2982 xfer = fw_xfer_alloc(); 2983 if(xfer == NULL) goto err; 2984 xfer->fc = bind->xfer->fc; 2985 xfer->sc = bind->xfer->sc; 2986 xfer->recv.buf = buf; 2987 xfer->recv.len = len; 2988 xfer->recv.off = off; 2989 xfer->spd = spd; 2990 xfer->act.hand = bind->xfer->act.hand; 2991 if (fc->status != FWBUSRESET) 2992 xfer->act.hand(xfer); 2993 else 2994 STAILQ_INSERT_TAIL(&fc->pending, xfer, link); 2995 return; 2996 break; 2997 case FWACT_CH: 2998 if(fc->ir[bind->xfer->sub]->queued >= 2999 fc->ir[bind->xfer->sub]->maxq){ 3000 printf("%s:Discard a packet %x %d\n", 3001 device_get_nameunit(fc->dev), 3002 bind->xfer->sub, 3003 fc->ir[bind->xfer->sub]->queued); 3004 goto err; 3005 } 3006 xfer = fw_xfer_alloc(); 3007 if(xfer == NULL) goto err; 3008 xfer->recv.buf = buf; 3009 xfer->recv.len = len; 3010 xfer->recv.off = off; 3011 xfer->spd = spd; 3012 s = splfw(); 3013 fc->ir[bind->xfer->sub]->queued++; 3014 STAILQ_INSERT_TAIL(&fc->ir[bind->xfer->sub]->q, xfer, link); 3015 splx(s); 3016 3017 wakeup((caddr_t)fc->ir[bind->xfer->sub]); 3018 3019 return; 3020 break; 3021 default: 3022 goto err; 3023 break; 3024 } 3025 break; 3026 case FWTCODE_STREAM: 3027 { 3028 struct fw_xferq *xferq; 3029 3030 xferq = fc->ir[sub]; 3031#if 0 3032 printf("stream rcv dma %d len %d off %d spd %d\n", 3033 sub, len, off, spd); 3034#endif 3035 if(xferq->queued >= xferq->maxq) { 3036 printf("receive queue is full\n"); 3037 goto err; 3038 } 3039 xfer = fw_xfer_alloc(); 3040 if(xfer == NULL) goto err; 3041 xfer->recv.buf = buf; 3042 xfer->recv.len = len; 3043 xfer->recv.off = off; 3044 xfer->spd = spd; 3045 s = splfw(); 3046 xferq->queued++; 3047 STAILQ_INSERT_TAIL(&xferq->q, xfer, link); 3048 splx(s); 3049 sc = device_get_softc(fc->bdev); 3050#if __FreeBSD_version >= 500000 3051 if (SEL_WAITING(&xferq->rsel)) 3052#else 3053 if (&xferq->rsel.si_pid != 0) 3054#endif 3055 selwakeup(&xferq->rsel); 3056 if (xferq->flag & FWXFERQ_WAKEUP) { 3057 xferq->flag &= ~FWXFERQ_WAKEUP; 3058 wakeup((caddr_t)xferq); 3059 } 3060 if (xferq->flag & FWXFERQ_HANDLER) { 3061 xferq->hand(xferq); 3062 } 3063 return; 3064 break; 3065 } 3066 default: 3067 printf("fw_rcv: unknow tcode\n"); 3068 break; 3069 } 3070err: 3071 free(buf, M_DEVBUF); 3072} 3073/* 3074 * Post process for Bus Manager election process. 3075 */ 3076static void 3077fw_try_bmr_callback(struct fw_xfer *xfer) 3078{ 3079 struct fw_pkt *sfp,*rfp; 3080 struct firewire_comm *fc; 3081 3082 if(xfer == NULL) return; 3083 fc = xfer->fc; 3084 if(xfer->resp != 0){ 3085 goto error; 3086 } 3087 3088 if(xfer->send.buf == NULL){ 3089 goto error; 3090 } 3091 sfp = (struct fw_pkt *)xfer->send.buf; 3092 3093 if(xfer->recv.buf == NULL){ 3094 goto error; 3095 } 3096 rfp = (struct fw_pkt *)xfer->recv.buf; 3097 CSRARC(fc, BUS_MGR_ID) 3098 = fc->set_bmr(fc, ntohl(rfp->mode.lres.payload[0]) & 0x3f); 3099 printf("%s: new bus manager %d ", 3100 device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); 3101 if((htonl(rfp->mode.lres.payload[0]) & 0x3f) == fc->nodeid){ 3102 printf("(me)\n"); 3103/* If I am bus manager, optimize gapcount */ 3104 if(fc->max_hop <= MAX_GAPHOP ){ 3105 fw_phy_config(fc, -1, gap_cnt[fc->max_hop]); 3106 } 3107 }else{ 3108 printf("\n"); 3109 } 3110error: 3111 fw_xfer_free(xfer); 3112} 3113/* 3114 * To candidate Bus Manager election process. 3115 */ 3116void fw_try_bmr(void *arg) 3117{ 3118 struct fw_xfer *xfer; 3119 struct firewire_comm *fc = (struct firewire_comm *)arg; 3120 struct fw_pkt *fp; 3121 int err = 0; 3122 3123 xfer = fw_xfer_alloc(); 3124 if(xfer == NULL){ 3125 return; 3126 } 3127 xfer->send.len = 24; 3128 xfer->spd = 0; 3129 xfer->send.buf = malloc(24, M_DEVBUF, M_DONTWAIT); 3130 if(xfer->send.buf == NULL){ 3131 fw_xfer_free( xfer); 3132 return; 3133 } 3134 3135 fc->status = FWBUSMGRELECT; 3136 3137 xfer->send.off = 0; 3138 fp = (struct fw_pkt *)xfer->send.buf; 3139 fp->mode.lreq.dest_hi = htons(0xffff); 3140 fp->mode.lreq.tlrt = 0; 3141 fp->mode.lreq.tcode = FWTCODE_LREQ; 3142 fp->mode.lreq.pri = 0; 3143 fp->mode.lreq.src = 0; 3144 fp->mode.lreq.len = htons(8); 3145 fp->mode.lreq.extcode = htons(FW_LREQ_CMPSWAP); 3146 xfer->dst = FWLOCALBUS | fc->irm; 3147 fp->mode.lreq.dst = htons(xfer->dst); 3148 fp->mode.lreq.dest_lo = htonl(0xf0000000 | BUS_MGR_ID); 3149 fp->mode.lreq.payload[0] = 0x3f; 3150 fp->mode.lreq.payload[1] = fc->nodeid; 3151 xfer->act_type = FWACT_XFER; 3152 xfer->act.hand = fw_try_bmr_callback; 3153 3154 err = fw_asyreq(fc, -1, xfer); 3155 if(err){ 3156 fw_xfer_free( xfer); 3157 return; 3158 } 3159 return; 3160} 3161 3162#ifdef FW_VMACCESS 3163/* 3164 * Software implementation for physical memory block access. 3165 * XXX:Too slow, usef for debug purpose only. 3166 */ 3167static void fw_vmaccess(struct fw_xfer *xfer){ 3168 struct fw_pkt *rfp, *sfp = NULL; 3169 u_int32_t *ld = (u_int32_t *)(xfer->recv.buf + xfer->recv.off); 3170 3171 printf("vmaccess spd:%2x len:%03x %d data:%08x %08x %08x %08x\n", 3172 xfer->spd, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 3173 printf("vmaccess data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 3174 if(xfer->resp != 0){ 3175 fw_xfer_free( xfer); 3176 return; 3177 } 3178 if(xfer->recv.buf == NULL){ 3179 fw_xfer_free( xfer); 3180 return; 3181 } 3182 rfp = (struct fw_pkt *)xfer->recv.buf; 3183 switch(rfp->mode.hdr.tcode){ 3184 /* XXX need fix for 64bit arch */ 3185 case FWTCODE_WREQB: 3186 xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT); 3187 xfer->send.len = 12; 3188 sfp = (struct fw_pkt *)xfer->send.buf; 3189 bcopy(rfp->mode.wreqb.payload, 3190 (caddr_t)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len)); 3191 sfp->mode.wres.tcode = FWTCODE_WRES; 3192 sfp->mode.wres.rtcode = 0; 3193 break; 3194 case FWTCODE_WREQQ: 3195 xfer->send.buf = malloc(12, M_DEVBUF, M_NOWAIT); 3196 xfer->send.len = 12; 3197 sfp->mode.wres.tcode = FWTCODE_WRES; 3198 *((u_int32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data; 3199 sfp->mode.wres.rtcode = 0; 3200 break; 3201 case FWTCODE_RREQB: 3202 xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_DEVBUF, M_NOWAIT); 3203 xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len); 3204 sfp = (struct fw_pkt *)xfer->send.buf; 3205 bcopy((caddr_t)ntohl(rfp->mode.rreqb.dest_lo), 3206 sfp->mode.rresb.payload, (u_int16_t)ntohs(rfp->mode.rreqb.len)); 3207 sfp->mode.rresb.tcode = FWTCODE_RRESB; 3208 sfp->mode.rresb.len = rfp->mode.rreqb.len; 3209 sfp->mode.rresb.rtcode = 0; 3210 sfp->mode.rresb.extcode = 0; 3211 break; 3212 case FWTCODE_RREQQ: 3213 xfer->send.buf = malloc(16, M_DEVBUF, M_NOWAIT); 3214 xfer->send.len = 16; 3215 sfp = (struct fw_pkt *)xfer->send.buf; 3216 sfp->mode.rresq.data = *(u_int32_t *)(ntohl(rfp->mode.rreqq.dest_lo)); 3217 sfp->mode.wres.tcode = FWTCODE_RRESQ; 3218 sfp->mode.rresb.rtcode = 0; 3219 break; 3220 default: 3221 fw_xfer_free( xfer); 3222 return; 3223 } 3224 xfer->send.off = 0; 3225 sfp->mode.hdr.dst = rfp->mode.hdr.src; 3226 xfer->dst = ntohs(rfp->mode.hdr.src); 3227 xfer->act.hand = fw_xfer_free; 3228 xfer->retry_req = fw_asybusy; 3229 3230 sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt; 3231 sfp->mode.hdr.pri = 0; 3232 3233 fw_asyreq(xfer->fc, -1, xfer); 3234/**/ 3235 return; 3236} 3237#endif 3238 3239/* 3240 * CRC16 check-sum for IEEE1394 register blocks. 3241 */ 3242u_int16_t fw_crc16(u_int32_t *ptr, u_int32_t len){ 3243 u_int32_t i, sum, crc = 0; 3244 int shift; 3245 len = (len + 3) & ~3; 3246 for(i = 0 ; i < len ; i+= 4){ 3247 for( shift = 28 ; shift >= 0 ; shift -= 4){ 3248 sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf; 3249 crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum; 3250 } 3251 crc &= 0xffff; 3252 } 3253 return((u_int16_t) crc); 3254} 3255DRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,0,0); 3256MODULE_VERSION(firewire, 1); 3257