dcam_frame.c revision 8eea8e29cc4374d1ee24c25a07f45af132db3499
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*
* dcam1394 driver. Support for video frame access.
*/
#include <sys/int_limits.h>
#include <sys/tnf_probe.h>
static void dcam_free_resources(dcam_state_t *);
typedef struct dcam_mode_info_s {
int bytes_per_pkt;
int pkts_per_frame;
/*
* packets per frame
*
* 30fps
* mode_0 1/2h, 60q, 240b
* mode_1 1h, 160q, 640
* mode_2 2h, 480q, 1920
* mode_3 2h, 640q, 2560
* mode_4 2h, 960q, 3840
* mode_5 2h, 320q, 1280
*
* 15fps
* mode_0 1/4h, 30q, 120
* mode_1 1/2h, 80q, 320
* mode_2 1h, 240q, 960
* mode_3 1h, 320q, 1280
* mode_4 1h, 480q, 1920
* mode_5 1h, 160q, 640
*
* 7.5fps
* mode_0 1/8h, 15q, 60
* mode_1 1/4h, 40q, 160
* mode_2 1/2h, 120q, 480
* mode_3 1/2h, 160q, 640
* mode_4 1/2h, 240q, 960
* mode_5 1/2h, 80q, 320
*
* 3.75fps
* mode_0 x
* mode_1 1/8h, 20q, 80
* mode_2 1/4h, 60q, 240
* mode_3 1/4h, 80q, 320
* mode_4 1/4h, 120q, 480
* mode_5 1/4h, 40q, 160
*
* 60fps
* mode_5 4H, 640q, 2560
*
*/
/* indexed by vid mode, frame rate */
/* fps: 3.75 7.5 15 30 60 */
/* vid mode 0 */ -1, 60, 120, 240, -1,
/* vid mode 1 */ 80, 160, 320, 640, -1,
/* vid mode 2 */ 240, 480, 960, 1920, -1,
/* vid mode 3 */ 320, 640, 1280, 2560, -1,
/* vid mode 4 */ 480, 960, 1920, 3840, -1,
/* vid mode 5 */ 160, 320, 640, 1280, 2560
};
/* indexed by vid mode */
static int g_bytes_per_frame[6] = {
57600,
153600,
460800,
614400,
921600,
307200
};
static
/*
* dcam1394_ioctl_frame_rcv_start
*/
int
{
return (1);
}
}
if (dcam_frame_rcv_start(softc_p)) {
return (1);
}
return (0);
}
/*
* dcam_frame_rcv_init
*/
int
int ring_buff_capacity)
{
int bytes_per_frame;
int cookie;
int failure;
/* used for appending ixls */
if (bytes_per_pkt == -1) {
return (1);
}
return (1);
}
/* allocate isoch channel */
&failure) != DDI_SUCCESS) {
return (1);
}
/*
* At this point, all buffer memory has been allocated and
* mapped, and is tracked on a linear linked list. Now need to
* build the IXL. Done on a frame-by-frame basis. Could
* theoretically have been done at the same time as the mem alloc
* above, but hey, no need to be so fancy here.
*
* ixl buff size is bound by SHRT_MAX and needs to
* be a multiple of packet size
*/
/* for each frame build frame's ixl list */
/*
* if this is the 1st frame, put a IXL label at the top so a
* loop can be created later
*/
if (frame == 0) {
sizeof (ixl1394_label_t), KM_SLEEP);
}
/* add wait-for-sync IXL command */
sizeof (ixl1394_set_syncwait_t), KM_SLEEP);
/* add in each dma cookie */
cookie++) {
if (min(bytes_per_frame,
}
xfer_cmd++) {
if (xfer_cmd == 0) {
sizeof (ixl1394_xfer_pkt_t),
KM_SLEEP);
new_ixl_xfpp->size =
continue;
}
/* allocate & init an IXL transfer command. */
kmem_zalloc(sizeof (ixl1394_xfer_buf_t),
KM_SLEEP);
}
if (cookie > 0) {
&(buff_info_p->dma_cookie));
}
}
/*
* at this point, have finished a frame. put in a callback
*/
sizeof (ixl1394_callback_t), KM_SLEEP);
}
/*
* for the final touch, put an IXL jump at the end to jump to the
* label at the top
*/
/* don't need this, but it's neater */
/* call fwim routine to alloc an isoch resource */
/* other misc args. note speed doesn't matter for isoch receive */
isoch_args.default_tag = 0;
/* set the ISO channel number */
/* set the ISO speed */
return (1);
}
result = 1234;
return (1);
}
return (0);
}
/*
* dcam_frame_rcv_fini
*/
int
{
return (0);
}
/*
* dcam_frame_rcv_start
*/
int
{
return (1);
}
return (1);
}
return (0);
}
/*
* dcam_frame_rcv_stop
*/
int
{
/* if resources have already been cleared, nothing to do */
return (0);
}
return (0);
}
void
{
/*
* The following fixes a memory leak. See bug #4423667.
* The original code only released memory for the first frame.
*/
/* free ixl opcode resources */
switch (tmp->ixl_opcode) {
case IXL1394_OP_LABEL:
break;
case IXL1394_OP_SET_SYNCWAIT:
break;
case IXL1394_OP_RECV_PKT_ST:
break;
case IXL1394_OP_RECV_BUF:
break;
case IXL1394_OP_CALLBACK:
break;
case IXL1394_OP_JUMP:
break;
}
}
/*
* free ring buff and indicate that the resources have been cleared
*/
}
/*
* dcam_frame_is_done
*
* This routine is called after DMA engine has stored a single received
* frame in ring buffer position pointed to by write pointer; this
* routine marks the frame's vid mode, timestamp, and sequence number
*
* Store received frame in ring buffer position pointed to by write pointer.
* Increment write pointer. If write pointer is pointing to the same
* position as read pointer, increment read pointer.
*
* If device driver is processing a user process's read() request
* invalidate the read() request processing operation.
*
*/
/* ARGSUSED */
void
{
int num_read_ptrs;
int read_ptr_id;
int vid_mode;
unsigned int seq_num;
/*
* Store received frame in ring buffer position pointed to by
* write pointer (this routine is called after DMA engine has
* stored a single received frame in ring buffer position pointed
* to by write pointer; this routine marks the frame's vid mode,
* timestamp, and sequence number)
*/
return;
}
return;
}
/* mark vid mode */
vid_mode =
softc_p->
/* update sequence counter overflow in param_status */
softc_p->param_status |=
/* mark frame's sequence number */
/* mark frame's timestamp */
/* increment write pointer */
num_read_ptrs = 1;
/*
* if write pointer is pointing to the same position as
* read pointer
*/
if ((ring_buff_write_ptr_pos_get(ring_buff_p) ==
(seq_num != 0)) {
/* increment read pointer */
/*
* if device driver is processing a user
* process's read() request
*/
/*
* invalidate the read() request processing
* operation
*/
}
/* inform user app that we have lost one frame */
softc_p->param_status |=
}
}
/* inform user app that we have received one frame */
}
/* ARGSUSED */
static void
{
}