patch-2.3.40 linux/drivers/block/ide-disk.c

Next file: linux/drivers/block/ide-dma.c
Previous file: linux/drivers/block/ide-cd.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
@@ -139,10 +139,20 @@
 	int i;
 	unsigned int msect, nsect;
 	struct request *rq;
-
+#if 0
 	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
 		return ide_error(drive, "read_intr", stat);
 	}
+#else	/* new way for dealing with premature shared PCI interrupts */
+	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			return ide_error(drive, "read_intr", stat);
+		}
+		/* no data yet, so wait for another interrupt */
+		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
+		return ide_started;
+	}
+#endif
 	msect = drive->mult_count;
 	
 read_next:
@@ -163,7 +173,7 @@
 	rq->buffer += nsect<<9;
 	rq->errors = 0;
 	i = (rq->nr_sectors -= nsect);
-	if ((rq->current_nr_sectors -= nsect) <= 0)
+	if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
 		ide_end_request(1, HWGROUP(drive));
 	if (i > 0) {
 		if (msect)
@@ -198,7 +208,7 @@
 			rq->errors = 0;
 			i = --rq->nr_sectors;
 			--rq->current_nr_sectors;
-			if (rq->current_nr_sectors <= 0)
+			if (((long)rq->current_nr_sectors) <= 0)
 				ide_end_request(1, hwgroup);
 			if (i > 0) {
 				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
@@ -207,8 +217,8 @@
 			}
                         return ide_stopped;
 		}
-                printk("%s: write_intr error2: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
-        }
+		return ide_stopped;	/* the original code did this here (?) */
+	}
 	return ide_error(drive, "write_intr", stat);
 }
 
@@ -221,12 +231,22 @@
 int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
 {
  	ide_hwgroup_t	*hwgroup= HWGROUP(drive);
+
+	/*
+	 *	This may look a bit odd, but remember wrq is a copy of the
+	 *	request not the original. The pointers are real however so the
+	 *	bh's are not copies. Remember that or bad stuff will happen
+	 *
+	 *	At the point we are called the drive has asked us for the
+	 *	data, and its our job to feed it, walking across bh boundaries
+	 *	if need be.
+	 */
+
  	struct request	*rq = &hwgroup->wrq;
 
   	do {
  		unsigned long flags;
   		unsigned int nsect = rq->current_nr_sectors;
-
 		if (nsect > mcount)
 			nsect = mcount;
 		mcount -= nsect;
@@ -241,9 +261,11 @@
 #ifdef CONFIG_BLK_DEV_PDC4030
 		rq->sector += nsect;
 #endif
-		if ((rq->nr_sectors -= nsect) <= 0) {
+		if (((long)(rq->nr_sectors -= nsect)) <= 0) {
+#ifdef DEBUG
 			printk("%s: multwrite: count=%d, current=%ld\n",
 				drive->name, nsect, rq->nr_sectors);
+#endif
 			spin_unlock_irqrestore(&io_request_lock, flags);
 			break;
 		}
@@ -253,11 +275,14 @@
 				rq->buffer             = rq->bh->b_data;
 			} else {
 				spin_unlock_irqrestore(&io_request_lock, flags);
-				printk("%s: buffer list corrupted\n", drive->name);
+				printk("%s: buffer list corrupted (%ld, %ld, %d)\n",
+					drive->name, rq->current_nr_sectors,
+					rq->nr_sectors, nsect);
 				ide_end_request(0, hwgroup);
 				return 1;
 			}
 		} else {
+			/* Fix the pointer.. we ate data */
 			rq->buffer += nsect << 9;
 		}
                 spin_unlock_irqrestore(&io_request_lock, flags);
@@ -277,6 +302,10 @@
 
 	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
 		if (stat & DRQ_STAT) {
+			/*
+			 *	The drive wants data. Remember rq is the copy
+			 *	of the request
+			 */
 			if (rq->nr_sectors) {
 				if (ide_multwrite(drive, drive->mult_count))
 					return ide_stopped;
@@ -284,6 +313,10 @@
 				return ide_started;
 			}
 		} else {
+			/*
+			 *	If the copy has all the blocks completed then
+			 *	we can end the original request.
+			 */
 			if (!rq->nr_sectors) {	/* all done? */
 				rq = hwgroup->rq;
 				for (i = rq->nr_sectors; i > 0;){
@@ -293,6 +326,7 @@
 				return ide_stopped;
 			}
 		}
+		return ide_stopped;	/* the original code did this here (?) */
 	}
 	return ide_error(drive, "multwrite_intr", stat);
 }
@@ -302,13 +336,9 @@
  */
 static ide_startstop_t set_multmode_intr (ide_drive_t *drive)
 {
-	byte stat = GET_STAT();
+	byte stat;
 
-#if 0
-	if (OK_STAT(stat,READY_STAT,BAD_STAT) || drive->mult_req == 0) {
-#else
-	if (OK_STAT(stat,READY_STAT,BAD_STAT)) {
-#endif
+	if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) {
 		drive->mult_count = drive->mult_req;
 	} else {
 		drive->mult_req = drive->mult_count = 0;
@@ -323,11 +353,16 @@
  */
 static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
 {
-	byte stat = GET_STAT();
+	byte stat;
 
-	if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+	if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
+		return ide_stopped;
+
+	if (stat & (ERR_STAT|DRQ_STAT))
 		return ide_error(drive, "set_geometry_intr", stat);
-	return ide_stopped;
+
+	ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL);
+	return ide_started;	
 }
 
 /*
@@ -419,6 +454,8 @@
 			 * of data to be written.  If we hit an error (corrupted buffer list)
 			 * in ide_multwrite(), then we need to remove the handler/timer
 			 * before returning.  Fortunately, this NEVER happens (right?).
+			 *
+			 * Except when you get an error it seems...
 			 */
 			hwgroup->wrq = *rq; /* scratchpad */
 			ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
@@ -772,7 +809,7 @@
 			drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
 	if (drive->using_dma) {
-		if ((id->field_valid & 4) && (id->word93 & 0x2000) &&
+		if ((id->field_valid & 4) && (id->hw_config & 0x2000) &&
 		    (HWIF(drive)->udma_four) &&
 		    (id->dma_ultra & (id->dma_ultra >> 11) & 3)) {
 			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)