Deleted Added
sdiff udiff text old ( 54237 ) new ( 54462 )
full compact
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Copyright 1997,1998 Luigi Rizzo.
4 *
5 * Derived from files in the Voxware 3.5 distribution,
6 * Copyright by Hannu Savolainen 1994, under the same copyright
7 * conditions.
8 * All rights reserved.

--- 14 unchanged lines hidden (view full) ---

23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: head/sys/dev/sound/isa/sb16.c 54237 1999-12-07 01:53:24Z billf $
32 */
33
34#include <dev/sound/pcm/sound.h>
35
36#include "sbc.h"
37
38#define __SB_MIXER_C__ /* XXX warning... */
39#include <dev/sound/isa/sb.h>

--- 15 unchanged lines hidden (view full) ---

55#endif
56static int esschan_setdir(void *data, int dir);
57static int esschan_setformat(void *data, u_int32_t format);
58static int esschan_setspeed(void *data, u_int32_t speed);
59static int esschan_setblocksize(void *data, u_int32_t blocksize);
60static int esschan_trigger(void *data, int go);
61static int esschan_getptr(void *data);
62static pcmchan_caps *esschan_getcaps(void *data);
63static pcmchan_caps sb_playcaps = {
64 4000, 22050,
65 AFMT_U8,
66 AFMT_U8
67};
68
69static pcmchan_caps sb_reccaps = {
70 4000, 13000,

--- 8 unchanged lines hidden (view full) ---

79};
80
81static pcmchan_caps sbpro_reccaps = {
82 4000, 15000,
83 AFMT_STEREO | AFMT_U8,
84 AFMT_STEREO | AFMT_U8
85};
86
87static pcmchan_caps sb16_playcaps = {
88 5000, 45000,
89 AFMT_STEREO | AFMT_S16_LE,
90 AFMT_STEREO | AFMT_S16_LE
91};
92
93static pcmchan_caps sb16_reccaps = {
94 5000, 45000,
95 AFMT_STEREO | AFMT_U8,
96 AFMT_STEREO | AFMT_U8
97};
98
99static pcmchan_caps ess_playcaps = {
100 5000, 49000,
101 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
102 AFMT_STEREO | AFMT_S16_LE
103};
104
105static pcmchan_caps ess_reccaps = {
106 5000, 49000,

--- 32 unchanged lines hidden (view full) ---

139 snd_dbuf *buffer;
140 int dir;
141 u_int32_t fmt;
142 int ess_dma_started;
143};
144
145struct sb_info {
146 struct resource *io_base; /* I/O address for the board */
147 int io_rid;
148 struct resource *irq;
149 int irq_rid;
150 struct resource *drq1; /* play */
151 int drq1_rid;
152 struct resource *drq2; /* rec */
153 int drq2_rid;
154 bus_dma_tag_t parent_dmat;
155
156 int dma16, dma8;
157 int bd_id;
158 u_long bd_flags; /* board-specific flags */
159 struct sb_chinfo pch, rch;
160};
161
162static int sb_rd(struct sb_info *sb, int reg);
163static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
164static int sb_dspready(struct sb_info *sb);
165static int sb_cmd(struct sb_info *sb, u_char val);
166static int sb_cmd1(struct sb_info *sb, u_char cmd, int val);
167static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
168static u_int sb_get_byte(struct sb_info *sb);
169static int ess_write(struct sb_info *sb, u_char reg, int val);
170static int ess_read(struct sb_info *sb, u_char reg);
171
172/*
173 * in the SB, there is a set of indirect "mixer" registers with
174 * address at offset 4, data at offset 5
175 */
176static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
177static int sb_getmixer(struct sb_info *sb, u_int port);
178
179static void sb_intr(void *arg);
180static void ess_intr(void *arg);
181static int sb_init(device_t dev, struct sb_info *sb);
182static int sb_reset_dsp(struct sb_info *sb);
183
184static int sb_format(struct sb_chinfo *ch, u_int32_t format);
185static int sb_speed(struct sb_chinfo *ch, int speed);
186static int sb_start(struct sb_chinfo *ch);
187static int sb_stop(struct sb_chinfo *ch);
188
189static int ess_format(struct sb_chinfo *ch, u_int32_t format);
190static int ess_speed(struct sb_chinfo *ch, int speed);
191static int ess_start(struct sb_chinfo *ch);
192static int ess_stop(struct sb_chinfo *ch);
193static int ess_abort(struct sb_chinfo *ch);
194static int sbmix_init(snd_mixer *m);
195static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
196static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src);
197
198static snd_mixer sb_mixer = {
199 "SoundBlaster mixer",
200 sbmix_init,
201 sbmix_set,

--- 170 unchanged lines hidden (view full) ---

372 return 0;
373}
374
375static void
376sb_release_resources(struct sb_info *sb, device_t dev)
377{
378 /* should we bus_teardown_intr here? */
379 if (sb->irq) {
380 bus_release_resource(dev, SYS_RES_IRQ, sb->irq_rid, sb->irq);
381 sb->irq = 0;
382 }
383 if (sb->drq1) {
384 bus_release_resource(dev, SYS_RES_DRQ, sb->drq1_rid, sb->drq1);
385 sb->drq1 = 0;
386 }
387 if (sb->drq2) {
388 bus_release_resource(dev, SYS_RES_DRQ, sb->drq2_rid, sb->drq2);
389 sb->drq2 = 0;
390 }
391 if (sb->io_base) {
392 bus_release_resource(dev, SYS_RES_IOPORT, sb->io_rid,
393 sb->io_base);
394 sb->io_base = 0;
395 }
396 free(sb, M_DEVBUF);
397}
398
399static int
400sb_alloc_resources(struct sb_info *sb, device_t dev)
401{
402 if (!sb->io_base)
403 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
404 &sb->io_rid, 0, ~0, 1,
405 RF_ACTIVE);
406 if (!sb->irq)
407 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
408 &sb->irq_rid, 0, ~0, 1,
409 RF_ACTIVE);
410 if (!sb->drq1)
411 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ,
412 &sb->drq1_rid, 0, ~0, 1,
413 RF_ACTIVE);
414 if (!sb->drq2 && sb->drq2_rid > 0)
415 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ,
416 &sb->drq2_rid, 0, ~0, 1,
417 RF_ACTIVE);
418
419 if (sb->io_base && sb->drq1 && sb->irq) {
420 sb->dma8 = rman_get_start(sb->drq1);
421 isa_dma_acquire(sb->dma8);
422 isa_dmainit(sb->dma8, DSP_BUFFSIZE);
423
424 if (sb->drq2) {
425 sb->dma16 = rman_get_start(sb->drq2);
426 isa_dma_acquire(sb->dma16);
427 isa_dmainit(sb->dma16, DSP_BUFFSIZE);
428 } else sb->dma16 = sb->dma8;
429
430 if (sb->dma8 > sb->dma16) {
431 int tmp = sb->dma16;
432 sb->dma16 = sb->dma8;
433 sb->dma8 = tmp;
434 }
435 return 0;
436 } else return ENXIO;
437}
438
439static int
440sb_identify_board(device_t dev, struct sb_info *sb)
441{
442 char *fmt = NULL;
443 static char buf[64];
444 int essver = 0;
445
446 sb_cmd(sb, DSP_CMD_GETVER); /* Get version */
447 sb->bd_id = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
448
449 switch (sb->bd_id >> 8) {
450 case 1: /* old sound blaster has nothing... */
451 case 2:
452 fmt = "SoundBlaster %d.%d" ; /* default */
453 break;
454
455 case 3:
456 fmt = "SoundBlaster Pro %d.%d";
457 if (sb->bd_id == 0x301) {
458 int rev;
459
460 /* Try to detect ESS chips. */
461 sb_cmd(sb, DSP_CMD_GETID); /* Return ident. bytes. */
462 essver = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
463 rev = essver & 0x000f;
464 essver &= 0xfff0;
465 if (essver == 0x4880) {
466 /* the ESS488 can be treated as an SBPRO */
467 fmt = "SoundBlaster Pro (ESS488 rev %d)";
468 } else if (essver == 0x6880) {
469 if (rev < 8) fmt = "ESS688 rev %d";
470 else fmt = "ESS1868 rev %d";
471 sb->bd_flags |= BD_F_ESS;
472 } else return ENXIO;
473 sb->bd_id &= 0xff00;
474 sb->bd_id |= ((essver & 0xf000) >> 8) | rev;
475 }
476 break;
477
478 case 4:
479 sb->bd_flags |= BD_F_SB16;
480 if (sb->bd_flags & BD_F_SB16X) fmt = "SB16 ViBRA16X %d.%d";
481 else fmt = "SoundBlaster 16 %d.%d";
482 break;
483
484 default:
485 device_printf(dev, "failed to get SB version (%x)\n",
486 sb->bd_id);
487 return ENXIO;
488 }
489 if (essver) snprintf(buf, sizeof buf, fmt, sb->bd_id & 0x000f);
490 else snprintf(buf, sizeof buf, fmt, sb->bd_id >> 8, sb->bd_id & 0xff);
491 device_set_desc_copy(dev, buf);
492 return sb_reset_dsp(sb);
493}
494
495static int
496sb_init(device_t dev, struct sb_info *sb)
497{
498 int x, irq;
499
500 sb->bd_flags &= ~BD_F_MIX_MASK;
501 /* do various initializations depending on board id. */
502 switch (sb->bd_id >> 8) {
503 case 1: /* old sound blaster has nothing... */
504 break;
505
506 case 2:
507 sb->bd_flags |= BD_F_DUP_MIDI;
508 if (sb->bd_id > 0x200) sb->bd_flags |= BD_F_MIX_CT1335;
509 break;
510
511 case 3:
512 sb->bd_flags |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
513 break;
514
515 case 4:
516 sb->bd_flags |= BD_F_SB16 | BD_F_MIX_CT1745;
517 if (sb->dma16 != sb->dma8) sb->bd_flags |= BD_F_DUPLEX;
518
519 /* soft irq/dma configuration */
520 x = -1;
521 irq = rman_get_start(sb->irq);
522 if (irq == 5) x = 2;
523 else if (irq == 7) x = 4;
524 else if (irq == 9) x = 1;
525 else if (irq == 10) x = 8;
526 if (x == -1) device_printf(dev,
527 "bad irq %d (5/7/9/10 valid)\n",
528 irq);
529 else sb_setmixer(sb, IRQ_NR, x);
530 sb_setmixer(sb, DMA_NR, (1 << sb->dma16) | (1 << sb->dma8));
531 break;
532 }
533 return 0;
534}
535
536static int
537sb_probe(device_t dev)
538{
539 snddev_info *d = device_get_softc(dev);
540 struct sb_info *sb;
541 int allocated, i;
542 int error;
543
544 if (isa_get_vendorid(dev)) return ENXIO; /* not yet */
545
546 device_set_desc(dev, "SoundBlaster");
547 bzero(d, sizeof *d);
548 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
549 if (!sb) return ENXIO;
550 bzero(sb, sizeof *sb);
551
552 allocated = 0;
553 sb->io_rid = 0;
554 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
555 0, ~0, 16, RF_ACTIVE);
556 if (!sb->io_base) {
557 BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
558 allocated = 1;
559 sb->io_rid = 0;
560 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
561 &sb->io_rid, 0x220, 0x22f,
562 16, RF_ACTIVE);
563 if (!sb->io_base) {
564 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
565 &sb->io_rid, 0x240,
566 0x24f, 16, RF_ACTIVE);
567 }
568 }
569 if (!sb->io_base) return ENXIO;
570
571 error = sb_reset_dsp(sb);
572 if (error) goto no;
573 error = sb_identify_board(dev, sb);
574 if (error) goto no;
575no:
576 i = sb->io_rid;
577 sb_release_resources(sb, dev);
578 if (allocated) bus_delete_resource(dev, SYS_RES_IOPORT, i);
579 return error;
580}
581
582static int
583sb_doattach(device_t dev, struct sb_info *sb)
584{
585 snddev_info *d = device_get_softc(dev);
586 void *ih;
587 int error;
588 char status[SND_STATUSLEN];
589
590 sb->irq_rid = 0;
591 sb->drq1_rid = 0;
592 sb->drq2_rid = 1;
593 if (sb_alloc_resources(sb, dev)) goto no;
594 error = sb_reset_dsp(sb);
595 if (error) goto no;
596 error = sb_identify_board(dev, sb);
597 if (error) goto no;
598
599 sb_init(dev, sb);
600 mixer_init(d, &sb_mixer, sb);
601 if (sb->bd_flags & BD_F_ESS)
602 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih);
603 else
604 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih);
605
606 if (sb->bd_flags & BD_F_SB16)
607 pcm_setflags(dev, pcm_getflags(dev) | SD_F_EVILSB16);
608 if (sb->dma16 == sb->dma8)
609 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
610 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
611 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
612 /*highaddr*/BUS_SPACE_MAXADDR,
613 /*filter*/NULL, /*filterarg*/NULL,
614 /*maxsize*/DSP_BUFFSIZE, /*nsegments*/1,
615 /*maxsegz*/0x3ffff,
616 /*flags*/0, &sb->parent_dmat) != 0) {
617 device_printf(dev, "unable to create dma tag\n");
618 goto no;
619 }
620
621 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d",
622 rman_get_start(sb->io_base), rman_get_start(sb->irq),
623 sb->dma8);
624 if (sb->dma16 != sb->dma8) snprintf(status + strlen(status),
625 SND_STATUSLEN - strlen(status), ":%d", sb->dma16);
626
627 if (pcm_register(dev, sb, 1, 1)) goto no;
628 if (sb->bd_flags & BD_F_ESS) {
629 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb);
630 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb);
631 } else {
632 pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
633 pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
634 }
635 pcm_setstatus(dev, status);
636
637 return 0;
638
639no:
640 sb_release_resources(sb, dev);
641 return ENXIO;
642}
643
644static int
645sb_attach(device_t dev)
646{
647 struct sb_info *sb;
648 int flags = device_get_flags(dev);
649
650 if (flags & DV_F_DUAL_DMA) {
651 bus_set_resource(dev, SYS_RES_DRQ, 1,
652 flags & DV_F_DRQ_MASK, 1);
653 }
654 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
655 if (!sb) return ENXIO;
656 bzero(sb, sizeof *sb);
657
658 /* XXX in probe should set io resource to right val instead of this */
659 sb->io_rid = 0;
660 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
661 0, ~0, 16, RF_ACTIVE);
662 if (!sb->io_base) {
663 BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
664 sb->io_rid = 0;
665 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
666 &sb->io_rid, 0x220, 0x22f,
667 16, RF_ACTIVE);
668 if (!sb->io_base) {
669 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
670 &sb->io_rid, 0x240,
671 0x24f, 16, RF_ACTIVE);
672 }
673 }
674 if (!sb->io_base) return ENXIO;
675
676 return sb_doattach(dev, sb);
677}
678
679static device_method_t sb_methods[] = {
680 /* Device interface */
681 DEVMETHOD(device_probe, sb_probe),
682 DEVMETHOD(device_attach, sb_attach),
683
684 { 0, 0 }
685};
686
687static driver_t sb_driver = {
688 "pcm",
689 sb_methods,
690 sizeof(snddev_info),
691};
692
693DRIVER_MODULE(sb, isa, sb_driver, pcm_devclass, 0, 0);
694
695static void
696sb_intr(void *arg)
697{
698 struct sb_info *sb = (struct sb_info *)arg;
699 int reason = 3, c;
700
701 /*
702 * SB < 4.0 is half duplex and has only 1 bit for int source,

--- 121 unchanged lines hidden (view full) ---

824static int
825sb_start(struct sb_chinfo *ch)
826{
827 struct sb_info *sb = ch->parent;
828 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
829 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
830 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
831 int l = ch->buffer->dl;
832 u_char i1, i2 = 0;
833
834 if (b16) l >>= 1;
835 l--;
836 if (play) sb_cmd(sb, DSP_CMD_SPKON);
837 if (sb->bd_flags & BD_F_SB16) {
838 i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON |
839 (play? DSP_F16_DAC : DSP_F16_ADC);
840 i1 |= (b16 && (sb->bd_flags & BD_F_DUPLEX))? DSP_DMA16 : DSP_DMA8;
841 i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0);
842 sb_cmd(sb, i1);
843 sb_cmd2(sb, i2, l);
844 } else {
845 if (sb->bd_flags & BD_F_HISPEED) i1 = play? 0x90 : 0x98;
846 else i1 = play? 0x1c : 0x2c;
847 sb_setmixer(sb, 0x0e, stereo? 2 : 0);
848 /* an ESS extension -- they can do 16 bits */

--- 145 unchanged lines hidden (view full) ---

994 struct sb_info *sb = devinfo;
995 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
996
997 ch->parent = sb;
998 ch->channel = c;
999 ch->buffer = b;
1000 ch->buffer->bufsize = DSP_BUFFSIZE;
1001 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) return NULL;
1002 ch->buffer->chan = (dir == PCMDIR_PLAY)? sb->dma16 : sb->dma8;
1003 return ch;
1004}
1005
1006static int
1007sbchan_setdir(void *data, int dir)
1008{
1009 struct sb_chinfo *ch = data;
1010 ch->dir = dir;

--- 37 unchanged lines hidden (view full) ---

1048 return buf_isadmaptr(ch->buffer);
1049}
1050
1051static pcmchan_caps *
1052sbchan_getcaps(void *data)
1053{
1054 struct sb_chinfo *ch = data;
1055 int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
1056 if (ch->parent->bd_id <= 0x200)
1057 return p? &sb_playcaps : &sb_reccaps;
1058 else if (ch->parent->bd_id >= 0x400)
1059 return p? &sb16_playcaps : &sb16_reccaps;
1060 else
1061 return p? &sbpro_playcaps : &sbpro_reccaps;
1062}
1063/* channel interface for ESS18xx */
1064#ifdef notyet
1065static void *
1066esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
1067{
1068 /* the same as sbchan_init()? */
1069}

