Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Aug 1995 03:52:01 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        current@freebsd.org, root@io.cts.com
Cc:        vak@cronyx.ru
Subject:   Re: wd0 detect fails
Message-ID:  <199508271752.DAA24683@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>I put a 2MB caching Promise IDE controller into my 486 and moved the
>drives off the onboard IDE controller that this motherboard supports.
>I disabled the BIOS settings for the onboard IDE, then restarted.

>Under a current kernel built just two days ago, it fails to find wdc0
>at 0x1f0, can't mount /root, and panics.

>If I go back to my previous kernel built August 8, it can find it just
>fine (which is what I'm using now) and 0x1f0-0x1f7 irq 14.

>So something has changed in the probing at startup that is causing it
>to miss the drives hanging off this older caching controller.

Cdrom support was added.  The following change looks wrong (but works
here):

diff -c -2 -r1.81 wd.c
*** 1.81	1995/05/16 07:52:04
--- wd.c	1995/08/19 19:40:54
***************
*** 1863,1868 ****
  	DELAY(10 * 1000);
  	outb(wdc + wd_ctlr, WDCTL_IDS);
! 	if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
! 	    || (du->dk_error = inb(wdc + wd_error)) != 0x01)
  		return (1);
  	outb(wdc + wd_ctlr, WDCTL_4BIT);
--- 1903,1912 ----
  	DELAY(10 * 1000);
  	outb(wdc + wd_ctlr, WDCTL_IDS);
! 	if (wdwait(du, 0, TIMEOUT) != 0)
! 		return (1);
! 	du->dk_status = inb(wdc + wd_status);
! 	du->dk_error = inb(wdc + wd_error);
! 	if ((du->dk_status & ~(WDCS_READY | WDCS_SEEKCMPLT)) != 0 ||
! 	    du->dk_error != 0x01)
  		return (1);
  	outb(wdc + wd_ctlr, WDCTL_4BIT);

The ATA spec (revision 4c, section B.6) says that the hardware shall set
the status to 0x50 (WDCS_READY | WDCS_SEEKCMPLT) within 31 seconds of
reset.  This is what the old code tested for, except for the follow bugs:

oldbug1) The other status bits (except WDCS_BUSY) aren't required to be
         zero.
oldbug2) TIMEOUT is to small.  It is 10000 ms but should be 31000 ms.

The new code only waits for the WDCS_BUSY bit to go low; then it tests
the other bits.  This may be OK - the spec seems to say that the status
register is set atomically, and reading the status register again might
fix any timing problems (normally the status register shouldn't be read
twice because of side effects.  Reading it twice is is probably a
harmless no-op here).  The new code then tests the bits sloppily:

newbug1) The (WDCS_READY | WDCS_SEEKCMPLT) bits aren't required to be one.

It is being fussier.  than the old code about the bits that should be
zero and sloppier about the bits that should be one.  I wouldn't have
expected this to matter for drives that meet the spec.

The new code also has some changes involving the b_active state.  These
seemed OK.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508271752.DAA24683>