patch-2.4.21 linux-2.4.21/drivers/scsi/ide-scsi.c

Next file: linux-2.4.21/drivers/scsi/ide-scsi.h
Previous file: linux-2.4.21/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/scsi/ide-scsi.c linux-2.4.21/drivers/scsi/ide-scsi.c
@@ -1,7 +1,8 @@
 /*
- * linux/drivers/scsi/ide-scsi.c	Version 0.9		Jul   4, 1999
+ * linux/drivers/scsi/ide-scsi.c	Version 0.93    June 10, 2002
  *
  * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2001 - 2002 Andre Hedrick <andre@linux-ide.org>
  */
 
 /*
@@ -27,11 +28,19 @@
  *                        detection of devices with CONFIG_SCSI_MULTI_LUN
  * Ver 0.8   Feb 05 99   Optical media need translation too. Reverse 0.7.
  * Ver 0.9   Jul 04 99   Fix a bug in SG_SET_TRANSFORM.
+ * Ver 0.91  Jan 06 02   Added 'ignore' parameter when ide-scsi is a module
+ *                        so that use of scsi emulation can be made independent
+ *                        of load order when other IDE drivers are modules.
+ *                        Chris Ebenezer <chriseb@pobox.com>
+ * Ver 0.92  Mar 21 02   Include DevFs support
+ *                        Borsenkow Andrej <Andrej.Borsenkow@mow.siemens.ru>
+ * Ver 0.93  Jun 10 02   Fix "off by one" error in transforms
  */
 
-#define IDESCSI_VERSION "0.9"
+#define IDESCSI_VERSION "0.93"
 
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
@@ -53,76 +62,77 @@
 #include "ide-scsi.h"
 #include <scsi/sg.h>
 
-#define IDESCSI_DEBUG_LOG		0
+#define IDESCSI_DEBUG_LOG	0
 
 typedef struct idescsi_pc_s {
-	u8 c[12];				/* Actual packet bytes */
-	int request_transfer;			/* Bytes to transfer */
-	int actually_transferred;		/* Bytes actually transferred */
-	int buffer_size;			/* Size of our data buffer */
-	struct request *rq;			/* The corresponding request */
-	byte *buffer;				/* Data buffer */
-	byte *current_position;			/* Pointer into the above buffer */
-	struct scatterlist *sg;			/* Scatter gather table */
-	int b_count;				/* Bytes transferred from current entry */
-	Scsi_Cmnd *scsi_cmd;			/* SCSI command */
-	void (*done)(Scsi_Cmnd *);		/* Scsi completion routine */
-	unsigned long flags;			/* Status/Action flags */
-	unsigned long timeout;			/* Command timeout */
+	u8 c[12];			/* Actual packet bytes */
+	int request_transfer;		/* Bytes to transfer */
+	int actually_transferred;	/* Bytes actually transferred */
+	int buffer_size;		/* Size of our data buffer */
+	struct request *rq;		/* The corresponding request */
+	u8 *buffer;			/* Data buffer */
+	u8 *current_position;		/* Pointer into the above buffer */
+	struct scatterlist *sg;		/* Scatter gather table */
+	int b_count;			/* Bytes transferred from current entry */
+	Scsi_Cmnd *scsi_cmd;		/* SCSI command */
+	void (*done)(Scsi_Cmnd *);	/* Scsi completion routine */
+	unsigned long flags;		/* Status/Action flags */
+	unsigned long timeout;		/* Command timeout */
 } idescsi_pc_t;
 
 /*
  *	Packet command status bits.
  */
-#define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
-#define PC_WRITING			1	/* Data direction */
-#define PC_TRANSFORM			2	/* transform SCSI commands */
+#define PC_DMA_IN_PROGRESS	0	/* 1 while DMA in progress */
+#define PC_WRITING		1	/* Data direction */
+#define PC_TRANSFORM		2	/* transform SCSI commands */
+#define PC_DMA_OK		4	/* Use DMA */
 
 /*
  *	SCSI command transformation layer
  */
-#define IDESCSI_TRANSFORM		0	/* Enable/Disable transformation */
-#define IDESCSI_SG_TRANSFORM		1	/* /dev/sg transformation */
+#define IDESCSI_TRANSFORM	0	/* Enable/Disable transformation */
+#define IDESCSI_SG_TRANSFORM	1	/* /dev/sg transformation */
 
 /*
  *	Log flags
  */
-#define IDESCSI_LOG_CMD			0	/* Log SCSI commands */
+#define IDESCSI_LOG_CMD		0	/* Log SCSI commands */
+
+#define IDESCSI_DEVFS
 
 typedef struct {
 	ide_drive_t *drive;
-	idescsi_pc_t *pc;			/* Current packet command */
-	unsigned long flags;			/* Status/Action flags */
-	unsigned long transform;		/* SCSI cmd translation layer */
-	unsigned long log;			/* log flags */
+	idescsi_pc_t *pc;		/* Current packet command */
+	unsigned long flags;		/* Status/Action flags */
+	unsigned long transform;	/* SCSI cmd translation layer */
+	unsigned long log;		/* log flags */
+	int id;				/* id */
+#ifdef IDESCSI_DEVFS
+	devfs_handle_t de;		/* pointer to IDE device */
+#endif /* IDESCSI_DEVFS */
 } idescsi_scsi_t;
 
 /*
  *	Per ATAPI device status bits.
  */
-#define IDESCSI_DRQ_INTERRUPT		0	/* DRQ interrupt device */
+#define IDESCSI_DRQ_INTERRUPT	0	/* DRQ interrupt device */
 
 /*
  *	ide-scsi requests.
  */
-#define IDESCSI_PC_RQ			90
-
-/*
- *	Bits of the interrupt reason register.
- */
-#define IDESCSI_IREASON_COD	0x1		/* Information transferred is command */
-#define IDESCSI_IREASON_IO	0x2		/* The device requests us to read */
+#define IDESCSI_PC_RQ		90
 
 static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount)
 {
 	while (bcount--)
-		IN_BYTE (IDE_DATA_REG);
+		(void) HWIF(drive)->INB(IDE_DATA_REG);
 }
 
 static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
 {
 	while (bcount--)
-		OUT_BYTE (0, IDE_DATA_REG);
+		HWIF(drive)->OUTB(0, IDE_DATA_REG);
 }
 
 /*
@@ -134,13 +144,15 @@
 
 	while (bcount) {
 		if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
-			printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
-			idescsi_discard_data (drive, bcount);
+			printk(KERN_ERR "ide-scsi: scatter gather "
+				"table too small, discarding data\n");
+			idescsi_discard_data(drive, bcount);
 			return;
 		}
-		count = IDE_MIN (pc->sg->length - pc->b_count, bcount);
-		atapi_input_bytes (drive, pc->sg->address + pc->b_count, count);
-		bcount -= count; pc->b_count += count;
+		count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
+		HWIF(drive)->atapi_input_bytes(drive, pc->sg->address + pc->b_count, count);
+		bcount -= count;
+		pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
 			pc->b_count = 0;
@@ -154,13 +166,15 @@
 
 	while (bcount) {
 		if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
-			printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
-			idescsi_output_zeros (drive, bcount);
+			printk(KERN_ERR "ide-scsi: scatter gather table "
+				"too small, padding with zeros\n");
+			idescsi_output_zeros(drive, bcount);
 			return;
 		}
-		count = IDE_MIN (pc->sg->length - pc->b_count, bcount);
-		atapi_output_bytes (drive, pc->sg->address + pc->b_count, count);
-		bcount -= count; pc->b_count += count;
+		count = IDE_MIN(pc->sg->length - pc->b_count, bcount);
+		HWIF(drive)->atapi_output_bytes(drive, pc->sg->address + pc->b_count, count);
+		bcount -= count;
+		pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
 			pc->b_count = 0;
@@ -181,26 +195,38 @@
 		return;
 	if (drive->media == ide_cdrom || drive->media == ide_optical) {
 		if (c[0] == READ_6 || c[0] == WRITE_6) {
-			c[8] = c[4];		c[5] = c[3];		c[4] = c[2];
-			c[3] = c[1] & 0x1f;	c[2] = 0;		c[1] &= 0xe0;
+			c[8] = c[4];
+			c[5] = c[3];
+			c[4] = c[2];
+			c[3] = c[1] & 0x1f;
+			c[2] = 0;
+			c[1] &= 0xe0;
 			c[0] += (READ_10 - READ_6);
 		}
 		if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
+			unsigned short new_len;
 			if (!scsi_buf)
 				return;
 			if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL)
 				return;
 			memset(atapi_buf, 0, pc->buffer_size + 4);
 			memset (c, 0, 12);
-			c[0] = sc[0] | 0x40;	c[1] = sc[1];		c[2] = sc[2];
-			c[8] = sc[4] + 4;	c[9] = sc[5];
-			if (sc[4] + 4 > 255)
-				c[7] = sc[4] + 4 - 255;
+			c[0] = sc[0] | 0x40;
+			c[1] = sc[1];
+			c[2] = sc[2];
+ 			new_len = sc[4] + 4;
+			c[8] = new_len;
+			c[7] = new_len >> 8;
+			c[9] = sc[5];
 			if (c[0] == MODE_SELECT_10) {
-				atapi_buf[1] = scsi_buf[0];	/* Mode data length */
-				atapi_buf[2] = scsi_buf[1];	/* Medium type */
-				atapi_buf[3] = scsi_buf[2];	/* Device specific parameter */
-				atapi_buf[7] = scsi_buf[3];	/* Block descriptor length */
+				/* Mode data length */
+				atapi_buf[1] = scsi_buf[0];
+				/* Medium type */
+				atapi_buf[2] = scsi_buf[1];
+				/* Device specific parameter */
+				atapi_buf[3] = scsi_buf[2];
+				/* Block descriptor length */
+				atapi_buf[7] = scsi_buf[3];
 				memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4);
 			}
 			pc->buffer = atapi_buf;
@@ -220,15 +246,21 @@
 		return;
 	if (drive->media == ide_cdrom || drive->media == ide_optical) {
 		if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
-			scsi_buf[0] = atapi_buf[1];		/* Mode data length */
-			scsi_buf[1] = atapi_buf[2];		/* Medium type */
-			scsi_buf[2] = atapi_buf[3];		/* Device specific parameter */
-			scsi_buf[3] = atapi_buf[7];		/* Block descriptor length */
+			/* Mode data length */
+			scsi_buf[0] = atapi_buf[1];
+			/* Medium type */
+			scsi_buf[1] = atapi_buf[2];
+			/* Device specific parameter */
+			scsi_buf[2] = atapi_buf[3];
+			/* Block descriptor length */
+			scsi_buf[3] = atapi_buf[7];
 			memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8);
 		}
 		if (pc->c[0] == INQUIRY) {
-			scsi_buf[2] |= 2;			/* ansi_revision */
-			scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;	/* response data format */
+			/* ansi_revision */
+			scsi_buf[2] |= 2;
+			/* response data format */
+			scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
 		}
 	}
 	if (atapi_buf && atapi_buf != scsi_buf)
@@ -256,47 +288,83 @@
 	printk("]\n");
 }
 
-static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
+static int idescsi_do_end_request (ide_drive_t *drive, int uptodate)
+{
+	struct request *rq;
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	rq = HWGROUP(drive)->rq;
+
+	/*
+	 * decide whether to reenable DMA -- 3 is a random magic for now,
+	 * if we DMA timeout more than 3 times, just stay in PIO
+	 */
+	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+		drive->state = 0;
+		HWGROUP(drive)->hwif->ide_dma_on(drive);
+	}
+
+	if (!end_that_request_first(rq, uptodate, drive->name)) {
+		add_blkdev_randomness(MAJOR(rq->rq_dev));
+		blkdev_dequeue_request(rq);
+		HWGROUP(drive)->rq = NULL;
+		end_that_request_last(rq);
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	return ret;
+}
+
+static int idescsi_end_request (ide_drive_t *drive, int uptodate)
 {
-	ide_drive_t *drive = hwgroup->drive;
 	idescsi_scsi_t *scsi = drive->driver_data;
-	struct request *rq = hwgroup->rq;
-	idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer;
+	struct request *rq = HWGROUP(drive)->rq;
+	idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
 	u8 *scsi_buf;
 	unsigned long flags;
 
 	if (rq->cmd != IDESCSI_PC_RQ) {
-		ide_end_request (uptodate, hwgroup);
-		return;
+		idescsi_do_end_request(drive, uptodate);
+		return 0;
 	}
-	ide_end_drive_cmd (drive, 0, 0);
+	ide_end_drive_cmd(drive, 0, 0);
 	if (rq->errors >= ERROR_MAX) {
 		pc->scsi_cmd->result = DID_ERROR << 16;
 		if (log)
-			printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
+			printk("ide-scsi: %s: I/O error for %lu\n",
+				drive->name, pc->scsi_cmd->serial_number);
 	} else if (rq->errors) {
 		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
 		if (log)
-			printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
+			printk("ide-scsi: %s: check condition for %lu\n",
+				drive->name, pc->scsi_cmd->serial_number);
 	} else {
 		pc->scsi_cmd->result = DID_OK << 16;
-		idescsi_transform_pc2 (drive, pc);
+		idescsi_transform_pc2(drive, pc);
 		if (log) {
-			printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number);
-			if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) {
+			printk("ide-scsi: %s: suc %lu", drive->name,
+				pc->scsi_cmd->serial_number);
+			if (!test_bit(PC_WRITING, &pc->flags) &&
+			    pc->actually_transferred &&
+			    pc->actually_transferred <= 1024 &&
+			    pc->buffer) {
 				printk(", rst = ");
 				scsi_buf = pc->scsi_cmd->request_buffer;
 				hexdump(scsi_buf, IDE_MIN(16, pc->scsi_cmd->request_bufflen));
 			} else printk("\n");
 		}
 	}
-	spin_lock_irqsave(&io_request_lock,flags);	
+	spin_lock_irqsave(&io_request_lock, flags);	
 	pc->done(pc->scsi_cmd);
-	spin_unlock_irqrestore(&io_request_lock,flags);
-	idescsi_free_bh (rq->bh);
-	kfree(pc); kfree(rq);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	idescsi_free_bh(rq->bh);
+	kfree(pc);
+	kfree(rq);
 	scsi->pc = NULL;
+	return 0;
 }
 
 static inline unsigned long get_timeout(idescsi_pc_t *pc)
@@ -310,84 +378,112 @@
 static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
-	byte status, ireason;
-	int bcount;
-	idescsi_pc_t *pc=scsi->pc;
+	idescsi_pc_t *pc = scsi->pc;
 	struct request *rq = pc->rq;
+	atapi_bcount_t bcount;
+	atapi_status_t status;
+	atapi_ireason_t ireason;
+	atapi_feature_t feature;
 	unsigned int temp;
 
 #if IDESCSI_DEBUG_LOG
-	printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
+	printk(KERN_INFO "ide-scsi: Reached idescsi_pc_intr "
+		"interrupt handler\n");
 #endif /* IDESCSI_DEBUG_LOG */
 
-	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
+	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 #if IDESCSI_DEBUG_LOG
-		printk ("ide-scsi: %s: DMA complete\n", drive->name);
+		printk("ide-scsi: %s: DMA complete\n", drive->name);
 #endif /* IDESCSI_DEBUG_LOG */
-		pc->actually_transferred=pc->request_transfer;
-		(void) (HWIF(drive)->dmaproc(ide_dma_end, drive));
+		pc->actually_transferred = pc->request_transfer;
+		(void) (HWIF(drive)->ide_dma_end(drive));
 	}
 
-	status = GET_STAT();						/* Clear the interrupt */
+	feature.all = 0;
+	/* Clear the interrupt */
+	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
 
-	if ((status & DRQ_STAT) == 0) {					/* No more interrupts */
+	if (!status.b.drq) {
+		/* No more interrupts */
 		if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
-			printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-		ide__sti();
-		if (status & ERR_STAT)
+			printk(KERN_INFO "Packet command completed, %d "
+				"bytes transferred\n",
+				pc->actually_transferred);
+		local_irq_enable();
+		if (status.b.check)
 			rq->errors++;
-		idescsi_end_request (1, HWGROUP(drive));
+		idescsi_end_request(drive, 1);
 		return ide_stopped;
 	}
-	bcount = IN_BYTE (IDE_BCOUNTH_REG) << 8 | IN_BYTE (IDE_BCOUNTL_REG);
-	ireason = IN_BYTE (IDE_IREASON_REG);
 
-	if (ireason & IDESCSI_IREASON_COD) {
-		printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
-		return ide_do_reset (drive);
-	}
-	if (ireason & IDESCSI_IREASON_IO) {
-		temp = pc->actually_transferred + bcount;
-		if ( temp > pc->request_transfer) {
+	bcount.b.low	= HWIF(drive)->INB(IDE_BCOUNTL_REG);
+	bcount.b.high	= HWIF(drive)->INB(IDE_BCOUNTH_REG);
+	ireason.all	= HWIF(drive)->INB(IDE_IREASON_REG);
+
+	if (ireason.b.cod) {
+		printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
+		return ide_do_reset(drive);
+	}
+	if (ireason.b.io) {
+		temp = pc->actually_transferred + bcount.all;
+		if (temp > pc->request_transfer) {
 			if (temp > pc->buffer_size) {
-				printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n");
+				printk(KERN_ERR "ide-scsi: The scsi wants to "
+					"send us more data than expected "
+					"- discarding data\n");
+				printk(KERN_ERR "ide-scsi: [");
+				hexdump(pc->c, 12);
+				printk("]\n");
+				printk(KERN_ERR "ide-scsi: expected %d got %d limit %d\n",
+					pc->request_transfer, temp, pc->buffer_size);
 				temp = pc->buffer_size - pc->actually_transferred;
 				if (temp) {
 					clear_bit(PC_WRITING, &pc->flags);
 					if (pc->sg)
 						idescsi_input_buffers(drive, pc, temp);
 					else
-						atapi_input_bytes(drive, pc->current_position, temp);
-					printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount);
+						HWIF(drive)->atapi_input_bytes(drive, pc->current_position, temp);
+					printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount.all);
 				}
 				pc->actually_transferred += temp;
 				pc->current_position += temp;
-				idescsi_discard_data (drive,bcount - temp);
-				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+				idescsi_discard_data(drive, bcount.all - temp);
+				if (HWGROUP(drive)->handler != NULL)
+					BUG();
+				ide_set_handler(drive,
+						&idescsi_pc_intr,
+						get_timeout(pc),
+						NULL);
 				return ide_started;
 			}
 #if IDESCSI_DEBUG_LOG
-			printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n");
+			printk(KERN_NOTICE "ide-scsi: The scsi wants to send "
+				"us more data than expected - "
+				"allowing transfer\n");
 #endif /* IDESCSI_DEBUG_LOG */
 		}
 	}
-	if (ireason & IDESCSI_IREASON_IO) {
+	if (ireason.b.io) {
 		clear_bit(PC_WRITING, &pc->flags);
 		if (pc->sg)
-			idescsi_input_buffers (drive, pc, bcount);
+			idescsi_input_buffers(drive, pc, bcount.all);
 		else
-			atapi_input_bytes (drive,pc->current_position,bcount);
+			HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
 	} else {
 		set_bit(PC_WRITING, &pc->flags);
 		if (pc->sg)
-			idescsi_output_buffers (drive, pc, bcount);
+			idescsi_output_buffers(drive, pc, bcount.all);
 		else
-			atapi_output_bytes (drive,pc->current_position,bcount);
+			HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
 	}
-	pc->actually_transferred+=bcount;				/* Update the current position */
-	pc->current_position+=bcount;
-
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);	/* And set the interrupt handler again */
+	/* Update the current position */
+	pc->actually_transferred += bcount.all;
+	pc->current_position += bcount.all;
+
+	if (HWGROUP(drive)->handler != NULL)
+		BUG();
+	/* And set the interrupt handler again */
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
 	return ide_started;
 }
 
@@ -395,20 +491,33 @@
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
 	idescsi_pc_t *pc = scsi->pc;
-	byte ireason;
+	atapi_ireason_t ireason;
 	ide_startstop_t startstop;
 
-	if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
-		printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n");
+	if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+		printk(KERN_ERR "ide-scsi: Strange, packet command "
+			"initiated yet DRQ isn't asserted\n");
 		return startstop;
 	}
-	ireason = IN_BYTE (IDE_IREASON_REG);
-	if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) {
-		printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n");
-		return ide_do_reset (drive);
+
+	ireason.all	= HWIF(drive)->INB(IDE_IREASON_REG);
+
+	if (!ireason.b.cod || ireason.b.io) {
+		printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
+				"issuing a packet command\n");
+		return ide_do_reset(drive);
+	}
+
+	if (HWGROUP(drive)->handler != NULL)
+		BUG();
+	/* Set the interrupt routine */
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+	/* Send the actual packet */
+	HWIF(drive)->atapi_output_bytes(drive, scsi->pc->c, 12);
+	if (test_bit (PC_DMA_OK, &pc->flags)) {
+		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+		(void) (HWIF(drive)->ide_dma_begin(drive));
 	}
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);	/* Set the interrupt routine */
-	atapi_output_bytes (drive, scsi->pc->c, 12);			/* Send the actual packet */
 	return ide_started;
 }
 
@@ -418,36 +527,49 @@
 static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
-	int bcount;
+	atapi_feature_t feature;
+	atapi_bcount_t bcount;
 	struct request *rq = pc->rq;
-	int dma_ok = 0;
-
-	scsi->pc=pc;							/* Set the current packet command */
-	pc->actually_transferred=0;					/* We haven't transferred any data yet */
-	pc->current_position=pc->buffer;
-	bcount = IDE_MIN (pc->request_transfer, 63 * 1024);		/* Request to transfer the entire buffer at once */
 
-	if (drive->using_dma && rq->bh)
-		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+	/* Set the current packet command */
+	scsi->pc = pc;
+	/* We haven't transferred any data yet */
+	pc->actually_transferred = 0;
+	pc->current_position = pc->buffer;
+	/* Request to transfer the entire buffer at once */
+	bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
+
+	if (drive->using_dma && rq->bh) {
+		if (test_bit(PC_WRITING, &pc->flags))
+			feature.b.dma = !HWIF(drive)->ide_dma_write(drive);
+		else
+			feature.b.dma = !HWIF(drive)->ide_dma_read(drive);
+	}
 
-	SELECT_DRIVE(HWIF(drive), drive);
+	SELECT_DRIVE(drive);
 	if (IDE_CONTROL_REG)
-		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
-	OUT_BYTE (dma_ok,IDE_FEATURE_REG);
-	OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG);
-	OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG);
-
-	if (dma_ok) {
-		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
-	}
-	if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
-		ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL);
-		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */
+		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
+	HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
+	HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
+	HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
+
+	if (feature.b.dma) {
+		set_bit(PC_DMA_OK, &pc->flags);
+	}
+	if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
+		if (HWGROUP(drive)->handler != NULL)
+			BUG();
+		ide_set_handler(drive,
+				&idescsi_transfer_pc,
+				get_timeout(pc),
+				NULL);
+		/* Issue the packet command */
+		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
 	} else {
-		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
-		return idescsi_transfer_pc (drive);
+		/* Issue the packet command */
+		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
+		return idescsi_transfer_pc(drive);
 	}
 }
 
@@ -457,19 +579,30 @@
 static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
 #if IDESCSI_DEBUG_LOG
-	printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
-	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
+	printk(KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",
+		rq->rq_status, (unsigned int) rq->rq_dev, rq->cmd, rq->errors);
+	printk(KERN_INFO "sector: %ld, nr_sectors: %ld, "
+		"current_nr_sectors: %ld\n", rq->sector,
+		rq->nr_sectors, rq->current_nr_sectors);
 #endif /* IDESCSI_DEBUG_LOG */
 
 	if (rq->cmd == IDESCSI_PC_RQ) {
-		return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer);
+		return idescsi_issue_pc(drive, rq->special);
 	}
-	printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd);
-	idescsi_end_request (0,HWGROUP (drive));
+	printk(KERN_ERR "ide-scsi: %s: unsupported command in request "
+		"queue (%x)\n", drive->name, rq->cmd);
+	idescsi_end_request(drive, 0);
 	return ide_stopped;
 }
 
-static int idescsi_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
+static int idescsi_do_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	/* need to figure out how to parse scsi-atapi media type */
+
+	return -EINVAL;
+}
+
+static int idescsi_ide_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -482,6 +615,7 @@
 
 static ide_drive_t *idescsi_drives[MAX_HWIFS * MAX_DRIVES];
 static int idescsi_initialized = 0;
+static int drive_count = 0;
 
 static void idescsi_add_settings(ide_drive_t *drive)
 {
@@ -502,34 +636,58 @@
  */
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id)
 {
+	int minor = (drive->select.b.unit) << PARTN_BITS;
+
 	DRIVER(drive)->busy++;
 	idescsi_drives[id] = drive;
 	drive->driver_data = scsi;
 	drive->ready_stat = 0;
-	memset (scsi, 0, sizeof (idescsi_scsi_t));
+	memset(scsi, 0, sizeof(idescsi_scsi_t));
 	scsi->drive = drive;
+	scsi->id = id;
 	if (drive->id && (drive->id->config & 0x0060) == 0x20)
-		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+		set_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags);
 	set_bit(IDESCSI_TRANSFORM, &scsi->transform);
 	clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
 	set_bit(IDESCSI_LOG_CMD, &scsi->log);
 #endif /* IDESCSI_DEBUG_LOG */
 	idescsi_add_settings(drive);
+#ifdef IDESCSI_DEVFS
+	scsi->de = devfs_register(drive->de, "generic", DEVFS_FL_DEFAULT,
+					HWIF(drive)->major, minor,
+					S_IFBLK | S_IRUSR | S_IWUSR,
+					ide_fops, NULL);
+#endif /* IDESCSI_DEVFS */
+	drive_count++;
+	DRIVER(drive)->busy--;
 }
 
 static int idescsi_cleanup (ide_drive_t *drive)
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
 
-	if (ide_unregister_subdriver (drive))
+	if (ide_unregister_subdriver(drive)) {
+		printk("%s: %s: failed to unregister! \n",
+			__FUNCTION__, drive->name);
+		printk("%s: usage %d, busy %d, driver %p, Dbusy %d\n",
+			drive->name, drive->usage, drive->busy,
+			drive->driver, DRIVER(drive)->busy);
 		return 1;
+	}
+	idescsi_drives[scsi->id] = NULL;
+#ifdef IDESCSI_DEVFS
+	if (scsi->de)
+		devfs_unregister(scsi->de);
+#endif /* IDESCSI_DEVFS */
 	drive->driver_data = NULL;
