[1905] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

Bug in sr_vendor.c + patch

daemon@ATHENA.MIT.EDU (Andries.Brouwer@cwi.nl)
Sun May 25 15:25:07 1997

Date: 	Sun, 25 May 1997 21:22:16 +0200
From: Andries.Brouwer@cwi.nl
To: kraxel@cs.tu-berlin.de, linux-kernel@vger.rutgers.edu,
        linux-scsi@vger.rutgers.edu, lnz@dandelion.com

[Sent to linux-kernel, linux-scsi. I do not read these lists;
 please cc if you want me to read your reply.
 Also sent to Gerd Knorr and Leonard Zubkoff.]

Since 2.1.34 I noticed that mounting a CDROM would always
fail the first time and succeed the next time. Mount would
succeed immediately if it was preceded by a dd accessing the CDROM.

Tracing the cause of this I find that this is because of sr_vendor.c,
where the routine sr_cd_check() does a read-raw of sector 16
in order to determine whether the CDROM is of XA type.
When this read-raw is followed by a read of sector 16
(either from some small C program or from the kernel
isofs/inode.c:isofs_read_super()), then the read-raw
results are returned, so that the data are shifted by 4 bytes.
Any following read of the same sector will return the shifted
data, but as soon as a read of a different sector is interpolated,
all is fine.

Clearly, some cacheing is done somewhere.

CPU: 486
SCSI controller: Adaptec 1542CF.
CDROM reader: NEC 3X.

Host: scsi0 Channel: 00 Id: 01 Lun: 00
  Vendor: NEC      Model: CD-ROM DRIVE:500 Rev: 1.0
  Type:   CD-ROM                           ANSI SCSI revision: 02

I am not sure what the proper correction is.
[That might depend on who is doing this cacheing.]
The patch below puts NEC CD-ROM DRIVE:500 on the black list
where no multisession capabilities are to be checked.

(This patch also corrects a test for scsi_malloc failure.)

Andries

--- /nb/linux/linux-2.1.40/linux/drivers/scsi/sr_vendor.c	Tue Apr 15 21:43:08 1997
+++ ./sr_vendor.c	Sun May 25 20:32:35 1997
@@ -3,7 +3,7 @@
  * vendor-specific code for SCSI CD-ROM's goes here.
  *
  * This is needed becauce most of the new features (multisession and
- * the like) are to new to be included into the SCSI-II standard (to
+ * the like) are too new to be included into the SCSI-II standard (to
  * be exact: there is'nt anything in my draft copy).
  *
  *   Gerd Knorr <kraxel@cs.tu-berlin.de> 
@@ -65,7 +65,10 @@
 		if (!strncmp (model,"CD-ROM DRIVE:25", 15)  ||
 		    !strncmp (model,"CD-ROM DRIVE:36", 15)  ||
 		    !strncmp (model,"CD-ROM DRIVE:83", 15)  ||
-		    !strncmp (model,"CD-ROM DRIVE:84 ",16))
+		    !strncmp (model,"CD-ROM DRIVE:84 ",16)  ||
+		        /* my NEC 3x returns the read-raw data if a read-raw
+			   is followed by a read for the same sector - aeb */
+		    !strncmp (model,"CD-ROM DRIVE:500",16))
 			/* these can't handle multisession, may hang */
 			scsi_CDs[minor].cdi.mask |= CDC_MULTI_SESSION;
 
@@ -188,7 +191,8 @@
 		if (rc != 0)
 			break;
 		if (buffer[14] != 0 && buffer[14] != 0xb0) {
-			printk(KERN_INFO "sr (nec): Hmm, seems the cdrom doesn't support multisession CD's\n");
+			printk(KERN_INFO "sr (nec): Hmm, seems the cdrom "
+			       "doesn't support multisession CD's\n");
 			no_multi = 1;
 			break;
 		}
@@ -208,7 +212,8 @@
 		if (rc == 0x28000002 &&
 		    !scsi_ioctl(scsi_CDs[minor].device,
 				SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
-			printk(KERN_INFO "sr (toshiba): Hmm, seems the drive doesn't support multisession CD's\n");
+			printk(KERN_INFO "sr (toshiba): Hmm, seems the drive "
+			       "doesn't support multisession CD's\n");
 		    no_multi = 1;
 		    break;
 		}
@@ -272,7 +277,8 @@
 			break;
 		}
 		if ((buffer[0] << 8) + buffer[1] < 0x0a) {
-			printk(KERN_INFO "sr (sony): Hmm, seems the drive doesn't support multisession CD's\n");
+			printk(KERN_INFO "sr (sony): Hmm, seems the drive "
+			       "doesn't support multisession CD's\n");
 			no_multi = 1;
 			break;
 		}
@@ -303,7 +309,7 @@
 	if (CDS_AUDIO != sr_disk_status(cdi)) { 
 	    /* read a sector in raw mode to check the sector format */
 	    raw_sector = (unsigned char *) scsi_malloc(2048+512);
-	    if (!buffer) return -ENOMEM;
+	    if (!raw_sector) return -ENOMEM;
 	    if (0 == sr_read_sector(minor,sector+16,CD_FRAMESIZE_RAW1,
 				    raw_sector)){
 		is_xa = (raw_sector[3] == 0x02);

home help back first fref pref prev next nref lref last post