summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/wd.c
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-10-14 15:41:10 +0000
committerdg <dg@FreeBSD.org>1995-10-14 15:41:10 +0000
commit8d3425ea6285435601f20980b43c3143b05bc8d7 (patch)
tree70f4d924760a26cfd35ea6eb6ac64af1e30cefa4 /sys/i386/isa/wd.c
parenta308e5f9a1ba49753fdbe0e60fd5ee377a5096df (diff)
downloadFreeBSD-src-8d3425ea6285435601f20980b43c3143b05bc8d7.zip
FreeBSD-src-8d3425ea6285435601f20980b43c3143b05bc8d7.tar.gz
Latest fixes from Serge:
I tried to solve the problem of IDE probing compatibility in this version. When compiled without an ATAPI option, the wd driver is fully backward compatible with 2.0.5. With ATAPI option, the wdprobe becomes strictly weaker. That is, if wdprobe works without ATAPI option, it will always work with it too. Another problem was with the CD-ROM drive attached as a slave in the IDE bus, where there is no master. All IDE CD-ROM drives are shipped in slave configuration, and most users just plug them in, never thinking about jumpers. It works fine with ms-dos and ms-windows, and this version of the driver supports it as well. The eject op can now load disks. Just repeat it twice, and the disk will be ejected and then loaded back. The disc cannot be ejected if it is mounted. Submitted by: Serge Vakulenko, <vak@cronyx.ru>
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