NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/39204



The following reply was made to PR kern/39204; it has been noted by GNATS.

From: Nat Sloss <nathanialsloss%yahoo.com.au@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/39204
Date: Fri, 11 May 2012 23:57:39 +1000

 Hi,
 
 I think I fixed the problem.  I had broken audio when booted from and saving 
 to harddrive, more so when booted from and saving to usb, and it was even 
 more broken in emulated in qemu. 
 
 What fixed it was adding a delay before the call to start output in pad_read.  
 The delay would work for one of the scenarios above but not for the others.
 
 More delay was needed for usb and qemu.  And then I discovered that the writer 
 was only scheduled at the end of audio pint.  So calling start output in 
 quick succession resulted in silence being copied.
 
 I also found that audio would skip on small reads less than PADBLKSIZE and 
 this was because of the second call to start output outside of the while loop 
 in pad_read as it was no longer necessary as there was a delay ensuring that 
 data was in the stream.
 
 So after attempting many different things I came up with this patch:
        
 --- pad.c.orig  2012-01-27 16:58:34.000000000 +1100
 +++ pad.c       2012-05-11 23:35:22.000000000 +1000
 @@ -54,6 +54,7 @@
  #define PADUNIT(x)     minor(x)
 
  extern struct cfdriver pad_cd;
 +extern struct cfdriver audio_cd;
 
  typedef struct pad_block {
         uint8_t         *pb_ptr;
 @@ -333,14 +334,21 @@
  {
         pad_softc_t *sc;
         pad_block_t pb;
 +       struct audio_softc *ac;
         void (*intr)(void *);
         void *intrarg;
 -       int err;
 +       int err, i, used;
 
         sc = device_lookup_private(&pad_cd, PADUNIT(dev));
         if (sc == NULL)
                 return ENXIO;
 
 +       for (i = 0; i < 256; i++) {
 +               ac = device_lookup_private(&audio_cd, i);
 +               if (ac->hw_hdl == sc)
 +                       break;
 +       }
 +
         err = 0;
 
         mutex_enter(&sc->sc_lock);
 @@ -356,6 +364,18 @@
                         continue;
                 }
 
 +               mutex_exit(&sc->sc_lock);
 +               i = 0;
 +               while ((used = audio_stream_get_used(ac->sc_pustream)) <
 +                   PAD_BLKSIZE * 2 && used < ac->sc_pr.usedlow) {
 +                       softint_schedule(ac->sc_sih_wr);
 +                       DELAY(250);
 +                       i++;
 +                       if (i > 8000)
 +                               break;
 +               }
 +               mutex_enter(&sc->sc_lock);
 +
                 if (intr) {
                         mutex_enter(&sc->sc_intr_lock);
                         (*intr)(intrarg);
 @@ -374,11 +394,6 @@
                 intrarg = sc->sc_intrarg;
         }
 
 -       if (intr) {
 -               mutex_enter(&sc->sc_intr_lock);
 -               (*intr)(intrarg);
 -               mutex_exit(&sc->sc_intr_lock);
 -       }
         mutex_exit(&sc->sc_lock);
 
         return err;
 
 
 This solves the problem for harddrive with 1 GHz cpu, usb and qemu situations. 
 
 If audio is not broken for you try using pad in an qemu emulation and you 
 will find with the un-patched version is gives broken audio, but with the 
 patch above it is fixed.
 
 Note:  This patch is my own work which I submit freely under the NetBSD 
 license.
 
 I hope this helps.
 
 Regards,
 
 Nat.
 


Home | Main Index | Thread Index | Old Index