-	kfree (scsi);
+	kfree(scsi);
+	drive_count--;
 	return 0;
 }
 
-int idescsi_reinit(ide_drive_t *drive);
+int idescsi_init(void);
+int idescsi_attach(ide_drive_t *drive);
 
 /*
  *	IDE subdriver functions, registered with ide.c
@@ -539,15 +697,23 @@
 	version:		IDESCSI_VERSION,
 	media:			ide_scsi,
 	busy:			0,
+#ifdef CONFIG_IDEDMA_ONLYDISK
+	supports_dma:		0,
+#else
 	supports_dma:		1,
+#endif
 	supports_dsc_overlap:	0,
 	cleanup:		idescsi_cleanup,
 	standby:		NULL,
+	suspend:		NULL,
+	resume:			NULL,
 	flushcache:		NULL,
 	do_request:		idescsi_do_request,
 	end_request:		idescsi_end_request,
-	ioctl:			NULL,
-	open:			idescsi_open,
+	sense:			NULL,
+	error:			NULL,
+	ioctl:			idescsi_do_ioctl,
+	open:			idescsi_ide_open,
 	release:		idescsi_ide_release,
 	media_change:		NULL,
 	revalidate:		NULL,
@@ -555,12 +721,12 @@
 	capacity:		NULL,
 	special:		NULL,
 	proc:			NULL,
-	reinit:			idescsi_reinit,
+	init:			idescsi_init,
+	attach:			idescsi_attach,
 	ata_prebuilder:		NULL,
 	atapi_prebuilder:	NULL,
 };
 
-int idescsi_init (void);
 static ide_module_t idescsi_module = {
 	IDE_DRIVER_MODULE,
 	idescsi_init,
@@ -568,51 +734,91 @@
 	NULL
 };
 
-int idescsi_reinit (ide_drive_t *drive)
+int idescsi_attach (ide_drive_t *drive)
 {
-#if 0
 	idescsi_scsi_t *scsi;
-	byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255};
-	int i, failed, id;
-
-	if (!idescsi_initialized)
-		return 0;
-	for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++)
-		idescsi_drives[i] = NULL;
+	u8 media[] = {	TYPE_DISK,		/* 0x00 */
+			TYPE_TAPE,		/* 0x01 */
+			TYPE_PRINTER,		/* 0x02 */
+			TYPE_PROCESSOR,		/* 0x03 */
+			TYPE_WORM,		/* 0x04 */
+			TYPE_ROM,		/* 0x05 */
+			TYPE_SCANNER,		/* 0x06 */
+			TYPE_MOD,		/* 0x07 */
+			255};
+	int i = 0, ret = 0, id = 0;
+//	int id = 2 * HWIF(drive)->index + drive->select.b.unit;
+//	int id = drive_count + 1;
+
+	for (id = 0; id < MAX_HWIFS*MAX_DRIVES; id++)
+		if (idescsi_drives[id] == NULL)
+			break;
+
+	printk("%s: id = %d\n", drive->name, id);
+
+	if ((!idescsi_initialized) || (drive->media == ide_disk)) {
+		printk(KERN_ERR "ide-scsi: (%sinitialized) %s: "
+				"media-type (%ssupported)\n",
+			(idescsi_initialized) ? "" : "! ",
+			drive->name,
+			(drive->media == ide_disk) ? "! " : "");
+		return (drive->media == ide_disk) ? 2 : 0;
+	}
 
 	MOD_INC_USE_COUNT;
+
 	for (i = 0; media[i] != 255; i++) {
-		failed = 0;
-		while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) {
+		if (drive->media != media[i])
+			continue;
+		else
+			break;
+	}
 
-			if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) {
-				printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name);
-				continue;
-			}
-			if (ide_register_subdriver (drive, &idescsi_driver, IDE_SUBDRIVER_VERSION)) {
-				printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
-				kfree (scsi);
-				continue;
-			}
-			for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++);
-				idescsi_setup (drive, scsi, id);
-			failed--;
-		}
+	if ((scsi = (idescsi_scsi_t *) kmalloc(sizeof(idescsi_scsi_t), GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "ide-scsi: %s: Can't allocate a scsi "
+			"structure\n", drive->name);
+		ret = 1;
+		goto bye_game_over;
 	}
-	ide_register_module(&idescsi_module);
+	if (ide_register_subdriver(drive, &idescsi_driver,
+			IDE_SUBDRIVER_VERSION)) {
+		printk(KERN_ERR "ide-scsi: %s: Failed to register the "
+			"driver with ide.c\n", drive->name);
+		kfree(scsi);
+		ret = 1;
+		goto bye_game_over;
+	}
+
+	idescsi_setup(drive, scsi, id);
+
+//	scan_scsis(HBA, 1, channel, id, lun);
+bye_game_over:
 	MOD_DEC_USE_COUNT;
-#endif
-	return 0;
+	return ret;
 }
 
