Subject: kern/11178: wss audio full duplex operation does not work
To: None <gnats-bugs@gnats.netbsd.org>
From: None <weiss@uni-mainz.de>
List: netbsd-bugs
Date: 10/09/2000 12:22:11
>Number:         11178
>Category:       kern
>Synopsis:       wss audio full duplex operation does not work
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 09 12:22:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Juergen Weiss
>Release:        NetBSD-1.4.2
>Organization:
	Uni Mainz
>Environment:
	i386 and alpha, NetBSD 1.4.2 to current, wss audio device

>Description:
 wss audio driver does not allow full duplex operation. This failure was observed on
 i386 and alpha (multia) hardware. Reason for failure is, that there is only one 
 interrupt handler, not two for play and record.
>How-To-Repeat:
 use wss audio driver in full duplex mode
>Fix:

The following patch should work:

*** usr/src/sys/dev/isa/ad1848_isa.c	Mon Mar 22 15:54:01 1999
--- /usr/src/sys/dev/isa/ad1848_isa.c	Mon Jul 31 09:53:25 2000
***************
*** 458,464 ****
  	ad1848_isa_halt_output(isc);
  	ad1848_isa_halt_input(isc);
  
! 	isc->sc_intr = 0;
  
  	if (isc->sc_playdrq != -1)
  		isa_dmamap_destroy(isc->sc_ic, isc->sc_playdrq);
--- 458,464 ----
  	ad1848_isa_halt_output(isc);
  	ad1848_isa_halt_input(isc);
  
! 	isc->sc_pintr = isc->sc_rintr = 0;
  
  	if (isc->sc_playdrq != -1)
  		isa_dmamap_destroy(isc->sc_ic, isc->sc_playdrq);
***************
*** 487,494 ****
  	    DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_recrun = 1;
! 	isc->sc_intr = intr;
! 	isc->sc_arg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
--- 487,499 ----
  	    DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_recrun = 1;
! 	if (sc->mode == 2 && isc->sc_playdrq != isc->sc_recdrq) {
! 	    isc->sc_rintr = intr;
! 	    isc->sc_rarg = arg;
! 	} else {
! 	    isc->sc_pintr = intr;
! 	    isc->sc_parg = arg;
! 	}
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
***************
*** 524,531 ****
  	    DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_playrun = 1;
! 	isc->sc_intr = intr;
! 	isc->sc_arg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
--- 529,536 ----
  	    DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_playrun = 1;
! 	isc->sc_pintr = intr;
! 	isc->sc_parg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
***************
*** 589,603 ****
  	isc->sc_interrupts++;
  
  	/* Handle interrupt */
! 	if (isc->sc_intr && (status & INTERRUPT_STATUS)) {
! 		(*isc->sc_intr)(isc->sc_arg);
! 		retval = 1;
  	}
- 
- 	/* clear interrupt */
- 	if (status & INTERRUPT_STATUS)
- 		ADWRITE(sc, AD1848_STATUS, 0);
- 
  	return(retval);
  }
  
--- 594,619 ----
  	isc->sc_interrupts++;
  
  	/* Handle interrupt */
! 	if ((status & INTERRUPT_STATUS) != 0) {
! 	    if (sc->mode == 2 && isc->sc_playdrq != isc->sc_recdrq) {
! 		status = ad_read(sc, CS_IRQ_STATUS);
! 		if ((status & CS_IRQ_PI) && isc->sc_pintr) {
! 		    (*isc->sc_pintr)(isc->sc_parg);
! 		    retval = 1;
! 		}
! 		if ((status & CS_IRQ_CI) && isc->sc_rintr) {
! 		    (*isc->sc_rintr)(isc->sc_rarg);
! 		    retval = 1;
! 		}
! 	    } else {
! 		if (isc->sc_pintr) {
! 		    (*isc->sc_pintr)(isc->sc_parg);
! 		    retval = 1;
! 		}
! 	    }
! 	    /* clear interrupt */
! 	    ADWRITE(sc, AD1848_STATUS, 0);
  	}
  	return(retval);
  }
  
diff -rc usr/src/sys/dev/isa/ad1848var.h /usr/src/sys/dev/isa/ad1848var.h
*** usr/src/sys/dev/isa/ad1848var.h	Mon Mar 22 15:29:14 1999
--- /usr/src/sys/dev/isa/ad1848var.h	Mon Jul 31 09:55:07 2000
***************
*** 87,94 ****
  	int	sc_recdrq;		/* record/capture DMA */
  	
  	u_long	sc_interrupts;		/* number of interrupts taken */
! 	void	(*sc_intr)(void *);	/* dma completion intr handler */
! 	void	*sc_arg;		/* arg for sc_intr() */
  
  	/* Only used by pss XXX */
  	int	sc_iobase;
--- 87,96 ----
  	int	sc_recdrq;		/* record/capture DMA */
  	
  	u_long	sc_interrupts;		/* number of interrupts taken */
! 	void	(*sc_pintr)(void *);	/* dma completion intr handler */
! 	void	*sc_parg;		/* arg for sc_intr() */
! 	void	(*sc_rintr)(void *);	/* dma completion intr handler */
! 	void	*sc_rarg;		/* arg for sc_intr() */
  
  	/* Only used by pss XXX */
  	int	sc_iobase;

>Release-Note:
>Audit-Trail:
>Unformatted: