dcam.c revision 8eea8e29cc4374d1ee24c25a07f45af132db3499
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * CDDL HEADER START
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * The contents of this file are subject to the terms of the
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Common Development and Distribution License, Version 1.0 only
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * (the "License"). You may not use this file except in compliance
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * with the License.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * See the License for the specific language governing permissions
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * and limitations under the License.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * When distributing Covered Code, include this CDDL HEADER in each
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If applicable, add the following below this CDDL HEADER, with the
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * fields enclosed by brackets "[]" replaced with your own identifying
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * information: Portions Copyright [yyyy] [name of copyright owner]
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * CDDL HEADER END
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Use is subject to license terms.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#pragma ident "%Z%%M% %I% %E% SMI"
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam1394 driver. Controls IIDC compliant devices attached through a
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * IEEE-1394 bus.
8eea8e29cc4374d1ee24c25a07f45af132db3499apextern int tnf_mod_load(void);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#endif /* ! NPROBE */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* for power management (we have only one component) */
8eea8e29cc4374d1ee24c25a07f45af132db3499apstatic char *dcam_pmc[] = {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap "NAME=dcam1394",
8eea8e29cc4374d1ee24c25a07f45af132db3499apstatic int byte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p,
8eea8e29cc4374d1ee24c25a07f45af132db3499apstatic int byte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* opaque state structure head */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap /* flags */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap 0, /* device reference count */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap "SUNW 1394-based Digital Camera driver 1.0",
8eea8e29cc4374d1ee24c25a07f45af132db3499ap err = ddi_soft_state_init(&dcam_state_p, sizeof (dcam_state_t), 2);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#endif /* ! NPROBE */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#endif /* ! NPROBE */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#endif /* ! NPROBE */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_attach
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap switch (cmd) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Initialize soft state
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * set default vid_mode, frame_rate and ring_buff_capacity
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (ddi_create_minor_node(dip, tmp_str, S_IFCHR, instance,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap "dcam_attach: t1394_get_targetinfo failed\n");
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (ddi_add_event_handler(dip, ev_cookie, dcam_bus_reset_notify,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * init the soft state's parameter attribute structure
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * power management stuff
8eea8e29cc4374d1ee24c25a07f45af132db3499ap sizeof (dcam_pmc)/sizeof (char *)) == DDI_PROP_SUCCESS) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap "power-managed?")) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_power: perform dcam power management
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_getinfo
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
8eea8e29cc4374d1ee24c25a07f45af132db3499ap switch (cmd) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_detach
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap switch (cmd) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * power management stuff
8eea8e29cc4374d1ee24c25a07f45af132db3499ap (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * deregister with 1394 DDI framework
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (t1394_detach(&softc_p->sl_handle, 0) != DDI_SUCCESS) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * free state structures, mutexes, condvars;
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * deregister interrupts
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Remove all minor nodes, all dev_t's properties
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_open
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * if dcam_attach hasn't completed, return error
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * XXX: Check this out
8eea8e29cc4374d1ee24c25a07f45af132db3499ap /* disallow block, mount, and layered opens */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap is_ctrl_file = (getminor(*dev_p) & DCAM1394_MINOR_CTRL) ? 1 : 0;
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * The open is either for the capture file or the control file.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If it's the control file construct new flags.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If it's the capture file return busy if it's already open,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * otherwise construct new flags.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * power management stuff
8eea8e29cc4374d1ee24c25a07f45af132db3499ap "power-managed?")) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Wait for the power to be up and stable
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * before proceeding. 100 msecs should
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * certainly be enough, and if we check
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * every msec we'll probably loop just a
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * few times.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap for (i = 0; i < 100; i++) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_close
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * power management stuff
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (ddi_prop_exists(DDI_DEV_T_ANY, softc->dip, 0, "power-managed?")) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If an application which has opened the camera capture
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * device exits without calling DCAM1394_CMD_FRAME_RCV_STOP
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * ioctl, then we need to release resources.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If driver is completely closed, then stabilize the camera
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * and turn off transient flags
8eea8e29cc4374d1ee24c25a07f45af132db3499ap (DCAM1394_FLAG_OPEN_CONTROL | DCAM1394_FLAG_OPEN_CAPTURE))) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_read
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If read pointer is not pointing to the same position as write pointer
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * copy frame data from ring buffer position pointed to by read pointer.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If during the course of copying frame data, the device driver
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * invalidated this read() request processing operation, restart
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * this operation.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Increment read pointer and return frame data to user process.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Else return error
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap unsigned long user_frame_buff_addr;
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p->reader_flags[read_ptr_id] |= DCAM1394_FLAG_READ_REQ_PROC;
8eea8e29cc4374d1ee24c25a07f45af132db3499ap write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Since the app wants realtime video, set the read
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * pointer to the newest data.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * copy frame data from ring buffer position pointed
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * to by read pointer
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * Fix for bug #4424042
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * don't lock this section
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * get buff pointer; do ddi_copyout()
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * get user buffer address only once
8eea8e29cc4374d1ee24c25a07f45af132db3499ap 0xffffffffULL) |
8eea8e29cc4374d1ee24c25a07f45af132db3499ap 0xffffffff00000000ULL);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap#endif /* _MULTI_DATAMODEL */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * if during the course of copying frame data,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * the device driver invalidated this read()
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * request processing operation; restart this
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * operation
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * return number of bytes actually written to user space
8eea8e29cc4374d1ee24c25a07f45af132db3499ap uio_p->uio_resid -= g_vid_mode_frame_num_bytes[softc_p->cur_vid_mode];
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p->reader_flags[read_ptr_id] &= ~(DCAM1394_FLAG_READ_REQ_PROC);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap /* increment read pointer */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_ioctl
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * determine user applications data model
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32)
8eea8e29cc4374d1ee24c25a07f45af132db3499ap switch (cmd) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap is_ctrl_file = (getminor(dev) & DCAM1394_MINOR_CTRL) ? 1:0;
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * the simplest way to flush ring_buff is to empty it
8eea8e29cc4374d1ee24c25a07f45af132db3499ap for (i = 0; i < softc_p->ring_buff_p->num_read_ptrs; i++) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * if device driver is processing a user
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * process's read() request
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * invalidate the read() request processing
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * operation
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (rc);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_chpoll
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * now check for events
8eea8e29cc4374d1ee24c25a07f45af132db3499ap /* if no events have occurred */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (revent == 0) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_bus_reset_notify
8eea8e29cc4374d1ee24c25a07f45af132db3499ap/* ARGSUSED */
8eea8e29cc4374d1ee24c25a07f45af132db3499apdcam_bus_reset_notify(dev_info_t *dip, ddi_eventcookie_t ev_cookie, void *arg,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * this is needed to handle LG camera "changing GUID" bug
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * XXX: What's this about?
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if ((dip == NULL) || (arg == NULL) || (impl_data == NULL) ||
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * simply return if no target info
8eea8e29cc4374d1ee24c25a07f45af132db3499ap localinfo->bus_generation, 0, &targetinfo) != DDI_SUCCESS)
8eea8e29cc4374d1ee24c25a07f45af132db3499ap if (localinfo->local_nodeID == softc_p->targetinfo.target_nodeID) {
8eea8e29cc4374d1ee24c25a07f45af132db3499ap /* struct copies */
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * byte_copy_to_user_buff
8eea8e29cc4374d1ee24c25a07f45af132db3499apbyte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p, size_t num_bytes,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (-1);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * byte_copy_from_user_buff
8eea8e29cc4374d1ee24c25a07f45af132db3499apbyte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (-1);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * dcam_reset()
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (-1);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * If the camera has a TI VSP, tweak the iris feature
8eea8e29cc4374d1ee24c25a07f45af132db3499ap * to "on" and value 4.
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (-1);
8eea8e29cc4374d1ee24c25a07f45af132db3499ap return (0);