summaryrefslogtreecommitdiffstats
path: root/sys/dev/pcm
diff options
context:
space:
mode:
authorscrappy <scrappy@FreeBSD.org>1998-02-17 14:17:13 +0000
committerscrappy <scrappy@FreeBSD.org>1998-02-17 14:17:13 +0000
commitb171ac7ee4cbb0dbbb40690811b00336ec7146d0 (patch)
treec67c48140d38cbc8a51b5f1b5a5b41309a6f6f37 /sys/dev/pcm
parent6777765e4373946684584119df163e71de8ed128 (diff)
downloadFreeBSD-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/pcm')
-rw-r--r--sys/dev/pcm/isa/mss.c66
-rw-r--r--sys/dev/pcm/isa/sb.c297
-rw-r--r--sys/dev/pcm/isa/sb.h9
3 files changed, 211 insertions, 161 deletions
diff --git a/sys/dev/pcm/isa/mss.c b/sys/dev/pcm/isa/mss.c
index a6bf624..26eaee5 100644
--- a/sys/dev/pcm/isa/mss.c
+++ b/sys/dev/pcm/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/pcm/isa/sb.c b/sys/dev/pcm/isa/sb.c
index 09440e1..3d75aea 100644
--- a/sys/dev/pcm/isa/sb.c
+++ b/sys/dev/pcm/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/pcm/isa/sb.h b/sys/dev/pcm/isa/sb.h
index 1735c14..0bd4210 100644
--- a/sys/dev/pcm/isa/sb.h
+++ b/sys/dev/pcm/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
OpenPOWER on IntegriCloud