Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 2003 19:07:49 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        jjramsey@pobox.com
Cc:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: Semirandom bug in FreeBSD's ATA querying
Message-ID:  <20030112183638.I5726-100000@gamplex.bde.org>
In-Reply-To: <20030112005620.10542.qmail@web10703.mail.yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 11 Jan 2003, James J. Ramsey wrote:

> ...
> I have been repeated told that this is a hardware
> problem. I disagree for two reasons:
>
> 1) The problem has never occured under Linux, Windows,
> or an OpenBSD 3.1 snapshot (although the last one had
> other problems).
>
> 2) The kernel messages from Linux indicate that it is
> correctly querying the hard drive. Here's what I mean.
> The following kernel message is from a FreeBSD
> install. I captured it by pressing Scroll Lock and
> pressing the Page Up key to get to the text:
>
> ad0: 8866663634010175MB
> <?U}O|U}!~IEzA~M~!|M~1.5?!?!~!~!?!?!~!?!>
> [16955114026566160/17/63] at ata0-master PIO4
>
> The garbage between the angle brackets should be the
> name of the hard drive, "QUANTUM FIREBALLP". Compare
> this with the kernel message from Linux:
>
> hda: QUANTUM FIREBALLP LM20.5, ATA DISK drive
>
> The name of the disk drive is reported correctly.
>
> Considering that the disk drive name only comes as a
> result of a particular ATA command, it is clear that
> Linux is reading the results of the command correctly.
> It is simply doing something correctly that FreeBSD is
> not. That is not indicative of a hidden hardware bug.

Actually, it is indicative of a timing bug, which may be
in either the hardware or the driver but is most likely
in the hardware.  Linux and the old FreeBSD driver (wd)
have more compatibility cruft including delays to
support broken drives.  Try adding some delays near
the broken command.

From ata-all.c:

%%%
    /* apparently some devices needs this repeated */
    do {
	if (ata_command(atadev, command, 0, 0, 0, ATA_WAIT_INTR)) {
	    ata_prtdev(atadev, "%s identify failed\n",
		       command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA");
	    free(ata_parm, M_ATA);
	    return -1;
	}
	if (retry++ > 4) {
	    ata_prtdev(atadev, "%s identify retries exceeded\n",
		       command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA");
	    free(ata_parm, M_ATA);
	    return -1;
	}
    } while (ata_wait(atadev, ((command == ATA_C_ATAPI_IDENTIFY) ?
			       ATA_S_DRQ : (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))));
    ATA_INSW(atadev->channel->r_io, ATA_DATA, (int16_t *)ata_parm,
	     sizeof(struct ata_params)/sizeof(int16_t));
%%%

Try adding delays before ata_command() and ata_wait(), and before
ATA_INSW().  The Linux driver (16 Jan 2001 version at least) has 50
msec delays near here.  At least in old version of ATA, delays of 400
nsec are supposed to work, but the Linux driver uses much larger delays
for superstituous and/or hisorical reasons.  The ata driver has
corresponding 1-10 usec delays in its command and wait functions, but
seems to have these slightly misplaced (no wait after getting !ATA_S_BUSY
before checking the other status bits for the first time).  Many (most?)
drives don't need any delays.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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