--- 178 unchanged lines hidden (view full) ---

1248 */
1249 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
1250 break;
1251 }
1252 return src;
1253}
1254
1255static int
1256sbpnp_probe(device_t dev)
1257{
1258 char *s = NULL;
1259 u_int32_t logical_id = isa_get_logicalid(dev);
1260
1261 switch(logical_id) {
1262 case 0x01000000: /* @@@0001 */
1263 s = "Avance Asound 100";
1264 break;
1265
1266 case 0x01100000: /* @@@1001 */
1267 s = "Avance Asound 110";
1268 break;
1269
1270 case 0x01200000: /* @@@2001 */
1271 s = "Avance Logic ALS120";
1272 break;
1273
1274 case 0x68187316: /* ESS1868 */
1275 s = "ESS1868";
1276 break;
1277
1278 case 0x69187316: /* ESS1869 */
1279 case 0xacb0110e: /* Compaq's Presario 1621 ESS1869 */
1280 s = "ESS1869";
1281 break;
1282
1283 case 0x79187316: /* ESS1879 */
1284 s = "ESS1879";
1285 break;
1286
1287 case 0x88187316: /* ESS1888 */
1288 s = "ESS1888";
1289 break;
1290 }
1291 if (s) {
1292 device_set_desc(dev, s);
1293 return (0);
1294 }
1295 return ENXIO;
1296}
1297
1298static int
1299sbpnp_attach(device_t dev)
1300{
1301 struct sb_info *sb;
1302 u_int32_t vend_id = isa_get_vendorid(dev);
1303
1304 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1305 if (!sb) return ENXIO;
1306 bzero(sb, sizeof *sb);
1307
1308 switch(vend_id) {
1309 case 0xf0008c0e:
1310 case 0x10019305:
1311 case 0x20019305:
1312 /* XXX add here the vend_id for other vibra16X cards... */
1313 sb->bd_flags = BD_F_SB16X;
1314 }
1315 return sb_doattach(dev, sb);
1316}
1317
1318static device_method_t sbpnp_methods[] = {
1319 /* Device interface */
1320 DEVMETHOD(device_probe, sbpnp_probe),
1321 DEVMETHOD(device_attach, sbpnp_attach),
1322
1323 { 0, 0 }
1324};
1325
1326static driver_t sbpnp_driver = {
1327 "pcm",
1328 sbpnp_methods,
1329 sizeof(snddev_info),
1330};
1331
1332DRIVER_MODULE(sbpnp, isa, sbpnp_driver, pcm_devclass, 0, 0);
1333
1334#if NSBC > 0
1335#define DESCSTR " PCM Audio"
1336static int
1337sbsbc_probe(device_t dev)
1338{
1339 char *s = NULL;
1340 struct sndcard_func *func;
1341
1342 /* The parent device has already been probed. */
1343
1344 func = device_get_ivars(dev);
1345 if (func == NULL || func->func != SCF_PCM)
1346 return (ENXIO);
1347
1348 s = "SB PCM Audio";
1349
1350 device_set_desc(dev, s);
1351 return 0;
1352}
1353
1354static int
1355sbsbc_attach(device_t dev)
1356{
1357 struct sb_info *sb;
1358 u_int32_t vend_id;
1359 device_t sbc;
1360
1361 sbc = device_get_parent(dev);
1362 vend_id = isa_get_vendorid(sbc);
1363 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1364 if (!sb) return ENXIO;
1365 bzero(sb, sizeof *sb);
1366
1367 switch(vend_id) {
1368 case 0xf0008c0e:
1369 case 0x10019305:
1370 case 0x20019305:
1371 /* XXX add here the vend_id for other vibra16X cards... */
1372 sb->bd_flags = BD_F_SB16X;
1373 }
1374 return sb_doattach(dev, sb);
1375}
1376
1377static device_method_t sbsbc_methods[] = {
1378 /* Device interface */
1379 DEVMETHOD(device_probe, sbsbc_probe),
1380 DEVMETHOD(device_attach, sbsbc_attach),
1381
1382 { 0, 0 }
1383};
1384
1385static driver_t sbsbc_driver = {
1386 "pcm",
1387 sbsbc_methods,
1388 sizeof(snddev_info),
1389};
1390
1391DRIVER_MODULE(sbsbc, sbc, sbsbc_driver, pcm_devclass, 0, 0);
1392
1393#endif /* NSBC > 0 */