Skip site navigation (1)Skip section navigation (2)
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>