Subject: kern/5143: ad1848 probe chokes on (compatible) cs4236
To: None <gnats-bugs@gnats.netbsd.org>
From: None <rh@vip.at>
List: netbsd-bugs
Date: 03/10/1998 17:15:39
>Number:         5143
>Category:       kern
>Synopsis:       ad1848 probe chokes when probing cs4236
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Mar 10 08:20:00 1998
>Last-Modified:
>Originator:     Rene Hexel
>Organization:
	
>Release:        NetBSD 1.3 and NetBSD-current as of March 9, 1998
>Environment:
System: NetBSD idle 1.3 NetBSD 1.3 (IDLE) #28: Tue Mar 10 16:31:10 CET 1998 rh@idle:/usr/local/depot/packages/orig/sys/src/sys/arch/i386/compile/IDLE i386


>Description:
	The mode 1 "register mirroring" test in ad1848_probe() fails
with ad1848 compatible devices (such as the cs4236, and probably others
as well) if register 11 (SP_TEST_AND_INIT) for some reason contains a
non-zero value.  Since this register has clear-upon-read semantics the
first read operation returns the original value, whereas a subsequent read
returns zero. This breaks the mirror test in ad1848_probe(), which reads
every register twice, first at its "real" position and then at its "mirror"
position 16 bytes away!

>How-To-Repeat:
	Insert a sound board containing a Crystal CS4236 chip, such as
the Terratec EWS 64XL (might also work with other AD1848 compatible chips).
Compile a kernel with AUDIO_DEBUG and ad1848debug set and with a little
luck watch the following message during system startup:
	
	netbsd: ad_detect_F(11/5/0)
	
	"5" can, of course, be replaced by any other non-zero value...

>Fix:
	From /usr/sys or /sys (or wherever you keep your kernel sources)
apply the following patch to the NetBSD-1.3 (the patch is the same for
NetBSD-current as of March 9, 1998, but the faulty line is 432 instead
of 417):

*** dev/isa/ad1848.c.orig	Sun Oct 19 16:07:01 1997
--- dev/isa/ad1848.c	Tue Mar 10 16:42:50 1998
***************
*** 414,420 ****
      for (i = 0; i < 16; i++)
  	if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) {
  	    DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2));
! 	    goto bad;
  	}
  
      /*
--- 414,420 ----
      for (i = 0; i < 16; i++)
  	if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) {
  	    DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2));
! 	    if (i != SP_TEST_AND_INIT) goto bad;
  	}
  
      /*
>Audit-Trail:
>Unformatted: