Subject: Re: kern/22869: Slave IDE drive not detected
To: Manuel Bouyer <bouyer@antioche.lip6.fr>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-kern
Date: 09/22/2003 21:08:50
Well, I tried the following change, and it helped a bit.  It prevents
trying to further probe the ghost on the laptop's primary bus.  It
also avoids waiting for BSY to clear on the bogus drive 1 with my CF
cards.  However, the real IDENTIFY command never manages to complete
on the CF cards now.  I'll look into this some more later.


Index: wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.125
diff -u -r1.125 wdc.c
--- wdc.c	2003/09/19 21:36:02	1.125
+++ wdc.c	2003/09/22 21:07:43
@@ -205,14 +205,14 @@
 			chp->wdc->select(chp,0);
 		bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 		    WDSD_IBM);
-		delay(10);
+		delay(10);	/* 400ns delay */
 		st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
 		
 		if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
 			chp->wdc->select(chp,1);
 		bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 		    WDSD_IBM | 0x10);
-		delay(10);
+		delay(10);	/* 400ns delay */
 		st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
 
 		WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
@@ -231,14 +231,14 @@
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 			    WDSD_IBM);
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
-			    0x01);
+			    0x02);
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
-			    wd_cyl_lo) != 0x01)
+			    wd_cyl_lo) != 0x02)
 				ret_value &= ~0x01;
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
-			    0x02);
+			    0x01);
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
-			    wd_cyl_lo) != 0x02)
+			    wd_cyl_lo) != 0x01)
 				ret_value &= ~0x01;
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector,
 			    0x01);
@@ -250,6 +250,9 @@
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
 			    wd_sector) != 0x02)
 				ret_value &= ~0x01;
+			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+			    wd_cyl_lo) != 0x01)
+				ret_value &= ~0x01;
 		}
 
 		/* Register writability test, drive 1. */
@@ -259,14 +262,14 @@
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 			    WDSD_IBM | 0x10);
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
-			    0x01);
+			    0x02);
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
-			    wd_cyl_lo) != 0x01)
+			    wd_cyl_lo) != 0x02)
 				ret_value &= ~0x02;
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
-			    0x02);
+			    0x01);
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
-			    wd_cyl_lo) != 0x02)
+			    wd_cyl_lo) != 0x01)
 				ret_value &= ~0x02;
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector,
 			    0x01);
@@ -278,28 +281,9 @@
 			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
 			    wd_sector) != 0x02)
 				ret_value &= ~0x02;
-		}
-
-		/* Register ghost test. */
-		if (ret_value == 0x03) {
-			if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
-				chp->wdc->select(chp,1);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
-			    WDSD_IBM | 0x10);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector, 0x01);
-			if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
-				chp->wdc->select(chp,0);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
-			    WDSD_IBM);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector, 0x02);
-			if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
-				chp->wdc->select(chp,1);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
-			    WDSD_IBM | 0x10);
-			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector) == 0x02) {
-				printf("ghost detected\n");
-				ret_value = 0x01;
-			}
+			if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+			    wd_cyl_lo) != 0x01)
+				ret_value &= ~0x02;
 		}
 
 		if (ret_value == 0)
@@ -312,16 +296,15 @@
 	/* assert SRST, wait for reset to complete */
 	bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 	    WDSD_IBM);
-	delay(10);
+	delay(10);	/* 400ns delay */
 	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
 	    WDCTL_RST | WDCTL_IDS); 
-	DELAY(1000);
-	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
-	    WDCTL_IDS);
 	delay(1000);
+	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_IDS);
+	delay(1000);
 	(void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
 	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
-	delay(10);
+	delay(10);	/* 400ns delay */
 
 	ret_value = __wdcwait_reset(chp, ret_value);
 	WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
@@ -345,7 +328,7 @@
 			chp->wdc->select(chp,drive);
 		bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 		    WDSD_IBM | (drive << 4));
-		delay(10);
+		delay(10);	/* 400ns delay */
 		/* Save registers contents */
 		sc = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
 		sn = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -362,13 +345,28 @@
 		 */
 		if (cl == 0x14 && ch == 0xeb) {
 			chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
-		} else {
+			continue;
+		}
+		bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_command,
+		    WDCC_IDENTIFY);
+		delay(10);	/* 400ns delay */
+		if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status) & (WDCS_BSY | WDCS_DRQ)) {
 			chp->ch_drive[drive].drive_flags |= DRIVE_ATA;
 			if (chp->wdc == NULL ||
 			    (chp->wdc->cap & WDC_CAPABILITY_PREATA) != 0)
 				chp->ch_drive[drive].drive_flags |= DRIVE_OLD;
 		}
 	}
+
+	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
+	    WDCTL_RST | WDCTL_IDS); 
+	delay(1000);
+	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_IDS);
+	delay(1000);
+	(void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
+	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
+	delay(10);
+
 	return (ret_value);	
 }
 
@@ -464,7 +462,7 @@
 				chp->wdc->select(chp,i);
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
 			    WDSD_IBM | (i << 4));
-			delay(10);
+			delay(10);	/* 400ns delay */
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
 			    wd_error, 0x58);
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
@@ -479,11 +477,6 @@
 				    chp->channel, i), DEBUG_PROBE);
 				    chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
 			}
-			if (chp->wdc->cap & WDC_CAPABILITY_SELECT)
-				chp->wdc->select(chp,i);
-			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
-			    WDSD_IBM | (i << 4));
-			delay(100);
 			if (wait_for_ready(chp, 10000) != 0) {
 				WDCDEBUG_PRINT(("%s:%d:%d: not ready\n",
 				    chp->wdc->sc_dev.dv_xname,
@@ -493,6 +486,7 @@
 			}
 			bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
 			    wd_command, WDCC_RECAL);
+			delay(10);	/* 400ns delay */
 			if (wait_for_ready(chp, 10000) != 0) {
 				WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
 				    chp->wdc->sc_dev.dv_xname,
@@ -859,7 +853,7 @@
 	    WDCTL_RST | WDCTL_IDS);
 	delay(1000);
 	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
-	    WDCTL_IDS);
+	    WDCTL_RST | WDCTL_4BIT);
 	delay(1000);
 	(void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
 	bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
@@ -886,7 +880,7 @@
 	int drv_mask;
 {
 	int timeout;
-	u_int8_t st0, st1;
+	u_int8_t st0, er0, st1, er1;
 #ifdef WDCDEBUG
 	u_int8_t sc0, sn0, cl0, ch0;
 	u_int8_t sc1, sn1, cl1, ch1;
@@ -899,6 +893,7 @@
 		    WDSD_IBM); /* master */
 		delay(10);
 		st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+		er0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
 #ifdef WDCDEBUG
 		sc0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
 		sn0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -911,6 +906,7 @@
 		    WDSD_IBM | 0x10); /* slave */
 		delay(10);
 		st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+		er1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
 #ifdef WDCDEBUG
 		sc1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
 		sn1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -944,6 +940,10 @@
 	if (st1 & WDCS_BSY)
 		drv_mask &= ~0x02;
 end:
+	if (er0 != 0x01 && er0 != 0x81)
+		drv_mask &= ~0x01;
+	if (er1 != 0x01)
+		drv_mask &= ~0x02;
 	WDCDEBUG_PRINT(("%s:%d:0: after reset, sc=0x%x sn=0x%x "
 	    "cl=0x%x ch=0x%x\n",
 	     chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
@@ -953,9 +953,9 @@
 	     chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
 	     chp->channel, sc1, sn1, cl1, ch1), DEBUG_PROBE);
 
-	WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x, st1=0x%x\n",
+	WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x er0=0x%x, st1=0x%x er1=0x%x\n",
 	    chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel,
-	    st0, st1), DEBUG_PROBE);
+	    st0, er0, st1, er1), DEBUG_PROBE);
 
 	return drv_mask;
 }