diff options
author | csgr <csgr@FreeBSD.org> | 1994-04-10 11:17:13 +0000 |
---|---|---|
committer | csgr <csgr@FreeBSD.org> | 1994-04-10 11:17:13 +0000 |
commit | 868c85662bfa7f66e2e285f81356b32e01b2aa37 (patch) | |
tree | 54ba2ff0ae3a4fa65e914424a34a98926b3ed7d1 /sys | |
parent | d7f39fe8335fb7d221705913040e0629aceeeea8 (diff) | |
download | FreeBSD-src-868c85662bfa7f66e2e285f81356b32e01b2aa37.zip FreeBSD-src-868c85662bfa7f66e2e285f81356b32e01b2aa37.tar.gz |
Modify wdprobe() to correctly recognise some 2 drive systems,
on which it was failing. Modifications follow ATA, but also
allow some weird setups which seem to contradict ATA (aaarrrrgghhh!!)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/isa/wd.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 1de0215..99587f2 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -37,7 +37,7 @@ static int wdtest = 0; * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.35 1994/03/04 16:43:07 ache Exp $ + * $Id: wd.c,v 1.36 1994/03/06 03:10:58 jkh Exp $ */ /* TODO: @@ -209,9 +209,46 @@ wdprobe(struct isa_device *dvp) /* execute a controller only command */ if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0 - || wdwait(du, 0, TIMEOUT) != 0) + || wdwait(du, 0, TIMEOUT) < 0) goto nodevice; + /* + * drive(s) did not time out during diagnostic : + * Get error status and check that both drives are OK. + * Table 9-2 of ATA specs suggests that we must check for + * a value of 0x01 + * + * Strangely, some controllers will return a status of + * 0x81 (drive 0 OK, drive 1 failure), and then when + * the DRV bit is set, return status of 0x01 (OK) for + * drive 2. (This seems to contradict the ATA spec.) + */ + du->dk_error = inb(du->dk_port + wd_error); + /* printf("Error : %x\n", du->dk_error); */ + if(du->dk_error != 0x01) { + if(du->dk_error & 0x80) { /* drive 1 failure */ + + /* first set the DRV bit */ + u_int sdh; + sdh = inb(du->dk_port+ wd_sdh); + sdh = sdh | 0x10; + outb(du->dk_port+ wd_sdh, sdh); + + /* Wait, to make sure drv 1 has completed diags */ + if ( wdwait(du, 0, TIMEOUT) < 0) + goto nodevice; + + /* Get status for drive 1 */ + du->dk_error = inb(du->dk_port + wd_error); + /* printf("Error (drv 1) : %x\n", du->dk_error); */ + + if(du->dk_error != 0x01) + goto nodevice; + } else /* drive 0 fail */ + goto nodevice; + } + + free(du, M_TEMP); return (IO_WDCSIZE); |