Print this page
fixup .text where possible
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/1394/targets/dcam1394/dcam.c
+++ new/usr/src/uts/common/io/1394/targets/dcam1394/dcam.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * dcam.c
29 29 *
30 30 * dcam1394 driver. Controls IIDC compliant devices attached through a
31 31 * IEEE-1394 bus.
32 32 */
33 33
34 34 #include <sys/conf.h>
35 35 #include <sys/ddi.h>
36 36 #include <sys/modctl.h>
37 37 #include <sys/sunndi.h>
38 38 #include <sys/types.h>
39 39 #include <sys/ddi.h>
40 40 #include <sys/sunddi.h>
41 41 #include <sys/file.h>
42 42 #include <sys/errno.h>
43 43 #include <sys/open.h>
44 44 #include <sys/cred.h>
45 45 #include <sys/mkdev.h>
46 46 #include <sys/kmem.h>
47 47 #include <sys/stat.h>
48 48 #include <sys/cmn_err.h>
49 49 #include <sys/stream.h>
50 50 #include <sys/buf.h>
51 51 #include <sys/uio.h>
52 52 #include <sys/devops.h>
53 53 #include <sys/1394/t1394.h>
54 54 #include <sys/tnf_probe.h>
55 55
56 56 #include <sys/dcam/dcam1394_io.h>
57 57 #include <sys/1394/targets/dcam1394/dcam.h>
58 58 #include <sys/1394/targets/dcam1394/dcam_reg.h>
59 59 #include <sys/1394/targets/dcam1394/dcam_param.h>
60 60 #include <sys/1394/targets/dcam1394/dcam_frame.h>
61 61
62 62 #ifndef NPROBE
63 63 extern int tnf_mod_load(void);
64 64 extern int tnf_mod_unload(struct modlinkage *mlp);
65 65 #endif /* ! NPROBE */
66 66
67 67
68 68 /* for power management (we have only one component) */
69 69 static char *dcam_pmc[] = {
70 70 "NAME=dcam1394",
71 71 "0=Off",
72 72 "1=On"
73 73 };
74 74
75 75 int g_vid_mode_frame_num_bytes[] =
76 76 {
77 77 57600, /* vid mode 0 */
78 78 153600, /* vid mode 1 */
79 79 460800, /* vid mode 2 */
80 80 614400, /* vid mode 3 */
81 81 921600, /* vid mode 4 */
82 82 307200 /* vid mode 5 */
83 83 };
84 84
85 85 static int byte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p,
86 86 size_t num_bytes, int start_index, int *end_index);
87 87 static int byte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
88 88 size_t num_bytes, int start_index, int *end_index);
89 89 static int dcam_reset(dcam_state_t *softc_p);
90 90
91 91 /* opaque state structure head */
92 92 void *dcam_state_p;
93 93
94 94 static struct cb_ops dcam_cb_ops = {
95 95 dcam_open, /* open */
96 96 dcam_close, /* close */
97 97 nodev, /* strategy */
98 98 nodev, /* print */
99 99 nodev, /* dump */
100 100 dcam_read, /* read */
101 101 nodev, /* write */
102 102 dcam_ioctl, /* ioctl */
103 103 nodev, /* devmap */
104 104 nodev, /* mmap */
105 105 nodev, /* segmap */
106 106 dcam_chpoll, /* chpoll */
107 107 ddi_prop_op, /* prop_op */
108 108 NULL, /* streams */
109 109 /* flags */
110 110 D_NEW | D_MP | D_64BIT | D_HOTPLUG,
111 111 CB_REV, /* rev */
112 112 nodev, /* aread */
113 113 nodev /* awrite */
114 114 };
115 115
116 116 static struct dev_ops dcam_dev_ops = {
117 117 DEVO_REV, /* DEVO_REV indicated by manual */
118 118 0, /* device reference count */
119 119 dcam_getinfo, /* getinfo */
120 120 nulldev, /* identify */
121 121 nulldev, /* probe */
122 122 dcam_attach, /* attach */
123 123 dcam_detach, /* detach */
124 124 nodev, /* reset */
125 125 &dcam_cb_ops, /* ptr to cb_ops struct */
126 126 NULL, /* ptr to bus_ops struct; none */
127 127 dcam_power, /* power */
128 128 ddi_quiesce_not_supported, /* devo_quiesce */
129 129 };
130 130
↓ open down ↓ |
130 lines elided |
↑ open up ↑ |
131 131 extern struct mod_ops mod_driverops;
132 132
133 133 static struct modldrv modldrv = {
134 134 &mod_driverops,
135 135 "SUNW 1394-based Digital Camera driver",
136 136 &dcam_dev_ops,
137 137 };
138 138
139 139 static struct modlinkage modlinkage = {
140 140 MODREV_1,
141 - (void *)&modldrv,
142 - NULL,
141 + { (void *)&modldrv,
142 + NULL }
143 143 };
144 144
145 145
146 146 int
147 147 _init(void)
148 148 {
149 149 int err;
150 150
151 151 err = ddi_soft_state_init(&dcam_state_p, sizeof (dcam_state_t), 2);
152 152
153 153 if (err) {
154 154 return (err);
155 155 }
156 156
157 157 #ifndef NPROBE
158 158 (void) tnf_mod_load();
159 159 #endif /* ! NPROBE */
160 160
161 161 if (err = mod_install(&modlinkage)) {
162 162
163 163 #ifndef NPROBE
164 164 (void) tnf_mod_unload(&modlinkage);
165 165 #endif /* ! NPROBE */
166 166
167 167 ddi_soft_state_fini(&dcam_state_p);
168 168
169 169 }
170 170
171 171 return (err);
172 172 }
173 173
174 174
175 175 int
176 176 _info(struct modinfo *modinfop)
177 177 {
178 178 int err;
179 179
180 180 err = mod_info(&modlinkage, modinfop);
181 181 return (err);
182 182 }
183 183
184 184
185 185 int
186 186 _fini(void)
187 187 {
188 188 int err;
189 189
190 190 if ((err = mod_remove(&modlinkage)) != 0) {
191 191 return (err);
192 192 }
193 193
194 194 #ifndef NPROBE
195 195 (void) tnf_mod_unload(&modlinkage);
196 196 #endif /* ! NPROBE */
197 197
198 198 ddi_soft_state_fini(&dcam_state_p);
199 199
200 200 return (err);
201 201 }
202 202
203 203
204 204 /*
205 205 * dcam_attach
206 206 */
207 207 /* ARGSUSED */
208 208 int
209 209 dcam_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
210 210 {
211 211 char tmp_str[MAX_STR_LEN];
212 212 dcam_state_t *softc_p;
213 213 ddi_eventcookie_t ev_cookie;
214 214 int instance;
215 215 int ret_val;
216 216
217 217 switch (cmd) {
218 218
219 219 case DDI_ATTACH:
220 220 instance = ddi_get_instance(dip);
221 221
222 222 if (ddi_soft_state_zalloc(dcam_state_p, instance) !=
223 223 DDI_SUCCESS) {
224 224 return (DDI_FAILURE);
225 225 }
226 226
227 227 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
228 228 NULL) {
229 229 ddi_soft_state_free(dcam_state_p, instance);
230 230 return (DDI_FAILURE);
231 231 }
232 232
233 233 /*
234 234 * Initialize soft state
235 235 */
236 236 softc_p->dip = dip;
237 237 softc_p->instance = instance;
238 238 softc_p->usr_model = -1;
239 239 softc_p->ixlp = NULL;
240 240
241 241 softc_p->seq_count = 0;
242 242 softc_p->param_status = 0;
243 243
244 244 /*
245 245 * set default vid_mode, frame_rate and ring_buff_capacity
246 246 */
247 247 softc_p->cur_vid_mode = 1;
248 248 softc_p->cur_frame_rate = 3;
249 249 softc_p->cur_ring_buff_capacity = 10;
250 250 softc_p->camera_online = 1;
251 251
252 252 (void) sprintf(tmp_str, "dcam%d", instance);
253 253
254 254 if (ddi_create_minor_node(dip, tmp_str, S_IFCHR, instance,
255 255 DDI_PSEUDO, 0) != DDI_SUCCESS) {
256 256 ddi_soft_state_free(dcam_state_p, instance);
257 257
258 258 return (DDI_FAILURE);
259 259 }
260 260
261 261 (void) sprintf(tmp_str, "dcamctl%d", instance);
262 262
263 263 if (ddi_create_minor_node(dip, tmp_str, S_IFCHR,
264 264 instance + DCAM1394_MINOR_CTRL, "ddi_dcam1394", 0) !=
265 265 DDI_SUCCESS) {
266 266 ddi_soft_state_free(dcam_state_p, instance);
267 267
268 268 return (DDI_FAILURE);
269 269 }
270 270
271 271 if (t1394_attach(dip, T1394_VERSION_V1, 0,
272 272 &(softc_p->attachinfo),
273 273 &(softc_p->sl_handle)) != DDI_SUCCESS) {
274 274 ddi_soft_state_free(dcam_state_p, instance);
275 275 ddi_remove_minor_node(dip, NULL);
276 276
277 277 return (DDI_FAILURE);
278 278 }
279 279
280 280 if (t1394_get_targetinfo(softc_p->sl_handle,
281 281 softc_p->attachinfo.localinfo.bus_generation, 0,
282 282 &(softc_p->targetinfo)) != DDI_SUCCESS) {
283 283 cmn_err(CE_WARN,
284 284 "dcam_attach: t1394_get_targetinfo failed\n");
285 285 }
286 286
287 287 if (ddi_get_eventcookie(dip, DDI_DEVI_BUS_RESET_EVENT,
288 288 &ev_cookie) != DDI_SUCCESS) {
289 289 (void) t1394_detach(&softc_p->sl_handle, 0);
290 290
291 291 ddi_soft_state_free(dcam_state_p, instance);
292 292 ddi_remove_minor_node(dip, NULL);
293 293
294 294 return (DDI_FAILURE);
295 295 }
296 296
297 297 if (ddi_add_event_handler(dip, ev_cookie, dcam_bus_reset_notify,
298 298 softc_p, &softc_p->event_id) != DDI_SUCCESS) {
299 299 (void) t1394_detach(&softc_p->sl_handle, 0);
300 300
301 301 ddi_soft_state_free(dcam_state_p, instance);
302 302 ddi_remove_minor_node(dip, NULL);
303 303
304 304 return (DDI_FAILURE);
305 305 }
306 306
307 307 mutex_init(&softc_p->softc_mutex, NULL, MUTEX_DRIVER,
308 308 softc_p->attachinfo.iblock_cookie);
309 309
310 310 mutex_init(&softc_p->dcam_frame_is_done_mutex, NULL,
311 311 MUTEX_DRIVER, softc_p->attachinfo.iblock_cookie);
312 312
313 313 /*
314 314 * init the soft state's parameter attribute structure
315 315 */
316 316 if (param_attr_init(softc_p, softc_p->param_attr) !=
317 317 DDI_SUCCESS) {
318 318 (void) ddi_remove_event_handler(softc_p->event_id);
319 319 (void) t1394_detach(&softc_p->sl_handle, 0);
320 320
321 321 ddi_soft_state_free(dcam_state_p, instance);
322 322 ddi_remove_minor_node(dip, NULL);
323 323
324 324 return (DDI_FAILURE);
325 325 }
326 326
327 327 /*
328 328 * power management stuff
329 329 */
330 330 if (ddi_prop_update_string_array(DDI_DEV_T_NONE,
331 331 dip, "pm-components", dcam_pmc,
332 332 sizeof (dcam_pmc)/sizeof (char *)) == DDI_PROP_SUCCESS) {
333 333
334 334 (void) pm_raise_power(dip, 0, 1);
335 335 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, 0,
336 336 "power-managed?")) {
337 337 (void) pm_idle_component(dip, 0);
338 338 } else {
339 339 (void) pm_busy_component(dip, 0);
340 340 }
341 341 }
342 342
343 343 softc_p->flags |= DCAM1394_FLAG_ATTACH_COMPLETE;
344 344
345 345 ddi_report_dev(dip);
346 346 ret_val = DDI_SUCCESS;
347 347 break;
348 348
349 349 case DDI_RESUME:
350 350 instance = ddi_get_instance(dip);
351 351 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) ==
352 352 NULL) {
353 353 ddi_soft_state_free(dcam_state_p, instance);
354 354 return (DDI_FAILURE);
355 355 }
356 356
357 357 mutex_enter(&softc_p->softc_mutex);
358 358
359 359 if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
360 360 (void) dcam1394_ioctl_frame_rcv_start(softc_p);
361 361 }
362 362
363 363 softc_p->suspended = 0;
364 364
365 365 mutex_exit(&softc_p->softc_mutex);
366 366
367 367 ret_val = DDI_SUCCESS;
368 368 break;
369 369
370 370 default:
371 371 ret_val = DDI_FAILURE;
372 372 break;
373 373 }
374 374
375 375 return (ret_val);
376 376 }
377 377
378 378
379 379 /*
380 380 * dcam_power: perform dcam power management
381 381 */
382 382 /* ARGSUSED */
383 383 int
384 384 dcam_power(dev_info_t *dip, int component, int level)
385 385 {
386 386 dcam_state_t *softc_p;
387 387 int instance;
388 388
389 389 instance = ddi_get_instance(dip);
390 390 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
391 391
392 392 if (softc_p == NULL)
393 393 return (DDI_FAILURE);
394 394
395 395 softc_p->pm_cable_power = level;
396 396
397 397 return (DDI_SUCCESS);
398 398
399 399 }
400 400
401 401
402 402 /*
403 403 * dcam_getinfo
404 404 */
405 405 /* ARGSUSED */
406 406 int
407 407 dcam_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
408 408 {
409 409 dev_t dev;
410 410 dcam_state_t *softc_p;
411 411 int status;
412 412 int instance;
413 413
414 414 switch (cmd) {
415 415
416 416 case DDI_INFO_DEVT2DEVINFO:
417 417 dev = (dev_t)arg;
418 418 instance = DEV_TO_INSTANCE(dev);
419 419 softc_p = (dcam_state_t *)
420 420 ddi_get_soft_state(dcam_state_p, instance);
421 421
422 422 if (softc_p == NULL) {
423 423 return (DDI_FAILURE);
424 424 }
425 425
426 426 *result = (void *)softc_p->dip;
427 427 status = DDI_SUCCESS;
428 428 break;
429 429
430 430 case DDI_INFO_DEVT2INSTANCE:
431 431 dev = (dev_t)arg;
432 432 instance = DEV_TO_INSTANCE(dev);
433 433 *result = (void *)(uintptr_t)instance;
434 434 status = DDI_SUCCESS;
435 435 break;
436 436
437 437 default:
438 438 status = DDI_FAILURE;
439 439 }
440 440
441 441 return (status);
442 442 }
443 443
444 444
445 445 /*
446 446 * dcam_detach
447 447 */
448 448 /* ARGSUSED */
449 449 int
450 450 dcam_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
451 451 {
452 452 int instance;
453 453 dcam_state_t *softc_p;
454 454
455 455 instance = ddi_get_instance(dip);
456 456
457 457 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
458 458 if (softc_p == NULL) {
459 459 return (DDI_FAILURE);
460 460 }
461 461
462 462
463 463 switch (cmd) {
464 464
465 465 case DDI_SUSPEND:
466 466 mutex_enter(&softc_p->softc_mutex);
467 467
468 468 softc_p->suspended = 1;
469 469
470 470 if (softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
471 471 (void) dcam_frame_rcv_stop(softc_p);
472 472 }
473 473
474 474 mutex_exit(&softc_p->softc_mutex);
475 475 return (DDI_SUCCESS);
476 476
477 477
478 478 case DDI_DETACH:
479 479 /*
480 480 * power management stuff
481 481 */
482 482 (void) pm_lower_power(dip, 0, 0);
483 483 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
484 484
485 485 /*
486 486 * deregister with 1394 DDI framework
487 487 */
488 488 if (t1394_detach(&softc_p->sl_handle, 0) != DDI_SUCCESS) {
489 489 return (DDI_FAILURE);
490 490 }
491 491
492 492 (void) ddi_remove_event_handler(softc_p->event_id);
493 493
494 494 /*
495 495 * free state structures, mutexes, condvars;
496 496 * deregister interrupts
497 497 */
498 498 mutex_destroy(&softc_p->softc_mutex);
499 499 mutex_destroy(&softc_p->dcam_frame_is_done_mutex);
500 500
501 501 /*
502 502 * Remove all minor nodes, all dev_t's properties
503 503 */
504 504 ddi_remove_minor_node(dip, NULL);
505 505
506 506 ddi_soft_state_free(dcam_state_p, instance);
507 507 ddi_prop_remove_all(dip);
508 508
509 509 return (DDI_SUCCESS);
510 510
511 511 default:
512 512 return (DDI_FAILURE);
513 513
514 514 }
515 515 }
516 516
517 517
518 518 /*
519 519 * dcam_open
520 520 */
521 521 /* ARGSUSED */
522 522 int
523 523 dcam_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
524 524 {
525 525 dcam_state_t *softc_p;
526 526 int instance;
527 527 int is_ctrl_file;
528 528 uint_t new_flags;
529 529
530 530 instance = (int)DEV_TO_INSTANCE(*dev_p);
531 531
532 532 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
533 533 return (ENXIO);
534 534 }
535 535
536 536 /*
537 537 * if dcam_attach hasn't completed, return error
538 538 * XXX: Check this out
539 539 */
540 540 if (!(softc_p->flags & DCAM1394_FLAG_ATTACH_COMPLETE)) {
541 541 return (ENXIO);
542 542 }
543 543
544 544 /* disallow block, mount, and layered opens */
545 545 if (otyp != OTYP_CHR) {
546 546 return (EINVAL);
547 547 }
548 548
549 549 new_flags = 0;
550 550 is_ctrl_file = (getminor(*dev_p) & DCAM1394_MINOR_CTRL) ? 1 : 0;
551 551
552 552 mutex_enter(&softc_p->softc_mutex);
553 553
554 554 /*
555 555 * The open is either for the capture file or the control file.
556 556 * If it's the control file construct new flags.
557 557 *
558 558 * If it's the capture file return busy if it's already open,
559 559 * otherwise construct new flags.
560 560 */
561 561 if (is_ctrl_file) {
562 562 new_flags |= DCAM1394_FLAG_OPEN_CONTROL;
563 563 } else {
564 564 if (softc_p->flags & DCAM1394_FLAG_OPEN_CAPTURE) {
565 565 mutex_exit(&softc_p->softc_mutex);
566 566 return (EBUSY);
567 567 }
568 568
569 569 new_flags |= DCAM1394_FLAG_OPEN_CAPTURE;
570 570 }
571 571
572 572 new_flags |= DCAM1394_FLAG_OPEN;
573 573 softc_p->flags |= new_flags;
574 574
575 575 mutex_exit(&softc_p->softc_mutex);
576 576
577 577 /*
578 578 * power management stuff
579 579 */
580 580 if (softc_p->pm_open_count == 0) {
581 581 if (ddi_prop_exists(DDI_DEV_T_ANY, softc_p->dip, 0,
582 582 "power-managed?")) {
583 583 (void) pm_busy_component(softc_p->dip, 0);
584 584 if (softc_p->pm_cable_power == 0) {
585 585 int i;
586 586
587 587 (void) pm_raise_power(softc_p->dip, 0, 1);
588 588
589 589 /*
590 590 * Wait for the power to be up and stable
591 591 * before proceeding. 100 msecs should
592 592 * certainly be enough, and if we check
593 593 * every msec we'll probably loop just a
594 594 * few times.
595 595 */
596 596 for (i = 0; i < 100; i++) {
597 597 if (param_power_set(softc_p, 1) == 0) {
598 598 break;
599 599 }
600 600 delay((clock_t)drv_usectohz(1000));
601 601 }
602 602 }
603 603 }
604 604 }
605 605 softc_p->pm_open_count++;
606 606
607 607 return (0);
608 608 }
609 609
610 610
611 611 /*
612 612 * dcam_close
613 613 */
614 614 /* ARGSUSED */
615 615 int
616 616 dcam_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
617 617 {
618 618 int instance;
619 619 dcam_state_t *softc;
620 620
621 621 instance = DEV_TO_INSTANCE(dev);
622 622 softc = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
623 623
624 624 /*
625 625 * power management stuff
626 626 */
627 627 softc->pm_open_count = 0;
628 628 if (ddi_prop_exists(DDI_DEV_T_ANY, softc->dip, 0, "power-managed?")) {
629 629 (void) pm_idle_component(softc->dip, 0);
630 630 }
631 631
632 632 mutex_enter(&softc->softc_mutex);
633 633
634 634 if (getminor(dev) & DCAM1394_MINOR_CTRL) {
635 635 softc->flags &= ~DCAM1394_FLAG_OPEN_CONTROL;
636 636 } else {
637 637 /*
638 638 * If an application which has opened the camera capture
639 639 * device exits without calling DCAM1394_CMD_FRAME_RCV_STOP
640 640 * ioctl, then we need to release resources.
641 641 */
642 642 if (softc->flags & DCAM1394_FLAG_FRAME_RCV_INIT) {
643 643 (void) dcam_frame_rcv_stop(softc);
644 644 softc->flags &= ~DCAM1394_FLAG_FRAME_RCV_INIT;
645 645 }
646 646
647 647 (void) param_power_set(softc, 0);
648 648
649 649 softc->flags &= ~DCAM1394_FLAG_OPEN_CAPTURE;
650 650 }
651 651
652 652 /*
653 653 * If driver is completely closed, then stabilize the camera
654 654 * and turn off transient flags
655 655 */
656 656 if (!(softc->flags &
657 657 (DCAM1394_FLAG_OPEN_CONTROL | DCAM1394_FLAG_OPEN_CAPTURE))) {
658 658 softc->flags &= DCAM1394_FLAG_ATTACH_COMPLETE;
659 659 }
660 660
661 661 mutex_exit(&softc->softc_mutex);
662 662
663 663 return (DDI_SUCCESS);
664 664
665 665 }
666 666
667 667
668 668 /*
669 669 * dcam_read
670 670 *
671 671 * If read pointer is not pointing to the same position as write pointer
672 672 * copy frame data from ring buffer position pointed to by read pointer.
673 673 *
674 674 * If during the course of copying frame data, the device driver
675 675 * invalidated this read() request processing operation, restart
676 676 * this operation.
677 677 *
678 678 * Increment read pointer and return frame data to user process.
679 679 *
680 680 * Else return error
681 681 *
682 682 */
683 683 /* ARGSUSED */
684 684 int
685 685 dcam_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
686 686 {
687 687 buff_info_t *buff_info_p;
688 688 dcam_state_t *softc_p;
689 689 hrtime_t timestamp;
690 690 int index, instance;
691 691 int read_ptr_id;
692 692 size_t read_ptr_pos, write_ptr_pos;
693 693 int read_req_invalid;
694 694 ring_buff_t *ring_buff_p;
695 695 uchar_t *frame_data_p;
696 696 uint_t seq_num;
697 697 unsigned long user_frame_buff_addr;
698 698 uint_t vid_mode;
699 699 int gotten_addr_flag;
700 700
701 701 instance = DEV_TO_INSTANCE(dev);
702 702
703 703 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
704 704 if (softc_p == NULL) {
705 705 return (ENXIO);
706 706 }
707 707
708 708 if ((ring_buff_p = softc_p->ring_buff_p) == NULL) {
709 709 return (EAGAIN);
710 710 }
711 711
712 712 read_ptr_id = 0;
713 713
714 714 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
715 715
716 716 softc_p->reader_flags[read_ptr_id] |= DCAM1394_FLAG_READ_REQ_PROC;
717 717
718 718 user_frame_buff_addr = 0;
719 719 gotten_addr_flag = 0;
720 720
721 721 do {
722 722 read_ptr_pos = ring_buff_read_ptr_pos_get(ring_buff_p,
723 723 read_ptr_id);
724 724
725 725 write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
726 726
727 727 if (read_ptr_pos != write_ptr_pos) {
728 728 /*
729 729 * Since the app wants realtime video, set the read
730 730 * pointer to the newest data.
731 731 */
732 732 if (write_ptr_pos == 0) {
733 733 read_ptr_pos = ring_buff_p->num_buffs - 1;
734 734 } else {
735 735 read_ptr_pos = write_ptr_pos - 1;
736 736 }
737 737
738 738 /*
739 739 * copy frame data from ring buffer position pointed
740 740 * to by read pointer
741 741 */
742 742 index = 0;
743 743 buff_info_p =
744 744 &(ring_buff_p->buff_info_array_p[read_ptr_pos]);
745 745
746 746 vid_mode = softc_p->cur_vid_mode;
747 747 seq_num = buff_info_p->seq_num;
748 748 timestamp = buff_info_p->timestamp;
749 749 frame_data_p = (uchar_t *)buff_info_p->kaddr_p;
750 750
751 751 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
752 752
753 753 /*
754 754 * Fix for bug #4424042
755 755 * don't lock this section
756 756 */
757 757
758 758 if (byte_copy_to_user_buff((uchar_t *)&vid_mode,
759 759 uio_p, sizeof (uint_t), index, &index)) {
760 760
761 761 return (EFAULT);
762 762 }
763 763
764 764 if (byte_copy_to_user_buff((uchar_t *)&seq_num,
765 765 uio_p, sizeof (unsigned int), index, &index)) {
766 766
767 767 return (EFAULT);
768 768 }
769 769
770 770 if (byte_copy_to_user_buff((uchar_t *)×tamp,
771 771 uio_p, sizeof (hrtime_t), index, &index)) {
772 772
773 773 return (EFAULT);
774 774 }
775 775
776 776 /*
777 777 * get buff pointer; do ddi_copyout()
778 778 * get user buffer address only once
779 779 */
780 780 if (!gotten_addr_flag) {
781 781 if (byte_copy_from_user_buff(
782 782 (uchar_t *)&user_frame_buff_addr, uio_p,
783 783 softc_p->usr_model, index, &index)) {
784 784
785 785 return (EFAULT);
786 786 }
787 787
788 788 #ifdef _MULTI_DATAMODEL
789 789 if (softc_p->usr_model == ILP32_PTR_SIZE) {
790 790 user_frame_buff_addr =
791 791 ((user_frame_buff_addr >> 32) &
792 792 0xffffffffULL) |
793 793 ((user_frame_buff_addr << 32) &
794 794 0xffffffff00000000ULL);
795 795 }
796 796 #endif /* _MULTI_DATAMODEL */
797 797
798 798 gotten_addr_flag = 1;
799 799 }
800 800
801 801 if (ddi_copyout(
802 802 (caddr_t)frame_data_p,
803 803 (caddr_t)user_frame_buff_addr,
804 804 g_vid_mode_frame_num_bytes[softc_p->cur_vid_mode],
805 805 0)) {
806 806 return (EFAULT);
807 807 }
808 808
809 809 /*
810 810 * if during the course of copying frame data,
811 811 * the device driver invalidated this read()
812 812 * request processing operation; restart this
813 813 * operation
814 814 */
815 815
816 816 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
817 817
818 818 read_req_invalid = softc_p->reader_flags[read_ptr_id] &
819 819 DCAM1394_FLAG_READ_REQ_INVALID;
820 820
821 821 softc_p->reader_flags[read_ptr_id] &=
822 822 ~(DCAM1394_FLAG_READ_REQ_INVALID);
823 823
824 824 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
825 825
826 826 } else {
827 827 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
828 828 return (EAGAIN);
829 829 }
830 830
831 831 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
832 832 } while (read_req_invalid);
833 833
834 834 /*
835 835 * return number of bytes actually written to user space
836 836 */
837 837 uio_p->uio_resid -= g_vid_mode_frame_num_bytes[softc_p->cur_vid_mode];
838 838
839 839 softc_p->reader_flags[read_ptr_id] &= ~(DCAM1394_FLAG_READ_REQ_PROC);
840 840
841 841 /* increment read pointer */
842 842 ring_buff_read_ptr_incr(ring_buff_p, read_ptr_id);
843 843
844 844 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
845 845
846 846 return (0);
847 847 }
848 848
849 849
850 850 /*
851 851 * dcam_ioctl
852 852 */
853 853 /* ARGSUSED */
854 854 int
855 855 dcam_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
856 856 int *rvalp)
857 857 {
858 858 dcam_state_t *softc_p;
859 859 dcam1394_param_list_t *param_list;
860 860 dcam1394_reg_io_t dcam_reg_io;
861 861 int instance, is_ctrl_file, rc, i;
862 862
863 863 rc = 0;
864 864 param_list = (dcam1394_param_list_t *)0;
865 865
866 866 instance = DEV_TO_INSTANCE(dev);
867 867
868 868 if ((softc_p = ddi_get_soft_state(dcam_state_p, instance)) == NULL) {
869 869 rc = ENXIO;
870 870 goto done;
871 871 }
872 872
873 873 /*
874 874 * determine user applications data model
875 875 */
876 876 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32)
877 877 softc_p->usr_model = ILP32_PTR_SIZE;
878 878 else
879 879 softc_p->usr_model = LP64_PTR_SIZE;
880 880
881 881
882 882 switch (cmd) {
883 883
884 884 case DCAM1394_CMD_REG_READ:
885 885 if (ddi_copyin((caddr_t)arg, &dcam_reg_io,
886 886 sizeof (dcam1394_reg_io_t), mode)) {
887 887 rc = EFAULT;
888 888 goto done;
889 889 }
890 890
891 891 if (dcam_reg_read(softc_p, &dcam_reg_io)) {
892 892 rc = EFAULT;
893 893 goto done;
894 894 }
895 895
896 896 if (ddi_copyout(&dcam_reg_io, (caddr_t)arg,
897 897 sizeof (dcam1394_reg_io_t), mode)) {
898 898 rc = EFAULT;
899 899 goto done;
900 900 }
901 901 break;
902 902
903 903 case DCAM1394_CMD_REG_WRITE:
904 904 if (ddi_copyin((caddr_t)arg, &dcam_reg_io,
905 905 sizeof (dcam1394_reg_io_t), mode)) {
906 906 rc = EFAULT;
907 907 goto done;
908 908 }
909 909
910 910 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
911 911 rc = EFAULT;
912 912 goto done;
913 913 }
914 914
915 915 if (ddi_copyout(&dcam_reg_io, (caddr_t)arg,
916 916 sizeof (dcam1394_reg_io_t), mode)) {
917 917 rc = EFAULT;
918 918 goto done;
919 919 }
920 920 break;
921 921
922 922 case DCAM1394_CMD_CAM_RESET:
923 923 if (dcam_reset(softc_p)) {
924 924 rc = EIO;
925 925 goto done;
926 926 }
927 927 break;
928 928
929 929 case DCAM1394_CMD_PARAM_GET:
930 930 param_list = (dcam1394_param_list_t *)
931 931 kmem_alloc(sizeof (dcam1394_param_list_t), KM_SLEEP);
932 932
933 933 if (ddi_copyin((caddr_t)arg, (caddr_t)param_list,
934 934 sizeof (dcam1394_param_list_t), mode)) {
935 935 rc = EFAULT;
936 936 goto done;
937 937 }
938 938
939 939 if (dcam1394_ioctl_param_get(softc_p, *param_list)) {
940 940 rc = EINVAL;
941 941 }
942 942
943 943 if (ddi_copyout((caddr_t)param_list, (caddr_t)arg,
944 944 sizeof (dcam1394_param_list_t), mode)) {
945 945 rc = EFAULT;
946 946 goto done;
947 947 }
948 948 break;
949 949
950 950 case DCAM1394_CMD_PARAM_SET:
951 951 param_list = (dcam1394_param_list_t *)
952 952 kmem_alloc((size_t)sizeof (dcam1394_param_list_t),
953 953 KM_SLEEP);
954 954
955 955 if (ddi_copyin((caddr_t)arg, (caddr_t)param_list,
956 956 sizeof (dcam1394_param_list_t), mode)) {
957 957 rc = EFAULT;
958 958 goto done;
959 959 }
960 960
961 961 is_ctrl_file = (getminor(dev) & DCAM1394_MINOR_CTRL) ? 1:0;
962 962
963 963 if (dcam1394_ioctl_param_set(softc_p, is_ctrl_file,
964 964 *param_list)) {
965 965 rc = EINVAL;
966 966 }
967 967
968 968 if (is_ctrl_file) {
969 969 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
970 970 softc_p->param_status |= DCAM1394_STATUS_PARAM_CHANGE;
971 971 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
972 972 }
973 973
974 974 if (ddi_copyout(param_list, (caddr_t)arg,
975 975 sizeof (dcam1394_param_list_t), mode)) {
976 976 rc = EFAULT;
977 977 goto done;
978 978 }
979 979 break;
980 980
981 981 case DCAM1394_CMD_FRAME_RCV_START:
982 982 if (dcam1394_ioctl_frame_rcv_start(softc_p)) {
983 983 rc = ENXIO;
984 984 }
985 985 break;
986 986
987 987 case DCAM1394_CMD_FRAME_RCV_STOP:
988 988 if (dcam_frame_rcv_stop(softc_p)) {
989 989 rc = ENXIO;
990 990 }
991 991 break;
992 992
993 993 case DCAM1394_CMD_RING_BUFF_FLUSH:
994 994 if (softc_p->ring_buff_p == NULL) {
995 995 rc = EAGAIN;
996 996 break;
997 997 }
998 998
999 999 /*
1000 1000 * the simplest way to flush ring_buff is to empty it
1001 1001 */
1002 1002 for (i = 0; i < softc_p->ring_buff_p->num_read_ptrs; i++) {
1003 1003 softc_p->ring_buff_p->read_ptr_pos[i] =
1004 1004 softc_p->ring_buff_p->write_ptr_pos;
1005 1005
1006 1006 /*
1007 1007 * if device driver is processing a user
1008 1008 * process's read() request
1009 1009 */
1010 1010 if (softc_p->reader_flags[i] &
1011 1011 DCAM1394_FLAG_READ_REQ_PROC) {
1012 1012
1013 1013 /*
1014 1014 * invalidate the read() request processing
1015 1015 * operation
1016 1016 */
1017 1017 softc_p->reader_flags[i] |=
1018 1018 DCAM1394_FLAG_READ_REQ_INVALID;
1019 1019 }
1020 1020 }
1021 1021 break;
1022 1022
1023 1023 case DCAM1394_CMD_FRAME_SEQ_NUM_COUNT_RESET:
1024 1024 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
1025 1025 softc_p->seq_count = 0;
1026 1026 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
1027 1027 break;
1028 1028
1029 1029 default:
1030 1030 rc = EIO;
1031 1031 break;
1032 1032
1033 1033 }
1034 1034
1035 1035 done:
1036 1036 if (param_list)
1037 1037 kmem_free(param_list, sizeof (dcam1394_param_list_t));
1038 1038
1039 1039 return (rc);
1040 1040 }
1041 1041
1042 1042
1043 1043 /*
1044 1044 * dcam_chpoll
1045 1045 */
1046 1046 /* ARGSUSED */
1047 1047 int
1048 1048 dcam_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
1049 1049 struct pollhead **phpp)
1050 1050 {
1051 1051 dcam_state_t *softc_p;
1052 1052 int instance, ring_buff_has_data, read_ptr_id;
1053 1053 size_t read_ptr_pos, write_ptr_pos;
1054 1054 short revent;
1055 1055
1056 1056 instance = DEV_TO_INSTANCE(dev);
1057 1057
1058 1058 softc_p = (dcam_state_t *)ddi_get_soft_state(dcam_state_p, instance);
1059 1059 if (softc_p == NULL) {
1060 1060 return (ENXIO);
1061 1061 }
1062 1062
1063 1063 read_ptr_id = 0;
1064 1064 revent = 0;
1065 1065
1066 1066 if (softc_p->ring_buff_p == NULL) {
1067 1067 ring_buff_has_data = 0;
1068 1068 } else {
1069 1069 mutex_enter(&softc_p->dcam_frame_is_done_mutex);
1070 1070
1071 1071 read_ptr_pos =
1072 1072 ring_buff_read_ptr_pos_get(softc_p->ring_buff_p,
1073 1073 read_ptr_id);
1074 1074
1075 1075 write_ptr_pos =
1076 1076 ring_buff_write_ptr_pos_get(softc_p->ring_buff_p);
1077 1077
1078 1078 if (read_ptr_pos != write_ptr_pos) {
1079 1079 ring_buff_has_data = 1;
1080 1080 } else {
1081 1081 ring_buff_has_data = 0;
1082 1082 }
1083 1083
1084 1084 mutex_exit(&softc_p->dcam_frame_is_done_mutex);
1085 1085 }
1086 1086
1087 1087 /*
1088 1088 * now check for events
1089 1089 */
1090 1090 if ((events & POLLRDNORM) && ring_buff_has_data) {
1091 1091 revent |= POLLRDNORM;
1092 1092 }
1093 1093
1094 1094 if ((events & POLLPRI) && softc_p->param_status) {
1095 1095 revent |= POLLPRI;
1096 1096 }
1097 1097
1098 1098 /* if no events have occurred */
1099 1099 if (revent == 0) {
1100 1100 if (!anyyet) {
1101 1101 *phpp = &softc_p->dcam_pollhead;
1102 1102 }
1103 1103 }
1104 1104
1105 1105 *reventsp = revent;
1106 1106
1107 1107 return (0);
1108 1108 }
1109 1109
1110 1110
1111 1111 /*
1112 1112 * dcam_bus_reset_notify
1113 1113 */
1114 1114 /* ARGSUSED */
1115 1115 void
1116 1116 dcam_bus_reset_notify(dev_info_t *dip, ddi_eventcookie_t ev_cookie, void *arg,
1117 1117 void *impl_data)
1118 1118 {
1119 1119
1120 1120 dcam_state_t *softc_p;
1121 1121 t1394_localinfo_t *localinfo = impl_data;
1122 1122 t1394_targetinfo_t targetinfo;
1123 1123
1124 1124 softc_p = arg;
1125 1125
1126 1126 /*
1127 1127 * this is needed to handle LG camera "changing GUID" bug
1128 1128 * XXX: What's this about?
1129 1129 */
1130 1130 if ((dip == NULL) || (arg == NULL) || (impl_data == NULL) ||
1131 1131 (softc_p->sl_handle == NULL)) {
1132 1132 return;
1133 1133 }
1134 1134
1135 1135 localinfo = impl_data;
1136 1136
1137 1137 /*
1138 1138 * simply return if no target info
1139 1139 */
1140 1140 if (t1394_get_targetinfo(softc_p->sl_handle,
1141 1141 localinfo->bus_generation, 0, &targetinfo) != DDI_SUCCESS)
1142 1142 return;
1143 1143
1144 1144 if (localinfo->local_nodeID == softc_p->targetinfo.target_nodeID) {
1145 1145 softc_p->param_status |= DCAM1394_STATUS_CAM_UNPLUG;
1146 1146 } else {
1147 1147 softc_p->param_status &= ~DCAM1394_STATUS_CAM_UNPLUG;
1148 1148 }
1149 1149
1150 1150 /* struct copies */
1151 1151 softc_p->attachinfo.localinfo = *localinfo;
1152 1152
1153 1153 if (targetinfo.target_nodeID != T1394_INVALID_NODEID) {
1154 1154 softc_p->targetinfo.current_max_payload =
1155 1155 targetinfo.current_max_payload;
1156 1156
1157 1157 softc_p->targetinfo.current_max_speed =
1158 1158 targetinfo.current_max_speed;
1159 1159
1160 1160 softc_p->targetinfo.target_nodeID =
1161 1161 targetinfo.target_nodeID;
1162 1162 }
1163 1163 }
1164 1164
1165 1165
1166 1166 /*
1167 1167 * byte_copy_to_user_buff
1168 1168 */
1169 1169 static int
1170 1170 byte_copy_to_user_buff(uchar_t *src_addr_p, struct uio *uio_p, size_t num_bytes,
1171 1171 int start_index, int *end_index_p)
1172 1172 {
1173 1173 int index;
1174 1174 size_t len;
1175 1175 uchar_t *u8_p;
1176 1176
1177 1177 index = start_index;
1178 1178 u8_p = (uchar_t *)src_addr_p;
1179 1179
1180 1180 while (num_bytes) {
1181 1181
1182 1182 len = num_bytes;
1183 1183
1184 1184 if (uiomove(u8_p, len, UIO_READ, uio_p)) {
1185 1185 return (-1);
1186 1186 }
1187 1187
1188 1188 index++;
1189 1189 u8_p += len;
1190 1190 num_bytes -= len;
1191 1191 }
1192 1192
1193 1193 *end_index_p = index;
1194 1194
1195 1195 return (0);
1196 1196 }
1197 1197
1198 1198
1199 1199 /*
1200 1200 * byte_copy_from_user_buff
1201 1201 */
1202 1202 static int
1203 1203 byte_copy_from_user_buff(uchar_t *dst_addr_p, struct uio *uio_p,
1204 1204 size_t num_bytes, int start_index, int *end_index_p)
1205 1205 {
1206 1206 int index;
1207 1207 size_t len;
1208 1208 uchar_t *u8_p;
1209 1209
1210 1210 index = start_index;
1211 1211 u8_p = (uchar_t *)dst_addr_p;
1212 1212
1213 1213 while (num_bytes) {
1214 1214 len = num_bytes;
1215 1215
1216 1216 if (uiomove(u8_p, len, UIO_WRITE, uio_p)) {
1217 1217 return (-1);
1218 1218
1219 1219 }
1220 1220
1221 1221 index++;
1222 1222 u8_p += len;
1223 1223 num_bytes -= len;
1224 1224
1225 1225 }
1226 1226
1227 1227 *end_index_p = index;
1228 1228
1229 1229 return (0);
1230 1230 }
1231 1231
1232 1232
1233 1233 /*
1234 1234 * dcam_reset()
1235 1235 */
1236 1236 static int
1237 1237 dcam_reset(dcam_state_t *softc_p)
1238 1238 {
1239 1239 dcam1394_reg_io_t dcam_reg_io;
1240 1240
1241 1241 dcam_reg_io.offs = DCAM1394_REG_OFFS_INITIALIZE;
1242 1242 dcam_reg_io.val = DCAM1394_REG_VAL_INITIALIZE_ASSERT;
1243 1243
1244 1244 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
1245 1245 return (-1);
1246 1246 }
1247 1247
1248 1248 /*
1249 1249 * If the camera has a TI VSP, tweak the iris feature
1250 1250 * to "on" and value 4.
1251 1251 */
1252 1252 dcam_reg_io.offs = DCAM1394_REG_OFFS_FEATURE_CSR_BASE +
1253 1253 DCAM1394_REG_OFFS_IRIS_CSR;
1254 1254 dcam_reg_io.val = 0x82000004;
1255 1255
1256 1256 if (dcam_reg_write(softc_p, &dcam_reg_io)) {
1257 1257 return (-1);
1258 1258 }
1259 1259
1260 1260 return (0);
1261 1261 }
↓ open down ↓ |
1109 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX