summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/wd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/isa/wd.c')
-rw-r--r--sys/i386/isa/wd.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 115f275..d3c8ec3 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
- * $Id: wd.c,v 1.85 1995/09/30 00:11:19 jkh Exp $
+ * $Id: wd.c,v 1.86 1995/09/30 15:19:44 davidg Exp $
*/
/* TODO:
@@ -301,11 +301,34 @@ wdprobe(struct isa_device *dvp)
/* check if we have registers that work */
outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
outb(du->dk_port + wd_cyl_lo, 0xa5); /* wd_cyl_lo is read/write */
- if (inb(du->dk_port + wd_cyl_lo) == 0xff) /* XXX too weak */
- goto nodevice;
+ if (inb(du->dk_port + wd_cyl_lo) == 0xff) { /* XXX too weak */
+#ifdef ATAPI
+ /* There is no master, try the ATAPI slave. */
+ outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10);
+ outb(du->dk_port + wd_cyl_lo, 0xa5);
+ if (inb(du->dk_port + wd_cyl_lo) == 0xff)
+#endif
+ goto nodevice;
+ }
- if (wdreset(du) != 0 && (DELAY(RECOVERYTIME), wdreset(du)) != 0)
+ if (wdreset(du) == 0)
+ goto reset_ok;
+#ifdef ATAPI
+ /* test for ATAPI signature */
+ outb(du->dk_port + wd_sdh, WDSD_IBM); /* master */
+ if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
+ inb(du->dk_port + wd_cyl_hi) == 0xeb)
+ goto reset_ok;
+ du->dk_unit = 1;
+ outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10); /* slave */
+ if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
+ inb(du->dk_port + wd_cyl_hi) == 0xeb)
+ goto reset_ok;
+#endif
+ DELAY(RECOVERYTIME);
+ if (wdreset(du) != 0)
goto nodevice;
+reset_ok:
/* execute a controller only command */
if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
@@ -657,7 +680,7 @@ loop:
bp = wdtab[ctrlr].b_actf;
if (bp == NULL) {
#ifdef ATAPI
- if (atapi_start (ctrlr))
+ if (atapi_start && atapi_start (ctrlr))
/* mark controller active in ATAPI mode */
wdtab[ctrlr].b_active = 3;
#endif
@@ -891,7 +914,7 @@ wdintr(int unit)
#ifdef ATAPI
if (wdtab[unit].b_active == 3) {
/* process an ATAPI interrupt */
- if (atapi_intr (unit))
+ if (atapi_intr && atapi_intr (unit))
/* ATAPI op continues */
return;
/* controller is free, start new op */
@@ -1916,13 +1939,6 @@ wdreset(struct disk *du)
du->dk_error = inb(wdc + wd_error);
if (du->dk_error != 0x01)
err = 1; /* the drive is incompatible */
- if (err) {
- /* no IDE drive, test for ATAPI signature */
- int lo = inb(wdc + wd_cyl_lo);
- int hi = inb(wdc + wd_cyl_hi);
- if (lo == 0x14 && hi == 0xeb)
- err = 0; /* ATAPI drive detected */
- }
#else
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
|| (du->dk_error = inb(wdc + wd_error)) != 0x01)
@@ -2042,6 +2058,18 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
min_retries[du->dk_ctrlr] = timeout;
#endif
du->dk_status = status = inb(wdc + wd_status);
+#ifdef ATAPI
+ /*
+ * Atapi drives have a very interesting feature, when attached
+ * as a slave on the IDE bus, and there is no master.
+ * They release the bus after getting the command.
+ * We should reselect the drive here to get the status.
+ */
+ if (status == 0xff) {
+ outb(wdc + wd_sdh, WDSD_IBM | du->dk_unit << 4);
+ du->dk_status = status = inb(wdc + wd_status);
+ }
+#endif
if (!(status & WDCS_BUSY)) {
if (status & WDCS_ERR) {
du->dk_error = inb(wdc + wd_error);
OpenPOWER on IntegriCloud