patch-2.1.15 linux/drivers/block/ide-cd.c

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

diff -u --recursive --new-file v2.1.14/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
@@ -143,6 +143,7 @@
  * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
  *                          to fix the drive door locking problems.
  *
+ * 4.03  Dec 04, 1996  -- Added DSC overlap support.
  *
  * MOSTLY DONE LIST:
  *  Query the drive to find what features are available
@@ -969,6 +970,53 @@
 					      &cdrom_read_intr);
 }
 
+#define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
+#define IDECD_SEEK_TIMER	(2 * WAIT_MIN_SLEEP)	/* 40 ms */
+#define IDECD_SEEK_TIMEOUT	(20 * IDECD_SEEK_TIMER) /* 0.8 sec */
+
+static void cdrom_seek_intr (ide_drive_t *drive)
+{
+	struct cdrom_info *info = drive->driver_data;
+	int stat;
+	static int retry = 10;
+
+	if (cdrom_decode_status (drive, 0, &stat)) return;
+	CDROM_CONFIG_FLAGS(drive)->seeking = 1;
+
+	if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
+		if (--retry == 0) {
+			printk ("%s: disabled DSC seek overlap\n", drive->name);
+			drive->dsc_overlap = 0;
+		}
+	}
+}
+
+static void cdrom_start_seek_continuation (ide_drive_t *drive)
+{
+	struct packet_command pc;
+	struct request *rq = HWGROUP(drive)->rq;
+	int sector, frame, nskip;
+
+	sector = rq->sector;
+	nskip = (sector % SECTORS_PER_FRAME);
+	if (nskip > 0)
+		sector -= nskip;
+	frame = sector / SECTORS_PER_FRAME;
+
+	memset (&pc.c, 0, sizeof (pc.c));
+	pc.c[0] = SEEK;
+	put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
+	(void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
+}
+
+static void cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+{
+	struct cdrom_info *info = drive->driver_data;
+
+	info->dma = 0;
+	info->start_seek = jiffies;
+	cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
+}
 
 /*
  * Start a read request from the CD-ROM.
@@ -1250,8 +1298,28 @@
 	} else if (rq -> cmd != READ) {
 		printk ("ide-cd: bad cmd %d\n", rq -> cmd);
 		cdrom_end_request (0, drive);
-	} else
-		cdrom_start_read (drive, block);
+	} else {
+		struct cdrom_info *info = drive->driver_data;
+
+		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
+			unsigned long elpased = jiffies - info->start_seek;
+			int stat = GET_STAT();
+
+			if ((stat & SEEK_STAT) != SEEK_STAT) {
+				if (elpased < IDECD_SEEK_TIMEOUT) {
+					ide_stall_queue (drive, IDECD_SEEK_TIMER);
+					return;
+				}
+				printk ("%s: DSC timeout\n", drive->name);
+			}
+			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+		}
+		if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
+			cdrom_start_seek (drive, block);
+		else
+			cdrom_start_read (drive, block);
+		info->last_block = block;
+	}
 }
 
 
@@ -2831,6 +2899,7 @@
 	ide_cdrom,			/* media */
 	0,				/* busy */
 	1,				/* supports_dma */
+	1,				/* supports_dsc_overlap */
 	ide_cdrom_cleanup,		/* cleanup */
 	ide_do_rw_cdrom,		/* do_request */
 	NULL,				/* ??? or perhaps

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov