* add a non-reset device- will not reset the channel on open. you

will have to mknod yourself for now.
* don't eat the first write()
* partial rvplayer fix- don't panic on unaligned writes unless our
  feeder chain requires them for downconversion.  a fuller fix is
  on the way.
This commit is contained in:
Cameron Grant 1999-09-28 21:43:35 +00:00
parent 89c57f2d02
commit 5b78a73443
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51769
14 changed files with 106 additions and 52 deletions

View file

@ -36,7 +36,6 @@
#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
#define CANCHANGE(c) (!(c)->buffer.dl)
static int chn_reinit(pcm_channel *c);
static void chn_stintr(pcm_channel *c);
/*
* SOUND OUTPUT
@ -256,7 +255,7 @@ chn_wrintr(pcm_channel *c)
int
chn_write(pcm_channel *c, struct uio *buf)
{
int l, w, timeout, ret = 0;
int a, l, w, timeout, ret = 0;
long s;
snd_dbuf *b = &c->buffer;
@ -267,6 +266,7 @@ chn_write(pcm_channel *c, struct uio *buf)
tsleep(&s, PZERO, "pcmwrW", hz);
return EBUSY;
}
a = (1 << c->align) - 1;
c->flags |= CHN_F_WRITING;
while (buf->uio_resid > 0) {
s = spltty();
@ -282,7 +282,9 @@ chn_write(pcm_channel *c, struct uio *buf)
continue;
}
/* ensure we always have a whole number of samples */
l = min(b->fl, b->bufsize - b->fp) & DMA_ALIGN_MASK;
l = min(b->fl, b->bufsize - b->fp);
if (l & a) panic("unaligned write %d, %d", l, a + 1);
l &= ~a;
w = c->feeder->feed(c->feeder, b->buf + b->fp, l, buf);
if (w == 0) panic("no feed");
s = spltty();
@ -430,8 +432,8 @@ chn_read(pcm_channel *c, struct uio *buf)
void
chn_intr(pcm_channel *c)
{
if (!c->buffer.dl) chn_reinit(c);
if (c->direction == PCMDIR_PLAY) chn_wrintr(c); else chn_rdintr(c);
/* if (!c->buffer.dl) chn_reinit(c);
*/ if (c->direction == PCMDIR_PLAY) chn_wrintr(c); else chn_rdintr(c);
}
static void
@ -627,7 +629,7 @@ chn_reset(pcm_channel *c)
return 0;
}
static int
int
chn_reinit(pcm_channel *c)
{
if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) {

View file

@ -26,6 +26,7 @@
* $FreeBSD$
*/
int chn_reinit(pcm_channel *c);
int chn_write(pcm_channel *c, struct uio *buf);
int chn_read(pcm_channel *c, struct uio *buf);
int chn_sync(pcm_channel *c, int threshold);

View file

@ -79,6 +79,7 @@ typedef int (pcmfeed_feed_t)(pcm_feeder *feeder, u_int8_t *buffer, u_int32_t cou
struct _pcm_feeder {
char name[16];
int align;
pcmfeed_init_t *init;
pcmfeed_free_t *free;
pcmfeed_feed_t *feed;
@ -110,6 +111,7 @@ struct _pcm_channel {
pcmchan_getptr_t *getptr;
pcmchan_getcaps_t *getcaps;
pcm_feeder *feeder;
u_int32_t align;
int volume;
u_int32_t speed;

View file

@ -115,6 +115,10 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
fmt = AFMT_MU_LAW;
break;
case SND_DEV_NORESET:
fmt = 0;
break;
default:
return ENXIO;
}
@ -122,19 +126,23 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
if (rdch) {
chn_reset(rdch);
if (oflags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO;
if (fmt) {
rdch->volume = (100 << 8) | 100;
rdch->format = fmt;
rdch->speed = DSP_DEFAULT_SPEED;
rdch->blocksize = 2048;
}
}
if (wrch) {
chn_reset(wrch);
if (oflags & O_NONBLOCK) wrch->flags |= CHN_F_NBIO;
if (fmt) {
wrch->volume = (100 << 8) | 100;
wrch->format = fmt;
wrch->speed = DSP_DEFAULT_SPEED;
wrch->blocksize = 2048;
}
}
return 0;
}
@ -168,7 +176,10 @@ dsp_read(snddev_info *d, int chan, struct uio *buf, int flag)
if (!rdch || !(rdch->flags & CHN_F_BUSY))
panic("dsp_read: non%s channel", rdch? "busy" : "existant");
if (rdch->flags & CHN_F_MAPPED) return EINVAL;
if (!(rdch->flags & CHN_F_RUNNING)) rdch->flags |= CHN_F_RUNNING;
if (!(rdch->flags & CHN_F_RUNNING)) {
rdch->flags |= CHN_F_RUNNING;
chn_reinit(rdch);
}
return chn_read(rdch, buf);
}
@ -183,7 +194,10 @@ dsp_write(snddev_info *d, int chan, struct uio *buf, int flag)
if (!wrch || !(wrch->flags & CHN_F_BUSY))
panic("dsp_write: non%s channel", wrch? "busy" : "existant");
if (wrch->flags & CHN_F_MAPPED) return EINVAL;
if (!(wrch->flags & CHN_F_RUNNING)) wrch->flags |= CHN_F_RUNNING;
if (!(wrch->flags & CHN_F_RUNNING)) {
wrch->flags |= CHN_F_RUNNING;
chn_reinit(wrch);
}
return chn_write(wrch, buf);
}

View file

@ -120,7 +120,7 @@ feed_root(pcm_feeder *feeder, u_int8_t *buffer, u_int32_t count, struct uio *str
if (!tmp) panic("feed_root: uiomove didn't");
return tmp;
}
pcm_feeder feeder_root = { "root", NULL, NULL, feed_root };
pcm_feeder feeder_root = { "root", 0, NULL, NULL, feed_root };
/*****************************************************************************/
@ -137,7 +137,7 @@ feed_8to16(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
}
return k * 2;
}
static pcm_feeder feeder_8to16 = { "8to16", NULL, NULL, feed_8to16 };
static pcm_feeder feeder_8to16 = { "8to16", 0, NULL, NULL, feed_8to16 };
/*****************************************************************************/
@ -169,7 +169,7 @@ feed_16to8le(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_16to8le =
{ "16to8le", feed_16to8_init, feed_16to8_free, feed_16to8le };
{ "16to8le", 1, feed_16to8_init, feed_16to8_free, feed_16to8le };
/*****************************************************************************/
@ -187,7 +187,7 @@ feed_monotostereo8(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stre
return k * 2;
}
static pcm_feeder feeder_monotostereo8 =
{ "monotostereo8", NULL, NULL, feed_monotostereo8 };
{ "monotostereo8", 0, NULL, NULL, feed_monotostereo8 };
/*****************************************************************************/
@ -219,7 +219,7 @@ feed_stereotomono8(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stre
return i;
}
static pcm_feeder feeder_stereotomono8 =
{ "stereotomono8", feed_stereotomono8_init, feed_stereotomono8_free,
{ "stereotomono8", 1, feed_stereotomono8_init, feed_stereotomono8_free,
feed_stereotomono8 };
/*****************************************************************************/
@ -237,7 +237,7 @@ feed_endian(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
}
return i;
}
static pcm_feeder feeder_endian = { "endian", NULL, NULL, feed_endian };
static pcm_feeder feeder_endian = { "endian", -1, NULL, NULL, feed_endian };
/*****************************************************************************/
@ -253,9 +253,9 @@ feed_sign(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_sign8 =
{ "sign8", NULL, NULL, feed_sign, (void *)1 };
{ "sign8", 0, NULL, NULL, feed_sign, (void *)1 };
static pcm_feeder feeder_sign16 =
{ "sign16", NULL, NULL, feed_sign, (void *)2 };
{ "sign16", -1, NULL, NULL, feed_sign, (void *)2 };
/*****************************************************************************/
@ -270,9 +270,9 @@ feed_table(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_ulawtou8 =
{ "ulawtou8", NULL, NULL, feed_table, ulaw_to_u8 };
{ "ulawtou8", 0, NULL, NULL, feed_table, ulaw_to_u8 };
static pcm_feeder feeder_u8toulaw =
{ "u8toulaw", NULL, NULL, feed_table, u8_to_ulaw };
{ "u8toulaw", 0, NULL, NULL, feed_table, u8_to_ulaw };
/*****************************************************************************/
@ -358,6 +358,7 @@ chn_feedchain(pcm_channel *c)
struct fmtcvt *e;
while (chn_removefeeder(c) != -1);
c->align = 0;
if ((c->format & chn_getcaps(c)->formats) == c->format)
return c->format;
getspec(c->format, &s);
@ -389,6 +390,8 @@ chn_addfeeder(pcm_channel *c, pcm_feeder *f)
n->source = c->feeder;
c->feeder = n;
if (n->init) n->init(n);
if (n->align > 0) c->align += n->align;
else if (n->align < 0 && c->align < -n->align) c->align -= n->align;
return 0;
}

View file

@ -84,6 +84,9 @@ currently minor = (channel << 8) + (unit << 4) + dev
/dev/pcmX/status
/dev/pcmX/mixer
[etc.]
currently:
minor = (channel << 8) + (unit << 4) + dev
*/
#define PCMMINOR(x) (minor(x))
@ -235,6 +238,7 @@ sndopen(dev_t i_dev, int flags, int mode, struct proc *p)
case SND_DEV_AUDIO:
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_NORESET:
return d? dsp_open(d, chan, flags, dev) : ENXIO;
default:

View file

@ -142,6 +142,7 @@ int fkchan_setup(pcm_channel *c);
#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC /* ? */
#define SND_DEV_NORESET 10
#define DSP_DEFAULT_SPEED 8000

View file

@ -36,7 +36,6 @@
#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
#define CANCHANGE(c) (!(c)->buffer.dl)
static int chn_reinit(pcm_channel *c);
static void chn_stintr(pcm_channel *c);
/*
* SOUND OUTPUT
@ -256,7 +255,7 @@ chn_wrintr(pcm_channel *c)
int
chn_write(pcm_channel *c, struct uio *buf)
{
int l, w, timeout, ret = 0;
int a, l, w, timeout, ret = 0;
long s;
snd_dbuf *b = &c->buffer;
@ -267,6 +266,7 @@ chn_write(pcm_channel *c, struct uio *buf)
tsleep(&s, PZERO, "pcmwrW", hz);
return EBUSY;
}
a = (1 << c->align) - 1;
c->flags |= CHN_F_WRITING;
while (buf->uio_resid > 0) {
s = spltty();
@ -282,7 +282,9 @@ chn_write(pcm_channel *c, struct uio *buf)
continue;
}
/* ensure we always have a whole number of samples */
l = min(b->fl, b->bufsize - b->fp) & DMA_ALIGN_MASK;
l = min(b->fl, b->bufsize - b->fp);
if (l & a) panic("unaligned write %d, %d", l, a + 1);
l &= ~a;
w = c->feeder->feed(c->feeder, b->buf + b->fp, l, buf);
if (w == 0) panic("no feed");
s = spltty();
@ -430,8 +432,8 @@ chn_read(pcm_channel *c, struct uio *buf)
void
chn_intr(pcm_channel *c)
{
if (!c->buffer.dl) chn_reinit(c);
if (c->direction == PCMDIR_PLAY) chn_wrintr(c); else chn_rdintr(c);
/* if (!c->buffer.dl) chn_reinit(c);
*/ if (c->direction == PCMDIR_PLAY) chn_wrintr(c); else chn_rdintr(c);
}
static void
@ -627,7 +629,7 @@ chn_reset(pcm_channel *c)
return 0;
}
static int
int
chn_reinit(pcm_channel *c)
{
if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) {

View file

@ -26,6 +26,7 @@
* $FreeBSD$
*/
int chn_reinit(pcm_channel *c);
int chn_write(pcm_channel *c, struct uio *buf);
int chn_read(pcm_channel *c, struct uio *buf);
int chn_sync(pcm_channel *c, int threshold);

View file

@ -79,6 +79,7 @@ typedef int (pcmfeed_feed_t)(pcm_feeder *feeder, u_int8_t *buffer, u_int32_t cou
struct _pcm_feeder {
char name[16];
int align;
pcmfeed_init_t *init;
pcmfeed_free_t *free;
pcmfeed_feed_t *feed;
@ -110,6 +111,7 @@ struct _pcm_channel {
pcmchan_getptr_t *getptr;
pcmchan_getcaps_t *getcaps;
pcm_feeder *feeder;
u_int32_t align;
int volume;
u_int32_t speed;

View file

@ -115,6 +115,10 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
fmt = AFMT_MU_LAW;
break;
case SND_DEV_NORESET:
fmt = 0;
break;
default:
return ENXIO;
}
@ -122,19 +126,23 @@ dsp_open(snddev_info *d, int chan, int oflags, int devtype)
if (rdch) {
chn_reset(rdch);
if (oflags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO;
if (fmt) {
rdch->volume = (100 << 8) | 100;
rdch->format = fmt;
rdch->speed = DSP_DEFAULT_SPEED;
rdch->blocksize = 2048;
}
}
if (wrch) {
chn_reset(wrch);
if (oflags & O_NONBLOCK) wrch->flags |= CHN_F_NBIO;
if (fmt) {
wrch->volume = (100 << 8) | 100;
wrch->format = fmt;
wrch->speed = DSP_DEFAULT_SPEED;
wrch->blocksize = 2048;
}
}
return 0;
}
@ -168,7 +176,10 @@ dsp_read(snddev_info *d, int chan, struct uio *buf, int flag)
if (!rdch || !(rdch->flags & CHN_F_BUSY))
panic("dsp_read: non%s channel", rdch? "busy" : "existant");
if (rdch->flags & CHN_F_MAPPED) return EINVAL;
if (!(rdch->flags & CHN_F_RUNNING)) rdch->flags |= CHN_F_RUNNING;
if (!(rdch->flags & CHN_F_RUNNING)) {
rdch->flags |= CHN_F_RUNNING;
chn_reinit(rdch);
}
return chn_read(rdch, buf);
}
@ -183,7 +194,10 @@ dsp_write(snddev_info *d, int chan, struct uio *buf, int flag)
if (!wrch || !(wrch->flags & CHN_F_BUSY))
panic("dsp_write: non%s channel", wrch? "busy" : "existant");
if (wrch->flags & CHN_F_MAPPED) return EINVAL;
if (!(wrch->flags & CHN_F_RUNNING)) wrch->flags |= CHN_F_RUNNING;
if (!(wrch->flags & CHN_F_RUNNING)) {
wrch->flags |= CHN_F_RUNNING;
chn_reinit(wrch);
}
return chn_write(wrch, buf);
}

View file

@ -120,7 +120,7 @@ feed_root(pcm_feeder *feeder, u_int8_t *buffer, u_int32_t count, struct uio *str
if (!tmp) panic("feed_root: uiomove didn't");
return tmp;
}
pcm_feeder feeder_root = { "root", NULL, NULL, feed_root };
pcm_feeder feeder_root = { "root", 0, NULL, NULL, feed_root };
/*****************************************************************************/
@ -137,7 +137,7 @@ feed_8to16(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
}
return k * 2;
}
static pcm_feeder feeder_8to16 = { "8to16", NULL, NULL, feed_8to16 };
static pcm_feeder feeder_8to16 = { "8to16", 0, NULL, NULL, feed_8to16 };
/*****************************************************************************/
@ -169,7 +169,7 @@ feed_16to8le(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_16to8le =
{ "16to8le", feed_16to8_init, feed_16to8_free, feed_16to8le };
{ "16to8le", 1, feed_16to8_init, feed_16to8_free, feed_16to8le };
/*****************************************************************************/
@ -187,7 +187,7 @@ feed_monotostereo8(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stre
return k * 2;
}
static pcm_feeder feeder_monotostereo8 =
{ "monotostereo8", NULL, NULL, feed_monotostereo8 };
{ "monotostereo8", 0, NULL, NULL, feed_monotostereo8 };
/*****************************************************************************/
@ -219,7 +219,7 @@ feed_stereotomono8(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stre
return i;
}
static pcm_feeder feeder_stereotomono8 =
{ "stereotomono8", feed_stereotomono8_init, feed_stereotomono8_free,
{ "stereotomono8", 1, feed_stereotomono8_init, feed_stereotomono8_free,
feed_stereotomono8 };
/*****************************************************************************/
@ -237,7 +237,7 @@ feed_endian(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
}
return i;
}
static pcm_feeder feeder_endian = { "endian", NULL, NULL, feed_endian };
static pcm_feeder feeder_endian = { "endian", -1, NULL, NULL, feed_endian };
/*****************************************************************************/
@ -253,9 +253,9 @@ feed_sign(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_sign8 =
{ "sign8", NULL, NULL, feed_sign, (void *)1 };
{ "sign8", 0, NULL, NULL, feed_sign, (void *)1 };
static pcm_feeder feeder_sign16 =
{ "sign16", NULL, NULL, feed_sign, (void *)2 };
{ "sign16", -1, NULL, NULL, feed_sign, (void *)2 };
/*****************************************************************************/
@ -270,9 +270,9 @@ feed_table(pcm_feeder *f, u_int8_t *b, u_int32_t count, struct uio *stream)
return i;
}
static pcm_feeder feeder_ulawtou8 =
{ "ulawtou8", NULL, NULL, feed_table, ulaw_to_u8 };
{ "ulawtou8", 0, NULL, NULL, feed_table, ulaw_to_u8 };
static pcm_feeder feeder_u8toulaw =
{ "u8toulaw", NULL, NULL, feed_table, u8_to_ulaw };
{ "u8toulaw", 0, NULL, NULL, feed_table, u8_to_ulaw };
/*****************************************************************************/
@ -358,6 +358,7 @@ chn_feedchain(pcm_channel *c)
struct fmtcvt *e;
while (chn_removefeeder(c) != -1);
c->align = 0;
if ((c->format & chn_getcaps(c)->formats) == c->format)
return c->format;
getspec(c->format, &s);
@ -389,6 +390,8 @@ chn_addfeeder(pcm_channel *c, pcm_feeder *f)
n->source = c->feeder;
c->feeder = n;
if (n->init) n->init(n);
if (n->align > 0) c->align += n->align;
else if (n->align < 0 && c->align < -n->align) c->align -= n->align;
return 0;
}

View file

@ -84,6 +84,9 @@ currently minor = (channel << 8) + (unit << 4) + dev
/dev/pcmX/status
/dev/pcmX/mixer
[etc.]
currently:
minor = (channel << 8) + (unit << 4) + dev
*/
#define PCMMINOR(x) (minor(x))
@ -235,6 +238,7 @@ sndopen(dev_t i_dev, int flags, int mode, struct proc *p)
case SND_DEV_AUDIO:
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_NORESET:
return d? dsp_open(d, chan, flags, dev) : ENXIO;
default:

View file

@ -142,6 +142,7 @@ int fkchan_setup(pcm_channel *c);
#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC /* ? */
#define SND_DEV_NORESET 10
#define DSP_DEFAULT_SPEED 8000