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: