1 /* 2 * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 /* 8 * fwdv(4) - AV/C DV capture driver for FireWire camcorders 9 * 10 * References: 11 * AV/C General Specification 4.1 (TA Document 2001012) 12 * IEC 61883-1, IEC 61883-2 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/module.h> 18 #include <sys/bus.h> 19 #include <sys/kernel.h> 20 #include <sys/conf.h> 21 #include <sys/malloc.h> 22 #include <sys/lock.h> 23 #include <sys/mutex.h> 24 #include <sys/sysctl.h> 25 #include <sys/taskqueue.h> 26 #include <sys/fcntl.h> 27 #include <sys/poll.h> 28 #include <sys/selinfo.h> 29 #include <sys/uio.h> 30 #include <sys/mbuf.h> 31 32 #include <dev/firewire/firewire.h> 33 #include <dev/firewire/firewirereg.h> 34 #include <dev/firewire/iec13213.h> 35 #include <dev/firewire/iec68113.h> 36 #include <dev/firewire/fwdv.h> 37 #include <dev/firewire/fw_helpers.h> 38 39 static MALLOC_DEFINE(M_FWDV, "fwdv", "AV/C DV over FireWire"); 40 41 static int debug = 0; 42 static int iso_channel = FWDV_DEFAULT_ISO_CH; 43 SYSCTL_DECL(_hw_firewire); 44 static SYSCTL_NODE(_hw_firewire, OID_AUTO, fwdv, CTLFLAG_RD | CTLFLAG_MPSAFE, 45 0, "AV/C DV"); 46 SYSCTL_INT(_hw_firewire_fwdv, OID_AUTO, debug, CTLFLAG_RWTUN, &debug, 0, 47 "fwdv debug level"); 48 SYSCTL_INT(_hw_firewire_fwdv, OID_AUTO, iso_channel, CTLFLAG_RWTUN, 49 &iso_channel, 0, "ISO channel for DV receive"); 50 51 #define FWDV_DEBUG(lev, fmt, ...) \ 52 do { \ 53 if (debug >= (lev)) \ 54 printf("fwdv: " fmt, ## __VA_ARGS__); \ 55 } while (0) 56 57 static int fwdv_probe(device_t); 58 static int fwdv_attach(device_t); 59 static int fwdv_detach(device_t); 60 static void fwdv_probe_task(void *, int); 61 62 static int fwdv_avc_command(struct fwdv_softc *, const uint8_t *, int, 63 uint8_t *, int *); 64 static int fwdv_avc_unit_info(struct fwdv_softc *); 65 static int fwdv_avc_play(struct fwdv_softc *); 66 static int fwdv_avc_stop(struct fwdv_softc *); 67 68 static int fwdv_read_opcr(struct fwdv_softc *, int, uint32_t *); 69 70 static int fwdv_iso_start(struct fwdv_softc *); 71 static void fwdv_iso_stop(struct fwdv_softc *); 72 static void fwdv_iso_input(struct fw_xferq *); 73 74 static void fwdv_fcp_handler(struct fw_xfer *); 75 76 static d_open_t fwdv_cdev_open; 77 static d_close_t fwdv_cdev_close; 78 static d_read_t fwdv_cdev_read; 79 static d_poll_t fwdv_cdev_poll; 80 static d_ioctl_t fwdv_cdev_ioctl; 81 82 static struct cdevsw fwdv_cdevsw = { 83 .d_version = D_VERSION, 84 .d_flags = D_TRACKCLOSE, 85 .d_open = fwdv_cdev_open, 86 .d_close = fwdv_cdev_close, 87 .d_read = fwdv_cdev_read, 88 .d_poll = fwdv_cdev_poll, 89 .d_ioctl = fwdv_cdev_ioctl, 90 .d_name = "fwdv", 91 }; 92 93 static int 94 fwdv_read_quadlet(struct fwdv_softc *sc, uint16_t addr_hi, uint32_t addr_lo, 95 uint32_t *val) 96 { 97 uint16_t dst; 98 uint8_t spd; 99 100 FWDV_LOCK(sc); 101 if (sc->fwdev == NULL) { 102 FWDV_UNLOCK(sc); 103 return (ENXIO); 104 } 105 dst = FWLOCALBUS | sc->fwdev->dst; 106 spd = min(sc->fwdev->speed, FWSPD_S400); 107 FWDV_UNLOCK(sc); 108 109 return (fw_read_quadlet(sc->fd.fc, M_FWDV, dst, spd, 110 addr_hi, addr_lo, val)); 111 } 112 113 static void 114 fwdv_fcp_handler(struct fw_xfer *xfer) 115 { 116 struct fwdv_softc *sc = (struct fwdv_softc *)xfer->sc; 117 struct fw_pkt *fp; 118 uint16_t src_id; 119 int len; 120 121 fp = &xfer->recv.hdr; 122 123 if (xfer->resp != 0) { 124 FWDV_DEBUG(1, "FCP response error: %d\n", xfer->resp); 125 goto done; 126 } 127 128 len = fp->mode.wreqb.len; 129 if (len < 4 || len > FCP_MAX_FRAME_LEN) { 130 FWDV_DEBUG(1, "FCP response bad len: %d\n", len); 131 goto done; 132 } 133 134 if (xfer->recv.pay_len < 4) { 135 FWDV_DEBUG(1, "FCP response short payload: %d\n", 136 xfer->recv.pay_len); 137 goto done; 138 } 139 if (xfer->recv.pay_len < len) 140 len = xfer->recv.pay_len; 141 142 src_id = fp->mode.wreqb.src; 143 FWDV_LOCK(sc); 144 if (sc->fwdev == NULL || 145 (FWLOCALBUS | sc->fwdev->dst) != src_id) { 146 FWDV_UNLOCK(sc); 147 FWDV_DEBUG(2, "FCP response from unknown node 0x%04x\n", 148 src_id); 149 goto done; 150 } 151 152 if (xfer->recv.payload != NULL) { 153 memcpy(sc->fcp_resp, xfer->recv.payload, 154 min(len, FCP_MAX_FRAME_LEN)); 155 sc->fcp_resp_len = len; 156 sc->fcp_resp_ready = 1; 157 wakeup(&sc->fcp_resp_ready); 158 } 159 FWDV_UNLOCK(sc); 160 161 done: 162 STAILQ_INSERT_TAIL(&sc->fcp_bind.xferlist, xfer, link); 163 } 164 165 static int 166 fwdv_avc_command(struct fwdv_softc *sc, const uint8_t *cmd, int cmd_len, 167 uint8_t *resp, int *resp_len) 168 { 169 struct fw_xfer *xfer; 170 struct fw_pkt *fp; 171 uint16_t dst; 172 uint8_t spd; 173 int err, padded_len; 174 175 FWDV_LOCK(sc); 176 while (sc->avc_busy) { 177 if (sc->state == FWDV_STATE_DETACHING) { 178 FWDV_UNLOCK(sc); 179 return (ENXIO); 180 } 181 msleep(&sc->avc_busy, &sc->mtx, PWAIT, "fwdvavc", hz); 182 } 183 sc->avc_busy = 1; 184 185 if (sc->fwdev == NULL) { 186 sc->avc_busy = 0; 187 wakeup(&sc->avc_busy); 188 FWDV_UNLOCK(sc); 189 return (ENXIO); 190 } 191 dst = FWLOCALBUS | sc->fwdev->dst; 192 spd = min(sc->fwdev->speed, FWSPD_S400); 193 FWDV_UNLOCK(sc); 194 195 padded_len = roundup2(cmd_len, 4); 196 197 xfer = fw_xfer_alloc_buf(M_FWDV, padded_len, 0); 198 if (xfer == NULL) { 199 err = ENOMEM; 200 goto done; 201 } 202 203 xfer->fc = sc->fd.fc; 204 xfer->hand = fw_xferwake; 205 206 fp = &xfer->send.hdr; 207 fp->mode.wreqb.tcode = FWTCODE_WREQB; 208 fp->mode.wreqb.dst = dst; 209 fp->mode.wreqb.dest_hi = FCP_COMMAND_ADDR >> 32; 210 fp->mode.wreqb.dest_lo = FCP_COMMAND_ADDR & 0xffffffff; 211 fp->mode.wreqb.len = padded_len; 212 fp->mode.wreqb.extcode = 0; 213 xfer->send.spd = spd; 214 xfer->send.pay_len = padded_len; 215 216 memcpy(xfer->send.payload, cmd, cmd_len); 217 if (padded_len > cmd_len) 218 memset((uint8_t *)xfer->send.payload + cmd_len, 0, 219 padded_len - cmd_len); 220 221 FWDV_LOCK(sc); 222 sc->fcp_resp_ready = 0; 223 sc->fcp_resp_len = 0; 224 FWDV_UNLOCK(sc); 225 226 FWDV_DEBUG(2, "AVC cmd: %02x %02x %02x %02x (len=%d)\n", 227 cmd[0], cmd[1], cmd_len > 2 ? cmd[2] : 0, 228 cmd_len > 3 ? cmd[3] : 0, cmd_len); 229 230 err = fw_xfer_request_wait(xfer->fc, xfer, 2 * hz); 231 if (err != 0) { 232 fw_xfer_free_buf(xfer); 233 goto done; 234 } 235 236 if (xfer->resp != 0 || 237 xfer->recv.hdr.mode.wres.rtcode != FWRCODE_COMPLETE) { 238 FWDV_DEBUG(1, "FCP write failed: resp=%d rtcode=%d\n", 239 xfer->resp, xfer->recv.hdr.mode.wres.rtcode); 240 err = EIO; 241 } 242 fw_xfer_free_buf(xfer); 243 if (err != 0) 244 goto done; 245 246 FWDV_LOCK(sc); 247 for (int interim_retry = 0; interim_retry < 3; interim_retry++) { 248 while (!sc->fcp_resp_ready) { 249 if (sc->state == FWDV_STATE_DETACHING || 250 sc->fwdev == NULL) { 251 err = ENXIO; 252 goto done_locked; 253 } 254 err = msleep(&sc->fcp_resp_ready, &sc->mtx, PCATCH, 255 "fwdvfcp", 3 * hz); 256 if (err) { 257 err = (err == EWOULDBLOCK) ? ETIMEDOUT : err; 258 goto done_locked; 259 } 260 } 261 262 if (sc->fcp_resp_len >= 1 && 263 (sc->fcp_resp[0] >> 4) == AVC_RESP_INTERIM) { 264 FWDV_DEBUG(2, "AVC INTERIM, waiting for final\n"); 265 sc->fcp_resp_ready = 0; 266 if (interim_retry == 2) { 267 FWDV_DEBUG(1, "AVC INTERIM timeout\n"); 268 err = ETIMEDOUT; 269 goto done_locked; 270 } 271 continue; 272 } 273 break; 274 } 275 276 if (resp != NULL && resp_len != NULL) { 277 int copy_len = min(sc->fcp_resp_len, *resp_len); 278 memcpy(resp, sc->fcp_resp, copy_len); 279 *resp_len = copy_len; 280 } 281 FWDV_UNLOCK(sc); 282 283 FWDV_DEBUG(2, "AVC resp: %02x %02x %02x %02x (len=%d)\n", 284 sc->fcp_resp[0], sc->fcp_resp[1], 285 sc->fcp_resp_len > 2 ? sc->fcp_resp[2] : 0, 286 sc->fcp_resp_len > 3 ? sc->fcp_resp[3] : 0, 287 sc->fcp_resp_len); 288 289 FWDV_LOCK(sc); 290 sc->avc_busy = 0; 291 wakeup(&sc->avc_busy); 292 FWDV_UNLOCK(sc); 293 294 return (0); 295 296 done_locked: 297 sc->avc_busy = 0; 298 wakeup(&sc->avc_busy); 299 FWDV_UNLOCK(sc); 300 return (err); 301 302 done: 303 FWDV_LOCK(sc); 304 sc->avc_busy = 0; 305 wakeup(&sc->avc_busy); 306 FWDV_UNLOCK(sc); 307 return (err); 308 } 309 310 static int 311 fwdv_avc_unit_info(struct fwdv_softc *sc) 312 { 313 uint8_t cmd[8], resp[8]; 314 int resp_len, err; 315 316 cmd[0] = (AVC_CTYPE_STATUS << 4) | 0; 317 cmd[1] = AVC_ADDR_UNIT; 318 cmd[2] = AVC_OP_UNIT_INFO; 319 cmd[3] = 0xff; 320 cmd[4] = 0xff; 321 cmd[5] = 0xff; 322 cmd[6] = 0xff; 323 cmd[7] = 0xff; 324 325 resp_len = sizeof(resp); 326 err = fwdv_avc_command(sc, cmd, 8, resp, &resp_len); 327 if (err) 328 return (err); 329 330 if (resp_len < 8) { 331 device_printf(sc->fd.dev, 332 "UNIT INFO: short response (%d bytes)\n", resp_len); 333 return (EIO); 334 } 335 if ((resp[0] >> 4) != AVC_RESP_STABLE) { 336 device_printf(sc->fd.dev, 337 "UNIT INFO: unexpected response 0x%02x\n", resp[0]); 338 return (EIO); 339 } 340 341 FWDV_DEBUG(1, "UNIT INFO: unit_type=0x%02x, company_id=%02x%02x%02x\n", 342 resp[4] >> 3, resp[5], resp[6], resp[7]); 343 344 return (0); 345 } 346 347 static int 348 fwdv_avc_tape_control(struct fwdv_softc *sc, uint8_t opcode, uint8_t operand, 349 const char *name) 350 { 351 uint8_t cmd[4], resp[4]; 352 int resp_len, err; 353 354 cmd[0] = (AVC_CTYPE_CONTROL << 4) | 0; 355 cmd[1] = AVC_ADDR_TAPE0; 356 cmd[2] = opcode; 357 cmd[3] = operand; 358 359 resp_len = sizeof(resp); 360 err = fwdv_avc_command(sc, cmd, 4, resp, &resp_len); 361 if (err) 362 return (err); 363 if (resp_len < 1) 364 return (EIO); 365 366 if ((resp[0] >> 4) != AVC_RESP_ACCEPTED) { 367 device_printf(sc->fd.dev, "%s rejected: 0x%02x\n", 368 name, resp[0]); 369 return (EIO); 370 } 371 372 FWDV_DEBUG(1, "%s accepted\n", name); 373 return (0); 374 } 375 376 static int 377 fwdv_avc_play(struct fwdv_softc *sc) 378 { 379 380 return (fwdv_avc_tape_control(sc, AVC_OP_PLAY, AVC_PLAY_FWD, "PLAY")); 381 } 382 383 static int 384 fwdv_avc_stop(struct fwdv_softc *sc) 385 { 386 387 return (fwdv_avc_tape_control(sc, AVC_OP_WIND, AVC_WIND_STOP, "STOP")); 388 } 389 390 static int 391 fwdv_read_opcr(struct fwdv_softc *sc, int plug, uint32_t *val) 392 { 393 394 return (fwdv_read_quadlet(sc, CSR_BASE_HI, 395 CSR_BASE_LO | PCR_oPCR(plug), val)); 396 } 397 398 static int 399 fwdv_iso_start(struct fwdv_softc *sc) 400 { 401 struct firewire_comm *fc = sc->fd.fc; 402 struct fw_xferq *xferq; 403 uint32_t opcr_val; 404 int dma_ch, err; 405 uint8_t ch; 406 407 mtx_assert(&sc->mtx, MA_NOTOWNED); 408 409 FWDV_LOCK(sc); 410 if (sc->dma_ch >= 0 || sc->state == FWDV_STATE_STREAMING) { 411 FWDV_UNLOCK(sc); 412 return (0); 413 } 414 if (sc->state == FWDV_STATE_DETACHING) { 415 FWDV_UNLOCK(sc); 416 return (ENXIO); 417 } 418 FWDV_UNLOCK(sc); 419 420 ch = (uint8_t)(iso_channel & ISO_CHANNEL_MASK); 421 err = fwdv_read_opcr(sc, 0, &opcr_val); 422 if (err == 0 && (opcr_val & OPCR_ONLINE)) { 423 uint8_t dev_ch = (opcr_val & OPCR_CHANNEL_MASK) >> 424 OPCR_CHANNEL_SHIFT; 425 if (dev_ch < ISO_CHANNEL_MAX) { 426 ch = dev_ch; 427 FWDV_DEBUG(1, "oPCR[0] channel=%d\n", ch); 428 } 429 } 430 431 dma_ch = fw_open_isodma(fc, 0); 432 if (dma_ch < 0) { 433 device_printf(sc->fd.dev, "no IR DMA channel available\n"); 434 return (EBUSY); 435 } 436 437 FWDV_LOCK(sc); 438 if (sc->dma_ch >= 0) { 439 FWDV_UNLOCK(sc); 440 fc->ir[dma_ch]->flag &= ~FWXFERQ_OPEN; 441 return (0); 442 } 443 FWDV_UNLOCK(sc); 444 445 xferq = fc->ir[dma_ch]; 446 xferq->flag |= FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_STREAM; 447 sc->iso_channel = ch; 448 xferq->flag &= ~FWXFERQ_CHTAGMASK; 449 xferq->flag |= (ch & ISO_CHANNEL_MASK) | (1 << 6); 450 451 xferq->sc = (caddr_t)sc; 452 xferq->hand = fwdv_iso_input; 453 xferq->bnchunk = FWDV_ISO_NCHUNK; 454 xferq->bnpacket = 1; 455 xferq->psize = FWDV_ISO_PKTSIZE; 456 xferq->queued = 0; 457 xferq->buf = NULL; 458 459 xferq->bulkxfer = malloc(sizeof(struct fw_bulkxfer) * xferq->bnchunk, 460 M_FWDV, M_WAITOK | M_ZERO); 461 462 fw_iso_init_chunks(xferq); 463 464 sc->frame_size = FWDV_MAX_FRAME_SIZE; 465 sc->frame_buf = malloc(sc->frame_size, M_FWDV, M_WAITOK | M_ZERO); 466 sc->read_buf = malloc(sc->frame_size, M_FWDV, M_WAITOK | M_ZERO); 467 sc->frame_offset = 0; 468 sc->frame_ready = 0; 469 sc->frame_dropped = 0; 470 sc->frame_count = 0; 471 sc->dv_detected = 0; 472 473 err = fc->irx_enable(fc, dma_ch); 474 if (err) { 475 device_printf(sc->fd.dev, "failed to start IR DMA: %d\n", err); 476 goto fail; 477 } 478 479 FWDV_LOCK(sc); 480 if (sc->state == FWDV_STATE_DETACHING || sc->fwdev == NULL) { 481 FWDV_UNLOCK(sc); 482 fc->irx_disable(fc, dma_ch); 483 err = ENXIO; 484 goto fail; 485 } 486 sc->dma_ch = dma_ch; 487 sc->state = FWDV_STATE_STREAMING; 488 wakeup(sc); 489 FWDV_UNLOCK(sc); 490 491 return (0); 492 493 fail: 494 fw_iso_free_chunks(xferq, M_FWDV); 495 xferq->flag &= ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 496 FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 497 xferq->hand = NULL; 498 499 free(sc->frame_buf, M_FWDV); 500 free(sc->read_buf, M_FWDV); 501 sc->frame_buf = NULL; 502 sc->read_buf = NULL; 503 sc->dma_ch = -1; 504 505 return (err); 506 } 507 508 static void 509 fwdv_iso_stop(struct fwdv_softc *sc) 510 { 511 struct firewire_comm *fc = sc->fd.fc; 512 struct fw_xferq *xferq; 513 int dma_ch; 514 515 FWDV_LOCK(sc); 516 dma_ch = sc->dma_ch; 517 if (dma_ch < 0) { 518 FWDV_UNLOCK(sc); 519 return; 520 } 521 sc->dma_ch = -1; 522 FWDV_UNLOCK(sc); 523 524 xferq = fc->ir[dma_ch]; 525 526 if (xferq->flag & FWXFERQ_RUNNING) 527 fc->irx_disable(fc, dma_ch); 528 529 FWDV_LOCK(sc); 530 fw_iso_wait_inactive_locked(&sc->mtx, &sc->iso_active, "fwdvis"); 531 sc->frame_ready = 0; 532 while (sc->read_in_progress) 533 msleep(&sc->read_in_progress, &sc->mtx, PWAIT, "fwdvst", hz); 534 FWDV_UNLOCK(sc); 535 536 xferq->flag &= ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 537 FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 538 xferq->hand = NULL; 539 540 fw_iso_free_chunks(xferq, M_FWDV); 541 542 free(sc->frame_buf, M_FWDV); 543 free(sc->read_buf, M_FWDV); 544 sc->frame_buf = NULL; 545 sc->read_buf = NULL; 546 } 547 548 static void 549 fwdv_iso_input(struct fw_xferq *xferq) 550 { 551 struct fwdv_softc *sc = (struct fwdv_softc *)xferq->sc; 552 struct fw_bulkxfer *sxfer; 553 struct fw_pkt *fp; 554 struct ciphdr *ciph; 555 struct dvdbc *dv; 556 struct mbuf *m; 557 uint8_t *ptr, *end; 558 uint32_t plen; 559 uint8_t *tmp; 560 int dma_ch; 561 562 FWDV_LOCK(sc); 563 dma_ch = sc->dma_ch; 564 if (dma_ch < 0 || sc->frame_buf == NULL) { 565 FWDV_UNLOCK(sc); 566 return; 567 } 568 sc->iso_active = 1; 569 FWDV_UNLOCK(sc); 570 571 while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { 572 STAILQ_REMOVE_HEAD(&xferq->stvalid, link); 573 574 m = fw_iso_dequeue(xferq, sxfer, sc->fd.fc); 575 if (m == NULL) 576 continue; 577 578 fp = mtod(m, struct fw_pkt *); 579 plen = fp->mode.stream.len; 580 if (plen <= sizeof(struct ciphdr)) { 581 m_freem(m); 582 continue; 583 } 584 585 if (m->m_len < (int)(4 + sizeof(struct ciphdr))) { 586 m_freem(m); 587 continue; 588 } 589 590 ciph = (struct ciphdr *)(mtod(m, uint8_t *) + 4); 591 592 if (ciph->fmt != CIP_FMT_DVCR) { 593 m_freem(m); 594 continue; 595 } 596 597 if (!sc->dv_detected) { 598 sc->dv_system = ciph->fdf.dv.fs; 599 sc->dv_detected = 1; 600 if (ciph->fdf.dv.stype == CIP_STYPE_HD) { 601 sc->frame_size = DV_DVCPRO_HD_FRAME; 602 } else { 603 sc->frame_size = sc->dv_system ? 604 DV_SD_PAL_FRAME : DV_SD_NTSC_FRAME; 605 } 606 printf("fwdv: DV stype=%d %s detected (frame=%u)\n", 607 ciph->fdf.dv.stype, 608 sc->dv_system ? "PAL" : "NTSC", 609 sc->frame_size); 610 } 611 612 ptr = (uint8_t *)(ciph + 1); 613 end = mtod(m, uint8_t *) + 4 + plen; 614 if (end > mtod(m, uint8_t *) + m->m_len) 615 end = mtod(m, uint8_t *) + m->m_len; 616 617 while (ptr + DV_DIF_BLOCK_SIZE <= end) { 618 dv = (struct dvdbc *)ptr; 619 620 if (dv->sct == DV_SCT_HEADER && dv->dseq == 0) { 621 if (sc->frame_offset > 0) { 622 if (sc->frame_offset >= sc->frame_size) { 623 FWDV_LOCK(sc); 624 if (sc->read_in_progress) { 625 sc->frame_dropped++; 626 } else { 627 if (sc->frame_ready) 628 sc->frame_dropped++; 629 tmp = sc->read_buf; 630 sc->read_buf = 631 sc->frame_buf; 632 sc->frame_buf = tmp; 633 sc->frame_ready = 1; 634 sc->frame_count++; 635 wakeup(sc); 636 selwakeup(&sc->rsel); 637 } 638 FWDV_UNLOCK(sc); 639 } else { 640 sc->frame_dropped++; 641 } 642 } 643 sc->frame_offset = 0; 644 645 if (sc->dv_system == 1 && 646 (dv->payload[0] & DV_DSF_12) == 0) 647 dv->payload[0] |= DV_DSF_12; 648 } 649 650 if (sc->frame_offset + DV_DIF_BLOCK_SIZE <= 651 sc->frame_size) { 652 memcpy(sc->frame_buf + sc->frame_offset, 653 ptr, DV_DIF_BLOCK_SIZE); 654 sc->frame_offset += DV_DIF_BLOCK_SIZE; 655 } else { 656 sc->frame_dropped++; 657 sc->frame_offset = 0; 658 } 659 660 ptr += DV_DIF_BLOCK_SIZE; 661 } 662 663 m_freem(m); 664 } 665 666 fw_iso_rearm_done(xferq, sc->fd.fc, &sc->mtx, &sc->iso_active, 667 &sc->dma_ch, dma_ch); 668 } 669 670 static int 671 fwdv_cdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 672 { 673 struct fwdv_softc *sc = dev->si_drv1; 674 int err = 0; 675 676 FWDV_LOCK(sc); 677 if (sc->state == FWDV_STATE_DETACHING) { 678 FWDV_UNLOCK(sc); 679 return (ENXIO); 680 } 681 while (sc->state == FWDV_STATE_STARTING) { 682 err = msleep(sc, &sc->mtx, PCATCH, "fwdvst", 5 * hz); 683 if (err) { 684 FWDV_UNLOCK(sc); 685 return (err == EWOULDBLOCK ? EAGAIN : err); 686 } 687 } 688 if (sc->state == FWDV_STATE_DETACHING) { 689 FWDV_UNLOCK(sc); 690 return (ENXIO); 691 } 692 if (sc->state != FWDV_STATE_PROBED && 693 sc->state != FWDV_STATE_STREAMING) { 694 FWDV_UNLOCK(sc); 695 return (EAGAIN); 696 } 697 698 sc->open_count++; 699 if (sc->open_count == 1 && sc->state == FWDV_STATE_PROBED) { 700 sc->state = FWDV_STATE_STARTING; 701 FWDV_UNLOCK(sc); 702 err = fwdv_iso_start(sc); 703 if (err) { 704 FWDV_LOCK(sc); 705 sc->open_count--; 706 if (sc->state == FWDV_STATE_STARTING) { 707 sc->state = FWDV_STATE_PROBED; 708 wakeup(sc); 709 } 710 FWDV_UNLOCK(sc); 711 } 712 } else { 713 FWDV_UNLOCK(sc); 714 } 715 return (err); 716 } 717 718 static int 719 fwdv_cdev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 720 { 721 struct fwdv_softc *sc = dev->si_drv1; 722 723 FWDV_LOCK(sc); 724 sc->open_count--; 725 if (sc->open_count <= 0) { 726 sc->open_count = 0; 727 if (sc->state == FWDV_STATE_STREAMING) { 728 FWDV_UNLOCK(sc); 729 fwdv_iso_stop(sc); 730 FWDV_LOCK(sc); 731 if (sc->state != FWDV_STATE_DETACHING) 732 sc->state = FWDV_STATE_PROBED; 733 } 734 } 735 FWDV_UNLOCK(sc); 736 return (0); 737 } 738 739 static int 740 fwdv_cdev_read(struct cdev *dev, struct uio *uio, int ioflag) 741 { 742 struct fwdv_softc *sc = dev->si_drv1; 743 int err; 744 745 FWDV_LOCK(sc); 746 while (!sc->frame_ready) { 747 if (sc->state != FWDV_STATE_STREAMING) { 748 FWDV_UNLOCK(sc); 749 return (ENXIO); 750 } 751 if (ioflag & FNONBLOCK) { 752 FWDV_UNLOCK(sc); 753 return (EAGAIN); 754 } 755 err = msleep(sc, &sc->mtx, PCATCH, "fwdvrd", 0); 756 if (err) { 757 FWDV_UNLOCK(sc); 758 return (err); 759 } 760 } 761 762 sc->read_in_progress = 1; 763 sc->frame_ready = 0; 764 FWDV_UNLOCK(sc); 765 766 err = uiomove(sc->read_buf, min(uio->uio_resid, sc->frame_size), 767 uio); 768 769 FWDV_LOCK(sc); 770 sc->read_in_progress = 0; 771 wakeup(&sc->read_in_progress); 772 FWDV_UNLOCK(sc); 773 774 return (err); 775 } 776 777 static int 778 fwdv_cdev_poll(struct cdev *dev, int events, struct thread *td) 779 { 780 struct fwdv_softc *sc = dev->si_drv1; 781 int revents = 0; 782 783 FWDV_LOCK(sc); 784 if (sc->state != FWDV_STATE_STREAMING) { 785 revents = POLLHUP; 786 } else if (events & (POLLIN | POLLRDNORM)) { 787 if (sc->frame_ready) 788 revents |= events & (POLLIN | POLLRDNORM); 789 else 790 selrecord(td, &sc->rsel); 791 } 792 FWDV_UNLOCK(sc); 793 794 return (revents); 795 } 796 797 static int 798 fwdv_cdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 799 struct thread *td) 800 { 801 struct fwdv_softc *sc = dev->si_drv1; 802 struct fwdv_info *info; 803 804 switch (cmd) { 805 case FWDV_GINFO: 806 info = (struct fwdv_info *)data; 807 memset(info, 0, sizeof(*info)); 808 FWDV_LOCK(sc); 809 info->state = sc->state; 810 info->iso_channel = sc->iso_channel; 811 info->dv_system = sc->dv_detected ? sc->dv_system : 0xff; 812 info->frame_size = sc->frame_size; 813 info->frame_count = sc->frame_count; 814 info->frame_dropped = sc->frame_dropped; 815 info->eui_hi = sc->eui_hi; 816 info->eui_lo = sc->eui_lo; 817 strlcpy(info->vendor, sc->vendor, sizeof(info->vendor)); 818 strlcpy(info->model, sc->model, sizeof(info->model)); 819 FWDV_UNLOCK(sc); 820 return (0); 821 822 case FWDV_PLAY: 823 return (fwdv_avc_play(sc)); 824 825 case FWDV_STOP: 826 return (fwdv_avc_stop(sc)); 827 828 case FWDV_FFWD: 829 return (fwdv_avc_tape_control(sc, AVC_OP_WIND, 830 AVC_WIND_FFWD, "FFWD")); 831 832 case FWDV_REW: 833 return (fwdv_avc_tape_control(sc, AVC_OP_WIND, 834 AVC_WIND_REW, "REW")); 835 836 default: 837 return (ENOTTY); 838 } 839 } 840 841 static void 842 fwdv_parse_identity(struct fwdv_softc *sc) 843 { 844 struct fw_device *fwdev = sc->fwdev; 845 struct crom_context cc; 846 847 sc->vendor[0] = '\0'; 848 sc->model[0] = '\0'; 849 850 if (fwdev == NULL) 851 return; 852 853 crom_init_context(&cc, fwdev->csrrom); 854 855 crom_search_key(&cc, CSRKEY_VENDOR); 856 crom_next(&cc); 857 crom_parse_text(&cc, sc->vendor, sizeof(sc->vendor)); 858 859 crom_search_key(&cc, CSRKEY_MODEL); 860 crom_next(&cc); 861 crom_parse_text(&cc, sc->model, sizeof(sc->model)); 862 863 } 864 865 866 static void 867 fwdv_probe_task(void *arg, int pending __unused) 868 { 869 struct fwdv_softc *sc = (struct fwdv_softc *)arg; 870 int err, restart; 871 872 FWDV_LOCK(sc); 873 if (sc->state == FWDV_STATE_DETACHING || sc->fwdev == NULL) { 874 FWDV_UNLOCK(sc); 875 return; 876 } 877 FWDV_UNLOCK(sc); 878 879 fwdv_parse_identity(sc); 880 err = fwdv_avc_unit_info(sc); 881 if (err) { 882 device_printf(sc->fd.dev, 883 "UNIT INFO failed (%d), device may not be ready\n", err); 884 } 885 886 FWDV_LOCK(sc); 887 if (sc->state == FWDV_STATE_DETACHING || sc->fwdev == NULL) { 888 FWDV_UNLOCK(sc); 889 return; 890 } 891 sc->state = FWDV_STATE_PROBED; 892 restart = (sc->open_count > 0); 893 FWDV_UNLOCK(sc); 894 895 if (restart) 896 fwdv_iso_start(sc); 897 } 898 899 900 901 static int 902 fwdv_probe(device_t dev) 903 { 904 struct fw_unit *unit; 905 906 unit = fw_get_unit(dev); 907 if (unit == NULL) 908 return (ENXIO); 909 910 if (unit->spec_id != CSRVAL_1394TA) 911 return (ENXIO); 912 if (unit->sw_version != CSR_PROTAVC) 913 return (ENXIO); 914 915 device_set_desc(dev, "AV/C DV Capture over FireWire"); 916 return (BUS_PROBE_DEFAULT); 917 } 918 919 static int 920 fwdv_attach(device_t dev) 921 { 922 struct fwdv_softc *sc; 923 struct firewire_comm *fc; 924 struct fw_unit *unit; 925 struct fw_device *fwdev; 926 int err; 927 928 unit = fw_get_unit(dev); 929 if (unit == NULL) 930 return (ENXIO); 931 fwdev = unit->fwdev; 932 if (fwdev == NULL) 933 return (ENXIO); 934 935 sc = device_get_softc(dev); 936 sc->fd.dev = dev; 937 sc->fd.fc = fw_get_comm(dev); 938 fc = sc->fd.fc; 939 mtx_init(&sc->mtx, "fwdv", NULL, MTX_DEF); 940 941 sc->fwdev = fwdev; 942 sc->eui_hi = fwdev->eui.hi; 943 sc->eui_lo = fwdev->eui.lo; 944 sc->state = FWDV_STATE_IDLE; 945 sc->dma_ch = -1; 946 sc->open_count = 0; 947 sc->dv_system = 0; 948 sc->dv_detected = 0; 949 sc->avc_busy = 0; 950 sc->iso_active = 0; 951 knlist_init_mtx(&sc->rsel.si_note, &sc->mtx); 952 TASK_INIT(&sc->probe_task, 0, fwdv_probe_task, sc); 953 954 sc->cdev = make_dev(&fwdv_cdevsw, device_get_unit(dev), 955 UID_ROOT, GID_OPERATOR, 0660, "fwdv%d", device_get_unit(dev)); 956 if (sc->cdev == NULL) { 957 device_printf(dev, "make_dev failed\n"); 958 knlist_destroy(&sc->rsel.si_note); 959 mtx_destroy(&sc->mtx); 960 return (ENXIO); 961 } 962 sc->cdev->si_drv1 = sc; 963 964 STAILQ_INIT(&sc->fcp_bind.xferlist); 965 sc->fcp_bind.start = FCP_RESPONSE_ADDR; 966 sc->fcp_bind.end = FCP_RESPONSE_ADDR + FCP_MAX_FRAME_LEN - 1; 967 sc->fcp_bind.sc = sc; 968 if (fw_xferlist_add(&sc->fcp_bind.xferlist, M_FWDV, 969 0, FCP_MAX_FRAME_LEN, FWDV_FCP_XFERS, fc, sc, 970 fwdv_fcp_handler) < FWDV_FCP_XFERS) { 971 device_printf(dev, "fw_xferlist_add: allocation failed\n"); 972 fw_xferlist_remove(&sc->fcp_bind.xferlist); 973 destroy_dev(sc->cdev); 974 knlist_destroy(&sc->rsel.si_note); 975 mtx_destroy(&sc->mtx); 976 return (ENOMEM); 977 } 978 979 err = fw_bindadd(fc, &sc->fcp_bind); 980 if (err) { 981 device_printf(dev, "fw_bindadd failed: %d\n", err); 982 fw_xferlist_remove(&sc->fcp_bind.xferlist); 983 destroy_dev(sc->cdev); 984 knlist_destroy(&sc->rsel.si_note); 985 mtx_destroy(&sc->mtx); 986 return (err); 987 } 988 989 if (taskqueue_enqueue(taskqueue_thread, &sc->probe_task) != 0) 990 device_printf(dev, "probe task enqueue failed\n"); 991 992 return (0); 993 } 994 995 static int 996 fwdv_detach(device_t dev) 997 { 998 struct fwdv_softc *sc; 999 1000 sc = device_get_softc(dev); 1001 1002 FWDV_LOCK(sc); 1003 sc->state = FWDV_STATE_DETACHING; 1004 wakeup(sc); 1005 wakeup(&sc->fcp_resp_ready); 1006 wakeup(&sc->avc_busy); 1007 FWDV_UNLOCK(sc); 1008 1009 taskqueue_drain(taskqueue_thread, &sc->probe_task); 1010 fwdv_iso_stop(sc); 1011 1012 fw_bindremove(sc->fd.fc, &sc->fcp_bind); 1013 fw_xferlist_remove(&sc->fcp_bind.xferlist); 1014 1015 if (sc->cdev != NULL) 1016 destroy_dev(sc->cdev); 1017 1018 seldrain(&sc->rsel); 1019 knlist_destroy(&sc->rsel.si_note); 1020 mtx_destroy(&sc->mtx); 1021 1022 return (0); 1023 } 1024 1025 static device_method_t fwdv_methods[] = { 1026 DEVMETHOD(device_probe, fwdv_probe), 1027 DEVMETHOD(device_attach, fwdv_attach), 1028 DEVMETHOD(device_detach, fwdv_detach), 1029 DEVMETHOD_END 1030 }; 1031 1032 static driver_t fwdv_driver = { 1033 "fwdv", 1034 fwdv_methods, 1035 sizeof(struct fwdv_softc) 1036 }; 1037 1038 DRIVER_MODULE(fwdv, firewire, fwdv_driver, NULL, NULL); 1039 MODULE_VERSION(fwdv, 1); 1040 MODULE_DEPEND(fwdv, firewire, 1, 1, 1); 1041