/*
 * param_vid_mode_set
 */
int
param_vid_mode_set(dcam_state_t *softc_p, uint_t val)
{
	dcam1394_reg_io_t	reg_io;
	uint_t			vid_mode;

	vid_mode = val - DCAM1394_VID_MODE_0;

	reg_io.offs = DCAM1394_REG_OFFS_CUR_V_MODE;
	reg_io.val  = vid_mode << DCAM1394_SHIFT_CUR_V_MODE;

	if (dcam_reg_write(softc_p, &reg_io)) {
		return (1);
	}

	softc_p->cur_vid_mode = val;

	/*
	 * if we are currently receiving frames, we need to do a restart
	 * so that the new vid mode value takes effect
	 */
	if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
		(void) dcam_frame_rcv_stop(softc_p);
		(void) dcam1394_ioctl_frame_rcv_start(softc_p);
	}

	return (0);
}
/*
 * param_frame_rate_set
 */
int
param_frame_rate_set(dcam_state_t *softc_p, uint_t val)
{
	dcam1394_reg_io_t	reg_io;
	uint_t			frame_rate;

	/* if we are currently receiving frames, stop the camera */
	if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
		(void) dcam_frame_rcv_stop(softc_p);

		frame_rate = val - DCAM1394_FRAME_RATE_0 + 1;

		reg_io.offs = DCAM1394_REG_OFFS_CUR_V_FRM_RATE;
		reg_io.val  = frame_rate << DCAM1394_SHIFT_CUR_V_FRM_RATE;

		if (dcam_reg_write(softc_p, &reg_io)) {
			return (1);
		}

		/*
		 * Update the state info.
		 * note: the driver maintains frame rate in an array
		 * whereas the the camera uses predefined values whose
		 * lowest frame rate starts at 6
		 */
		softc_p->cur_frame_rate = val - 6;

		/* restart the camera */
		(void) dcam1394_ioctl_frame_rcv_start(softc_p);
	} else {
		frame_rate = val - DCAM1394_FRAME_RATE_0 + 1;

		reg_io.offs = DCAM1394_REG_OFFS_CUR_V_FRM_RATE;
		reg_io.val  = frame_rate << DCAM1394_SHIFT_CUR_V_FRM_RATE;

		if (dcam_reg_write(softc_p, &reg_io)) {
			return (1);
		}

		/* see note above re skewing of value by 6 */
		softc_p->cur_frame_rate = val - 6;
	}

	return (0);
}
/*
 * param_power_set()
 */
int
param_power_set(dcam_state_t *softc_p, uint_t val)
{
	dcam1394_reg_io_t reg_io;

	reg_io.offs = DCAM1394_REG_OFFS_CAMERA_POWER;
	reg_io.val = val << DCAM1394_SHIFT_CAMERA_POWER;

	if (dcam_reg_write(softc_p, &reg_io)) {
		return (1);
	}

	return (0);
}
/*
 * feature_set
 */
int
feature_set(dcam_state_t *softc_p, uint_t feature_csr_offs,
    uint_t subparam, uint_t val)
{
	dcam1394_reg_io_t  reg_io;

	reg_io.offs = feature_csr_offs + DCAM1394_REG_OFFS_FEATURE_CSR_BASE;

	if (dcam_reg_read(softc_p, &reg_io)) {
		return (1);
	}

	reg_io.val = feature_csr_val_construct(subparam, val, reg_io.val);

	if (dcam_reg_write(softc_p, &reg_io)) {
		return (1);
	}

	return (0);
}
Esempio n. 5
0
/*
 * dcam_frame_rcv_stop
 */
int
dcam_frame_rcv_stop(dcam_state_t *softc_p)
{
	dcam1394_reg_io_t reg_io;

	/* if resources have already been cleared, nothing to do */
	if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
		return (0);
	}

	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
	reg_io.val  = 0;

	(void) dcam_reg_write(softc_p, &reg_io);

	t1394_stop_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle, 0);
	t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
	t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);

	dcam_free_resources(softc_p);

	return (0);
}
Esempio n. 6
0
/*
 * dcam_frame_rcv_start
 */
int
dcam_frame_rcv_start(dcam_state_t *softc_p)
{
	id1394_isoch_dma_ctrlinfo_t	idma_ctrlinfo; /* currently not used */
	int32_t				result;
	dcam1394_reg_io_t		reg_io;

	if ((t1394_start_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle,
	    &idma_ctrlinfo, 0, &result)) != DDI_SUCCESS) {
		return (1);
	}

	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
	reg_io.val  = 0x80000000;

	if (dcam_reg_write(softc_p, &reg_io)) {
		return (1);
	}

	softc_p->flags |= DCAM1394_FLAG_FRAME_RCVING;

	return (0);
}
Esempio n. 7
0
/*
 * dcam_frame_rcv_init
 */
