summaryrefslogtreecommitdiffstats
path: root/sys/dev/pcm
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>1997-11-23 07:03:21 +0000
committerjmg <jmg@FreeBSD.org>1997-11-23 07:03:21 +0000
commit348887306acab40ade2bfdee099485c5473b6425 (patch)
tree52f7a18fc4b5a6fb697bc369f111cf679e96becb /sys/dev/pcm
parent4037ac32c7a48bc16ba2d0eab7e580d38e305ea7 (diff)
downloadFreeBSD-src-348887306acab40ade2bfdee099485c5473b6425.zip
FreeBSD-src-348887306acab40ade2bfdee099485c5473b6425.tar.gz
update of Luigi's sound drivers...
this updates to 971117 plus a small sb change that was after that release..
Diffstat (limited to 'sys/dev/pcm')
-rw-r--r--sys/dev/pcm/isa/mss.c78
-rw-r--r--sys/dev/pcm/isa/sb.c212
-rw-r--r--sys/dev/pcm/isa/sb.h1
3 files changed, 199 insertions, 92 deletions
diff --git a/sys/dev/pcm/isa/mss.c b/sys/dev/pcm/isa/mss.c
index 0cd2dfd..a6bf624 100644
--- a/sys/dev/pcm/isa/mss.c
+++ b/sys/dev/pcm/isa/mss.c
@@ -197,7 +197,7 @@ mss_attach(struct isa_device *dev)
printf("mss_attach <%s>%d at 0x%x irq %d dma %d:%d flags 0x%x\n",
d->name, dev->id_unit,
- d->io_base, d->irq, d->dma1, d->dma2, dev->id_flags);
+ d->io_base, d->irq, d->dbuf_out.chan, d->dbuf_in.chan, dev->id_flags);
dev->id_alive = 8 ; /* number of io ports */
/* should be already set but just in case... */
@@ -220,18 +220,18 @@ mss_attach(struct isa_device *dev)
printf("[IRQ Conflict?]");
/* Write IRQ+DMA setup */
- if (d->dma1 == d->dma2) /* single chan dma */
- outb(dev->id_iobase, bits | dma_bits[d->dma1]);
+ if ( ! FULL_DUPLEX(d) ) /* single chan dma */
+ outb(dev->id_iobase, bits | dma_bits[d->dbuf_out.chan]);
else {
- if (d->dma1 == 0 && d->dma2 == 1)
+ if (d->dbuf_out.chan == 0 && d->dbuf_in.chan == 1)
bits |= 5 ;
- else if (d->dma1 == 1 && d->dma2 == 0)
+ else if (d->dbuf_out.chan == 1 && d->dbuf_in.chan == 0)
bits |= 6 ;
- else if (d->dma1 == 3 && d->dma2 == 0)
+ else if (d->dbuf_out.chan == 3 && d->dbuf_in.chan == 0)
bits |= 7 ;
else {
printf("invalid dual dma config %d:%d\n",
- d->dma1, d->dma2);
+ d->dbuf_out.chan, d->dbuf_in.chan);
dev->id_irq = 0 ;
dev->id_alive = 0 ; /* this makes attach fail. */
return 0 ;
@@ -239,7 +239,7 @@ mss_attach(struct isa_device *dev)
outb(dev->id_iobase, bits );
}
}
- if (d->dma1 != d->dma2)
+ if ( FULL_DUPLEX(d) )
d->audio_fmt |= AFMT_FULLDUPLEX ;
mss_reinit(d);
ad1848_mixer_reset(d);
@@ -293,6 +293,9 @@ mss_open(dev_t dev, int flags, int mode, struct proc * p)
d->rsel.si_pid = 0;
d->rsel.si_flags = 0;
+ d->dbuf_out.total = d->dbuf_out.prev_total = 0 ;
+ d->dbuf_in.total = d->dbuf_in.prev_total = 0 ;
+
if (flags & O_NONBLOCK)
d->flags |= SND_F_NBIO ;
@@ -426,7 +429,7 @@ mss_callback(snddev_info *d, int reason)
if (retry == 0)
printf("start dma, failed to set bit 0x%02x 0x%02x\n",
m, ad_read(d, 9) ) ;
- if (wr || (d->dma1 == d->dma2) )
+ if (wr || ! FULL_DUPLEX(d) )
ad_write_cnt(d, 14, cnt);
else
ad_write_cnt(d, 30, cnt);
@@ -452,7 +455,7 @@ mss_callback(snddev_info *d, int reason)
* is needed, and it might cause false interrupts when the
* DMA is re-enabled later.
*/
- if (wr || (d->dma1 == d->dma2) )
+ if (wr || ! FULL_DUPLEX(d) )
ad_write_cnt(d, 14, 0);
else
ad_write_cnt(d, 30, 0);
@@ -492,7 +495,7 @@ mss_intr(int unit)
*/
for (i=10 ; i && inb(io_Status(d)) & 1 ; i-- ) {
/* get exact reason for full-duplex boards */
- c = (d->dma1 == d->dma2) ? 0x30 : ad_read(d, 24);
+ c = FULL_DUPLEX(d) ? ad_read(d, 24) : 0x30 ;
c &= ~served ;
if ( d->dbuf_out.dl && (c & 0x10) ) {
served |= 0x10 ;
@@ -505,10 +508,18 @@ mss_intr(int unit)
/*
* now ack the interrupt
*/
- if (d->dma1 == d->dma2)
- outb(io_Status(d), 0); /* Clear interrupt status */
- else
+ if ( FULL_DUPLEX(d) )
ad_write(d, 24, ~c); /* ack selectively */
+ else
+ outb(io_Status(d), 0); /* Clear interrupt status */
+ }
+ if (served == 0) {
+ printf("How strange... mss_intr with no reason!\n");
+ /*
+ * this should not happen... I have no idea what to do now.
+ * maybe should do a sanity check and restart dmas ?
+ */
+ outb(io_Status(d), 0); /* Clear interrupt status */
}
}
@@ -534,7 +545,7 @@ opti931_intr(int unit)
i11 = ad_read(d, 11); /* XXX what's for ? */
again:
- c=mc11 = (d->dma1 == d->dma2) ? 0xc : opti_read(d->conf_base, 11);
+ c=mc11 = FULL_DUPLEX(d) ? opti_read(d->conf_base, 11) : 0xc ;
mc11 &= 0x0c ;
if (c & 0x10) {
printf("Warning: CD interrupt\n");
@@ -791,7 +802,7 @@ mss_set_recsrc(snddev_info *d, int mask)
*/
static char mix_cvt[101] = {
- 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+ 0, 1, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
@@ -849,8 +860,12 @@ mss_mixer_set(snddev_info *d, int dev, int value)
regoffs = (*mix_d)[dev][LEFT_CHN].regno;
old = val = ad_read(d, regoffs);
- if (regoffs != 0)
- val = old & 0x7f ; /* clear mute bit. */
+ /*
+ * if volume is 0, mute chan. Otherwise, unmute.
+ */
+ if (regoffs != 0) /* main input is different */
+ val = (left == 0 ) ? old | 0x80 : old & 0x7f ;
+
change_bits(mix_d, &val, dev, LEFT_CHN, left);
ad_write(d, regoffs, val);
DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n",
@@ -863,7 +878,7 @@ mss_mixer_set(snddev_info *d, int dev, int value)
regoffs = (*mix_d)[dev][RIGHT_CHN].regno;
old = val = ad_read(d, regoffs);
if (regoffs != 1)
- val = old & 0x7f ; /* clear mute bit. */
+ val = (right == 0 ) ? old | 0x80 : old & 0x7f ;
change_bits(mix_d, &val, dev, RIGHT_CHN, right);
ad_write(d, regoffs, val);
DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n",
@@ -1261,7 +1276,7 @@ mss_reinit(snddev_info *d)
* perhaps this is not the place to set mode2, should be done
* only once at attach time...
*/
- if ( d->dma1 != d->dma2 && d->bd_id != MD_OPTI931)
+ if ( FULL_DUPLEX(d) && d->bd_id != MD_OPTI931)
/*
* set mode2 bit for dual dma op. This bit is not implemented
* on the OPTi931
@@ -1282,7 +1297,7 @@ mss_reinit(snddev_info *d)
}
ad_write(d, 8, r) ;
- if (d->dma1 != d->dma2) {
+ if ( FULL_DUPLEX(d) ) {
#if 0
if (d->bd_id == MD_GUSPNP && d->play_fmt == AFMT_MU_LAW) {
printf("warning, cannot do ulaw rec + play on the GUS\n");
@@ -1298,7 +1313,7 @@ mss_reinit(snddev_info *d)
* not sure if this is really needed...
*/
ad_write_cnt(d, 14, 0 ); /* playback count */
- if (d->dma1 != d->dma2)
+ if ( FULL_DUPLEX(d) )
ad_write_cnt(d, 30, 0 ); /* rec. count on dual dma */
ad_write(d, 10, 2 /* int enable */) ;
@@ -1322,7 +1337,7 @@ static void cs423x_attach(u_long csn, u_long vend_id, char *name,
struct isa_device *dev);
static struct pnp_device cs423x = {
- "cs423x/ymh0020",
+ "CS423x/Yamaha",
cs423x_probe,
cs423x_attach,
&nsnd, /* use this for all sound cards */
@@ -1343,6 +1358,8 @@ cs423x_probe(u_long csn, u_long vend_id)
s = "CS4232" ;
else if ( id == 0x2000a865)
s = "Yamaha SA2";
+ else if ( id == 0x3000a865)
+ s = "Yamaha SA3";
else if (vend_id == 0x8140d315)
s = "SoundscapeVIVO";
if (s) {
@@ -1376,8 +1393,8 @@ cs423x_attach(u_long csn, u_long vend_id, char *name,
if (d.flags & DV_PNP_SBCODEC) { /*** use sb-compatible codec ***/
dev->id_alive = 16 ; /* number of io ports ? */
tmp_d = sb_op_desc ;
- if (vend_id == 0x2000a865 || vend_id == 0x8140d315) {
- /* Yamaha SA2 or ENSONIQ SoundscapeVIVO ENS4081 */
+ if (vend_id==0x2000a865 || vend_id==0x3000a865 || vend_id==0x8140d315) {
+ /* Yamaha SA2/SA3 or ENSONIQ SoundscapeVIVO ENS4081 */
dev->id_iobase = d.port[0] ;
tmp_d.alt_base = d.port[1] ;
d.irq[1] = 0 ; /* only needed for the VIVO */
@@ -1393,9 +1410,11 @@ cs423x_attach(u_long csn, u_long vend_id, char *name,
tmp_d.alt_base = d.port[2];
switch (vend_id & 0xff00ffff) {
- case 0x2000a865: /* yamaha SA-2 */
+ case 0x2000a865: /* Yamaha SA2 */
+ case 0x3000a865: /* Yamaha SA3 */
dev->id_iobase = d.port[1];
tmp_d.alt_base = d.port[0];
+ tmp_d.conf_base = d.port[4];
tmp_d.bd_id = MD_YM0020 ;
break;
@@ -1424,6 +1443,13 @@ cs423x_attach(u_long csn, u_long vend_id, char *name,
write_pnp_parms( &d, ldn );
enable_pnp_card();
+ if ( (vend_id & 0x2000ffff) == 0x2000a865 ) {
+ /* special volume setting for the Yamaha... */
+ outb(tmp_d.conf_base, 7 /* volume, left */);
+ outb(tmp_d.conf_base+1, 0 );
+ outb(tmp_d.conf_base, 8 /* volume, right */);
+ outb(tmp_d.conf_base+1, 0 );
+ }
dev->id_drq = d.drq[0] ; /* primary dma */
dev->id_irq = (1 << d.irq[0] ) ;
dev->id_intr = pcmintr ;
diff --git a/sys/dev/pcm/isa/sb.c b/sys/dev/pcm/isa/sb.c
index d4825c1..09440e1 100644
--- a/sys/dev/pcm/isa/sb.c
+++ b/sys/dev/pcm/isa/sb.c
@@ -174,6 +174,9 @@ sb_dsp_open(dev_t dev, int flags, int mode, struct proc * p)
d->rsel.si_pid = 0;
d->rsel.si_flags = 0;
+ d->dbuf_out.total = d->dbuf_out.prev_total = 0 ;
+ d->dbuf_in.total = d->dbuf_in.prev_total = 0 ;
+
d->flags = 0 ;
d->bd_flags &= ~BD_F_HISPEED ;
@@ -273,25 +276,36 @@ again:
*/
reason = 0 ;
if ( c & 1 ) { /* 8-bit dma */
- if (d->dma1 < 4)
+ if (d->dbuf_out.chan < 4)
reason |= 1;
- if (d->dma2 < 4)
+ if (d->dbuf_in.chan < 4)
reason |= 2;
}
if ( c & 2 ) { /* 16-bit dma */
- if (d->dma1 >= 4)
+ if (d->dbuf_out.chan >= 4)
reason |= 1;
- if (d->dma2 >= 4)
+ if (d->dbuf_in.chan >= 4)
reason |= 2;
}
}
/* XXX previous location of ack... */
DEB(printf("sbintr, flags 0x%08lx reason %d\n", d->flags, reason));
- if ( d->dbuf_out.dl && (reason & 1) )
+ if ( reason & 1 ) { /* possibly a write interrupt */
+ if ( d->dbuf_out.dl )
dsp_wrintr(d);
- if ( d->dbuf_in.dl && (reason & 2) )
+ else {
+ if (d->bd_flags & BD_F_SB16)
+ printf("WARNING: wrintr but write DMA inactive!\n");
+ }
+ }
+ if ( reason & 2 ) {
+ if ( d->dbuf_in.dl )
dsp_rdintr(d);
-
+ else {
+ if (d->bd_flags & BD_F_SB16)
+ printf("WARNING: rdintr but read DMA inactive!\n");
+ }
+ }
if ( c & 2 )
inb(DSP_DATA_AVL16); /* 16-bit int ack */
if (c & 1)
@@ -307,7 +321,7 @@ again:
/*
* device-specific function called back from the dma module.
* The reason of the callback is the second argument.
- * NOTE: during operations, some ioctl can be done to change
+ * NOTE: during operations, some ioctl can be called to change
* settings (e.g. speed, channels, format), and the default
* ioctl handler will just record the change and set the
* flag SND_F_INIT. The callback routine is in charge of applying
@@ -319,7 +333,8 @@ static int
sb_callback(snddev_info *d, int reason)
{
int rd = reason & SND_CB_RD ;
- int l = (rd) ? d->dbuf_in.dl : d->dbuf_out.dl ;
+ snd_dbuf *b = (rd) ? & (d->dbuf_in) : & (d->dbuf_out) ;
+ int l = b->dl ;
switch (reason & SND_CB_REASON_MASK) {
case SND_CB_INIT : /* called with int enabled and no pending io */
@@ -336,6 +351,8 @@ sb_callback(snddev_info *d, int reason)
case SND_CB_START : /* called with int disabled */
if (d->bd_flags & BD_F_SB16) {
+ u_char c, c1 ;
+
/* the SB16 can do full duplex using one 16-bit channel
* and one 8-bit channel. It needs to be programmed to
* use split format though.
@@ -347,63 +364,80 @@ sb_callback(snddev_info *d, int reason)
int swap = 1 ; /* default... */
if (rd) {
- if (d->flags & SND_F_WRITING || d->dbuf_out.dl)
+ /* need not to swap if channel is already correct */
+ if ( d->rec_fmt == AFMT_S16_LE && b->chan > 4 )
swap = 0;
- if (d->rec_fmt == AFMT_S16_LE && d->dma2 >=4)
+ if ( d->rec_fmt != AFMT_S16_LE && b->chan < 4 )
swap = 0;
- if (d->rec_fmt != AFMT_S16_LE && d->dma2 <4)
+ 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 {
- if (d->flags & SND_F_READING || d->dbuf_in.dl)
+ /* need not to swap if channel is already correct */
+ if ( d->play_fmt == AFMT_S16_LE && b->chan > 4 )
swap = 0;
- if (d->play_fmt == AFMT_S16_LE && d->dma1 >=4)
+ if ( d->play_fmt != AFMT_S16_LE && b->chan < 4 )
swap = 0;
- if (d->play_fmt != AFMT_S16_LE && d->dma1 <4)
+ 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 (swap) {
- int c = d->dma2 ;
- d->dma2 = d->dma1;
- d->dma1 = c ;
+ 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->dma1, d->dma2));
- }
+ d->dbuf_out.chan, d->dbuf_in.chan));
}
- if (!rd)
- sb_cmd(d->io_base, DSP_CMD_SPKON);
- if (d->bd_flags & BD_F_SB16) {
- u_char c, c1 ;
-
- if (rd) {
- c = ((d->dma2 > 3) ? DSP_DMA16 : DSP_DMA8) |
- DSP_F16_AUTO |
- DSP_F16_FIFO_ON | DSP_F16_ADC ;
- c1 = (d->rec_fmt == AFMT_U8) ? 0 : DSP_F16_SIGNED ;
- if (d->rec_fmt == AFMT_MU_LAW) c1 = 0 ;
- if (d->rec_fmt == AFMT_S16_LE)
+ /*
+ * 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
+ * is assigned. This means that if the application
+ * tries to use a bad format, the sound will not be nice.
+ */
+ if ( b->chan > 4 ) {
+ c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA16 ;
+ c1 = DSP_F16_SIGNED ;
l /= 2 ;
} else {
- c = ((d->dma1 > 3) ? DSP_DMA16 : DSP_DMA8) |
- DSP_F16_AUTO |
- DSP_F16_FIFO_ON | DSP_F16_DAC ;
- c1 = (d->play_fmt == AFMT_U8) ? 0 : DSP_F16_SIGNED ;
- if (d->play_fmt == AFMT_MU_LAW) c1 = 0 ;
- if (d->play_fmt == AFMT_S16_LE)
- l /= 2 ;
+ c = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_DMA8 ;
+ c1 = 0 ;
}
-
+ c |= (rd) ? DSP_F16_ADC : DSP_F16_DAC ;
if (d->flags & SND_F_STEREO)
c1 |= DSP_F16_STEREO ;
sb_cmd(d->io_base, c );
sb_cmd3(d->io_base, c1 , l - 1) ;
- } else {
- /* code for the SB2 and SB3 */
+ } 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 */
u_char c ;
+ if (!rd)
+ sb_cmd(d->io_base, DSP_CMD_SPKON);
+ /* code for the SB2 and SB3 */
if (d->bd_flags & BD_F_HISPEED)
c = (rd) ? DSP_CMD_HSADC_AUTO : DSP_CMD_HSDAC_AUTO ;
else
@@ -416,18 +450,17 @@ sb_callback(snddev_info *d, int reason)
case SND_CB_STOP :
{
int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */
- if (d->bd_flags & BD_F_SB16) {
- if ( (rd && d->dbuf_in.chan>4) || (!rd && d->dbuf_out.chan>4) )
+ if ( d->bd_flags & BD_F_SB16 && b->chan > 4 )
cmd = DSP_CMD_DMAPAUSE_16 ;
- }
if (d->bd_flags & BD_F_HISPEED) {
sb_reset_dsp(d->io_base);
d->flags |= SND_F_INIT ;
} else {
sb_cmd(d->io_base, cmd); /* pause dma. */
/*
- * This seems to have the side effect of blocking the other
- * side as well so I have to re-enable it :(
+ * The above seems to have the undocumented side effect of
+ * blocking the other side as well. If the other
+ * channel was active (SB16) I have to re-enable it :(
*/
if ( (rd && d->dbuf_out.dl) ||
(!rd && d->dbuf_in.dl) )
@@ -508,7 +541,7 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev)
break ;
case 2 :
- d->dma2 = d->dma1 ; /* half duplex */
+ d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
d->bd_flags |= BD_F_DUP_MIDI ;
if (d->bd_id == 0x200)
@@ -536,11 +569,11 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev)
else
sb_setmixer(io_base, IRQ_NR, x);
- sb_setmixer(io_base, DMA_NR, (1 << d->dma1) | (1 << d->dma2));
+ sb_setmixer(io_base, DMA_NR, (1 << d->dbuf_out.chan) | (1 << d->dbuf_in.chan));
break ;
case 3 :
- d->dma2 = d->dma1 ; /* half duplex */
+ d->dbuf_in.chan = d->dbuf_out.chan ; /* half duplex */
fmt = "SoundBlaster Pro %d.%d";
d->bd_flags |= BD_F_DUP_MIDI ;
d->bd_flags &= ~BD_F_MIX_MASK ;
@@ -562,24 +595,48 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev)
ess_minor = inb(DSP_READ);
break;
}
- }
+ } else
+ DELAY(20);
}
if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
- printf("Hmm... Could this be an ESS488 based card (rev %d)\n",
- ess_minor & 0x0f);
- else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
- printf("Hmm... Could this be an ESS688 based card (rev %d)\n",
- ess_minor & 0x0f);
- }
-
- if (d->bd_flags & BD_F_JAZZ16) {
- if (d->bd_flags & BD_F_JAZZ16_2)
- fmt = "SoundMan Wave %d.%d";
+ 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
- fmt = "MV Jazz16 %d.%d";
- d->audio_fmt |= AFMT_S16_LE; /* 16 bits */
+ 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 );
+ }
+ }
+ }
}
+
}
sprintf(d->name, fmt, (d->bd_id >> 8) &0xff, d->bd_id & 0xff);
@@ -714,6 +771,9 @@ dsp_speed(snddev_info *d)
u_long flags;
int max_speed = 44100, speed = d->play_speed ;
+ /*
+ * special code for the SB16
+ */
if (d->bd_flags & BD_F_SB16) {
RANGE (speed, 5000, 45000);
d->play_speed = d->rec_speed = speed ;
@@ -725,6 +785,26 @@ dsp_speed(snddev_info *d)
sb_cmd(d->io_base, d->rec_speed & 0xff );
return speed ;
}
+
+ /*
+ * special code for the ESS ...
+ */
+ if (d->bd_flags & BD_F_ESS) {
+ int t;
+ RANGE (speed, 4000, 48000);
+ if (speed > 22000) {
+ t = (795500 + speed / 2) / speed;
+ speed = (795500 + t / 2) / t ;
+ t = ( 256 - (795500 + speed / 2) / speed ) | 0x80 ;
+ } else {
+ t = (397700 + speed / 2) / speed;
+ speed = (397700 + t / 2) / t ;
+ t = 128 - (397700 + speed / 2) / speed ;
+ }
+ sb_cmd2(d->io_base, 0xa1, t); /* set time constant */
+ return speed ;
+ }
+
/*
* only some models can do stereo, and only if not
* simultaneously using midi.
@@ -779,7 +859,7 @@ dsp_speed(snddev_info *d)
d->bd_flags |= BD_F_HISPEED ;
flags = spltty();
- sb_cmd2(d->io_base, DSP_CMD_TCONST, tconst);
+ sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
splx(flags);
tmp = 65536 - (tconst << 8);
@@ -791,7 +871,7 @@ dsp_speed(snddev_info *d)
tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
flags = spltty();
- sb_cmd2(d->io_base, DSP_CMD_TCONST, tconst);
+ sb_cmd2(d->io_base, 0x40, tconst); /* set time constant */
splx(flags);
tmp = 256 - tconst;
@@ -1044,7 +1124,7 @@ sb16pnp_probe(u_long csn, u_long vend_id)
* the vendor id, so I have just masked it for the time being...
* Reported values are:
* SB16 Value PnP: 0x2b008c0e
- * SB AWE64 PnP: 0x39008c0e 0x9d008c0e 0xc3008c0e
+ * SB AWExx PnP: 0x39008c0e 0x9d008c0e 0xc3008c0e
*/
if ( (vend_id & 0xffffff) == (0x9d008c0e & 0xffffff) )
s = "SB16 PnP";
diff --git a/sys/dev/pcm/isa/sb.h b/sys/dev/pcm/isa/sb.h
index d7a24d5..1735c14 100644
--- a/sys/dev/pcm/isa/sb.h
+++ b/sys/dev/pcm/isa/sb.h
@@ -137,6 +137,7 @@ extern int sbc_major, sbc_minor ;
#define BD_F_SB16 0x0100 /* this is a SB16 */
#define BD_F_NOREC 0x0200 /* recording not supported on this board */
#define BD_F_MIDIBUSY 0x0400 /* midi busy */
+#define BD_F_ESS 0x0800 /* this is an ESS chip */
/*
OpenPOWER on IntegriCloud