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