-/*
- *	idescsi_init will register the driver for each scsi.
- */
+#ifdef MODULE
+/* options */
+char *ignore = NULL;
+
+MODULE_PARM(ignore, "s");
+#endif
+
 int idescsi_init (void)
 {
+#ifdef CLASSIC_BUILTINS_METHOD
 	ide_drive_t *drive;
 	idescsi_scsi_t *scsi;
-	byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255};
+	u8 media[] = {  TYPE_DISK,		/* 0x00 */
+			TYPE_TAPE,		/* 0x01 */
+			TYPE_PRINTER,		/* 0x02 */
+			TYPE_PROCESSOR,		/* 0x03 */
+			TYPE_WORM,		/* 0x04 */
+			TYPE_ROM,		/* 0x05 */
+			TYPE_SCANNER,		/* 0x06 */
+			TYPE_MOD,		/* 0x07 */
+			255};
+
 	int i, failed, id;
 
 	if (idescsi_initialized)
@@ -623,22 +829,47 @@
 	MOD_INC_USE_COUNT;
 	for (i = 0; media[i] != 255; i++) {
 		failed = 0;
-		while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) {
+		while ((drive = ide_scan_devices(media[i],
+				idescsi_driver.name, NULL, failed++)) != NULL) {
+#ifdef MODULE
+			/* skip drives we were told to ignore */
+			if (ignore != NULL && strstr(ignore, drive->name)) {
+				printk("ide-scsi: ignoring drive %s\n",
+					drive->name);
+				continue;
+			}
+#endif
 
-			if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) {
-				printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name);
+		if ((scsi = (idescsi_scsi_t *) kmalloc(sizeof(idescsi_scsi_t), GFP_KERNEL)) == NULL) {
+				printk(KERN_ERR "ide-scsi: %s: Can't allocate "
+					"a scsi structure\n", drive->name);
 				continue;
 			}
-			if (ide_register_subdriver (drive, &idescsi_driver, IDE_SUBDRIVER_VERSION)) {
-				printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
-				kfree (scsi);
+			if (ide_register_subdriver(drive, &idescsi_driver,
+					IDE_SUBDRIVER_VERSION)) {
+				printk(KERN_ERR "ide-scsi: %s: Failed to "
+					"register the driver with ide.c\n",
+					drive->name);
+				kfree(scsi);
 				continue;
 			}
-			for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++);
-				idescsi_setup (drive, scsi, id);
+			for (id = 0;
+				id < MAX_HWIFS*MAX_DRIVES && idescsi_drives[id];
+					id++);
+				idescsi_setup(drive, scsi, id);
 			failed--;
 		}
 	}
+#else /* ! CLASSIC_BUILTINS_METHOD */
+	int i;
+
+	if (idescsi_initialized)
+		return 0;
+	idescsi_initialized = 1;
+	for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++)
+		idescsi_drives[i] = NULL;
+	MOD_INC_USE_COUNT;
+#endif /* CLASSIC_BUILTINS_METHOD */
 	ide_register_module(&idescsi_module);
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -652,9 +883,11 @@
 
 	host_template->proc_name = "ide-scsi";
 	host = scsi_register(host_template, 0);
-	if(host == NULL)
+	if (host == NULL) {
+		printk(KERN_WARNING "%s: host failure!\n", __FUNCTION__);
 		return 0;
-		
+	}
+
 	for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++)
 		last_lun = IDE_MAX(last_lun, idescsi_drives[id]->last_lun);
 	host->max_id = id;
@@ -671,7 +904,7 @@
 	for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
 		drive = idescsi_drives[id];
 		if (drive)
-			DRIVER(drive)->busy--;
+			DRIVER(drive)->busy = 0;
 	}
 	return 0;
 }
@@ -701,32 +934,36 @@
 {
 	struct buffer_head *bh, *bhp, *first_bh;
 
-	if ((first_bh = bhp = bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
+	if ((first_bh = bhp = bh = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
 		goto abort;
-	memset (bh, 0, sizeof (struct buffer_head));
+	memset(bh, 0, sizeof(struct buffer_head));
 	bh->b_reqnext = NULL;
 	while (--count) {
-		if ((bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
+		if ((bh = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
 			goto abort;
-		memset (bh, 0, sizeof (struct buffer_head));
+		memset(bh, 0, sizeof(struct buffer_head));
 		bhp->b_reqnext = bh;
 		bhp = bh;
 		bh->b_reqnext = NULL;
 	}
 	return first_bh;
 abort:
-	idescsi_free_bh (first_bh);
+	idescsi_free_bh(first_bh);
 	return NULL;
 }
 
 static inline int idescsi_set_direction (idescsi_pc_t *pc)
 {
 	switch (pc->c[0]) {
-		case READ_6: case READ_10: case READ_12:
-			clear_bit (PC_WRITING, &pc->flags);
+		case READ_6:
+		case READ_10:
+		case READ_12:
+			clear_bit(PC_WRITING, &pc->flags);
 			return 0;
-		case WRITE_6: case WRITE_10: case WRITE_12:
-			set_bit (PC_WRITING, &pc->flags);
+		case WRITE_6:
+		case WRITE_10:
+		case WRITE_12:
+			set_bit(PC_WRITING, &pc->flags);
 			return 0;
 		default:
 			return 1;
@@ -744,12 +981,17 @@
 	if (idescsi_set_direction(pc))
 		return NULL;
 	if (segments) {
-		if ((first_bh = bh = idescsi_kmalloc_bh (segments)) == NULL)
+		if ((first_bh = bh = idescsi_kmalloc_bh(segments)) == NULL)
 			return NULL;
 #if IDESCSI_DEBUG_LOG
-		printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10);
+		printk("ide-scsi: %s: building DMA table, %d segments, "
+			"%dkB total\n", drive->name, segments,
+			pc->request_transfer >> 10);
 #endif /* IDESCSI_DEBUG_LOG */
 		while (segments--) {
+#if 1
+			bh->b_data = sg->address;
+#else
 			if (sg->address) {
 				bh->b_page = virt_to_page(sg->address);
 				bh->b_data = (char *) ((unsigned long) sg->address & ~PAGE_MASK);
@@ -757,7 +999,7 @@
 				bh->b_page = sg->page;
 				bh->b_data = (char *) sg->offset;
 			}
-
+#endif
 			bh->b_size = sg->length;
 			bh = bh->b_reqnext;
 			sg++;
@@ -766,10 +1008,12 @@
 		/*
 		 * non-sg requests are guarenteed not to reside in highmem /jens
 		 */
-		if ((first_bh = bh = idescsi_kmalloc_bh (1)) == NULL)
+		if ((first_bh = bh = idescsi_kmalloc_bh(1)) == NULL)
 			return NULL;
 #if IDESCSI_DEBUG_LOG
-		printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10);
+		printk("ide-scsi: %s: building DMA table for a single "
+			"buffer (%dkB)\n", drive->name,
+			pc->request_transfer >> 10);
 #endif /* IDESCSI_DEBUG_LOG */
 		bh->b_data = pc->scsi_cmd->request_buffer;
 		bh->b_size = pc->request_transfer;
@@ -794,21 +1038,22 @@
 	idescsi_pc_t *pc = NULL;
 
 	if (!drive) {
-		printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target);
+		printk(KERN_ERR "ide-scsi: drive id %d not present\n",
+			cmd->target);
 		goto abort;
 	}
 	scsi = drive->driver_data;
-	pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
-	rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
+	pc = kmalloc(sizeof(idescsi_pc_t), GFP_ATOMIC);
+	rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
 	if (rq == NULL || pc == NULL) {
-		printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
+		printk(KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
 		goto abort;
 	}
 
-	memset (pc->c, 0, 12);
+	memset(pc->c, 0, 12);
 	pc->flags = 0;
 	pc->rq = rq;
-	memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
+	memcpy(pc->c, cmd->cmnd, cmd->cmd_len);
 	if (cmd->use_sg) {
 		pc->buffer = NULL;
 		pc->sg = cmd->request_buffer;
@@ -824,28 +1069,30 @@
 
 	if (should_transform(drive, cmd))
 		set_bit(PC_TRANSFORM, &pc->flags);
-	idescsi_transform_pc1 (drive, pc);
+	idescsi_transform_pc1(drive, pc);
 
 	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
-		printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
+		printk("ide-scsi: %s: que %lu, cmd = ",
+			drive->name, cmd->serial_number);
 		hexdump(cmd->cmnd, cmd->cmd_len);
 		if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
-			printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
+			printk("ide-scsi: %s: que %lu, tsl = ",
+				drive->name, cmd->serial_number);
 			hexdump(pc->c, 12);
 		}
 	}
 
-	ide_init_drive_cmd (rq);
-	rq->buffer = (char *) pc;
-	rq->bh = idescsi_dma_bh (drive, pc);
+	ide_init_drive_cmd(rq);
+	rq->special = pc;
+	rq->bh = idescsi_dma_bh(drive, pc);
 	rq->cmd = IDESCSI_PC_RQ;
 	spin_unlock_irq(&io_request_lock);
-	(void) ide_do_drive_cmd (drive, rq, ide_end);
+	(void) ide_do_drive_cmd(drive, rq, ide_end);
 	spin_lock_irq(&io_request_lock);
 	return 0;
 abort:
-	if (pc) kfree (pc);
-	if (rq) kfree (rq);
+	if (pc) kfree(pc);
+	if (rq) kfree(rq);
 	cmd->result = DID_ERROR << 16;
 	done(cmd);
 	return 0;
@@ -858,6 +1105,14 @@
 
 int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags)
 {
+	ide_drive_t *drive	= idescsi_drives[cmd->target];
+
+	/* We cannot reset the interface holding the lock. We can
+	   drop the lock here however */
+	   
+	spin_unlock(&io_request_lock);
+	(void) ide_do_reset(drive);
+	spin_lock(&io_request_lock);
 	return SCSI_RESET_SUCCESS;
 }
 
@@ -877,24 +1132,25 @@
 
 static int __init init_idescsi_module(void)
 {
+	drive_count = 0;
 	idescsi_init();
 	idescsi_template.module = THIS_MODULE;
-	scsi_register_module (MODULE_SCSI_HA, &idescsi_template);
+	scsi_register_module(MODULE_SCSI_HA, &idescsi_template);
 	return 0;
 }
 
 static void __exit exit_idescsi_module(void)
 {
 	ide_drive_t *drive;
-	byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255};
+	u8 media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255};
 	int i, failed;
 
-	scsi_unregister_module (MODULE_SCSI_HA, &idescsi_template);
+	scsi_unregister_module(MODULE_SCSI_HA, &idescsi_template);
 	for (i = 0; media[i] != 255; i++) {
 		failed = 0;
-		while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL)
-			if (idescsi_cleanup (drive)) {
-				printk ("%s: exit_idescsi_module() called while still busy\n", drive->name);
+		while ((drive = ide_scan_devices(media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL)
+			if (idescsi_cleanup(drive)) {
+				printk("%s: exit_idescsi_module() called while still busy\n", drive->name);
 				failed++;
 			}
 	}

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