patch-2.3.32 linux/drivers/scsi/sr.c

Next file: linux/drivers/scsi/sr.h
Previous file: linux/drivers/scsi/sim710_d.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.31/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
@@ -1,17 +1,17 @@
 /*
  *  sr.c Copyright (C) 1992 David Giller
- *           Copyright (C) 1993, 1994, 1995 Eric Youngdale
+ *           Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
  *
  *  adapted from:
  *      sd.c Copyright (C) 1992 Drew Eckhardt
  *      Linux scsi disk driver by
  *              Drew Eckhardt <drew@colorado.edu>
  *
- *      Modified by Eric Youngdale ericy@cais.com to
+ *      Modified by Eric Youngdale ericy@andante.org to
  *      add scatter-gather, multiple outstanding request, and other
  *      enhancements.
  *
- *          Modified by Eric Youngdale eric@aib.com to support loadable
+ *          Modified by Eric Youngdale eric@andante.org to support loadable
  *          low-level scsi drivers.
  *
  *       Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to
@@ -60,17 +60,28 @@
 static int sr_detect(Scsi_Device *);
 static void sr_detach(Scsi_Device *);
 
-struct Scsi_Device_Template sr_template = {
-	NULL, "cdrom", "sr", NULL, TYPE_ROM,
-	SCSI_CDROM_MAJOR, 0, 0, 0, 1,
-	sr_detect, sr_init,
-	sr_finish, sr_attach, sr_detach
+static int sr_init_command(Scsi_Cmnd *);
+
+struct Scsi_Device_Template sr_template =
+{
+	name:"cdrom",
+	tag:"sr",
+	scsi_type:TYPE_ROM,
+	major:SCSI_CDROM_MAJOR,
+	blk:1,
+	detect:sr_detect,
+	init:sr_init,
+	finish:sr_finish,
+	attach:sr_attach,
+	detach:sr_detach,
+	init_command:sr_init_command
 };
 
 Scsi_CD *scsi_CDs = NULL;
 static int *sr_sizes = NULL;
 
 static int *sr_blocksizes = NULL;
+static int *sr_hardsizes = NULL;
 
 static int sr_open(struct cdrom_device_info *, int);
 void get_sectorsize(int);
@@ -82,7 +93,7 @@
 
 static void sr_release(struct cdrom_device_info *cdi)
 {
-	if (scsi_CDs[MINOR(cdi->dev)].sector_size > 2048)
+	if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048)
 		sr_set_blocklength(MINOR(cdi->dev), 2048);
 	sync_dev(cdi->dev);
 	scsi_CDs[MINOR(cdi->dev)].device->access_count--;
@@ -108,7 +119,7 @@
 	sr_audio_ioctl,		/* audio ioctl */
 	sr_dev_ioctl,		/* device-specific ioctl */
 	CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED |
-	CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED |
+      CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED |
 	CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS |
 	CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM |
 	CDC_GENERIC_PACKET,
@@ -165,7 +176,7 @@
 		 */
 		scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
 
-		scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
+		scsi_CDs[MINOR(cdi->dev)].device->sector_size = 2048;
 	}
 	return retval;
 }
