121Sap25164 /*
221Sap25164 * CDDL HEADER START
321Sap25164 *
421Sap25164 * The contents of this file are subject to the terms of the
5*7656SSherry.Moore@Sun.COM * Common Development and Distribution License (the "License").
6*7656SSherry.Moore@Sun.COM * You may not use this file except in compliance with the License.
721Sap25164 *
821Sap25164 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
921Sap25164 * or http://www.opensolaris.org/os/licensing.
1021Sap25164 * See the License for the specific language governing permissions
1121Sap25164 * and limitations under the License.
1221Sap25164 *
1321Sap25164 * When distributing Covered Code, include this CDDL HEADER in each
1421Sap25164 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1521Sap25164 * If applicable, add the following below this CDDL HEADER, with the
1621Sap25164 * fields enclosed by brackets "[]" replaced with your own identifying
1721Sap25164 * information: Portions Copyright [yyyy] [name of copyright owner]
1821Sap25164 *
1921Sap25164 * CDDL HEADER END
2021Sap25164 */
2121Sap25164 /*
22*7656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2321Sap25164 * Use is subject to license terms.
2421Sap25164 */
2521Sap25164
2621Sap25164
2721Sap25164 /*
2821Sap25164 * dcam.c
2921Sap25164 *
3021Sap25164 * dcam1394 driver. Controls IIDC compliant devices attached through a
3121Sap25164 * IEEE-1394 bus.
3221Sap25164 */
3321Sap25164
3421Sap25164 #include <sys/conf.h>
3521Sap25164 #include <sys/ddi.h>
3621Sap25164 #include <sys/modctl.h>
3721Sap25164 #include <sys/sunndi.h>
3821Sap25164 #include <sys/types.h>
3921Sap25164 #include <sys/ddi.h>
4021Sap25164 #include <sys/sunddi.h>
4121Sap25164 #include <sys/file.h>
4221Sap25164 #include <sys/errno.h>
4321Sap25164 #include <sys/open.h>
4421Sap25164 #include <sys/cred.h>
4521Sap25164 #include <sys/mkdev.h>
4621Sap25164 #include <sys/kmem.h>
4721Sap25164 #include <sys/stat.h>
4821Sap25164 #include <sys/cmn_err.h>
4921Sap25164 #include <sys/stream.h>
5021Sap25164 #include <sys/buf.h>
5121Sap25164 #include <sys/uio.h>
5221Sap25164 #include <sys/devops.h>
5321Sap25164 #include <sys/1394/t1394.h>
5421Sap25164 #include <sys/tnf_probe.h>
5521Sap25164
5621Sap25164 #include <sys/dcam/dcam1394_io.h>
5721Sap25164 #include <sys/1394/targets/dcam1394/dcam.h>
5821Sap25164 #include <sys/1394/targets/dcam1394/dcam_reg.h>
5921Sap25164 #include <sys/1394/targets/dcam1394/dcam_param.h>
6021Sap25164 #include <sys/1394/targets/dcam1394/dcam_frame.h>
6121Sap25164
6221Sap25164 #ifndef NPROBE
6321Sap25164 extern int tnf_mod_load(void);
6421Sap25164 extern int tnf_mod_unload(struct modlinkage *mlp);
6521Sap25164 #endif /* ! NPROBE */
6621Sap25164
6721Sap25164
6821Sap25164 /* for power management (we have only one component) */
6921Sap25164 static char *dcam_pmc[] = {
7021Sap25164 "NAME=dcam1394",
7121Sap25164 "0=Off",
7221Sap25164 "1=On"
7321Sap25164 };
7421Sap25164
7521Sap25164 int g_vid_mode_frame_num_bytes[] =
7621Sap25164 {
7721Sap25164 57600, /* vid mode 0 */
7821Sap25164 153600, /* vid mode 1 */
7921Sap25164 460800, /* vid mode 2 */
8021Sap25164 614400, /* vid mode 3 */
8121Sap25164 921600, /* vid mode 4 */
8221Sap25164 307200 /* vid mode 5 */
8321Sap25164 };
8421Sap25164
8521Sap25164 static int byte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p,
8621Sap25164 size_t num_bytes, int start_index, int *end_index);
8721Sap25164 static int byte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
8821Sap25164 size_t num_bytes, int start_index, int *end_index);
8921Sap25164 static int dcam_reset(dcam_state_t *softc_p);
9021Sap25164
9121Sap25164 /* opaque state structure head */
9221Sap25164 void *dcam_state_p;
9321Sap25164
9421Sap25164 static struct cb_ops dcam_cb_ops = {
9521Sap25164 dcam_open, /* open */
9621Sap25164 dcam_close, /* close */
9721Sap25164 nodev, /* strategy */
9821Sap25164 nodev, /* print */
9921Sap25164 nodev, /* dump */
10021Sap25164 dcam_read, /* read */
10121Sap25164 nodev, /* write */
10221Sap25164 dcam_ioctl, /* ioctl */
10321Sap25164 nodev, /* devmap */
10421Sap25164 nodev, /* mmap */
10521Sap25164 nodev, /* segmap */
10621Sap25164 dcam_chpoll, /* chpoll */
10721Sap25164 ddi_prop_op, /* prop_op */
10821Sap25164 NULL, /* streams */
10921Sap25164 /* flags */
11021Sap25164 D_NEW | D_MP | D_64BIT | D_HOTPLUG,
11121Sap25164 CB_REV, /* rev */
11221Sap25164 nodev, /* aread */
11321Sap25164 nodev /* awrite */
11421Sap25164 };
11521Sap25164
11621Sap25164 static struct dev_ops dcam_dev_ops = {
11721Sap25164 DEVO_REV, /* DEVO_REV indicated by manual */
11821Sap25164 0, /* device reference count */
11921Sap25164 dcam_getinfo, /* getinfo */
12021Sap25164 nulldev, /* identify */
12121Sap25164 nulldev, /* probe */
12221Sap25164 dcam_attach, /* attach */
12321Sap25164 dcam_detach, /* detach */
12421Sap25164 nodev, /* reset */
12521Sap25164 &dcam_cb_ops, /* ptr to cb_ops struct */
12621Sap25164 NULL, /* ptr to bus_ops struct; none */
12721Sap25164 dcam_power, /* power */
128*7656SSherry.Moore@Sun.COM ddi_quiesce_not_supported, /* devo_quiesce */
12921Sap25164 };
13021Sap25164
13121Sap25164 extern struct mod_ops mod_driverops;
13221Sap25164
13321Sap25164 static struct modldrv modldrv = {
13421Sap25164 &mod_driverops,
135*7656SSherry.Moore@Sun.COM "SUNW 1394-based Digital Camera driver",
13621Sap25164 &dcam_dev_ops,
13721Sap25164 };
13821Sap25164
13921Sap25164 static struct modlinkage modlinkage = {
14021Sap25164 MODREV_1,
14121Sap25164 (void *)&modldrv,
14221Sap25164 NULL,
14321Sap25164 };
14421Sap25164
14521Sap25164
14621Sap25164 int
_init(void)14721Sap25164 _init(void)
14821Sap25164 {
14921Sap25164 int err;
15021Sap25164
15121Sap25164 err = ddi_soft_state_init(&dcam_state_p, sizeof (dcam_state_t), 2);
15221Sap25164
15321Sap25164 if (err) {
15421Sap25164 return (err);
15521Sap25164 }
15621Sap25164
15721Sap25164 #ifndef NPROBE
15821Sap25164 (void) tnf_mod_load();
15921Sap25164 #endif /* ! NPROBE */
16021Sap25164
16121Sap25164 if (err = mod_install(&modlinkage)) {
16221Sap25164
16321Sap25164 #ifndef NPROBE
16421Sap25164 (void) tnf_mod_unload(&modlinkage);
16521Sap25164 #endif /* ! NPROBE */
16621Sap25164
16721Sap25164 ddi_soft_state_fini(&dcam_state_p);
16821Sap25164
16921Sap25164 }
17021Sap25164
17121Sap25164 return (err);
17221Sap25164 }
17321Sap25164
17421Sap25164
17521Sap25164 int
_info(struct modinfo * modinfop)17621Sap25164 _info(struct modinfo *modinfop)
17721Sap25164 {
17821Sap25164 int err;
17921Sap25164
18021Sap25164 err = mod_info(&modlinkage, modinfop);
18121Sap25164 return (err);
18221Sap25164 }
18321Sap25164
18421Sap25164
18521Sap25164 int
_fini(void)18621Sap25164 _fini(void)
18721Sap25164 {
18821Sap25164 int err;
18921Sap25164
19021Sap25164 if ((err = mod_remove(&modlinkage)) != 0) {
19121Sap25164 return (err);
19221Sap25164 }
19321Sap25164
19421Sap25164 #ifndef NPROBE
19521Sap25164 (void) tnf_mod_unload(&modlinkage);
19621Sap25164 #endif /* ! NPROBE */
19721Sap25164
19821Sap25164 ddi_soft_state_fini(&dcam_state_p);
19921Sap25164
20021Sap25164 return (err);
20121Sap25164 }
20221Sap25164
20321Sap25164
20421Sap25164 /*
20521Sap25164 * dcam_attach
20621Sap25164 */
20721Sap25164 /* ARGSUSED */
20821Sap25164 int
dcam_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)20921Sap25164 dcam_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
21021Sap25164 {
21121Sap25164 char tmp_str[MAX_STR_LEN];
21221Sap25164 dcam_state_t *softc_p;
21321Sap25164 ddi_eventcookie_t ev_cookie;
21421Sap25164 int instance;
21521Sap25164 int ret_val;
21621Sap25164
21721Sap25164 switch (cmd) {
21821Sap25164
21921Sap25164 case DDI_ATTACH:
22021Sap25164 instance = ddi_get_instance(dip);
22121Sap25164
22221Sap25164 if (ddi_soft_state_zalloc(dcam_state_p, instance) !=
22321Sap25164 DDI_SUCCESS) {
22421Sap25164 return (DDI_FAILURE);
22521Sap25164 }
22621Sap25164
22721Sap25164 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
22821Sap25164 NULL) {
22921Sap25164 ddi_soft_state_free(dcam_state_p, instance);
23021Sap25164 return (DDI_FAILURE);
23121Sap25164 }
23221Sap25164
23321Sap25164 /*
23421Sap25164 * Initialize soft state
23521Sap25164 */
23621Sap25164 softc_p->dip = dip;
23721Sap25164 softc_p->instance = instance;
23821Sap25164 softc_p->usr_model = -1;
23921Sap25164 softc_p->ixlp = NULL;
24021Sap25164
24121Sap25164 softc_p->seq_count = 0;
24221Sap25164 softc_p->param_status = 0;
24321Sap25164
24421Sap25164 /*
24521Sap25164 * set default vid_mode, frame_rate and ring_buff_capacity
24621Sap25164 */
24721Sap25164 softc_p->cur_vid_mode = 1;
24821Sap25164 softc_p->cur_frame_rate = 3;
24921Sap25164 softc_p->cur_ring_buff_capacity = 10;
25021Sap25164 softc_p->camera_online = 1;
25121Sap25164
25221Sap25164 (void) sprintf(tmp_str, "dcam%d", instance);
25321Sap25164
25421Sap25164 if (ddi_create_minor_node(dip, tmp_str, S_IFCHR, instance,
25521Sap25164 DDI_PSEUDO, 0) != DDI_SUCCESS) {
25621Sap25164 ddi_soft_state_free(dcam_state_p, instance);
25721Sap25164
25821Sap25164 return (DDI_FAILURE);
25921Sap25164 }
26021Sap25164
26121Sap25164 (void) sprintf(tmp_str, "dcamctl%d", instance);
26221Sap25164
26321Sap25164 if (ddi_create_minor_node(dip, tmp_str, S_IFCHR,
26421Sap25164 instance + DCAM1394_MINOR_CTRL, "ddi_dcam1394", 0) !=
26521Sap25164 DDI_SUCCESS) {
26621Sap25164 ddi_soft_state_free(dcam_state_p, instance);
26721Sap25164
26821Sap25164 return (DDI_FAILURE);
26921Sap25164 }
27021Sap25164
27121Sap25164 if (t1394_attach(dip, T1394_VERSION_V1, 0,
27221Sap25164 &(softc_p->attachinfo),
27321Sap25164 &(softc_p->sl_handle)) != DDI_SUCCESS) {
27421Sap25164 ddi_soft_state_free(dcam_state_p, instance);
27521Sap25164 ddi_remove_minor_node(dip, NULL);
27621Sap25164
27721Sap25164 return (DDI_FAILURE);
27821Sap25164 }
27921Sap25164
28021Sap25164 if (t1394_get_targetinfo(softc_p->sl_handle,
28121Sap25164 softc_p->attachinfo.localinfo.bus_generation, 0,
28221Sap25164 &(softc_p->targetinfo)) != DDI_SUCCESS) {
28321Sap25164 cmn_err(CE_WARN,
28421Sap25164 "dcam_attach: t1394_get_targetinfo failed\n");
28521Sap25164 }
28621Sap25164
28721Sap25164 if (ddi_get_eventcookie(dip, DDI_DEVI_BUS_RESET_EVENT,
28821Sap25164 &ev_cookie) != DDI_SUCCESS) {
28921Sap25164 (void) t1394_detach(&softc_p->sl_handle, 0);
29021Sap25164
29121Sap25164 ddi_soft_state_free(dcam_state_p, instance);
29221Sap25164 ddi_remove_minor_node(dip, NULL);
29321Sap25164
29421Sap25164 return (DDI_FAILURE);
29521Sap25164 }
29621Sap25164
29721Sap25164 if (ddi_add_event_handler(dip, ev_cookie, dcam_bus_reset_notify,
29821Sap25164 softc_p, &softc_p->event_id) != DDI_SUCCESS) {
29921Sap25164 (void) t1394_detach(&softc_p->sl_handle, 0);
30021Sap25164
30121Sap25164 ddi_soft_state_free(dcam_state_p, instance);
30221Sap25164 ddi_remove_minor_node(dip, NULL);
30321Sap25164
30421Sap25164 return (DDI_FAILURE);
30521Sap25164 }
30621Sap25164
30721Sap25164 mutex_init(&softc_p->softc_mutex, NULL, MUTEX_DRIVER,
30821Sap25164 softc_p->attachinfo.iblock_cookie);
30921Sap25164
31021Sap25164 mutex_init(&softc_p->dcam_frame_is_done_mutex, NULL,
31121Sap25164 MUTEX_DRIVER, softc_p->attachinfo.iblock_cookie);
31221Sap25164
31321Sap25164 /*
31421Sap25164 * init the soft state's parameter attribute structure
31521Sap25164 */
31621Sap25164 if (param_attr_init(softc_p, softc_p->param_attr) !=
31721Sap25164 DDI_SUCCESS) {
31821Sap25164 (void) ddi_remove_event_handler(softc_p->event_id);
31921Sap25164 (void) t1394_detach(&softc_p->sl_handle, 0);
32021Sap25164
32121Sap25164 ddi_soft_state_free(dcam_state_p, instance);
32221Sap25164 ddi_remove_minor_node(dip, NULL);
32321Sap25164
32421Sap25164 return (DDI_FAILURE);
32521Sap25164 }
32621Sap25164
32721Sap25164 /*
32821Sap25164 * power management stuff
32921Sap25164 */
33021Sap25164 if (ddi_prop_update_string_array(DDI_DEV_T_NONE,
33121Sap25164 dip, "pm-components", dcam_pmc,
33221Sap25164 sizeof (dcam_pmc)/sizeof (char *)) == DDI_PROP_SUCCESS) {
33321Sap25164
33421Sap25164 (void) pm_raise_power(dip, 0, 1);
33521Sap25164 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, 0,
33621Sap25164 "power-managed?")) {
33721Sap25164 (void) pm_idle_component(dip, 0);
33821Sap25164 } else {
33921Sap25164 (void) pm_busy_component(dip, 0);
34021Sap25164 }
34121Sap25164 }
34221Sap25164
34321Sap25164 softc_p->flags |= DCAM1394_FLAG_ATTACH_COMPLETE;
34421Sap25164
34521Sap25164 ddi_report_dev(dip);
34621Sap25164 ret_val = DDI_SUCCESS;
34721Sap25164 break;
34821Sap25164
34921Sap25164 case DDI_RESUME:
35021Sap25164 instance = ddi_get_instance(dip);
35121Sap25164 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
35221Sap25164 NULL) {
35321Sap25164 ddi_soft_state_free(dcam_state_p, instance);
35421Sap25164 return (DDI_FAILURE);
35521Sap25164 }
35621Sap25164
35721Sap25164 mutex_enter(&softc_p->softc_mutex);
35821Sap25164
35921Sap25164 if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
36021Sap25164 (void) dcam1394_ioctl_frame_rcv_start(softc_p);
36121Sap25164 }
36221Sap25164
36321Sap25164 softc_p->suspended = 0;
36421Sap25164
36521Sap25164 mutex_exit(&softc_p->softc_mutex);
36621Sap25164
36721Sap25164 ret_val = DDI_SUCCESS;
36821Sap25164 break;
36921Sap25164
37021Sap25164 default:
37121Sap25164 ret_val = DDI_FAILURE;
37221Sap25164 break;
37321Sap25164 }
37421Sap25164
37521Sap25164 return (ret_val);
37621Sap25164 }
37721Sap25164
37821Sap25164
37921Sap25164 /*
38021Sap25164 * dcam_power: perform dcam power management
38121Sap25164 */
38221Sap25164 /* ARGSUSED */
38321Sap25164 int
dcam_power(dev_info_t * dip,int component,int level)38421Sap25164 dcam_power(dev_info_t *dip, int component, int level)
38521Sap25164 {
38621Sap25164 dcam_state_t *softc_p;
38721Sap25164 int instance;
38821Sap25164
38921Sap25164 instance = ddi_get_instance(dip);
39021Sap25164 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
39121Sap25164
39221Sap25164 if (softc_p == NULL)
39321Sap25164 return (DDI_FAILURE);
39421Sap25164
39521Sap25164 softc_p->pm_cable_power = level;
39621Sap25164
39721Sap25164 return (DDI_SUCCESS);
39821Sap25164
39921Sap25164 }
40021Sap25164
40121Sap25164
40221Sap25164 /*
40321Sap25164 * dcam_getinfo
40421Sap25164 */
40521Sap25164 /* ARGSUSED */
40621Sap25164 int
dcam_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)40721Sap25164 dcam_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
40821Sap25164 {
40921Sap25164 dev_t dev;
41021Sap25164 dcam_state_t *softc_p;
41121Sap25164 int status;
41221Sap25164 int instance;
41321Sap25164
41421Sap25164 switch (cmd) {
41521Sap25164
41621Sap25164 case DDI_INFO_DEVT2DEVINFO:
41721Sap25164 dev = (dev_t)arg;
41821Sap25164 instance = DEV_TO_INSTANCE(dev);
41921Sap25164 softc_p = (dcam_state_t *)
42021Sap25164 ddi_get_soft_state(dcam_state_p, instance);
42121Sap25164
42221Sap25164 if (softc_p == NULL) {
42321Sap25164 return (DDI_FAILURE);
42421Sap25164 }
42521Sap25164
42621Sap25164 *result = (void *)softc_p->dip;
42721Sap25164 status = DDI_SUCCESS;
42821Sap25164 break;
42921Sap25164
43021Sap25164 case DDI_INFO_DEVT2INSTANCE:
43121Sap25164 dev = (dev_t)arg;
43221Sap25164 instance = DEV_TO_INSTANCE(dev);
43321Sap25164 *result = (void *)(uintptr_t)instance;
43421Sap25164 status = DDI_SUCCESS;
43521Sap25164 break;
43621Sap25164
43721Sap25164 default:
43821Sap25164 status = DDI_FAILURE;
43921Sap25164 }
44021Sap25164
44121Sap25164 return (status);
44221Sap25164 }
44321Sap25164
44421Sap25164
44521Sap25164 /*
44621Sap25164 * dcam_detach
44721Sap25164 */
44821Sap25164 /* ARGSUSED */
44921Sap25164 int
dcam_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)45021Sap25164 dcam_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
45121Sap25164 {
45221Sap25164 int instance;
45321Sap25164 dcam_state_t *softc_p;
45421Sap25164
45521Sap25164 instance = ddi_get_instance(dip);
45621Sap25164
45721Sap25164 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
45821Sap25164 if (softc_p == NULL) {
45921Sap25164 return (DDI_FAILURE);
46021Sap25164 }
46121Sap25164
46221Sap25164
46321Sap25164 switch (cmd) {
46421Sap25164
46521Sap25164 case DDI_SUSPEND:
46621Sap25164 mutex_enter(&softc_p->softc_mutex);
46721Sap25164
46821Sap25164 softc_p->suspended = 1;
46921Sap25164
47021Sap25164 if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
47121Sap25164 (void) dcam_frame_rcv_stop(softc_p);
47221Sap25164 }
47321Sap25164
47421Sap25164 mutex_exit(&softc_p->softc_mutex);
47521Sap25164 return (DDI_SUCCESS);
47621Sap25164
47721Sap25164
47821Sap25164 case DDI_DETACH:
47921Sap25164 /*
48021Sap25164 * power management stuff
48121Sap25164 */
48221Sap25164 (void) pm_lower_power(dip, 0, 0);
48321Sap25164 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
48421Sap25164
48521Sap25164 /*
48621Sap25164 * deregister with 1394 DDI framework
48721Sap25164 */
48821Sap25164 if (t1394_detach(&softc_p->sl_handle, 0) != DDI_SUCCESS) {
48921Sap25164 return (DDI_FAILURE);
49021Sap25164 }
49121Sap25164
49221Sap25164 (void) ddi_remove_event_handler(softc_p->event_id);
49321Sap25164
49421Sap25164 /*
49521Sap25164 * free state structures, mutexes, condvars;
49621Sap25164 * deregister interrupts
49721Sap25164 */
49821Sap25164 mutex_destroy(&softc_p->softc_mutex);
49921Sap25164 mutex_destroy(&softc_p->dcam_frame_is_done_mutex);
50021Sap25164
50121Sap25164 /*
50221Sap25164 * Remove all minor nodes, all dev_t's properties
50321Sap25164 */
50421Sap25164 ddi_remove_minor_node(dip, NULL);
50521Sap25164
50621Sap25164 ddi_soft_state_free(dcam_state_p, instance);
50721Sap25164 ddi_prop_remove_all(dip);
50821Sap25164
50921Sap25164 return (DDI_SUCCESS);
51021Sap25164
51121Sap25164 default:
51221Sap25164 return (DDI_FAILURE);
51321Sap25164
51421Sap25164 }
51521Sap25164 }
51621Sap25164
51721Sap25164
51821Sap25164 /*
51921Sap25164 * dcam_open
52021Sap25164 */
52121Sap25164 /* ARGSUSED */
52221Sap25164 int
dcam_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)52321Sap25164 dcam_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
52421Sap25164 {
52521Sap25164 dcam_state_t *softc_p;
52621Sap25164 int instance;
52721Sap25164 int is_ctrl_file;
52821Sap25164 uint_t new_flags;
52921Sap25164
53021Sap25164 instance = (int)DEV_TO_INSTANCE(*dev_p);
53121Sap25164
53221Sap25164 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
53321Sap25164 return (ENXIO);
53421Sap25164 }
53521Sap25164
53621Sap25164 /*
53721Sap25164 * if dcam_attach hasn't completed, return error
53821Sap25164 * XXX: Check this out
53921Sap25164 */
54021Sap25164 if (!(softc_p->flags & DCAM1394_FLAG_ATTACH_COMPLETE)) {
54121Sap25164 return (ENXIO);
54221Sap25164 }
54321Sap25164
54421Sap25164 /* disallow block, mount, and layered opens */
54521Sap25164 if (otyp != OTYP_CHR) {
54621Sap25164 return (EINVAL);
54721Sap25164 }
54821Sap25164
54921Sap25164 new_flags = 0;
55021Sap25164 is_ctrl_file = (getminor(*dev_p) & DCAM1394_MINOR_CTRL) ? 1 : 0;
55121Sap25164
55221Sap25164 mutex_enter(&softc_p->softc_mutex);
55321Sap25164
55421Sap25164 /*
55521Sap25164 * The open is either for the capture file or the control file.
55621Sap25164 * If it's the control file construct new flags.
55721Sap25164 *
55821Sap25164 * If it's the capture file return busy if it's already open,
55921Sap25164 * otherwise construct new flags.
56021Sap25164 */
56121Sap25164 if (is_ctrl_file) {
56221Sap25164 new_flags |= DCAM1394_FLAG_OPEN_CONTROL;
56321Sap25164 } else {
56421Sap25164 if (softc_p->flags & DCAM1394_FLAG_OPEN_CAPTURE) {
56521Sap25164 mutex_exit(&softc_p->softc_mutex);
56621Sap25164 return (EBUSY);
56721Sap25164 }
56821Sap25164
56921Sap25164 new_flags |= DCAM1394_FLAG_OPEN_CAPTURE;
57021Sap25164 }
57121Sap25164
57221Sap25164 new_flags |= DCAM1394_FLAG_OPEN;
57321Sap25164 softc_p->flags |= new_flags;
57421Sap25164
57521Sap25164 mutex_exit(&softc_p->softc_mutex);
57621Sap25164
57721Sap25164 /*
57821Sap25164 * power management stuff
57921Sap25164 */
58021Sap25164 if (softc_p->pm_open_count == 0) {
58121Sap25164 if (ddi_prop_exists(DDI_DEV_T_ANY, softc_p->dip, 0,
58221Sap25164 "power-managed?")) {
58321Sap25164 (void) pm_busy_component(softc_p->dip, 0);
58421Sap25164 if (softc_p->pm_cable_power == 0) {
58521Sap25164 int i;
58621Sap25164
58721Sap25164 (void) pm_raise_power(softc_p->dip, 0, 1);
58821Sap25164
58921Sap25164 /*
59021Sap25164 * Wait for the power to be up and stable
59121Sap25164 * before proceeding. 100 msecs should
59221Sap25164 * certainly be enough, and if we check
59321Sap25164 * every msec we'll probably loop just a
59421Sap25164 * few times.
59521Sap25164 */
59621Sap25164 for (i = 0; i < 100; i++) {
59721Sap25164 if (param_power_set(softc_p, 1) == 0) {
59821Sap25164 break;
59921Sap25164 }
60021Sap25164 delay((clock_t)drv_usectohz(1000));
60121Sap25164 }
60221Sap25164 }
60321Sap25164 }
60421Sap25164 }
60521Sap25164 softc_p->pm_open_count++;
60621Sap25164
60721Sap25164 return (0);
60821Sap25164 }
60921Sap25164
61021Sap25164
61121Sap25164 /*
61221Sap25164 * dcam_close
61321Sap25164 */
61421Sap25164 /* ARGSUSED */
61521Sap25164 int
dcam_close(dev_t dev,int flags,int otyp,cred_t * cred_p)61621Sap25164 dcam_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
61721Sap25164 {
61821Sap25164 int instance;
61921Sap25164 dcam_state_t *softc;
62021Sap25164
62121Sap25164 instance = DEV_TO_INSTANCE(dev);
62221Sap25164 softc = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
62321Sap25164
62421Sap25164 /*
62521Sap25164 * power management stuff
62621Sap25164 */
62721Sap25164 softc->pm_open_count = 0;
62821Sap25164 if (ddi_prop_exists(DDI_DEV_T_ANY, softc->dip, 0, "power-managed?")) {
62921Sap25164 (void) pm_idle_component(softc->dip, 0);
63021Sap25164 }
63121Sap25164
63221Sap25164 mutex_enter(&softc->softc_mutex);
63321Sap25164
63421Sap25164 if (getminor(dev) & DCAM1394_MINOR_CTRL) {
63521Sap25164 softc->flags &= ~DCAM1394_FLAG_OPEN_CONTROL;
63621Sap25164 } else {
63721Sap25164 /*
63821Sap25164 * If an application which has opened the camera capture
63921Sap25164 * device exits without calling DCAM1394_CMD_FRAME_RCV_STOP
64021Sap25164 * ioctl, then we need to release resources.
64121Sap25164 */
64221Sap25164 if (softc->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
64321Sap25164 (void) dcam_frame_rcv_stop(softc);
64421Sap25164 softc->flags &= ~DCAM1394_FLAG_FRAME_RCV_INIT;
64521Sap25164 }
64621Sap25164
64721Sap25164 (void) param_power_set(softc, 0);
64821Sap25164
64921Sap25164 softc->flags &= ~DCAM1394_FLAG_OPEN_CAPTURE;
65021Sap25164 }
65121Sap25164
65221Sap25164 /*
65321Sap25164 * If driver is completely closed, then stabilize the camera
65421Sap25164 * and turn off transient flags
65521Sap25164 */
65621Sap25164 if (!(softc->flags &
65721Sap25164 (DCAM1394_FLAG_OPEN_CONTROL | DCAM1394_FLAG_OPEN_CAPTURE))) {
65821Sap25164 softc->flags &= DCAM1394_FLAG_ATTACH_COMPLETE;
65921Sap25164 }
66021Sap25164
66121Sap25164 mutex_exit(&softc->softc_mutex);
66221Sap25164
66321Sap25164 return (DDI_SUCCESS);
66421Sap25164
66521Sap25164 }
66621Sap25164
66721Sap25164
66821Sap25164 /*
66921Sap25164 * dcam_read
67021Sap25164 *
67121Sap25164 * If read pointer is not pointing to the same position as write pointer
67221Sap25164 * copy frame data from ring buffer position pointed to by read pointer.
67321Sap25164 *
67421Sap25164 * If during the course of copying frame data, the device driver
67521Sap25164 * invalidated this read() request processing operation, restart
67621Sap25164 * this operation.
67721Sap25164 *
67821Sap25164 * Increment read pointer and return frame data to user process.
67921Sap25164 *
68021Sap25164 * Else return error
68121Sap25164 *
68221Sap25164 */
68321Sap25164 /* ARGSUSED */
68421Sap25164 int
dcam_read(dev_t dev,struct uio * uio_p,cred_t * cred_p)68521Sap25164 dcam_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
68621Sap25164 {
68721Sap25164 buff_info_t *buff_info_p;
68821Sap25164 dcam_state_t *softc_p;
68921Sap25164 hrtime_t timestamp;
69021Sap25164 int index, instance;
69121Sap25164 int read_ptr_id;
69221Sap25164 size_t read_ptr_pos, write_ptr_pos;
69321Sap25164 int read_req_invalid;
69421Sap25164 ring_buff_t *ring_buff_p;
69521Sap25164 uchar_t *frame_data_p;
69621Sap25164 uint_t seq_num;
69721Sap25164 unsigned long user_frame_buff_addr;
69821Sap25164 uint_t vid_mode;
69921Sap25164 int gotten_addr_flag;
70021Sap25164
70121Sap25164 instance = DEV_TO_INSTANCE(dev);
70221Sap25164
70321Sap25164 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
70421Sap25164 if (softc_p == NULL) {
70521Sap25164 return (ENXIO);
70621Sap25164 }
70721Sap25164
70821Sap25164 if ((ring_buff_p = softc_p->ring_buff_p) == NULL) {
70921Sap25164 return (EAGAIN);
71021Sap25164 }
71121Sap25164
71221Sap25164 read_ptr_id = 0;
71321Sap25164
71421Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
71521Sap25164
71621Sap25164 softc_p->reader_flags[read_ptr_id] |= DCAM1394_FLAG_READ_REQ_PROC;
71721Sap25164
71821Sap25164 user_frame_buff_addr = 0;
71921Sap25164 gotten_addr_flag = 0;
72021Sap25164
72121Sap25164 do {
72221Sap25164 read_ptr_pos = ring_buff_read_ptr_pos_get(ring_buff_p,
72321Sap25164 read_ptr_id);
72421Sap25164
72521Sap25164 write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
72621Sap25164
72721Sap25164 if (read_ptr_pos != write_ptr_pos) {
72821Sap25164 /*
72921Sap25164 * Since the app wants realtime video, set the read
73021Sap25164 * pointer to the newest data.
73121Sap25164 */
73221Sap25164 if (write_ptr_pos == 0) {
73321Sap25164 read_ptr_pos = ring_buff_p->num_buffs - 1;
73421Sap25164 } else {
73521Sap25164 read_ptr_pos = write_ptr_pos - 1;
73621Sap25164 }
73721Sap25164
73821Sap25164 /*
73921Sap25164 * copy frame data from ring buffer position pointed
74021Sap25164 * to by read pointer
74121Sap25164 */
74221Sap25164 index = 0;
74321Sap25164 buff_info_p =
744*7656SSherry.Moore@Sun.COM &(ring_buff_p->buff_info_array_p[read_ptr_pos]);
74521Sap25164
74621Sap25164 vid_mode = softc_p->cur_vid_mode;
74721Sap25164 seq_num = buff_info_p->seq_num;
74821Sap25164 timestamp = buff_info_p->timestamp;
74921Sap25164 frame_data_p = (uchar_t *)buff_info_p->kaddr_p;
75021Sap25164
75121Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
75221Sap25164
75321Sap25164 /*
75421Sap25164 * Fix for bug #4424042
75521Sap25164 * don't lock this section
75621Sap25164 */
75721Sap25164
75821Sap25164 if (byte_copy_to_user_buff((uchar_t *)&vid_mode,
75921Sap25164 uio_p, sizeof (uint_t), index, &index)) {
76021Sap25164
76121Sap25164 return (EFAULT);
76221Sap25164 }
76321Sap25164
76421Sap25164 if (byte_copy_to_user_buff((uchar_t *)&seq_num,
76521Sap25164 uio_p, sizeof (unsigned int), index, &index)) {
76621Sap25164
76721Sap25164 return (EFAULT);
76821Sap25164 }
76921Sap25164
77021Sap25164 if (byte_copy_to_user_buff((uchar_t *)×tamp,
77121Sap25164 uio_p, sizeof (hrtime_t), index, &index)) {
77221Sap25164
77321Sap25164 return (EFAULT);
77421Sap25164 }
77521Sap25164
77621Sap25164 /*
77721Sap25164 * get buff pointer; do ddi_copyout()
77821Sap25164 * get user buffer address only once
77921Sap25164 */
78021Sap25164 if (!gotten_addr_flag) {
78121Sap25164 if (byte_copy_from_user_buff(
78221Sap25164 (uchar_t *)&user_frame_buff_addr, uio_p,
78321Sap25164 softc_p->usr_model, index, &index)) {
78421Sap25164
78521Sap25164 return (EFAULT);
78621Sap25164 }
78721Sap25164
78821Sap25164 #ifdef _MULTI_DATAMODEL
78921Sap25164 if (softc_p->usr_model == ILP32_PTR_SIZE) {
79021Sap25164 user_frame_buff_addr =
79121Sap25164 ((user_frame_buff_addr >> 32) &
79221Sap25164 0xffffffffULL) |
79321Sap25164 ((user_frame_buff_addr << 32) &
79421Sap25164 0xffffffff00000000ULL);
79521Sap25164 }
79621Sap25164 #endif /* _MULTI_DATAMODEL */
79721Sap25164
79821Sap25164 gotten_addr_flag = 1;
79921Sap25164 }
80021Sap25164
80121Sap25164 if (ddi_copyout(
80221Sap25164 (caddr_t)frame_data_p,
80321Sap25164 (caddr_t)user_frame_buff_addr,
80421Sap25164 g_vid_mode_frame_num_bytes[softc_p->cur_vid_mode],
80521Sap25164 0)) {
80621Sap25164 return (EFAULT);
80721Sap25164 }
80821Sap25164
80921Sap25164 /*
81021Sap25164 * if during the course of copying frame data,
81121Sap25164 * the device driver invalidated this read()
81221Sap25164 * request processing operation; restart this
81321Sap25164 * operation
81421Sap25164 */
81521Sap25164
81621Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
81721Sap25164
81821Sap25164 read_req_invalid = softc_p->reader_flags[read_ptr_id] &
81921Sap25164 DCAM1394_FLAG_READ_REQ_INVALID;
82021Sap25164
82121Sap25164 softc_p->reader_flags[read_ptr_id] &=
82221Sap25164 ~(DCAM1394_FLAG_READ_REQ_INVALID);
82321Sap25164
82421Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
82521Sap25164
82621Sap25164 } else {
82721Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
82821Sap25164 return (EAGAIN);
82921Sap25164 }
83021Sap25164
83121Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
83221Sap25164 } while (read_req_invalid);
83321Sap25164
83421Sap25164 /*
83521Sap25164 * return number of bytes actually written to user space
83621Sap25164 */
83721Sap25164 uio_p->uio_resid -= g_vid_mode_frame_num_bytes[softc_p->cur_vid_mode];
83821Sap25164
83921Sap25164 softc_p->reader_flags[read_ptr_id] &= ~(DCAM1394_FLAG_READ_REQ_PROC);
84021Sap25164
84121Sap25164 /* increment read pointer */
84221Sap25164 ring_buff_read_ptr_incr(ring_buff_p, read_ptr_id);
84321Sap25164
84421Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
84521Sap25164
84621Sap25164 return (0);
84721Sap25164 }
84821Sap25164
84921Sap25164
85021Sap25164 /*
85121Sap25164 * dcam_ioctl
85221Sap25164 */
85321Sap25164 /* ARGSUSED */
85421Sap25164 int
dcam_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rvalp)85521Sap25164 dcam_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
85621Sap25164 int *rvalp)
85721Sap25164 {
85821Sap25164 dcam_state_t *softc_p;
85921Sap25164 dcam1394_param_list_t *param_list;
86021Sap25164 dcam1394_reg_io_t dcam_reg_io;
86121Sap25164 int instance, is_ctrl_file, rc, i;
86221Sap25164
86321Sap25164 rc = 0;
86421Sap25164 param_list = (dcam1394_param_list_t *)0;
86521Sap25164
86621Sap25164 instance = DEV_TO_INSTANCE(dev);
86721Sap25164
86821Sap25164 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
86921Sap25164 rc = ENXIO;
87021Sap25164 goto done;
87121Sap25164 }
87221Sap25164
87321Sap25164 /*
87421Sap25164 * determine user applications data model
87521Sap25164 */
87621Sap25164 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32)
87721Sap25164 softc_p->usr_model = ILP32_PTR_SIZE;
87821Sap25164 else
87921Sap25164 softc_p->usr_model = LP64_PTR_SIZE;
88021Sap25164
88121Sap25164
88221Sap25164 switch (cmd) {
88321Sap25164
88421Sap25164 case DCAM1394_CMD_REG_READ:
88521Sap25164 if (ddi_copyin((caddr_t)arg, &dcam_reg_io,
88621Sap25164 sizeof (dcam1394_reg_io_t), mode)) {
88721Sap25164 rc = EFAULT;
88821Sap25164 goto done;
88921Sap25164 }
89021Sap25164
89121Sap25164 if (dcam_reg_read(softc_p, &dcam_reg_io)) {
89221Sap25164 rc = EFAULT;
89321Sap25164 goto done;
89421Sap25164 }
89521Sap25164
89621Sap25164 if (ddi_copyout(&dcam_reg_io, (caddr_t)arg,
89721Sap25164 sizeof (dcam1394_reg_io_t), mode)) {
89821Sap25164 rc = EFAULT;
89921Sap25164 goto done;
90021Sap25164 }
90121Sap25164 break;
90221Sap25164
90321Sap25164 case DCAM1394_CMD_REG_WRITE:
90421Sap25164 if (ddi_copyin((caddr_t)arg, &dcam_reg_io,
90521Sap25164 sizeof (dcam1394_reg_io_t), mode)) {
90621Sap25164 rc = EFAULT;
90721Sap25164 goto done;
90821Sap25164 }
90921Sap25164
91021Sap25164 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
91121Sap25164 rc = EFAULT;
91221Sap25164 goto done;
91321Sap25164 }
91421Sap25164
91521Sap25164 if (ddi_copyout(&dcam_reg_io, (caddr_t)arg,
91621Sap25164 sizeof (dcam1394_reg_io_t), mode)) {
91721Sap25164 rc = EFAULT;
91821Sap25164 goto done;
91921Sap25164 }
92021Sap25164 break;
92121Sap25164
92221Sap25164 case DCAM1394_CMD_CAM_RESET:
92321Sap25164 if (dcam_reset(softc_p)) {
92421Sap25164 rc = EIO;
92521Sap25164 goto done;
92621Sap25164 }
92721Sap25164 break;
92821Sap25164
92921Sap25164 case DCAM1394_CMD_PARAM_GET:
93021Sap25164 param_list = (dcam1394_param_list_t *)
93121Sap25164 kmem_alloc(sizeof (dcam1394_param_list_t), KM_SLEEP);
93221Sap25164
93321Sap25164 if (ddi_copyin((caddr_t)arg, (caddr_t)param_list,
93421Sap25164 sizeof (dcam1394_param_list_t), mode)) {
93521Sap25164 rc = EFAULT;
93621Sap25164 goto done;
93721Sap25164 }
93821Sap25164
93921Sap25164 if (dcam1394_ioctl_param_get(softc_p, *param_list)) {
94021Sap25164 rc = EINVAL;
94121Sap25164 }
94221Sap25164
94321Sap25164 if (ddi_copyout((caddr_t)param_list, (caddr_t)arg,
94421Sap25164 sizeof (dcam1394_param_list_t), mode)) {
94521Sap25164 rc = EFAULT;
94621Sap25164 goto done;
94721Sap25164 }
94821Sap25164 break;
94921Sap25164
95021Sap25164 case DCAM1394_CMD_PARAM_SET:
95121Sap25164 param_list = (dcam1394_param_list_t *)
95221Sap25164 kmem_alloc((size_t)sizeof (dcam1394_param_list_t),
95321Sap25164 KM_SLEEP);
95421Sap25164
95521Sap25164 if (ddi_copyin((caddr_t)arg, (caddr_t)param_list,
95621Sap25164 sizeof (dcam1394_param_list_t), mode)) {
95721Sap25164 rc = EFAULT;
95821Sap25164 goto done;
95921Sap25164 }
96021Sap25164
96121Sap25164 is_ctrl_file = (getminor(dev) & DCAM1394_MINOR_CTRL) ? 1:0;
96221Sap25164
96321Sap25164 if (dcam1394_ioctl_param_set(softc_p, is_ctrl_file,
96421Sap25164 *param_list)) {
96521Sap25164 rc = EINVAL;
96621Sap25164 }
96721Sap25164
96821Sap25164 if (is_ctrl_file) {
96921Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
97021Sap25164 softc_p->param_status |= DCAM1394_STATUS_PARAM_CHANGE;
97121Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
97221Sap25164 }
97321Sap25164
97421Sap25164 if (ddi_copyout(param_list, (caddr_t)arg,
97521Sap25164 sizeof (dcam1394_param_list_t), mode)) {
97621Sap25164 rc = EFAULT;
97721Sap25164 goto done;
97821Sap25164 }
97921Sap25164 break;
98021Sap25164
98121Sap25164 case DCAM1394_CMD_FRAME_RCV_START:
98221Sap25164 if (dcam1394_ioctl_frame_rcv_start(softc_p)) {
98321Sap25164 rc = ENXIO;
98421Sap25164 }
98521Sap25164 break;
98621Sap25164
98721Sap25164 case DCAM1394_CMD_FRAME_RCV_STOP:
98821Sap25164 if (dcam_frame_rcv_stop(softc_p)) {
98921Sap25164 rc = ENXIO;
99021Sap25164 }
99121Sap25164 break;
99221Sap25164
99321Sap25164 case DCAM1394_CMD_RING_BUFF_FLUSH:
99421Sap25164 if (softc_p->ring_buff_p == NULL) {
99521Sap25164 rc = EAGAIN;
99621Sap25164 break;
99721Sap25164 }
99821Sap25164
99921Sap25164 /*
100021Sap25164 * the simplest way to flush ring_buff is to empty it
100121Sap25164 */
100221Sap25164 for (i = 0; i < softc_p->ring_buff_p->num_read_ptrs; i++) {
100321Sap25164 softc_p->ring_buff_p->read_ptr_pos[i] =
100421Sap25164 softc_p->ring_buff_p->write_ptr_pos;
100521Sap25164
100621Sap25164 /*
100721Sap25164 * if device driver is processing a user
100821Sap25164 * process's read() request
100921Sap25164 */
101021Sap25164 if (softc_p->reader_flags[i] &
101121Sap25164 DCAM1394_FLAG_READ_REQ_PROC) {
101221Sap25164
101321Sap25164 /*
101421Sap25164 * invalidate the read() request processing
101521Sap25164 * operation
101621Sap25164 */
101721Sap25164 softc_p->reader_flags[i] |=
101821Sap25164 DCAM1394_FLAG_READ_REQ_INVALID;
101921Sap25164 }
102021Sap25164 }
102121Sap25164 break;
102221Sap25164
102321Sap25164 case DCAM1394_CMD_FRAME_SEQ_NUM_COUNT_RESET:
102421Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
102521Sap25164 softc_p->seq_count = 0;
102621Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
102721Sap25164 break;
102821Sap25164
102921Sap25164 default:
103021Sap25164 rc = EIO;
103121Sap25164 break;
103221Sap25164
103321Sap25164 }
103421Sap25164
103521Sap25164 done:
103621Sap25164 if (param_list)
103721Sap25164 kmem_free(param_list, sizeof (dcam1394_param_list_t));
103821Sap25164
103921Sap25164 return (rc);
104021Sap25164 }
104121Sap25164
104221Sap25164
104321Sap25164 /*
104421Sap25164 * dcam_chpoll
104521Sap25164 */
104621Sap25164 /* ARGSUSED */
104721Sap25164 int
dcam_chpoll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)104821Sap25164 dcam_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
104921Sap25164 struct pollhead **phpp)
105021Sap25164 {
105121Sap25164 dcam_state_t *softc_p;
105221Sap25164 int instance, ring_buff_has_data, read_ptr_id;
105321Sap25164 size_t read_ptr_pos, write_ptr_pos;
105421Sap25164 short revent;
105521Sap25164
105621Sap25164 instance = DEV_TO_INSTANCE(dev);
105721Sap25164
105821Sap25164 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
105921Sap25164 if (softc_p == NULL) {
106021Sap25164 return (ENXIO);
106121Sap25164 }
106221Sap25164
106321Sap25164 read_ptr_id = 0;
106421Sap25164 revent = 0;
106521Sap25164
106621Sap25164 if (softc_p->ring_buff_p == NULL) {
106721Sap25164 ring_buff_has_data = 0;
106821Sap25164 } else {
106921Sap25164 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
107021Sap25164
107121Sap25164 read_ptr_pos =
107221Sap25164 ring_buff_read_ptr_pos_get(softc_p->ring_buff_p,
107321Sap25164 read_ptr_id);
107421Sap25164
107521Sap25164 write_ptr_pos =
107621Sap25164 ring_buff_write_ptr_pos_get(softc_p->ring_buff_p);
107721Sap25164
107821Sap25164 if (read_ptr_pos != write_ptr_pos) {
107921Sap25164 ring_buff_has_data = 1;
108021Sap25164 } else {
108121Sap25164 ring_buff_has_data = 0;
108221Sap25164 }
108321Sap25164
108421Sap25164 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
108521Sap25164 }
108621Sap25164
108721Sap25164 /*
108821Sap25164 * now check for events
108921Sap25164 */
109021Sap25164 if ((events & POLLRDNORM) && ring_buff_has_data) {
109121Sap25164 revent |= POLLRDNORM;
109221Sap25164 }
109321Sap25164
109421Sap25164 if ((events & POLLPRI) && softc_p->param_status) {
109521Sap25164 revent |= POLLPRI;
109621Sap25164 }
109721Sap25164
109821Sap25164 /* if no events have occurred */
109921Sap25164 if (revent == 0) {
110021Sap25164 if (!anyyet) {
110121Sap25164 *phpp = &softc_p->dcam_pollhead;
110221Sap25164 }
110321Sap25164 }
110421Sap25164
110521Sap25164 *reventsp = revent;
110621Sap25164
110721Sap25164 return (0);
110821Sap25164 }
110921Sap25164
111021Sap25164
111121Sap25164 /*
111221Sap25164 * dcam_bus_reset_notify
111321Sap25164 */
111421Sap25164 /* ARGSUSED */
111521Sap25164 void
dcam_bus_reset_notify(dev_info_t * dip,ddi_eventcookie_t ev_cookie,void * arg,void * impl_data)111621Sap25164 dcam_bus_reset_notify(dev_info_t *dip, ddi_eventcookie_t ev_cookie, void *arg,
111721Sap25164 void *impl_data)
111821Sap25164 {
111921Sap25164
112021Sap25164 dcam_state_t *softc_p;
112121Sap25164 t1394_localinfo_t *localinfo = impl_data;
112221Sap25164 t1394_targetinfo_t targetinfo;
112321Sap25164
112421Sap25164 softc_p = arg;
112521Sap25164
112621Sap25164 /*
112721Sap25164 * this is needed to handle LG camera "changing GUID" bug
112821Sap25164 * XXX: What's this about?
112921Sap25164 */
113021Sap25164 if ((dip == NULL) || (arg == NULL) || (impl_data == NULL) ||
113121Sap25164 (softc_p->sl_handle == NULL)) {
113221Sap25164 return;
113321Sap25164 }
113421Sap25164
113521Sap25164 localinfo = impl_data;
113621Sap25164
113721Sap25164 /*
113821Sap25164 * simply return if no target info
113921Sap25164 */
114021Sap25164 if (t1394_get_targetinfo(softc_p->sl_handle,
114121Sap25164 localinfo->bus_generation, 0, &targetinfo) != DDI_SUCCESS)
114221Sap25164 return;
114321Sap25164
114421Sap25164 if (localinfo->local_nodeID == softc_p->targetinfo.target_nodeID) {
114521Sap25164 softc_p->param_status |= DCAM1394_STATUS_CAM_UNPLUG;
114621Sap25164 } else {
114721Sap25164 softc_p->param_status &= ~DCAM1394_STATUS_CAM_UNPLUG;
114821Sap25164 }
114921Sap25164
115021Sap25164 /* struct copies */
115121Sap25164 softc_p->attachinfo.localinfo = *localinfo;
115221Sap25164
115321Sap25164 if (targetinfo.target_nodeID != T1394_INVALID_NODEID) {
115421Sap25164 softc_p->targetinfo.current_max_payload =
115521Sap25164 targetinfo.current_max_payload;
115621Sap25164
115721Sap25164 softc_p->targetinfo.current_max_speed =
115821Sap25164 targetinfo.current_max_speed;
115921Sap25164
116021Sap25164 softc_p->targetinfo.target_nodeID =
116121Sap25164 targetinfo.target_nodeID;
116221Sap25164 }
116321Sap25164 }
116421Sap25164
116521Sap25164
116621Sap25164 /*
116721Sap25164 * byte_copy_to_user_buff
116821Sap25164 */
116921Sap25164 static int
byte_copy_to_user_buff(uchar_t * src_addr_p,struct uio * uio_p,size_t num_bytes,int start_index,int * end_index_p)117021Sap25164 byte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p, size_t num_bytes,
117121Sap25164 int start_index, int *end_index_p)
117221Sap25164 {
117321Sap25164 int index;
117421Sap25164 size_t len;
117521Sap25164 uchar_t *u8_p;
117621Sap25164
117721Sap25164 index = start_index;
117821Sap25164 u8_p = (uchar_t *)src_addr_p;
117921Sap25164
118021Sap25164 while (num_bytes) {
118121Sap25164
118221Sap25164 len = num_bytes;
118321Sap25164
118421Sap25164 if (uiomove(u8_p, len, UIO_READ, uio_p)) {
118521Sap25164 return (-1);
118621Sap25164 }
118721Sap25164
118821Sap25164 index++;
118921Sap25164 u8_p += len;
119021Sap25164 num_bytes -= len;
119121Sap25164 }
119221Sap25164
119321Sap25164 *end_index_p = index;
119421Sap25164
119521Sap25164 return (0);
119621Sap25164 }
119721Sap25164
119821Sap25164
119921Sap25164 /*
120021Sap25164 * byte_copy_from_user_buff
120121Sap25164 */
120221Sap25164 static int
byte_copy_from_user_buff(uchar_t * dst_addr_p,struct uio * uio_p,size_t num_bytes,int start_index,int * end_index_p)120321Sap25164 byte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
120421Sap25164 size_t num_bytes, int start_index, int *end_index_p)
120521Sap25164 {
120621Sap25164 int index;
120721Sap25164 size_t len;
120821Sap25164 uchar_t *u8_p;
120921Sap25164
121021Sap25164 index = start_index;
121121Sap25164 u8_p = (uchar_t *)dst_addr_p;
121221Sap25164
121321Sap25164 while (num_bytes) {
121421Sap25164 len = num_bytes;
121521Sap25164
121621Sap25164 if (uiomove(u8_p, len, UIO_WRITE, uio_p)) {
121721Sap25164 return (-1);
121821Sap25164
121921Sap25164 }
122021Sap25164
122121Sap25164 index++;
122221Sap25164 u8_p += len;
122321Sap25164 num_bytes -= len;
122421Sap25164
122521Sap25164 }
122621Sap25164
122721Sap25164 *end_index_p = index;
122821Sap25164
122921Sap25164 return (0);
123021Sap25164 }
123121Sap25164
123221Sap25164
123321Sap25164 /*
123421Sap25164 * dcam_reset()
123521Sap25164 */
123621Sap25164 static int
dcam_reset(dcam_state_t * softc_p)123721Sap25164 dcam_reset(dcam_state_t *softc_p)
123821Sap25164 {
123921Sap25164 dcam1394_reg_io_t dcam_reg_io;
124021Sap25164
124121Sap25164 dcam_reg_io.offs = DCAM1394_REG_OFFS_INITIALIZE;
124221Sap25164 dcam_reg_io.val = DCAM1394_REG_VAL_INITIALIZE_ASSERT;
124321Sap25164
124421Sap25164 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
124521Sap25164 return (-1);
124621Sap25164 }
124721Sap25164
124821Sap25164 /*
124921Sap25164 * If the camera has a TI VSP, tweak the iris feature
125021Sap25164 * to "on" and value 4.
125121Sap25164 */
125221Sap25164 dcam_reg_io.offs = DCAM1394_REG_OFFS_FEATURE_CSR_BASE +
1253*7656SSherry.Moore@Sun.COM DCAM1394_REG_OFFS_IRIS_CSR;
125421Sap25164 dcam_reg_io.val = 0x82000004;
125521Sap25164
125621Sap25164 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
125721Sap25164 return (-1);
125821Sap25164 }
125921Sap25164
126021Sap25164 return (0);
126121Sap25164 }
1262