[3032] in linux-scsi channel archive
Re: new scsi code
daemon@ATHENA.MIT.EDU (Gerd Knorr)
Mon Jan 5 12:57:56 1998
Date: Mon, 5 Jan 1998 17:43:48 +0100 (MET)
From: Gerd Knorr <kraxel@goldbach.isdn.cs.tu-berlin.de>
To: Eric Youngdale <eric@andante.jic.com>
cc: linux-scsi@vger.rutgers.edu
In-Reply-To: <Pine.LNX.3.95.980105080903.412O-100000@andante.jic.com>
> I don't read linux-kernel. I do read linux-scsi. Far too much
> noise on the kernel group (I used to spent all my free time deleting mail
> and not accomplishing anything).
I gate linux-kernel to a local newsgroup, a good solution for this
Problem.
> To: Andrew Sapozhnikov <sapa@hq.icb.chel.su>
> CC: Gerd Knorr <kraxel@goldbach.isdn.cs.tu-berlin.de>
>
> If you use the old error handling code, does the problem go away,
> or does it persist? If you are using the old error handling code, do you
> still get the "interrupt received but no mail" message?
I tracked the problem down in the meantime. scsi_check_sense() returns
FAILED for a ILLEGAL REQUEST. Result is that scsi_unjam_host() gets
called and takes the device offline...
If scsi_check_sense() returns SUCCESS, the error is handled one layer up
and everything is fine :-)
Below a patch for 2.1.x, it modifies scsi_check_sense() and has a few
changes for the scsi cdrom driver: some for the new scsi code, some to
make multisession handling for cdrom writers work (I hope).
That's the code I'm running currently, so far without problems.
Gerd
------------------------------- cut here -------------------------------
Common subdirectories: kernel/2.1.77/drivers/scsi/aic7xxx and linux/drivers/scsi/aic7xxx
diff -u kernel/2.1.77/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- kernel/2.1.77/drivers/scsi/scsi_error.c Wed Dec 24 11:34:05 1997
+++ linux/drivers/scsi/scsi_error.c Sun Dec 28 14:49:11 1997
@@ -1088,10 +1088,12 @@
case MEDIUM_ERROR:
return FAILED;
+ case ILLEGAL_REQUEST:
+ return SUCCESS;
+
case BLANK_CHECK:
case DATA_PROTECT:
case HARDWARE_ERROR:
- case ILLEGAL_REQUEST:
default:
return FAILED;
}
diff -u kernel/2.1.77/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- kernel/2.1.77/drivers/scsi/scsi_syms.c Sat Jan 3 13:24:28 1998
+++ linux/drivers/scsi/scsi_syms.c Sat Jan 3 13:24:00 1998
@@ -53,6 +53,7 @@
EXPORT_SYMBOL(scsi_init_malloc);
EXPORT_SYMBOL(scsi_init_free);
EXPORT_SYMBOL(scsi_ioctl);
+EXPORT_SYMBOL(scsi_sleep);
EXPORT_SYMBOL(print_command);
EXPORT_SYMBOL(print_sense);
EXPORT_SYMBOL(print_msg);
diff -u kernel/2.1.77/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- kernel/2.1.77/drivers/scsi/sr.c Wed Dec 24 11:34:05 1997
+++ linux/drivers/scsi/sr.c Sun Dec 28 13:40:20 1997
@@ -854,8 +854,6 @@
SDp->scsi_request_fn = do_sr_request;
scsi_CDs[i].device = SDp;
- sr_vendor_init(i);
-
sr_template.nr_dev++;
if(sr_template.nr_dev > sr_template.dev_max)
panic ("scsi_devices corrupt (sr)");
@@ -986,13 +984,11 @@
if (-EINVAL == rc) {
/* failed, drive has'nt this mode page */
scsi_CDs[i].cdi.speed = 1;
- scsi_CDs[i].cdi.capacity = 1;
/* disable speed select, drive probably can't do this either */
scsi_CDs[i].cdi.mask |= CDC_SELECT_SPEED;
} else {
n = buffer[3]+4;
scsi_CDs[i].cdi.speed = ((buffer[n+8] << 8) + buffer[n+9])/176;
- scsi_CDs[i].cdi.capacity = 1;
scsi_CDs[i].readcd_known = 1;
scsi_CDs[i].readcd_cdda = buffer[n+5] & 0x01;
/* print some capability bits */
@@ -1085,7 +1081,9 @@
scsi_CDs[i].cdi.handle = &scsi_CDs[i];
scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR,i);
scsi_CDs[i].cdi.mask = 0;
+ scsi_CDs[i].cdi.capacity = 1;
get_capabilities(i);
+ sr_vendor_init(i);
sprintf(name, "sr%d", i);
strcpy(scsi_CDs[i].cdi.name, name);
diff -u kernel/2.1.77/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- kernel/2.1.77/drivers/scsi/sr_ioctl.c Wed Dec 24 11:34:05 1997
+++ linux/drivers/scsi/sr_ioctl.c Sun Dec 28 14:50:09 1997
@@ -30,7 +30,7 @@
#define IOCTL_RETRIES 3
/* The CDROM is fairly slow, so we need a little extra time */
/* In fact, it is very slow if it has to spin up first */
-#define IOCTL_TIMEOUT 3000
+#define IOCTL_TIMEOUT 30*HZ
static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
{
@@ -51,11 +51,15 @@
int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength, int quiet)
{
Scsi_Cmnd * SCpnt;
+ Scsi_Device * SDev;
int result, err = 0, retries = 0;
+ SDev = scsi_CDs[target].device;
SCpnt = scsi_allocate_device(NULL, scsi_CDs[target].device, 1);
retry:
+ if( !scsi_block_when_processing_errors(SDev) )
+ return -ENODEV;
{
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
@@ -69,7 +73,7 @@
result = SCpnt->result;
/* Minimal error checking. Ignore cases we know about, and report the rest. */
- if(driver_byte(result) != 0)
+ if(driver_byte(result) != 0) {
switch(SCpnt->sense_buffer[2] & 0xf) {
case UNIT_ATTENTION:
scsi_CDs[target].device->changed = 1;
@@ -86,9 +90,7 @@
printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target);
if (retries++ < 10) {
/* sleep 2 sec and try again */
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 200;
- schedule ();
+ scsi_sleep(2*HZ);
goto retry;
} else {
/* 20 secs are enouth? */
@@ -123,7 +125,8 @@
print_command(sr_cmd);
print_sense("sr", SCpnt);
err = -EIO;
- };
+ }
+ }
result = SCpnt->result;
/* Wake up a process waiting for device*/
@@ -279,23 +282,10 @@
int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void* arg)
{
u_char sr_cmd[10];
- Scsi_Device * SDev;
int result, target;
target = MINOR(cdi->dev);
- SDev = scsi_CDs[target].device;
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if( !scsi_block_when_processing_errors(SDev) )
- {
- return -ENODEV;
- }
-
switch (cmd)
{
/* Sun-compatible */
@@ -718,22 +708,9 @@
unsigned int cmd, unsigned long arg)
{
int target, err;
- Scsi_Device * SDev;
target = MINOR(cdi->dev);
- SDev = scsi_CDs[target].device;
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if( !scsi_block_when_processing_errors(SDev) )
- {
- return -ENODEV;
- }
-
switch (cmd) {
case CDROMREADMODE1:
case CDROMREADMODE2:
diff -u kernel/2.1.77/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
--- kernel/2.1.77/drivers/scsi/sr_vendor.c Wed Dec 3 17:43:24 1997
+++ linux/drivers/scsi/sr_vendor.c Wed Dec 3 14:40:47 1997
@@ -56,8 +56,7 @@
#define VENDOR_NEC 2
#define VENDOR_TOSHIBA 3
-#define VENDOR_HP_4020 4 /* HP 4xxx writers, others too ?? */
-#define VENDOR_HP_6020 5 /* HP 6020 writers */
+#define VENDOR_WRITER 4 /* pre-scsi3 writers */
#define VENDOR_ID (scsi_CDs[minor].vendor)
@@ -72,13 +71,12 @@
/* default */
VENDOR_ID = VENDOR_SCSI3;
+ if (scsi_CDs[minor].readcd_known)
+ /* this is true for scsi3/mmc drives - no more checks */
+ return;
- if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) &&
- scsi_CDs[minor].device->type == TYPE_WORM) {
- if (!strncmp(model,"CD-Writer 6020",14))
- VENDOR_ID = VENDOR_HP_6020;
- else
- VENDOR_ID = VENDOR_HP_4020;
+ if (scsi_CDs[minor].device->type == TYPE_WORM) {
+ VENDOR_ID = VENDOR_WRITER;
} else if (!strncmp (vendor, "NEC", 3)) {
VENDOR_ID = VENDOR_NEC;
@@ -233,16 +231,13 @@
sector -= CD_MSF_OFFSET;
break;
- case VENDOR_HP_4020:
- /* Fallthrough */
- case VENDOR_HP_6020:
+ case VENDOR_WRITER:
+ memset(cmd,0,12);
cmd[0] = READ_TOC;
cmd[1] = (scsi_CDs[minor].device->lun << 5);
- cmd[8] = (VENDOR_ID == VENDOR_HP_4020) ?
- 0x04 : 0x0c;
+ cmd[8] = 0x04;
cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer,
- (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 0);
if (rc != 0) {
break;
}
@@ -252,16 +247,14 @@
break;
}
- if (VENDOR_ID == VENDOR_HP_4020) {
- cmd[0] = READ_TOC; /* Read TOC */
- cmd[1] = (scsi_CDs[minor].device->lun << 5);
- cmd[6] = rc & 0x7f; /* number of last session */
- cmd[8] = 0x0c;
- cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
- if (rc != 0) {
- break;
- }
+ cmd[0] = READ_TOC; /* Read TOC */
+ cmd[1] = (scsi_CDs[minor].device->lun << 5);
+ cmd[6] = rc & 0x7f; /* number of last session */
+ cmd[8] = 0x0c;
+ cmd[9] = 0x40;
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ if (rc != 0) {
+ break;
}
sector = buffer[11] + (buffer[10] << 8) +