@@ -178,7 +189,7 @@
 static void rw_intr(Scsi_Cmnd * SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->this_count;
+	int this_count = SCpnt->bufflen >> 9;
 	int good_sectors = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
 
@@ -191,6 +202,7 @@
 	   avoid unnecessary additional work such as memcpy's that could be avoided.
 	 */
 
+
 	if (driver_byte(result) != 0 &&		/* An error occurred */
 	    SCpnt->sense_buffer[0] == 0xF0 &&	/* Sense data is valid */
 	    (SCpnt->sense_buffer[2] == MEDIUM_ERROR ||
@@ -205,177 +217,169 @@
 			block_sectors = SCpnt->request.bh->b_size >> 9;
 		if (block_sectors < 4)
 			block_sectors = 4;
-		if (scsi_CDs[device_nr].sector_size == 2048)
+		if (scsi_CDs[device_nr].device->sector_size == 2048)
 			error_sector <<= 2;
 		error_sector &= ~(block_sectors - 1);
 		good_sectors = error_sector - SCpnt->request.sector;
 		if (good_sectors < 0 || good_sectors >= this_count)
 			good_sectors = 0;
 		/*
-		   The SCSI specification allows for the value returned by READ
-		   CAPACITY to be up to 75 2K sectors past the last readable
-		   block.  Therefore, if we hit a medium error within the last
-		   75 2K sectors, we decrease the saved size value.
+		 * The SCSI specification allows for the value returned by READ
+		 * CAPACITY to be up to 75 2K sectors past the last readable
+		 * block.  Therefore, if we hit a medium error within the last
+		 * 75 2K sectors, we decrease the saved size value.
 		 */
 		if ((error_sector >> 1) < sr_sizes[device_nr] &&
 		    scsi_CDs[device_nr].capacity - error_sector < 4 * 75)
 			sr_sizes[device_nr] = error_sector >> 1;
 	}
-	if (good_sectors > 0) {	/* Some sectors were read successfully. */
-		if (SCpnt->use_sg == 0) {
-			if (SCpnt->buffer != SCpnt->request.buffer) {
-				int offset;
-				offset = (SCpnt->request.sector % 4) << 9;
-				memcpy((char *) SCpnt->request.buffer,
-				       (char *) SCpnt->buffer + offset,
-				       good_sectors << 9);
-				/* Even though we are not using scatter-gather, we look
-				 * ahead and see if there is a linked request for the
-				 * other half of this buffer.  If there is, then satisfy
-				 * it. */
-				if ((offset == 0) && good_sectors == 2 &&
-				    SCpnt->request.nr_sectors > good_sectors &&
-				    SCpnt->request.bh &&
-				    SCpnt->request.bh->b_reqnext &&
-				    SCpnt->request.bh->b_reqnext->b_size == 1024) {
-					memcpy((char *) SCpnt->request.bh->b_reqnext->b_data,
-					   (char *) SCpnt->buffer + 1024,
-					       1024);
-					good_sectors += 2;
-				};
+	/*
+	 * This calls the generic completion function, now that we know
+	 * how many actual sectors finished, and how many sectors we need
+	 * to say have failed.
+	 */
+	scsi_io_completion(SCpnt, good_sectors, block_sectors);
+}
 
-				scsi_free(SCpnt->buffer, 2048);
-			}
-		} else {
-			struct scatterlist *sgpnt;
-			int i;
-			sgpnt = (struct scatterlist *) SCpnt->buffer;
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (sgpnt[i].alt_address) {
-					if (sgpnt[i].alt_address != sgpnt[i].address) {
-						memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
-					};
-					scsi_free(sgpnt[i].address, sgpnt[i].length);
-				};
-			};
-			scsi_free(SCpnt->buffer, SCpnt->sglist_len);	/* Free list of scatter-gather pointers */
-			if (SCpnt->request.sector % 4)
-				good_sectors -= 2;
-			/* See   if there is a padding record at the end that needs to be removed */
-			if (good_sectors > SCpnt->request.nr_sectors)
-				good_sectors -= 2;
-		};
 
-#ifdef DEBUG
-		printk("(%x %x %x) ", SCpnt->request.bh, SCpnt->request.nr_sectors,
-		       good_sectors);
-#endif
-		if (SCpnt->request.nr_sectors > this_count) {
-			SCpnt->request.errors = 0;
-			if (!SCpnt->request.bh)
-				panic("sr.c: linked page request (%lx %x)",
-				      SCpnt->request.sector, this_count);
-		}
-		SCpnt = end_scsi_request(SCpnt, 1, good_sectors);	/* All done */
-		if (result == 0) {
-			requeue_sr_request(SCpnt);
-			return;
-		}
-	}
-	if (good_sectors == 0) {
-		/* We only come through here if no sectors were read successfully. */
+static request_queue_t *sr_find_queue(kdev_t dev)
+{
+	/*
+	 * No such device
+	 */
+	if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
+		return NULL;
 
-		/* Free up any indirection buffers we allocated for DMA purposes. */
-		if (SCpnt->use_sg) {
-			struct scatterlist *sgpnt;
-			int i;
-			sgpnt = (struct scatterlist *) SCpnt->buffer;
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (sgpnt[i].alt_address) {
-					scsi_free(sgpnt[i].address, sgpnt[i].length);
-				}
-			}
-			scsi_free(SCpnt->buffer, SCpnt->sglist_len);	/* Free list of scatter-gather pointers */
-		} else {
-			if (SCpnt->buffer != SCpnt->request.buffer)
-				scsi_free(SCpnt->buffer, SCpnt->bufflen);
-		}
+	return &scsi_CDs[MINOR(dev)].device->request_queue;
+}
 
+static int sr_init_command(Scsi_Cmnd * SCpnt)
+{
+	int dev, devm, block, this_count;
+
+	devm = MINOR(SCpnt->request.rq_dev);
+	dev = DEVICE_NR(SCpnt->request.rq_dev);
+
+	block = SCpnt->request.sector;
+	this_count = SCpnt->request_bufflen >> 9;
+
+	if (!SCpnt->request.bh) {
+		/*
+		 * Umm, yeah, right.   Swapping to a cdrom.  Nice try.
+		 */
+		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		return 0;
 	}
-	if (driver_byte(result) != 0) {
-		if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {
-			if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
-				/* detected disc change.  set a bit and quietly refuse
-				 * further access.    */
-
-				scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->changed = 1;
-				SCpnt = end_scsi_request(SCpnt, 0, this_count);
-				requeue_sr_request(SCpnt);
-				return;
-			}
-		}
-		if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
-			printk("sr%d: CD-ROM error: ",
-			       DEVICE_NR(SCpnt->request.rq_dev));
-			print_sense("sr", SCpnt);
-			printk("command was: ");
-			print_command(SCpnt->cmnd);
-			if (scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].ten) {
-				scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0;
-				requeue_sr_request(SCpnt);
-				result = 0;
-				return;
-			} else {
-				SCpnt = end_scsi_request(SCpnt, 0, this_count);
-				requeue_sr_request(SCpnt);	/* Do next request */
-				return;
-			}
+	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
 
+	if (dev >= sr_template.nr_dev ||
+	    !scsi_CDs[dev].device ||
+	    !scsi_CDs[dev].device->online) {
+		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request.nr_sectors));
+		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
+		return 0;
+	}
+	if (scsi_CDs[dev].device->changed) {
+		/*
+		 * quietly refuse to do anything to a changed disc until the changed
+		 * bit has been reset
+		 */
+		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
+		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		return 0;
+	}
+	/*
+	 * we do lazy blocksize switching (when reading XA sectors,
+	 * see CDROMREADMODE2 ioctl) 
+	 */
+	if (scsi_CDs[dev].device->sector_size > 2048) {
+		if (!in_interrupt())
+			sr_set_blocklength(DEVICE_NR(CURRENT->rq_dev), 2048);
+		else
+			printk("sr: can't switch blocksize: in interrupt\n");
+	}
+	if (SCpnt->request.cmd == WRITE) {
+		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+		return 0;
+	}
+	if (scsi_CDs[dev].device->sector_size == 1024) {
+		if ((block & 1) || (SCpnt->request.nr_sectors & 1)) {
+			printk("sr.c:Bad 1K block number requested (%d %ld)",
+                               block, SCpnt->request.nr_sectors);
+			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+			return 0;
+		} else {
+			block = block >> 1;
+			this_count = this_count >> 1;
 		}
-		if (SCpnt->sense_buffer[2] == NOT_READY) {
-			printk(KERN_INFO "sr%d: CD-ROM not ready.  Make sure you have a disc in the drive.\n",
-			       DEVICE_NR(SCpnt->request.rq_dev));
-			SCpnt = end_scsi_request(SCpnt, 0, this_count);
-			requeue_sr_request(SCpnt);	/* Do next request */
-			return;
-		}
-		if (SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
-			printk("scsi%d: MEDIUM ERROR on "
-			       "channel %d, id %d, lun %d, CDB: ",
-			       SCpnt->host->host_no, (int) SCpnt->channel,
-			       (int) SCpnt->target, (int) SCpnt->lun);
-			print_command(SCpnt->cmnd);
-			print_sense("sr", SCpnt);
-			SCpnt = end_scsi_request(SCpnt, 0, block_sectors);
-			requeue_sr_request(SCpnt);
-			return;
+	}
+	if (scsi_CDs[dev].device->sector_size == 2048) {
+		if ((block & 3) || (SCpnt->request.nr_sectors & 3)) {
+			printk("sr.c:Bad 2K block number requested (%d %ld)",
+                               block, SCpnt->request.nr_sectors);
+			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+			return 0;
+		} else {
+			block = block >> 2;
+			this_count = this_count >> 2;
 		}
-		if (SCpnt->sense_buffer[2] == VOLUME_OVERFLOW) {
-			printk("scsi%d: VOLUME OVERFLOW on "
-			       "channel %d, id %d, lun %d, CDB: ",
-			       SCpnt->host->host_no, (int) SCpnt->channel,
-			       (int) SCpnt->target, (int) SCpnt->lun);
-			print_command(SCpnt->cmnd);
-			print_sense("sr", SCpnt);
-			SCpnt = end_scsi_request(SCpnt, 0, block_sectors);
-			requeue_sr_request(SCpnt);
-			return;
+	}
+	switch (SCpnt->request.cmd) {
+	case WRITE:
+		if (!scsi_CDs[dev].device->writeable) {
+			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
+			return 0;
 		}
+		SCpnt->cmnd[0] = WRITE_10;
+		break;
+	case READ:
+		SCpnt->cmnd[0] = READ_10;
+		break;
+	default:
+		panic("Unknown sr command %d\n", SCpnt->request.cmd);
 	}
-	/* We only get this far if we have an error we have not recognized */
-	if (result) {
-		printk("SCSI CD error : host %d id %d lun %d return code = %03x\n",
-		       scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->host->host_no,
-		   scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->id,
-		  scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->lun,
-		       result);
 
-		if (status_byte(result) == CHECK_CONDITION)
-			print_sense("sr", SCpnt);
+	SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
+                                   devm,
+		   (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
+				 this_count, SCpnt->request.nr_sectors));
+
+	SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
+
+	if (this_count > 0xffff)
+		this_count = 0xffff;
+
+	SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
+	SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
+	SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
+	SCpnt->cmnd[5] = (unsigned char) block & 0xff;
+	SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
+	SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
+	SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
 
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
-		requeue_sr_request(SCpnt);
-	}
+	/*
+	 * We shouldn't disconnect in the middle of a sector, so with a dumb
+	 * host adapter, it's safe to assume that we can at least transfer
+	 * this many bytes between each connect / disconnect.
+	 */
+	SCpnt->transfersize = scsi_CDs[dev].device->sector_size;
+	SCpnt->underflow = this_count << 9;
+
+	SCpnt->allowed = MAX_RETRIES;
+	SCpnt->timeout_per_command = SR_TIMEOUT;
+
+	/*
+	 * This is the completion routine we use.  This is matched in terms
+	 * of capability to this function.
+	 */
+	SCpnt->done = rw_intr;
+
+	/*
+	 * This indicates that the command is ready from our end to be
+	 * queued.
+	 */
+	return 1;
 }
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -416,390 +420,6 @@
  * translate them to SCSI commands.
  */
 
-static void do_sr_request(void)
-{
-	Scsi_Cmnd *SCpnt = NULL;
-	struct request *req = NULL;
-	Scsi_Device *SDev;
-	int flag = 0;
-
-	while (1 == 1) {
-		if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) {
-			return;
-		};
-
-		INIT_SCSI_REQUEST;
-
-		SDev = scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device;
-
-		/*
-		 * If the host for this device is in error recovery mode, don't
-		 * do anything at all here.  When the host leaves error recovery
-		 * mode, it will automatically restart things and start queueing
-		 * commands again.
-		 */
-		if (SDev->host->in_recovery) {
-			return;
-		}
-		/*
-		 * I am not sure where the best place to do this is.  We need
-		 * to hook in a place where we are likely to come if in user
-		 * space.
-		 */
-		if (SDev->was_reset) {
-			/*
-			 * We need to relock the door, but we might
-			 * be in an interrupt handler.  Only do this
-			 * from user space, since we do not want to
-			 * sleep from an interrupt.
-			 */
-			if (SDev->removable && !in_interrupt()) {
-				spin_unlock_irq(&io_request_lock);	/* FIXME!!!! */
-				scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
-				spin_lock_irq(&io_request_lock);	/* FIXME!!!! */
-				/* scsi_ioctl may allow CURRENT to change, so start over. */
-				SDev->was_reset = 0;
-				continue;
-			}
-			SDev->was_reset = 0;
-		}
-		/* we do lazy blocksize switching (when reading XA sectors,
-		 * see CDROMREADMODE2 ioctl) */
-		if (scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].sector_size > 2048) {
-			if (!in_interrupt())
-				sr_set_blocklength(DEVICE_NR(CURRENT->rq_dev), 2048);
-#if 1
-			else
-				printk("sr: can't switch blocksize: in interrupt\n");
-#endif
-		}
-		if (flag++ == 0)
-			SCpnt = scsi_allocate_device(&CURRENT,
-			 scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device, 0);
-		else
-			SCpnt = NULL;
-
-		/* This is a performance enhancement.  We dig down into the request list and
-		 * try to find a queueable request (i.e. device not busy, and host able to
-		 * accept another command.  If we find one, then we queue it. This can
-		 * make a big difference on systems with more than one disk drive.  We want
-		 * to have the interrupts off when monkeying with the request list, because
-		 * otherwise the kernel might try to slip in a request in between somewhere. */
-
-		if (!SCpnt && sr_template.nr_dev > 1) {
-			struct request *req1;
-			req1 = NULL;
-			req = CURRENT;
-			while (req) {
-				SCpnt = scsi_request_queueable(req,
-				scsi_CDs[DEVICE_NR(req->rq_dev)].device);
-				if (SCpnt)
-					break;
-				req1 = req;
-				req = req->next;
-			}
-			if (SCpnt && req->rq_status == RQ_INACTIVE) {
-				if (req == CURRENT)
-					CURRENT = CURRENT->next;
-				else
-					req1->next = req->next;
-			}
-		}
-		if (!SCpnt)
-			return;	/* Could not find anything to do */
-
-		wake_up(&wait_for_request);
-
-		/* Queue command */
-		requeue_sr_request(SCpnt);
-	}			/* While */
-}
-
-void requeue_sr_request(Scsi_Cmnd * SCpnt)
-{
-	unsigned int dev, block, realcount;
-	unsigned char cmd[10], *buffer, tries;
-	int this_count, start, end_rec;
-
-	tries = 2;
-
-repeat:
-	if (!SCpnt || SCpnt->request.rq_status == RQ_INACTIVE) {
-		do_sr_request();
-		return;
-	}
-	dev = MINOR(SCpnt->request.rq_dev);
-	block = SCpnt->request.sector;
-	buffer = NULL;
-	this_count = 0;
-
-	if (dev >= sr_template.nr_dev) {
-		/* printk("CD-ROM request error: invalid device.\n");                   */
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
-		tries = 2;
-		goto repeat;
-	}
-	if (!scsi_CDs[dev].use) {
-		/* printk("CD-ROM request error: device marked not in use.\n");         */
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
-		tries = 2;
-		goto repeat;
-	}
-	if (!scsi_CDs[dev].device->online) {
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
-		tries = 2;
-		goto repeat;
-	}
-	if (scsi_CDs[dev].device->changed) {
-		/*
-		 * quietly refuse to do anything to a changed disc
-		 * until the changed bit has been reset
-		 */
-		/* printk("CD-ROM has been changed.  Prohibiting further I/O.\n");      */
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
-		tries = 2;
-		goto repeat;
-	}
-	switch (SCpnt->request.cmd) {
-	case WRITE:
-		SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
-		goto repeat;
-		break;
-	case READ:
-		cmd[0] = READ_6;
-		break;
-	default:
-		panic("Unknown sr command %d\n", SCpnt->request.cmd);
-	}
-
-	cmd[1] = (SCpnt->lun << 5) & 0xe0;
-
-	/*
-	 * Now do the grungy work of figuring out which sectors we need, and
-	 * where in memory we are going to put them.
-	 *
-	 * The variables we need are:
-	 *
-	 * this_count= number of 512 byte sectors being read
-	 * block     = starting cdrom sector to read.
-	 * realcount = # of cdrom sectors to read
-	 *
-	 * The major difference between a scsi disk and a scsi cdrom
-	 * is that we will always use scatter-gather if we can, because we can
-	 * work around the fact that the buffer cache has a block size of 1024,
-	 * and we have 2048 byte sectors.  This code should work for buffers that
-	 * are any multiple of 512 bytes long.
-	 */
-
-	SCpnt->use_sg = 0;
-
-	if (SCpnt->host->sg_tablesize > 0 &&
-	    (!scsi_need_isa_buffer ||
-	     scsi_dma_free_sectors >= 10)) {
-		struct buffer_head *bh;
-		struct scatterlist *sgpnt;
-		int count, this_count_max;
-		bh = SCpnt->request.bh;
-		this_count = 0;
-		count = 0;
-		this_count_max = (scsi_CDs[dev].ten ? 0xffff : 0xff) << 4;
-		/* Calculate how many links we can use.  First see if we need
-		 * a padding record at the start */
-		this_count = SCpnt->request.sector % 4;
-		if (this_count)
-			count++;
-		while (bh && count < SCpnt->host->sg_tablesize) {
-			if ((this_count + (bh->b_size >> 9)) > this_count_max)
-				break;
-			this_count += (bh->b_size >> 9);
-			count++;
-			bh = bh->b_reqnext;
-		};
-		/* Fix up in case of an odd record at the end */
-		end_rec = 0;
-		if (this_count % 4) {
-			if (count < SCpnt->host->sg_tablesize) {
-				count++;
-				end_rec = (4 - (this_count % 4)) << 9;
-				this_count += 4 - (this_count % 4);
-			} else {
-				count--;
-				this_count -= (this_count % 4);
-			};
-		};
-		SCpnt->use_sg = count;	/* Number of chains */
-		/* scsi_malloc can only allocate in chunks of 512 bytes */
-		count = (SCpnt->use_sg * sizeof(struct scatterlist) + 511) & ~511;
-
-		SCpnt->sglist_len = count;
-		sgpnt = (struct scatterlist *) scsi_malloc(count);
-		if (!sgpnt) {
-			printk("Warning - running *really* short on DMA buffers\n");
-			SCpnt->use_sg = 0;	/* No memory left - bail out */
-		} else {
-			buffer = (unsigned char *) sgpnt;
-			count = 0;
-			bh = SCpnt->request.bh;
-			if (SCpnt->request.sector % 4) {
-				sgpnt[count].length = (SCpnt->request.sector % 4) << 9;
-				sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length);
-				if (!sgpnt[count].address)
-					panic("SCSI DMA pool exhausted.");
-				sgpnt[count].alt_address = sgpnt[count].address;	/* Flag to delete
-											   if needed */
-				count++;
-			};
-			for (bh = SCpnt->request.bh; count < SCpnt->use_sg;
-			     count++, bh = bh->b_reqnext) {
-				if (bh) {	/* Need a placeholder at the end of the record? */
-					sgpnt[count].address = bh->b_data;
-					sgpnt[count].length = bh->b_size;
-					sgpnt[count].alt_address = NULL;
-				} else {
-					sgpnt[count].address = (char *) scsi_malloc(end_rec);
-					if (!sgpnt[count].address)
-						panic("SCSI DMA pool exhausted.");
-					sgpnt[count].length = end_rec;
-					sgpnt[count].alt_address = sgpnt[count].address;
-					if (count + 1 != SCpnt->use_sg)
-						panic("Bad sr request list");
-					break;
-				};
-				if (virt_to_phys(sgpnt[count].address) + sgpnt[count].length - 1 >
-				    ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) {
-					sgpnt[count].alt_address = sgpnt[count].address;
-					/* We try to avoid exhausting the DMA pool, since it is easier
-					 * to control usage here.  In other places we might have a more
-					 * pressing need, and we would be screwed if we ran out */
-					if (scsi_dma_free_sectors < (sgpnt[count].length >> 9) + 5) {
-						sgpnt[count].address = NULL;
-					} else {
-						sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length);
-					};
-					/* If we start running low on DMA buffers, we abort the scatter-gather
-					 * operation, and free all of the memory we have allocated.  We want to
-					 * ensure that all scsi operations are able to do at least a non-scatter/gather
-					 * operation */
-					if (sgpnt[count].address == NULL) {	/* Out of dma memory */
-						printk("Warning: Running low on SCSI DMA buffers\n");
-						/* Try switching back to a non scatter-gather operation. */
-						while (--count >= 0) {
-							if (sgpnt[count].alt_address)
-								scsi_free(sgpnt[count].address, sgpnt[count].length);
-						};
-						SCpnt->use_sg = 0;
-						scsi_free(buffer, SCpnt->sglist_len);
-						break;
-					};	/* if address == NULL */
-				};	/* if need DMA fixup */
-			};	/* for loop to fill list */
-#ifdef DEBUG
-			printk("SR: %d %d %d %d %d *** ", SCpnt->use_sg, SCpnt->request.sector,
-			       this_count,
-			       SCpnt->request.current_nr_sectors,
-			       SCpnt->request.nr_sectors);
-			for (count = 0; count < SCpnt->use_sg; count++)
-				printk("SGlist: %d %x %x %x\n", count,
-				       sgpnt[count].address,
-				       sgpnt[count].alt_address,
-				       sgpnt[count].length);
-#endif
-		};		/* Able to allocate scatter-gather list */
-	};
-
-	if (SCpnt->use_sg == 0) {
-		/* We cannot use scatter-gather.  Do this the old fashion way */
-		if (!SCpnt->request.bh)
-			this_count = SCpnt->request.nr_sectors;
-		else
-			this_count = (SCpnt->request.bh->b_size >> 9);
-
-		start = block % 4;
-		if (start) {
-			this_count = ((this_count > 4 - start) ?
-				      (4 - start) : (this_count));
-			buffer = (unsigned char *) scsi_malloc(2048);
-		} else if (this_count < 4) {
-			buffer = (unsigned char *) scsi_malloc(2048);
-		} else {
-			this_count -= this_count % 4;
-			buffer = (unsigned char *) SCpnt->request.buffer;
-			if (virt_to_phys(buffer) + (this_count << 9) > ISA_DMA_THRESHOLD &&
-			    SCpnt->host->unchecked_isa_dma)
-				buffer = (unsigned char *) scsi_malloc(this_count << 9);
-		}
-	};
-
-	if (scsi_CDs[dev].sector_size == 2048)
-		block = block >> 2;	/* These are the sectors that the cdrom uses */
-	else
-		block = block & 0xfffffffc;
-
-	realcount = (this_count + 3) / 4;
-
-	if (scsi_CDs[dev].sector_size == 512)
-		realcount = realcount << 2;
-
-	/*
-	 * Note: The scsi standard says that READ_6 is *optional*, while
-	 * READ_10 is mandatory.   Thus there is no point in using
-	 * READ_6.
-	 */
-	if (scsi_CDs[dev].ten) {
-		if (realcount > 0xffff) {
-			realcount = 0xffff;
-			this_count = realcount * (scsi_CDs[dev].sector_size >> 9);
-		}
-		cmd[0] += READ_10 - READ_6;
-		cmd[2] = (unsigned char) (block >> 24) & 0xff;
-		cmd[3] = (unsigned char) (block >> 16) & 0xff;
-		cmd[4] = (unsigned char) (block >> 8) & 0xff;
-		cmd[5] = (unsigned char) block & 0xff;
-		cmd[6] = cmd[9] = 0;
-		cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
-		cmd[8] = (unsigned char) realcount & 0xff;
-	} else {
-		if (realcount > 0xff) {
-			realcount = 0xff;
-			this_count = realcount * (scsi_CDs[dev].sector_size >> 9);
-		}
-		cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
-		cmd[2] = (unsigned char) ((block >> 8) & 0xff);
-		cmd[3] = (unsigned char) block & 0xff;
-		cmd[4] = (unsigned char) realcount;
-		cmd[5] = 0;
-	}
-
-#ifdef DEBUG
-	{
-		int i;
-		printk("ReadCD: %d %d %d %d\n", block, realcount, buffer, this_count);
-		printk("Use sg: %d\n", SCpnt->use_sg);
-		printk("Dumping command: ");
-		for (i = 0; i < 12; i++)
-			printk("%2.2x ", cmd[i]);
-		printk("\n");
-	};
-#endif
-
-	/* Some dumb host adapters can speed transfers by knowing the
-	 * minimum transfersize in advance.
-	 *
-	 * We shouldn't disconnect in the middle of a sector, but the cdrom
-	 * sector size can be larger than the size of a buffer and the
-	 * transfer may be split to the size of a buffer.  So it's safe to
-	 * assume that we can at least transfer the minimum of the buffer
-	 * size (1024) and the sector size between each connect / disconnect.
-	 */
-
-	SCpnt->transfersize = (scsi_CDs[dev].sector_size > 1024) ?
-	    1024 : scsi_CDs[dev].sector_size;
-
-	SCpnt->this_count = this_count;
-	scsi_do_cmd(SCpnt, (void *) cmd, buffer,
-		    realcount * scsi_CDs[dev].sector_size,
-		    rw_intr, SR_TIMEOUT, MAX_RETRIES);
-}
 
 static int sr_detect(Scsi_Device * SDp)
 {
@@ -833,7 +453,7 @@
 	if (i >= sr_template.dev_max)
 		panic("scsi_devices corrupt (sr)");
 
-	SDp->scsi_request_fn = do_sr_request;
+
 	scsi_CDs[i].device = SDp;
 
 	sr_template.nr_dev++;
@@ -860,12 +480,13 @@
 	unsigned char cmd[10];
 	unsigned char *buffer;
 	int the_result, retries;
+	int sector_size;
 	Scsi_Cmnd *SCpnt;
 
-	spin_lock_irq(&io_request_lock);
 	buffer = (unsigned char *) scsi_malloc(512);
-	SCpnt = scsi_allocate_device(NULL, scsi_CDs[i].device, 1);
-	spin_unlock_irq(&io_request_lock);
+
+
+	SCpnt = scsi_allocate_device(scsi_CDs[i].device, 1);
 
 	retries = 3;
 	do {
@@ -879,8 +500,8 @@
 
 		/* Do the command and wait.. */
 
-		scsi_wait_cmd (SCpnt, (void *) cmd, (void *) buffer,
-			512, sr_init_done,  SR_TIMEOUT,	 MAX_RETRIES);
+		scsi_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
+			      512, sr_init_done, SR_TIMEOUT, MAX_RETRIES);
 
 		the_result = SCpnt->result;
 		retries--;
@@ -894,7 +515,7 @@
 
 	if (the_result) {
 		scsi_CDs[i].capacity = 0x1fffff;
-		scsi_CDs[i].sector_size = 2048;		/* A guess, just in case */
+		sector_size = 2048;	/* A guess, just in case */
 		scsi_CDs[i].needs_sector_size = 1;
 	} else {
 #if 0
@@ -905,9 +526,9 @@
 						    (buffer[1] << 16) |
 						    (buffer[2] << 8) |
 						    buffer[3]);
-		scsi_CDs[i].sector_size = (buffer[4] << 24) |
+		sector_size = (buffer[4] << 24) |
 		    (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
-		switch (scsi_CDs[i].sector_size) {
+		switch (sector_size) {
 			/*
 			 * HP 4020i CD-Recorder reports 2340 byte sectors
 			 * Philips CD-Writers report 2352 byte sectors
@@ -917,7 +538,7 @@
 		case 0:
 		case 2340:
 		case 2352:
-			scsi_CDs[i].sector_size = 2048;
+			sector_size = 2048;
 			/* fall through */
 		case 2048:
 			scsi_CDs[i].capacity *= 4;
@@ -926,11 +547,13 @@
 			break;
 		default:
 			printk("sr%d: unsupported sector size %d.\n",
-			       i, scsi_CDs[i].sector_size);
+			       i, sector_size);
 			scsi_CDs[i].capacity = 0;
 			scsi_CDs[i].needs_sector_size = 1;
 		}
 
+		scsi_CDs[i].device->sector_size = sector_size;
+
 		/*
 		 * Add this so that we have the ability to correctly gauge
 		 * what the device is capable of.
@@ -959,9 +582,7 @@
 		""
 	};
 
-	spin_lock_irq(&io_request_lock);
 	buffer = (unsigned char *) scsi_malloc(512);
-	spin_unlock_irq(&io_request_lock);
 	cmd[0] = MODE_SENSE;
 	cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;
 	cmd[2] = 0x2a;
@@ -1008,19 +629,19 @@
 	if ((buffer[n + 3] & 0x1) == 0)
 		/* can't write CD-R media */
 		scsi_CDs[i].cdi.mask |= CDC_CD_R;
-	if ((buffer[n+6] & 0x8) == 0)
+	if ((buffer[n + 6] & 0x8) == 0)
 		/* can't eject */
 		scsi_CDs[i].cdi.mask |= CDC_OPEN_TRAY;
 
-	if ((buffer[n+6] >> 5) == mechtype_individual_changer ||
-	    (buffer[n+6] >> 5) == mechtype_cartridge_changer)
-		scsi_CDs[i].cdi.capacity = 
-			cdrom_number_of_slots(&(scsi_CDs[i].cdi));
+	if ((buffer[n + 6] >> 5) == mechtype_individual_changer ||
+	    (buffer[n + 6] >> 5) == mechtype_cartridge_changer)
+		scsi_CDs[i].cdi.capacity =
+		    cdrom_number_of_slots(&(scsi_CDs[i].cdi));
 	if (scsi_CDs[i].cdi.capacity <= 1)
-                /* not a changer */
+		/* not a changer */
 		scsi_CDs[i].cdi.mask |= CDC_SELECT_DISC;
 	/*else    I don't think it can close its tray
-		scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */
+	   scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */
 
 
 	scsi_free(buffer, 512);
@@ -1036,27 +657,23 @@
 	Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
 	unsigned char *buffer = cgc->buffer;
 	int buflen;
-	int stat;
 
 	/* get the device */
-	SCpnt = scsi_allocate_device(NULL, device, 1);
+	SCpnt = scsi_allocate_device(device, 1);
 	if (SCpnt == NULL)
 		return -ENODEV;	/* this just doesn't seem right /axboe */
 
 	/* use buffer for ISA DMA */
 	buflen = (cgc->buflen + 511) & ~511;
 	if (cgc->buffer && SCpnt->host->unchecked_isa_dma &&
-    	   (virt_to_phys(cgc->buffer) + cgc->buflen - 1 > ISA_DMA_THRESHOLD)) {
-		spin_lock_irq(&io_request_lock);
+	    (virt_to_phys(cgc->buffer) + cgc->buflen - 1 > ISA_DMA_THRESHOLD)) {
 		buffer = scsi_malloc(buflen);
-		spin_unlock_irq(&io_request_lock);
 		if (buffer == NULL) {
 			printk("sr: SCSI DMA pool exhausted.");
 			return -ENOMEM;
 		}
 		memcpy(buffer, cgc->buffer, cgc->buflen);
 	}
-
 	/* set the LUN */
 	cgc->cmd[1] |= device->lun << 5;
 
@@ -1065,10 +682,11 @@
 	/* scsi_do_cmd sets the command length */
 	SCpnt->cmd_len = 0;
 
-	scsi_wait_cmd (SCpnt, (void *)cgc->cmd, (void *)buffer, cgc->buflen,
-		sr_init_done, SR_TIMEOUT, MAX_RETRIES);
+	scsi_wait_cmd(SCpnt, (void *) cgc->cmd, (void *) buffer, cgc->buflen,
+		      sr_init_done, SR_TIMEOUT, MAX_RETRIES);
 
-	stat = SCpnt->result;
+	if ((cgc->stat = SCpnt->result))
+		cgc->sense = (struct request_sense *) SCpnt->sense_buffer;
 
 	/* release */
 	SCpnt->request.rq_dev = MKDEV(0, 0);
@@ -1081,7 +699,8 @@
 		scsi_free(buffer, buflen);
 	}
 
-	return stat;
+
+	return cgc->stat;
 }
 
 static int sr_registered = 0;
