FreeBSD kernel sound device code
sbc.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1999 Seigo Tanimura
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#ifdef HAVE_KERNEL_OPTION_HEADERS
30#include "opt_snd.h"
31#endif
32
33#include <dev/sound/chip.h>
34#include <dev/sound/pcm/sound.h>
35#include <dev/sound/isa/sb.h>
36
37#include <isa/isavar.h>
38
39SND_DECLARE_FILE("$FreeBSD$");
40
41#define IO_MAX 3
42#define IRQ_MAX 1
43#define DRQ_MAX 2
44#define INTR_MAX 2
45
46struct sbc_softc;
47
48struct sbc_ihl {
49 driver_intr_t *intr[INTR_MAX];
52};
53
54/* Here is the parameter structure per a device. */
55struct sbc_softc {
56 device_t dev; /* device */
58
59 int io_rid[IO_MAX]; /* io port rids */
60 struct resource *io[IO_MAX]; /* io port resources */
61 int io_alloced[IO_MAX]; /* io port alloc flag */
62
63 int irq_rid[IRQ_MAX]; /* irq rids */
64 struct resource *irq[IRQ_MAX]; /* irq resources */
65 int irq_alloced[IRQ_MAX]; /* irq alloc flag */
66
67 int drq_rid[DRQ_MAX]; /* drq rids */
68 struct resource *drq[DRQ_MAX]; /* drq resources */
69 int drq_alloced[DRQ_MAX]; /* drq alloc flag */
70
72
73 void *ih[IRQ_MAX];
74
75 struct mtx *lock;
76
77 u_int32_t bd_ver;
78};
79
80static int sbc_probe(device_t dev);
81static int sbc_attach(device_t dev);
82static void sbc_intr(void *p);
83
84static struct resource *sbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
85 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags);
86static int sbc_release_resource(device_t bus, device_t child, int type, int rid,
87 struct resource *r);
88static int sbc_setup_intr(device_t dev, device_t child, struct resource *irq,
89 int flags,
90 driver_filter_t *filter,
91 driver_intr_t *intr,
92 void *arg, void **cookiep);
93static int sbc_teardown_intr(device_t dev, device_t child, struct resource *irq,
94 void *cookie);
95
96static int alloc_resource(struct sbc_softc *scp);
97static int release_resource(struct sbc_softc *scp);
98
99static devclass_t sbc_devclass;
100
101static int io_range[3] = {0x10, 0x2, 0x4};
102
103static int sb_rd(struct resource *io, int reg);
104static void sb_wr(struct resource *io, int reg, u_int8_t val);
105static int sb_dspready(struct resource *io);
106static int sb_cmd(struct resource *io, u_char val);
107static u_int sb_get_byte(struct resource *io);
108static void sb_setmixer(struct resource *io, u_int port, u_int value);
109
110static void
112{
113 scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev),
114 "snd_sbc softc");
115}
116
117static void
119{
120 snd_mtxfree(scp->lock);
121}
122
123void
124sbc_lock(struct sbc_softc *scp)
125{
126 snd_mtxlock(scp->lock);
127}
128
129void
131{
132 snd_mtxassert(scp->lock);
133}
134
135void
137{
138 snd_mtxunlock(scp->lock);
139}
140
141static int
142sb_rd(struct resource *io, int reg)
143{
144 return bus_space_read_1(rman_get_bustag(io),
145 rman_get_bushandle(io),
146 reg);
147}
148
149static void
150sb_wr(struct resource *io, int reg, u_int8_t val)
151{
152 bus_space_write_1(rman_get_bustag(io),
153 rman_get_bushandle(io),
154 reg, val);
155}
156
157static int
158sb_dspready(struct resource *io)
159{
160 return ((sb_rd(io, SBDSP_STATUS) & 0x80) == 0);
161}
162
163static int
164sb_dspwr(struct resource *io, u_char val)
165{
166 int i;
167
168 for (i = 0; i < 1000; i++) {
169 if (sb_dspready(io)) {
170 sb_wr(io, SBDSP_CMD, val);
171 return 1;
172 }
173 if (i > 10) DELAY((i > 100)? 1000 : 10);
174 }
175 printf("sb_dspwr(0x%02x) timed out.\n", val);
176 return 0;
177}
178
179static int
180sb_cmd(struct resource *io, u_char val)
181{
182 return sb_dspwr(io, val);
183}
184
185static void
186sb_setmixer(struct resource *io, u_int port, u_int value)
187{
188 u_long flags;
189
190 flags = spltty();
191 sb_wr(io, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
192 DELAY(10);
193 sb_wr(io, SB_MIX_DATA, (u_char) (value & 0xff));
194 DELAY(10);
195 splx(flags);
196}
197
198static u_int
199sb_get_byte(struct resource *io)
200{
201 int i;
202
203 for (i = 1000; i > 0; i--) {
204 if (sb_rd(io, DSP_DATA_AVAIL) & 0x80)
205 return sb_rd(io, DSP_READ);
206 else
207 DELAY(20);
208 }
209 return 0xffff;
210}
211
212static int
213sb_reset_dsp(struct resource *io)
214{
215 sb_wr(io, SBDSP_RST, 3);
216 DELAY(100);
217 sb_wr(io, SBDSP_RST, 0);
218 return (sb_get_byte(io) == 0xAA)? 0 : ENXIO;
219}
220
221static int
222sb_identify_board(struct resource *io)
223{
224 int ver, essver, rev;
225
226 sb_cmd(io, DSP_CMD_GETVER); /* Get version */
227 ver = (sb_get_byte(io) << 8) | sb_get_byte(io);
228 if (ver < 0x100 || ver > 0x4ff) return 0;
229 if (ver == 0x0301) {
230 /* Try to detect ESS chips. */
231 sb_cmd(io, DSP_CMD_GETID); /* Return ident. bytes. */
232 essver = (sb_get_byte(io) << 8) | sb_get_byte(io);
233 rev = essver & 0x000f;
234 essver &= 0xfff0;
235 if (essver == 0x4880) ver |= 0x1000;
236 else if (essver == 0x6880) ver = 0x0500 | rev;
237 }
238 return ver;
239}
240
241static struct isa_pnp_id sbc_ids[] = {
242 {0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */
243 {0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */
244 {0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */
245 {0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */
246 {0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */
247 {0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */
248 {0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */
249 {0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */
250
251 {0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */
252 {0x01100000, "Avance Asound 110"}, /* @@@1001 */
253 {0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */
254
255 {0x81167316, "ESS ES1681"}, /* ESS1681 */
256 {0x02017316, "ESS ES1688"}, /* ESS1688 */
257 {0x68097316, "ESS ES1688"}, /* ESS1688 */
258 {0x68187316, "ESS ES1868"}, /* ESS1868 */
259 {0x03007316, "ESS ES1869"}, /* ESS1869 */
260 {0x69187316, "ESS ES1869"}, /* ESS1869 */
261 {0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */
262 {0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */
263 {0x78187316, "ESS ES1878"}, /* ESS1878 */
264 {0x79187316, "ESS ES1879"}, /* ESS1879 */
265 {0x88187316, "ESS ES1888"}, /* ESS1888 */
266 {0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */
267 {0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */
268 {0}
269};
270
271static int
272sbc_probe(device_t dev)
273{
274 char *s = NULL;
275 u_int32_t lid, vid;
276
277 lid = isa_get_logicalid(dev);
278 vid = isa_get_vendorid(dev);
279 if (lid) {
280 if (lid == 0x01000000 && vid != 0x01009305) /* ALS0001 */
281 return ENXIO;
282 /* Check pnp ids */
283 return ISA_PNP_PROBE(device_get_parent(dev), dev, sbc_ids);
284 } else {
285 int rid = 0, ver;
286 struct resource *io;
287
288 io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid,
289 16, RF_ACTIVE);
290 if (!io) goto bad;
291 if (sb_reset_dsp(io)) goto bad2;
292 ver = sb_identify_board(io);
293 if (ver == 0) goto bad2;
294 switch ((ver & 0x00000f00) >> 8) {
295 case 1:
296 device_set_desc(dev, "SoundBlaster 1.0 (not supported)");
297 s = NULL;
298 break;
299
300 case 2:
301 s = "SoundBlaster 2.0";
302 break;
303
304 case 3:
305 s = (ver & 0x0000f000)? "ESS 488" : "SoundBlaster Pro";
306 break;
307
308 case 4:
309 s = "SoundBlaster 16";
310 break;
311
312 case 5:
313 s = (ver & 0x00000008)? "ESS 688" : "ESS 1688";
314 break;
315 }
316 if (s) device_set_desc(dev, s);
317bad2: bus_release_resource(dev, SYS_RES_IOPORT, rid, io);
318bad: return s? 0 : ENXIO;
319 }
320}
321
322static int
324{
325 char *err = NULL;
326 struct sbc_softc *scp;
327 struct sndcard_func *func;
328 u_int32_t logical_id = isa_get_logicalid(dev);
329 int flags = device_get_flags(dev);
330 int f, dh, dl, x, irq, i;
331
332 gone_in_dev(dev, 14, "ISA sound driver");
333 if (!logical_id && (flags & DV_F_DUAL_DMA)) {
334 bus_set_resource(dev, SYS_RES_DRQ, 1,
335 flags & DV_F_DRQ_MASK, 1);
336 }
337
338 scp = device_get_softc(dev);
339 bzero(scp, sizeof(*scp));
340 scp->dev = dev;
341 sbc_lockinit(scp);
342 err = "alloc_resource";
343 if (alloc_resource(scp)) goto bad;
344
345 err = "sb_reset_dsp";
346 if (sb_reset_dsp(scp->io[0])) goto bad;
347 err = "sb_identify_board";
348 scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff;
349 if (scp->bd_ver == 0) goto bad;
350 f = 0;
351 if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499;
352 switch ((scp->bd_ver & 0x0f00) >> 8) {
353 case 1: /* old sound blaster has nothing... */
354 break;
355
356 case 2:
357 f |= BD_F_DUP_MIDI;
358 if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335;
359 break;
360
361 case 5:
362 f |= BD_F_ESS;
363 scp->bd_ver = 0x0301;
364 case 3:
366 break;
367
368 case 4:
370 if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1;
371 if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl;
372 if (!logical_id && (dh < dl)) {
373 struct resource *r;
374 r = scp->drq[0];
375 scp->drq[0] = scp->drq[1];
376 scp->drq[1] = r;
377 dl = rman_get_start(scp->drq[0]);
378 dh = rman_get_start(scp->drq[1]);
379 }
380 /* soft irq/dma configuration */
381 x = -1;
382 irq = rman_get_start(scp->irq[0]);
383 if (irq == 5) x = 2;
384 else if (irq == 7) x = 4;
385 else if (irq == 9) x = 1;
386 else if (irq == 10) x = 8;
387 if (x == -1) {
388 err = "bad irq (5/7/9/10 valid)";
389 goto bad;
390 }
391 else sb_setmixer(scp->io[0], IRQ_NR, x);
392 sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl));
393 if (bootverbose) {
394 device_printf(dev, "setting card to irq %d, drq %d", irq, dl);
395 if (dl != dh) printf(", %d", dh);
396 printf("\n");
397 }
398 break;
399 }
400
401 switch (logical_id) {
402 case 0x43008c0e: /* CTL0043 */
403 case 0x01200000:
404 case 0x01000000:
405 f |= BD_F_SB16X;
406 break;
407 }
408 scp->bd_ver |= f << 16;
409
410 err = "setup_intr";
411 for (i = 0; i < IRQ_MAX; i++) {
412 scp->ihl[i].parent = scp;
413 if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i]))
414 goto bad;
415 }
416
417 /* PCM Audio */
418 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
419 if (func == NULL) goto bad;
420 func->func = SCF_PCM;
421 scp->child_pcm = device_add_child(dev, "pcm", -1);
422 device_set_ivars(scp->child_pcm, func);
423
424 /* Midi Interface */
425 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
426 if (func == NULL) goto bad;
427 func->func = SCF_MIDI;
428 scp->child_midi1 = device_add_child(dev, "midi", -1);
429 device_set_ivars(scp->child_midi1, func);
430
431 /* OPL FM Synthesizer */
432 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
433 if (func == NULL) goto bad;
434 func->func = SCF_SYNTH;
435 scp->child_midi2 = device_add_child(dev, "midi", -1);
436 device_set_ivars(scp->child_midi2, func);
437
438 /* probe/attach kids */
439 bus_generic_attach(dev);
440
441 return (0);
442
443bad: if (err) device_printf(dev, "%s\n", err);
444 release_resource(scp);
445 return (ENXIO);
446}
447
448static int
450{
451 struct sbc_softc *scp = device_get_softc(dev);
452
453 sbc_lock(scp);
454 device_delete_child(dev, scp->child_midi2);
455 device_delete_child(dev, scp->child_midi1);
456 device_delete_child(dev, scp->child_pcm);
457 release_resource(scp);
458 sbc_lockdestroy(scp);
459 return bus_generic_detach(dev);
460}
461
462static void
463sbc_intr(void *p)
464{
465 struct sbc_ihl *ihl = p;
466 int i;
467
468 /* sbc_lock(ihl->parent); */
469 i = 0;
470 while (i < INTR_MAX) {
471 if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]);
472 i++;
473 }
474 /* sbc_unlock(ihl->parent); */
475}
476
477static int
478sbc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
479 driver_filter_t *filter,
480 driver_intr_t *intr,
481 void *arg, void **cookiep)
482{
483 struct sbc_softc *scp = device_get_softc(dev);
484 struct sbc_ihl *ihl = NULL;
485 int i, ret;
486
487 if (filter != NULL) {
488 printf("sbc.c: we cannot use a filter here\n");
489 return (EINVAL);
490 }
491 sbc_lock(scp);
492 i = 0;
493 while (i < IRQ_MAX) {
494 if (irq == scp->irq[i]) ihl = &scp->ihl[i];
495 i++;
496 }
497 ret = 0;
498 if (ihl == NULL) ret = EINVAL;
499 i = 0;
500 while ((ret == 0) && (i < INTR_MAX)) {
501 if (ihl->intr[i] == NULL) {
502 ihl->intr[i] = intr;
503 ihl->intr_arg[i] = arg;
504 *cookiep = &ihl->intr[i];
505 ret = -1;
506 } else i++;
507 }
508 sbc_unlock(scp);
509 return (ret > 0)? EINVAL : 0;
510}
511
512static int
513sbc_teardown_intr(device_t dev, device_t child, struct resource *irq,
514 void *cookie)
515{
516 struct sbc_softc *scp = device_get_softc(dev);
517 struct sbc_ihl *ihl = NULL;
518 int i, ret;
519
520 sbc_lock(scp);
521 i = 0;
522 while (i < IRQ_MAX) {
523 if (irq == scp->irq[i]) ihl = &scp->ihl[i];
524 i++;
525 }
526 ret = 0;
527 if (ihl == NULL) ret = EINVAL;
528 i = 0;
529 while ((ret == 0) && (i < INTR_MAX)) {
530 if (cookie == &ihl->intr[i]) {
531 ihl->intr[i] = NULL;
532 ihl->intr_arg[i] = NULL;
533 return 0;
534 } else i++;
535 }
536 sbc_unlock(scp);
537 return (ret > 0)? EINVAL : 0;
538}
539
540static struct resource *
541sbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
542 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
543{
544 struct sbc_softc *scp;
545 int *alloced, rid_max, alloced_max;
546 struct resource **res;
547
548 scp = device_get_softc(bus);
549 switch (type) {
550 case SYS_RES_IOPORT:
551 alloced = scp->io_alloced;
552 res = scp->io;
553 rid_max = IO_MAX - 1;
554 alloced_max = 1;
555 break;
556 case SYS_RES_DRQ:
557 alloced = scp->drq_alloced;
558 res = scp->drq;
559 rid_max = DRQ_MAX - 1;
560 alloced_max = 1;
561 break;
562 case SYS_RES_IRQ:
563 alloced = scp->irq_alloced;
564 res = scp->irq;
565 rid_max = IRQ_MAX - 1;
566 alloced_max = INTR_MAX; /* pcm and mpu may share the irq. */
567 break;
568 default:
569 return (NULL);
570 }
571
572 if (*rid > rid_max || alloced[*rid] == alloced_max)
573 return (NULL);
574
575 alloced[*rid]++;
576 return (res[*rid]);
577}
578
579static int
580sbc_release_resource(device_t bus, device_t child, int type, int rid,
581 struct resource *r)
582{
583 struct sbc_softc *scp;
584 int *alloced, rid_max;
585
586 scp = device_get_softc(bus);
587 switch (type) {
588 case SYS_RES_IOPORT:
589 alloced = scp->io_alloced;
590 rid_max = IO_MAX - 1;
591 break;
592 case SYS_RES_DRQ:
593 alloced = scp->drq_alloced;
594 rid_max = DRQ_MAX - 1;
595 break;
596 case SYS_RES_IRQ:
597 alloced = scp->irq_alloced;
598 rid_max = IRQ_MAX - 1;
599 break;
600 default:
601 return (1);
602 }
603
604 if (rid > rid_max || alloced[rid] == 0)
605 return (1);
606
607 alloced[rid]--;
608 return (0);
609}
610
611static int
612sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result)
613{
614 struct sbc_softc *scp = device_get_softc(bus);
615 struct sndcard_func *func = device_get_ivars(dev);
616
617 switch (index) {
618 case 0:
619 *result = func->func;
620 break;
621
622 case 1:
623 *result = scp->bd_ver;
624 break;
625
626 default:
627 return ENOENT;
628 }
629
630 return 0;
631}
632
633static int
634sbc_write_ivar(device_t bus, device_t dev,
635 int index, uintptr_t value)
636{
637 switch (index) {
638 case 0:
639 case 1:
640 return EINVAL;
641
642 default:
643 return (ENOENT);
644 }
645}
646
647static int
649{
650 int i;
651
652 for (i = 0 ; i < IO_MAX ; i++) {
653 if (scp->io[i] == NULL) {
654 scp->io_rid[i] = i;
655 scp->io[i] = bus_alloc_resource_anywhere(scp->dev,
656 SYS_RES_IOPORT,
657 &scp->io_rid[i],
658 io_range[i],
659 RF_ACTIVE);
660 if (i == 0 && scp->io[i] == NULL)
661 return (1);
662 scp->io_alloced[i] = 0;
663 }
664 }
665 for (i = 0 ; i < DRQ_MAX ; i++) {
666 if (scp->drq[i] == NULL) {
667 scp->drq_rid[i] = i;
668 scp->drq[i] = bus_alloc_resource_any(scp->dev,
669 SYS_RES_DRQ,
670 &scp->drq_rid[i],
671 RF_ACTIVE);
672 if (i == 0 && scp->drq[i] == NULL)
673 return (1);
674 scp->drq_alloced[i] = 0;
675 }
676 }
677 for (i = 0 ; i < IRQ_MAX ; i++) {
678 if (scp->irq[i] == NULL) {
679 scp->irq_rid[i] = i;
680 scp->irq[i] = bus_alloc_resource_any(scp->dev,
681 SYS_RES_IRQ,
682 &scp->irq_rid[i],
683 RF_ACTIVE);
684 if (i == 0 && scp->irq[i] == NULL)
685 return (1);
686 scp->irq_alloced[i] = 0;
687 }
688 }
689 return (0);
690}
691
692static int
694{
695 int i;
696
697 for (i = 0 ; i < IO_MAX ; i++) {
698 if (scp->io[i] != NULL) {
699 bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]);
700 scp->io[i] = NULL;
701 }
702 }
703 for (i = 0 ; i < DRQ_MAX ; i++) {
704 if (scp->drq[i] != NULL) {
705 bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]);
706 scp->drq[i] = NULL;
707 }
708 }
709 for (i = 0 ; i < IRQ_MAX ; i++) {
710 if (scp->irq[i] != NULL) {
711 if (scp->ih[i] != NULL)
712 bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]);
713 scp->ih[i] = NULL;
714 bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]);
715 scp->irq[i] = NULL;
716 }
717 }
718 return (0);
719}
720
721static device_method_t sbc_methods[] = {
722 /* Device interface */
723 DEVMETHOD(device_probe, sbc_probe),
724 DEVMETHOD(device_attach, sbc_attach),
725 DEVMETHOD(device_detach, sbc_detach),
726 DEVMETHOD(device_shutdown, bus_generic_shutdown),
727 DEVMETHOD(device_suspend, bus_generic_suspend),
728 DEVMETHOD(device_resume, bus_generic_resume),
729
730 /* Bus interface */
731 DEVMETHOD(bus_read_ivar, sbc_read_ivar),
732 DEVMETHOD(bus_write_ivar, sbc_write_ivar),
733 DEVMETHOD(bus_alloc_resource, sbc_alloc_resource),
734 DEVMETHOD(bus_release_resource, sbc_release_resource),
735 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
736 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
737 DEVMETHOD(bus_setup_intr, sbc_setup_intr),
738 DEVMETHOD(bus_teardown_intr, sbc_teardown_intr),
739
740 DEVMETHOD_END
741};
742
743static driver_t sbc_driver = {
744 "sbc",
746 sizeof(struct sbc_softc),
747};
748
749/* sbc can be attached to an isa bus. */
751DRIVER_MODULE(snd_sbc, acpi, sbc_driver, sbc_devclass, 0, 0);
753MODULE_VERSION(snd_sbc, 1);
METHOD int intr
Definition: audio_dai_if.m:91
@ SCF_SYNTH
Definition: chip.h:38
@ SCF_PCM
Definition: chip.h:36
@ SCF_MIDI
Definition: chip.h:37
int type
Definition: dsp.c:386
u_int32_t count
Definition: feeder_if.m:86
uint32_t value
Definition: hdaa.c:58
uint8_t reg
Definition: hdac.c:211
device_t child
Definition: hdac_if.m:33
uint8_t r
unsigned dev
Definition: mixer_if.m:59
u_int index
uint16_t rid
u_int32_t val
uint16_t vid
u_int func
u_int bus
int * irq
#define DSP_READ
Definition: sb.h:44
#define SBDSP_RST
Definition: sb.h:43
#define DSP_CMD_GETVER
Definition: sb.h:112
#define DSP_CMD_GETID
Definition: sb.h:113
#define BD_F_MIX_CT1345
Definition: sb.h:166
#define SB_MIX_ADDR
Definition: sb.h:51
#define BD_F_SB16
Definition: sb.h:169
#define BD_F_MIX_CT1335
Definition: sb.h:165
#define DMA_NR
Definition: sb.h:192
#define SBDSP_STATUS
Definition: sb.h:47
#define BD_F_ESS
Definition: sb.h:174
#define BD_F_SB16X
Definition: sb.h:170
#define SBDSP_CMD
Definition: sb.h:46
#define SB_MIX_DATA
Definition: sb.h:52
#define BD_F_MIX_CT1745
Definition: sb.h:167
#define DSP_DATA_AVAIL
Definition: sb.h:48
#define BD_F_DUP_MIDI
Definition: sb.h:162
#define IRQ_NR
Definition: sb.h:191
static void sb_wr(struct resource *io, int reg, u_int8_t val)
Definition: sbc.c:150
void sbc_lockassert(struct sbc_softc *scp)
Definition: sbc.c:130
static int sb_dspready(struct resource *io)
Definition: sbc.c:158
static int sb_rd(struct resource *io, int reg)
Definition: sbc.c:142
static void sb_setmixer(struct resource *io, u_int port, u_int value)
Definition: sbc.c:186
static void sbc_lockdestroy(struct sbc_softc *scp)
Definition: sbc.c:118
static int sbc_write_ivar(device_t bus, device_t dev, int index, uintptr_t value)
Definition: sbc.c:634
static int sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *result)
Definition: sbc.c:612
static devclass_t sbc_devclass
Definition: sbc.c:99
static int sb_identify_board(struct resource *io)
Definition: sbc.c:222
static int alloc_resource(struct sbc_softc *scp)
Definition: sbc.c:648
DRIVER_MODULE(snd_sbc, isa, sbc_driver, sbc_devclass, 0, 0)
static int io_range[3]
Definition: sbc.c:101
#define IO_MAX
Definition: sbc.c:41
static int release_resource(struct sbc_softc *scp)
Definition: sbc.c:693
static void sbc_lockinit(struct sbc_softc *scp)
Definition: sbc.c:111
static struct resource * sbc_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
Definition: sbc.c:541
static struct isa_pnp_id sbc_ids[]
Definition: sbc.c:241
static int sbc_attach(device_t dev)
Definition: sbc.c:323
void sbc_unlock(struct sbc_softc *scp)
Definition: sbc.c:136
static int sb_reset_dsp(struct resource *io)
Definition: sbc.c:213
SND_DECLARE_FILE("$FreeBSD$")
static void sbc_intr(void *p)
Definition: sbc.c:463
static device_method_t sbc_methods[]
Definition: sbc.c:721
static int sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie)
Definition: sbc.c:513
#define IRQ_MAX
Definition: sbc.c:42
static int sb_cmd(struct resource *io, u_char val)
Definition: sbc.c:180
void sbc_lock(struct sbc_softc *scp)
Definition: sbc.c:124
#define DRQ_MAX
Definition: sbc.c:43
MODULE_VERSION(snd_sbc, 1)
static int sbc_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
Definition: sbc.c:580
static u_int sb_get_byte(struct resource *io)
Definition: sbc.c:199
ISA_PNP_INFO(sbc_ids)
#define INTR_MAX
Definition: sbc.c:44
static int sbc_probe(device_t dev)
Definition: sbc.c:272
static int sbc_detach(device_t dev)
Definition: sbc.c:449
static int sbc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, void **cookiep)
Definition: sbc.c:478
static int sb_dspwr(struct resource *io, u_char val)
Definition: sbc.c:164
MODULE_DEPEND(snd_sbc, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER)
static driver_t sbc_driver
Definition: sbc.c:743
void snd_mtxassert(void *m)
Definition: sound.c:107
void * snd_mtxcreate(const char *desc, const char *type)
Definition: sound.c:88
void snd_mtxfree(void *m)
Definition: sound.c:98
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
Definition: sound.c:117
#define DV_F_DUAL_DMA
Definition: sound.h:369
#define SOUND_PREFVER
Definition: sound.h:103
#define SOUND_MAXVER
Definition: sound.h:104
#define DV_F_DRQ_MASK
Definition: sound.h:368
#define snd_mtxlock(m)
Definition: sound.h:347
#define snd_mtxunlock(m)
Definition: sound.h:348
#define SOUND_MINVER
Definition: sound.h:102
Definition: sbc.c:48
driver_intr_t * intr[INTR_MAX]
Definition: sbc.c:49
void * intr_arg[INTR_MAX]
Definition: sbc.c:50
struct sbc_softc * parent
Definition: sbc.c:51
Definition: sbc.c:55
int drq_rid[DRQ_MAX]
Definition: sbc.c:67
struct sbc_ihl ihl[IRQ_MAX]
Definition: sbc.c:71
int irq_rid[IRQ_MAX]
Definition: sbc.c:63
u_int32_t bd_ver
Definition: sbc.c:77
int drq_alloced[DRQ_MAX]
Definition: sbc.c:69
struct mtx * lock
Definition: sbc.c:75
device_t child_pcm
Definition: sbc.c:57
device_t child_midi2
Definition: sbc.c:57
struct resource * drq[DRQ_MAX]
Definition: sbc.c:68
int io_alloced[IO_MAX]
Definition: sbc.c:61
struct resource * irq[IRQ_MAX]
Definition: sbc.c:64
int io_rid[IO_MAX]
Definition: sbc.c:59
void * ih[IRQ_MAX]
Definition: sbc.c:73
device_t child_midi1
Definition: sbc.c:57
struct resource * io[IO_MAX]
Definition: sbc.c:60
device_t dev
Definition: sbc.c:56
int irq_alloced[IRQ_MAX]
Definition: sbc.c:65
int func
Definition: chip.h:47