Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/audio/impl/audio_ddi.c
+++ new/usr/src/uts/common/io/audio/impl/audio_ddi.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 (C) 4Front Technologies 1996-2008.
23 23 *
24 24 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 */
27 27
28 28 #include <sys/types.h>
29 29 #include <sys/sysmacros.h>
30 30 #include <sys/stropts.h>
31 31 #include <sys/strsun.h>
32 32 #include <sys/list.h>
33 33 #include <sys/mkdev.h>
34 34 #include <sys/conf.h>
35 35 #include <sys/note.h>
36 36 #include <sys/atomic.h>
37 37 #include <sys/ddi.h>
38 38 #include <sys/sunddi.h>
39 39
40 40 #include "audio_impl.h"
41 41
42 42 /*
43 43 * Audio DDI glue implementation.
44 44 */
45 45
46 46 /*
47 47 * The audio module is itself a pseudo driver, as it contains the
48 48 * logic to support un-associated nodes. (Think generic /dev/mixer
49 49 * and /dev/sndstat used by OSS.)
50 50 */
51 51 static int
52 52 audio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
53 53 {
54 54 audio_dev_t *adev;
55 55
56 56 /* pseudo devices don't need S/R support */
57 57 if ((cmd != DDI_ATTACH) || (dip == NULL)) {
58 58 return (DDI_FAILURE);
59 59 }
60 60
61 61 if (ddi_get_instance(dip) != 0) {
62 62 return (DDI_FAILURE);
63 63 }
64 64
65 65 /* this can't fail */
66 66 adev = audio_dev_alloc(dip, 0);
67 67 adev->d_flags = DEV_SNDSTAT_CAP;
68 68 audio_dev_set_description(adev, "Audio Common Code");
69 69 audio_dev_set_version(adev, "pseudo");
70 70 ddi_set_driver_private(dip, adev);
71 71
72 72 /* look up our properties! */
73 73
74 74 if (audio_dev_register(adev) != NULL) {
75 75 audio_dev_free(adev);
76 76 return (DDI_FAILURE);
77 77 }
78 78
79 79 ddi_report_dev(dip);
80 80
81 81 return (DDI_SUCCESS);
82 82 }
83 83
84 84 static int
85 85 audio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
86 86 {
87 87 audio_dev_t *adev;
88 88
89 89 /* pseudo devices don't need S/R support */
90 90 if (cmd != DDI_DETACH) {
91 91 return (DDI_FAILURE);
92 92 }
93 93
94 94 if (dip == NULL) {
95 95 return (DDI_FAILURE);
96 96 }
97 97
98 98 if ((adev = ddi_get_driver_private(dip)) == NULL) {
99 99 return (DDI_FAILURE);
100 100 }
101 101
102 102 if (audio_dev_unregister(adev) != DDI_SUCCESS) {
103 103 return (DDI_FAILURE);
104 104 }
105 105
106 106 audio_dev_free(adev);
107 107
108 108 return (DDI_SUCCESS);
109 109 }
110 110
111 111 static int
112 112 audio_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resp)
113 113 {
114 114 dip = NULL;
115 115
116 116 if (getminor((dev_t)arg) & AUDIO_MN_CLONE_MASK) {
117 117 audio_client_t *c;
118 118 c = auclnt_hold_by_devt((dev_t)arg);
119 119 if (c != NULL) {
120 120 dip = c->c_dev->d_dip;
121 121 auclnt_release(c);
122 122 }
123 123 } else {
124 124 audio_dev_t *adev;
125 125 if ((adev = auimpl_dev_hold_by_devt((dev_t)arg)) != NULL) {
126 126 dip = adev->d_dip;
127 127 auimpl_dev_release(adev);
128 128 }
129 129 }
130 130
131 131 if (dip == NULL) {
132 132 return (DDI_FAILURE);
133 133 }
134 134
135 135 switch (cmd) {
136 136 case DDI_INFO_DEVT2DEVINFO:
137 137 *resp = dip;
138 138 break;
139 139 case DDI_INFO_DEVT2INSTANCE:
140 140 *resp = (void *)(uintptr_t)ddi_get_instance(dip);
141 141 break;
142 142 default:
143 143 *resp = NULL;
144 144 return (DDI_FAILURE);
145 145 }
146 146 return (DDI_SUCCESS);
147 147 }
148 148
149 149 static int
150 150 audio_open(dev_t *devp, int oflag, int otyp, cred_t *credp)
151 151 {
152 152 int rv;
153 153 audio_client_t *c;
154 154
155 155 if (otyp == OTYP_BLK) {
156 156 return (ENXIO);
157 157 }
158 158
159 159 if ((c = auimpl_client_create(*devp)) == NULL) {
160 160 audio_dev_warn(NULL, "client create failed");
161 161 return (ENXIO);
162 162 }
163 163
164 164 c->c_omode = oflag;
165 165 c->c_pid = ddi_get_pid();
166 166 c->c_cred = credp;
167 167
168 168 /*
169 169 * Call client/personality specific open handler. Note that
170 170 * we "insist" that there is an open. The personality layer
171 171 * will initialize/allocate any engines required.
172 172 *
173 173 * Hmm... do we need to pass in the cred?
174 174 */
175 175 if ((rv = c->c_open(c, oflag)) != 0) {
176 176 audio_dev_warn(c->c_dev, "open failed (rv %d)", rv);
177 177 auimpl_client_destroy(c);
178 178 return (rv);
179 179 }
180 180
181 181 /* we do device cloning! */
182 182 *devp = makedevice(c->c_major, c->c_minor);
183 183
184 184 /* now we can receive upcalls */
185 185 auimpl_client_activate(c);
186 186
187 187 atomic_inc_uint(&c->c_dev->d_serial);
188 188
189 189 return (0);
190 190 }
191 191
192 192 static int
193 193 audio_stropen(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp)
194 194 {
195 195 int rv;
196 196 audio_client_t *c;
197 197
198 198 if (sflag != 0) {
199 199 /* no direct clone or module opens */
200 200 return (ENXIO);
201 201 }
202 202
203 203 /*
204 204 * Make sure its a STREAMS personality - only legacy Sun API uses
205 205 * STREAMS.
206 206 */
207 207 switch (AUDIO_MN_TYPE_MASK & getminor(*devp)) {
208 208 case AUDIO_MINOR_DEVAUDIO:
209 209 case AUDIO_MINOR_DEVAUDIOCTL:
210 210 break;
211 211 default:
212 212 return (ENOSTR);
213 213 }
214 214
215 215 if ((c = auimpl_client_create(*devp)) == NULL) {
216 216 audio_dev_warn(NULL, "client create failed");
217 217 return (ENXIO);
218 218 }
219 219
220 220 rq->q_ptr = WR(rq)->q_ptr = c;
221 221 c->c_omode = oflag;
222 222 c->c_pid = ddi_get_pid();
223 223 c->c_cred = credp;
224 224 c->c_rq = rq;
225 225 c->c_wq = WR(rq);
226 226
227 227 /*
228 228 * Call client/personality specific open handler. Note that
229 229 * we "insist" that there is an open. The personality layer
230 230 * will initialize/allocate any engines required.
231 231 *
232 232 * Hmm... do we need to pass in the cred?
233 233 */
234 234 if ((rv = c->c_open(c, oflag)) != 0) {
235 235 audio_dev_warn(c->c_dev, "open failed (rv %d)", rv);
236 236 auimpl_client_destroy(c);
237 237 return (rv);
238 238 }
239 239
240 240 /* we do device cloning! */
241 241 *devp = makedevice(c->c_major, c->c_minor);
242 242
243 243 qprocson(rq);
244 244
245 245 /* now we can receive upcalls */
246 246 auimpl_client_activate(c);
247 247
248 248 atomic_inc_uint(&c->c_dev->d_serial);
249 249
250 250 return (0);
251 251 }
252 252
253 253 static int
254 254 audio_strclose(queue_t *rq, int flag, cred_t *credp)
255 255 {
256 256 audio_client_t *c;
257 257 audio_dev_t *d;
258 258 int rv;
259 259
260 260 _NOTE(ARGUNUSED(flag));
261 261 _NOTE(ARGUNUSED(credp));
262 262
263 263 if ((c = rq->q_ptr) == NULL) {
264 264 return (ENXIO);
265 265 }
266 266 if (ddi_can_receive_sig() || (ddi_get_pid() == 0)) {
267 267 rv = auclnt_drain(c);
268 268 }
269 269
270 270 /* make sure we won't get any upcalls */
271 271 auimpl_client_deactivate(c);
272 272
273 273 /*
274 274 * Pick up any data sitting around in input buffers. This
275 275 * avoids leaving record data stuck in queues.
276 276 */
277 277 if (c->c_istream.s_engine != NULL)
278 278 auimpl_input_callback(c->c_istream.s_engine);
279 279
280 280 /* get a local hold on the device */
281 281 d = c->c_dev;
282 282 auimpl_dev_hold(c->c_dev);
283 283
284 284 /* Turn off queue processing... */
285 285 qprocsoff(rq);
286 286
287 287 /* Call personality specific close handler */
288 288 c->c_close(c);
289 289
290 290 auimpl_client_destroy(c);
291 291
292 292 /* notify peers that a change has occurred */
293 293 atomic_inc_uint(&d->d_serial);
294 294
295 295 /* now we can drop the release we had on the device */
296 296 auimpl_dev_release(d);
297 297
298 298 return (rv);
299 299 }
300 300
301 301 static int
302 302 audio_close(dev_t dev, int flag, int otyp, cred_t *credp)
303 303 {
304 304 audio_client_t *c;
305 305 audio_dev_t *d;
306 306
307 307 _NOTE(ARGUNUSED(flag));
308 308 _NOTE(ARGUNUSED(credp));
309 309 _NOTE(ARGUNUSED(otyp));
310 310
311 311 if ((c = auclnt_hold_by_devt(dev)) == NULL) {
312 312 audio_dev_warn(NULL, "close on bogus devt %x,%x",
313 313 getmajor(dev), getminor(dev));
314 314 return (ENXIO);
315 315 }
316 316
317 317 /* we don't want any upcalls anymore */
318 318 auimpl_client_deactivate(c);
319 319
320 320 /*
321 321 * Pick up any data sitting around in input buffers. This
322 322 * avoids leaving record data stuck in queues.
323 323 */
324 324 if (c->c_istream.s_engine != NULL)
325 325 auimpl_input_callback(c->c_istream.s_engine);
326 326
327 327 /* get a local hold on the device */
328 328 d = c->c_dev;
329 329 auimpl_dev_hold(c->c_dev);
330 330
331 331 /*
332 332 * NB: This must be done before c->c_close, since it calls
333 333 * auclnt_close which will block waiting for the refence count
334 334 * to drop to zero.
335 335 */
336 336 auclnt_release(c);
337 337
338 338 /* Call personality specific close handler */
339 339 c->c_close(c);
340 340
341 341 auimpl_client_destroy(c);
342 342
343 343 /* notify peers that a change has occurred */
344 344 atomic_inc_uint(&d->d_serial);
345 345
346 346 /* now we can drop the release we had on the device */
347 347 auimpl_dev_release(d);
348 348
349 349 return (0);
350 350 }
351 351
352 352 static int
353 353 audio_write(dev_t dev, struct uio *uio, cred_t *credp)
354 354 {
355 355 audio_client_t *c;
356 356 int rv;
357 357
358 358 if ((c = auclnt_hold_by_devt(dev)) == NULL) {
359 359 return (ENXIO);
360 360 }
361 361 if ((rv = auclnt_serialize(c)) == 0) {
362 362 rv = (c->c_write == NULL) ? ENXIO : c->c_write(c, uio, credp);
363 363 auclnt_unserialize(c);
364 364 }
365 365 auclnt_release(c);
366 366
367 367 return (rv);
368 368 }
369 369
370 370 static int
371 371 audio_read(dev_t dev, struct uio *uio, cred_t *credp)
372 372 {
373 373 audio_client_t *c;
374 374 int rv;
375 375
376 376 if ((c = auclnt_hold_by_devt(dev)) == NULL) {
377 377 return (ENXIO);
378 378 }
379 379 if ((rv = auclnt_serialize(c)) == 0) {
380 380 rv = (c->c_read == NULL) ? ENXIO : c->c_read(c, uio, credp);
381 381 auclnt_unserialize(c);
382 382 }
383 383 auclnt_release(c);
384 384
385 385 return (rv);
386 386 }
387 387
388 388 static int
389 389 audio_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
390 390 int *rvalp)
391 391 {
392 392 audio_client_t *c;
393 393 int rv;
394 394
395 395 if ((c = auclnt_hold_by_devt(dev)) == NULL) {
396 396 return (ENXIO);
397 397 }
398 398 rv = (c->c_ioctl == NULL) ? ENXIO : c->c_ioctl(c, cmd, arg, mode,
399 399 credp, rvalp);
400 400 auclnt_release(c);
401 401
402 402 return (rv);
403 403 }
404 404
405 405 static int
406 406 audio_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
407 407 struct pollhead **phpp)
408 408 {
409 409 audio_client_t *c;
410 410 int rv;
411 411
412 412 if ((c = auclnt_hold_by_devt(dev)) == NULL) {
413 413 return (ENXIO);
414 414 }
415 415 rv = (c->c_chpoll == NULL) ?
416 416 ENXIO :
417 417 c->c_chpoll(c, events, anyyet, reventsp, phpp);
418 418 auclnt_release(c);
419 419
420 420 return (rv);
421 421 }
422 422
423 423 static int
424 424 audio_wput(queue_t *wq, mblk_t *mp)
425 425 {
426 426 audio_client_t *c;
427 427
428 428 c = wq->q_ptr;
429 429 if (c->c_wput) {
430 430 c->c_wput(c, mp);
431 431 } else {
432 432 freemsg(mp);
433 433 }
434 434 return (0);
435 435 }
436 436
437 437 static int
438 438 audio_wsrv(queue_t *wq)
439 439 {
440 440 audio_client_t *c;
441 441
442 442 c = wq->q_ptr;
443 443 if (c->c_wsrv) {
444 444 c->c_wsrv(c);
445 445 } else {
446 446 flushq(wq, FLUSHALL);
447 447 }
448 448 return (0);
449 449 }
450 450
451 451 static int
452 452 audio_rsrv(queue_t *rq)
453 453 {
454 454 audio_client_t *c;
455 455
456 456 c = rq->q_ptr;
457 457 if (c->c_rsrv) {
458 458 c->c_rsrv(c);
459 459 } else {
460 460 flushq(rq, FLUSHALL);
461 461 }
462 462 return (0);
463 463 }
464 464
465 465
466 466 static struct dev_ops audio_dev_ops = {
467 467 DEVO_REV, /* rev */
468 468 0, /* refcnt */
469 469 NULL, /* getinfo */
470 470 nulldev, /* identify */
471 471 nulldev, /* probe */
472 472 audio_attach, /* attach */
473 473 audio_detach, /* detach */
474 474 nodev, /* reset */
475 475 NULL, /* cb_ops */
476 476 NULL, /* bus_ops */
477 477 NULL, /* power */
↓ open down ↓ |
477 lines elided |
↑ open up ↑ |
478 478 };
479 479
480 480 static struct modldrv modldrv = {
481 481 &mod_driverops,
482 482 "Audio Framework",
483 483 &audio_dev_ops,
484 484 };
485 485
486 486 static struct modlinkage modlinkage = {
487 487 MODREV_1, /* MODREV_1 indicated by manual */
488 - &modldrv,
489 - NULL
488 + { &modldrv, NULL }
490 489 };
491 490
492 491 struct audio_ops_helper {
493 492 struct cb_ops cbops; /* NB: must be first */
494 493 struct streamtab strtab;
495 494 struct qinit rqinit;
496 495 struct qinit wqinit;
497 496 struct module_info minfo;
498 497 char name[MODMAXNAMELEN+1];
499 498 };
500 499
501 500 void
502 501 audio_init_ops(struct dev_ops *devops, const char *name)
503 502 {
504 503 struct audio_ops_helper *helper;
505 504
506 505 helper = kmem_zalloc(sizeof (*helper), KM_SLEEP);
507 506
508 507 (void) strlcpy(helper->name, name, sizeof (helper->name));
509 508
510 509 helper->minfo.mi_idnum = 0; /* only for strlog(1M) */
511 510 helper->minfo.mi_idname = helper->name;
512 511 helper->minfo.mi_minpsz = 0;
513 512 helper->minfo.mi_maxpsz = 8192;
514 513 helper->minfo.mi_hiwat = 65536;
515 514 helper->minfo.mi_lowat = 32768;
516 515
517 516 helper->wqinit.qi_putp = audio_wput;
518 517 helper->wqinit.qi_srvp = audio_wsrv;
519 518 helper->wqinit.qi_qopen = NULL;
520 519 helper->wqinit.qi_qclose = NULL;
521 520 helper->wqinit.qi_qadmin = NULL;
522 521 helper->wqinit.qi_minfo = &helper->minfo;
523 522 helper->wqinit.qi_mstat = NULL;
524 523
525 524 helper->rqinit.qi_putp = putq;
526 525 helper->rqinit.qi_srvp = audio_rsrv;
527 526 helper->rqinit.qi_qopen = audio_stropen;
528 527 helper->rqinit.qi_qclose = audio_strclose;
529 528 helper->rqinit.qi_qadmin = NULL;
530 529 helper->rqinit.qi_minfo = &helper->minfo;
531 530 helper->rqinit.qi_mstat = NULL;
532 531
533 532 helper->strtab.st_rdinit = &helper->rqinit;
534 533 helper->strtab.st_wrinit = &helper->wqinit;
535 534 helper->strtab.st_muxrinit = NULL;
536 535 helper->strtab.st_muxwinit = NULL;
537 536
538 537 helper->cbops.cb_open = audio_open;
539 538 helper->cbops.cb_close = audio_close;
540 539 helper->cbops.cb_strategy = nodev;
541 540 helper->cbops.cb_print = nodev;
542 541 helper->cbops.cb_dump = nodev;
543 542 helper->cbops.cb_read = audio_read;
544 543 helper->cbops.cb_write = audio_write;
545 544 helper->cbops.cb_ioctl = audio_ioctl;
546 545 helper->cbops.cb_devmap = nodev;
547 546 helper->cbops.cb_mmap = nodev;
548 547 helper->cbops.cb_segmap = nodev;
549 548 helper->cbops.cb_chpoll = audio_chpoll;
550 549 helper->cbops.cb_prop_op = ddi_prop_op;
551 550 helper->cbops.cb_str = &helper->strtab;
552 551 helper->cbops.cb_flag = D_MP | D_64BIT;
553 552 helper->cbops.cb_rev = CB_REV;
554 553 helper->cbops.cb_aread = nodev;
555 554 helper->cbops.cb_awrite = nodev;
556 555
557 556 devops->devo_cb_ops = &helper->cbops;
558 557 devops->devo_getinfo = audio_getinfo;
559 558 }
560 559
561 560 void
562 561 audio_fini_ops(struct dev_ops *devops)
563 562 {
564 563 kmem_free(devops->devo_cb_ops, sizeof (struct audio_ops_helper));
565 564 devops->devo_cb_ops = NULL;
566 565 devops->devo_getinfo = NULL;
567 566 }
568 567
569 568 void
570 569 auimpl_dev_vwarn(audio_dev_t *dev, const char *fmt, va_list va)
571 570 {
572 571 char buf[256];
573 572
574 573 if (dev != NULL) {
575 574 (void) snprintf(buf, sizeof (buf), "%s#%d: %s",
576 575 ddi_driver_name(dev->d_dip), ddi_get_instance(dev->d_dip),
577 576 fmt);
578 577 } else {
579 578 (void) snprintf(buf, sizeof (buf), "audio: %s", fmt);
580 579 }
581 580
582 581 vcmn_err(CE_WARN, buf, va);
583 582 }
584 583
585 584
586 585 void
587 586 audio_dev_warn(audio_dev_t *dev, const char *fmt, ...)
588 587 {
589 588 va_list va;
590 589
591 590 va_start(va, fmt);
592 591 auimpl_dev_vwarn(dev, fmt, va);
593 592 va_end(va);
594 593 }
595 594
596 595 /*
597 596 * _init, _info, and _fini DDI glue.
598 597 */
599 598 int
600 599 _init(void)
601 600 {
602 601 int rv;
603 602
604 603 auimpl_client_init();
605 604 auimpl_dev_init();
606 605 auimpl_sun_init();
607 606 auimpl_oss_init();
608 607
609 608 audio_init_ops(&audio_dev_ops, "audio");
610 609
611 610 if ((rv = mod_install(&modlinkage)) != 0) {
612 611 audio_fini_ops(&audio_dev_ops);
613 612 auimpl_dev_fini();
614 613 auimpl_client_fini();
615 614 }
616 615 return (rv);
617 616 }
618 617
619 618 int
620 619 _info(struct modinfo *modinfop)
621 620 {
622 621 return (mod_info(&modlinkage, modinfop));
623 622 }
624 623
625 624 int
626 625 _fini(void)
627 626 {
628 627 int rv;
629 628
630 629 if ((rv = mod_remove(&modlinkage)) != 0)
631 630 return (rv);
632 631
633 632 auimpl_dev_fini();
634 633 auimpl_client_fini();
635 634
636 635 return (rv);
637 636 }
↓ open down ↓ |
138 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX