Date: Mon, 10 Feb 1997 21:58:54 -0800 From: Steven Wallace <swallace@ece.uci.edu> To: current@freebsd.org Cc: bugs@freebsd.org Subject: Important bug fix for sound driver Message-ID: <199702110558.VAA23924@newport.ece.uci.edu>
next in thread | raw e-mail | index | archive | help
In compiling a Linux program for FreeBSD, I have discovered a bug in
FreeBSD's version of the sound driver.
The problem has to do with the SNDCTL_DSP_GETOSPACE ioctl.
It is suppose to return the available buffer space to the structure
audio_buf_info.
When you first open the /dev/dsp device and check the buffer, it
reports there is 0 bytes available when there is nothing in it.
If you write a partial fragment,
and then quickly check the buffer, now there appears to be some space
left. The ioctl is only reporting partially used fragments and not
whole fragments.
I therefore used the code from Linux 1.3.20's dmabuf.c to correct
the problem (It has the same BSD-style copyright).
Here is the diff output.
If there is no objections, this should be commited for 2.2R.
Steven
*** i386/isa/sound/dmabuf.c.orig Tue Sep 10 03:04:50 1996
--- i386/isa/sound/dmabuf.c Mon Feb 10 21:37:21 1997
***************
*** 44,49 ****
--- 44,53 ----
* Needs dynamic run-time alloction.
*/
+ static int space_in_queue (int);
+ static void reorganize_buffers (int);
+ static void dma_init_buffers (int);
+
static void
reorganize_buffers (int dev)
{
***************
*** 510,523 ****
case SNDCTL_DSP_GETOSPACE:
if (!local)
return RET_ERROR (EINVAL);
! {
! audio_buf_info *info = (audio_buf_info *) arg;
! info->fragments = dmap->qlen;
! info->fragsize = dmap->fragment_size;
! info->bytes = dmap->qlen * dmap->fragment_size;
! }
return 0;
default:
--- 514,561 ----
case SNDCTL_DSP_GETOSPACE:
if (!local)
return RET_ERROR (EINVAL);
+ else
+ {
+ audio_buf_info *info = (audio_buf_info *) arg;
! if (!(dmap->flags & DMA_ALLOC_DONE))
! reorganize_buffers (dev);
! info->fragstotal = dmap->nbufs;
!
! if (cmd == SNDCTL_DSP_GETISPACE)
! info->fragments = dmap->qlen;
! else
! {
! if (!space_in_queue (dev))
! info->fragments = 0;
! else
! {
! info->fragments = dmap->nbufs - dmap->qlen;
! if (audio_devs[dev]->local_qlen)
! {
! int tmp = audio_devs[dev]->local_qlen (dev);
!
! if (tmp & info->fragments)
! tmp--; /*
! * This buffer has been counted twice
! */
! info->fragments -= tmp;
! }
! }
! }
!
! if (info->fragments < 0)
! info->fragments = 0;
! else if (info->fragments > dmap->nbufs)
! info->fragments = dmap->nbufs;
!
! info->fragsize = dmap->fragment_size;
! info->bytes = info->fragments * dmap->fragment_size;
!
! if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
! info->bytes -= dmap->counts[dmap->qhead];
! }
return 0;
default:
*** i386/include/soundcard.h.orig Thu Nov 21 16:23:40 1996
--- i386/include/soundcard.h Mon Feb 10 21:37:07 1997
***************
*** 577,582 ****
--- 577,583 ----
*/
typedef struct audio_buf_info {
int fragments; /* # of available fragments (partially usend ones not counted) */
+ int fragstotal; /* Total # of fragments allocated */
int fragsize; /* Size of a fragment in bytes */
int bytes; /* Available space in bytes (includes partially used fragments) */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702110558.VAA23924>
