diff options
author | scrappy <scrappy@FreeBSD.org> | 1998-02-17 14:17:13 +0000 |
---|---|---|
committer | scrappy <scrappy@FreeBSD.org> | 1998-02-17 14:17:13 +0000 |
commit | b171ac7ee4cbb0dbbb40690811b00336ec7146d0 (patch) | |
tree | c67c48140d38cbc8a51b5f1b5a5b41309a6f6f37 /sys/dev/sound | |
parent | 6777765e4373946684584119df163e71de8ed128 (diff) | |
download | FreeBSD-src-b171ac7ee4cbb0dbbb40690811b00336ec7146d0.zip FreeBSD-src-b171ac7ee4cbb0dbbb40690811b00336ec7146d0.tar.gz |
Upgrade Luigi's audio driver to Jan/23 version... will bring in Feb/15th
version as soon as I've tested it...
Installed/tested on my home machine...any problems, please report directly
to me.
Diffstat (limited to 'sys/dev/sound')
-rw-r--r-- | sys/dev/sound/isa/mss.c | 66 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb.c | 297 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb.h | 9 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb16.c | 297 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb8.c | 297 |
5 files changed, 553 insertions, 413 deletions
diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c index a6bf624..26eaee5 100644 --- a/sys/dev/sound/isa/mss.c +++ b/sys/dev/sound/isa/mss.c @@ -94,7 +94,7 @@ snddev_info mss_op_desc = { NULL /* mss_read */, NULL /* mss_write */, mss_ioctl, - sndpoll /* mss_poll */, + sndselect /* mss_select */, mss_intr, mss_callback , @@ -133,8 +133,8 @@ mss_probe(struct isa_device *dev) bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) ); if (dev->id_iobase == -1) { dev->id_iobase = 0x530; - printf("mss_probe: no address supplied, try default 0x%x\n", - dev->id_iobase); + BVDDB(printf("mss_probe: no address supplied, try default 0x%x\n", + dev->id_iobase)); } if (snd_conflict(dev->id_iobase)) return 0 ; @@ -150,13 +150,13 @@ mss_probe(struct isa_device *dev) tmp = inb(dev->id_iobase + 3); if (tmp == 0xff) { /* Bus float */ - DEB(printf("I/O address inactive (%x), try pseudo_mss\n", tmp)); + BVDDB(printf("I/O address inactive (%x), try pseudo_mss\n", tmp)); dev->id_flags &= ~DV_F_TRUE_MSS ; goto mss_probe_end; } tmp &= 0x3f ; if (tmp != 0x04 && tmp != 0x0f && tmp != 0x00) { - DEB(printf("No MSS signature detected on port 0x%x (0x%x)\n", + BVDDB(printf("No MSS signature detected on port 0x%x (0x%x)\n", dev->id_iobase, inb(dev->id_iobase + 3))); return 0; } @@ -276,10 +276,12 @@ mss_open(dev_t dev, int flags, int mode, struct proc * p) d->flags |= SND_F_BUSY_DSP ; else if (dev == SND_DEV_DSP16) d->flags |= SND_F_BUSY_DSP16 ; - if ( ! (d->flags & SND_F_BUSY) ) { + if ( d->flags & SND_F_BUSY ) + splx(s); /* device was already set, no need to reinit */ + else { /* * device was idle. Do the necessary initialization, - * but no need keep interrupts blocked since this device + * but no need keep interrupts blocked. * will not get them */ @@ -313,7 +315,6 @@ mss_open(dev_t dev, int flags, int mode, struct proc * p) } ask_init(d); /* and reset buffers... */ } - splx(s); return 0 ; } @@ -343,14 +344,15 @@ mss_close(dev_t dev, int flags, int mode, struct proc * p) d->flags &= ~SND_F_BUSY_DSP ; else if (dev == SND_DEV_DSP16) d->flags &= ~SND_F_BUSY_DSP16 ; - if ( ! (d->flags & SND_F_BUSY_ANY) ) { /* last one ... */ + if ( d->flags & SND_F_BUSY_ANY ) /* still some device open */ + splx(s); + else { /* last one */ d->flags |= SND_F_CLOSING ; splx(s); /* is this ok here ? */ snd_flush(d); outb(io_Status(d), 0); /* Clear interrupt status */ d->flags = 0 ; } - splx(s); return 0 ; } @@ -435,6 +437,7 @@ mss_callback(snddev_info *d, int reason) ad_write_cnt(d, 30, cnt); break ; + case SND_CB_STOP : case SND_CB_ABORT : /* XXX check this... */ m = ad_read(d,9) ; @@ -548,11 +551,11 @@ again: c=mc11 = FULL_DUPLEX(d) ? opti_read(d->conf_base, 11) : 0xc ; mc11 &= 0x0c ; if (c & 0x10) { - printf("Warning: CD interrupt\n"); + DEB(printf("Warning: CD interrupt\n");) mc11 |= 0x10 ; } if (c & 0x20) { - printf("Warning: MPU interrupt\n"); + DEB(printf("Warning: MPU interrupt\n");) mc11 |= 0x20 ; } if (mc11 & masked) @@ -578,7 +581,7 @@ again: } opti_write(d->conf_base, 11, ~mc11); /* ack */ if (--loops) goto again; - printf("xxx too many loops\n"); + DEB(printf("xxx too many loops\n");) } /* @@ -637,13 +640,13 @@ gus_readw(int io_base, u_char reg) static int AD_WAIT_INIT(snddev_info *d, int x) { - int n = 0; /* to shut up the compiler... */ + int arg=x, n = 0; /* to shut up the compiler... */ for (; x-- ; ) if ( (n=inb(io_Index_Addr(d))) & IA_BUSY) DELAY(10); else return n ; - printf("AD_WAIT_INIT FAILED 0x%02x\n", n); + printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); return n ; } @@ -1061,7 +1064,7 @@ mss_detect(struct isa_device *dev) else break ; if ((inb(io_Index_Addr(d)) & IA_BUSY) != 0x00) { /* Not a AD1848 */ - DEB(printf("mss_detect error, busy still set (0x%02x)\n", + BVDDB(printf("mss_detect error, busy still set (0x%02x)\n", inb(io_Index_Addr(d)))); return 0; } @@ -1076,7 +1079,7 @@ mss_detect(struct isa_device *dev) tmp1 = ad_read(d, 0) ; tmp2 = ad_read(d, 1) ; if ( tmp1 != 0xaa || tmp2 != 0x45) { - DEB(printf("mss_detect error - IREG (0x%02x/0x%02x) want 0xaa/0x45\n", + BVDDB(printf("mss_detect error - IREG (0x%02x/0x%02x) want 0xaa/0x45\n", tmp1, tmp2)); return 0; } @@ -1087,7 +1090,7 @@ mss_detect(struct isa_device *dev) tmp2 = ad_read(d, 1) ; if (tmp1 != 0x45 || tmp2 != 0xaa) { - DEB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2)); + BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2)); return 0; } @@ -1101,7 +1104,7 @@ mss_detect(struct isa_device *dev) tmp1 = ad_read(d, 12); if ((tmp & 0x0f) != (tmp1 & 0x0f)) { - DEB(printf("mss_detect error - I12 (0x%02x was 0x%02x)\n", + BVDDB(printf("mss_detect error - I12 (0x%02x was 0x%02x)\n", tmp1, tmp)); return 0; } @@ -1112,7 +1115,7 @@ mss_detect(struct isa_device *dev) * 0x0A=RevC. also CS4231/CS4231A and OPTi931 */ - printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f); + BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);) /* * The original AD1848/CS4248 has just 16 indirect registers. This @@ -1125,7 +1128,7 @@ mss_detect(struct isa_device *dev) for (i = 0; i < 16; i++) if ((tmp1 = ad_read(d, i)) != (tmp2 = ad_read(d, i + 16))) { - DEB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", + BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", i, tmp1, tmp2)); /* * note - this seems to fail on the 4232 on I11. So we just break @@ -1148,7 +1151,7 @@ mss_detect(struct isa_device *dev) name = "CS4248" ; /* Our best knowledge just now */ } if ((tmp1 & 0xf0) == 0x00) { - printf("this should be an OPTi931\n"); + BVDDB(printf("this should be an OPTi931\n");) } else if ((tmp1 & 0xc0) == 0xC0) { /* * The 4231 has bit7=1 always, and bit6 we just set to 1. @@ -1162,14 +1165,13 @@ mss_detect(struct isa_device *dev) ad_write(d, 0, 0xaa); if ((tmp1 = ad_read(d, 16)) == 0xaa) { /* Rotten bits? */ - DEB(printf("mss_detect error - step H(%x)\n", tmp1)); + BVDDB(printf("mss_detect error - step H(%x)\n", tmp1)); return 0; } /* * Verify that some bits of I25 are read only. */ - DEB(printf("mss_detect() - step I\n")); tmp1 = ad_read(d, 25); /* Original bits */ ad_write(d, 25, ~tmp1); /* Invert all bits */ if ((ad_read(d, 25) & 0xe7) == (tmp1 & 0xe7)) { @@ -1240,7 +1242,7 @@ mss_detect(struct isa_device *dev) break ; default: /* Assume CS4231 */ - printf("unknown id 0x%02x, assuming CS4231\n", id); + BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);) d->bd_id = MD_CS4231; } @@ -1249,7 +1251,7 @@ mss_detect(struct isa_device *dev) } } - DEB(printf("mss_detect() - Detected %s\n", name)); + BVDDB(printf("mss_detect() - Detected %s\n", name)); strcpy(d->name, name); dev->id_flags &= ~DV_F_DEV_MASK ; dev->id_flags |= (d->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK ; @@ -1390,7 +1392,7 @@ cs423x_attach(u_long csn, u_long vend_id, char *name, return ; } snddev_last_probed = &tmp_d; - if (d.flags & DV_PNP_SBCODEC) { /*** use sb-compatible codec ***/ + if (d.flags) { /*** use sb-compatible codec ***/ dev->id_alive = 16 ; /* number of io ports ? */ tmp_d = sb_op_desc ; if (vend_id==0x2000a865 || vend_id==0x3000a865 || vend_id==0x8140d315) { @@ -1455,6 +1457,7 @@ cs423x_attach(u_long csn, u_long vend_id, char *name, dev->id_intr = pcmintr ; dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ; + tmp_d.synth_base = d.port[1]; /* XXX check this for yamaha */ pcmattach(dev); } @@ -1508,7 +1511,7 @@ opti931_attach(u_long csn, u_long vend_id, char *name, enable_pnp_card(); snddev_last_probed = &tmp_d; - tmp_d = d.flags & DV_PNP_SBCODEC ? sb_op_desc : mss_op_desc ; + tmp_d = d.flags ? sb_op_desc : mss_op_desc ; strcpy(tmp_d.name, name); @@ -1526,10 +1529,11 @@ opti931_attach(u_long csn, u_long vend_id, char *name, dev->id_iobase = d.port[0] - 4 ; /* old mss have 4 bytes before... */ tmp_d.io_base = dev->id_iobase; /* needed for ad_write to work... */ tmp_d.alt_base = d.port[2]; + tmp_d.synth_base = d.port[1]; opti_write(p, 4, 0xd6 /* fifo empty, OPL3, audio enable, SB3.2 */ ); ad_write (&tmp_d, 10, 2); /* enable interrupts */ - if (d.flags & DV_PNP_SBCODEC) { /* sb-compatible codec */ + if (d.flags) { /* sb-compatible codec */ /* * the 931 is not a real SB, it has important pieces of * hardware controlled by both the WSS and the SB port... @@ -1598,7 +1602,6 @@ guspnp_attach(u_long csn, u_long vend_id, char *name, read_pnp_parms ( &d , 0 ) ; /* d.irq[1] = d.irq[0] ; */ - printf("pnp_read 0xf2 returns 0x%x\n", pnp_read(0xf2) ); pnp_write ( 0xf2, 0xff ); /* enable power on the guspnp */ write_pnp_parms ( &d , 0 ); @@ -1623,7 +1626,6 @@ guspnp_attach(u_long csn, u_long vend_id, char *name, DELAY(1000 * 30); /* release reset and enable DAC */ gus_write(tmp_d.conf_base, 0x4c /* _URSTI */, 3 ); - printf("resetting the gus...\n"); DELAY(1000 * 30); /* end of reset */ @@ -1645,7 +1647,7 @@ guspnp_attach(u_long csn, u_long vend_id, char *name, /* enable access to hidden regs */ tmp = gus_read(tmp_d.conf_base, 0x5b /* IVERI */ ); gus_write(tmp_d.conf_base, 0x5b , tmp | 1 ); - printf("GUS: silicon rev %c\n", 'A' + ( ( tmp & 0xf ) >> 4) ); + BVDDB(printf("GUS: silicon rev %c\n", 'A' + ( ( tmp & 0xf ) >> 4) );) strcpy(tmp_d.name, name); diff --git a/sys/dev/sound/isa/sb.c b/sys/dev/sound/isa/sb.c index 09440e1..3d75aea 100644 --- a/sys/dev/sound/isa/sb.c +++ b/sys/dev/sound/isa/sb.c @@ -92,7 +92,7 @@ snddev_info sb_op_desc = { NULL /* use generic sndread */, NULL /* use generic sndwrite */, sb_dsp_ioctl, - sndpoll, + sndselect, sbintr, sb_callback, @@ -123,7 +123,7 @@ sb_probe(struct isa_device *dev) bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) ); if (dev->id_iobase == -1) { dev->id_iobase = 0x220; - printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n"); + BVDDB(printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n");) if (snd_conflict(dev->id_iobase)) dev->id_iobase = 0x240; } @@ -196,6 +196,10 @@ sb_dsp_open(dev_t dev, int flags, int mode, struct proc * p) d->play_fmt = d->rec_fmt = AFMT_U8 ; break ; } + if ( (flags & FREAD) == 0) + d->rec_fmt = 0 ; + if ( (flags & FWRITE) == 0) + d->play_fmt = 0 ; d->flags |= SND_F_BUSY ; d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ; @@ -250,6 +254,8 @@ sb_dsp_ioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc * p) /* * for the remaining functions, use the default handler. + * ENOSYS means that the default handler should take care + * of implementing the ioctl. */ return ENOSYS ; @@ -292,7 +298,7 @@ again: DEB(printf("sbintr, flags 0x%08lx reason %d\n", d->flags, reason)); if ( reason & 1 ) { /* possibly a write interrupt */ if ( d->dbuf_out.dl ) - dsp_wrintr(d); + dsp_wrintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: wrintr but write DMA inactive!\n"); @@ -300,7 +306,7 @@ again: } if ( reason & 2 ) { if ( d->dbuf_in.dl ) - dsp_rdintr(d); + dsp_rdintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: rdintr but read DMA inactive!\n"); @@ -340,16 +346,11 @@ sb_callback(snddev_info *d, int reason) case SND_CB_INIT : /* called with int enabled and no pending io */ dsp_speed(d); snd_set_blocksize(d); - if (d->play_fmt & AFMT_MU_LAW) + if ( (d->play_fmt & AFMT_MU_LAW) || (d->rec_fmt & AFMT_MU_LAW) ) d->flags |= SND_F_XLAT8 ; else d->flags &= ~SND_F_XLAT8 ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - return 1; - break; - case SND_CB_START : /* called with int disabled */ if (d->bd_flags & BD_F_SB16) { u_char c, c1 ; @@ -363,42 +364,40 @@ sb_callback(snddev_info *d, int reason) */ int swap = 1 ; /* default... */ - if (rd) { - /* need not to swap if channel is already correct */ - if ( d->rec_fmt == AFMT_S16_LE && b->chan > 4 ) + if (d->play_fmt == 0) { + /* do whatever the read channel wants */ + if ( d->rec_fmt == AFMT_S16_LE && d->dbuf_in.chan > 4 ) swap = 0; - if ( d->rec_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->rec_fmt != AFMT_S16_LE && d->dbuf_in.chan < 4 ) swap = 0; - if (swap && (d->flags & SND_F_WRITING || d->dbuf_out.dl)) { - /* cannot swap if writing is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break; /* XXX should return an error */ - } } else { - /* need not to swap if channel is already correct */ - if ( d->play_fmt == AFMT_S16_LE && b->chan > 4 ) + /* privilege the write channel */ + if ( d->play_fmt == AFMT_S16_LE && d->dbuf_out.chan > 4 ) swap = 0; - if ( d->play_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->play_fmt != AFMT_S16_LE && d->dbuf_out.chan < 4 ) swap = 0; - if (swap && ( d->flags & SND_F_READING || d->dbuf_in.dl)) { - /* cannot swap if reading is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break ; /* XXX should return an error */ + if ( d->rec_fmt ) { + /* check for possible config errors. */ + if (d->rec_fmt == d->play_fmt) { + DDB(printf("sorry, read DMA channel unavailable\n")); + } } } - + DEB(printf("sb16: play_fmt %d, rec_fmt %x, swap %d\n", + d->play_fmt, d->rec_fmt, swap);) if (swap) { int c = d->dbuf_in.chan ; d->dbuf_in.chan = d->dbuf_out.chan; d->dbuf_out.chan = c ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - DEB(printf("START dma chan: play %d, rec %d\n", - d->dbuf_out.chan, d->dbuf_in.chan)); + } } + reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); + reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); + break ; + case SND_CB_START : /* called with int disabled */ + if (d->bd_flags & BD_F_SB16) { + u_char c, c1 ; /* * XXX note: c1 and l should be set basing on d->rec_fmt, * but there is no choice once a 16 or 8-bit channel @@ -408,7 +407,7 @@ sb_callback(snddev_info *d, int reason) if ( b->chan > 4 ) { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ; c1 = DSP_F16_SIGNED ; - l /= 2 ; + l /= 2 ; } else { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ; c1 = 0 ; @@ -421,28 +420,25 @@ sb_callback(snddev_info *d, int reason) sb_cmd3(d->io_base, c1 , l - 1) ; } else if (d->bd_flags & BD_F_ESS) { /* XXX this code is still incomplete */ - sb_cmd2(d->io_base, 0xb8, rd ? 0x0e : 0x04 ); /* auto dma */ - sb_cmd2(d->io_base, 0xa8, 2 /* chans */ ); - sb_cmd2(d->io_base, 0xb9, 2); /* demand mode */ - /* - input: 0xb8 -> 0x0e ; - 0xa8 -> channels - 0xb9 -> 2 - mono,U8: 51, d0 - mono,S16 71, f4 - st, U8 51, 98 - st, S16 71, bc - */ - } else { /* SBPro */ + } else { /* SBPro -- stereo not supported */ u_char c ; if (!rd) sb_cmd(d->io_base, DSP_CMD_SPKON); - /* code for the SB2 and SB3 */ + /* code for the SB2 and SB3, only MONO */ if (d->bd_flags & BD_F_HISPEED) - c = (rd) ? DSP_CMD_HSADC_AUTO : DSP_CMD_HSDAC_AUTO ; + c = (rd) ? 0x98 : 0x90 ; else - c = (rd) ? DSP_CMD_ADC8_AUTO : DSP_CMD_DAC8_AUTO ; - sb_cmd3(d->io_base, c , l - 1) ; + c = (rd) ? 0x2c : 0x1c ; + /* + * some ESS extensions -- they can do 16 bits + */ + if ( (rd && d->rec_fmt == AFMT_S16_LE) || + (!rd && d->play_fmt == AFMT_S16_LE) ) { + c |= 1; + l /= 2 ; + } + sb_cmd3(d->io_base, 0x48 , l - 1) ; + sb_cmd(d->io_base, c ) ; } break; @@ -451,7 +447,7 @@ sb_callback(snddev_info *d, int reason) { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ if ( d->bd_flags & BD_F_SB16 && b->chan > 4 ) - cmd = DSP_CMD_DMAPAUSE_16 ; + cmd = DSP_CMD_DMAPAUSE_16 ; if (d->bd_flags & BD_F_HISPEED) { sb_reset_dsp(d->io_base); d->flags |= SND_F_INIT ; @@ -485,9 +481,9 @@ sb_reset_dsp(int io_base) { int loopc; - outb(DSP_RESET, 1); + outb(io_base + SBDSP_RST, 1); DELAY(100); - outb(DSP_RESET, 0); + outb(io_base + SBDSP_RST, 0); for (loopc = 0; loopc<100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++) DELAY(30); @@ -568,7 +564,9 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) d->name, dev->id_unit, d->irq); else sb_setmixer(io_base, IRQ_NR, x); - + if (d->dbuf_out.chan == d->dbuf_in.chan) { + printf("WARNING: sb: misconfigured secondary DMA channel\n"); + } sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan)); break ; @@ -599,41 +597,22 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) DELAY(20); } - if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) + if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) { + /* the ESS488 can be treated as an SBPRO */ printf("ESS488 (rev %d)\n", ess_minor & 0x0f); - else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { - if ( (ess_minor & 0xf) >= 8 ) - printf("ESS1688 (rev %d)\n", ess_minor & 0x0f); - else - printf("ESS688 (rev %d)\n", ess_minor & 0x0f); - } else break ; - d->bd_id = (ess_major << 8) | ess_minor ; - d->bd_flags |= BD_F_ESS; - /* - * ESS-specific initialization, taken from OSSFree 3.8 - */ - { - static u_char irqs[16] = { - 0, 0, 0x50, 0, 0, 0x54, 0, 0x58, - 0, 0x50, 0x5c, 0, 0, 0, 0, 0 }; - static u_char drqs[8] = { - 0x51, 0x52, 0, 0x53, 0, 0, 0, 0 }; - x = irqs[d->irq & 0xf]; - if (x == 0) - printf("ESS : invalid IRQ %d\n", d->irq); - else { - sb_cmd(io_base, 0xb1 ); /* set IRQ */ - sb_cmd(io_base, x ); - - x = drqs[ d->dbuf_out.chan & 0x7 ]; - if (x == 0) - printf("ESS : invalid DRQ %d\n", d->dbuf_out.chan); - else { - sb_cmd(io_base, 0xb2 ); /* set DRQ */ - sb_cmd(io_base, x ); - } - } + } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { + int rev = ess_minor & 0xf ; + if ( rev >= 8 ) + printf("ESS1868 (rev %d)\n", rev); + else + printf("ESS688 (rev %d)\n", rev); + d->audio_fmt |= AFMT_S16_LE; /* in fact it is U16_LE */ + break ; /* XXX */ + } else { + printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", + ess_major, ess_minor); + break ; } } @@ -679,8 +658,8 @@ sb_cmd(int io_base, u_char val) int i; for (i = 0; i < 1000 ; i++) { - if ((inb(DSP_STATUS) & 0x80) == 0) { - outb(DSP_COMMAND, val); + if ((inb(io_base + SBDSP_STATUS) & 0x80) == 0) { + outb(io_base + SBDSP_CMD, val); return 1; } if (i > 10) @@ -712,32 +691,23 @@ sb_cmd2(int io_base, u_char cmd, int val) return 0; } +/* + * in the SB, there is a set of indirect "mixer" registers with + * address at offset 4, data at offset 5 + */ void sb_setmixer(int io_base, u_int port, u_int value) { u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - outb(MIXER_DATA, (u_char) (value & 0xff)); + outb(io_base + 5, (u_char) (value & 0xff)); DELAY(10); splx(flags); } -u_int -sb_get_byte(int io_base) -{ - int i; - - for (i = 1000; i; i--) - if (inb(DSP_DATA_AVAIL) & 0x80) - return inb(DSP_READ); - else - DELAY(20); - return 0xffff; -} - int sb_getmixer(int io_base, u_int port) { @@ -745,15 +715,29 @@ sb_getmixer(int io_base, u_int port) u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - val = inb(MIXER_DATA); + val = inb(io_base + 5); DELAY(10); splx(flags); return val; } +u_int +sb_get_byte(int io_base) +{ + int i; + + for (i = 1000; i; i--) + if (inb(DSP_DATA_AVAIL) & 0x80) + return inb(DSP_READ); + else + DELAY(20); + return 0xffff; +} + + /* * various utility functions for the DSP @@ -806,11 +790,12 @@ dsp_speed(snddev_info *d) } /* - * only some models can do stereo, and only if not + * This is code for the SB3.x and lower. + * Only some models can do stereo, and only if not * simultaneously using midi. + * At the moment we do not support either... */ - if ( (d->bd_id & 0xff00) < 0x300 || d->bd_flags & BD_F_MIDIBUSY) - d->flags &= ~SND_F_STEREO; + d->flags &= ~SND_F_STEREO; /* * here enforce speed limitations. @@ -830,26 +815,12 @@ dsp_speed(snddev_info *d) RANGE(speed, 4000, max_speed); - /* - * Logitech SoundMan Games and Jazz16 cards can support 44.1kHz - * stereo - */ -#if !defined (SM_GAMES) - /* - * Max. stereo speed is 22050 - */ - if (d->flags & SND_F_STEREO && speed > 22050 && !(d->bd_flags & BD_F_JAZZ16)) - speed = 22050; -#endif - - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed *= 2; /* * Now the speed should be valid. Compute the value to be * programmed into the board. - * - * XXX stereo init is still missing... */ if (speed > 22050) { /* High speed mode on 2.01/3.xx */ @@ -878,7 +849,7 @@ dsp_speed(snddev_info *d) speed = (1000000 + tmp / 2) / tmp; } - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed /= 2; d->play_speed = d->rec_speed = speed; @@ -1024,6 +995,79 @@ sb_mixer_set(snddev_info *d, int dev, int value) */ #if NPNP > 0 +static char *ess1868_probe(u_long csn, u_long vend_id); +static void ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); + +static struct pnp_device ess1868 = { + "ESS1868", + ess1868_probe, + ess1868_attach, + &nsnd, /* use this for all sound cards */ + &tty_imask /* imask */ +}; +DATA_SET (pnpdevice_set, ess1868); + +static char * +ess1868_probe(u_long csn, u_long vend_id) +{ + /* + * pnp X 1 os enable drq0 3 irq0 12 port0 0x240 + */ + if (vend_id == 0x68187316) { + struct pnp_cinfo d ; + read_pnp_parms ( &d , 1 ) ; + if (d.enable == 0) { + printf("This is an ESS1868, but LDN 1 is disabled\n"); + return NULL; + } + return "ESS1868" ; + } + return NULL ; +} + +static void +ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev) +{ + struct pnp_cinfo d ; + snddev_info tmp_d ; /* patched copy of the basic snddev_info */ + int the_irq = 0 ; + + tmp_d = sb_op_desc; + snddev_last_probed = &tmp_d; + +#if 0 + read_pnp_parms ( &d , 3 ); /* disable LDN 3 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 3 ); + + read_pnp_parms ( &d , 2 ); /* disable LDN 2 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 2 ); + read_pnp_parms ( &d , 0 ); /* read config base */ + tmp_d.conf_base = d.port[0]; + write_pnp_parms ( &d , 0 ); +#endif + + read_pnp_parms ( &d , 1 ) ; + dev->id_iobase = d.port[0]; + d.port[1] = 0 ; + d.port[2] = 0 ; + write_pnp_parms ( &d , 1 ); + enable_pnp_card(); + + dev->id_drq = d.drq[0] ; /* primary dma */ + dev->id_irq = (1 << d.irq[0] ) ; + dev->id_intr = pcmintr ; + dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */; + + snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */ + pcmattach(dev); +} + static char *opti925_probe(u_long csn, u_long vend_id); static void opti925_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); @@ -1155,6 +1199,7 @@ sb16pnp_attach(u_long csn, u_long vend_id, char *name, read_pnp_parms ( &d , 0 ) ; d.port[1] = 0 ; /* only the first address is used */ dev->id_iobase = d.port[0]; + tmp_d.synth_base = d.port[2]; write_pnp_parms ( &d , 0 ); enable_pnp_card(); diff --git a/sys/dev/sound/isa/sb.h b/sys/dev/sound/isa/sb.h index 1735c14..0bd4210 100644 --- a/sys/dev/sound/isa/sb.h +++ b/sys/dev/sound/isa/sb.h @@ -11,18 +11,21 @@ extern int sbc_major, sbc_minor ; * sound blaster registers */ -#define DSP_RESET (io_base + 0x6) +#define SBDSP_RST 0x6 #define DSP_READ (io_base + 0xA) #define DSP_WRITE (io_base + 0xC) -#define DSP_COMMAND (io_base + 0xC) -#define DSP_STATUS (io_base + 0xC) +#define SBDSP_CMD 0xC +#define SBDSP_STATUS 0xC #define DSP_DATA_AVAIL (io_base + 0xE) #define DSP_DATA_AVL16 (io_base + 0xF) + +#if 0 #define MIXER_ADDR (io_base + 0x4) #define MIXER_DATA (io_base + 0x5) #define OPL3_LEFT (io_base + 0x0) #define OPL3_RIGHT (io_base + 0x2) #define OPL3_BOTH (io_base + 0x8) +#endif /* * DSP Commands. There are many, and in many cases they are used explicitly diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c index 09440e1..3d75aea 100644 --- a/sys/dev/sound/isa/sb16.c +++ b/sys/dev/sound/isa/sb16.c @@ -92,7 +92,7 @@ snddev_info sb_op_desc = { NULL /* use generic sndread */, NULL /* use generic sndwrite */, sb_dsp_ioctl, - sndpoll, + sndselect, sbintr, sb_callback, @@ -123,7 +123,7 @@ sb_probe(struct isa_device *dev) bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) ); if (dev->id_iobase == -1) { dev->id_iobase = 0x220; - printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n"); + BVDDB(printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n");) if (snd_conflict(dev->id_iobase)) dev->id_iobase = 0x240; } @@ -196,6 +196,10 @@ sb_dsp_open(dev_t dev, int flags, int mode, struct proc * p) d->play_fmt = d->rec_fmt = AFMT_U8 ; break ; } + if ( (flags & FREAD) == 0) + d->rec_fmt = 0 ; + if ( (flags & FWRITE) == 0) + d->play_fmt = 0 ; d->flags |= SND_F_BUSY ; d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ; @@ -250,6 +254,8 @@ sb_dsp_ioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc * p) /* * for the remaining functions, use the default handler. + * ENOSYS means that the default handler should take care + * of implementing the ioctl. */ return ENOSYS ; @@ -292,7 +298,7 @@ again: DEB(printf("sbintr, flags 0x%08lx reason %d\n", d->flags, reason)); if ( reason & 1 ) { /* possibly a write interrupt */ if ( d->dbuf_out.dl ) - dsp_wrintr(d); + dsp_wrintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: wrintr but write DMA inactive!\n"); @@ -300,7 +306,7 @@ again: } if ( reason & 2 ) { if ( d->dbuf_in.dl ) - dsp_rdintr(d); + dsp_rdintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: rdintr but read DMA inactive!\n"); @@ -340,16 +346,11 @@ sb_callback(snddev_info *d, int reason) case SND_CB_INIT : /* called with int enabled and no pending io */ dsp_speed(d); snd_set_blocksize(d); - if (d->play_fmt & AFMT_MU_LAW) + if ( (d->play_fmt & AFMT_MU_LAW) || (d->rec_fmt & AFMT_MU_LAW) ) d->flags |= SND_F_XLAT8 ; else d->flags &= ~SND_F_XLAT8 ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - return 1; - break; - case SND_CB_START : /* called with int disabled */ if (d->bd_flags & BD_F_SB16) { u_char c, c1 ; @@ -363,42 +364,40 @@ sb_callback(snddev_info *d, int reason) */ int swap = 1 ; /* default... */ - if (rd) { - /* need not to swap if channel is already correct */ - if ( d->rec_fmt == AFMT_S16_LE && b->chan > 4 ) + if (d->play_fmt == 0) { + /* do whatever the read channel wants */ + if ( d->rec_fmt == AFMT_S16_LE && d->dbuf_in.chan > 4 ) swap = 0; - if ( d->rec_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->rec_fmt != AFMT_S16_LE && d->dbuf_in.chan < 4 ) swap = 0; - if (swap && (d->flags & SND_F_WRITING || d->dbuf_out.dl)) { - /* cannot swap if writing is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break; /* XXX should return an error */ - } } else { - /* need not to swap if channel is already correct */ - if ( d->play_fmt == AFMT_S16_LE && b->chan > 4 ) + /* privilege the write channel */ + if ( d->play_fmt == AFMT_S16_LE && d->dbuf_out.chan > 4 ) swap = 0; - if ( d->play_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->play_fmt != AFMT_S16_LE && d->dbuf_out.chan < 4 ) swap = 0; - if (swap && ( d->flags & SND_F_READING || d->dbuf_in.dl)) { - /* cannot swap if reading is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break ; /* XXX should return an error */ + if ( d->rec_fmt ) { + /* check for possible config errors. */ + if (d->rec_fmt == d->play_fmt) { + DDB(printf("sorry, read DMA channel unavailable\n")); + } } } - + DEB(printf("sb16: play_fmt %d, rec_fmt %x, swap %d\n", + d->play_fmt, d->rec_fmt, swap);) if (swap) { int c = d->dbuf_in.chan ; d->dbuf_in.chan = d->dbuf_out.chan; d->dbuf_out.chan = c ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - DEB(printf("START dma chan: play %d, rec %d\n", - d->dbuf_out.chan, d->dbuf_in.chan)); + } } + reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); + reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); + break ; + case SND_CB_START : /* called with int disabled */ + if (d->bd_flags & BD_F_SB16) { + u_char c, c1 ; /* * XXX note: c1 and l should be set basing on d->rec_fmt, * but there is no choice once a 16 or 8-bit channel @@ -408,7 +407,7 @@ sb_callback(snddev_info *d, int reason) if ( b->chan > 4 ) { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ; c1 = DSP_F16_SIGNED ; - l /= 2 ; + l /= 2 ; } else { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ; c1 = 0 ; @@ -421,28 +420,25 @@ sb_callback(snddev_info *d, int reason) sb_cmd3(d->io_base, c1 , l - 1) ; } else if (d->bd_flags & BD_F_ESS) { /* XXX this code is still incomplete */ - sb_cmd2(d->io_base, 0xb8, rd ? 0x0e : 0x04 ); /* auto dma */ - sb_cmd2(d->io_base, 0xa8, 2 /* chans */ ); - sb_cmd2(d->io_base, 0xb9, 2); /* demand mode */ - /* - input: 0xb8 -> 0x0e ; - 0xa8 -> channels - 0xb9 -> 2 - mono,U8: 51, d0 - mono,S16 71, f4 - st, U8 51, 98 - st, S16 71, bc - */ - } else { /* SBPro */ + } else { /* SBPro -- stereo not supported */ u_char c ; if (!rd) sb_cmd(d->io_base, DSP_CMD_SPKON); - /* code for the SB2 and SB3 */ + /* code for the SB2 and SB3, only MONO */ if (d->bd_flags & BD_F_HISPEED) - c = (rd) ? DSP_CMD_HSADC_AUTO : DSP_CMD_HSDAC_AUTO ; + c = (rd) ? 0x98 : 0x90 ; else - c = (rd) ? DSP_CMD_ADC8_AUTO : DSP_CMD_DAC8_AUTO ; - sb_cmd3(d->io_base, c , l - 1) ; + c = (rd) ? 0x2c : 0x1c ; + /* + * some ESS extensions -- they can do 16 bits + */ + if ( (rd && d->rec_fmt == AFMT_S16_LE) || + (!rd && d->play_fmt == AFMT_S16_LE) ) { + c |= 1; + l /= 2 ; + } + sb_cmd3(d->io_base, 0x48 , l - 1) ; + sb_cmd(d->io_base, c ) ; } break; @@ -451,7 +447,7 @@ sb_callback(snddev_info *d, int reason) { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ if ( d->bd_flags & BD_F_SB16 && b->chan > 4 ) - cmd = DSP_CMD_DMAPAUSE_16 ; + cmd = DSP_CMD_DMAPAUSE_16 ; if (d->bd_flags & BD_F_HISPEED) { sb_reset_dsp(d->io_base); d->flags |= SND_F_INIT ; @@ -485,9 +481,9 @@ sb_reset_dsp(int io_base) { int loopc; - outb(DSP_RESET, 1); + outb(io_base + SBDSP_RST, 1); DELAY(100); - outb(DSP_RESET, 0); + outb(io_base + SBDSP_RST, 0); for (loopc = 0; loopc<100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++) DELAY(30); @@ -568,7 +564,9 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) d->name, dev->id_unit, d->irq); else sb_setmixer(io_base, IRQ_NR, x); - + if (d->dbuf_out.chan == d->dbuf_in.chan) { + printf("WARNING: sb: misconfigured secondary DMA channel\n"); + } sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan)); break ; @@ -599,41 +597,22 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) DELAY(20); } - if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) + if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) { + /* the ESS488 can be treated as an SBPRO */ printf("ESS488 (rev %d)\n", ess_minor & 0x0f); - else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { - if ( (ess_minor & 0xf) >= 8 ) - printf("ESS1688 (rev %d)\n", ess_minor & 0x0f); - else - printf("ESS688 (rev %d)\n", ess_minor & 0x0f); - } else break ; - d->bd_id = (ess_major << 8) | ess_minor ; - d->bd_flags |= BD_F_ESS; - /* - * ESS-specific initialization, taken from OSSFree 3.8 - */ - { - static u_char irqs[16] = { - 0, 0, 0x50, 0, 0, 0x54, 0, 0x58, - 0, 0x50, 0x5c, 0, 0, 0, 0, 0 }; - static u_char drqs[8] = { - 0x51, 0x52, 0, 0x53, 0, 0, 0, 0 }; - x = irqs[d->irq & 0xf]; - if (x == 0) - printf("ESS : invalid IRQ %d\n", d->irq); - else { - sb_cmd(io_base, 0xb1 ); /* set IRQ */ - sb_cmd(io_base, x ); - - x = drqs[ d->dbuf_out.chan & 0x7 ]; - if (x == 0) - printf("ESS : invalid DRQ %d\n", d->dbuf_out.chan); - else { - sb_cmd(io_base, 0xb2 ); /* set DRQ */ - sb_cmd(io_base, x ); - } - } + } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { + int rev = ess_minor & 0xf ; + if ( rev >= 8 ) + printf("ESS1868 (rev %d)\n", rev); + else + printf("ESS688 (rev %d)\n", rev); + d->audio_fmt |= AFMT_S16_LE; /* in fact it is U16_LE */ + break ; /* XXX */ + } else { + printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", + ess_major, ess_minor); + break ; } } @@ -679,8 +658,8 @@ sb_cmd(int io_base, u_char val) int i; for (i = 0; i < 1000 ; i++) { - if ((inb(DSP_STATUS) & 0x80) == 0) { - outb(DSP_COMMAND, val); + if ((inb(io_base + SBDSP_STATUS) & 0x80) == 0) { + outb(io_base + SBDSP_CMD, val); return 1; } if (i > 10) @@ -712,32 +691,23 @@ sb_cmd2(int io_base, u_char cmd, int val) return 0; } +/* + * in the SB, there is a set of indirect "mixer" registers with + * address at offset 4, data at offset 5 + */ void sb_setmixer(int io_base, u_int port, u_int value) { u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - outb(MIXER_DATA, (u_char) (value & 0xff)); + outb(io_base + 5, (u_char) (value & 0xff)); DELAY(10); splx(flags); } -u_int -sb_get_byte(int io_base) -{ - int i; - - for (i = 1000; i; i--) - if (inb(DSP_DATA_AVAIL) & 0x80) - return inb(DSP_READ); - else - DELAY(20); - return 0xffff; -} - int sb_getmixer(int io_base, u_int port) { @@ -745,15 +715,29 @@ sb_getmixer(int io_base, u_int port) u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - val = inb(MIXER_DATA); + val = inb(io_base + 5); DELAY(10); splx(flags); return val; } +u_int +sb_get_byte(int io_base) +{ + int i; + + for (i = 1000; i; i--) + if (inb(DSP_DATA_AVAIL) & 0x80) + return inb(DSP_READ); + else + DELAY(20); + return 0xffff; +} + + /* * various utility functions for the DSP @@ -806,11 +790,12 @@ dsp_speed(snddev_info *d) } /* - * only some models can do stereo, and only if not + * This is code for the SB3.x and lower. + * Only some models can do stereo, and only if not * simultaneously using midi. + * At the moment we do not support either... */ - if ( (d->bd_id & 0xff00) < 0x300 || d->bd_flags & BD_F_MIDIBUSY) - d->flags &= ~SND_F_STEREO; + d->flags &= ~SND_F_STEREO; /* * here enforce speed limitations. @@ -830,26 +815,12 @@ dsp_speed(snddev_info *d) RANGE(speed, 4000, max_speed); - /* - * Logitech SoundMan Games and Jazz16 cards can support 44.1kHz - * stereo - */ -#if !defined (SM_GAMES) - /* - * Max. stereo speed is 22050 - */ - if (d->flags & SND_F_STEREO && speed > 22050 && !(d->bd_flags & BD_F_JAZZ16)) - speed = 22050; -#endif - - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed *= 2; /* * Now the speed should be valid. Compute the value to be * programmed into the board. - * - * XXX stereo init is still missing... */ if (speed > 22050) { /* High speed mode on 2.01/3.xx */ @@ -878,7 +849,7 @@ dsp_speed(snddev_info *d) speed = (1000000 + tmp / 2) / tmp; } - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed /= 2; d->play_speed = d->rec_speed = speed; @@ -1024,6 +995,79 @@ sb_mixer_set(snddev_info *d, int dev, int value) */ #if NPNP > 0 +static char *ess1868_probe(u_long csn, u_long vend_id); +static void ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); + +static struct pnp_device ess1868 = { + "ESS1868", + ess1868_probe, + ess1868_attach, + &nsnd, /* use this for all sound cards */ + &tty_imask /* imask */ +}; +DATA_SET (pnpdevice_set, ess1868); + +static char * +ess1868_probe(u_long csn, u_long vend_id) +{ + /* + * pnp X 1 os enable drq0 3 irq0 12 port0 0x240 + */ + if (vend_id == 0x68187316) { + struct pnp_cinfo d ; + read_pnp_parms ( &d , 1 ) ; + if (d.enable == 0) { + printf("This is an ESS1868, but LDN 1 is disabled\n"); + return NULL; + } + return "ESS1868" ; + } + return NULL ; +} + +static void +ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev) +{ + struct pnp_cinfo d ; + snddev_info tmp_d ; /* patched copy of the basic snddev_info */ + int the_irq = 0 ; + + tmp_d = sb_op_desc; + snddev_last_probed = &tmp_d; + +#if 0 + read_pnp_parms ( &d , 3 ); /* disable LDN 3 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 3 ); + + read_pnp_parms ( &d , 2 ); /* disable LDN 2 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 2 ); + read_pnp_parms ( &d , 0 ); /* read config base */ + tmp_d.conf_base = d.port[0]; + write_pnp_parms ( &d , 0 ); +#endif + + read_pnp_parms ( &d , 1 ) ; + dev->id_iobase = d.port[0]; + d.port[1] = 0 ; + d.port[2] = 0 ; + write_pnp_parms ( &d , 1 ); + enable_pnp_card(); + + dev->id_drq = d.drq[0] ; /* primary dma */ + dev->id_irq = (1 << d.irq[0] ) ; + dev->id_intr = pcmintr ; + dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */; + + snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */ + pcmattach(dev); +} + static char *opti925_probe(u_long csn, u_long vend_id); static void opti925_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); @@ -1155,6 +1199,7 @@ sb16pnp_attach(u_long csn, u_long vend_id, char *name, read_pnp_parms ( &d , 0 ) ; d.port[1] = 0 ; /* only the first address is used */ dev->id_iobase = d.port[0]; + tmp_d.synth_base = d.port[2]; write_pnp_parms ( &d , 0 ); enable_pnp_card(); diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c index 09440e1..3d75aea 100644 --- a/sys/dev/sound/isa/sb8.c +++ b/sys/dev/sound/isa/sb8.c @@ -92,7 +92,7 @@ snddev_info sb_op_desc = { NULL /* use generic sndread */, NULL /* use generic sndwrite */, sb_dsp_ioctl, - sndpoll, + sndselect, sbintr, sb_callback, @@ -123,7 +123,7 @@ sb_probe(struct isa_device *dev) bzero(&pcm_info[dev->id_unit], sizeof(pcm_info[dev->id_unit]) ); if (dev->id_iobase == -1) { dev->id_iobase = 0x220; - printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n"); + BVDDB(printf("sb_probe: no address supplied, try defaults (0x220,0x240)\n");) if (snd_conflict(dev->id_iobase)) dev->id_iobase = 0x240; } @@ -196,6 +196,10 @@ sb_dsp_open(dev_t dev, int flags, int mode, struct proc * p) d->play_fmt = d->rec_fmt = AFMT_U8 ; break ; } + if ( (flags & FREAD) == 0) + d->rec_fmt = 0 ; + if ( (flags & FWRITE) == 0) + d->play_fmt = 0 ; d->flags |= SND_F_BUSY ; d->play_speed = d->rec_speed = DSP_DEFAULT_SPEED ; @@ -250,6 +254,8 @@ sb_dsp_ioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc * p) /* * for the remaining functions, use the default handler. + * ENOSYS means that the default handler should take care + * of implementing the ioctl. */ return ENOSYS ; @@ -292,7 +298,7 @@ again: DEB(printf("sbintr, flags 0x%08lx reason %d\n", d->flags, reason)); if ( reason & 1 ) { /* possibly a write interrupt */ if ( d->dbuf_out.dl ) - dsp_wrintr(d); + dsp_wrintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: wrintr but write DMA inactive!\n"); @@ -300,7 +306,7 @@ again: } if ( reason & 2 ) { if ( d->dbuf_in.dl ) - dsp_rdintr(d); + dsp_rdintr(d); else { if (d->bd_flags & BD_F_SB16) printf("WARNING: rdintr but read DMA inactive!\n"); @@ -340,16 +346,11 @@ sb_callback(snddev_info *d, int reason) case SND_CB_INIT : /* called with int enabled and no pending io */ dsp_speed(d); snd_set_blocksize(d); - if (d->play_fmt & AFMT_MU_LAW) + if ( (d->play_fmt & AFMT_MU_LAW) || (d->rec_fmt & AFMT_MU_LAW) ) d->flags |= SND_F_XLAT8 ; else d->flags &= ~SND_F_XLAT8 ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - return 1; - break; - case SND_CB_START : /* called with int disabled */ if (d->bd_flags & BD_F_SB16) { u_char c, c1 ; @@ -363,42 +364,40 @@ sb_callback(snddev_info *d, int reason) */ int swap = 1 ; /* default... */ - if (rd) { - /* need not to swap if channel is already correct */ - if ( d->rec_fmt == AFMT_S16_LE && b->chan > 4 ) + if (d->play_fmt == 0) { + /* do whatever the read channel wants */ + if ( d->rec_fmt == AFMT_S16_LE && d->dbuf_in.chan > 4 ) swap = 0; - if ( d->rec_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->rec_fmt != AFMT_S16_LE && d->dbuf_in.chan < 4 ) swap = 0; - if (swap && (d->flags & SND_F_WRITING || d->dbuf_out.dl)) { - /* cannot swap if writing is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break; /* XXX should return an error */ - } } else { - /* need not to swap if channel is already correct */ - if ( d->play_fmt == AFMT_S16_LE && b->chan > 4 ) + /* privilege the write channel */ + if ( d->play_fmt == AFMT_S16_LE && d->dbuf_out.chan > 4 ) swap = 0; - if ( d->play_fmt != AFMT_S16_LE && b->chan < 4 ) + if ( d->play_fmt != AFMT_S16_LE && d->dbuf_out.chan < 4 ) swap = 0; - if (swap && ( d->flags & SND_F_READING || d->dbuf_in.dl)) { - /* cannot swap if reading is already active */ - DDB(printf("sorry, DMA channel unavailable\n")); - swap = 0; - break ; /* XXX should return an error */ + if ( d->rec_fmt ) { + /* check for possible config errors. */ + if (d->rec_fmt == d->play_fmt) { + DDB(printf("sorry, read DMA channel unavailable\n")); + } } } - + DEB(printf("sb16: play_fmt %d, rec_fmt %x, swap %d\n", + d->play_fmt, d->rec_fmt, swap);) if (swap) { int c = d->dbuf_in.chan ; d->dbuf_in.chan = d->dbuf_out.chan; d->dbuf_out.chan = c ; - reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); - reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); - DEB(printf("START dma chan: play %d, rec %d\n", - d->dbuf_out.chan, d->dbuf_in.chan)); + } } + reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); + reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); + break ; + case SND_CB_START : /* called with int disabled */ + if (d->bd_flags & BD_F_SB16) { + u_char c, c1 ; /* * XXX note: c1 and l should be set basing on d->rec_fmt, * but there is no choice once a 16 or 8-bit channel @@ -408,7 +407,7 @@ sb_callback(snddev_info *d, int reason) if ( b->chan > 4 ) { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ; c1 = DSP_F16_SIGNED ; - l /= 2 ; + l /= 2 ; } else { c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ; c1 = 0 ; @@ -421,28 +420,25 @@ sb_callback(snddev_info *d, int reason) sb_cmd3(d->io_base, c1 , l - 1) ; } else if (d->bd_flags & BD_F_ESS) { /* XXX this code is still incomplete */ - sb_cmd2(d->io_base, 0xb8, rd ? 0x0e : 0x04 ); /* auto dma */ - sb_cmd2(d->io_base, 0xa8, 2 /* chans */ ); - sb_cmd2(d->io_base, 0xb9, 2); /* demand mode */ - /* - input: 0xb8 -> 0x0e ; - 0xa8 -> channels - 0xb9 -> 2 - mono,U8: 51, d0 - mono,S16 71, f4 - st, U8 51, 98 - st, S16 71, bc - */ - } else { /* SBPro */ + } else { /* SBPro -- stereo not supported */ u_char c ; if (!rd) sb_cmd(d->io_base, DSP_CMD_SPKON); - /* code for the SB2 and SB3 */ + /* code for the SB2 and SB3, only MONO */ if (d->bd_flags & BD_F_HISPEED) - c = (rd) ? DSP_CMD_HSADC_AUTO : DSP_CMD_HSDAC_AUTO ; + c = (rd) ? 0x98 : 0x90 ; else - c = (rd) ? DSP_CMD_ADC8_AUTO : DSP_CMD_DAC8_AUTO ; - sb_cmd3(d->io_base, c , l - 1) ; + c = (rd) ? 0x2c : 0x1c ; + /* + * some ESS extensions -- they can do 16 bits + */ + if ( (rd && d->rec_fmt == AFMT_S16_LE) || + (!rd && d->play_fmt == AFMT_S16_LE) ) { + c |= 1; + l /= 2 ; + } + sb_cmd3(d->io_base, 0x48 , l - 1) ; + sb_cmd(d->io_base, c ) ; } break; @@ -451,7 +447,7 @@ sb_callback(snddev_info *d, int reason) { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ if ( d->bd_flags & BD_F_SB16 && b->chan > 4 ) - cmd = DSP_CMD_DMAPAUSE_16 ; + cmd = DSP_CMD_DMAPAUSE_16 ; if (d->bd_flags & BD_F_HISPEED) { sb_reset_dsp(d->io_base); d->flags |= SND_F_INIT ; @@ -485,9 +481,9 @@ sb_reset_dsp(int io_base) { int loopc; - outb(DSP_RESET, 1); + outb(io_base + SBDSP_RST, 1); DELAY(100); - outb(DSP_RESET, 0); + outb(io_base + SBDSP_RST, 0); for (loopc = 0; loopc<100 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++) DELAY(30); @@ -568,7 +564,9 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) d->name, dev->id_unit, d->irq); else sb_setmixer(io_base, IRQ_NR, x); - + if (d->dbuf_out.chan == d->dbuf_in.chan) { + printf("WARNING: sb: misconfigured secondary DMA channel\n"); + } sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan)); break ; @@ -599,41 +597,22 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) DELAY(20); } - if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) + if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) { + /* the ESS488 can be treated as an SBPRO */ printf("ESS488 (rev %d)\n", ess_minor & 0x0f); - else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { - if ( (ess_minor & 0xf) >= 8 ) - printf("ESS1688 (rev %d)\n", ess_minor & 0x0f); - else - printf("ESS688 (rev %d)\n", ess_minor & 0x0f); - } else break ; - d->bd_id = (ess_major << 8) | ess_minor ; - d->bd_flags |= BD_F_ESS; - /* - * ESS-specific initialization, taken from OSSFree 3.8 - */ - { - static u_char irqs[16] = { - 0, 0, 0x50, 0, 0, 0x54, 0, 0x58, - 0, 0x50, 0x5c, 0, 0, 0, 0, 0 }; - static u_char drqs[8] = { - 0x51, 0x52, 0, 0x53, 0, 0, 0, 0 }; - x = irqs[d->irq & 0xf]; - if (x == 0) - printf("ESS : invalid IRQ %d\n", d->irq); - else { - sb_cmd(io_base, 0xb1 ); /* set IRQ */ - sb_cmd(io_base, x ); - - x = drqs[ d->dbuf_out.chan & 0x7 ]; - if (x == 0) - printf("ESS : invalid DRQ %d\n", d->dbuf_out.chan); - else { - sb_cmd(io_base, 0xb2 ); /* set DRQ */ - sb_cmd(io_base, x ); - } - } + } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { + int rev = ess_minor & 0xf ; + if ( rev >= 8 ) + printf("ESS1868 (rev %d)\n", rev); + else + printf("ESS688 (rev %d)\n", rev); + d->audio_fmt |= AFMT_S16_LE; /* in fact it is U16_LE */ + break ; /* XXX */ + } else { + printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", + ess_major, ess_minor); + break ; } } @@ -679,8 +658,8 @@ sb_cmd(int io_base, u_char val) int i; for (i = 0; i < 1000 ; i++) { - if ((inb(DSP_STATUS) & 0x80) == 0) { - outb(DSP_COMMAND, val); + if ((inb(io_base + SBDSP_STATUS) & 0x80) == 0) { + outb(io_base + SBDSP_CMD, val); return 1; } if (i > 10) @@ -712,32 +691,23 @@ sb_cmd2(int io_base, u_char cmd, int val) return 0; } +/* + * in the SB, there is a set of indirect "mixer" registers with + * address at offset 4, data at offset 5 + */ void sb_setmixer(int io_base, u_int port, u_int value) { u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - outb(MIXER_DATA, (u_char) (value & 0xff)); + outb(io_base + 5, (u_char) (value & 0xff)); DELAY(10); splx(flags); } -u_int -sb_get_byte(int io_base) -{ - int i; - - for (i = 1000; i; i--) - if (inb(DSP_DATA_AVAIL) & 0x80) - return inb(DSP_READ); - else - DELAY(20); - return 0xffff; -} - int sb_getmixer(int io_base, u_int port) { @@ -745,15 +715,29 @@ sb_getmixer(int io_base, u_int port) u_long flags; flags = spltty(); - outb(MIXER_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - val = inb(MIXER_DATA); + val = inb(io_base + 5); DELAY(10); splx(flags); return val; } +u_int +sb_get_byte(int io_base) +{ + int i; + + for (i = 1000; i; i--) + if (inb(DSP_DATA_AVAIL) & 0x80) + return inb(DSP_READ); + else + DELAY(20); + return 0xffff; +} + + /* * various utility functions for the DSP @@ -806,11 +790,12 @@ dsp_speed(snddev_info *d) } /* - * only some models can do stereo, and only if not + * This is code for the SB3.x and lower. + * Only some models can do stereo, and only if not * simultaneously using midi. + * At the moment we do not support either... */ - if ( (d->bd_id & 0xff00) < 0x300 || d->bd_flags & BD_F_MIDIBUSY) - d->flags &= ~SND_F_STEREO; + d->flags &= ~SND_F_STEREO; /* * here enforce speed limitations. @@ -830,26 +815,12 @@ dsp_speed(snddev_info *d) RANGE(speed, 4000, max_speed); - /* - * Logitech SoundMan Games and Jazz16 cards can support 44.1kHz - * stereo - */ -#if !defined (SM_GAMES) - /* - * Max. stereo speed is 22050 - */ - if (d->flags & SND_F_STEREO && speed > 22050 && !(d->bd_flags & BD_F_JAZZ16)) - speed = 22050; -#endif - - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed *= 2; /* * Now the speed should be valid. Compute the value to be * programmed into the board. - * - * XXX stereo init is still missing... */ if (speed > 22050) { /* High speed mode on 2.01/3.xx */ @@ -878,7 +849,7 @@ dsp_speed(snddev_info *d) speed = (1000000 + tmp / 2) / tmp; } - if (d->flags & SND_F_STEREO) + if (d->flags & SND_F_STEREO) /* really unused right now... */ speed /= 2; d->play_speed = d->rec_speed = speed; @@ -1024,6 +995,79 @@ sb_mixer_set(snddev_info *d, int dev, int value) */ #if NPNP > 0 +static char *ess1868_probe(u_long csn, u_long vend_id); +static void ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); + +static struct pnp_device ess1868 = { + "ESS1868", + ess1868_probe, + ess1868_attach, + &nsnd, /* use this for all sound cards */ + &tty_imask /* imask */ +}; +DATA_SET (pnpdevice_set, ess1868); + +static char * +ess1868_probe(u_long csn, u_long vend_id) +{ + /* + * pnp X 1 os enable drq0 3 irq0 12 port0 0x240 + */ + if (vend_id == 0x68187316) { + struct pnp_cinfo d ; + read_pnp_parms ( &d , 1 ) ; + if (d.enable == 0) { + printf("This is an ESS1868, but LDN 1 is disabled\n"); + return NULL; + } + return "ESS1868" ; + } + return NULL ; +} + +static void +ess1868_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev) +{ + struct pnp_cinfo d ; + snddev_info tmp_d ; /* patched copy of the basic snddev_info */ + int the_irq = 0 ; + + tmp_d = sb_op_desc; + snddev_last_probed = &tmp_d; + +#if 0 + read_pnp_parms ( &d , 3 ); /* disable LDN 3 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 3 ); + + read_pnp_parms ( &d , 2 ); /* disable LDN 2 */ + d.port[0] = 0 ; + d.enable = 0 ; + write_pnp_parms ( &d , 2 ); + read_pnp_parms ( &d , 0 ); /* read config base */ + tmp_d.conf_base = d.port[0]; + write_pnp_parms ( &d , 0 ); +#endif + + read_pnp_parms ( &d , 1 ) ; + dev->id_iobase = d.port[0]; + d.port[1] = 0 ; + d.port[2] = 0 ; + write_pnp_parms ( &d , 1 ); + enable_pnp_card(); + + dev->id_drq = d.drq[0] ; /* primary dma */ + dev->id_irq = (1 << d.irq[0] ) ; + dev->id_intr = pcmintr ; + dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */; + + snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */ + pcmattach(dev); +} + static char *opti925_probe(u_long csn, u_long vend_id); static void opti925_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); @@ -1155,6 +1199,7 @@ sb16pnp_attach(u_long csn, u_long vend_id, char *name, read_pnp_parms ( &d , 0 ) ; d.port[1] = 0 ; /* only the first address is used */ dev->id_iobase = d.port[0]; + tmp_d.synth_base = d.port[2]; write_pnp_parms ( &d , 0 ); enable_pnp_card(); |