@@ -1113,12 +732,18 @@
 	sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
 						 sizeof(int), GFP_ATOMIC);
 
+	sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
+						 sizeof(int), GFP_ATOMIC);
 	/*
 	 * These are good guesses for the time being.
 	 */
 	for (i = 0; i < sr_template.dev_max; i++)
+        {
 		sr_blocksizes[i] = 2048;
+		sr_hardsizes[i] = 2048;
+        }
 	blksize_size[MAJOR_NR] = sr_blocksizes;
+        hardsect_size[MAJOR_NR] = sr_hardsizes;
 	return 0;
 }
 
@@ -1127,7 +752,7 @@
 	int i;
 	char name[6];
 
-	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+	blk_dev[MAJOR_NR].queue = sr_find_queue;
 	blk_size[MAJOR_NR] = sr_sizes;
 
 	for (i = 0; i < sr_template.nr_dev; ++i) {
@@ -1136,7 +761,7 @@
 		if (scsi_CDs[i].capacity)
 			continue;
 		scsi_CDs[i].capacity = 0x1fffff;
-		scsi_CDs[i].sector_size = 2048;		/* A guess, just in case */
+		scsi_CDs[i].device->sector_size = 2048;		/* A guess, just in case */
 		scsi_CDs[i].needs_sector_size = 1;
 		scsi_CDs[i].device->changed = 1;	/* force recheck CD type */
 #if 0
@@ -1145,8 +770,9 @@
 		printk("Scd sectorsize = %d bytes.\n", scsi_CDs[i].sector_size);
 #endif
 		scsi_CDs[i].use = 1;
-		scsi_CDs[i].ten = 1;
-		scsi_CDs[i].remap = 1;
+
+		scsi_CDs[i].device->ten = 1;
+		scsi_CDs[i].device->remap = 1;
 		scsi_CDs[i].readcd_known = 0;
 		scsi_CDs[i].readcd_cdda = 0;
 		sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
@@ -1234,9 +860,12 @@
 
 		scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
 		sr_blocksizes = NULL;
+		scsi_init_free((char *) sr_hardsizes, sr_template.dev_max * sizeof(int));
+		sr_hardsizes = NULL;
 	}
 	blksize_size[MAJOR_NR] = NULL;
-	blk_dev[MAJOR_NR].request_fn = NULL;
+        hardsect_size[MAJOR_NR] = sr_hardsizes;
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	blk_size[MAJOR_NR] = NULL;
 	read_ahead[MAJOR_NR] = 0;
 

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