int
dcam_frame_rcv_init(dcam_state_t *softc_p, int vid_mode, int frame_rate,
    int ring_buff_capacity)
{
	int16_t			bytes_per_pkt;	/* # pkt bytes + overhead */
	int			bytes_per_frame;
	size_t			frame;
	int			cookie;
	int			failure;
	id1394_isoch_dmainfo_t	isoch_args;	/* for alloc isoch call */
	ixl1394_command_t	*last_ixlp;	/* last ixl in chain, */
						/* used for appending ixls */
	ixl1394_command_t	*new_ixl_cmdp;	/* new ixl command */
	ixl1394_set_syncwait_t	*new_ixl_sswp;	/* new ixl set syncwait */
	ixl1394_xfer_pkt_t	*new_ixl_xfpp;	/* new ixl xfer packet */
	ixl1394_xfer_buf_t	*new_ixl_xfbp;	/* new ixl xfer buffer */
	ixl1394_callback_t	*new_ixl_cbp;	/* new ixl callback */
	ixl1394_jump_t		*new_ixl_jmpp;	/* new ixl jump */
	int32_t			result;		/* errno from alloc_isoch_dma */
	buff_info_t		*buff_info_p;
	dcam1394_reg_io_t	reg_io;
	uint_t			data;
	size_t			num_bytes, num_bytes_left;
	size_t			num_xfer_cmds, xfer_cmd;
	size_t			max_ixl_buff_size;
	uint64_t		ixl_buff_kaddr;
	caddr_t			ixl_buff_vaddr;

	bytes_per_pkt = g_bytes_per_packet[vid_mode][frame_rate];
	if (bytes_per_pkt == -1) {
		return (1);
	}

	bytes_per_frame = g_bytes_per_frame[vid_mode];

	if ((softc_p->ring_buff_p = ring_buff_create(softc_p,
	    (size_t)ring_buff_capacity, (size_t)bytes_per_frame)) == NULL) {
		return (1);
	}

	softc_p->ring_buff_p->read_ptr_pos[0] = 0;

	/* allocate isoch channel */
	softc_p->sii.si_channel_mask	= 0xFFFF000000000000;
	softc_p->sii.si_bandwidth	= bytes_per_pkt;
	softc_p->sii.rsrc_fail_target	= dcam_rsrc_fail;
	softc_p->sii.single_evt_arg	= softc_p;
	softc_p->sii.si_speed		= softc_p->targetinfo.current_max_speed;

	if (t1394_alloc_isoch_single(softc_p->sl_handle,
	    &softc_p->sii, 0, &softc_p->sii_output_args, &softc_p->sii_hdl,
	    &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
	 */
	max_ixl_buff_size = (SHRT_MAX / bytes_per_pkt) * bytes_per_pkt;

	/* for each frame build frame's ixl list */
	for (frame = 0; frame < softc_p->ring_buff_p->num_buffs; frame++) {

		buff_info_p = &(softc_p->ring_buff_p->buff_info_array_p[frame]);

		/*
		 * if this is the 1st frame, put a IXL label at the top so a
		 * loop can be created later
		 */
		if (frame == 0) {
			new_ixl_cmdp = kmem_zalloc(
					sizeof (ixl1394_label_t), KM_SLEEP);
			softc_p->ixlp = new_ixl_cmdp;

			new_ixl_cmdp->ixl_opcode = IXL1394_OP_LABEL;

			last_ixlp = softc_p->ixlp;
		}

		/* add wait-for-sync IXL command */
		new_ixl_sswp = kmem_zalloc(
				sizeof (ixl1394_set_syncwait_t), KM_SLEEP);

		new_ixl_sswp->ixl_opcode = IXL1394_OP_SET_SYNCWAIT;

		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_sswp;
		last_ixlp = (ixl1394_command_t *)new_ixl_sswp;

		/* add in each dma cookie */
		for (cookie = 0; cookie < buff_info_p->dma_cookie_count;
		    cookie++) {

			num_xfer_cmds = min(bytes_per_frame,
			    buff_info_p->dma_cookie.dmac_size) /
			    max_ixl_buff_size;

			if (min(bytes_per_frame,
			    buff_info_p->dma_cookie.dmac_size) %
			    max_ixl_buff_size) {
				num_xfer_cmds++;
			}

			num_bytes_left = min(bytes_per_frame,
			    buff_info_p->dma_cookie.dmac_size);

			ixl_buff_kaddr =
			    buff_info_p->dma_cookie.dmac_laddress;

			ixl_buff_vaddr = buff_info_p->kaddr_p;

			for (xfer_cmd = 0; xfer_cmd < (num_xfer_cmds + 1);
			    xfer_cmd++) {
				num_bytes = min(num_bytes_left,
				    max_ixl_buff_size);

				if (xfer_cmd == 0) {
					new_ixl_xfpp =
					    kmem_zalloc(
						sizeof (ixl1394_xfer_pkt_t),
						KM_SLEEP);

					new_ixl_xfpp->ixl_opcode =
					    IXL1394_OP_RECV_PKT_ST;

					new_ixl_xfpp->ixl_buf._dmac_ll =
					    ixl_buff_kaddr;
					new_ixl_xfpp->size =
					    (uint16_t)bytes_per_pkt;
					new_ixl_xfpp->mem_bufp =
					    ixl_buff_vaddr;

					last_ixlp->next_ixlp =
					    (ixl1394_command_t *)new_ixl_xfpp;
					last_ixlp =
					    (ixl1394_command_t *)new_ixl_xfpp;

					num_bytes_left -= bytes_per_pkt;
					ixl_buff_kaddr += bytes_per_pkt;
					ixl_buff_vaddr += bytes_per_pkt;

					continue;
				}

				/* allocate & init an IXL transfer command. */
				new_ixl_xfbp =
				    kmem_zalloc(sizeof (ixl1394_xfer_buf_t),
					    KM_SLEEP);

				new_ixl_xfbp->ixl_opcode = IXL1394_OP_RECV_BUF;

				new_ixl_xfbp->ixl_buf._dmac_ll =
				    ixl_buff_kaddr;
				new_ixl_xfbp->size = (uint16_t)num_bytes;
				new_ixl_xfbp->pkt_size = bytes_per_pkt;
				new_ixl_xfbp->mem_bufp = ixl_buff_vaddr;

				last_ixlp->next_ixlp =
				    (ixl1394_command_t *)new_ixl_xfbp;
				last_ixlp =
				    (ixl1394_command_t *)new_ixl_xfbp;

				num_bytes_left -= num_bytes;
				ixl_buff_kaddr += num_bytes;
				ixl_buff_vaddr += num_bytes;
			}

			if (cookie > 0) {
				ddi_dma_nextcookie(buff_info_p->dma_handle,
				    &(buff_info_p->dma_cookie));
			}

		}

		/*
		 * at this point, have finished a frame.  put in a callback
		 */
		new_ixl_cbp = kmem_zalloc(
				sizeof (ixl1394_callback_t), KM_SLEEP);

		new_ixl_cbp->ixl_opcode	= IXL1394_OP_CALLBACK;

		new_ixl_cbp->callback = &dcam_frame_is_done;
		new_ixl_cbp->callback_arg = NULL;

		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_cbp;
		last_ixlp = (ixl1394_command_t *)new_ixl_cbp;
	}

	/*
	 * for the final touch, put an IXL jump at the end to jump to the
	 * label at the top
	 */
	new_ixl_jmpp = kmem_zalloc(sizeof (ixl1394_jump_t), KM_SLEEP);

	new_ixl_jmpp->ixl_opcode = IXL1394_OP_JUMP;

	new_ixl_jmpp->label = softc_p->ixlp;

	last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_jmpp;

	/* don't need this, but it's neater */
	last_ixlp = (ixl1394_command_t *)new_ixl_jmpp;

	/* call fwim routine to alloc an isoch resource */
	isoch_args.ixlp		= softc_p->ixlp;
	isoch_args.channel_num	= softc_p->sii_output_args.channel_num;

	/* other misc args.  note speed doesn't matter for isoch receive */
	isoch_args.idma_options		= ID1394_LISTEN_PKT_MODE;
	isoch_args.default_tag		= 0;
	isoch_args.default_sync		= 1;
	isoch_args.global_callback_arg	= softc_p;

	/* set the ISO channel number */
	data = (softc_p->sii_output_args.channel_num & 0xF) << 28;

	/* set the ISO speed */
	data |= (softc_p->targetinfo.current_max_speed << 24);

	reg_io.offs = DCAM1394_REG_OFFS_CUR_ISO_CHANNEL;
	reg_io.val  = data;

	if (dcam_reg_write(softc_p, &reg_io)) {
		return (1);
	}

	result = 1234;

	if (t1394_alloc_isoch_dma(softc_p->sl_handle, &isoch_args, 0,
	    &softc_p->isoch_handle, &result) != DDI_SUCCESS) {
		return (1);
	}

	return (0);
}