1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * dcam_frame.c
  31  *
  32  * dcam1394 driver.  Support for video frame access.
  33  */
  34 
  35 #include <sys/int_limits.h>
  36 #include <sys/types.h>
  37 #include <sys/kmem.h>
  38 #include <sys/cmn_err.h>
  39 #include <sys/1394/targets/dcam1394/dcam.h>
  40 #include <sys/1394/targets/dcam1394/dcam_frame.h>
  41 #include <sys/tnf_probe.h>
  42 #include <sys/dcam/dcam1394_io.h>
  43 
  44 #include <sys/1394/targets/dcam1394/dcam_reg.h>
  45 
  46 static void dcam_free_resources(dcam_state_t *);
  47 
  48 typedef struct dcam_mode_info_s {
  49         int bytes_per_pkt;
  50         int pkts_per_frame;
  51 } dcam_mode_info_t;
  52 
  53 /*
  54  * packets per frame
  55  *
  56  * 30fps
  57  *  mode_0 1/2h, 60q,  240b
  58  *  mode_1 1h,  160q,  640
  59  *  mode_2 2h,  480q, 1920
  60  *  mode_3 2h,  640q, 2560
  61  *  mode_4 2h,  960q, 3840
  62  *  mode_5 2h,  320q, 1280
  63  *
  64  * 15fps
  65  *  mode_0 1/4h, 30q,  120
  66  *  mode_1 1/2h, 80q,  320
  67  *  mode_2 1h,  240q,  960
  68  *  mode_3 1h,  320q, 1280
  69  *  mode_4 1h,  480q, 1920
  70  *  mode_5 1h,  160q,  640
  71  *
  72  * 7.5fps
  73  *  mode_0 1/8h,  15q,  60
  74  *  mode_1 1/4h,  40q, 160
  75  *  mode_2 1/2h, 120q, 480
  76  *  mode_3 1/2h, 160q, 640
  77  *  mode_4 1/2h, 240q, 960
  78  *  mode_5 1/2h,  80q, 320
  79  *
  80  * 3.75fps
  81  *  mode_0 x
  82  *  mode_1 1/8h,  20q,  80
  83  *  mode_2 1/4h,  60q, 240
  84  *  mode_3 1/4h,  80q, 320
  85  *  mode_4 1/4h, 120q, 480
  86  *  mode_5 1/4h,  40q, 160
  87  *
  88  * 60fps
  89  *  mode_5 4H, 640q, 2560
  90  *
  91  */
  92 
  93 /* indexed by vid mode, frame rate */
  94 static int g_bytes_per_packet[6][5] = {
  95 
  96         /* fps:                 3.75    7.5     15      30      60 */
  97         /* vid mode 0 */        -1,     60,     120,    240,    -1,
  98         /* vid mode 1 */        80,     160,    320,    640,    -1,
  99         /* vid mode 2 */        240,    480,    960,    1920,   -1,
 100         /* vid mode 3 */        320,    640,    1280,   2560,   -1,
 101         /* vid mode 4 */        480,    960,    1920,   3840,   -1,
 102         /* vid mode 5 */        160,    320,    640,    1280,   2560
 103 };
 104 
 105 /* indexed by vid mode */
 106 static int g_bytes_per_frame[6] = {
 107     57600,
 108     153600,
 109     460800,
 110     614400,
 111     921600,
 112     307200
 113 };
 114 
 115 
 116 static
 117 void dcam_rsrc_fail(t1394_isoch_single_handle_t t1394_single_hdl,
 118     opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args);
 119 
 120 /*
 121  * dcam1394_ioctl_frame_rcv_start
 122  */
 123 int
 124 dcam1394_ioctl_frame_rcv_start(dcam_state_t *softc_p)
 125 {
 126         if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
 127 
 128                 if (dcam_frame_rcv_init(softc_p, softc_p->cur_vid_mode,
 129                     softc_p->cur_frame_rate, softc_p->cur_ring_buff_capacity)) {
 130 
 131                         dcam_free_resources(softc_p);
 132                         return (1);
 133                 }
 134 
 135                 softc_p->flags |= DCAM1394_FLAG_FRAME_RCV_INIT;
 136         }
 137 
 138         if (dcam_frame_rcv_start(softc_p)) {
 139                 return (1);
 140         }
 141 
 142         return (0);
 143 }
 144 
 145 
 146 /*
 147  * dcam_frame_rcv_init
 148  */
 149 int
 150 dcam_frame_rcv_init(dcam_state_t *softc_p, int vid_mode, int frame_rate,
 151     int ring_buff_capacity)
 152 {
 153         int16_t                 bytes_per_pkt;  /* # pkt bytes + overhead */
 154         int                     bytes_per_frame;
 155         size_t                  frame;
 156         int                     cookie;
 157         int                     failure;
 158         id1394_isoch_dmainfo_t  isoch_args;     /* for alloc isoch call */
 159         ixl1394_command_t       *last_ixlp;     /* last ixl in chain, */
 160                                                 /* used for appending ixls */
 161         ixl1394_command_t       *new_ixl_cmdp;  /* new ixl command */
 162         ixl1394_set_syncwait_t  *new_ixl_sswp;  /* new ixl set syncwait */
 163         ixl1394_xfer_pkt_t      *new_ixl_xfpp;  /* new ixl xfer packet */
 164         ixl1394_xfer_buf_t      *new_ixl_xfbp;  /* new ixl xfer buffer */
 165         ixl1394_callback_t      *new_ixl_cbp;   /* new ixl callback */
 166         ixl1394_jump_t          *new_ixl_jmpp;  /* new ixl jump */
 167         int32_t                 result;         /* errno from alloc_isoch_dma */
 168         buff_info_t             *buff_info_p;
 169         dcam1394_reg_io_t       reg_io;
 170         uint_t                  data;
 171         size_t                  num_bytes, num_bytes_left;
 172         size_t                  num_xfer_cmds, xfer_cmd;
 173         size_t                  max_ixl_buff_size;
 174         uint64_t                ixl_buff_kaddr;
 175         caddr_t                 ixl_buff_vaddr;
 176 
 177         bytes_per_pkt = g_bytes_per_packet[vid_mode][frame_rate];
 178         if (bytes_per_pkt == -1) {
 179                 return (1);
 180         }
 181 
 182         bytes_per_frame = g_bytes_per_frame[vid_mode];
 183 
 184         if ((softc_p->ring_buff_p = ring_buff_create(softc_p,
 185             (size_t)ring_buff_capacity, (size_t)bytes_per_frame)) == NULL) {
 186                 return (1);
 187         }
 188 
 189         softc_p->ring_buff_p->read_ptr_pos[0] = 0;
 190 
 191         /* allocate isoch channel */
 192         softc_p->sii.si_channel_mask = 0xFFFF000000000000;
 193         softc_p->sii.si_bandwidth    = bytes_per_pkt;
 194         softc_p->sii.rsrc_fail_target        = dcam_rsrc_fail;
 195         softc_p->sii.single_evt_arg  = softc_p;
 196         softc_p->sii.si_speed                = softc_p->targetinfo.current_max_speed;
 197 
 198         if (t1394_alloc_isoch_single(softc_p->sl_handle,
 199             &softc_p->sii, 0, &softc_p->sii_output_args, &softc_p->sii_hdl,
 200             &failure) != DDI_SUCCESS) {
 201                 return (1);
 202         }
 203 
 204         /*
 205          * At this point, all buffer memory has been allocated and
 206          * mapped, and is tracked on a linear linked list.  Now need to
 207          * build the IXL.  Done on a frame-by-frame basis.  Could
 208          * theoretically have been done at the same time as the mem alloc
 209          * above, but hey, no need to be so fancy here.
 210          *
 211          * ixl buff size is bound by SHRT_MAX and needs to
 212          * be a multiple of packet size
 213          */
 214         max_ixl_buff_size = (SHRT_MAX / bytes_per_pkt) * bytes_per_pkt;
 215 
 216         /* for each frame build frame's ixl list */
 217         for (frame = 0; frame < softc_p->ring_buff_p->num_buffs; frame++) {
 218 
 219                 buff_info_p = &(softc_p->ring_buff_p->buff_info_array_p[frame]);
 220 
 221                 /*
 222                  * if this is the 1st frame, put a IXL label at the top so a
 223                  * loop can be created later
 224                  */
 225                 if (frame == 0) {
 226                         new_ixl_cmdp = kmem_zalloc(
 227                                         sizeof (ixl1394_label_t), KM_SLEEP);
 228                         softc_p->ixlp = new_ixl_cmdp;
 229 
 230                         new_ixl_cmdp->ixl_opcode = IXL1394_OP_LABEL;
 231 
 232                         last_ixlp = softc_p->ixlp;
 233                 }
 234 
 235                 /* add wait-for-sync IXL command */
 236                 new_ixl_sswp = kmem_zalloc(
 237                                 sizeof (ixl1394_set_syncwait_t), KM_SLEEP);
 238 
 239                 new_ixl_sswp->ixl_opcode = IXL1394_OP_SET_SYNCWAIT;
 240 
 241                 last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_sswp;
 242                 last_ixlp = (ixl1394_command_t *)new_ixl_sswp;
 243 
 244                 /* add in each dma cookie */
 245                 for (cookie = 0; cookie < buff_info_p->dma_cookie_count;
 246                     cookie++) {
 247 
 248                         num_xfer_cmds = min(bytes_per_frame,
 249                             buff_info_p->dma_cookie.dmac_size) /
 250                             max_ixl_buff_size;
 251 
 252                         if (min(bytes_per_frame,
 253                             buff_info_p->dma_cookie.dmac_size) %
 254                             max_ixl_buff_size) {
 255                                 num_xfer_cmds++;
 256                         }
 257 
 258                         num_bytes_left = min(bytes_per_frame,
 259                             buff_info_p->dma_cookie.dmac_size);
 260 
 261                         ixl_buff_kaddr =
 262                             buff_info_p->dma_cookie.dmac_laddress;
 263 
 264                         ixl_buff_vaddr = buff_info_p->kaddr_p;
 265 
 266                         for (xfer_cmd = 0; xfer_cmd < (num_xfer_cmds + 1);
 267                             xfer_cmd++) {
 268                                 num_bytes = min(num_bytes_left,
 269                                     max_ixl_buff_size);
 270 
 271                                 if (xfer_cmd == 0) {
 272                                         new_ixl_xfpp =
 273                                             kmem_zalloc(
 274                                                 sizeof (ixl1394_xfer_pkt_t),
 275                                                 KM_SLEEP);
 276 
 277                                         new_ixl_xfpp->ixl_opcode =
 278                                             IXL1394_OP_RECV_PKT_ST;
 279 
 280                                         new_ixl_xfpp->ixl_buf._dmac_ll =
 281                                             ixl_buff_kaddr;
 282                                         new_ixl_xfpp->size =
 283                                             (uint16_t)bytes_per_pkt;
 284                                         new_ixl_xfpp->mem_bufp =
 285                                             ixl_buff_vaddr;
 286 
 287                                         last_ixlp->next_ixlp =
 288                                             (ixl1394_command_t *)new_ixl_xfpp;
 289                                         last_ixlp =
 290                                             (ixl1394_command_t *)new_ixl_xfpp;
 291 
 292                                         num_bytes_left -= bytes_per_pkt;
 293                                         ixl_buff_kaddr += bytes_per_pkt;
 294                                         ixl_buff_vaddr += bytes_per_pkt;
 295 
 296                                         continue;
 297                                 }
 298 
 299                                 /* allocate & init an IXL transfer command. */
 300                                 new_ixl_xfbp =
 301                                     kmem_zalloc(sizeof (ixl1394_xfer_buf_t),
 302                                             KM_SLEEP);
 303 
 304                                 new_ixl_xfbp->ixl_opcode = IXL1394_OP_RECV_BUF;
 305 
 306                                 new_ixl_xfbp->ixl_buf._dmac_ll =
 307                                     ixl_buff_kaddr;
 308                                 new_ixl_xfbp->size = (uint16_t)num_bytes;
 309                                 new_ixl_xfbp->pkt_size = bytes_per_pkt;
 310                                 new_ixl_xfbp->mem_bufp = ixl_buff_vaddr;
 311 
 312                                 last_ixlp->next_ixlp =
 313                                     (ixl1394_command_t *)new_ixl_xfbp;
 314                                 last_ixlp =
 315                                     (ixl1394_command_t *)new_ixl_xfbp;
 316 
 317                                 num_bytes_left -= num_bytes;
 318                                 ixl_buff_kaddr += num_bytes;
 319                                 ixl_buff_vaddr += num_bytes;
 320                         }
 321 
 322                         if (cookie > 0) {
 323                                 ddi_dma_nextcookie(buff_info_p->dma_handle,
 324                                     &(buff_info_p->dma_cookie));
 325                         }
 326 
 327                 }
 328 
 329                 /*
 330                  * at this point, have finished a frame.  put in a callback
 331                  */
 332                 new_ixl_cbp = kmem_zalloc(
 333                                 sizeof (ixl1394_callback_t), KM_SLEEP);
 334 
 335                 new_ixl_cbp->ixl_opcode      = IXL1394_OP_CALLBACK;
 336 
 337                 new_ixl_cbp->callback = &dcam_frame_is_done;
 338                 new_ixl_cbp->callback_arg = NULL;
 339 
 340                 last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_cbp;
 341                 last_ixlp = (ixl1394_command_t *)new_ixl_cbp;
 342         }
 343 
 344         /*
 345          * for the final touch, put an IXL jump at the end to jump to the
 346          * label at the top
 347          */
 348         new_ixl_jmpp = kmem_zalloc(sizeof (ixl1394_jump_t), KM_SLEEP);
 349 
 350         new_ixl_jmpp->ixl_opcode = IXL1394_OP_JUMP;
 351 
 352         new_ixl_jmpp->label = softc_p->ixlp;
 353 
 354         last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
 355 
 356         /* don't need this, but it's neater */
 357         last_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
 358 
 359         /* call fwim routine to alloc an isoch resource */
 360         isoch_args.ixlp         = softc_p->ixlp;
 361         isoch_args.channel_num  = softc_p->sii_output_args.channel_num;
 362 
 363         /* other misc args.  note speed doesn't matter for isoch receive */
 364         isoch_args.idma_options         = ID1394_LISTEN_PKT_MODE;
 365         isoch_args.default_tag          = 0;
 366         isoch_args.default_sync         = 1;
 367         isoch_args.global_callback_arg  = softc_p;
 368 
 369         /* set the ISO channel number */
 370         data = (softc_p->sii_output_args.channel_num & 0xF) << 28;
 371 
 372         /* set the ISO speed */
 373         data |= (softc_p->targetinfo.current_max_speed << 24);
 374 
 375         reg_io.offs = DCAM1394_REG_OFFS_CUR_ISO_CHANNEL;
 376         reg_io.val  = data;
 377 
 378         if (dcam_reg_write(softc_p, &reg_io)) {
 379                 return (1);
 380         }
 381 
 382         result = 1234;
 383 
 384         if (t1394_alloc_isoch_dma(softc_p->sl_handle, &isoch_args, 0,
 385             &softc_p->isoch_handle, &result) != DDI_SUCCESS) {
 386                 return (1);
 387         }
 388 
 389         return (0);
 390 }
 391 
 392 
 393 /*
 394  * dcam_frame_rcv_fini
 395  */
 396 int
 397 dcam_frame_rcv_fini(dcam_state_t *softc_p)
 398 {
 399         t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
 400 
 401         softc_p->isoch_handle = NULL;
 402 
 403         t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
 404 
 405         return (0);
 406 }
 407 
 408 
 409 /*
 410  * dcam_frame_rcv_start
 411  */
 412 int
 413 dcam_frame_rcv_start(dcam_state_t *softc_p)
 414 {
 415         id1394_isoch_dma_ctrlinfo_t     idma_ctrlinfo; /* currently not used */
 416         int32_t                         result;
 417         dcam1394_reg_io_t               reg_io;
 418 
 419         if ((t1394_start_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle,
 420             &idma_ctrlinfo, 0, &result)) != DDI_SUCCESS) {
 421                 return (1);
 422         }
 423 
 424         reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
 425         reg_io.val  = 0x80000000;
 426 
 427         if (dcam_reg_write(softc_p, &reg_io)) {
 428                 return (1);
 429         }
 430 
 431         softc_p->flags |= DCAM1394_FLAG_FRAME_RCVING;
 432 
 433         return (0);
 434 }
 435 
 436 
 437 /*
 438  * dcam_frame_rcv_stop
 439  */
 440 int
 441 dcam_frame_rcv_stop(dcam_state_t *softc_p)
 442 {
 443         dcam1394_reg_io_t reg_io;
 444 
 445         /* if resources have already been cleared, nothing to do */
 446         if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
 447                 return (0);
 448         }
 449 
 450         reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
 451         reg_io.val  = 0;
 452 
 453         (void) dcam_reg_write(softc_p, &reg_io);
 454 
 455         t1394_stop_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle, 0);
 456         t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
 457         t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
 458 
 459         dcam_free_resources(softc_p);
 460 
 461         return (0);
 462 }
 463 
 464 
 465 void
 466 dcam_free_resources(dcam_state_t *softc_p)
 467 {
 468         ixl1394_command_t *ptr;
 469         ixl1394_command_t *tmp;
 470 
 471         /*
 472          *  The following fixes a memory leak.  See bug #4423667.
 473          *  The original code  only released memory for the first  frame.
 474          */
 475 
 476         /* free ixl opcode resources */
 477         ptr = softc_p->ixlp;
 478 
 479         while (ptr != NULL) {
 480                 tmp = ptr;
 481                 ptr = ptr->next_ixlp;
 482 
 483                 switch (tmp->ixl_opcode) {
 484                         case IXL1394_OP_LABEL:
 485                                 kmem_free(tmp, sizeof (ixl1394_label_t));
 486                         break;
 487 
 488                         case IXL1394_OP_SET_SYNCWAIT:
 489                                 kmem_free(tmp, sizeof (ixl1394_set_syncwait_t));
 490                         break;
 491 
 492                         case IXL1394_OP_RECV_PKT_ST:
 493                                 kmem_free(tmp, sizeof (ixl1394_xfer_pkt_t));
 494                         break;
 495 
 496                         case IXL1394_OP_RECV_BUF:
 497                                 kmem_free(tmp, sizeof (ixl1394_xfer_buf_t));
 498                         break;
 499 
 500                         case IXL1394_OP_CALLBACK:
 501                                 kmem_free(tmp, sizeof (ixl1394_callback_t));
 502                         break;
 503 
 504                         case IXL1394_OP_JUMP:
 505                                 kmem_free(tmp, sizeof (ixl1394_jump_t));
 506                         break;
 507                 }
 508         }
 509 
 510         /*
 511          * free ring buff and indicate that the resources have been cleared
 512          */
 513         ring_buff_free(softc_p, softc_p->ring_buff_p);
 514 
 515         softc_p->flags &= ~DCAM1394_FLAG_FRAME_RCV_INIT;
 516         softc_p->ixlp = NULL;
 517 }
 518 
 519 
 520 /*
 521  * dcam_frame_is_done
 522  *
 523  * This routine is called after DMA engine has stored a single received
 524  * frame in ring buffer position pointed to by write pointer; this
 525  * routine marks the frame's vid mode, timestamp, and sequence number
 526  *
 527  * Store received frame in ring buffer position pointed to by write pointer.
 528  * Increment write pointer.  If write pointer is pointing to the same
 529  * position as read pointer, increment read pointer.
 530  *
 531  * If device driver is processing a user process's read() request
 532  * invalidate the read() request processing operation.
 533  *
 534  */
 535 
 536 /* ARGSUSED */
 537 void
 538 dcam_frame_is_done(void *ssp, ixl1394_callback_t *ixlp)
 539 {
 540         dcam_state_t    *softc_p;
 541         int              num_read_ptrs;
 542         int              read_ptr_id;
 543         int              vid_mode;
 544         size_t           write_ptr_pos;
 545         ring_buff_t     *ring_buff_p;
 546         unsigned int     seq_num;
 547 
 548         /*
 549          * Store received frame in ring buffer position pointed to by
 550          * write pointer (this routine is called after DMA engine has
 551          * stored a single received frame in ring buffer position pointed
 552          * to by write pointer; this routine marks the frame's vid mode,
 553          * timestamp, and sequence number)
 554          */
 555 
 556         if ((softc_p = (dcam_state_t *)ssp) == NULL) {
 557                 return;
 558         }
 559 
 560         if ((ring_buff_p = softc_p->ring_buff_p) == NULL) {
 561                 return;
 562         }
 563 
 564         mutex_enter(&softc_p->dcam_frame_is_done_mutex);
 565 
 566         write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
 567 
 568         /* mark vid mode */
 569         vid_mode =
 570             softc_p->
 571                 param_attr[DCAM1394_PARAM_VID_MODE][DCAM1394_SUBPARAM_NONE];
 572         ring_buff_p->buff_info_array_p[write_ptr_pos].vid_mode = vid_mode;
 573 
 574 
 575         /* update sequence counter overflow in param_status */
 576         if (softc_p->seq_count == 0xffffffff)
 577                 softc_p->param_status |=
 578                     DCAM1394_STATUS_FRAME_SEQ_NUM_COUNT_OVERFLOW;
 579 
 580 
 581         /* mark frame's sequence number */
 582         ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num =
 583             softc_p->seq_count++;
 584 
 585         seq_num = ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num;
 586 
 587 
 588         /* mark frame's timestamp */
 589         ring_buff_p->buff_info_array_p[write_ptr_pos].timestamp = gethrtime();
 590 
 591 
 592         /* increment write pointer */
 593         ring_buff_write_ptr_incr(ring_buff_p);
 594 
 595         num_read_ptrs = 1;
 596 
 597         for (read_ptr_id = 0; read_ptr_id < num_read_ptrs; read_ptr_id++) {
 598 
 599                 /*
 600                  * if write pointer is pointing to the same position as
 601                  * read pointer
 602                  */
 603 
 604                 if ((ring_buff_write_ptr_pos_get(ring_buff_p) ==
 605                     ring_buff_read_ptr_pos_get(ring_buff_p, read_ptr_id)) &&
 606                     (seq_num != 0)) {
 607 
 608                         /* increment read pointer */
 609                         ring_buff_read_ptr_incr(ring_buff_p, read_ptr_id);
 610 
 611                         /*
 612                          * if device driver is processing a user
 613                          * process's read() request
 614                          */
 615                         if (softc_p->reader_flags[read_ptr_id] &
 616                             DCAM1394_FLAG_READ_REQ_PROC) {
 617 
 618                                 /*
 619                                  * invalidate the read() request processing
 620                                  * operation
 621                                  */
 622                                 softc_p->reader_flags[read_ptr_id] |=
 623                                     DCAM1394_FLAG_READ_REQ_INVALID;
 624                         }
 625 
 626                         /* inform user app that we have lost one frame */
 627                         softc_p->param_status |=
 628                             DCAM1394_STATUS_RING_BUFF_LOST_FRAME;
 629                 }
 630         }
 631 
 632         /* inform user app that we have received one frame */
 633         softc_p->param_status |= DCAM1394_STATUS_FRAME_RCV_DONE;
 634 
 635         mutex_exit(&softc_p->dcam_frame_is_done_mutex);
 636 }
 637 
 638 
 639 /* ARGSUSED */
 640 static void
 641 dcam_rsrc_fail(t1394_isoch_single_handle_t t1394_single_hdl,
 642     opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args)
 643 {
 644         cmn_err(CE_NOTE, "dcam_rsrc_fail(): unable to re-alloc resources\n");
 645 }