linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 00/12] Re-implement am53c974 driver
@ 2014-11-21 12:41 Hannes Reinecke
  2014-11-21 12:41 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
                   ` (12 more replies)
  0 siblings, 13 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Hi all,

having found some issues with the current tmscsim driver
I looked at the code and found is really awkward to clean
up.
Seeing that the am53c974 chip is actually based on the
'ESP' chip design I've re-implemented it based on the
common esp_scsi routines. This new driver
(cunningly named 'am53c974') provides all features
found on the tmscsim driver, with the goal of obsoleting
the old tmscsim driver.
Tested with Tekram DC390 and qemu esp-scsi.

Changes to v1:
- Include suggestions from Paolo Bonzini
- Remove the tmscsim driver
- Update MAINTAINERS file

Hannes Reinecke (11):
  esp_scsi: spellcheck 'driver'
  esp_scsi: make number of tags configurable
  esp_scsi: convert to dev_printk
  esp_scsi: debug event and command
  esp_scsi: read status registers
  esp_scsi: use FIFO for command submission
  scsi: add 'am53c974' driver
  am53c974: BLAST residual handling
  esp: correctly detect am53c974
  esp: enable CONFIG2_FENAB for am53c974
  Replace tmscsim by am53c974

Paolo Bonzini (1):
  esp_scsi: let DMA driver provide a config2 value

 MAINTAINERS             |    7 +-
 drivers/scsi/Kconfig    |    8 +-
 drivers/scsi/Makefile   |    2 +-
 drivers/scsi/am53c974.c |  581 +++++++++++
 drivers/scsi/esp_scsi.c |  411 +++++---
 drivers/scsi/esp_scsi.h |   22 +-
 drivers/scsi/tmscsim.c  | 2626 -----------------------------------------------
 drivers/scsi/tmscsim.h  |  549 ----------
 8 files changed, 854 insertions(+), 3352 deletions(-)
 create mode 100644 drivers/scsi/am53c974.c
 delete mode 100644 drivers/scsi/tmscsim.c
 delete mode 100644 drivers/scsi/tmscsim.h

-- 
1.8.5.2


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/12] esp_scsi: spellcheck 'driver'
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:42   ` David Miller
  2014-11-21 12:41 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index cd68805..b5862e4 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -1,4 +1,4 @@
-/* esp_scsi.h: Defines and structures for the ESP drier.
+/* esp_scsi.h: Defines and structures for the ESP driver.
  *
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/12] esp_scsi: make number of tags configurable
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
  2014-11-21 12:41 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:42   ` David Miller
  2014-11-21 12:41 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Add a field 'num_tags' to the esp structure to allow drivers
to overwrite the number of avialable tags if required.
Default is ESP_DEFAULT_TAGS.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.c | 12 ++++++------
 drivers/scsi/esp_scsi.h |  3 +--
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 38c23e0..a2e7868 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2317,6 +2317,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
 	static int instance;
 	int err;
 
+	if (!esp->num_tags)
+		esp->num_tags = ESP_DEFAULT_TAGS;
+	else if (esp->num_tags >= ESP_MAX_TAG)
+		esp->num_tags = ESP_MAX_TAG - 1;
 	esp->host->transportt = esp_transport_template;
 	esp->host->max_lun = ESP_MAX_LUN;
 	esp->host->cmd_per_lun = 2;
@@ -2403,12 +2407,8 @@ static int esp_slave_configure(struct scsi_device *dev)
 	struct esp *esp = shost_priv(dev->host);
 	struct esp_target_data *tp = &esp->target[dev->id];
 
-	if (dev->tagged_supported) {
-		/* XXX make this configurable somehow XXX */
-		int goal_tags = min(ESP_DEFAULT_TAGS, ESP_MAX_TAG);
-
-		scsi_adjust_queue_depth(dev, goal_tags);
-	}
+	if (dev->tagged_supported)
+		scsi_adjust_queue_depth(dev, esp->num_tags);
 
 	tp->flags |= ESP_TGT_DISCONNECT;
 
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index b5862e4..975d293 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -283,7 +283,6 @@ struct esp_cmd_entry {
 	struct completion	*eh_done;
 };
 
-/* XXX make this configurable somehow XXX */
 #define ESP_DEFAULT_TAGS	16
 
 #define ESP_MAX_TARGET		16
@@ -445,7 +444,7 @@ struct esp {
 	u8			prev_soff;
 	u8			prev_stp;
 	u8			prev_cfg3;
-	u8			__pad;
+	u8			num_tags;
 
 	struct list_head	esp_cmd_pool;
 
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/12] esp_scsi: convert to dev_printk
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
  2014-11-21 12:41 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
  2014-11-21 12:41 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:43   ` David Miller
  2014-11-21 12:41 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Use dev_printk functions for correct device annotations.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.c | 212 ++++++++++++++++++++++++------------------------
 1 file changed, 106 insertions(+), 106 deletions(-)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index a2e7868..10a3d17 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -52,52 +52,52 @@ static u32 esp_debug;
 
 #define esp_log_intr(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_INTR) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_reset(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_RESET) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_msgin(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_MSGIN) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_msgout(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_MSGOUT) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_cmddone(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_CMDDONE) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_disconnect(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_DISCONNECT) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_datastart(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_DATASTART) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_datadone(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_DATADONE) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_reconnect(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_RECONNECT) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_log_autosense(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_AUTOSENSE) \
-		printk(f, ## a); \
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
 #define esp_read8(REG)		esp->ops->esp_read8(esp, REG)
@@ -150,19 +150,17 @@ static void esp_dump_cmd_log(struct esp *esp)
 	int idx = esp->esp_event_cur;
 	int stop = idx;
 
-	printk(KERN_INFO PFX "esp%d: Dumping command log\n",
-	       esp->host->unique_id);
+	shost_printk(KERN_INFO, esp->host, "Dumping command log\n");
 	do {
 		struct esp_event_ent *p = &esp->esp_event_log[idx];
 
-		printk(KERN_INFO PFX "esp%d: ent[%d] %s ",
-		       esp->host->unique_id, idx,
-		       p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT");
-
-		printk("val[%02x] sreg[%02x] seqreg[%02x] "
-		       "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
-		       p->val, p->sreg, p->seqreg,
-		       p->sreg2, p->ireg, p->select_state, p->event);
+		shost_printk(KERN_INFO, esp->host,
+			     "ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] "
+			     "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
+			     idx,
+			     p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT",
+			     p->val, p->sreg, p->seqreg,
+			     p->sreg2, p->ireg, p->select_state, p->event);
 
 		idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
 	} while (idx != stop);
@@ -176,9 +174,8 @@ static void esp_flush_fifo(struct esp *esp)
 
 		while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) {
 			if (--lim == 0) {
-				printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES "
-				       "will not clear!\n",
-				       esp->host->unique_id);
+				shost_printk(KERN_ALERT, esp->host,
+					     "ESP_FF_BYTES will not clear!\n");
 				break;
 			}
 			udelay(1);
@@ -383,12 +380,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
 	p->cur_residue -= len;
 	p->tot_residue -= len;
 	if (p->cur_residue < 0 || p->tot_residue < 0) {
-		printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
-		       esp->host->unique_id);
-		printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
-		       "len[%u]\n",
-		       esp->host->unique_id,
-		       p->cur_residue, p->tot_residue, len);
+		shost_printk(KERN_ERR, esp->host,
+			     "Data transfer overflow.\n");
+		shost_printk(KERN_ERR, esp->host,
+			     "cur_residue[%d] tot_residue[%d] len[%u]\n",
+			     p->cur_residue, p->tot_residue, len);
 		p->cur_residue = 0;
 		p->tot_residue = 0;
 	}
@@ -604,9 +600,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
 
 
 	if (!ent->sense_ptr) {
-		esp_log_autosense("esp%d: Doing auto-sense for "
-				  "tgt[%d] lun[%d]\n",
-				  esp->host->unique_id, tgt, lun);
+		esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n",
+				  tgt, lun);
 
 		ent->sense_ptr = cmd->sense_buffer;
 		ent->sense_dma = esp->ops->map_single(esp,
@@ -953,8 +948,8 @@ static int esp_check_gross_error(struct esp *esp)
 		 * - DMA programmed with wrong direction
 		 * - improper phase change
 		 */
-		printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n",
-		       esp->host->unique_id, esp->sreg);
+		shost_printk(KERN_ERR, esp->host,
+			     "Gross error sreg[%02x]\n", esp->sreg);
 		/* XXX Reset the chip. XXX */
 		return 1;
 	}
@@ -982,14 +977,13 @@ static int esp_check_spur_intr(struct esp *esp)
 			 * ESP is not, the only possibility is a DMA error.
 			 */
 			if (!esp->ops->dma_error(esp)) {
-				printk(KERN_ERR PFX "esp%d: Spurious irq, "
-				       "sreg=%02x.\n",
-				       esp->host->unique_id, esp->sreg);
+				shost_printk(KERN_ERR, esp->host,
+					     "Spurious irq, sreg=%02x.\n",
+					     esp->sreg);
 				return -1;
 			}
 
-			printk(KERN_ERR PFX "esp%d: DMA error\n",
-			       esp->host->unique_id);
+			shost_printk(KERN_ERR, esp->host, "DMA error\n");
 
 			/* XXX Reset the chip. XXX */
 			return -1;
@@ -1002,7 +996,7 @@ static int esp_check_spur_intr(struct esp *esp)
 
 static void esp_schedule_reset(struct esp *esp)
 {
-	esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
+	esp_log_reset("esp_schedule_reset() from %pf\n",
 		      __builtin_return_address(0));
 	esp->flags |= ESP_FLAG_RESETTING;
 	esp_event(esp, ESP_EVENT_RESET);
@@ -1019,20 +1013,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
 	int i;
 
 	if (!lp->num_tagged) {
-		printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n",
-		       esp->host->unique_id);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect w/num_tagged==0\n");
 		return NULL;
 	}
 
-	esp_log_reconnect("ESP: reconnect tag, ");
+	esp_log_reconnect("reconnect tag, ");
 
 	for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) {
 		if (esp->ops->irq_pending(esp))
 			break;
 	}
 	if (i == ESP_QUICKIRQ_LIMIT) {
-		printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n",
-		       esp->host->unique_id);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect IRQ1 timeout\n");
 		return NULL;
 	}
 
@@ -1043,14 +1037,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
 			  i, esp->ireg, esp->sreg);
 
 	if (esp->ireg & ESP_INTR_DC) {
-		printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n",
-		       esp->host->unique_id);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect, got disconnect.\n");
 		return NULL;
 	}
 
 	if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) {
-		printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n",
-		       esp->host->unique_id, esp->sreg);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect, not MIP sreg[%02x].\n", esp->sreg);
 		return NULL;
 	}
 
@@ -1073,8 +1067,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
 		udelay(1);
 	}
 	if (i == ESP_RESELECT_TAG_LIMIT) {
-		printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n",
-		       esp->host->unique_id);
+		shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n");
 		return NULL;
 	}
 	esp->ops->dma_drain(esp);
@@ -1087,17 +1080,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
 
 	if (esp->command_block[0] < SIMPLE_QUEUE_TAG ||
 	    esp->command_block[0] > ORDERED_QUEUE_TAG) {
-		printk(KERN_ERR PFX "esp%d: Reconnect, bad tag "
-		       "type %02x.\n",
-		       esp->host->unique_id, esp->command_block[0]);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect, bad tag type %02x.\n",
+			     esp->command_block[0]);
 		return NULL;
 	}
 
 	ent = lp->tagged_cmds[esp->command_block[1]];
 	if (!ent) {
-		printk(KERN_ERR PFX "esp%d: Reconnect, no entry for "
-		       "tag %02x.\n",
-		       esp->host->unique_id, esp->command_block[1]);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect, no entry for tag %02x.\n",
+			     esp->command_block[1]);
 		return NULL;
 	}
 
@@ -1163,9 +1156,9 @@ static int esp_reconnect(struct esp *esp)
 	tp = &esp->target[target];
 	dev = __scsi_device_lookup_by_target(tp->starget, lun);
 	if (!dev) {
-		printk(KERN_ERR PFX "esp%d: Reconnect, no lp "
-		       "tgt[%u] lun[%u]\n",
-		       esp->host->unique_id, target, lun);
+		shost_printk(KERN_ERR, esp->host,
+			     "Reconnect, no lp tgt[%u] lun[%u]\n",
+			     target, lun);
 		goto do_reset;
 	}
 	lp = dev->hostdata;
@@ -1291,8 +1284,8 @@ static int esp_finish_select(struct esp *esp)
 		return 0;
 	}
 
-	printk("ESP: Unexpected selection completion ireg[%x].\n",
-	       esp->ireg);
+	shost_printk(KERN_INFO, esp->host,
+		     "Unexpected selection completion ireg[%x]\n", esp->ireg);
 	esp_schedule_reset(esp);
 	return 0;
 }
@@ -1556,8 +1549,8 @@ static void esp_msgin_extended(struct esp *esp)
 		return;
 	}
 
-	printk("ESP: Unexpected extended msg type %x\n",
-	       esp->msg_in[2]);
+	shost_printk(KERN_INFO, esp->host,
+		     "Unexpected extended msg type %x\n", esp->msg_in[2]);
 
 	esp->msg_out[0] = ABORT_TASK_SET;
 	esp->msg_out_len = 1;
@@ -1574,7 +1567,8 @@ static int esp_msgin_process(struct esp *esp)
 
 	if (msg0 & 0x80) {
 		/* Identify */
-		printk("ESP: Unexpected msgin identify\n");
+		shost_printk(KERN_INFO, esp->host,
+			     "Unexpected msgin identify\n");
 		return 0;
 	}
 
@@ -1673,8 +1667,9 @@ again:
 			break;
 
 		default:
-			printk("ESP: Unexpected phase, sreg=%02x\n",
-			       esp->sreg);
+			shost_printk(KERN_INFO, esp->host,
+				     "Unexpected phase, sreg=%02x\n",
+				     esp->sreg);
 			esp_schedule_reset(esp);
 			return 0;
 		}
@@ -1708,18 +1703,17 @@ again:
 		esp->data_dma_len = dma_len;
 
 		if (!dma_len) {
-			printk(KERN_ERR PFX "esp%d: DMA length is zero!\n",
-			       esp->host->unique_id);
-			printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n",
-			       esp->host->unique_id,
-			       (unsigned long long)esp_cur_dma_addr(ent, cmd),
-			       esp_cur_dma_len(ent, cmd));
+			shost_printk(KERN_ERR, esp->host,
+				     "DMA length is zero!\n");
+			shost_printk(KERN_ERR, esp->host,
+				     "cur adr[%08llx] len[%08x]\n",
+				     (unsigned long long)esp_cur_dma_addr(ent, cmd),
+				     esp_cur_dma_len(ent, cmd));
 			esp_schedule_reset(esp);
 			return 0;
 		}
 
-		esp_log_datastart("ESP: start data addr[%08llx] len[%u] "
-				  "write(%d)\n",
+		esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n",
 				  (unsigned long long)dma_addr, dma_len, write);
 
 		esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
@@ -1733,7 +1727,8 @@ again:
 		int bytes_sent;
 
 		if (esp->ops->dma_error(esp)) {
-			printk("ESP: data done, DMA error, resetting\n");
+			shost_printk(KERN_INFO, esp->host,
+				     "data done, DMA error, resetting\n");
 			esp_schedule_reset(esp);
 			return 0;
 		}
@@ -1749,14 +1744,15 @@ again:
 			/* We should always see exactly a bus-service
 			 * interrupt at the end of a successful transfer.
 			 */
-			printk("ESP: data done, not BSERV, resetting\n");
+			shost_printk(KERN_INFO, esp->host,
+				     "data done, not BSERV, resetting\n");
 			esp_schedule_reset(esp);
 			return 0;
 		}
 
 		bytes_sent = esp_data_bytes_sent(esp, ent, cmd);
 
-		esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n",
+		esp_log_datadone("data done flgs[%x] sent[%d]\n",
 				 ent->flags, bytes_sent);
 
 		if (bytes_sent < 0) {
@@ -1785,8 +1781,9 @@ again:
 		}
 
 		if (ent->message != COMMAND_COMPLETE) {
-			printk("ESP: Unexpected message %x in status\n",
-			       ent->message);
+			shost_printk(KERN_INFO, esp->host,
+				     "Unexpected message %x in status\n",
+				     ent->message);
 			esp_schedule_reset(esp);
 			return 0;
 		}
@@ -1804,8 +1801,7 @@ again:
 			scsi_esp_cmd(esp, ESP_CMD_ESEL);
 
 		if (ent->message == COMMAND_COMPLETE) {
-			esp_log_cmddone("ESP: Command done status[%x] "
-					"message[%x]\n",
+			esp_log_cmddone("Command done status[%x] message[%x]\n",
 					ent->status, ent->message);
 			if (ent->status == SAM_STAT_TASK_SET_FULL)
 				esp_event_queue_full(esp, ent);
@@ -1821,16 +1817,16 @@ again:
 							       DID_OK));
 			}
 		} else if (ent->message == DISCONNECT) {
-			esp_log_disconnect("ESP: Disconnecting tgt[%d] "
-					   "tag[%x:%x]\n",
+			esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n",
 					   cmd->device->id,
 					   ent->tag[0], ent->tag[1]);
 
 			esp->active_cmd = NULL;
 			esp_maybe_execute_command(esp);
 		} else {
-			printk("ESP: Unexpected message %x in freebus\n",
-			       ent->message);
+			shost_printk(KERN_INFO, esp->host,
+				     "Unexpected message %x in freebus\n",
+				     ent->message);
 			esp_schedule_reset(esp);
 			return 0;
 		}
@@ -1917,7 +1913,7 @@ again:
 				val = esp_read8(ESP_FDATA);
 			esp->msg_in[esp->msg_in_len++] = val;
 
-			esp_log_msgin("ESP: Got msgin byte %x\n", val);
+			esp_log_msgin("Got msgin byte %x\n", val);
 
 			if (!esp_msgin_process(esp))
 				esp->msg_in_len = 0;
@@ -1930,7 +1926,8 @@ again:
 			if (esp->event != ESP_EVENT_FREE_BUS)
 				esp_event(esp, ESP_EVENT_CHECK_PHASE);
 		} else {
-			printk("ESP: MSGIN neither BSERV not FDON, resetting");
+			shost_printk(KERN_INFO, esp->host,
+				     "MSGIN neither BSERV not FDON, resetting");
 			esp_schedule_reset(esp);
 			return 0;
 		}
@@ -1961,8 +1958,8 @@ again:
 		break;
 
 	default:
-		printk("ESP: Unexpected event %x, resetting\n",
-		       esp->event);
+		shost_printk(KERN_INFO, esp->host,
+			     "Unexpected event %x, resetting\n", esp->event);
 		esp_schedule_reset(esp);
 		return 0;
 		break;
@@ -2085,14 +2082,15 @@ static void __esp_interrupt(struct esp *esp)
 		}
 	}
 
-	esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] "
+	esp_log_intr("intr sreg[%02x] seqreg[%02x] "
 		     "sreg2[%02x] ireg[%02x]\n",
 		     esp->sreg, esp->seqreg, esp->sreg2, esp->ireg);
 
 	intr_done = 0;
 
 	if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) {
-		printk("ESP: unexpected IREG %02x\n", esp->ireg);
+		shost_printk(KERN_INFO, esp->host,
+			     "unexpected IREG %02x\n", esp->ireg);
 		if (esp->ireg & ESP_INTR_IC)
 			esp_dump_cmd_log(esp);
 
@@ -2334,12 +2332,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
 
 	esp_bootup_reset(esp);
 
-	printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n",
-	       esp->host->unique_id, esp->regs, esp->dma_regs,
-	       esp->host->irq);
-	printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
-	       esp->host->unique_id, esp_chip_names[esp->rev],
-	       esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
+	dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n",
+		   esp->host->unique_id, esp->regs, esp->dma_regs,
+		   esp->host->irq);
+	dev_printk(KERN_INFO, dev,
+		   "esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
+		   esp->host->unique_id, esp_chip_names[esp->rev],
+		   esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
 
 	/* Let the SCSI bus reset settle. */
 	ssleep(esp_bus_reset_settle);
@@ -2437,19 +2436,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
 	 * XXX much for the final driver.
 	 */
 	spin_lock_irqsave(esp->host->host_lock, flags);
-	printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n",
-	       esp->host->unique_id, cmd, cmd->cmnd[0]);
+	shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n",
+		     cmd, cmd->cmnd[0]);
 	ent = esp->active_cmd;
 	if (ent)
-		printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n",
-		       esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+		shost_printk(KERN_ERR, esp->host,
+			     "Current command [%p:%02x]\n",
+			     ent->cmd, ent->cmd->cmnd[0]);
 	list_for_each_entry(ent, &esp->queued_cmds, list) {
-		printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n",
-		       esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+		shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n",
+			     ent->cmd, ent->cmd->cmnd[0]);
 	}
 	list_for_each_entry(ent, &esp->active_cmds, list) {
-		printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n",
-		       esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+		shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n",
+			     ent->cmd, ent->cmd->cmnd[0]);
 	}
 	esp_dump_cmd_log(esp);
 	spin_unlock_irqrestore(esp->host->host_lock, flags);
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/12] esp_scsi: debug event and command
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (2 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:43   ` David Miller
  2014-11-21 12:41 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Add new debug definitions for event and command logging.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 10a3d17..3a5d81c 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -49,6 +49,8 @@ static u32 esp_debug;
 #define ESP_DEBUG_DATADONE	0x00000100
 #define ESP_DEBUG_RECONNECT	0x00000200
 #define ESP_DEBUG_AUTOSENSE	0x00000400
+#define ESP_DEBUG_EVENT		0x00000800
+#define ESP_DEBUG_COMMAND	0x00001000
 
 #define esp_log_intr(f, a...) \
 do {	if (esp_debug & ESP_DEBUG_INTR) \
@@ -100,6 +102,16 @@ do {	if (esp_debug & ESP_DEBUG_AUTOSENSE) \
 		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
 } while (0)
 
+#define esp_log_event(f, a...) \
+do {   if (esp_debug & ESP_DEBUG_EVENT)	\
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
+} while (0)
+
+#define esp_log_command(f, a...) \
+do {   if (esp_debug & ESP_DEBUG_COMMAND)	\
+		shost_printk(KERN_DEBUG, esp->host, f, ## a);	\
+} while (0)
+
 #define esp_read8(REG)		esp->ops->esp_read8(esp, REG)
 #define esp_write8(VAL,REG)	esp->ops->esp_write8(esp, VAL, REG)
 
@@ -126,6 +138,7 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
 
 	esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
 
+	esp_log_command("cmd[%02x]\n", val);
 	esp_write8(val, ESP_CMD);
 }
 EXPORT_SYMBOL(scsi_esp_cmd);
@@ -1638,6 +1651,8 @@ static int esp_process_event(struct esp *esp)
 
 again:
 	write = 0;
+	esp_log_event("process event %d phase %x\n",
+		      esp->event, esp->sreg & ESP_STAT_PMASK);
 	switch (esp->event) {
 	case ESP_EVENT_CHECK_PHASE:
 		switch (esp->sreg & ESP_STAT_PMASK) {
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/12] esp_scsi: read status registers
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (3 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:44   ` David Miller
  2014-11-21 12:41 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

A read to ESP_INTRPT will clear ESP_STATUS and ESP_SSTEP. So read
all status registers in one go to avoid losing information.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 3a5d81c..0ad0f08 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -982,7 +982,6 @@ static int esp_check_spur_intr(struct esp *esp)
 
 	default:
 		if (!(esp->sreg & ESP_STAT_INTR)) {
-			esp->ireg = esp_read8(ESP_INTRPT);
 			if (esp->ireg & ESP_INTR_SR)
 				return 1;
 
@@ -2056,7 +2055,12 @@ static void __esp_interrupt(struct esp *esp)
 	int finish_reset, intr_done;
 	u8 phase;
 
+       /*
+	* Once INTRPT is read STATUS and SSTEP are cleared.
+	*/
 	esp->sreg = esp_read8(ESP_STATUS);
+	esp->seqreg = esp_read8(ESP_SSTEP);
+	esp->ireg = esp_read8(ESP_INTRPT);
 
 	if (esp->flags & ESP_FLAG_RESETTING) {
 		finish_reset = 1;
@@ -2069,8 +2073,6 @@ static void __esp_interrupt(struct esp *esp)
 			return;
 	}
 
-	esp->ireg = esp_read8(ESP_INTRPT);
-
 	if (esp->ireg & ESP_INTR_SR)
 		finish_reset = 1;
 
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/12] esp_scsi: use FIFO for command submission
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (4 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 13:09   ` Paolo Bonzini
  2014-11-21 17:42   ` David Miller
  2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

Using DMA for command submission has the drawback that it might
generate additional DMA completion interrupts after the command
has been submitted to the device.
Additionally the am53c974 has a design flaw causing it
to generate spurious interrupts even though DMA completion
interrupts are not enabled.
This can be avoided by using the FIFO for command submission.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/esp_scsi.c | 46 +++++++++++++++++++++++++++++-----------------
 drivers/scsi/esp_scsi.h |  1 +
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 0ad0f08..2a3277d 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -143,6 +143,24 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
 }
 EXPORT_SYMBOL(scsi_esp_cmd);
 
+static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
+{
+	if (esp->flags & ESP_FLAG_USE_FIFO) {
+		int i;
+
+		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+		for (i = 0; i < len; i++)
+			esp_write8(esp->command_block[i], ESP_FDATA);
+		scsi_esp_cmd(esp, cmd);
+	} else {
+		if (esp->rev == FASHME)
+			scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+		cmd |= ESP_CMD_DMA;
+		esp->ops->send_dma_cmd(esp, esp->command_block_dma,
+				       len, max_len, 0, cmd);
+	}
+}
+
 static void esp_event(struct esp *esp, u8 val)
 {
 	struct esp_event_ent *p;
@@ -650,10 +668,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
 
 	val = (p - esp->command_block);
 
-	if (esp->rev == FASHME)
-		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-	esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-			       val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
+	esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
 }
 
 static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
@@ -789,12 +804,12 @@ build_identify:
 	}
 
 	if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
-		start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
+		start_cmd = ESP_CMD_SELA;
 		if (ent->tag[0]) {
 			*p++ = ent->tag[0];
 			*p++ = ent->tag[1];
 
-			start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
+			start_cmd = ESP_CMD_SA3;
 		}
 
 		for (i = 0; i < cmd->cmd_len; i++)
@@ -814,7 +829,7 @@ build_identify:
 			esp->msg_out_len += 2;
 		}
 
-		start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
+		start_cmd = ESP_CMD_SELAS;
 		esp->select_state = ESP_SELECT_MSGOUT;
 	}
 	val = tgt;
@@ -834,10 +849,7 @@ build_identify:
 		printk("]\n");
 	}
 
-	if (esp->rev == FASHME)
-		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-	esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-			       val, 16, 0, start_cmd);
+	esp_send_dma_cmd(esp, val, 16, start_cmd);
 }
 
 static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
@@ -1646,7 +1658,7 @@ static int esp_msgin_process(struct esp *esp)
 
 static int esp_process_event(struct esp *esp)
 {
-	int write;
+	int write, i;
 
 again:
 	write = 0;
@@ -1872,6 +1884,10 @@ again:
 			if (esp->msg_out_len == 1) {
 				esp_write8(esp->msg_out[0], ESP_FDATA);
 				scsi_esp_cmd(esp, ESP_CMD_TI);
+			} else if (esp->flags & ESP_FLAG_USE_FIFO) {
+				for (i = 0; i < esp->msg_out_len; i++)
+					esp_write8(esp->msg_out[i], ESP_FDATA);
+				scsi_esp_cmd(esp, ESP_CMD_TI);
 			} else {
 				/* Use DMA. */
 				memcpy(esp->command_block,
@@ -1949,11 +1965,7 @@ again:
 	case ESP_EVENT_CMD_START:
 		memcpy(esp->command_block, esp->cmd_bytes_ptr,
 		       esp->cmd_bytes_left);
-		if (esp->rev == FASHME)
-			scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-		esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-				       esp->cmd_bytes_left, 16, 0,
-				       ESP_CMD_DMA | ESP_CMD_TI);
+		esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
 		esp_event(esp, ESP_EVENT_CMD_DONE);
 		esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
 		break;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 975d293..27dcaf8 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -478,6 +478,7 @@ struct esp {
 #define ESP_FLAG_WIDE_CAPABLE	0x00000008
 #define ESP_FLAG_QUICKIRQ_CHECK	0x00000010
 #define ESP_FLAG_DISABLE_SYNC	0x00000020
+#define ESP_FLAG_USE_FIFO	0x00000040
 
 	u8			select_state;
 #define ESP_SELECT_NONE		0x00 /* Not selecting */
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (5 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-24 13:36   ` Christoph Hellwig
                     ` (2 more replies)
  2014-11-21 12:41 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
                   ` (5 subsequent siblings)
  12 siblings, 3 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

This patch adds a new implementation for the Tekram DC-390T /
AMD AM53c974 SCSI controller, based on the generic
esp_scsi infrastructure.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/Kconfig    |  18 ++
 drivers/scsi/Makefile   |   1 +
 drivers/scsi/am53c974.c | 531 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 550 insertions(+)
 create mode 100644 drivers/scsi/am53c974.c

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 60c67e1..519c3ef 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1357,6 +1357,24 @@ config SCSI_DC390T
 	  To compile this driver as a module, choose M here: the
 	  module will be called tmscsim.
 
+config SCSI_AM53C974
+	tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
+	depends on PCI && SCSI
+	select SCSI_SPI_ATTRS
+	---help---
+	  This driver supports PCI SCSI host adapters based on the Am53C974A
+	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
+	  PCscsi/PCnet (Am53/79C974) solutions.
+	  This is a new implementation base on the generic esp_scsi driver.
+
+	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
+
+	  Note that this driver does NOT support Tekram DC390W/U/F, which are
+	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called am53c974.
+
 config SCSI_T128
 	tristate "Trantor T128/T128F/T228 SCSI support"
 	depends on ISA && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 59f1ce6..79a6571 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
 obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
+obj-$(CONFIG_SCSI_AM53C974)	+= esp_scsi.o	am53c974.o
 obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
 obj-$(CONFIG_MEGARAID_SAS)	+= megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
new file mode 100644
index 0000000..86c4c42
--- /dev/null
+++ b/drivers/scsi/am53c974.c
@@ -0,0 +1,531 @@
+/*
+ * AMD am53c974 driver.
+ * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME "am53c974"
+#define DRV_MODULE_VERSION "1.00"
+
+// #define ESP_DMA_DEBUG
+
+#define ESP_DMA_CMD 0x10
+#define ESP_DMA_STC 0x11
+#define ESP_DMA_SPA 0x12
+#define ESP_DMA_WBC 0x13
+#define ESP_DMA_WAC 0x14
+#define ESP_DMA_STATUS 0x15
+#define ESP_DMA_SMDLA 0x16
+#define ESP_DMA_WMAC 0x17
+
+#define ESP_DMA_CMD_IDLE 0x00
+#define ESP_DMA_CMD_BLAST 0x01
+#define ESP_DMA_CMD_ABORT 0x02
+#define ESP_DMA_CMD_START 0x03
+#define ESP_DMA_CMD_MASK  0x03
+#define ESP_DMA_CMD_DIAG 0x04
+#define ESP_DMA_CMD_MDL 0x10
+#define ESP_DMA_CMD_INTE_P 0x20
+#define ESP_DMA_CMD_INTE_D 0x40
+#define ESP_DMA_CMD_DIR 0x80
+
+#define ESP_DMA_STAT_PWDN 0x01
+#define ESP_DMA_STAT_ERROR 0x02
+#define ESP_DMA_STAT_ABORT 0x04
+#define ESP_DMA_STAT_DONE 0x08
+#define ESP_DMA_STAT_SCSIINT 0x10
+#define ESP_DMA_STAT_BCMPLT 0x20
+
+/* EEPROM is accessed with 16-bit values */
+#define DC390_EEPROM_READ 0x80
+#define DC390_EEPROM_LEN 0x40
+
+/*
+ * DC390 EEPROM
+ *
+ * 8 * 4 bytes of per-device options
+ * followed by HBA specific options
+ */
+
+/* Per-device options */
+#define DC390_EE_MODE1 0x00
+#define DC390_EE_SPEED 0x01
+
+/* HBA-specific options */
+#define DC390_EE_ADAPT_SCSI_ID 0x40
+#define DC390_EE_MODE2 0x41
+#define DC390_EE_DELAY 0x42
+#define DC390_EE_TAG_CMD_NUM 0x43
+
+#define DC390_EE_MODE1_PARITY_CHK   0x01
+#define DC390_EE_MODE1_SYNC_NEGO    0x02
+#define DC390_EE_MODE1_EN_DISC      0x04
+#define DC390_EE_MODE1_SEND_START   0x08
+#define DC390_EE_MODE1_TCQ          0x10
+
+#define DC390_EE_MODE2_MORE_2DRV    0x01
+#define DC390_EE_MODE2_GREATER_1G   0x02
+#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
+#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
+#define DC390_EE_MODE2_NO_SEEK      0x10
+#define DC390_EE_MODE2_LUN_CHECK    0x20
+
+struct pci_esp_priv {
+	struct esp *esp;
+	u8 dma_status;
+};
+
+#define PCI_ESP_GET_PRIV(esp) ((struct pci_esp_priv *) \
+			       pci_get_drvdata((struct pci_dev *) \
+					       (esp)->dev))
+
+static void pci_esp_dma_drain(struct esp *esp);
+
+static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+	iowrite8(val, esp->regs + (reg * 4UL));
+}
+
+static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
+{
+	return ioread8(esp->regs + (reg * 4UL));
+}
+
+static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
+{
+	return iowrite32(val, esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
+				     size_t sz, int dir)
+{
+	return pci_map_single(esp->dev, buf, sz, dir);
+}
+
+static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+			  int num_sg, int dir)
+{
+	return pci_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+				 size_t sz, int dir)
+{
+	pci_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+			     int num_sg, int dir)
+{
+	pci_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int pci_esp_irq_pending(struct esp *esp)
+{
+	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
+
+	pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
+#ifdef ESP_DMA_DEBUG
+	if (pep->dma_status)
+		shost_printk(KERN_INFO, esp->host, "dma intr dreg[%02x]\n",
+			     pep->dma_status);
+#endif
+	if (pep->dma_status & (ESP_DMA_STAT_ERROR |
+			       ESP_DMA_STAT_ABORT |
+			       ESP_DMA_STAT_DONE |
+			       ESP_DMA_STAT_SCSIINT))
+		return 1;
+
+	return 0;
+}
+
+static void pci_esp_reset_dma(struct esp *esp)
+{
+	/* Nothing to do ? */
+}
+
+static void pci_esp_dma_drain(struct esp *esp)
+{
+	u8 resid;
+	int lim = 1000;
+
+
+	if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
+	    (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
+		/* Data-In or Data-Out, nothing to be done */
+		return;
+
+	while (--lim > 0) {
+		resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
+		if (resid <= 1)
+			break;
+		cpu_relax();
+	}
+	if (resid > 1) {
+		/* FIFO not cleared */
+		shost_printk(KERN_INFO, esp->host,
+			     "FIFO not cleared, %d bytes left\n",
+			     resid);
+	}
+
+	/*
+	 * When there is a residual BCMPLT will never be set
+	 * (obviously). But we still have to issue the BLAST
+	 * command, otherwise the data will not being transferred.
+	 * But we'll never know when the BLAST operation is
+	 * finished. So check for some time and give up eventually.
+	 */
+	lim = 1000;
+	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
+	while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
+		if (--lim == 0)
+			break;
+		cpu_relax();
+	}
+	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+#ifdef ESP_DMA_DEBUG
+	shost_printk(KERN_INFO, esp->host,
+		     "DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+#endif
+}
+
+static void pci_esp_dma_invalidate(struct esp *esp)
+{
+	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
+
+#ifdef ESP_DMA_DEBUG
+	shost_printk(KERN_INFO, esp->host, "invalidate DMA\n");
+#endif
+	pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+	pep->dma_status = 0;
+}
+
+static int pci_esp_dma_error(struct esp *esp)
+{
+	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
+
+	if (pep->dma_status & ESP_DMA_STAT_ERROR) {
+		u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
+
+		if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
+			pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
+
+		return 1;
+	}
+	if (pep->dma_status & ESP_DMA_STAT_ABORT) {
+		pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+		pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
+		return 1;
+	}
+	return 0;
+}
+
+static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+				 u32 dma_count, int write, u8 cmd)
+{
+	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
+	u32 val = 0;
+
+	BUG_ON(!(cmd & ESP_CMD_DMA));
+
+	pep->dma_status = 0;
+
+	/* Set DMA engine to IDLE */
+	if (write)
+		/* DMA write direction logic is inverted */
+		val |= ESP_DMA_CMD_DIR;
+	pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
+
+	pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+	pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+
+	pci_esp_write32(esp, esp_count, ESP_DMA_STC);
+	pci_esp_write32(esp, addr, ESP_DMA_SPA);
+
+#ifdef ESP_DMA_DEBUG
+	shost_printk(KERN_INFO, esp->host, "start dma addr[%x] count[%d:%d]\n",
+		     addr, esp_count, dma_count);
+#endif
+	scsi_esp_cmd(esp, cmd);
+	/* Send DMA Start command */
+	pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
+}
+
+static const struct esp_driver_ops pci_esp_ops = {
+	.esp_write8	=	pci_esp_write8,
+	.esp_read8	=	pci_esp_read8,
+	.map_single	=	pci_esp_map_single,
+	.map_sg		=	pci_esp_map_sg,
+	.unmap_single	=	pci_esp_unmap_single,
+	.unmap_sg	=	pci_esp_unmap_sg,
+	.irq_pending	=	pci_esp_irq_pending,
+	.reset_dma	=	pci_esp_reset_dma,
+	.dma_drain	=	pci_esp_dma_drain,
+	.dma_invalidate	=	pci_esp_dma_invalidate,
+	.send_dma_cmd	=	pci_esp_send_dma_cmd,
+	.dma_error	=	pci_esp_dma_error,
+};
+
+/*
+ * Read DC-390 eeprom
+ */
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+{
+	u8 carryFlag = 1, j = 0x80, bval;
+	int i;
+
+	for (i = 0; i < 9; i++) {
+		if (carryFlag) {
+			pci_write_config_byte(pdev, 0x80, 0x40);
+			bval = 0xc0;
+		} else
+			bval = 0x80;
+
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, bval);
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, 0);
+		udelay(160);
+
+		carryFlag = (cmd & j) ? 1 : 0;
+		j >>= 1;
+	}
+}
+
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
+{
+	int i;
+	u16 wval = 0;
+	u8 bval;
+
+	for (i = 0; i < 16; i++) {
+		wval <<= 1;
+
+		pci_write_config_byte(pdev, 0x80, 0x80);
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, 0x40);
+		udelay(160);
+		pci_read_config_byte(pdev, 0x00, &bval);
+
+		if (bval == 0x22)
+			wval |= 1;
+	}
+
+	return wval;
+}
+
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+{
+	u8 cmd = DC390_EEPROM_READ, i;
+
+	for (i = 0; i < DC390_EEPROM_LEN; i++) {
+		pci_write_config_byte(pdev, 0xc0, 0);
+		udelay(160);
+
+		dc390_eeprom_prepare_read(pdev, cmd++);
+		*ptr++ = dc390_eeprom_get_data(pdev);
+
+		pci_write_config_byte(pdev, 0x80, 0);
+		pci_write_config_byte(pdev, 0x80, 0);
+		udelay(160);
+	}
+}
+
+static void dc390_check_eeprom(struct esp *esp)
+{
+	u8 EEbuf[128];
+	u16 *ptr = (u16 *)EEbuf, wval = 0;
+	int i;
+
+	dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
+
+	for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
+		wval += *ptr;
+
+	/* no Tekram EEprom found */
+	if (wval != 0x1234) {
+		struct pci_dev *pdev = esp->dev;
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "No valid Tekram EEprom found\n");
+		return;
+	}
+	esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
+	esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+}
+
+static int pci_esp_probe_one(struct pci_dev *pdev,
+			      const struct pci_device_id *id)
+{
+	struct scsi_host_template *hostt = &scsi_esp_template;
+	int err = -ENODEV;
+	struct Scsi_Host *shost;
+	struct esp *esp;
+	struct pci_esp_priv *pep;
+
+	if (pci_enable_device(pdev)) {
+		dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
+		return -ENODEV;
+	}
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to set 32bit DMA mask\n");
+		goto fail_disable_device;
+	}
+
+	shost = scsi_host_alloc(hostt, sizeof(struct esp));
+	if (!shost) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to allocate scsi host\n");
+		err = -ENOMEM;
+		goto fail_disable_device;
+	}
+
+	pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
+	if (!pep) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to allocate esp_priv\n");
+		err = -ENOMEM;
+		goto fail_host_alloc;
+	}
+
+	esp = shost_priv(shost);
+	esp->host = shost;
+	esp->dev = pdev;
+	esp->ops = &pci_esp_ops;
+	/*
+	 * The am53c974 HBA has a design flaw of generating
+	 * spurious DMA completion interrupts when using
+	 * DMA for command submission.
+	 */
+	esp->flags |= ESP_FLAG_USE_FIFO;
+	pep->esp = esp;
+
+	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "pci memory selection failed\n");
+		goto fail_priv_alloc;
+	}
+
+	esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+	if (!esp->regs) {
+		dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
+		goto fail_release_regions;
+	}
+	esp->dma_regs = esp->regs;
+
+	pci_set_master(pdev);
+
+	esp->command_block = pci_alloc_consistent(pdev, 16,
+						  &esp->command_block_dma);
+	if (!esp->command_block) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "failed to allocate command block\n");
+		err = -ENOMEM;
+		goto fail_unmap_regs;
+	}
+
+	if (request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
+			DRV_MODULE_NAME, esp)) {
+		dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
+		goto fail_unmap_command_block;
+	}
+
+	esp->scsi_id = 7;
+	dc390_check_eeprom(esp);
+
+	shost->this_id = esp->scsi_id;
+	shost->max_id = 8;
+	shost->irq = pdev->irq;
+	shost->io_port = pci_resource_start(pdev, 0);
+	shost->n_io_port = pci_resource_len(pdev, 0);
+	shost->unique_id = shost->io_port;
+	esp->scsi_id_mask = (1 << esp->scsi_id);
+	/* Assume 40MHz clock */
+	esp->cfreq = 40000000;
+
+	pci_set_drvdata(pdev, pep);
+
+	err = scsi_esp_register(esp, &pdev->dev);
+	if (err)
+		goto fail_free_irq;
+
+	return 0;
+
+fail_free_irq:
+	free_irq(pdev->irq, esp);
+fail_unmap_command_block:
+	pci_free_consistent(pdev, 16, esp->command_block,
+			    esp->command_block_dma);
+fail_unmap_regs:
+	pci_iounmap(pdev, esp->regs);
+fail_release_regions:
+	pci_release_regions(pdev);
+fail_priv_alloc:
+	kfree(pep);
+fail_host_alloc:
+	scsi_host_put(shost);
+fail_disable_device:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void pci_esp_remove_one(struct pci_dev *pdev)
+{
+	struct pci_esp_priv *pep = pci_get_drvdata(pdev);
+	struct esp *esp = pep->esp;
+
+	scsi_esp_unregister(esp);
+	free_irq(pdev->irq, esp);
+	pci_free_consistent(pdev, 16, esp->command_block,
+			    esp->command_block_dma);
+	pci_iounmap(pdev, esp->regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(pep);
+
+	scsi_host_put(esp->host);
+}
+
+static struct pci_device_id am53c974_pci_tbl[] = {
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
+
+static struct pci_driver am53c974_driver = {
+	.name           = DRV_MODULE_NAME,
+	.id_table       = am53c974_pci_tbl,
+	.probe          = pci_esp_probe_one,
+	.remove         = pci_esp_remove_one,
+};
+
+static int __init am53c974_module_init(void)
+{
+	return pci_register_driver(&am53c974_driver);
+}
+
+static void __exit am53c974_module_exit(void)
+{
+	pci_unregister_driver(&am53c974_driver);
+}
+
+MODULE_DESCRIPTION("AM53C974 SCSI driver");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+module_init(am53c974_module_init);
+module_exit(am53c974_module_exit);
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/12] am53c974: BLAST residual handling
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (6 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 13:09   ` Paolo Bonzini
  2014-11-21 17:45   ` David Miller
  2014-11-21 12:41 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
                   ` (4 subsequent siblings)
  12 siblings, 2 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

The am53c974 has an design issue where a single byte might be
left in the SCSI FIFO after a DMA transfer.
As the handling code is currently untested add a WARN_ON()
statement here.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/am53c974.c |  6 ++++++
 drivers/scsi/esp_scsi.c | 29 +++++++++++++++++++++++++++++
 drivers/scsi/esp_scsi.h |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 86c4c42..1c1312f 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -197,6 +197,12 @@ static void pci_esp_dma_drain(struct esp *esp)
 	shost_printk(KERN_INFO, esp->host,
 		     "DMA blast done (%d tries, %d bytes left)\n", lim, resid);
 #endif
+	/* BLAST residual handling is currently untested */
+	if (WARN_ON_ONCE(resid == 1)) {
+		struct esp_cmd_entry *ent = esp->active_cmd;
+
+		ent->flags |= ESP_CMD_FLAG_RESIDUAL;
+	}
 }
 
 static void pci_esp_dma_invalidate(struct esp *esp)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 2a3277d..07b4d93 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1334,6 +1334,35 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
 	bytes_sent = esp->data_dma_len;
 	bytes_sent -= ecount;
 
+	/*
+	 * The am53c974 has a DMA 'pecularity'. The doc states:
+	 * In some odd byte conditions, one residual byte will
+	 * be left in the SCSI FIFO, and the FIFO Flags will
+	 * never count to '0 '. When this happens, the residual
+	 * byte should be retrieved via PIO following completion
+	 * of the BLAST operation.
+	 */
+	if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
+		size_t count = 1;
+		size_t offset = bytes_sent;
+		u8 bval = esp_read8(ESP_FDATA);
+
+		if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
+			ent->sense_ptr[bytes_sent] = bval;
+		else {
+			struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
+			u8 *ptr;
+
+			ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
+						  &offset, &count);
+			if (likely(ptr)) {
+				*(ptr + offset) = bval;
+				scsi_kunmap_atomic_sg(ptr);
+			}
+		}
+		bytes_sent += fifo_cnt;
+		ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
+	}
 	if (!(ent->flags & ESP_CMD_FLAG_WRITE))
 		bytes_sent -= fifo_cnt;
 
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 27dcaf8..5fa456c 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -269,6 +269,7 @@ struct esp_cmd_entry {
 #define ESP_CMD_FLAG_WRITE	0x01 /* DMA is a write */
 #define ESP_CMD_FLAG_ABORT	0x02 /* being aborted */
 #define ESP_CMD_FLAG_AUTOSENSE	0x04 /* Doing automatic REQUEST_SENSE */
+#define ESP_CMD_FLAG_RESIDUAL	0x08 /* AM53c974 BLAST residual */
 
 	u8			tag[2];
 	u8			orig_tag[2];
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/12] esp: correctly detect am53c974
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (7 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:46   ` David Miller
  2014-11-21 12:41 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

The am53c974 returns the same ID as the FAS236, but implements
things slightly differently. So detect the am53c974 by checking
for ESP_CONFIG4 register.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/am53c974.c |  2 ++
 drivers/scsi/esp_scsi.c | 17 ++++++++++++++++-
 drivers/scsi/esp_scsi.h | 15 +++++++++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 1c1312f..340cb2f 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -367,6 +367,8 @@ static void dc390_check_eeprom(struct esp *esp)
 	}
 	esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
 	esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+	if (EEbuf[DC390_EE_MODE2] & DC390_EE_MODE2_ACTIVE_NEGATION)
+		esp->config4 |= ESP_CONFIG4_RADE | ESP_CONFIG4_RAE;
 }
 
 static int pci_esp_probe_one(struct pci_dev *pdev,
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 07b4d93..797e208 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -268,6 +268,19 @@ static void esp_reset_esp(struct esp *esp)
 	} else {
 		esp->min_period = ((5 * esp->ccycle) / 1000);
 	}
+	if (esp->rev == FAS236) {
+		/*
+		 * The AM53c974 chip returns the same ID as FAS236;
+		 * try to configure glitch eater.
+		 */
+		u8 config4 = ESP_CONFIG4_GE1;
+		esp_write8(config4, ESP_CFG4);
+		config4 = esp_read8(ESP_CFG4);
+		if ((config4 & ESP_CONFIG4_GE1) == ESP_CONFIG4_GE1) {
+			esp->rev = PCSCSI;
+			esp_write8(esp->config4, ESP_CFG4);
+		}
+	}
 	esp->max_period = (esp->max_period + 3)>>2;
 	esp->min_period = (esp->min_period + 3)>>2;
 
@@ -293,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)
 		/* fallthrough... */
 
 	case FAS236:
-		/* Fast 236 or HME */
+	case PCSCSI:
+		/* Fast 236, AM53c974 or HME */
 		esp_write8(esp->config2, ESP_CFG2);
 		if (esp->rev == FASHME) {
 			u8 cfg3 = esp->target[0].esp_config3;
@@ -2364,6 +2378,7 @@ static const char *esp_chip_names[] = {
 	"FAS100A",
 	"FAST",
 	"FASHME",
+	"AM53C974",
 };
 
 static struct scsi_transport_template *esp_transport_template;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 5fa456c..84dcbe4 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -25,6 +25,7 @@
 #define ESP_CTEST	0x0aUL		/* wo  Chip test register      0x28  */
 #define ESP_CFG2	0x0bUL		/* rw  Second cfg register     0x2c  */
 #define ESP_CFG3	0x0cUL		/* rw  Third cfg register      0x30  */
+#define ESP_CFG4	0x0dUL		/* rw  Fourth cfg register     0x34  */
 #define ESP_TCHI	0x0eUL		/* rw  High bits transf count  0x38  */
 #define ESP_UID		ESP_TCHI	/* ro  Unique ID code          0x38  */
 #define FAS_RLO		ESP_TCHI	/* rw  HME extended counter    0x38  */
@@ -76,6 +77,18 @@
 #define ESP_CONFIG3_IMS       0x80     /* ID msg chk'ng        (esp/fas236)  */
 #define ESP_CONFIG3_OBPUSH    0x80     /* Push odd-byte to dma (hme)         */
 
+/* ESP config register 4 read-write, found only on am53c974 chips */
+#define ESP_CONFIG4_RADE      0x04     /* Active negation */
+#define ESP_CONFIG4_RAE       0x08     /* Active negation on REQ and ACK */
+#define ESP_CONFIG4_PWD       0x20     /* Reduced power feature */
+#define ESP_CONFIG4_GE0       0x40     /* Glitch eater bit 0 */
+#define ESP_CONFIG4_GE1       0x80     /* Glitch eater bit 1 */
+
+#define ESP_CONFIG_GE_12NS    (0)
+#define ESP_CONFIG_GE_25NS    (ESP_CONFIG_GE1)
+#define ESP_CONFIG_GE_35NS    (ESP_CONFIG_GE0)
+#define ESP_CONFIG_GE_0NS     (ESP_CONFIG_GE0 | ESP_CONFIG_GE1)
+
 /* ESP command register read-write */
 /* Group 1 commands:  These may be sent at any point in time to the ESP
  *                    chip.  None of them can generate interrupts 'cept
@@ -254,6 +267,7 @@ enum esp_rev {
 	FAS100A    = 0x04,
 	FAST       = 0x05,
 	FASHME     = 0x06,
+	PCSCSI     = 0x07,  /* AM53c974 */
 };
 
 struct esp_cmd_entry {
@@ -466,6 +480,7 @@ struct esp {
 	u8			bursts;
 	u8			config1;
 	u8			config2;
+	u8			config4;
 
 	u8			scsi_id;
 	u32			scsi_id_mask;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (8 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 17:47   ` David Miller
  2014-11-21 12:41 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi

From: Paolo Bonzini <pbonzini@redhat.com>

On PCscsi, the FENAB configuration also enables 24-bit DMA
transfer lengths (and provides the chip id in TCHI after reset).
We want to be able to enable this parameter from the DMA driver.

Check if the caller of scsi_esp_register provided a value for esp->config2.
If this is the case, assume this is not an ESP100, skip the detection
phase and leave esp->config2 untouched.  It will be used in esp_reset_esp.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 drivers/scsi/esp_scsi.c | 70 ++++++++++++++++++++++++++-----------------------
 1 file changed, 37 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 797e208..bd17516 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2219,46 +2219,50 @@ static void esp_get_revision(struct esp *esp)
 	u8 val;
 
 	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
-	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+	if (esp->config2 == 0) {
+		esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+		esp_write8(esp->config2, ESP_CFG2);
+
+		val = esp_read8(ESP_CFG2);
+		val &= ~ESP_CONFIG2_MAGIC;
+
+		esp->config2 = 0;
+		if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+			/*
+			 * If what we write to cfg2 does not come back,
+			 * cfg2 is not implemented.
+			 * Therefore this must be a plain esp100.
+			 */
+			esp->rev = ESP100;
+			return;
+		}
+	}
+
+	esp_set_all_config3(esp, 5);
+	esp->prev_cfg3 = 5;
 	esp_write8(esp->config2, ESP_CFG2);
+	esp_write8(0, ESP_CFG3);
+	esp_write8(esp->prev_cfg3, ESP_CFG3);
 
-	val = esp_read8(ESP_CFG2);
-	val &= ~ESP_CONFIG2_MAGIC;
-	if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-		/* If what we write to cfg2 does not come back, cfg2 is not
-		 * implemented, therefore this must be a plain esp100.
+	val = esp_read8(ESP_CFG3);
+	if (val != 5) {
+		/* The cfg2 register is implemented, however
+		 * cfg3 is not, must be esp100a.
 		 */
-		esp->rev = ESP100;
+		esp->rev = ESP100A;
 	} else {
-		esp->config2 = 0;
-		esp_set_all_config3(esp, 5);
-		esp->prev_cfg3 = 5;
-		esp_write8(esp->config2, ESP_CFG2);
-		esp_write8(0, ESP_CFG3);
+		esp_set_all_config3(esp, 0);
+		esp->prev_cfg3 = 0;
 		esp_write8(esp->prev_cfg3, ESP_CFG3);
 
-		val = esp_read8(ESP_CFG3);
-		if (val != 5) {
-			/* The cfg2 register is implemented, however
-			 * cfg3 is not, must be esp100a.
-			 */
-			esp->rev = ESP100A;
+		/* All of cfg{1,2,3} implemented, must be one of
+		 * the fas variants, figure out which one.
+		 */
+		if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
+			esp->rev = FAST;
+			esp->sync_defp = SYNC_DEFP_FAST;
 		} else {
-			esp_set_all_config3(esp, 0);
-			esp->prev_cfg3 = 0;
-			esp_write8(esp->prev_cfg3, ESP_CFG3);
-
-			/* All of cfg{1,2,3} implemented, must be one of
-			 * the fas variants, figure out which one.
-			 */
-			if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
-				esp->rev = FAST;
-				esp->sync_defp = SYNC_DEFP_FAST;
-			} else {
-				esp->rev = ESP236;
-			}
-			esp->config2 = 0;
-			esp_write8(esp->config2, ESP_CFG2);
+			esp->rev = ESP236;
 		}
 	}
 }
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (9 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-21 13:10   ` Paolo Bonzini
  2014-11-21 17:47   ` David Miller
  2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
  2014-11-24  8:14 ` [PATCHv2 00/12] Re-implement am53c974 driver Christoph Hellwig
  12 siblings, 2 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

CONFIG2_FENAB ('feature enable') changed definition between chip
revisions, from 'Latch SCSI Phase' to 'Latch SCSI Phase, display
chip ID upon reset, and enable 24 bit addresses'.
So only enable it for am53c974 where we know what it's doing.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/am53c974.c | 41 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/esp_scsi.c |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 340cb2f..55622eb 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -17,6 +17,8 @@
 #define DRV_MODULE_NAME "am53c974"
 #define DRV_MODULE_VERSION "1.00"
 
+static bool am53c974_fenab = true;
+
 // #define ESP_DMA_DEBUG
 
 #define ESP_DMA_CMD 0x10
@@ -254,6 +256,8 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
 
 	pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
 	pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+	if (esp->config2 & ESP_CONFIG2_FENAB)
+		pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
 
 	pci_esp_write32(esp, esp_count, ESP_DMA_STC);
 	pci_esp_write32(esp, addr, ESP_DMA_SPA);
@@ -267,6 +271,33 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
 	pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
 }
 
+static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
+{
+	int dma_limit = 16;
+	u32 base, end;
+
+	/*
+	 * If CONFIG2_FENAB is set we can
+	 * handle up to 24 bit addresses
+	 */
+	if (esp->config2 & ESP_CONFIG2_FENAB)
+		dma_limit = 24;
+
+	if (dma_len > (1U << dma_limit))
+		dma_len = (1U << dma_limit);
+
+	/*
+	 * Prevent crossing a 24-bit address boundary.
+	 */
+	base = dma_addr & ((1U << 24) - 1U);
+	end = base + dma_len;
+	if (end > (1U << 24))
+		end = (1U <<24);
+	dma_len = end - base;
+
+	return dma_len;
+}
+
 static const struct esp_driver_ops pci_esp_ops = {
 	.esp_write8	=	pci_esp_write8,
 	.esp_read8	=	pci_esp_read8,
@@ -280,6 +311,7 @@ static const struct esp_driver_ops pci_esp_ops = {
 	.dma_invalidate	=	pci_esp_dma_invalidate,
 	.send_dma_cmd	=	pci_esp_send_dma_cmd,
 	.dma_error	=	pci_esp_dma_error,
+	.dma_length_limit =	pci_esp_dma_length_limit,
 };
 
 /*
@@ -417,6 +449,12 @@ static int pci_esp_probe_one(struct pci_dev *pdev,
 	 * DMA for command submission.
 	 */
 	esp->flags |= ESP_FLAG_USE_FIFO;
+	/*
+	 * Enable CONFIG2_FENAB to allow for large DMA transfers
+	 */
+	if (am53c974_fenab)
+		esp->config2 |= ESP_CONFIG2_FENAB;
+
 	pep->esp = esp;
 
 	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
@@ -535,5 +573,8 @@ MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
+module_param(am53c974_fenab, bool, 0444);
+MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
+
 module_init(am53c974_module_init);
 module_exit(am53c974_module_exit);
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index bd17516..56f361e 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1343,6 +1343,8 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
 			  (((unsigned int)esp_read8(ESP_TCMED)) << 8));
 		if (esp->rev == FASHME)
 			ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
+		if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
+			ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
 	}
 
 	bytes_sent = esp->data_dma_len;
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 12/12] Replace tmscsim by am53c974
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (10 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
  2014-11-23 13:22   ` Guennadi Liakhovetski
  2014-11-24  8:14 ` [PATCHv2 00/12] Re-implement am53c974 driver Christoph Hellwig
  12 siblings, 1 reply; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi, Hannes Reinecke

The am53c974 is a re-implementation of the tmscsim driver,
and provides the same functionality.
So remove the tmscsim driver and make am53c974 an alias to tmscsim.

Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 MAINTAINERS             |    7 +-
 drivers/scsi/Kconfig    |   16 -
 drivers/scsi/Makefile   |    1 -
 drivers/scsi/am53c974.c |    1 +
 drivers/scsi/tmscsim.c  | 2626 -----------------------------------------------
 drivers/scsi/tmscsim.h  |  549 ----------
 6 files changed, 4 insertions(+), 3196 deletions(-)
 delete mode 100644 drivers/scsi/tmscsim.c
 delete mode 100644 drivers/scsi/tmscsim.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d206f37..d780e46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2862,11 +2862,10 @@ F:	Documentation/networking/dmfe.txt
 F:	drivers/net/ethernet/dec/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
-M:	Kurt Garloff <garloff@suse.de>
-W:	http://www.garloff.de/kurt/linux/dc390/
-M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+M:	Hannes Reinecke <hare@suse.de>
+L:	linux-scsi@vger.kernel.org
 S:	Maintained
-F:	drivers/scsi/tmscsim.*
+F:	drivers/scsi/am53c974.c
 
 DC395x SCSI driver
 M:	Oliver Neukum <oliver@neukum.org>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 519c3ef..f871a80 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1341,22 +1341,6 @@ config SCSI_DC395x
 	  To compile this driver as a module, choose M here: the
 	  module will be called dc395x.
 
-config SCSI_DC390T
-	tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
-	depends on PCI && SCSI
-	---help---
-	  This driver supports PCI SCSI host adapters based on the Am53C974A
-	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
-	  PCscsi/PCnet (Am53/79C974) solutions.
-
-	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
-
-	  Note that this driver does NOT support Tekram DC390W/U/F, which are
-	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tmscsim.
-
 config SCSI_AM53C974
 	tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
 	depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 79a6571..a9f3fa8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO)	+= eata_pio.o
 obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
-obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
 obj-$(CONFIG_SCSI_AM53C974)	+= esp_scsi.o	am53c974.o
 obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 55622eb..5ce2bb2 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -572,6 +572,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");
 MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_ALIAS("tmscsim");
 
 module_param(am53c974_fenab, bool, 0444);
 MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
deleted file mode 100644
index 844c9a0..0000000
--- a/drivers/scsi/tmscsim.c
+++ /dev/null
@@ -1,2626 +0,0 @@
-/************************************************************************
- *	FILE NAME : TMSCSIM.C						*
- *	     BY   : C.L. Huang,  ching@tekram.com.tw			*
- *	Description: Device Driver for Tekram DC-390(T) PCI SCSI	*
- *		     Bus Master Host Adapter				*
- * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.			*
- ************************************************************************
- * (C) Copyright: put under GNU GPL in 10/96				*
- *				(see Documentation/scsi/tmscsim.txt)	*
- ************************************************************************
- * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $		*
- *	Enhancements and bugfixes by					*
- *	Kurt Garloff <kurt@garloff.de>	<garloff@suse.de>		*
- ************************************************************************
- *	HISTORY:							*
- *									*
- *	REV#	DATE	NAME	DESCRIPTION				*
- *	1.00  96/04/24	CLH	First release				*
- *	1.01  96/06/12	CLH	Fixed bug of Media Change for Removable *
- *				Device, scan all LUN. Support Pre2.0.10 *
- *	1.02  96/06/18	CLH	Fixed bug of Command timeout ...	*
- *	1.03  96/09/25	KG	Added tmscsim_proc_info()		*
- *	1.04  96/10/11	CLH	Updating for support KV 2.0.x		*
- *	1.05  96/10/18	KG	Fixed bug in DC390_abort(null ptr deref)*
- *	1.06  96/10/25	KG	Fixed module support			*
- *	1.07  96/11/09	KG	Fixed tmscsim_proc_info()		*
- *	1.08  96/11/18	KG	Fixed null ptr in DC390_Disconnect()	*
- *	1.09  96/11/30	KG	Added register the allocated IO space	*
- *	1.10  96/12/05	CLH	Modified tmscsim_proc_info(), and reset *
- *				pending interrupt in DC390_detect()	*
- *	1.11  97/02/05	KG/CLH	Fixeds problem with partitions greater	*
- *				than 1GB				*
- *	1.12  98/02/15  MJ      Rewritten PCI probing			*
- *	1.13  98/04/08	KG	Support for non DC390, __initfunc decls,*
- *				changed max devs from 10 to 16		*
- *	1.14a 98/05/05	KG	Dynamic DCB allocation, add-single-dev	*
- *				for LUNs if LUN_SCAN (BIOS) not set	*
- *				runtime config using /proc interface	*
- *	1.14b 98/05/06	KG	eliminated cli (); sti (); spinlocks	*
- *	1.14c 98/05/07	KG	2.0.x compatibility			*
- *	1.20a 98/05/07	KG	changed names of funcs to be consistent *
- *				DC390_ (entry points), dc390_ (internal)*
- *				reworked locking			*
- *	1.20b 98/05/12	KG	bugs: version, kfree, _ctmp		*
- *				debug output				*
- *	1.20c 98/05/12	KG	bugs: kfree, parsing, EEpromDefaults	*
- *	1.20d 98/05/14	KG	bugs: list linkage, clear flag after  	*
- *				reset on startup, code cleanup		*
- *	1.20e 98/05/15	KG	spinlock comments, name space cleanup	*
- *				pLastDCB now part of ACB structure	*
- *				added stats, timeout for 2.1, TagQ bug	*
- *				RESET and INQUIRY interface commands	*
- *	1.20f 98/05/18	KG	spinlocks fixes, max_lun fix, free DCBs	*
- *				for missing LUNs, pending int		*
- *	1.20g 98/05/19	KG	Clean up: Avoid short			*
- *	1.20h 98/05/21	KG	Remove AdaptSCSIID, max_lun ...		*
- *	1.20i 98/05/21	KG	Aiiie: Bug with TagQMask       		*
- *	1.20j 98/05/24	KG	Handle STAT_BUSY, handle pACB->pLinkDCB	*
- *				== 0 in remove_dev and DoingSRB_Done	*
- *	1.20k 98/05/25	KG	DMA_INT	(experimental)	       		*
- *	1.20l 98/05/27	KG	remove DMA_INT; DMA_IDLE cmds added;	*
- *	1.20m 98/06/10	KG	glitch configurable; made some global	*
- *				vars part of ACB; use DC390_readX	*
- *	1.20n 98/06/11	KG	startup params				*
- *	1.20o 98/06/15	KG	added TagMaxNum to boot/module params	*
- *				Device Nr -> Idx, TagMaxNum power of 2  *
- *	1.20p 98/06/17	KG	Docu updates. Reset depends on settings *
- *				pci_set_master added; 2.0.xx: pcibios_*	*
- *				used instead of MechNum things ...	*
- *	1.20q 98/06/23	KG	Changed defaults. Added debug code for	*
- *				removable media and fixed it. TagMaxNum	*
- *				fixed for DC390. Locking: ACB, DRV for	*
- *				better IRQ sharing. Spelling: Queueing	*
- *				Parsing and glitch_cfg changes. Display	*
- *				real SyncSpeed value. Made DisConn	*
- *				functional (!)				*
- *	1.20r 98/06/30	KG	Debug macros, allow disabling DsCn, set	*
- *				BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module	*
- *				param -1 fixed.				*
- *	1.20s 98/08/20	KG	Debug info on abort(), try to check PCI,*
- *				phys_to_bus instead of phys_to_virt,	*
- *				fixed sel. process, fixed locking,	*
- *				added MODULE_XXX infos, changed IRQ	*
- *				request flags, disable DMA_INT		*
- *	1.20t 98/09/07	KG	TagQ report fixed; Write Erase DMA Stat;*
- *				initfunc -> __init; better abort;	*
- *				Timeout for XFER_DONE & BLAST_COMPLETE;	*
- *				Allow up to 33 commands being processed *
- *	2.0a  98/10/14	KG	Max Cmnds back to 17. DMA_Stat clearing *
- *				all flags. Clear within while() loops	*
- *				in DataIn_0/Out_0. Null ptr in dumpinfo	*
- *				for pSRB==0. Better locking during init.*
- *				bios_param() now respects part. table.	*
- *	2.0b  98/10/24	KG	Docu fixes. Timeout Msg in DMA Blast.	*
- *				Disallow illegal idx in INQUIRY/REMOVE	*
- *	2.0c  98/11/19	KG	Cleaned up detect/init for SMP boxes, 	*
- *				Write Erase DMA (1.20t) caused problems	*
- *	2.0d  98/12/25	KG	Christmas release ;-) Message handling  *
- *				completely reworked. Handle target ini-	*
- *				tiated SDTR correctly.			*
- *	2.0d1 99/01/25	KG	Try to handle RESTORE_PTR		*
- *	2.0d2 99/02/08	KG	Check for failure of kmalloc, correct 	*
- *				inclusion of scsicam.h, DelayReset	*
- *	2.0d3 99/05/31	KG	DRIVER_OK -> DID_OK, DID_NO_CONNECT,	*
- *				detect Target mode and warn.		*
- *				pcmd->result handling cleaned up.	*
- *	2.0d4 99/06/01	KG	Cleaned selection process. Found bug	*
- *				which prevented more than 16 tags. Now:	*
- *				24. SDTR cleanup. Cleaner multi-LUN	*
- *				handling. Don't modify ControlRegs/FIFO	*
- *				when connected.				*
- *	2.0d5 99/06/01	KG	Clear DevID, Fix INQUIRY after cfg chg.	*
- *	2.0d6 99/06/02	KG	Added ADD special command to allow cfg.	*
- *				before detection. Reset SYNC_NEGO_DONE	*
- *				after a bus reset.			*
- *	2.0d7 99/06/03	KG	Fixed bugs wrt add,remove commands	*
- *	2.0d8 99/06/04	KG	Removed copying of cmnd into CmdBlock.	*
- *				Fixed Oops in _release().		*
- *	2.0d9 99/06/06	KG	Also tag queue INQUIRY, T_U_R, ...	*
- *				Allow arb. no. of Tagged Cmnds. Max 32	*
- *	2.0d1099/06/20	KG	TagMaxNo changes now honoured! Queueing *
- *				clearified (renamed ..) TagMask handling*
- *				cleaned.				*
- *	2.0d1199/06/28	KG	cmd->result now identical to 2.0d2	*
- *	2.0d1299/07/04	KG	Changed order of processing in IRQ	*
- *	2.0d1399/07/05	KG	Don't update DCB fields if removed	*
- *	2.0d1499/07/05	KG	remove_dev: Move kfree() to the end	*
- *	2.0d1599/07/12	KG	use_new_eh_code: 0, ULONG -> UINT where	*
- *				appropriate				*
- *	2.0d1699/07/13	KG	Reenable StartSCSI interrupt, Retry msg	*
- *	2.0d1799/07/15	KG	Remove debug msg. Disable recfg. when	*
- *				there are queued cmnds			*
- *	2.0d1899/07/18	KG	Selection timeout: Don't requeue	*
- *	2.0d1999/07/18	KG	Abort: Only call scsi_done if dequeued	*
- *	2.0d2099/07/19	KG	Rst_Detect: DoingSRB_Done		*
- *	2.0d2199/08/15	KG	dev_id for request/free_irq, cmnd[0] for*
- *				RETRY, SRBdone does DID_ABORT for the 	*
- *				cmd passed by DC390_reset()		*
- *	2.0d2299/08/25	KG	dev_id fixed. can_queue: 42		*
- *	2.0d2399/08/25	KG	Removed some debugging code. dev_id 	*
- *				now is set to pACB. Use u8,u16,u32. 	*
- *	2.0d2499/11/14	KG	Unreg. I/O if failed IRQ alloc. Call	*
- * 				done () w/ DID_BAD_TARGET in case of	*
- *				missing DCB. We	are old EH!!		*
- *	2.0d2500/01/15	KG	2.3.3x compat from Andreas Schultz	*
- *				set unique_id. Disable RETRY message.	*
- *	2.0d2600/01/29	KG	Go to new EH.				*
- *	2.0d2700/01/31	KG	... but maintain 2.0 compat.		*
- *				and fix DCB freeing			*
- *	2.0d2800/02/14	KG	Queue statistics fixed, dump special cmd*
- *				Waiting_Timer for failed StartSCSI	*
- *				New EH: Don't return cmnds to ML on RST *
- *				Use old EH (don't have new EH fns yet)	*
- * 				Reset: Unlock, but refuse to queue	*
- * 				2.3 __setup function			*
- *	2.0e  00/05/22	KG	Return residual for 2.3			*
- *	2.0e1 00/05/25	KG	Compile fixes for 2.3.99		*
- *	2.0e2 00/05/27	KG	Jeff Garzik's pci_enable_device()	*
- *	2.0e3 00/09/29	KG	Some 2.4 changes. Don't try Sync Nego	*
- *				before INQUIRY has reported ability. 	*
- *				Recognise INQUIRY as scanning command.	*
- *	2.0e4 00/10/13	KG	Allow compilation into 2.4 kernel	*
- *	2.0e5 00/11/17	KG	Store Inq.flags in DCB			*
- *	2.0e6 00/11/22  KG	2.4 init function (Thx to O.Schumann)	*
- * 				2.4 PCI device table (Thx to A.Richter)	*
- *	2.0e7 00/11/28	KG	Allow overriding of BIOS settings	*
- *	2.0f  00/12/20	KG	Handle failed INQUIRYs during scan	*
- *	2.1a  03/11/29  GL, KG	Initial fixing for 2.6. Convert to	*
- *				use the current PCI-mapping API, update	*
- *				command-queuing.			*
- *	2.1b  04/04/13  GL	Fix for 64-bit platforms		*
- *	2.1b1 04/01/31	GL	(applied 05.04) Remove internal		*
- *				command-queuing.			*
- *	2.1b2 04/02/01	CH	(applied 05.04) Fix error-handling	*
- *	2.1c  04/05/23  GL	Update to use the new pci_driver API,	*
- *				some scsi EH updates, more cleanup.	*
- *	2.1d  04/05/27	GL	Moved setting of scan_devices to	*
- *				slave_alloc/_configure/_destroy, as	*
- *				suggested by CH.			*
- ***********************************************************************/
-
-/* DEBUG options */
-//#define DC390_DEBUG0
-//#define DC390_DEBUG1
-//#define DC390_DCBDEBUG
-//#define DC390_PARSEDEBUG
-//#define DC390_REMOVABLEDEBUG
-//#define DC390_LOCKDEBUG
-
-//#define NOP do{}while(0)
-#define C_NOP
-
-/* Debug definitions */
-#ifdef DC390_DEBUG0
-# define DEBUG0(x) x
-#else
-# define DEBUG0(x) C_NOP
-#endif
-#ifdef DC390_DEBUG1
-# define DEBUG1(x) x
-#else
-# define DEBUG1(x) C_NOP
-#endif
-#ifdef DC390_DCBDEBUG
-# define DCBDEBUG(x) x
-#else
-# define DCBDEBUG(x) C_NOP
-#endif
-#ifdef DC390_PARSEDEBUG
-# define PARSEDEBUG(x) x
-#else
-# define PARSEDEBUG(x) C_NOP
-#endif
-#ifdef DC390_REMOVABLEDEBUG
-# define REMOVABLEDEBUG(x) x
-#else
-# define REMOVABLEDEBUG(x) C_NOP
-#endif
-#define DCBDEBUG1(x) C_NOP
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsicam.h>
-#include <scsi/scsi_tcq.h>
-
-#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1d 2004-05-27"
-
-#define PCI_DEVICE_ID_AMD53C974 	PCI_DEVICE_ID_AMD_SCSI
-
-#include "tmscsim.h"
-
-
-static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-
-static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
-static void dc390_Disconnect( struct dc390_acb* pACB );
-static void dc390_Reselect( struct dc390_acb* pACB );
-static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
-static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
-static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
-static void dc390_ResetDevParam(struct dc390_acb* pACB);
-
-static u32	dc390_laststatus = 0;
-static u8	dc390_adapterCnt = 0;
-
-static int disable_clustering;
-module_param(disable_clustering, int, S_IRUGO);
-MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
-
-/* Startup values, to be overriden on the commandline */
-static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
-
-module_param_array(tmscsim, int, NULL, 0);
-MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
-MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
-MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-
-static void *dc390_phase0[]={
-       dc390_DataOut_0,
-       dc390_DataIn_0,
-       dc390_Command_0,
-       dc390_Status_0,
-       dc390_Nop_0,
-       dc390_Nop_0,
-       dc390_MsgOut_0,
-       dc390_MsgIn_0,
-       dc390_Nop_1
-       };
-
-static void *dc390_phase1[]={
-       dc390_DataOutPhase,
-       dc390_DataInPhase,
-       dc390_CommandPhase,
-       dc390_StatusPhase,
-       dc390_Nop_0,
-       dc390_Nop_0,
-       dc390_MsgOutPhase,
-       dc390_MsgInPhase,
-       dc390_Nop_1
-       };
-
-#ifdef DC390_DEBUG1
-static char* dc390_p0_str[] = {
-       "dc390_DataOut_0",
-       "dc390_DataIn_0",
-       "dc390_Command_0",
-       "dc390_Status_0",
-       "dc390_Nop_0",
-       "dc390_Nop_0",
-       "dc390_MsgOut_0",
-       "dc390_MsgIn_0",
-       "dc390_Nop_1"
-       };
-     
-static char* dc390_p1_str[] = {
-       "dc390_DataOutPhase",
-       "dc390_DataInPhase",
-       "dc390_CommandPhase",
-       "dc390_StatusPhase",
-       "dc390_Nop_0",
-       "dc390_Nop_0",
-       "dc390_MsgOutPhase",
-       "dc390_MsgInPhase",
-       "dc390_Nop_1"
-       };
-#endif   
-
-static u8  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
-static u8  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
-static u8  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
-
-/***********************************************************************
- * Functions for the management of the internal structures 
- * (DCBs, SRBs, Queueing)
- *
- **********************************************************************/
-static void inline dc390_start_segment(struct dc390_srb* pSRB)
-{
-	struct scatterlist *psgl = pSRB->pSegmentList;
-
-	/* start new sg segment */
-	pSRB->SGBusAddr = sg_dma_address(psgl);
-	pSRB->SGToBeXferLen = sg_dma_len(psgl);
-}
-
-static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
-{
-	unsigned long xfer = pSRB->SGToBeXferLen - residue;
-
-	/* xfer more bytes transferred */
-	pSRB->SGBusAddr += xfer;
-	pSRB->TotalXferredLen += xfer;
-	pSRB->SGToBeXferLen = residue;
-
-	return xfer;
-}
-
-static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
-{
-   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
-   while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
-     {
-	pDCB = pDCB->pNextDCB;
-	if (pDCB == pACB->pLinkDCB)
-	     return NULL;
-     }
-   DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",	\
-		      pDCB, pDCB->TargetID, pDCB->TargetLUN));
-   return pDCB;
-}
-
-/* Insert SRB oin top of free list */
-static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-    DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
-    pSRB->pNextSRB = pACB->pFreeSRB;
-    pACB->pFreeSRB = pSRB;
-}
-
-static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-    pDCB->GoingSRBCnt++;
-    DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB));
-    /* Append to the list of Going commands */
-    if( pDCB->pGoingSRB )
-	pDCB->pGoingLast->pNextSRB = pSRB;
-    else
-	pDCB->pGoingSRB = pSRB;
-
-    pDCB->pGoingLast = pSRB;
-    /* No next one in sent list */
-    pSRB->pNextSRB = NULL;
-}
-
-static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-	DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
-   if (pSRB == pDCB->pGoingSRB)
-	pDCB->pGoingSRB = pSRB->pNextSRB;
-   else
-     {
-	struct dc390_srb* psrb = pDCB->pGoingSRB;
-	while (psrb && psrb->pNextSRB != pSRB)
-	  psrb = psrb->pNextSRB;
-	if (!psrb) 
-	  { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; }
-	psrb->pNextSRB = pSRB->pNextSRB;
-	if (pSRB == pDCB->pGoingLast)
-	  pDCB->pGoingLast = psrb;
-     }
-   pDCB->GoingSRBCnt--;
-}
-
-static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
-{
-	sg_init_one(sg, addr, length);
-	return sg;
-}
-
-/* Create pci mapping */
-static int dc390_pci_map (struct dc390_srb* pSRB)
-{
-	int error = 0;
-	struct scsi_cmnd *pcmd = pSRB->pcmd;
-	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
-	dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
-
-	/* Map sense buffer */
-	if (pSRB->SRBFlag & AUTO_REQSENSE) {
-		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
-		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
-						     DMA_FROM_DEVICE);
-		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
-
-		/* TODO: error handling */
-		if (pSRB->SGcount != 1)
-			error = 1;
-		DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
-	/* Map SG list */
-	} else if (scsi_sg_count(pcmd)) {
-		int nseg;
-
-		nseg = scsi_dma_map(pcmd);
-
-		pSRB->pSegmentList	= scsi_sglist(pcmd);
-		pSRB->SGcount		= nseg;
-
-		/* TODO: error handling */
-		if (nseg < 0)
-			error = 1;
-		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
-			      __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
-	/* Map single segment */
-	} else
-		pSRB->SGcount = 0;
-
-	return error;
-}
-
-/* Remove pci mapping */
-static void dc390_pci_unmap (struct dc390_srb* pSRB)
-{
-	struct scsi_cmnd *pcmd = pSRB->pcmd;
-	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
-	DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
-
-	if (pSRB->SRBFlag) {
-		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
-		DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
-	} else {
-		scsi_dma_unmap(pcmd);
-		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
-			      __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
-	}
-}
-
-static void __inline__
-dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-	if (pSRB->TagNumber != SCSI_NO_TAG) {
-		pDCB->TagMask &= ~(1 << pSRB->TagNumber);   /* free tag mask */
-		pSRB->TagNumber = SCSI_NO_TAG;
-	}
-}
-
-
-static int
-dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    struct scsi_cmnd *scmd = pSRB->pcmd;
-    struct scsi_device *sdev = scmd->device;
-    u8 cmd, disc_allowed, try_sync_nego;
-
-    pSRB->ScsiPhase = SCSI_NOP0;
-
-    if (pACB->Connected)
-    {
-	// Should not happen normally
-	printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n",
-		pSRB->SRBState, pSRB->SRBFlag);
-	pSRB->SRBState = SRB_READY;
-	pACB->SelConn++;
-	return 1;
-    }
-    if (time_before (jiffies, pACB->last_reset))
-    {
-	DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
-	return 1;
-    }
-    /* KG: Moved pci mapping here */
-    dc390_pci_map(pSRB);
-    /* TODO: error handling */
-    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
-    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
-    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-    DC390_write8 (CtrlReg4, pDCB->CtrlR4);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);		/* Flush FIFO */
-    DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
-            scmd->cmnd[0], pDCB->SyncMode));
-
-    /* Don't disconnect on AUTO_REQSENSE, cause it might be an
-     * Contingent Allegiance Condition (6.6), where no tags should be used.
-     * All other have to be allowed to disconnect to prevent Incorrect 
-     * Initiator Connection (6.8.2/6.5.2) */
-    /* Changed KG, 99/06/06 */
-    if (! (pSRB->SRBFlag & AUTO_REQSENSE))
-	disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
-    else
-	disc_allowed = 0;
-
-    if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
-	(((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
-	  !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
-      try_sync_nego = 1;
-    else
-      try_sync_nego = 0;
-
-    pSRB->MsgCnt = 0;
-    cmd = SEL_W_ATN;
-    DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
-    /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
-    if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && (scmd->flags & SCMD_TAGGED)) {
-	DC390_write8(ScsiFifo, MSG_SIMPLE_TAG);
-	pDCB->TagMask |= 1 << scmd->request->tag;
-	pSRB->TagNumber = scmd->request->tag;
-	DC390_write8(ScsiFifo, scmd->request->tag);
-	DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
-	cmd = SEL_W_ATN3;
-    } else {
-	/* No TagQ */
-//no_tag:
-	DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
-    }
-
-    pSRB->SRBState = SRB_START_;
-
-    if (try_sync_nego)
-      { 
-	u8 Sync_Off = pDCB->SyncOffset;
-        DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
-	pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
-	pSRB->MsgOutBuf[1] = 3;
-	pSRB->MsgOutBuf[2] = EXTENDED_SDTR;
-	pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
-	if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET;
-	pSRB->MsgOutBuf[4] = Sync_Off;
-	pSRB->MsgCnt = 5;
-	//pSRB->SRBState = SRB_MSGOUT_;
-	pSRB->SRBState |= DO_SYNC_NEGO;
-	cmd = SEL_W_ATN_STOP;
-      }
-
-    /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
-    if (cmd != SEL_W_ATN_STOP)
-      {
-	if( pSRB->SRBFlag & AUTO_REQSENSE )
-	  {
-	    DC390_write8 (ScsiFifo, REQUEST_SENSE);
-	    DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
-	    DC390_write8 (ScsiFifo, 0);
-	    DC390_write8 (ScsiFifo, 0);
-	    DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
-	    DC390_write8 (ScsiFifo, 0);
-	    DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
-	  }
-	else	/* write cmnd to bus */ 
-	  {
-	    u8 *ptr; u8 i;
-	    ptr = (u8 *)scmd->cmnd;
-	    for (i = 0; i < scmd->cmd_len; i++)
-	      DC390_write8 (ScsiFifo, *(ptr++));
-	  }
-      }
-    DEBUG0(if (pACB->pActiveDCB)	\
-	   printk (KERN_WARNING "DC390: ActiveDCB != 0\n"));
-    DEBUG0(if (pDCB->pActiveSRB)	\
-	   printk (KERN_WARNING "DC390: ActiveSRB != 0\n"));
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    if (DC390_read8 (Scsi_Status) & INTERRUPT)
-    {
-	dc390_freetag (pDCB, pSRB);
-	DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n",
-		       scmd->device->id, (u8)scmd->device->lun));
-	pSRB->SRBState = SRB_READY;
-	//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-	pACB->SelLost++;
-	return 1;
-    }
-    DC390_write8 (ScsiCmd, cmd);
-    pACB->pActiveDCB = pDCB;
-    pDCB->pActiveSRB = pSRB;
-    pACB->Connected = 1;
-    pSRB->ScsiPhase = SCSI_NOP1;
-    return 0;
-}
-
-
-static void __inline__
-dc390_InvalidCmd(struct dc390_acb* pACB)
-{
-	if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
-		DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-}
-
-
-static irqreturn_t __inline__
-DC390_Interrupt(void *dev_id)
-{
-    struct dc390_acb *pACB = dev_id;
-    struct dc390_dcb *pDCB;
-    struct dc390_srb *pSRB;
-    u8  sstatus=0;
-    u8  phase;
-    void   (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
-    u8  istate, istatus;
-
-    sstatus = DC390_read8 (Scsi_Status);
-    if( !(sstatus & INTERRUPT) )
-	return IRQ_NONE;
-
-    DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
-
-    //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
-    //dstatus = DC390_read8 (DMA_Status);
-    //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-    spin_lock_irq(pACB->pScsiHost->host_lock);
-
-    istate = DC390_read8 (Intern_State);
-    istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
-
-    DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
-    dc390_laststatus &= ~0x00ffffff;
-    dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
-
-    if (sstatus & ILLEGAL_OP_ERR)
-    {
-	printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
-	dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
-    }
-	
-    else if (istatus &  INVALID_CMD)
-    {
-	printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus);
-	dc390_InvalidCmd( pACB );
-	goto unlock;
-    }
-
-    if (istatus &  SCSI_RESET)
-    {
-	dc390_ScsiRstDetect( pACB );
-	goto unlock;
-    }
-
-    if (istatus &  DISCONNECTED)
-    {
-	dc390_Disconnect( pACB );
-	goto unlock;
-    }
-
-    if (istatus &  RESELECTED)
-    {
-	dc390_Reselect( pACB );
-	goto unlock;
-    }
-
-    else if (istatus & (SELECTED | SEL_ATTENTION))
-    {
-	printk (KERN_ERR "DC390: Target mode not supported!\n");
-	goto unlock;
-    }
-
-    if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
-    {
-	pDCB = pACB->pActiveDCB;
-	if (!pDCB)
-	{
-		printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
-		goto unlock;
-	}
-	pSRB = pDCB->pActiveSRB;
-	if( pDCB->DCBFlag & ABORT_DEV_ )
-	  dc390_EnableMsgOut_Abort (pACB, pSRB);
-
-	phase = pSRB->ScsiPhase;
-	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
-	stateV = (void *) dc390_phase0[phase];
-	( *stateV )( pACB, pSRB, &sstatus );
-
-	pSRB->ScsiPhase = sstatus & 7;
-	phase = (u8) sstatus & 7;
-	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
-	stateV = (void *) dc390_phase1[phase];
-	( *stateV )( pACB, pSRB, &sstatus );
-    }
-
- unlock:
-    spin_unlock_irq(pACB->pScsiHost->host_lock);
-    return IRQ_HANDLED;
-}
-
-static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
-{
-    irqreturn_t ret;
-    DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
-    /* Locking is done in DC390_Interrupt */
-    ret = DC390_Interrupt(dev_id);
-    DEBUG1(printk (".. IRQ returned\n"));
-    return ret;
-}
-
-static void
-dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   sstatus;
-    u32  ResidCnt;
-    u8   dstate = 0;
-
-    sstatus = *psstatus;
-
-    if( !(pSRB->SRBState & SRB_XFERPAD) )
-    {
-	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
-	    pSRB->SRBStatus |= PARITY_ERROR;
-
-	if( sstatus & COUNT_2_ZERO )
-	{
-	    unsigned long timeout = jiffies + HZ;
-
-	    /* Function called from the ISR with the host_lock held and interrupts disabled */
-	    if (pSRB->SGToBeXferLen)
-		while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
-		    spin_unlock_irq(pACB->pScsiHost->host_lock);
-		    udelay(50);
-		    spin_lock_irq(pACB->pScsiHost->host_lock);
-		}
-	    if (!time_before(jiffies, timeout))
-		printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
-			DC390_read32 (DMA_Wk_ByteCntr));
-	    dc390_laststatus &= ~0xff000000;
-	    dc390_laststatus |= dstate << 24;
-	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
-	    pSRB->SGIndex++;
-	    if( pSRB->SGIndex < pSRB->SGcount )
-	    {
-		pSRB->pSegmentList++;
-
-		dc390_start_segment(pSRB);
-	    }
-	    else
-		pSRB->SGToBeXferLen = 0;
-	}
-	else
-	{
-	    ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
-		    (((u32) DC390_read8 (CtcReg_High) << 16) |
-		     ((u32) DC390_read8 (CtcReg_Mid) << 8) |
-		     (u32) DC390_read8 (CtcReg_Low));
-
-	    dc390_advance_segment(pSRB, ResidCnt);
-	}
-    }
-    if ((*psstatus & 7) != SCSI_DATA_OUT)
-    {
-	    DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
-	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    }	    
-}
-
-static void
-dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   sstatus, residual, bval;
-    u32  ResidCnt, i;
-    unsigned long   xferCnt;
-
-    sstatus = *psstatus;
-
-    if( !(pSRB->SRBState & SRB_XFERPAD) )
-    {
-	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
-	    pSRB->SRBStatus |= PARITY_ERROR;
-
-	if( sstatus & COUNT_2_ZERO )
-	{
-	    int dstate = 0;
-	    unsigned long timeout = jiffies + HZ;
-
-	    /* Function called from the ISR with the host_lock held and interrupts disabled */
-	    if (pSRB->SGToBeXferLen)
-		while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
-		    spin_unlock_irq(pACB->pScsiHost->host_lock);
-		    udelay(50);
-		    spin_lock_irq(pACB->pScsiHost->host_lock);
-		}
-	    if (!time_before(jiffies, timeout)) {
-		printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
-			DC390_read32 (DMA_Wk_ByteCntr));
-		printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
-	    }
-	    dc390_laststatus &= ~0xff000000;
-	    dc390_laststatus |= dstate << 24;
-	    DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16)	\
-		+ ((unsigned long) DC390_read8 (CtcReg_Mid) << 8)		\
-		+ ((unsigned long) DC390_read8 (CtcReg_Low)));
-	    DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
-
-	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-
-	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
-	    pSRB->SGIndex++;
-	    if( pSRB->SGIndex < pSRB->SGcount )
-	    {
-		pSRB->pSegmentList++;
-
-		dc390_start_segment(pSRB);
-	    }
-	    else
-		pSRB->SGToBeXferLen = 0;
-	}
-	else	/* phase changed */
-	{
-	    residual = 0;
-	    bval = DC390_read8 (Current_Fifo);
-	    while( bval & 0x1f )
-	    {
-		DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
-		if( (bval & 0x1f) == 1 )
-		{
-		    for(i=0; i < 0x100; i++)
-		    {
-			bval = DC390_read8 (Current_Fifo);
-			if( !(bval & 0x1f) )
-			    goto din_1;
-			else if( i == 0x0ff )
-			{
-			    residual = 1;   /* ;1 residual byte */
-			    goto din_1;
-			}
-		    }
-		}
-		else
-		    bval = DC390_read8 (Current_Fifo);
-	    }
-din_1:
-	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
-	    for (i = 0xa000; i; i--)
-	    {
-		bval = DC390_read8 (DMA_Status);
-		if (bval & BLAST_COMPLETE)
-		    break;
-	    }
-	    /* It seems a DMA Blast abort isn't that bad ... */
-	    if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
-	    //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-	    dc390_laststatus &= ~0xff000000;
-	    dc390_laststatus |= bval << 24;
-
-	    DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
-	    ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
-			((u32) DC390_read8 (CtcReg_Mid) << 8)) |
-		    (u32) DC390_read8 (CtcReg_Low);
-
-	    xferCnt = dc390_advance_segment(pSRB, ResidCnt);
-
-	    if (residual) {
-		size_t count = 1;
-		size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
-		unsigned long flags;
-		u8 *ptr;
-
-		bval = DC390_read8 (ScsiFifo);	    /* get one residual byte */
-
-		local_irq_save(flags);
-		ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
-		if (likely(ptr)) {
-			*(ptr + offset) = bval;
-			scsi_kunmap_atomic_sg(ptr);
-		}
-		local_irq_restore(flags);
-		WARN_ON(!ptr);
-
-		/* 1 more byte read */
-		xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
-	    }
-	    DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
-			   pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
-	}
-    }
-    if ((*psstatus & 7) != SCSI_DATA_IN)
-    {
-	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-    }
-}
-
-static void
-dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-
-    pSRB->TargetStatus = DC390_read8 (ScsiFifo);
-    //udelay (1);
-    pSRB->EndMessage = DC390_read8 (ScsiFifo);	/* get message */
-
-    *psstatus = SCSI_NOP0;
-    pSRB->SRBState = SRB_COMPLETED;
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-}
-
-static void
-dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
-	*psstatus = SCSI_NOP0;
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void __inline__
-dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
-{
-  DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-  DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-  DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-  DC390_write8 (CtrlReg4, pDCB->CtrlR4);
-  dc390_SetXferRate (pACB, pDCB);
-}
-
-
-#ifdef DC390_DEBUG0
-static void
-dc390_printMsg (u8 *MsgBuf, u8 len)
-{
-  int i;
-  printk (" %02x", MsgBuf[0]);
-  for (i = 1; i < len; i++)
-    printk (" %02x", MsgBuf[i]);
-  printk ("\n");
-}
-#endif
-
-#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
-
-/* reject_msg */
-static void __inline__
-dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
-  pSRB->MsgCnt = 1;
-  DC390_ENABLE_MSGOUT;
-  DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
-}
-
-/* abort command */
-static void
-dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
-{
-    pSRB->MsgOutBuf[0] = ABORT; 
-    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
-    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
-static struct dc390_srb*
-dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
-{
-  struct dc390_srb* pSRB = pDCB->pGoingSRB;
-
-  if (pSRB)
-    {
-	struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
-	pSRB = (struct dc390_srb *)scmd->host_scribble;
-
-	if (pDCB->DCBFlag & ABORT_DEV_)
-	{
-	  pSRB->SRBState = SRB_ABORT_SENT;
-	  dc390_EnableMsgOut_Abort( pACB, pSRB );
-	}
-
-	if (!(pSRB->SRBState & SRB_DISCONNECT))
-		goto mingx0;
-
-	pDCB->pActiveSRB = pSRB;
-	pSRB->SRBState = SRB_DATA_XFER;
-    }
-  else
-    {
-    mingx0:
-      pSRB = pACB->pTmpSRB;
-      pSRB->SRBState = SRB_UNEXPECT_RESEL;
-      pDCB->pActiveSRB = pSRB;
-      pSRB->MsgOutBuf[0] = ABORT_TAG;
-      pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
-    }
-  return pSRB;
-}
-
-
-/* set async transfer mode */
-static void 
-dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
-  if (!(pSRB->SRBState & DO_SYNC_NEGO)) 
-    printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
-  pSRB->SRBState &= ~DO_SYNC_NEGO;
-  pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
-  pDCB->SyncPeriod = 0;
-  pDCB->SyncOffset = 0;
-  //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
-  pDCB->CtrlR3 = FAST_CLK;	/* fast clock / normal scsi */
-  pDCB->CtrlR4 &= 0x3f;
-  pDCB->CtrlR4 |= pACB->glitch_cfg;	/* glitch eater */
-  dc390_reprog (pACB, pDCB);
-}
-
-/* set sync transfer mode */
-static void
-dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  u8 bval;
-  u16 wval, wval1;
-  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
-  u8 oldsyncperiod = pDCB->SyncPeriod;
-  u8 oldsyncoffset = pDCB->SyncOffset;
-  
-  if (!(pSRB->SRBState & DO_SYNC_NEGO))
-    {
-      printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", 
-	      pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
-
-      /* reject */
-      //dc390_MsgIn_reject (pACB, pSRB);
-      //return dc390_MsgIn_set_async (pACB, pSRB);
-
-      /* Reply with corrected SDTR Message */
-      if (pSRB->MsgInBuf[4] > 15)
-	{ 
-	  printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
-	  pSRB->MsgInBuf[4] = 15;
-	}
-      if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
-	{
-	  printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
-	  pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
-	}
-      memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
-      pSRB->MsgCnt = 5;
-      DC390_ENABLE_MSGOUT;
-    }
-
-  pSRB->SRBState &= ~DO_SYNC_NEGO;
-  pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
-  pDCB->SyncOffset &= 0x0f0;
-  pDCB->SyncOffset |= pSRB->MsgInBuf[4];
-  pDCB->NegoPeriod = pSRB->MsgInBuf[3];
-
-  wval = (u16) pSRB->MsgInBuf[3];
-  wval = wval << 2; wval -= 3; wval1 = wval / 25;	/* compute speed */
-  if( (wval1 * 25) != wval) wval1++;
-  bval = FAST_CLK+FAST_SCSI;	/* fast clock / fast scsi */
-
-  pDCB->CtrlR4 &= 0x3f;		/* Glitch eater: 12ns less than normal */
-  if (pACB->glitch_cfg != NS_TO_GLITCH(0))
-    pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
-  else
-    pDCB->CtrlR4 |= NS_TO_GLITCH(0);
-  if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
-
-  if (wval1 >= 8)
-    {
-      wval1--;	/* Timing computation differs by 1 from FAST_SCSI */
-      bval = FAST_CLK;		/* fast clock / normal scsi */
-      pDCB->CtrlR4 |= pACB->glitch_cfg; 	/* glitch eater */
-    }
-
-  pDCB->CtrlR3 = bval;
-  pDCB->SyncPeriod = (u8)wval1;
-  
-  if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
-    {
-      if (! (bval & FAST_SCSI)) wval1++;
-      printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, 
-	      40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
-    }
-  
-  dc390_reprog (pACB, pDCB);
-}
-
-
-/* handle RESTORE_PTR */
-/* This doesn't look very healthy... to-be-fixed */
-static void 
-dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-    struct scsi_cmnd *pcmd = pSRB->pcmd;
-    struct scatterlist *psgl;
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGIndex = 0;
-    if (scsi_sg_count(pcmd)) {
-	size_t saved;
-	pSRB->pSegmentList = scsi_sglist(pcmd);
-	psgl = pSRB->pSegmentList;
-	//dc390_pci_sync(pSRB);
-
-	while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
-	{
-	    pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
-	    pSRB->SGIndex++;
-	    if( pSRB->SGIndex < pSRB->SGcount )
-	    {
-		pSRB->pSegmentList++;
-
-		dc390_start_segment(pSRB);
-	    }
-	    else
-		pSRB->SGToBeXferLen = 0;
-	}
-
-	saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
-	pSRB->SGToBeXferLen -= saved;
-	pSRB->SGBusAddr += saved;
-	printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
-		pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
-
-    } else {
-	 pSRB->SGcount = 0;
-	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
-    }
-
-  pSRB->TotalXferredLen = pSRB->Saved_Ptr;
-}
-
-
-/* According to the docs, the AM53C974 reads the message and 
- * generates a Successful Operation IRQ before asserting ACK for
- * the last byte (how does it know whether it's the last ?) */
-/* The old code handled it in another way, indicating, that on
- * every message byte an IRQ is generated and every byte has to
- * be manually ACKed. Hmmm ?  (KG, 98/11/28) */
-/* The old implementation was correct. Sigh! */
-
-/* Check if the message is complete */
-static u8 __inline__
-dc390_MsgIn_complete (u8 *msgbuf, u32 len)
-{ 
-  if (*msgbuf == EXTENDED_MESSAGE)
-  {
-	if (len < 2) return 0;
-	if (len < msgbuf[1] + 2) return 0;
-  }
-  else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
-	if (len < 2) return 0;
-  return 1;
-}
-
-
-
-/* read and eval received messages */
-static void
-dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
-
-    /* Read the msg */
-
-    pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
-    //pSRB->SRBState = 0;
-
-    /* Msg complete ? */
-    if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
-      {
-	DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
-	/* Now eval the msg */
-	switch (pSRB->MsgInBuf[0]) 
-	  {
-	  case DISCONNECT: 
-	    pSRB->SRBState = SRB_DISCONNECT; break;
-	    
-	  case SIMPLE_QUEUE_TAG:
-	  case HEAD_OF_QUEUE_TAG:
-	  case ORDERED_QUEUE_TAG:
-	    pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
-	    break;
-	    
-	  case MESSAGE_REJECT: 
-	    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-	    pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
-	    if( pSRB->SRBState & DO_SYNC_NEGO)
-	      dc390_MsgIn_set_async (pACB, pSRB);
-	    break;
-	    
-	  case EXTENDED_MESSAGE:
-	    /* reject every extended msg but SDTR */
-	    if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
-	      dc390_MsgIn_reject (pACB, pSRB);
-	    else
-	      {
-		if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
-		  dc390_MsgIn_set_async (pACB, pSRB);
-		else
-		  dc390_MsgIn_set_sync (pACB, pSRB);
-	      }
-	    
-	    // nothing has to be done
-	  case COMMAND_COMPLETE: break;
-	    
-	    // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
-	    // scsi command. Thanks, Gerard, for pointing it out.
-	  case SAVE_POINTERS: 
-	    pSRB->Saved_Ptr = pSRB->TotalXferredLen;
-	    break;
-	    // The device might want to restart transfer with a RESTORE
-	  case RESTORE_POINTERS:
-	    DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n"));
-	    dc390_restore_ptr (pACB, pSRB);
-	    break;
-
-	    // reject unknown messages
-	  default: dc390_MsgIn_reject (pACB, pSRB);
-	  }
-	
-	/* Clear counter and MsgIn state */
-	pSRB->SRBState &= ~SRB_MSGIN;
-	pACB->MsgLen = 0;
-      }
-
-    *psstatus = SCSI_NOP0;
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void
-dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
-{
-    unsigned long  lval;
-    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
-
-    if (pSRB == pACB->pTmpSRB)
-    {
-	if (pDCB)
-		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
-	else
-		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
-	/* Try to recover - some broken disks react badly to tagged INQUIRY */
-	if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
-		pSRB = pDCB->pGoingSRB;
-		pDCB->pActiveSRB = pSRB;
-	} else {
-		pSRB->pSRBDCB = pDCB;
-		dc390_EnableMsgOut_Abort(pACB, pSRB);
-		if (pDCB)
-			pDCB->DCBFlag |= ABORT_DEV;
-		return;
-	}
-    }
-
-    if( pSRB->SGIndex < pSRB->SGcount )
-    {
-	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-	if( !pSRB->SGToBeXferLen )
-	{
-	    dc390_start_segment(pSRB);
-
-	    DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
-	}
-	lval = pSRB->SGToBeXferLen;
-	DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
-	DC390_write8 (CtcReg_Low, (u8) lval);
-	lval >>= 8;
-	DC390_write8 (CtcReg_Mid, (u8) lval);
-	lval >>= 8;
-	DC390_write8 (CtcReg_High, (u8) lval);
-
-	DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
-	DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
-
-	//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-	pSRB->SRBState = SRB_DATA_XFER;
-
-	DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
-
-	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
-	//DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
-	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
-    }
-    else    /* xfer pad */
-    {
-	if( pSRB->SGcount )
-	{
-	    pSRB->AdaptStatus = H_OVER_UNDER_RUN;
-	    pSRB->SRBStatus |= OVER_RUN;
-	    DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
-	}
-	DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
-	DC390_write8 (CtcReg_Low, 0);
-	DC390_write8 (CtcReg_Mid, 0);
-	DC390_write8 (CtcReg_High, 0);
-
-	pSRB->SRBState |= SRB_XFERPAD;
-	DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
-/*
-	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-*/
-    }
-}
-
-
-static void
-dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
-}
-
-static void
-dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
-}
-
-static void
-dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    struct dc390_dcb*   pDCB;
-    u8  i, cnt;
-    u8     *ptr;
-
-    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
-    {
-	cnt = (u8) pSRB->pcmd->cmd_len;
-	ptr = (u8 *) pSRB->pcmd->cmnd;
-	for(i=0; i < cnt; i++)
-	    DC390_write8 (ScsiFifo, *(ptr++));
-    }
-    else
-    {
-	DC390_write8 (ScsiFifo, REQUEST_SENSE);
-	pDCB = pACB->pActiveDCB;
-	DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
-	DC390_write8 (ScsiFifo, 0);
-	DC390_write8 (ScsiFifo, 0);
-	DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
-	DC390_write8 (ScsiFifo, 0);
-	DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
-    }
-    pSRB->SRBState = SRB_COMMAND;
-    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-}
-
-static void
-dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pSRB->SRBState = SRB_STATUS;
-    DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   bval, i, cnt;
-    u8     *ptr;
-    struct dc390_dcb*    pDCB;
-
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pDCB = pACB->pActiveDCB;
-    if( !(pSRB->SRBState & SRB_MSGOUT) )
-    {
-	cnt = pSRB->MsgCnt;
-	if( cnt )
-	{
-	    ptr = (u8 *) pSRB->MsgOutBuf;
-	    for(i=0; i < cnt; i++)
-		DC390_write8 (ScsiFifo, *(ptr++));
-	    pSRB->MsgCnt = 0;
-	    if( (pDCB->DCBFlag & ABORT_DEV_) &&
-		(pSRB->MsgOutBuf[0] == ABORT) )
-		pSRB->SRBState = SRB_ABORT_SENT;
-	}
-	else
-	{
-	    bval = ABORT;	/* ??? MSG_NOP */
-	    if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
-		(pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
-		(pSRB->SRBFlag & AUTO_REQSENSE) )
-	    {
-		if( pDCB->SyncMode & SYNC_ENABLE )
-		    goto  mop1;
-	    }
-	    DC390_write8 (ScsiFifo, bval);
-	}
-	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    }
-    else
-    {
-mop1:
-        printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
-	DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
-	DC390_write8 (ScsiFifo, 3);	/*    ;length of extended msg */
-	DC390_write8 (ScsiFifo, EXTENDED_SDTR);	/*    ; sync nego */
-	DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
-	if (pDCB->SyncOffset & 0x0f)
-		    DC390_write8 (ScsiFifo, pDCB->SyncOffset);
-	else
-		    DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);		    
-	pSRB->SRBState |= DO_SYNC_NEGO;
-	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    }
-}
-
-static void
-dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    if( !(pSRB->SRBState & SRB_MSGIN) )
-    {
-	pSRB->SRBState &= ~SRB_DISCONNECT;
-	pSRB->SRBState |= SRB_MSGIN;
-    }
-    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-
-static void
-dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
-{
-    u8  bval, i, cnt;
-    struct dc390_dcb*   ptr;
-
-    if( !(pDCB->TargetLUN) )
-    {
-	if( !pACB->scan_devices )
-	{
-	    ptr = pACB->pLinkDCB;
-	    cnt = pACB->DCBCnt;
-	    bval = pDCB->TargetID;
-	    for(i=0; i<cnt; i++)
-	    {
-		if( ptr->TargetID == bval )
-		{
-		    ptr->SyncPeriod = pDCB->SyncPeriod;
-		    ptr->SyncOffset = pDCB->SyncOffset;
-		    ptr->CtrlR3 = pDCB->CtrlR3;
-		    ptr->CtrlR4 = pDCB->CtrlR4;
-		    ptr->SyncMode = pDCB->SyncMode;
-		}
-		ptr = ptr->pNextDCB;
-	    }
-	}
-    }
-    return;
-}
-
-
-static void
-dc390_Disconnect( struct dc390_acb* pACB )
-{
-    struct dc390_dcb *pDCB;
-    struct dc390_srb *pSRB, *psrb;
-    u8  i, cnt;
-
-    DEBUG0(printk(KERN_INFO "DISC,"));
-
-    if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
-    pACB->Connected = 0;
-    pDCB = pACB->pActiveDCB;
-    if (!pDCB)
-     {
-	DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
-	       pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
-	mdelay(400);
-	DC390_read8 (INT_Status);	/* Reset Pending INT */
-	DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-	return;
-     }
-    DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-    pSRB = pDCB->pActiveSRB;
-    pACB->pActiveDCB = NULL;
-    pSRB->ScsiPhase = SCSI_NOP0;
-    if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
-	pSRB->SRBState = 0;
-    else if( pSRB->SRBState & SRB_ABORT_SENT )
-    {
-	pDCB->TagMask = 0;
-	pDCB->DCBFlag = 0;
-	cnt = pDCB->GoingSRBCnt;
-	pDCB->GoingSRBCnt = 0;
-	pSRB = pDCB->pGoingSRB;
-	for( i=0; i < cnt; i++)
-	{
-	    psrb = pSRB->pNextSRB;
-	    dc390_Free_insert (pACB, pSRB);
-	    pSRB = psrb;
-	}
-	pDCB->pGoingSRB = NULL;
-    }
-    else
-    {
-	if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
-	   !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
-	{	/* Selection time out */
-		pSRB->AdaptStatus = H_SEL_TIMEOUT;
-		pSRB->TargetStatus = 0;
-		goto  disc1;
-	}
-	else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
-	{
-disc1:
-	    dc390_freetag (pDCB, pSRB);
-	    pDCB->pActiveSRB = NULL;
-	    pSRB->SRBState = SRB_FREE;
-	    dc390_SRBdone( pACB, pDCB, pSRB);
-	}
-    }
-    pACB->MsgLen = 0;
-}
-
-
-static void
-dc390_Reselect( struct dc390_acb* pACB )
-{
-    struct dc390_dcb*   pDCB;
-    struct dc390_srb*   pSRB;
-    u8  id, lun;
-
-    DEBUG0(printk(KERN_INFO "RSEL,"));
-    pACB->Connected = 1;
-    pDCB = pACB->pActiveDCB;
-    if( pDCB )
-    {	/* Arbitration lost but Reselection won */
-	DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
-	pSRB = pDCB->pActiveSRB;
-	if( !( pACB->scan_devices ) )
-	{
-	    struct scsi_cmnd *pcmd = pSRB->pcmd;
-	    scsi_set_resid(pcmd, scsi_bufflen(pcmd));
-	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-	    dc390_Going_remove(pDCB, pSRB);
-	    dc390_Free_insert(pACB, pSRB);
-	    pcmd->scsi_done (pcmd);
-	    DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
-	}
-    }
-    /* Get ID */
-    lun = DC390_read8 (ScsiFifo);
-    DEBUG0(printk ("Dev %02x,", lun));
-    if (!(lun & (1 << pACB->pScsiHost->this_id)))
-      printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
-    else
-      lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
-    id = 0; while (lun >>= 1) id++;
-    /* Get LUN */
-    lun = DC390_read8 (ScsiFifo);
-    if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
-    lun &= 7;
-    DEBUG0(printk ("(%02i-%i),", id, lun));
-    pDCB = dc390_findDCB (pACB, id, lun);
-    if (!pDCB)
-    {
-	printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
-		    id, lun);
-	return;
-    }
-    pACB->pActiveDCB = pDCB;
-    /* TagQ: We expect a message soon, so never mind the exact SRB */
-    if( pDCB->SyncMode & EN_TAG_QUEUEING )
-    {
-	pSRB = pACB->pTmpSRB;
-	pDCB->pActiveSRB = pSRB;
-    }
-    else
-    {
-	pSRB = pDCB->pActiveSRB;
-	if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
-	{
-	    pSRB= pACB->pTmpSRB;
-	    pSRB->SRBState = SRB_UNEXPECT_RESEL;
-	    printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
-		    id, lun);
-	    pDCB->pActiveSRB = pSRB;
-	    dc390_EnableMsgOut_Abort ( pACB, pSRB );
-	}
-	else
-	{
-	    if( pDCB->DCBFlag & ABORT_DEV_ )
-	    {
-		pSRB->SRBState = SRB_ABORT_SENT;
-		printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
-			id, lun);
-		dc390_EnableMsgOut_Abort( pACB, pSRB );
-	    }
-	    else
-		pSRB->SRBState = SRB_DATA_XFER;
-	}
-    }
-
-    DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
-    pSRB->ScsiPhase = SCSI_NOP0;
-    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
-    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
-    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-    DC390_write8 (CtrlReg4, pDCB->CtrlR4);	/* ; Glitch eater */
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);	/* ;to release the /ACK signal */
-}
-
-static int __inline__
-dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-	struct scsi_cmnd *pcmd;
-
-	pcmd = pSRB->pcmd;
-
-	REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
-			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
-	pSRB->SRBFlag |= AUTO_REQSENSE;
-	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-	pSRB->AdaptStatus = 0;
-	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-	/* We are called from SRBdone, original PCI mapping has been removed
-	 * already, new one is set up from StartSCSI */
-	pSRB->SGIndex = 0;
-
-	pSRB->TotalXferredLen = 0;
-	pSRB->SGToBeXferLen = 0;
-	return dc390_StartSCSI(pACB, pDCB, pSRB);
-}
-
-
-static void
-dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    u8 status;
-    struct scsi_cmnd *pcmd;
-
-    pcmd = pSRB->pcmd;
-    /* KG: Moved pci_unmap here */
-    dc390_pci_unmap(pSRB);
-
-    status = pSRB->TargetStatus;
-
-    DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
-    if(pSRB->SRBFlag & AUTO_REQSENSE)
-    {	/* Last command was a Request Sense */
-	pSRB->SRBFlag &= ~AUTO_REQSENSE;
-	pSRB->AdaptStatus = 0;
-	pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
-
-	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
-	if (status == SAM_STAT_CHECK_CONDITION)
-	    pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
-	else /* Retry */
-	{
-	    if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
-	    {
-		/* Don't retry on TEST_UNIT_READY */
-		pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
-		REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
-		       (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
-	    } else {
-		SET_RES_DRV(pcmd->result, DRIVER_SENSE);
-		//pSRB->ScsiCmdLen	 = (u8) (pSRB->Segment1[0] >> 8);
-		DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
-		pSRB->TotalXferredLen = 0;
-		SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-	    }
-	}
-	goto cmd_done;
-    }
-    if( status )
-    {
-	if (status == SAM_STAT_CHECK_CONDITION)
-	{
-	    if (dc390_RequestSense(pACB, pDCB, pSRB)) {
-		SET_RES_DID(pcmd->result, DID_ERROR);
-		goto cmd_done;
-	    }
-	    return;
-	}
-	else if (status == SAM_STAT_TASK_SET_FULL)
-	{
-	    scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-	    DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
-	    pSRB->TotalXferredLen = 0;
-	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-	}
-	else if (status == SAM_STAT_BUSY &&
-		 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
-		 pACB->scan_devices)
-	{
-	    pSRB->AdaptStatus = 0;
-	    pSRB->TargetStatus = status;
-	    pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
-	}
-	else
-	{   /* Another error */
-	    pSRB->TotalXferredLen = 0;
-	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-	    goto cmd_done;
-	}
-    }
-    else
-    {	/*  Target status == 0 */
-	status = pSRB->AdaptStatus;
-	if (status == H_OVER_UNDER_RUN)
-	{
-	    pSRB->TargetStatus = 0;
-	    SET_RES_DID(pcmd->result,DID_OK);
-	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
-	}
-	else if (status == H_SEL_TIMEOUT)
-	{
-	    pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
-	    /* Devices are removed below ... */
-	}
-	else if( pSRB->SRBStatus & PARITY_ERROR)
-	{
-	    //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
-	    SET_RES_DID(pcmd->result,DID_PARITY);
-	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
-	}
-	else		       /* No error */
-	{
-	    pSRB->AdaptStatus = 0;
-	    pSRB->TargetStatus = 0;
-	    SET_RES_DID(pcmd->result,DID_OK);
-	}
-    }
-
-cmd_done:
-    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
-
-    dc390_Going_remove (pDCB, pSRB);
-    /* Add to free list */
-    dc390_Free_insert (pACB, pSRB);
-
-    DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
-    pcmd->scsi_done (pcmd);
-
-    return;
-}
-
-
-/* Remove all SRBs from Going list and inform midlevel */
-static void
-dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
-{
-    struct dc390_dcb *pDCB, *pdcb;
-    struct dc390_srb *psrb, *psrb2;
-    int i;
-    struct scsi_cmnd *pcmd;
-
-    pDCB = pACB->pLinkDCB;
-    pdcb = pDCB;
-    if (! pdcb) return;
-    do
-    {
-	psrb = pdcb->pGoingSRB;
-	for (i = 0; i < pdcb->GoingSRBCnt; i++)
-	{
-	    psrb2 = psrb->pNextSRB;
-	    pcmd = psrb->pcmd;
-	    dc390_Free_insert (pACB, psrb);
-	    psrb  = psrb2;
-	}
-	pdcb->GoingSRBCnt = 0;
-	pdcb->pGoingSRB = NULL;
-	pdcb->TagMask = 0;
-	pdcb = pdcb->pNextDCB;
-    } while( pdcb != pDCB );
-}
-
-
-static void
-dc390_ResetSCSIBus( struct dc390_acb* pACB )
-{
-    //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
-    //udelay (250);
-    //DC390_write8 (ScsiCmd, NOP_CMD);
-
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
-    pACB->Connected = 0;
-
-    return;
-}
-
-static void
-dc390_ScsiRstDetect( struct dc390_acb* pACB )
-{
-    printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
-    //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
-
-    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    /* Unlock before ? */
-    /* delay half a second */
-    udelay (1000);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pACB->last_reset = jiffies + 5*HZ/2
-		    + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-    pACB->Connected = 0;
-
-    if( pACB->ACBFlag & RESET_DEV )
-	pACB->ACBFlag |= RESET_DONE;
-    else
-    {   /* Reset was issued by sb else */
-	pACB->ACBFlag |= RESET_DETECT;
-
-	dc390_ResetDevParam( pACB );
-	dc390_DoingSRB_Done( pACB, NULL);
-	//dc390_RecoverSRB( pACB );
-	pACB->pActiveDCB = NULL;
-	pACB->ACBFlag = 0;
-    }
-    return;
-}
-
-static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
-		void (*done)(struct scsi_cmnd *))
-{
-	struct scsi_device *sdev = cmd->device;
-	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
-	struct dc390_dcb *dcb = sdev->hostdata;
-	struct dc390_srb *srb;
-
-	if (sdev->queue_depth <= dcb->GoingSRBCnt)
-		goto device_busy;
-	if (acb->pActiveDCB)
-		goto host_busy;
-	if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
-		goto host_busy;
-
-	srb = acb->pFreeSRB;
-	if (unlikely(srb == NULL))
-		goto host_busy;
-
-	cmd->scsi_done = done;
-	cmd->result = 0;
-	acb->Cmds++;
-
-	acb->pFreeSRB = srb->pNextSRB;
-	srb->pNextSRB = NULL;
-
-	srb->pSRBDCB = dcb;
-	srb->pcmd = cmd;
-	cmd->host_scribble = (char *)srb;
-    
-	srb->SGIndex = 0;
-	srb->AdaptStatus = 0;
-	srb->TargetStatus = 0;
-	srb->MsgCnt = 0;
-
-	srb->SRBStatus = 0;
-	srb->SRBFlag = 0;
-	srb->SRBState = 0;
-	srb->TotalXferredLen = 0;
-	srb->SGBusAddr = 0;
-	srb->SGToBeXferLen = 0;
-	srb->ScsiPhase = 0;
-	srb->EndMessage = 0;
-	srb->TagNumber = SCSI_NO_TAG;
-
-	if (dc390_StartSCSI(acb, dcb, srb)) {
-		dc390_Free_insert(acb, srb);
-		goto host_busy;
-	}
-
-	dc390_Going_append(dcb, srb);
-
-	return 0;
-
- host_busy:
-	return SCSI_MLQUEUE_HOST_BUSY;
-
- device_busy:
-	return SCSI_MLQUEUE_DEVICE_BUSY;
-}
-
-static DEF_SCSI_QCMD(DC390_queuecommand)
-
-static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-    struct pci_dev *pdev;
-    u16 pstat;
-
-    if (!pDCB) pDCB = pACB->pActiveDCB;
-    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
-
-    if (pSRB) 
-    {
-	printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",
-		pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
-		pSRB->ScsiPhase);
-	printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
-    }
-    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);
-    printk ("DC390: Register dump: SCSI block:\n");
-    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
-    printk ("DC390:  %06x   %02x   %02x   %02x",
-	    DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
-	    DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
-    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",
-	    DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
-	    DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
-    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
-    if (DC390_read8(Current_Fifo) & 0x1f)
-      {
-	printk ("DC390: FIFO:");
-	while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));
-	printk ("\n");
-      }
-    printk ("DC390: Register dump: DMA engine:\n");
-    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
-    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
-	    DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
-	    DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
-	    DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
-    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-    pdev = pACB->pdev;
-    pci_read_config_word(pdev, PCI_STATUS, &pstat);
-    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
-    printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
-}
-
-
-static int DC390_abort(struct scsi_cmnd *cmd)
-{
-	struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-	struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-
-	scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
-
-	/* abort() is too stupid for already sent commands at the moment. 
-	 * If it's called we are in trouble anyway, so let's dump some info 
-	 * into the syslog at least. (KG, 98/08/20,99/06/20) */
-	dc390_dumpinfo(pACB, pDCB, NULL);
-
-	pDCB->DCBFlag |= ABORT_DEV_;
-	printk(KERN_INFO "DC390: Aborted.\n");
-
-	return FAILED;
-}
-
-
-static void dc390_ResetDevParam( struct dc390_acb* pACB )
-{
-    struct dc390_dcb *pDCB, *pdcb;
-
-    pDCB = pACB->pLinkDCB;
-    if (! pDCB) return;
-    pdcb = pDCB;
-    do
-    {
-	pDCB->SyncMode &= ~SYNC_NEGO_DONE;
-	pDCB->SyncPeriod = 0;
-	pDCB->SyncOffset = 0;
-	pDCB->TagMask = 0;
-	pDCB->CtrlR3 = FAST_CLK;
-	pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
-	pDCB->CtrlR4 |= pACB->glitch_cfg;
-	pDCB = pDCB->pNextDCB;
-    }
-    while( pdcb != pDCB );
-    pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT);
-
-}
-
-static int DC390_bus_reset (struct scsi_cmnd *cmd)
-{
-	struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-	u8   bval;
-
-	spin_lock_irq(cmd->device->host->host_lock);
-
-	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
-	DC390_write8(CtrlReg1, bval);	/* disable IRQ on bus reset */
-
-	pACB->ACBFlag |= RESET_DEV;
-	dc390_ResetSCSIBus(pACB);
-
-	dc390_ResetDevParam(pACB);
-	mdelay(1);
-	pACB->last_reset = jiffies + 3*HZ/2
-		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-
-	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-	DC390_read8(INT_Status);		/* Reset Pending INT */
-
-	dc390_DoingSRB_Done(pACB, cmd);
-
-	pACB->pActiveDCB = NULL;
-	pACB->ACBFlag = 0;
-
-	bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
-	DC390_write8(CtrlReg1, bval);	/* re-enable interrupt */
-
-	spin_unlock_irq(cmd->device->host->host_lock);
-
-	return SUCCESS;
-}
-
-/**
- * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
- * scsi device that we need to deal with.
- *
- * @scsi_device: The new scsi device that we need to handle.
- */
-static int dc390_slave_alloc(struct scsi_device *scsi_device)
-{
-	struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-	struct dc390_dcb *pDCB, *pDCB2 = NULL;
-	uint id = scsi_device->id;
-	uint lun = scsi_device->lun;
-
-	pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
-	if (!pDCB)
-		return -ENOMEM;
-
-	if (!pACB->DCBCnt++) {
-		pACB->pLinkDCB = pDCB;
-		pACB->pDCBRunRobin = pDCB;
-	} else {
-		pACB->pLastDCB->pNextDCB = pDCB;
-	}
-   
-	pDCB->pNextDCB = pACB->pLinkDCB;
-	pACB->pLastDCB = pDCB;
-
-	pDCB->pDCBACB = pACB;
-	pDCB->TargetID = id;
-	pDCB->TargetLUN = lun;
-
-	/*
-	 * Some values are for all LUNs: Copy them 
-	 * In a clean way: We would have an own structure for a SCSI-ID 
-	 */
-	if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
-		pDCB->DevMode = pDCB2->DevMode;
-		pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
-		pDCB->SyncPeriod = pDCB2->SyncPeriod;
-		pDCB->SyncOffset = pDCB2->SyncOffset;
-		pDCB->NegoPeriod = pDCB2->NegoPeriod;
-      
-		pDCB->CtrlR3 = pDCB2->CtrlR3;
-		pDCB->CtrlR4 = pDCB2->CtrlR4;
-	} else {
-		u8 index = pACB->AdapterIndex;
-		PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
-
-		pDCB->DevMode = prom->EE_MODE1;
-		pDCB->NegoPeriod =
-			(dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
-		pDCB->CtrlR3 = FAST_CLK;
-		pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
-		if (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
-			pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
-	}
-
-	if (pDCB->DevMode & SYNC_NEGO_)
-		pDCB->SyncMode |= SYNC_ENABLE;
-	else {
-		pDCB->SyncMode = 0;
-		pDCB->SyncOffset &= ~0x0f;
-	}
-
-	pDCB->CtrlR1 = pACB->pScsiHost->this_id;
-	if (pDCB->DevMode & PARITY_CHK_)
-		pDCB->CtrlR1 |= PARITY_ERR_REPO;
-
-	pACB->scan_devices = 1;
-	scsi_device->hostdata = pDCB;
-	return 0;
-}
-
-/**
- * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
- * device that is going away.
- *
- * @scsi_device: The scsi device that we need to remove.
- */
-static void dc390_slave_destroy(struct scsi_device *scsi_device)
-{
-	struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-	struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
-	struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
-
-	pACB->scan_devices = 0;
-
-	BUG_ON(pDCB->GoingSRBCnt > 1);
-	
-	if (pDCB == pACB->pLinkDCB) {
-		if (pACB->pLastDCB == pDCB) {
-			pDCB->pNextDCB = NULL;
-			pACB->pLastDCB = NULL;
-		}
-		pACB->pLinkDCB = pDCB->pNextDCB;
-	} else {
-		while (pPrevDCB->pNextDCB != pDCB)
-			pPrevDCB = pPrevDCB->pNextDCB;
-		pPrevDCB->pNextDCB = pDCB->pNextDCB;
-		if (pDCB == pACB->pLastDCB)
-			pACB->pLastDCB = pPrevDCB;
-	}
-
-	if (pDCB == pACB->pActiveDCB)
-		pACB->pActiveDCB = NULL;
-	if (pDCB == pACB->pLinkDCB)
-		pACB->pLinkDCB = pDCB->pNextDCB;
-	if (pDCB == pACB->pDCBRunRobin)
-		pACB->pDCBRunRobin = pDCB->pNextDCB;
-	kfree(pDCB); 
-	
-	pACB->DCBCnt--;
-}
-
-static int dc390_slave_configure(struct scsi_device *sdev)
-{
-	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
-	struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
-
-	acb->scan_devices = 0;
-
-	/*
-	 * XXX: Note that while this driver used to called scsi_activate_tcq,
-	 * it never actually set a tag type, so emulate the old behavior.
-	 */
-	scsi_set_tag_type(sdev, 0);
-
-	if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
-		dcb->SyncMode |= EN_TAG_QUEUEING;
-		scsi_adjust_queue_depth(sdev, acb->TagMaxNum);
-	}
-
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.module			= THIS_MODULE,
-	.proc_name		= "tmscsim", 
-	.name			= DC390_BANNER " V" DC390_VERSION,
-	.slave_alloc		= dc390_slave_alloc,
-	.slave_configure	= dc390_slave_configure,
-	.slave_destroy		= dc390_slave_destroy,
-	.queuecommand		= DC390_queuecommand,
-	.eh_abort_handler	= DC390_abort,
-	.eh_bus_reset_handler	= DC390_bus_reset,
-	.can_queue		= 1,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.max_sectors		= 0x4000, /* 8MiB = 16 * 1024 * 512 */
-	.use_blk_tags		= 1,
-};
-
-/***********************************************************************
- * Functions for access to DC390 EEPROM
- * and some to emulate it
- *
- **********************************************************************/
-
-static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
-{
-	u8 carryFlag = 1, j = 0x80, bval;
-	int i;
-
-	for (i = 0; i < 9; i++) {
-		if (carryFlag) {
-			pci_write_config_byte(pdev, 0x80, 0x40);
-			bval = 0xc0;
-		} else
-			bval = 0x80;
-
-		udelay(160);
-		pci_write_config_byte(pdev, 0x80, bval);
-		udelay(160);
-		pci_write_config_byte(pdev, 0x80, 0);
-		udelay(160);
-
-		carryFlag = (cmd & j) ? 1 : 0;
-		j >>= 1;
-	}
-}
-
-static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
-{
-	int i;
-	u16 wval = 0;
-	u8 bval;
-
-	for (i = 0; i < 16; i++) {
-		wval <<= 1;
-
-		pci_write_config_byte(pdev, 0x80, 0x80);
-		udelay(160);
-		pci_write_config_byte(pdev, 0x80, 0x40);
-		udelay(160);
-		pci_read_config_byte(pdev, 0x00, &bval);
-
-		if (bval == 0x22)
-			wval |= 1;
-	}
-
-	return wval;
-}
-
-static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
-{
-	u8 cmd = EEPROM_READ, i;
-
-	for (i = 0; i < 0x40; i++) {
-		pci_write_config_byte(pdev, 0xc0, 0);
-		udelay(160);
-
-		dc390_eeprom_prepare_read(pdev, cmd++);
-		*ptr++ = dc390_eeprom_get_data(pdev);
-
-		pci_write_config_byte(pdev, 0x80, 0);
-		pci_write_config_byte(pdev, 0x80, 0);
-		udelay(160);
-	}
-}
-
-/* Override EEprom values with explicitly set values */
-static void dc390_eeprom_override(u8 index)
-{
-	u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
-
-	/* Adapter Settings */
-	if (tmscsim[0] != -2)
-		ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0];	/* Adapter ID */
-	if (tmscsim[3] != -2)
-		ptr[EE_MODE2] = (u8)tmscsim[3];
-	if (tmscsim[5] != -2)
-		ptr[EE_DELAY] = tmscsim[5];		/* Reset delay */
-	if (tmscsim[4] != -2)
-		ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4];	/* Tagged Cmds */
-
-	/* Device Settings */
-	for (id = 0; id < MAX_SCSI_ID; id++) {
-		if (tmscsim[2] != -2)
-			ptr[id << 2] = (u8)tmscsim[2];		/* EE_MODE1 */
-		if (tmscsim[1] != -2)
-			ptr[(id << 2) + 1] = (u8)tmscsim[1];	/* EE_Speed */
-	}
-}
-
-static int tmscsim_def[] = {
-	7,
-	0 /* 10MHz */,
-	PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
-	MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
-	3 /* 16 Tags per LUN */,
-	1 /* s delay after Reset */,
-};
-
-/* Copy defaults over set values where missing */
-static void dc390_fill_with_defaults (void)
-{
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		if (tmscsim[i] < 0 || tmscsim[i] > 255)
-			tmscsim[i] = tmscsim_def[i];
-	}
-
-	/* Sanity checks */
-	if (tmscsim[0] > 7)
-		tmscsim[0] = 7;
-	if (tmscsim[1] > 7)
-		tmscsim[1] = 4;
-	if (tmscsim[4] > 5)
-		tmscsim[4] = 4;
-	if (tmscsim[5] > 180)
-		tmscsim[5] = 180;
-}
-
-static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
-{
-	u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
-	u8 EEbuf[128];
-	u16 *ptr = (u16 *)EEbuf, wval = 0;
-	int i;
-
-	dc390_read_eeprom(pdev, ptr);
-	memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
-	memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], 
-	       &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
-
-	dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
-
-	for (i = 0; i < 0x40; i++, ptr++)
-		wval += *ptr;
-
-	/* no Tekram EEprom found */
-	if (wval != 0x1234) {
-		int speed;
-
-		printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
-
-		/*
-		 * XXX(hch): bogus, because we might have tekram and
-		 *           non-tekram hbas in a single machine.
-		 */
-		dc390_fill_with_defaults();
-
-		speed = dc390_clock_speed[tmscsim[1]];
-		printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
-		       "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
-		       tmscsim[0], tmscsim[1], speed / 10, speed % 10,
-		       (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
-	}
-}
-
-static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
-{
-	struct Scsi_Host *shost = pACB->pScsiHost;
-	u8 dstate;
-
-	/* Disable SCSI bus reset interrupt */
-	DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
-
-	if (pACB->Gmode2 & RST_SCSI_BUS) {
-		dc390_ResetSCSIBus(pACB);
-		udelay(1000);
-		pACB->last_reset = jiffies + HZ/2 +
-			HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-	}
-
-	pACB->ACBFlag = 0;
-
-	/* Reset Pending INT */
-	DC390_read8(INT_Status);
-	
-	/* 250ms selection timeout */
-	DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
-	
-	/* Conversion factor = 0 , 40MHz clock */
-	DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
-	
-	/* NOP cmd - clear command register */
-	DC390_write8(ScsiCmd, NOP_CMD);
-	
-	/* Enable Feature and SCSI-2 */
-	DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
-	
-	/* Fast clock */
-	DC390_write8(CtrlReg3, FAST_CLK);
-
-	/* Negation */
-	DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
-		(dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
-		 NEGATE_REQACKDATA : 0);
-	
-	/* Clear Transfer Count High: ID */
-	DC390_write8(CtcReg_High, 0);
-	DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
-	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-	DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-	dstate = DC390_read8(DMA_Status);
-	DC390_write8(DMA_Status, dstate);
-}
-
-static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct dc390_acb *pACB;
-	struct Scsi_Host *shost;
-	unsigned long io_port;
-	int error = -ENODEV, i;
-
-	if (pci_enable_device(pdev))
-		goto out;
-
-	pci_set_master(pdev);
-
-	error = -ENOMEM;
-	if (disable_clustering)
-		driver_template.use_clustering = DISABLE_CLUSTERING;
-	shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
-	if (!shost)
-		goto out_disable_device;
-
-	pACB = (struct dc390_acb *)shost->hostdata;
-	memset(pACB, 0, sizeof(struct dc390_acb));
-
-	dc390_check_eeprom(pdev, dc390_adapterCnt);
-	dc390_eeprom_override(dc390_adapterCnt);
-
-	io_port = pci_resource_start(pdev, 0);
-
-	shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
-	shost->io_port = io_port;
-	shost->n_io_port = 0x80;
-	shost->irq = pdev->irq;
-	shost->base = io_port;
-	shost->unique_id = io_port;
-
-	pACB->last_reset = jiffies;
-	pACB->pScsiHost = shost;
-	pACB->IOPortBase = (u16) io_port;
-	pACB->IRQLevel = pdev->irq;
-	
-	shost->max_id = 8;
-
-	if (shost->max_id - 1 ==
-	    dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
-		shost->max_id--;
-
-	if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
-		shost->max_lun = 8;
-	else
-		shost->max_lun = 1;
-
-	pACB->pFreeSRB = pACB->SRB_array;
-	pACB->SRBCount = MAX_SRB_CNT;
-	pACB->AdapterIndex = dc390_adapterCnt;
-	pACB->TagMaxNum =
-		2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
-	pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
-
-	for (i = 0; i < pACB->SRBCount-1; i++)
-		pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
-	pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
-	pACB->pTmpSRB = &pACB->TmpSRB;
-
-	pACB->sel_timeout = SEL_TIMEOUT;
-	pACB->glitch_cfg = EATER_25NS;
-	pACB->pdev = pdev;
-
-	if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
-		printk(KERN_ERR "DC390: register IO ports error!\n");
-		goto out_host_put;
-	}
-
-	/* Reset Pending INT */
-	DC390_read8_(INT_Status, io_port);
-
-	if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
-				"tmscsim", pACB)) {
-		printk(KERN_ERR "DC390: register IRQ error!\n");
-		goto out_release_region;
-	}
-
-	dc390_init_hw(pACB, dc390_adapterCnt);
-	
-	dc390_adapterCnt++;
-
-	pci_set_drvdata(pdev, shost);
-
-	error = scsi_add_host(shost, &pdev->dev);
-	if (error)
-		goto out_free_irq;
-	scsi_scan_host(shost);
-	return 0;
-
- out_free_irq:
-	free_irq(pdev->irq, pACB);
- out_release_region:
-	release_region(io_port, shost->n_io_port);
- out_host_put:
-	scsi_host_put(shost);
- out_disable_device:
-	pci_disable_device(pdev);
- out:
-	return error;
-}
-
-/**
- * dc390_remove_one - Called to remove a single instance of the adapter.
- *
- * @dev: The PCI device to remove.
- */
-static void dc390_remove_one(struct pci_dev *dev)
-{
-	struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
-	unsigned long iflags;
-	struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
-	u8 bval;
-
-	scsi_remove_host(scsi_host);
-
-	spin_lock_irqsave(scsi_host->host_lock, iflags);
-	pACB->ACBFlag = RESET_DEV;
-	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
-	DC390_write8 (CtrlReg1, bval);	/* disable interrupt */
-	if (pACB->Gmode2 & RST_SCSI_BUS)
-		dc390_ResetSCSIBus(pACB);
-	spin_unlock_irqrestore(scsi_host->host_lock, iflags);
-
-	free_irq(scsi_host->irq, pACB);
-	release_region(scsi_host->io_port, scsi_host->n_io_port);
-
-	pci_disable_device(dev);
-	scsi_host_put(scsi_host);
-}
-
-static struct pci_device_id tmscsim_pci_tbl[] = {
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-
-static struct pci_driver dc390_driver = {
-	.name           = "tmscsim",
-	.id_table       = tmscsim_pci_tbl,
-	.probe          = dc390_probe_one,
-	.remove         = dc390_remove_one,
-};
-
-static int __init dc390_module_init(void)
-{
-	if (!disable_clustering) {
-		printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
-		printk(KERN_INFO "       with \"disable_clustering=1\" and report to maintainers\n");
-	}
-
-	if (tmscsim[0] == -1 || tmscsim[0] > 15) {
-		tmscsim[0] = 7;
-		tmscsim[1] = 4;
-		tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
-		tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
-		tmscsim[4] = 2;
-		tmscsim[5] = 10;
-		printk (KERN_INFO "DC390: Using safe settings.\n");
-	}
-
-	return pci_register_driver(&dc390_driver);
-}
-
-static void __exit dc390_module_exit(void)
-{
-	pci_unregister_driver(&dc390_driver);
-}
-
-module_init(dc390_module_init);
-module_exit(dc390_module_exit);
-
-#ifndef MODULE
-static int __init dc390_setup (char *str)
-{	
-	int ints[8],i, im;
-
-	get_options(str, ARRAY_SIZE(ints), ints);
-	im = ints[0];
-
-	if (im > 6) {
-		printk (KERN_NOTICE "DC390: ignore extra params!\n");
-		im = 6;
-	}
-
-	for (i = 0; i < im; i++)
-		tmscsim[i] = ints[i+1];
-	/* dc390_checkparams (); */
-	return 1;
-}
-
-__setup("tmscsim=", dc390_setup);
-#endif
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
deleted file mode 100644
index c9ad4bb..0000000
--- a/drivers/scsi/tmscsim.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/***********************************************************************
-;*	File Name : TMSCSIM.H					       *
-;*		    TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter  *
-;*		    Device Driver				       *
-;***********************************************************************/
-/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
-
-#ifndef _TMSCSIM_H
-#define _TMSCSIM_H
-
-#include <linux/types.h>
-
-#define MAX_ADAPTER_NUM 	4
-#define MAX_SG_LIST_BUF 	16	/* Not used */
-#define MAX_SCSI_ID		8
-#define MAX_SRB_CNT		50	/* Max number of started commands */
-
-#define SEL_TIMEOUT		153	/* 250 ms selection timeout (@ 40 MHz) */
-
-/*
-;-----------------------------------------------------------------------
-; SCSI Request Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_srb
-{
-//u8		CmdBlock[12];
-
-struct dc390_srb	*pNextSRB;
-struct dc390_dcb	*pSRBDCB;
-struct scsi_cmnd	*pcmd;
-struct scatterlist	*pSegmentList;
-
-struct scatterlist Segmentx;	/* make a one entry of S/G list table */
-
-unsigned long	SGBusAddr;	/*;a segment starting address as seen by AM53C974A
-				  in CPU endianness. We're only getting 32-bit bus
-				  addresses by default */
-unsigned long	SGToBeXferLen;	/*; to be xfer length */
-unsigned long	TotalXferredLen;
-unsigned long	SavedTotXLen;
-unsigned long	Saved_Ptr;
-u32		SRBState;
-
-u8		SRBStatus;
-u8		SRBFlag;	/*; b0-AutoReqSense,b6-Read,b7-write */
-				/*; b4-settimeout,b5-Residual valid */
-u8		AdaptStatus;
-u8		TargetStatus;
-
-u8		ScsiPhase;
-s8		TagNumber;
-u8		SGIndex;
-u8		SGcount;
-
-u8		MsgCnt;
-u8		EndMessage;
-
-u8		MsgInBuf[6];
-u8		MsgOutBuf[6];
-
-//u8		IORBFlag;	/*;81h-Reset, 2-retry */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Device Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_dcb
-{
-struct dc390_dcb	*pNextDCB;
-struct dc390_acb	*pDCBACB;
-
-/* Queued SRBs */
-struct dc390_srb	*pGoingSRB;
-struct dc390_srb	*pGoingLast;
-struct dc390_srb	*pActiveSRB;
-u8		GoingSRBCnt;
-
-u32		TagMask;
-
-u8		TargetID;	/*; SCSI Target ID  (SCSI Only) */
-u8		TargetLUN;	/*; SCSI Log.  Unit (SCSI Only) */
-u8		DevMode;
-u8		DCBFlag;
-
-u8		CtrlR1;
-u8		CtrlR3;
-u8		CtrlR4;
-
-u8		SyncMode;	/*; 0:async mode */
-u8		NegoPeriod;	/*;for nego. */
-u8		SyncPeriod;	/*;for reg. */
-u8		SyncOffset;	/*;for reg. and nego.(low nibble) */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Adapter Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_acb
-{
-struct Scsi_Host *pScsiHost;
-u16		IOPortBase;
-u8		IRQLevel;
-u8		status;
-
-u8		SRBCount;
-u8		AdapterIndex;	/*; nth Adapter this driver */
-u8		DCBCnt;
-
-u8		TagMaxNum;
-u8		ACBFlag;
-u8		Gmode2;
-u8		scan_devices;
-
-struct dc390_dcb	*pLinkDCB;
-struct dc390_dcb	*pLastDCB;
-struct dc390_dcb	*pDCBRunRobin;
-
-struct dc390_dcb	*pActiveDCB;
-struct dc390_srb	*pFreeSRB;
-struct dc390_srb	*pTmpSRB;
-
-u8		msgin123[4];
-u8		Connected;
-u8		pad;
-
-#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
-spinlock_t	lock;
-#endif
-u8		sel_timeout;
-u8		glitch_cfg;
-
-u8		MsgLen;
-u8		Ignore_IRQ;	/* Not used */
-
-struct pci_dev	*pdev;
-
-unsigned long   last_reset;
-unsigned long	Cmds;
-u32		SelLost;
-u32		SelConn;
-u32		CmdInQ;
-u32		CmdOutOfSRB;
-
-struct dc390_srb	TmpSRB;
-struct dc390_srb	SRB_array[MAX_SRB_CNT]; 	/* 50 SRBs */
-};
-
-
-/*;-----------------------------------------------------------------------*/
-
-
-#define BIT31	0x80000000
-#define BIT30	0x40000000
-#define BIT29	0x20000000
-#define BIT28	0x10000000
-#define BIT27	0x08000000
-#define BIT26	0x04000000
-#define BIT25	0x02000000
-#define BIT24	0x01000000
-#define BIT23	0x00800000
-#define BIT22	0x00400000
-#define BIT21	0x00200000
-#define BIT20	0x00100000
-#define BIT19	0x00080000
-#define BIT18	0x00040000
-#define BIT17	0x00020000
-#define BIT16	0x00010000
-#define BIT15	0x00008000
-#define BIT14	0x00004000
-#define BIT13	0x00002000
-#define BIT12	0x00001000
-#define BIT11	0x00000800
-#define BIT10	0x00000400
-#define BIT9	0x00000200
-#define BIT8	0x00000100
-#define BIT7	0x00000080
-#define BIT6	0x00000040
-#define BIT5	0x00000020
-#define BIT4	0x00000010
-#define BIT3	0x00000008
-#define BIT2	0x00000004
-#define BIT1	0x00000002
-#define BIT0	0x00000001
-
-/*;---UnitCtrlFlag */
-#define UNIT_ALLOCATED	BIT0
-#define UNIT_INFO_CHANGED BIT1
-#define FORMATING_MEDIA BIT2
-#define UNIT_RETRY	BIT3
-
-/*;---UnitFlags */
-#define DASD_SUPPORT	BIT0
-#define SCSI_SUPPORT	BIT1
-#define ASPI_SUPPORT	BIT2
-
-/*;----SRBState machine definition */
-#define SRB_FREE	0
-#define SRB_WAIT	BIT0
-#define SRB_READY	BIT1
-#define SRB_MSGOUT	BIT2	/*;arbitration+msg_out 1st byte*/
-#define SRB_MSGIN	BIT3
-#define SRB_MSGIN_MULTI BIT4
-#define SRB_COMMAND	BIT5
-#define SRB_START_	BIT6	/*;arbitration+msg_out+command_out*/
-#define SRB_DISCONNECT	BIT7
-#define SRB_DATA_XFER	BIT8
-#define SRB_XFERPAD	BIT9
-#define SRB_STATUS	BIT10
-#define SRB_COMPLETED	BIT11
-#define SRB_ABORT_SENT	BIT12
-#define DO_SYNC_NEGO	BIT13
-#define SRB_UNEXPECT_RESEL BIT14
-
-/*;---SRBstatus */
-#define SRB_OK		BIT0
-#define ABORTION	BIT1
-#define OVER_RUN	BIT2
-#define UNDER_RUN	BIT3
-#define PARITY_ERROR	BIT4
-#define SRB_ERROR	BIT5
-
-/*;---ACBFlag */
-#define RESET_DEV	BIT0
-#define RESET_DETECT	BIT1
-#define RESET_DONE	BIT2
-
-/*;---DCBFlag */
-#define ABORT_DEV_	BIT0
-
-/*;---SRBFlag */
-#define DATAOUT 	BIT7
-#define DATAIN		BIT6
-#define RESIDUAL_VALID	BIT5
-#define ENABLE_TIMER	BIT4
-#define RESET_DEV0	BIT2
-#define ABORT_DEV	BIT1
-#define AUTO_REQSENSE	BIT0
-
-/*;---Adapter status */
-#define H_STATUS_GOOD	 0
-#define H_SEL_TIMEOUT	 0x11
-#define H_OVER_UNDER_RUN 0x12
-#define H_UNEXP_BUS_FREE 0x13
-#define H_TARGET_PHASE_F 0x14
-#define H_INVALID_CCB_OP 0x16
-#define H_LINK_CCB_BAD	 0x17
-#define H_BAD_TARGET_DIR 0x18
-#define H_DUPLICATE_CCB  0x19
-#define H_BAD_CCB_OR_SG  0x1A
-#define H_ABORT 	 0x0FF
-
-/* cmd->result */
-#define RES_TARGET		0x000000FF	/* Target State */
-#define RES_TARGET_LNX		STATUS_MASK	/* Only official ... */
-#define RES_ENDMSG		0x0000FF00	/* End Message */
-#define RES_DID			0x00FF0000	/* DID_ codes */
-#define RES_DRV			0xFF000000	/* DRIVER_ codes */
-
-#define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
-#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
-
-#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
-#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
-#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
-#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
-#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
-
-/*;---Sync_Mode */
-#define SYNC_DISABLE	0
-#define SYNC_ENABLE	BIT0
-#define SYNC_NEGO_DONE	BIT1
-#define WIDE_ENABLE	BIT2	/* Not used ;-) */
-#define WIDE_NEGO_DONE	BIT3	/* Not used ;-) */
-#define EN_TAG_QUEUEING	BIT4
-#define EN_ATN_STOP	BIT5
-
-#define SYNC_NEGO_OFFSET 15
-
-/*;---SCSI bus phase*/
-#define SCSI_DATA_OUT	0
-#define SCSI_DATA_IN	1
-#define SCSI_COMMAND	2
-#define SCSI_STATUS_	3
-#define SCSI_NOP0	4
-#define SCSI_NOP1	5
-#define SCSI_MSG_OUT	6
-#define SCSI_MSG_IN	7
-
-/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
-#define ABORT_TAG	0x0d
-
-/*
- *	SISC query queue
- */
-typedef struct {
-	dma_addr_t		saved_dma_handle;
-} dc390_cmd_scp_t;
-
-/*
-;==========================================================
-; EEPROM byte offset
-;==========================================================
-*/
-typedef  struct  _EEprom
-{
-u8	EE_MODE1;
-u8	EE_SPEED;
-u8	xx1;
-u8	xx2;
-} EEprom, *PEEprom;
-
-#define REAL_EE_ADAPT_SCSI_ID 64
-#define REAL_EE_MODE2	65
-#define REAL_EE_DELAY	66
-#define REAL_EE_TAG_CMD_NUM	67
-
-#define EE_ADAPT_SCSI_ID 32
-#define EE_MODE2	33
-#define EE_DELAY	34
-#define EE_TAG_CMD_NUM	35
-
-#define EE_LEN		40
-
-/*; EE_MODE1 bits definition*/
-#define PARITY_CHK_	BIT0
-#define SYNC_NEGO_	BIT1
-#define EN_DISCONNECT_	BIT2
-#define SEND_START_	BIT3
-#define TAG_QUEUEING_	BIT4
-
-/*; EE_MODE2 bits definition*/
-#define MORE2_DRV	BIT0
-#define GREATER_1G	BIT1
-#define RST_SCSI_BUS	BIT2
-#define ACTIVE_NEGATION BIT3
-#define NO_SEEK 	BIT4
-#define LUN_CHECK	BIT5
-
-#define ENABLE_CE	1
-#define DISABLE_CE	0
-#define EEPROM_READ	0x80
-
-/*
-;==========================================================
-;	AMD 53C974 Registers bit Definition
-;==========================================================
-*/
-/*
-;====================
-; SCSI Register
-;====================
-*/
-
-/*; Command Reg.(+0CH) (rw) */
-#define DMA_COMMAND		BIT7
-#define NOP_CMD 		0
-#define CLEAR_FIFO_CMD		1
-#define RST_DEVICE_CMD		2
-#define RST_SCSI_BUS_CMD	3
-
-#define INFO_XFER_CMD		0x10
-#define INITIATOR_CMD_CMPLTE	0x11
-#define MSG_ACCEPTED_CMD	0x12
-#define XFER_PAD_BYTE		0x18
-#define SET_ATN_CMD		0x1A
-#define RESET_ATN_CMD		0x1B
-
-#define SEL_WO_ATN		0x41	/* currently not used */
-#define SEL_W_ATN		0x42
-#define SEL_W_ATN_STOP		0x43
-#define SEL_W_ATN3		0x46
-#define EN_SEL_RESEL		0x44
-#define DIS_SEL_RESEL		0x45	/* currently not used */
-#define RESEL			0x40	/* " */
-#define RESEL_ATN3		0x47	/* " */
-
-#define DATA_XFER_CMD		INFO_XFER_CMD
-
-
-/*; SCSI Status Reg.(+10H) (r) */
-#define INTERRUPT		BIT7
-#define ILLEGAL_OP_ERR		BIT6
-#define PARITY_ERR		BIT5
-#define COUNT_2_ZERO		BIT4
-#define GROUP_CODE_VALID	BIT3
-#define SCSI_PHASE_MASK 	(BIT2+BIT1+BIT0) 
-/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
-
-/*; Interrupt Status Reg.(+14H) (r) */
-#define SCSI_RESET		BIT7
-#define INVALID_CMD		BIT6
-#define DISCONNECTED		BIT5
-#define SERVICE_REQUEST 	BIT4
-#define SUCCESSFUL_OP		BIT3
-#define RESELECTED		BIT2
-#define SEL_ATTENTION		BIT1
-#define SELECTED		BIT0
-
-/*; Internal State Reg.(+18H) (r) */
-#define SYNC_OFFSET_FLAG	BIT3
-#define INTRN_STATE_MASK	(BIT2+BIT1+BIT0)
-/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
-
-/*; Clock Factor Reg.(+24H) (w) */
-#define CLK_FREQ_40MHZ		0
-#define CLK_FREQ_35MHZ		(BIT2+BIT1+BIT0)
-#define CLK_FREQ_30MHZ		(BIT2+BIT1)
-#define CLK_FREQ_25MHZ		(BIT2+BIT0)
-#define CLK_FREQ_20MHZ		BIT2
-#define CLK_FREQ_15MHZ		(BIT1+BIT0)
-#define CLK_FREQ_10MHZ		BIT1
-
-/*; Control Reg. 1(+20H) (rw) */
-#define EXTENDED_TIMING 	BIT7
-#define DIS_INT_ON_SCSI_RST	BIT6
-#define PARITY_ERR_REPO 	BIT4
-#define SCSI_ID_ON_BUS		(BIT2+BIT1+BIT0) /* host adapter ID */
-
-/*; Control Reg. 2(+2CH) (rw) */
-#define EN_FEATURE		BIT6
-#define EN_SCSI2_CMD		BIT3
-
-/*; Control Reg. 3(+30H) (rw) */
-#define ID_MSG_CHECK		BIT7
-#define EN_QTAG_MSG		BIT6
-#define EN_GRP2_CMD		BIT5
-#define FAST_SCSI		BIT4	/* ;10MB/SEC */
-#define FAST_CLK		BIT3	/* ;25 - 40 MHZ */
-
-/*; Control Reg. 4(+34H) (rw) */
-#define EATER_12NS		0
-#define EATER_25NS		BIT7
-#define EATER_35NS		BIT6
-#define EATER_0NS		(BIT7+BIT6)
-#define REDUCED_POWER		BIT5
-#define CTRL4_RESERVED		BIT4	/* must be 1 acc. to AM53C974.c */
-#define NEGATE_REQACKDATA	BIT2
-#define NEGATE_REQACK		BIT3
-
-#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
-#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
-
-/*
-;====================
-; DMA Register
-;====================
-*/
-/*; DMA Command Reg.(+40H) (rw) */
-#define READ_DIRECTION		BIT7
-#define WRITE_DIRECTION 	0
-#define EN_DMA_INT		BIT6
-#define EN_PAGE_INT		BIT5	/* page transfer interrupt enable */
-#define MAP_TO_MDL		BIT4
-#define DIAGNOSTIC		BIT2
-#define DMA_IDLE_CMD		0
-#define DMA_BLAST_CMD		BIT0
-#define DMA_ABORT_CMD		BIT1
-#define DMA_START_CMD		(BIT1+BIT0)
-
-/*; DMA Status Reg.(+54H) (r) */
-#define PCI_MS_ABORT		BIT6
-#define BLAST_COMPLETE		BIT5
-#define SCSI_INTERRUPT		BIT4
-#define DMA_XFER_DONE		BIT3
-#define DMA_XFER_ABORT		BIT2
-#define DMA_XFER_ERROR		BIT1
-#define POWER_DOWN		BIT0
-
-/*; DMA SCSI Bus and Ctrl.(+70H) */
-#define EN_INT_ON_PCI_ABORT	BIT25
-#define WRT_ERASE_DMA_STAT	BIT24
-#define PW_DOWN_CTRL		BIT21
-#define SCSI_BUSY		BIT20
-#define SCLK			BIT19
-#define SCAM			BIT18
-#define SCSI_LINES		0x0003ffff
-
-/*
-;==========================================================
-; SCSI Chip register address offset
-;==========================================================
-;Registers are rw unless declared otherwise 
-*/
-#define CtcReg_Low	0x00	/* r	curr. transfer count */
-#define CtcReg_Mid	0x04	/* r */
-#define CtcReg_High	0x38	/* r */
-#define ScsiFifo	0x08
-#define ScsiCmd 	0x0C
-#define Scsi_Status	0x10	/* r */
-#define INT_Status	0x14	/* r */
-#define Sync_Period	0x18	/* w */
-#define Sync_Offset	0x1C	/* w */
-#define Clk_Factor	0x24	/* w */
-#define CtrlReg1	0x20	
-#define CtrlReg2	0x2C
-#define CtrlReg3	0x30
-#define CtrlReg4	0x34
-#define DMA_Cmd 	0x40
-#define DMA_XferCnt	0x44	/* rw	starting transfer count (32 bit) */
-#define DMA_XferAddr	0x48	/* rw	starting physical address (32 bit) */
-#define DMA_Wk_ByteCntr 0x4C	/* r	working byte counter */
-#define DMA_Wk_AddrCntr 0x50	/* r	working address counter */
-#define DMA_Status	0x54	/* r */
-#define DMA_MDL_Addr	0x58	/* rw	starting MDL address */
-#define DMA_Wk_MDL_Cntr 0x5C	/* r	working MDL counter */
-#define DMA_ScsiBusCtrl 0x70	/* rw	SCSI Bus, PCI/DMA Ctrl */
-
-#define StcReg_Low	CtcReg_Low	/* w	start transfer count */
-#define StcReg_Mid	CtcReg_Mid	/* w */
-#define StcReg_High	CtcReg_High	/* w */
-#define Scsi_Dest_ID	Scsi_Status	/* w */
-#define Scsi_TimeOut	INT_Status	/* w */
-#define Intern_State	Sync_Period	/* r */
-#define Current_Fifo	Sync_Offset	/* r	Curr. FIFO / int. state */
-
-
-#define DC390_read8(address)			\
-	(inb (pACB->IOPortBase + (address)))
-
-#define DC390_read8_(address, base)		\
-	(inb ((u16)(base) + (address)))
-
-#define DC390_read16(address)			\
-	(inw (pACB->IOPortBase + (address)))
-
-#define DC390_read32(address)			\
-	(inl (pACB->IOPortBase + (address)))
-
-#define DC390_write8(address,value)		\
-	outb ((value), pACB->IOPortBase + (address))
-
-#define DC390_write8_(address,value,base)	\
-	outb ((value), (u16)(base) + (address))
-
-#define DC390_write16(address,value)		\
-	outw ((value), pACB->IOPortBase + (address))
-
-#define DC390_write32(address,value)		\
-	outl ((value), pACB->IOPortBase + (address))
-
-
-#endif /* _TMSCSIM_H */
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/12] esp_scsi: use FIFO for command submission
  2014-11-21 12:41 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
@ 2014-11-21 13:09   ` Paolo Bonzini
  2014-11-21 17:42   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: Paolo Bonzini @ 2014-11-21 13:09 UTC (permalink / raw)
  To: Hannes Reinecke, James Bottomley
  Cc: Christoph Hellwig, Guennadi Liakhovetski, David S. Miller,
	linux-scsi



On 21/11/2014 13:41, Hannes Reinecke wrote:
> Using DMA for command submission has the drawback that it might
> generate additional DMA completion interrupts after the command
> has been submitted to the device.
> Additionally the am53c974 has a design flaw causing it
> to generate spurious interrupts even though DMA completion
> interrupts are not enabled.
> This can be avoided by using the FIFO for command submission.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/scsi/esp_scsi.c | 46 +++++++++++++++++++++++++++++-----------------
>  drivers/scsi/esp_scsi.h |  1 +
>  2 files changed, 30 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> index 0ad0f08..2a3277d 100644
> --- a/drivers/scsi/esp_scsi.c
> +++ b/drivers/scsi/esp_scsi.c
> @@ -143,6 +143,24 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
>  }
>  EXPORT_SYMBOL(scsi_esp_cmd);
>  
> +static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
> +{
> +	if (esp->flags & ESP_FLAG_USE_FIFO) {
> +		int i;
> +
> +		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> +		for (i = 0; i < len; i++)
> +			esp_write8(esp->command_block[i], ESP_FDATA);
> +		scsi_esp_cmd(esp, cmd);
> +	} else {
> +		if (esp->rev == FASHME)
> +			scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> +		cmd |= ESP_CMD_DMA;
> +		esp->ops->send_dma_cmd(esp, esp->command_block_dma,
> +				       len, max_len, 0, cmd);
> +	}
> +}
> +
>  static void esp_event(struct esp *esp, u8 val)
>  {
>  	struct esp_event_ent *p;
> @@ -650,10 +668,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
>  
>  	val = (p - esp->command_block);
>  
> -	if (esp->rev == FASHME)
> -		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> -	esp->ops->send_dma_cmd(esp, esp->command_block_dma,
> -			       val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
> +	esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
>  }
>  
>  static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
> @@ -789,12 +804,12 @@ build_identify:
>  	}
>  
>  	if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
> -		start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
> +		start_cmd = ESP_CMD_SELA;
>  		if (ent->tag[0]) {
>  			*p++ = ent->tag[0];
>  			*p++ = ent->tag[1];
>  
> -			start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
> +			start_cmd = ESP_CMD_SA3;
>  		}
>  
>  		for (i = 0; i < cmd->cmd_len; i++)
> @@ -814,7 +829,7 @@ build_identify:
>  			esp->msg_out_len += 2;
>  		}
>  
> -		start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
> +		start_cmd = ESP_CMD_SELAS;
>  		esp->select_state = ESP_SELECT_MSGOUT;
>  	}
>  	val = tgt;
> @@ -834,10 +849,7 @@ build_identify:
>  		printk("]\n");
>  	}
>  
> -	if (esp->rev == FASHME)
> -		scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> -	esp->ops->send_dma_cmd(esp, esp->command_block_dma,
> -			       val, 16, 0, start_cmd);
> +	esp_send_dma_cmd(esp, val, 16, start_cmd);
>  }
>  
>  static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
> @@ -1646,7 +1658,7 @@ static int esp_msgin_process(struct esp *esp)
>  
>  static int esp_process_event(struct esp *esp)
>  {
> -	int write;
> +	int write, i;
>  
>  again:
>  	write = 0;
> @@ -1872,6 +1884,10 @@ again:
>  			if (esp->msg_out_len == 1) {
>  				esp_write8(esp->msg_out[0], ESP_FDATA);
>  				scsi_esp_cmd(esp, ESP_CMD_TI);
> +			} else if (esp->flags & ESP_FLAG_USE_FIFO) {
> +				for (i = 0; i < esp->msg_out_len; i++)
> +					esp_write8(esp->msg_out[i], ESP_FDATA);
> +				scsi_esp_cmd(esp, ESP_CMD_TI);
>  			} else {
>  				/* Use DMA. */
>  				memcpy(esp->command_block,
> @@ -1949,11 +1965,7 @@ again:
>  	case ESP_EVENT_CMD_START:
>  		memcpy(esp->command_block, esp->cmd_bytes_ptr,
>  		       esp->cmd_bytes_left);
> -		if (esp->rev == FASHME)
> -			scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> -		esp->ops->send_dma_cmd(esp, esp->command_block_dma,
> -				       esp->cmd_bytes_left, 16, 0,
> -				       ESP_CMD_DMA | ESP_CMD_TI);
> +		esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
>  		esp_event(esp, ESP_EVENT_CMD_DONE);
>  		esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
>  		break;
> diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
> index 975d293..27dcaf8 100644
> --- a/drivers/scsi/esp_scsi.h
> +++ b/drivers/scsi/esp_scsi.h
> @@ -478,6 +478,7 @@ struct esp {
>  #define ESP_FLAG_WIDE_CAPABLE	0x00000008
>  #define ESP_FLAG_QUICKIRQ_CHECK	0x00000010
>  #define ESP_FLAG_DISABLE_SYNC	0x00000020
> +#define ESP_FLAG_USE_FIFO	0x00000040
>  
>  	u8			select_state;
>  #define ESP_SELECT_NONE		0x00 /* Not selecting */
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 08/12] am53c974: BLAST residual handling
  2014-11-21 12:41 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
@ 2014-11-21 13:09   ` Paolo Bonzini
  2014-11-21 17:45   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: Paolo Bonzini @ 2014-11-21 13:09 UTC (permalink / raw)
  To: Hannes Reinecke, James Bottomley
  Cc: Christoph Hellwig, Guennadi Liakhovetski, David S. Miller,
	linux-scsi



On 21/11/2014 13:41, Hannes Reinecke wrote:
> The am53c974 has an design issue where a single byte might be
> left in the SCSI FIFO after a DMA transfer.
> As the handling code is currently untested add a WARN_ON()
> statement here.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/scsi/am53c974.c |  6 ++++++
>  drivers/scsi/esp_scsi.c | 29 +++++++++++++++++++++++++++++
>  drivers/scsi/esp_scsi.h |  1 +
>  3 files changed, 36 insertions(+)
> 
> diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
> index 86c4c42..1c1312f 100644
> --- a/drivers/scsi/am53c974.c
> +++ b/drivers/scsi/am53c974.c
> @@ -197,6 +197,12 @@ static void pci_esp_dma_drain(struct esp *esp)
>  	shost_printk(KERN_INFO, esp->host,
>  		     "DMA blast done (%d tries, %d bytes left)\n", lim, resid);
>  #endif
> +	/* BLAST residual handling is currently untested */
> +	if (WARN_ON_ONCE(resid == 1)) {
> +		struct esp_cmd_entry *ent = esp->active_cmd;
> +
> +		ent->flags |= ESP_CMD_FLAG_RESIDUAL;
> +	}
>  }
>  
>  static void pci_esp_dma_invalidate(struct esp *esp)
> diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> index 2a3277d..07b4d93 100644
> --- a/drivers/scsi/esp_scsi.c
> +++ b/drivers/scsi/esp_scsi.c
> @@ -1334,6 +1334,35 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
>  	bytes_sent = esp->data_dma_len;
>  	bytes_sent -= ecount;
>  
> +	/*
> +	 * The am53c974 has a DMA 'pecularity'. The doc states:
> +	 * In some odd byte conditions, one residual byte will
> +	 * be left in the SCSI FIFO, and the FIFO Flags will
> +	 * never count to '0 '. When this happens, the residual
> +	 * byte should be retrieved via PIO following completion
> +	 * of the BLAST operation.
> +	 */
> +	if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
> +		size_t count = 1;
> +		size_t offset = bytes_sent;
> +		u8 bval = esp_read8(ESP_FDATA);
> +
> +		if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
> +			ent->sense_ptr[bytes_sent] = bval;
> +		else {
> +			struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
> +			u8 *ptr;
> +
> +			ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
> +						  &offset, &count);
> +			if (likely(ptr)) {
> +				*(ptr + offset) = bval;
> +				scsi_kunmap_atomic_sg(ptr);
> +			}
> +		}
> +		bytes_sent += fifo_cnt;
> +		ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
> +	}
>  	if (!(ent->flags & ESP_CMD_FLAG_WRITE))
>  		bytes_sent -= fifo_cnt;
>  
> diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
> index 27dcaf8..5fa456c 100644
> --- a/drivers/scsi/esp_scsi.h
> +++ b/drivers/scsi/esp_scsi.h
> @@ -269,6 +269,7 @@ struct esp_cmd_entry {
>  #define ESP_CMD_FLAG_WRITE	0x01 /* DMA is a write */
>  #define ESP_CMD_FLAG_ABORT	0x02 /* being aborted */
>  #define ESP_CMD_FLAG_AUTOSENSE	0x04 /* Doing automatic REQUEST_SENSE */
> +#define ESP_CMD_FLAG_RESIDUAL	0x08 /* AM53c974 BLAST residual */
>  
>  	u8			tag[2];
>  	u8			orig_tag[2];
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974
  2014-11-21 12:41 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
@ 2014-11-21 13:10   ` Paolo Bonzini
  2014-11-21 17:47   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: Paolo Bonzini @ 2014-11-21 13:10 UTC (permalink / raw)
  To: Hannes Reinecke, James Bottomley
  Cc: Christoph Hellwig, Guennadi Liakhovetski, David S. Miller,
	linux-scsi



On 21/11/2014 13:41, Hannes Reinecke wrote:
> CONFIG2_FENAB ('feature enable') changed definition between chip
> revisions, from 'Latch SCSI Phase' to 'Latch SCSI Phase, display
> chip ID upon reset, and enable 24 bit addresses'.
> So only enable it for am53c974 where we know what it's doing.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/scsi/am53c974.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  drivers/scsi/esp_scsi.c |  2 ++
>  2 files changed, 43 insertions(+)
> 
> diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
> index 340cb2f..55622eb 100644
> --- a/drivers/scsi/am53c974.c
> +++ b/drivers/scsi/am53c974.c
> @@ -17,6 +17,8 @@
>  #define DRV_MODULE_NAME "am53c974"
>  #define DRV_MODULE_VERSION "1.00"
>  
> +static bool am53c974_fenab = true;
> +
>  // #define ESP_DMA_DEBUG
>  
>  #define ESP_DMA_CMD 0x10
> @@ -254,6 +256,8 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
>  
>  	pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
>  	pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> +	if (esp->config2 & ESP_CONFIG2_FENAB)
> +		pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
>  
>  	pci_esp_write32(esp, esp_count, ESP_DMA_STC);
>  	pci_esp_write32(esp, addr, ESP_DMA_SPA);
> @@ -267,6 +271,33 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
>  	pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
>  }
>  
> +static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
> +{
> +	int dma_limit = 16;
> +	u32 base, end;
> +
> +	/*
> +	 * If CONFIG2_FENAB is set we can
> +	 * handle up to 24 bit addresses
> +	 */
> +	if (esp->config2 & ESP_CONFIG2_FENAB)
> +		dma_limit = 24;
> +
> +	if (dma_len > (1U << dma_limit))
> +		dma_len = (1U << dma_limit);
> +
> +	/*
> +	 * Prevent crossing a 24-bit address boundary.
> +	 */
> +	base = dma_addr & ((1U << 24) - 1U);
> +	end = base + dma_len;
> +	if (end > (1U << 24))
> +		end = (1U <<24);
> +	dma_len = end - base;
> +
> +	return dma_len;
> +}
> +
>  static const struct esp_driver_ops pci_esp_ops = {
>  	.esp_write8	=	pci_esp_write8,
>  	.esp_read8	=	pci_esp_read8,
> @@ -280,6 +311,7 @@ static const struct esp_driver_ops pci_esp_ops = {
>  	.dma_invalidate	=	pci_esp_dma_invalidate,
>  	.send_dma_cmd	=	pci_esp_send_dma_cmd,
>  	.dma_error	=	pci_esp_dma_error,
> +	.dma_length_limit =	pci_esp_dma_length_limit,
>  };
>  
>  /*
> @@ -417,6 +449,12 @@ static int pci_esp_probe_one(struct pci_dev *pdev,
>  	 * DMA for command submission.
>  	 */
>  	esp->flags |= ESP_FLAG_USE_FIFO;
> +	/*
> +	 * Enable CONFIG2_FENAB to allow for large DMA transfers
> +	 */
> +	if (am53c974_fenab)
> +		esp->config2 |= ESP_CONFIG2_FENAB;
> +
>  	pep->esp = esp;
>  
>  	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
> @@ -535,5 +573,8 @@ MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
>  MODULE_LICENSE("GPL");
>  MODULE_VERSION(DRV_MODULE_VERSION);
>  
> +module_param(am53c974_fenab, bool, 0444);
> +MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
> +
>  module_init(am53c974_module_init);
>  module_exit(am53c974_module_exit);
> diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> index bd17516..56f361e 100644
> --- a/drivers/scsi/esp_scsi.c
> +++ b/drivers/scsi/esp_scsi.c
> @@ -1343,6 +1343,8 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
>  			  (((unsigned int)esp_read8(ESP_TCMED)) << 8));
>  		if (esp->rev == FASHME)
>  			ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
> +		if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
> +			ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
>  	}
>  
>  	bytes_sent = esp->data_dma_len;
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/12] esp_scsi: use FIFO for command submission
  2014-11-21 12:41 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
  2014-11-21 13:09   ` Paolo Bonzini
@ 2014-11-21 17:42   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:42 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:50 +0100

> Using DMA for command submission has the drawback that it might
> generate additional DMA completion interrupts after the command
> has been submitted to the device.
> Additionally the am53c974 has a design flaw causing it
> to generate spurious interrupts even though DMA completion
> interrupts are not enabled.
> This can be avoided by using the FIFO for command submission.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/12] esp_scsi: spellcheck 'driver'
  2014-11-21 12:41 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
@ 2014-11-21 17:42   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:42 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:45 +0100

> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/12] esp_scsi: make number of tags configurable
  2014-11-21 12:41 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
@ 2014-11-21 17:42   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:42 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:46 +0100

> Add a field 'num_tags' to the esp structure to allow drivers
> to overwrite the number of avialable tags if required.
> Default is ESP_DEFAULT_TAGS.
> 
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/12] esp_scsi: convert to dev_printk
  2014-11-21 12:41 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
@ 2014-11-21 17:43   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:43 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:47 +0100

> Use dev_printk functions for correct device annotations.
> 
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 04/12] esp_scsi: debug event and command
  2014-11-21 12:41 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
@ 2014-11-21 17:43   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:43 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:48 +0100

> Add new debug definitions for event and command logging.
> 
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 05/12] esp_scsi: read status registers
  2014-11-21 12:41 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
@ 2014-11-21 17:44   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:44 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:49 +0100

> A read to ESP_INTRPT will clear ESP_STATUS and ESP_SSTEP. So read
> all status registers in one go to avoid losing information.
> 
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 08/12] am53c974: BLAST residual handling
  2014-11-21 12:41 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
  2014-11-21 13:09   ` Paolo Bonzini
@ 2014-11-21 17:45   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:45 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:52 +0100

> The am53c974 has an design issue where a single byte might be
> left in the SCSI FIFO after a DMA transfer.
> As the handling code is currently untested add a WARN_ON()
> statement here.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/12] esp: correctly detect am53c974
  2014-11-21 12:41 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
@ 2014-11-21 17:46   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:46 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:53 +0100

> +		if ((config4 & ESP_CONFIG4_GE1) == ESP_CONFIG4_GE1) {

Please condense this down to the more simple and straightforward:

	if (x & BIT(N))

because this is always equivalent to the expression you have used:

	if ((x & BIT(N)) == BIT(N))

Thanks.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value
  2014-11-21 12:41 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
@ 2014-11-21 17:47   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:47 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:54 +0100

> From: Paolo Bonzini <pbonzini@redhat.com>
> 
> On PCscsi, the FENAB configuration also enables 24-bit DMA
> transfer lengths (and provides the chip id in TCHI after reset).
> We want to be able to enable this parameter from the DMA driver.
> 
> Check if the caller of scsi_esp_register provided a value for esp->config2.
> If this is the case, assume this is not an ESP100, skip the detection
> phase and leave esp->config2 untouched.  It will be used in esp_reset_esp.
> 
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974
  2014-11-21 12:41 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
  2014-11-21 13:10   ` Paolo Bonzini
@ 2014-11-21 17:47   ` David Miller
  1 sibling, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-21 17:47 UTC (permalink / raw)
  To: hare; +Cc: jbottomley, hch, pbonzini, g.liakhovetski, linux-scsi

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Nov 2014 13:41:55 +0100

> CONFIG2_FENAB ('feature enable') changed definition between chip
> revisions, from 'Latch SCSI Phase' to 'Latch SCSI Phase, display
> chip ID upon reset, and enable 24 bit addresses'.
> So only enable it for am53c974 where we know what it's doing.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 12/12] Replace tmscsim by am53c974
  2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
@ 2014-11-23 13:22   ` Guennadi Liakhovetski
  2014-11-23 18:45     ` David Miller
  0 siblings, 1 reply; 36+ messages in thread
From: Guennadi Liakhovetski @ 2014-11-23 13:22 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
	David S. Miller, linux-scsi

On Fri, 21 Nov 2014, Hannes Reinecke wrote:

> The am53c974 is a re-implementation of the tmscsim driver,
> and provides the same functionality.
> So remove the tmscsim driver and make am53c974 an alias to tmscsim.
> 
> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  MAINTAINERS             |    7 +-
>  drivers/scsi/Kconfig    |   16 -
>  drivers/scsi/Makefile   |    1 -
>  drivers/scsi/am53c974.c |    1 +
>  drivers/scsi/tmscsim.c  | 2626 -----------------------------------------------
>  drivers/scsi/tmscsim.h  |  549 ----------
>  6 files changed, 4 insertions(+), 3196 deletions(-)
>  delete mode 100644 drivers/scsi/tmscsim.c
>  delete mode 100644 drivers/scsi/tmscsim.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d206f37..d780e46 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2862,11 +2862,10 @@ F:	Documentation/networking/dmfe.txt
>  F:	drivers/net/ethernet/dec/tulip/dmfe.c
>  
>  DC390/AM53C974 SCSI driver
> -M:	Kurt Garloff <garloff@suse.de>
> -W:	http://www.garloff.de/kurt/linux/dc390/
> -M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> +M:	Hannes Reinecke <hare@suse.de>
> +L:	linux-scsi@vger.kernel.org
>  S:	Maintained
> -F:	drivers/scsi/tmscsim.*
> +F:	drivers/scsi/am53c974.c
>  
>  DC395x SCSI driver
>  M:	Oliver Neukum <oliver@neukum.org>

Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks
Guennadi

> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index 519c3ef..f871a80 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -1341,22 +1341,6 @@ config SCSI_DC395x
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called dc395x.
>  
> -config SCSI_DC390T
> -	tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
> -	depends on PCI && SCSI
> -	---help---
> -	  This driver supports PCI SCSI host adapters based on the Am53C974A
> -	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
> -	  PCscsi/PCnet (Am53/79C974) solutions.
> -
> -	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
> -
> -	  Note that this driver does NOT support Tekram DC390W/U/F, which are
> -	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
> -
> -	  To compile this driver as a module, choose M here: the
> -	  module will be called tmscsim.
> -
>  config SCSI_AM53C974
>  	tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
>  	depends on PCI && SCSI
> diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
> index 79a6571..a9f3fa8 100644
> --- a/drivers/scsi/Makefile
> +++ b/drivers/scsi/Makefile
> @@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO)	+= eata_pio.o
>  obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
>  obj-$(CONFIG_SCSI_EATA)		+= eata.o
>  obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
> -obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
>  obj-$(CONFIG_SCSI_AM53C974)	+= esp_scsi.o	am53c974.o
>  obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
>  obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
> diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
> index 55622eb..5ce2bb2 100644
> --- a/drivers/scsi/am53c974.c
> +++ b/drivers/scsi/am53c974.c
> @@ -572,6 +572,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");
>  MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
>  MODULE_LICENSE("GPL");
>  MODULE_VERSION(DRV_MODULE_VERSION);
> +MODULE_ALIAS("tmscsim");
>  
>  module_param(am53c974_fenab, bool, 0444);
>  MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
> diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
> deleted file mode 100644
> index 844c9a0..0000000
> --- a/drivers/scsi/tmscsim.c
> +++ /dev/null
> @@ -1,2626 +0,0 @@
> -/************************************************************************
> - *	FILE NAME : TMSCSIM.C						*
> - *	     BY   : C.L. Huang,  ching@tekram.com.tw			*
> - *	Description: Device Driver for Tekram DC-390(T) PCI SCSI	*
> - *		     Bus Master Host Adapter				*
> - * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.			*
> - ************************************************************************
> - * (C) Copyright: put under GNU GPL in 10/96				*
> - *				(see Documentation/scsi/tmscsim.txt)	*
> - ************************************************************************
> - * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $		*
> - *	Enhancements and bugfixes by					*
> - *	Kurt Garloff <kurt@garloff.de>	<garloff@suse.de>		*
> - ************************************************************************
> - *	HISTORY:							*
> - *									*
> - *	REV#	DATE	NAME	DESCRIPTION				*
> - *	1.00  96/04/24	CLH	First release				*
> - *	1.01  96/06/12	CLH	Fixed bug of Media Change for Removable *
> - *				Device, scan all LUN. Support Pre2.0.10 *
> - *	1.02  96/06/18	CLH	Fixed bug of Command timeout ...	*
> - *	1.03  96/09/25	KG	Added tmscsim_proc_info()		*
> - *	1.04  96/10/11	CLH	Updating for support KV 2.0.x		*
> - *	1.05  96/10/18	KG	Fixed bug in DC390_abort(null ptr deref)*
> - *	1.06  96/10/25	KG	Fixed module support			*
> - *	1.07  96/11/09	KG	Fixed tmscsim_proc_info()		*
> - *	1.08  96/11/18	KG	Fixed null ptr in DC390_Disconnect()	*
> - *	1.09  96/11/30	KG	Added register the allocated IO space	*
> - *	1.10  96/12/05	CLH	Modified tmscsim_proc_info(), and reset *
> - *				pending interrupt in DC390_detect()	*
> - *	1.11  97/02/05	KG/CLH	Fixeds problem with partitions greater	*
> - *				than 1GB				*
> - *	1.12  98/02/15  MJ      Rewritten PCI probing			*
> - *	1.13  98/04/08	KG	Support for non DC390, __initfunc decls,*
> - *				changed max devs from 10 to 16		*
> - *	1.14a 98/05/05	KG	Dynamic DCB allocation, add-single-dev	*
> - *				for LUNs if LUN_SCAN (BIOS) not set	*
> - *				runtime config using /proc interface	*
> - *	1.14b 98/05/06	KG	eliminated cli (); sti (); spinlocks	*
> - *	1.14c 98/05/07	KG	2.0.x compatibility			*
> - *	1.20a 98/05/07	KG	changed names of funcs to be consistent *
> - *				DC390_ (entry points), dc390_ (internal)*
> - *				reworked locking			*
> - *	1.20b 98/05/12	KG	bugs: version, kfree, _ctmp		*
> - *				debug output				*
> - *	1.20c 98/05/12	KG	bugs: kfree, parsing, EEpromDefaults	*
> - *	1.20d 98/05/14	KG	bugs: list linkage, clear flag after  	*
> - *				reset on startup, code cleanup		*
> - *	1.20e 98/05/15	KG	spinlock comments, name space cleanup	*
> - *				pLastDCB now part of ACB structure	*
> - *				added stats, timeout for 2.1, TagQ bug	*
> - *				RESET and INQUIRY interface commands	*
> - *	1.20f 98/05/18	KG	spinlocks fixes, max_lun fix, free DCBs	*
> - *				for missing LUNs, pending int		*
> - *	1.20g 98/05/19	KG	Clean up: Avoid short			*
> - *	1.20h 98/05/21	KG	Remove AdaptSCSIID, max_lun ...		*
> - *	1.20i 98/05/21	KG	Aiiie: Bug with TagQMask       		*
> - *	1.20j 98/05/24	KG	Handle STAT_BUSY, handle pACB->pLinkDCB	*
> - *				== 0 in remove_dev and DoingSRB_Done	*
> - *	1.20k 98/05/25	KG	DMA_INT	(experimental)	       		*
> - *	1.20l 98/05/27	KG	remove DMA_INT; DMA_IDLE cmds added;	*
> - *	1.20m 98/06/10	KG	glitch configurable; made some global	*
> - *				vars part of ACB; use DC390_readX	*
> - *	1.20n 98/06/11	KG	startup params				*
> - *	1.20o 98/06/15	KG	added TagMaxNum to boot/module params	*
> - *				Device Nr -> Idx, TagMaxNum power of 2  *
> - *	1.20p 98/06/17	KG	Docu updates. Reset depends on settings *
> - *				pci_set_master added; 2.0.xx: pcibios_*	*
> - *				used instead of MechNum things ...	*
> - *	1.20q 98/06/23	KG	Changed defaults. Added debug code for	*
> - *				removable media and fixed it. TagMaxNum	*
> - *				fixed for DC390. Locking: ACB, DRV for	*
> - *				better IRQ sharing. Spelling: Queueing	*
> - *				Parsing and glitch_cfg changes. Display	*
> - *				real SyncSpeed value. Made DisConn	*
> - *				functional (!)				*
> - *	1.20r 98/06/30	KG	Debug macros, allow disabling DsCn, set	*
> - *				BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module	*
> - *				param -1 fixed.				*
> - *	1.20s 98/08/20	KG	Debug info on abort(), try to check PCI,*
> - *				phys_to_bus instead of phys_to_virt,	*
> - *				fixed sel. process, fixed locking,	*
> - *				added MODULE_XXX infos, changed IRQ	*
> - *				request flags, disable DMA_INT		*
> - *	1.20t 98/09/07	KG	TagQ report fixed; Write Erase DMA Stat;*
> - *				initfunc -> __init; better abort;	*
> - *				Timeout for XFER_DONE & BLAST_COMPLETE;	*
> - *				Allow up to 33 commands being processed *
> - *	2.0a  98/10/14	KG	Max Cmnds back to 17. DMA_Stat clearing *
> - *				all flags. Clear within while() loops	*
> - *				in DataIn_0/Out_0. Null ptr in dumpinfo	*
> - *				for pSRB==0. Better locking during init.*
> - *				bios_param() now respects part. table.	*
> - *	2.0b  98/10/24	KG	Docu fixes. Timeout Msg in DMA Blast.	*
> - *				Disallow illegal idx in INQUIRY/REMOVE	*
> - *	2.0c  98/11/19	KG	Cleaned up detect/init for SMP boxes, 	*
> - *				Write Erase DMA (1.20t) caused problems	*
> - *	2.0d  98/12/25	KG	Christmas release ;-) Message handling  *
> - *				completely reworked. Handle target ini-	*
> - *				tiated SDTR correctly.			*
> - *	2.0d1 99/01/25	KG	Try to handle RESTORE_PTR		*
> - *	2.0d2 99/02/08	KG	Check for failure of kmalloc, correct 	*
> - *				inclusion of scsicam.h, DelayReset	*
> - *	2.0d3 99/05/31	KG	DRIVER_OK -> DID_OK, DID_NO_CONNECT,	*
> - *				detect Target mode and warn.		*
> - *				pcmd->result handling cleaned up.	*
> - *	2.0d4 99/06/01	KG	Cleaned selection process. Found bug	*
> - *				which prevented more than 16 tags. Now:	*
> - *				24. SDTR cleanup. Cleaner multi-LUN	*
> - *				handling. Don't modify ControlRegs/FIFO	*
> - *				when connected.				*
> - *	2.0d5 99/06/01	KG	Clear DevID, Fix INQUIRY after cfg chg.	*
> - *	2.0d6 99/06/02	KG	Added ADD special command to allow cfg.	*
> - *				before detection. Reset SYNC_NEGO_DONE	*
> - *				after a bus reset.			*
> - *	2.0d7 99/06/03	KG	Fixed bugs wrt add,remove commands	*
> - *	2.0d8 99/06/04	KG	Removed copying of cmnd into CmdBlock.	*
> - *				Fixed Oops in _release().		*
> - *	2.0d9 99/06/06	KG	Also tag queue INQUIRY, T_U_R, ...	*
> - *				Allow arb. no. of Tagged Cmnds. Max 32	*
> - *	2.0d1099/06/20	KG	TagMaxNo changes now honoured! Queueing *
> - *				clearified (renamed ..) TagMask handling*
> - *				cleaned.				*
> - *	2.0d1199/06/28	KG	cmd->result now identical to 2.0d2	*
> - *	2.0d1299/07/04	KG	Changed order of processing in IRQ	*
> - *	2.0d1399/07/05	KG	Don't update DCB fields if removed	*
> - *	2.0d1499/07/05	KG	remove_dev: Move kfree() to the end	*
> - *	2.0d1599/07/12	KG	use_new_eh_code: 0, ULONG -> UINT where	*
> - *				appropriate				*
> - *	2.0d1699/07/13	KG	Reenable StartSCSI interrupt, Retry msg	*
> - *	2.0d1799/07/15	KG	Remove debug msg. Disable recfg. when	*
> - *				there are queued cmnds			*
> - *	2.0d1899/07/18	KG	Selection timeout: Don't requeue	*
> - *	2.0d1999/07/18	KG	Abort: Only call scsi_done if dequeued	*
> - *	2.0d2099/07/19	KG	Rst_Detect: DoingSRB_Done		*
> - *	2.0d2199/08/15	KG	dev_id for request/free_irq, cmnd[0] for*
> - *				RETRY, SRBdone does DID_ABORT for the 	*
> - *				cmd passed by DC390_reset()		*
> - *	2.0d2299/08/25	KG	dev_id fixed. can_queue: 42		*
> - *	2.0d2399/08/25	KG	Removed some debugging code. dev_id 	*
> - *				now is set to pACB. Use u8,u16,u32. 	*
> - *	2.0d2499/11/14	KG	Unreg. I/O if failed IRQ alloc. Call	*
> - * 				done () w/ DID_BAD_TARGET in case of	*
> - *				missing DCB. We	are old EH!!		*
> - *	2.0d2500/01/15	KG	2.3.3x compat from Andreas Schultz	*
> - *				set unique_id. Disable RETRY message.	*
> - *	2.0d2600/01/29	KG	Go to new EH.				*
> - *	2.0d2700/01/31	KG	... but maintain 2.0 compat.		*
> - *				and fix DCB freeing			*
> - *	2.0d2800/02/14	KG	Queue statistics fixed, dump special cmd*
> - *				Waiting_Timer for failed StartSCSI	*
> - *				New EH: Don't return cmnds to ML on RST *
> - *				Use old EH (don't have new EH fns yet)	*
> - * 				Reset: Unlock, but refuse to queue	*
> - * 				2.3 __setup function			*
> - *	2.0e  00/05/22	KG	Return residual for 2.3			*
> - *	2.0e1 00/05/25	KG	Compile fixes for 2.3.99		*
> - *	2.0e2 00/05/27	KG	Jeff Garzik's pci_enable_device()	*
> - *	2.0e3 00/09/29	KG	Some 2.4 changes. Don't try Sync Nego	*
> - *				before INQUIRY has reported ability. 	*
> - *				Recognise INQUIRY as scanning command.	*
> - *	2.0e4 00/10/13	KG	Allow compilation into 2.4 kernel	*
> - *	2.0e5 00/11/17	KG	Store Inq.flags in DCB			*
> - *	2.0e6 00/11/22  KG	2.4 init function (Thx to O.Schumann)	*
> - * 				2.4 PCI device table (Thx to A.Richter)	*
> - *	2.0e7 00/11/28	KG	Allow overriding of BIOS settings	*
> - *	2.0f  00/12/20	KG	Handle failed INQUIRYs during scan	*
> - *	2.1a  03/11/29  GL, KG	Initial fixing for 2.6. Convert to	*
> - *				use the current PCI-mapping API, update	*
> - *				command-queuing.			*
> - *	2.1b  04/04/13  GL	Fix for 64-bit platforms		*
> - *	2.1b1 04/01/31	GL	(applied 05.04) Remove internal		*
> - *				command-queuing.			*
> - *	2.1b2 04/02/01	CH	(applied 05.04) Fix error-handling	*
> - *	2.1c  04/05/23  GL	Update to use the new pci_driver API,	*
> - *				some scsi EH updates, more cleanup.	*
> - *	2.1d  04/05/27	GL	Moved setting of scan_devices to	*
> - *				slave_alloc/_configure/_destroy, as	*
> - *				suggested by CH.			*
> - ***********************************************************************/
> -
> -/* DEBUG options */
> -//#define DC390_DEBUG0
> -//#define DC390_DEBUG1
> -//#define DC390_DCBDEBUG
> -//#define DC390_PARSEDEBUG
> -//#define DC390_REMOVABLEDEBUG
> -//#define DC390_LOCKDEBUG
> -
> -//#define NOP do{}while(0)
> -#define C_NOP
> -
> -/* Debug definitions */
> -#ifdef DC390_DEBUG0
> -# define DEBUG0(x) x
> -#else
> -# define DEBUG0(x) C_NOP
> -#endif
> -#ifdef DC390_DEBUG1
> -# define DEBUG1(x) x
> -#else
> -# define DEBUG1(x) C_NOP
> -#endif
> -#ifdef DC390_DCBDEBUG
> -# define DCBDEBUG(x) x
> -#else
> -# define DCBDEBUG(x) C_NOP
> -#endif
> -#ifdef DC390_PARSEDEBUG
> -# define PARSEDEBUG(x) x
> -#else
> -# define PARSEDEBUG(x) C_NOP
> -#endif
> -#ifdef DC390_REMOVABLEDEBUG
> -# define REMOVABLEDEBUG(x) x
> -#else
> -# define REMOVABLEDEBUG(x) C_NOP
> -#endif
> -#define DCBDEBUG1(x) C_NOP
> -
> -#include <linux/module.h>
> -#include <linux/delay.h>
> -#include <linux/signal.h>
> -#include <linux/errno.h>
> -#include <linux/kernel.h>
> -#include <linux/ioport.h>
> -#include <linux/pci.h>
> -#include <linux/proc_fs.h>
> -#include <linux/string.h>
> -#include <linux/mm.h>
> -#include <linux/blkdev.h>
> -#include <linux/timer.h>
> -#include <linux/interrupt.h>
> -#include <linux/init.h>
> -#include <linux/spinlock.h>
> -#include <linux/slab.h>
> -#include <asm/io.h>
> -
> -#include <scsi/scsi.h>
> -#include <scsi/scsi_cmnd.h>
> -#include <scsi/scsi_device.h>
> -#include <scsi/scsi_host.h>
> -#include <scsi/scsicam.h>
> -#include <scsi/scsi_tcq.h>
> -
> -#define DC390_BANNER "Tekram DC390/AM53C974"
> -#define DC390_VERSION "2.1d 2004-05-27"
> -
> -#define PCI_DEVICE_ID_AMD53C974 	PCI_DEVICE_ID_AMD_SCSI
> -
> -#include "tmscsim.h"
> -
> -
> -static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -
> -static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
> -static void dc390_Disconnect( struct dc390_acb* pACB );
> -static void dc390_Reselect( struct dc390_acb* pACB );
> -static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
> -static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
> -static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
> -static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
> -static void dc390_ResetDevParam(struct dc390_acb* pACB);
> -
> -static u32	dc390_laststatus = 0;
> -static u8	dc390_adapterCnt = 0;
> -
> -static int disable_clustering;
> -module_param(disable_clustering, int, S_IRUGO);
> -MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
> -
> -/* Startup values, to be overriden on the commandline */
> -static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
> -
> -module_param_array(tmscsim, int, NULL, 0);
> -MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
> -MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
> -MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
> -MODULE_LICENSE("GPL");
> -MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
> -
> -static void *dc390_phase0[]={
> -       dc390_DataOut_0,
> -       dc390_DataIn_0,
> -       dc390_Command_0,
> -       dc390_Status_0,
> -       dc390_Nop_0,
> -       dc390_Nop_0,
> -       dc390_MsgOut_0,
> -       dc390_MsgIn_0,
> -       dc390_Nop_1
> -       };
> -
> -static void *dc390_phase1[]={
> -       dc390_DataOutPhase,
> -       dc390_DataInPhase,
> -       dc390_CommandPhase,
> -       dc390_StatusPhase,
> -       dc390_Nop_0,
> -       dc390_Nop_0,
> -       dc390_MsgOutPhase,
> -       dc390_MsgInPhase,
> -       dc390_Nop_1
> -       };
> -
> -#ifdef DC390_DEBUG1
> -static char* dc390_p0_str[] = {
> -       "dc390_DataOut_0",
> -       "dc390_DataIn_0",
> -       "dc390_Command_0",
> -       "dc390_Status_0",
> -       "dc390_Nop_0",
> -       "dc390_Nop_0",
> -       "dc390_MsgOut_0",
> -       "dc390_MsgIn_0",
> -       "dc390_Nop_1"
> -       };
> -     
> -static char* dc390_p1_str[] = {
> -       "dc390_DataOutPhase",
> -       "dc390_DataInPhase",
> -       "dc390_CommandPhase",
> -       "dc390_StatusPhase",
> -       "dc390_Nop_0",
> -       "dc390_Nop_0",
> -       "dc390_MsgOutPhase",
> -       "dc390_MsgInPhase",
> -       "dc390_Nop_1"
> -       };
> -#endif   
> -
> -static u8  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
> -static u8  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
> -static u8  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
> -
> -/***********************************************************************
> - * Functions for the management of the internal structures 
> - * (DCBs, SRBs, Queueing)
> - *
> - **********************************************************************/
> -static void inline dc390_start_segment(struct dc390_srb* pSRB)
> -{
> -	struct scatterlist *psgl = pSRB->pSegmentList;
> -
> -	/* start new sg segment */
> -	pSRB->SGBusAddr = sg_dma_address(psgl);
> -	pSRB->SGToBeXferLen = sg_dma_len(psgl);
> -}
> -
> -static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
> -{
> -	unsigned long xfer = pSRB->SGToBeXferLen - residue;
> -
> -	/* xfer more bytes transferred */
> -	pSRB->SGBusAddr += xfer;
> -	pSRB->TotalXferredLen += xfer;
> -	pSRB->SGToBeXferLen = residue;
> -
> -	return xfer;
> -}
> -
> -static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
> -{
> -   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
> -   while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
> -     {
> -	pDCB = pDCB->pNextDCB;
> -	if (pDCB == pACB->pLinkDCB)
> -	     return NULL;
> -     }
> -   DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",	\
> -		      pDCB, pDCB->TargetID, pDCB->TargetLUN));
> -   return pDCB;
> -}
> -
> -/* Insert SRB oin top of free list */
> -static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> -    DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
> -    pSRB->pNextSRB = pACB->pFreeSRB;
> -    pACB->pFreeSRB = pSRB;
> -}
> -
> -static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> -    pDCB->GoingSRBCnt++;
> -    DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB));
> -    /* Append to the list of Going commands */
> -    if( pDCB->pGoingSRB )
> -	pDCB->pGoingLast->pNextSRB = pSRB;
> -    else
> -	pDCB->pGoingSRB = pSRB;
> -
> -    pDCB->pGoingLast = pSRB;
> -    /* No next one in sent list */
> -    pSRB->pNextSRB = NULL;
> -}
> -
> -static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> -	DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
> -   if (pSRB == pDCB->pGoingSRB)
> -	pDCB->pGoingSRB = pSRB->pNextSRB;
> -   else
> -     {
> -	struct dc390_srb* psrb = pDCB->pGoingSRB;
> -	while (psrb && psrb->pNextSRB != pSRB)
> -	  psrb = psrb->pNextSRB;
> -	if (!psrb) 
> -	  { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; }
> -	psrb->pNextSRB = pSRB->pNextSRB;
> -	if (pSRB == pDCB->pGoingLast)
> -	  pDCB->pGoingLast = psrb;
> -     }
> -   pDCB->GoingSRBCnt--;
> -}
> -
> -static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
> -{
> -	sg_init_one(sg, addr, length);
> -	return sg;
> -}
> -
> -/* Create pci mapping */
> -static int dc390_pci_map (struct dc390_srb* pSRB)
> -{
> -	int error = 0;
> -	struct scsi_cmnd *pcmd = pSRB->pcmd;
> -	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
> -	dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
> -
> -	/* Map sense buffer */
> -	if (pSRB->SRBFlag & AUTO_REQSENSE) {
> -		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
> -		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
> -						     DMA_FROM_DEVICE);
> -		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
> -
> -		/* TODO: error handling */
> -		if (pSRB->SGcount != 1)
> -			error = 1;
> -		DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
> -	/* Map SG list */
> -	} else if (scsi_sg_count(pcmd)) {
> -		int nseg;
> -
> -		nseg = scsi_dma_map(pcmd);
> -
> -		pSRB->pSegmentList	= scsi_sglist(pcmd);
> -		pSRB->SGcount		= nseg;
> -
> -		/* TODO: error handling */
> -		if (nseg < 0)
> -			error = 1;
> -		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
> -			      __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
> -	/* Map single segment */
> -	} else
> -		pSRB->SGcount = 0;
> -
> -	return error;
> -}
> -
> -/* Remove pci mapping */
> -static void dc390_pci_unmap (struct dc390_srb* pSRB)
> -{
> -	struct scsi_cmnd *pcmd = pSRB->pcmd;
> -	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
> -	DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
> -
> -	if (pSRB->SRBFlag) {
> -		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
> -		DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
> -	} else {
> -		scsi_dma_unmap(pcmd);
> -		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
> -			      __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
> -	}
> -}
> -
> -static void __inline__
> -dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> -	if (pSRB->TagNumber != SCSI_NO_TAG) {
> -		pDCB->TagMask &= ~(1 << pSRB->TagNumber);   /* free tag mask */
> -		pSRB->TagNumber = SCSI_NO_TAG;
> -	}
> -}
> -
> -
> -static int
> -dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
> -{
> -    struct scsi_cmnd *scmd = pSRB->pcmd;
> -    struct scsi_device *sdev = scmd->device;
> -    u8 cmd, disc_allowed, try_sync_nego;
> -
> -    pSRB->ScsiPhase = SCSI_NOP0;
> -
> -    if (pACB->Connected)
> -    {
> -	// Should not happen normally
> -	printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n",
> -		pSRB->SRBState, pSRB->SRBFlag);
> -	pSRB->SRBState = SRB_READY;
> -	pACB->SelConn++;
> -	return 1;
> -    }
> -    if (time_before (jiffies, pACB->last_reset))
> -    {
> -	DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
> -	return 1;
> -    }
> -    /* KG: Moved pci mapping here */
> -    dc390_pci_map(pSRB);
> -    /* TODO: error handling */
> -    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
> -    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> -    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> -    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
> -    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> -    DC390_write8 (CtrlReg4, pDCB->CtrlR4);
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);		/* Flush FIFO */
> -    DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
> -            scmd->cmnd[0], pDCB->SyncMode));
> -
> -    /* Don't disconnect on AUTO_REQSENSE, cause it might be an
> -     * Contingent Allegiance Condition (6.6), where no tags should be used.
> -     * All other have to be allowed to disconnect to prevent Incorrect 
> -     * Initiator Connection (6.8.2/6.5.2) */
> -    /* Changed KG, 99/06/06 */
> -    if (! (pSRB->SRBFlag & AUTO_REQSENSE))
> -	disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
> -    else
> -	disc_allowed = 0;
> -
> -    if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
> -	(((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
> -	  !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
> -      try_sync_nego = 1;
> -    else
> -      try_sync_nego = 0;
> -
> -    pSRB->MsgCnt = 0;
> -    cmd = SEL_W_ATN;
> -    DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
> -    /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
> -    if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && (scmd->flags & SCMD_TAGGED)) {
> -	DC390_write8(ScsiFifo, MSG_SIMPLE_TAG);
> -	pDCB->TagMask |= 1 << scmd->request->tag;
> -	pSRB->TagNumber = scmd->request->tag;
> -	DC390_write8(ScsiFifo, scmd->request->tag);
> -	DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
> -	cmd = SEL_W_ATN3;
> -    } else {
> -	/* No TagQ */
> -//no_tag:
> -	DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
> -    }
> -
> -    pSRB->SRBState = SRB_START_;
> -
> -    if (try_sync_nego)
> -      { 
> -	u8 Sync_Off = pDCB->SyncOffset;
> -        DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
> -	pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
> -	pSRB->MsgOutBuf[1] = 3;
> -	pSRB->MsgOutBuf[2] = EXTENDED_SDTR;
> -	pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
> -	if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET;
> -	pSRB->MsgOutBuf[4] = Sync_Off;
> -	pSRB->MsgCnt = 5;
> -	//pSRB->SRBState = SRB_MSGOUT_;
> -	pSRB->SRBState |= DO_SYNC_NEGO;
> -	cmd = SEL_W_ATN_STOP;
> -      }
> -
> -    /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
> -    if (cmd != SEL_W_ATN_STOP)
> -      {
> -	if( pSRB->SRBFlag & AUTO_REQSENSE )
> -	  {
> -	    DC390_write8 (ScsiFifo, REQUEST_SENSE);
> -	    DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
> -	    DC390_write8 (ScsiFifo, 0);
> -	    DC390_write8 (ScsiFifo, 0);
> -	    DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
> -	    DC390_write8 (ScsiFifo, 0);
> -	    DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
> -	  }
> -	else	/* write cmnd to bus */ 
> -	  {
> -	    u8 *ptr; u8 i;
> -	    ptr = (u8 *)scmd->cmnd;
> -	    for (i = 0; i < scmd->cmd_len; i++)
> -	      DC390_write8 (ScsiFifo, *(ptr++));
> -	  }
> -      }
> -    DEBUG0(if (pACB->pActiveDCB)	\
> -	   printk (KERN_WARNING "DC390: ActiveDCB != 0\n"));
> -    DEBUG0(if (pDCB->pActiveSRB)	\
> -	   printk (KERN_WARNING "DC390: ActiveSRB != 0\n"));
> -    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -    if (DC390_read8 (Scsi_Status) & INTERRUPT)
> -    {
> -	dc390_freetag (pDCB, pSRB);
> -	DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n",
> -		       scmd->device->id, (u8)scmd->device->lun));
> -	pSRB->SRBState = SRB_READY;
> -	//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -	pACB->SelLost++;
> -	return 1;
> -    }
> -    DC390_write8 (ScsiCmd, cmd);
> -    pACB->pActiveDCB = pDCB;
> -    pDCB->pActiveSRB = pSRB;
> -    pACB->Connected = 1;
> -    pSRB->ScsiPhase = SCSI_NOP1;
> -    return 0;
> -}
> -
> -
> -static void __inline__
> -dc390_InvalidCmd(struct dc390_acb* pACB)
> -{
> -	if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
> -		DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> -}
> -
> -
> -static irqreturn_t __inline__
> -DC390_Interrupt(void *dev_id)
> -{
> -    struct dc390_acb *pACB = dev_id;
> -    struct dc390_dcb *pDCB;
> -    struct dc390_srb *pSRB;
> -    u8  sstatus=0;
> -    u8  phase;
> -    void   (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
> -    u8  istate, istatus;
> -
> -    sstatus = DC390_read8 (Scsi_Status);
> -    if( !(sstatus & INTERRUPT) )
> -	return IRQ_NONE;
> -
> -    DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
> -
> -    //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
> -    //dstatus = DC390_read8 (DMA_Status);
> -    //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> -    spin_lock_irq(pACB->pScsiHost->host_lock);
> -
> -    istate = DC390_read8 (Intern_State);
> -    istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
> -
> -    DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
> -    dc390_laststatus &= ~0x00ffffff;
> -    dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
> -
> -    if (sstatus & ILLEGAL_OP_ERR)
> -    {
> -	printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
> -	dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
> -    }
> -	
> -    else if (istatus &  INVALID_CMD)
> -    {
> -	printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus);
> -	dc390_InvalidCmd( pACB );
> -	goto unlock;
> -    }
> -
> -    if (istatus &  SCSI_RESET)
> -    {
> -	dc390_ScsiRstDetect( pACB );
> -	goto unlock;
> -    }
> -
> -    if (istatus &  DISCONNECTED)
> -    {
> -	dc390_Disconnect( pACB );
> -	goto unlock;
> -    }
> -
> -    if (istatus &  RESELECTED)
> -    {
> -	dc390_Reselect( pACB );
> -	goto unlock;
> -    }
> -
> -    else if (istatus & (SELECTED | SEL_ATTENTION))
> -    {
> -	printk (KERN_ERR "DC390: Target mode not supported!\n");
> -	goto unlock;
> -    }
> -
> -    if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
> -    {
> -	pDCB = pACB->pActiveDCB;
> -	if (!pDCB)
> -	{
> -		printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
> -		goto unlock;
> -	}
> -	pSRB = pDCB->pActiveSRB;
> -	if( pDCB->DCBFlag & ABORT_DEV_ )
> -	  dc390_EnableMsgOut_Abort (pACB, pSRB);
> -
> -	phase = pSRB->ScsiPhase;
> -	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
> -	stateV = (void *) dc390_phase0[phase];
> -	( *stateV )( pACB, pSRB, &sstatus );
> -
> -	pSRB->ScsiPhase = sstatus & 7;
> -	phase = (u8) sstatus & 7;
> -	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
> -	stateV = (void *) dc390_phase1[phase];
> -	( *stateV )( pACB, pSRB, &sstatus );
> -    }
> -
> - unlock:
> -    spin_unlock_irq(pACB->pScsiHost->host_lock);
> -    return IRQ_HANDLED;
> -}
> -
> -static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
> -{
> -    irqreturn_t ret;
> -    DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
> -    /* Locking is done in DC390_Interrupt */
> -    ret = DC390_Interrupt(dev_id);
> -    DEBUG1(printk (".. IRQ returned\n"));
> -    return ret;
> -}
> -
> -static void
> -dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    u8   sstatus;
> -    u32  ResidCnt;
> -    u8   dstate = 0;
> -
> -    sstatus = *psstatus;
> -
> -    if( !(pSRB->SRBState & SRB_XFERPAD) )
> -    {
> -	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
> -	    pSRB->SRBStatus |= PARITY_ERROR;
> -
> -	if( sstatus & COUNT_2_ZERO )
> -	{
> -	    unsigned long timeout = jiffies + HZ;
> -
> -	    /* Function called from the ISR with the host_lock held and interrupts disabled */
> -	    if (pSRB->SGToBeXferLen)
> -		while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
> -		    spin_unlock_irq(pACB->pScsiHost->host_lock);
> -		    udelay(50);
> -		    spin_lock_irq(pACB->pScsiHost->host_lock);
> -		}
> -	    if (!time_before(jiffies, timeout))
> -		printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
> -			DC390_read32 (DMA_Wk_ByteCntr));
> -	    dc390_laststatus &= ~0xff000000;
> -	    dc390_laststatus |= dstate << 24;
> -	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
> -	    pSRB->SGIndex++;
> -	    if( pSRB->SGIndex < pSRB->SGcount )
> -	    {
> -		pSRB->pSegmentList++;
> -
> -		dc390_start_segment(pSRB);
> -	    }
> -	    else
> -		pSRB->SGToBeXferLen = 0;
> -	}
> -	else
> -	{
> -	    ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
> -		    (((u32) DC390_read8 (CtcReg_High) << 16) |
> -		     ((u32) DC390_read8 (CtcReg_Mid) << 8) |
> -		     (u32) DC390_read8 (CtcReg_Low));
> -
> -	    dc390_advance_segment(pSRB, ResidCnt);
> -	}
> -    }
> -    if ((*psstatus & 7) != SCSI_DATA_OUT)
> -    {
> -	    DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
> -	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    }	    
> -}
> -
> -static void
> -dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    u8   sstatus, residual, bval;
> -    u32  ResidCnt, i;
> -    unsigned long   xferCnt;
> -
> -    sstatus = *psstatus;
> -
> -    if( !(pSRB->SRBState & SRB_XFERPAD) )
> -    {
> -	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
> -	    pSRB->SRBStatus |= PARITY_ERROR;
> -
> -	if( sstatus & COUNT_2_ZERO )
> -	{
> -	    int dstate = 0;
> -	    unsigned long timeout = jiffies + HZ;
> -
> -	    /* Function called from the ISR with the host_lock held and interrupts disabled */
> -	    if (pSRB->SGToBeXferLen)
> -		while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
> -		    spin_unlock_irq(pACB->pScsiHost->host_lock);
> -		    udelay(50);
> -		    spin_lock_irq(pACB->pScsiHost->host_lock);
> -		}
> -	    if (!time_before(jiffies, timeout)) {
> -		printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
> -			DC390_read32 (DMA_Wk_ByteCntr));
> -		printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
> -	    }
> -	    dc390_laststatus &= ~0xff000000;
> -	    dc390_laststatus |= dstate << 24;
> -	    DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16)	\
> -		+ ((unsigned long) DC390_read8 (CtcReg_Mid) << 8)		\
> -		+ ((unsigned long) DC390_read8 (CtcReg_Low)));
> -	    DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
> -
> -	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> -
> -	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
> -	    pSRB->SGIndex++;
> -	    if( pSRB->SGIndex < pSRB->SGcount )
> -	    {
> -		pSRB->pSegmentList++;
> -
> -		dc390_start_segment(pSRB);
> -	    }
> -	    else
> -		pSRB->SGToBeXferLen = 0;
> -	}
> -	else	/* phase changed */
> -	{
> -	    residual = 0;
> -	    bval = DC390_read8 (Current_Fifo);
> -	    while( bval & 0x1f )
> -	    {
> -		DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
> -		if( (bval & 0x1f) == 1 )
> -		{
> -		    for(i=0; i < 0x100; i++)
> -		    {
> -			bval = DC390_read8 (Current_Fifo);
> -			if( !(bval & 0x1f) )
> -			    goto din_1;
> -			else if( i == 0x0ff )
> -			{
> -			    residual = 1;   /* ;1 residual byte */
> -			    goto din_1;
> -			}
> -		    }
> -		}
> -		else
> -		    bval = DC390_read8 (Current_Fifo);
> -	    }
> -din_1:
> -	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
> -	    for (i = 0xa000; i; i--)
> -	    {
> -		bval = DC390_read8 (DMA_Status);
> -		if (bval & BLAST_COMPLETE)
> -		    break;
> -	    }
> -	    /* It seems a DMA Blast abort isn't that bad ... */
> -	    if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
> -	    //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> -	    dc390_laststatus &= ~0xff000000;
> -	    dc390_laststatus |= bval << 24;
> -
> -	    DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
> -	    ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
> -			((u32) DC390_read8 (CtcReg_Mid) << 8)) |
> -		    (u32) DC390_read8 (CtcReg_Low);
> -
> -	    xferCnt = dc390_advance_segment(pSRB, ResidCnt);
> -
> -	    if (residual) {
> -		size_t count = 1;
> -		size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
> -		unsigned long flags;
> -		u8 *ptr;
> -
> -		bval = DC390_read8 (ScsiFifo);	    /* get one residual byte */
> -
> -		local_irq_save(flags);
> -		ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
> -		if (likely(ptr)) {
> -			*(ptr + offset) = bval;
> -			scsi_kunmap_atomic_sg(ptr);
> -		}
> -		local_irq_restore(flags);
> -		WARN_ON(!ptr);
> -
> -		/* 1 more byte read */
> -		xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
> -	    }
> -	    DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
> -			   pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
> -	}
> -    }
> -    if ((*psstatus & 7) != SCSI_DATA_IN)
> -    {
> -	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> -    }
> -}
> -
> -static void
> -dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -static void
> -dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -
> -    pSRB->TargetStatus = DC390_read8 (ScsiFifo);
> -    //udelay (1);
> -    pSRB->EndMessage = DC390_read8 (ScsiFifo);	/* get message */
> -
> -    *psstatus = SCSI_NOP0;
> -    pSRB->SRBState = SRB_COMPLETED;
> -    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
> -}
> -
> -static void
> -dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
> -	*psstatus = SCSI_NOP0;
> -    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -
> -static void __inline__
> -dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
> -{
> -  DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> -  DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> -  DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> -  DC390_write8 (CtrlReg4, pDCB->CtrlR4);
> -  dc390_SetXferRate (pACB, pDCB);
> -}
> -
> -
> -#ifdef DC390_DEBUG0
> -static void
> -dc390_printMsg (u8 *MsgBuf, u8 len)
> -{
> -  int i;
> -  printk (" %02x", MsgBuf[0]);
> -  for (i = 1; i < len; i++)
> -    printk (" %02x", MsgBuf[i]);
> -  printk ("\n");
> -}
> -#endif
> -
> -#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
> -
> -/* reject_msg */
> -static void __inline__
> -dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> -  pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
> -  pSRB->MsgCnt = 1;
> -  DC390_ENABLE_MSGOUT;
> -  DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
> -}
> -
> -/* abort command */
> -static void
> -dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
> -{
> -    pSRB->MsgOutBuf[0] = ABORT; 
> -    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
> -    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
> -}
> -
> -static struct dc390_srb*
> -dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
> -{
> -  struct dc390_srb* pSRB = pDCB->pGoingSRB;
> -
> -  if (pSRB)
> -    {
> -	struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
> -	pSRB = (struct dc390_srb *)scmd->host_scribble;
> -
> -	if (pDCB->DCBFlag & ABORT_DEV_)
> -	{
> -	  pSRB->SRBState = SRB_ABORT_SENT;
> -	  dc390_EnableMsgOut_Abort( pACB, pSRB );
> -	}
> -
> -	if (!(pSRB->SRBState & SRB_DISCONNECT))
> -		goto mingx0;
> -
> -	pDCB->pActiveSRB = pSRB;
> -	pSRB->SRBState = SRB_DATA_XFER;
> -    }
> -  else
> -    {
> -    mingx0:
> -      pSRB = pACB->pTmpSRB;
> -      pSRB->SRBState = SRB_UNEXPECT_RESEL;
> -      pDCB->pActiveSRB = pSRB;
> -      pSRB->MsgOutBuf[0] = ABORT_TAG;
> -      pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
> -    }
> -  return pSRB;
> -}
> -
> -
> -/* set async transfer mode */
> -static void 
> -dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> -  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
> -  if (!(pSRB->SRBState & DO_SYNC_NEGO)) 
> -    printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
> -  pSRB->SRBState &= ~DO_SYNC_NEGO;
> -  pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
> -  pDCB->SyncPeriod = 0;
> -  pDCB->SyncOffset = 0;
> -  //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
> -  pDCB->CtrlR3 = FAST_CLK;	/* fast clock / normal scsi */
> -  pDCB->CtrlR4 &= 0x3f;
> -  pDCB->CtrlR4 |= pACB->glitch_cfg;	/* glitch eater */
> -  dc390_reprog (pACB, pDCB);
> -}
> -
> -/* set sync transfer mode */
> -static void
> -dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> -  u8 bval;
> -  u16 wval, wval1;
> -  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
> -  u8 oldsyncperiod = pDCB->SyncPeriod;
> -  u8 oldsyncoffset = pDCB->SyncOffset;
> -  
> -  if (!(pSRB->SRBState & DO_SYNC_NEGO))
> -    {
> -      printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", 
> -	      pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
> -
> -      /* reject */
> -      //dc390_MsgIn_reject (pACB, pSRB);
> -      //return dc390_MsgIn_set_async (pACB, pSRB);
> -
> -      /* Reply with corrected SDTR Message */
> -      if (pSRB->MsgInBuf[4] > 15)
> -	{ 
> -	  printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
> -	  pSRB->MsgInBuf[4] = 15;
> -	}
> -      if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
> -	{
> -	  printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
> -	  pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
> -	}
> -      memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
> -      pSRB->MsgCnt = 5;
> -      DC390_ENABLE_MSGOUT;
> -    }
> -
> -  pSRB->SRBState &= ~DO_SYNC_NEGO;
> -  pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
> -  pDCB->SyncOffset &= 0x0f0;
> -  pDCB->SyncOffset |= pSRB->MsgInBuf[4];
> -  pDCB->NegoPeriod = pSRB->MsgInBuf[3];
> -
> -  wval = (u16) pSRB->MsgInBuf[3];
> -  wval = wval << 2; wval -= 3; wval1 = wval / 25;	/* compute speed */
> -  if( (wval1 * 25) != wval) wval1++;
> -  bval = FAST_CLK+FAST_SCSI;	/* fast clock / fast scsi */
> -
> -  pDCB->CtrlR4 &= 0x3f;		/* Glitch eater: 12ns less than normal */
> -  if (pACB->glitch_cfg != NS_TO_GLITCH(0))
> -    pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
> -  else
> -    pDCB->CtrlR4 |= NS_TO_GLITCH(0);
> -  if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
> -
> -  if (wval1 >= 8)
> -    {
> -      wval1--;	/* Timing computation differs by 1 from FAST_SCSI */
> -      bval = FAST_CLK;		/* fast clock / normal scsi */
> -      pDCB->CtrlR4 |= pACB->glitch_cfg; 	/* glitch eater */
> -    }
> -
> -  pDCB->CtrlR3 = bval;
> -  pDCB->SyncPeriod = (u8)wval1;
> -  
> -  if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
> -    {
> -      if (! (bval & FAST_SCSI)) wval1++;
> -      printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, 
> -	      40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
> -    }
> -  
> -  dc390_reprog (pACB, pDCB);
> -}
> -
> -
> -/* handle RESTORE_PTR */
> -/* This doesn't look very healthy... to-be-fixed */
> -static void 
> -dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> -    struct scsi_cmnd *pcmd = pSRB->pcmd;
> -    struct scatterlist *psgl;
> -    pSRB->TotalXferredLen = 0;
> -    pSRB->SGIndex = 0;
> -    if (scsi_sg_count(pcmd)) {
> -	size_t saved;
> -	pSRB->pSegmentList = scsi_sglist(pcmd);
> -	psgl = pSRB->pSegmentList;
> -	//dc390_pci_sync(pSRB);
> -
> -	while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
> -	{
> -	    pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
> -	    pSRB->SGIndex++;
> -	    if( pSRB->SGIndex < pSRB->SGcount )
> -	    {
> -		pSRB->pSegmentList++;
> -
> -		dc390_start_segment(pSRB);
> -	    }
> -	    else
> -		pSRB->SGToBeXferLen = 0;
> -	}
> -
> -	saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
> -	pSRB->SGToBeXferLen -= saved;
> -	pSRB->SGBusAddr += saved;
> -	printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
> -		pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
> -
> -    } else {
> -	 pSRB->SGcount = 0;
> -	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
> -    }
> -
> -  pSRB->TotalXferredLen = pSRB->Saved_Ptr;
> -}
> -
> -
> -/* According to the docs, the AM53C974 reads the message and 
> - * generates a Successful Operation IRQ before asserting ACK for
> - * the last byte (how does it know whether it's the last ?) */
> -/* The old code handled it in another way, indicating, that on
> - * every message byte an IRQ is generated and every byte has to
> - * be manually ACKed. Hmmm ?  (KG, 98/11/28) */
> -/* The old implementation was correct. Sigh! */
> -
> -/* Check if the message is complete */
> -static u8 __inline__
> -dc390_MsgIn_complete (u8 *msgbuf, u32 len)
> -{ 
> -  if (*msgbuf == EXTENDED_MESSAGE)
> -  {
> -	if (len < 2) return 0;
> -	if (len < msgbuf[1] + 2) return 0;
> -  }
> -  else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
> -	if (len < 2) return 0;
> -  return 1;
> -}
> -
> -
> -
> -/* read and eval received messages */
> -static void
> -dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
> -
> -    /* Read the msg */
> -
> -    pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
> -    //pSRB->SRBState = 0;
> -
> -    /* Msg complete ? */
> -    if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
> -      {
> -	DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
> -	/* Now eval the msg */
> -	switch (pSRB->MsgInBuf[0]) 
> -	  {
> -	  case DISCONNECT: 
> -	    pSRB->SRBState = SRB_DISCONNECT; break;
> -	    
> -	  case SIMPLE_QUEUE_TAG:
> -	  case HEAD_OF_QUEUE_TAG:
> -	  case ORDERED_QUEUE_TAG:
> -	    pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
> -	    break;
> -	    
> -	  case MESSAGE_REJECT: 
> -	    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
> -	    pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
> -	    if( pSRB->SRBState & DO_SYNC_NEGO)
> -	      dc390_MsgIn_set_async (pACB, pSRB);
> -	    break;
> -	    
> -	  case EXTENDED_MESSAGE:
> -	    /* reject every extended msg but SDTR */
> -	    if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
> -	      dc390_MsgIn_reject (pACB, pSRB);
> -	    else
> -	      {
> -		if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
> -		  dc390_MsgIn_set_async (pACB, pSRB);
> -		else
> -		  dc390_MsgIn_set_sync (pACB, pSRB);
> -	      }
> -	    
> -	    // nothing has to be done
> -	  case COMMAND_COMPLETE: break;
> -	    
> -	    // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
> -	    // scsi command. Thanks, Gerard, for pointing it out.
> -	  case SAVE_POINTERS: 
> -	    pSRB->Saved_Ptr = pSRB->TotalXferredLen;
> -	    break;
> -	    // The device might want to restart transfer with a RESTORE
> -	  case RESTORE_POINTERS:
> -	    DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n"));
> -	    dc390_restore_ptr (pACB, pSRB);
> -	    break;
> -
> -	    // reject unknown messages
> -	  default: dc390_MsgIn_reject (pACB, pSRB);
> -	  }
> -	
> -	/* Clear counter and MsgIn state */
> -	pSRB->SRBState &= ~SRB_MSGIN;
> -	pACB->MsgLen = 0;
> -      }
> -
> -    *psstatus = SCSI_NOP0;
> -    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
> -    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -
> -static void
> -dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
> -{
> -    unsigned long  lval;
> -    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
> -
> -    if (pSRB == pACB->pTmpSRB)
> -    {
> -	if (pDCB)
> -		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
> -	else
> -		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
> -
> -	/* Try to recover - some broken disks react badly to tagged INQUIRY */
> -	if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
> -		pSRB = pDCB->pGoingSRB;
> -		pDCB->pActiveSRB = pSRB;
> -	} else {
> -		pSRB->pSRBDCB = pDCB;
> -		dc390_EnableMsgOut_Abort(pACB, pSRB);
> -		if (pDCB)
> -			pDCB->DCBFlag |= ABORT_DEV;
> -		return;
> -	}
> -    }
> -
> -    if( pSRB->SGIndex < pSRB->SGcount )
> -    {
> -	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> -	if( !pSRB->SGToBeXferLen )
> -	{
> -	    dc390_start_segment(pSRB);
> -
> -	    DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
> -	}
> -	lval = pSRB->SGToBeXferLen;
> -	DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
> -	DC390_write8 (CtcReg_Low, (u8) lval);
> -	lval >>= 8;
> -	DC390_write8 (CtcReg_Mid, (u8) lval);
> -	lval >>= 8;
> -	DC390_write8 (CtcReg_High, (u8) lval);
> -
> -	DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
> -	DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
> -
> -	//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> -	pSRB->SRBState = SRB_DATA_XFER;
> -
> -	DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
> -
> -	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
> -	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
> -	//DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
> -	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
> -    }
> -    else    /* xfer pad */
> -    {
> -	if( pSRB->SGcount )
> -	{
> -	    pSRB->AdaptStatus = H_OVER_UNDER_RUN;
> -	    pSRB->SRBStatus |= OVER_RUN;
> -	    DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
> -	}
> -	DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
> -	DC390_write8 (CtcReg_Low, 0);
> -	DC390_write8 (CtcReg_Mid, 0);
> -	DC390_write8 (CtcReg_High, 0);
> -
> -	pSRB->SRBState |= SRB_XFERPAD;
> -	DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
> -/*
> -	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> -	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
> -*/
> -    }
> -}
> -
> -
> -static void
> -dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
> -}
> -
> -static void
> -dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
> -}
> -
> -static void
> -dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    struct dc390_dcb*   pDCB;
> -    u8  i, cnt;
> -    u8     *ptr;
> -
> -    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
> -    {
> -	cnt = (u8) pSRB->pcmd->cmd_len;
> -	ptr = (u8 *) pSRB->pcmd->cmnd;
> -	for(i=0; i < cnt; i++)
> -	    DC390_write8 (ScsiFifo, *(ptr++));
> -    }
> -    else
> -    {
> -	DC390_write8 (ScsiFifo, REQUEST_SENSE);
> -	pDCB = pACB->pActiveDCB;
> -	DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
> -	DC390_write8 (ScsiFifo, 0);
> -	DC390_write8 (ScsiFifo, 0);
> -	DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
> -	DC390_write8 (ScsiFifo, 0);
> -	DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
> -    }
> -    pSRB->SRBState = SRB_COMMAND;
> -    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> -}
> -
> -static void
> -dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    pSRB->SRBState = SRB_STATUS;
> -    DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
> -    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -static void
> -dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    u8   bval, i, cnt;
> -    u8     *ptr;
> -    struct dc390_dcb*    pDCB;
> -
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    pDCB = pACB->pActiveDCB;
> -    if( !(pSRB->SRBState & SRB_MSGOUT) )
> -    {
> -	cnt = pSRB->MsgCnt;
> -	if( cnt )
> -	{
> -	    ptr = (u8 *) pSRB->MsgOutBuf;
> -	    for(i=0; i < cnt; i++)
> -		DC390_write8 (ScsiFifo, *(ptr++));
> -	    pSRB->MsgCnt = 0;
> -	    if( (pDCB->DCBFlag & ABORT_DEV_) &&
> -		(pSRB->MsgOutBuf[0] == ABORT) )
> -		pSRB->SRBState = SRB_ABORT_SENT;
> -	}
> -	else
> -	{
> -	    bval = ABORT;	/* ??? MSG_NOP */
> -	    if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
> -		(pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
> -		(pSRB->SRBFlag & AUTO_REQSENSE) )
> -	    {
> -		if( pDCB->SyncMode & SYNC_ENABLE )
> -		    goto  mop1;
> -	    }
> -	    DC390_write8 (ScsiFifo, bval);
> -	}
> -	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> -    }
> -    else
> -    {
> -mop1:
> -        printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
> -	DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
> -	DC390_write8 (ScsiFifo, 3);	/*    ;length of extended msg */
> -	DC390_write8 (ScsiFifo, EXTENDED_SDTR);	/*    ; sync nego */
> -	DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
> -	if (pDCB->SyncOffset & 0x0f)
> -		    DC390_write8 (ScsiFifo, pDCB->SyncOffset);
> -	else
> -		    DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);		    
> -	pSRB->SRBState |= DO_SYNC_NEGO;
> -	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> -    }
> -}
> -
> -static void
> -dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    if( !(pSRB->SRBState & SRB_MSGIN) )
> -    {
> -	pSRB->SRBState &= ~SRB_DISCONNECT;
> -	pSRB->SRBState |= SRB_MSGIN;
> -    }
> -    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> -    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -static void
> -dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -static void
> -dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -
> -static void
> -dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
> -{
> -    u8  bval, i, cnt;
> -    struct dc390_dcb*   ptr;
> -
> -    if( !(pDCB->TargetLUN) )
> -    {
> -	if( !pACB->scan_devices )
> -	{
> -	    ptr = pACB->pLinkDCB;
> -	    cnt = pACB->DCBCnt;
> -	    bval = pDCB->TargetID;
> -	    for(i=0; i<cnt; i++)
> -	    {
> -		if( ptr->TargetID == bval )
> -		{
> -		    ptr->SyncPeriod = pDCB->SyncPeriod;
> -		    ptr->SyncOffset = pDCB->SyncOffset;
> -		    ptr->CtrlR3 = pDCB->CtrlR3;
> -		    ptr->CtrlR4 = pDCB->CtrlR4;
> -		    ptr->SyncMode = pDCB->SyncMode;
> -		}
> -		ptr = ptr->pNextDCB;
> -	    }
> -	}
> -    }
> -    return;
> -}
> -
> -
> -static void
> -dc390_Disconnect( struct dc390_acb* pACB )
> -{
> -    struct dc390_dcb *pDCB;
> -    struct dc390_srb *pSRB, *psrb;
> -    u8  i, cnt;
> -
> -    DEBUG0(printk(KERN_INFO "DISC,"));
> -
> -    if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
> -    pACB->Connected = 0;
> -    pDCB = pACB->pActiveDCB;
> -    if (!pDCB)
> -     {
> -	DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
> -	       pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
> -	mdelay(400);
> -	DC390_read8 (INT_Status);	/* Reset Pending INT */
> -	DC390_write8 (ScsiCmd, EN_SEL_RESEL);
> -	return;
> -     }
> -    DC390_write8 (ScsiCmd, EN_SEL_RESEL);
> -    pSRB = pDCB->pActiveSRB;
> -    pACB->pActiveDCB = NULL;
> -    pSRB->ScsiPhase = SCSI_NOP0;
> -    if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
> -	pSRB->SRBState = 0;
> -    else if( pSRB->SRBState & SRB_ABORT_SENT )
> -    {
> -	pDCB->TagMask = 0;
> -	pDCB->DCBFlag = 0;
> -	cnt = pDCB->GoingSRBCnt;
> -	pDCB->GoingSRBCnt = 0;
> -	pSRB = pDCB->pGoingSRB;
> -	for( i=0; i < cnt; i++)
> -	{
> -	    psrb = pSRB->pNextSRB;
> -	    dc390_Free_insert (pACB, pSRB);
> -	    pSRB = psrb;
> -	}
> -	pDCB->pGoingSRB = NULL;
> -    }
> -    else
> -    {
> -	if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
> -	   !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
> -	{	/* Selection time out */
> -		pSRB->AdaptStatus = H_SEL_TIMEOUT;
> -		pSRB->TargetStatus = 0;
> -		goto  disc1;
> -	}
> -	else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
> -	{
> -disc1:
> -	    dc390_freetag (pDCB, pSRB);
> -	    pDCB->pActiveSRB = NULL;
> -	    pSRB->SRBState = SRB_FREE;
> -	    dc390_SRBdone( pACB, pDCB, pSRB);
> -	}
> -    }
> -    pACB->MsgLen = 0;
> -}
> -
> -
> -static void
> -dc390_Reselect( struct dc390_acb* pACB )
> -{
> -    struct dc390_dcb*   pDCB;
> -    struct dc390_srb*   pSRB;
> -    u8  id, lun;
> -
> -    DEBUG0(printk(KERN_INFO "RSEL,"));
> -    pACB->Connected = 1;
> -    pDCB = pACB->pActiveDCB;
> -    if( pDCB )
> -    {	/* Arbitration lost but Reselection won */
> -	DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
> -	pSRB = pDCB->pActiveSRB;
> -	if( !( pACB->scan_devices ) )
> -	{
> -	    struct scsi_cmnd *pcmd = pSRB->pcmd;
> -	    scsi_set_resid(pcmd, scsi_bufflen(pcmd));
> -	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> -	    dc390_Going_remove(pDCB, pSRB);
> -	    dc390_Free_insert(pACB, pSRB);
> -	    pcmd->scsi_done (pcmd);
> -	    DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
> -	}
> -    }
> -    /* Get ID */
> -    lun = DC390_read8 (ScsiFifo);
> -    DEBUG0(printk ("Dev %02x,", lun));
> -    if (!(lun & (1 << pACB->pScsiHost->this_id)))
> -      printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
> -    else
> -      lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
> -    id = 0; while (lun >>= 1) id++;
> -    /* Get LUN */
> -    lun = DC390_read8 (ScsiFifo);
> -    if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
> -    lun &= 7;
> -    DEBUG0(printk ("(%02i-%i),", id, lun));
> -    pDCB = dc390_findDCB (pACB, id, lun);
> -    if (!pDCB)
> -    {
> -	printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
> -		    id, lun);
> -	return;
> -    }
> -    pACB->pActiveDCB = pDCB;
> -    /* TagQ: We expect a message soon, so never mind the exact SRB */
> -    if( pDCB->SyncMode & EN_TAG_QUEUEING )
> -    {
> -	pSRB = pACB->pTmpSRB;
> -	pDCB->pActiveSRB = pSRB;
> -    }
> -    else
> -    {
> -	pSRB = pDCB->pActiveSRB;
> -	if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
> -	{
> -	    pSRB= pACB->pTmpSRB;
> -	    pSRB->SRBState = SRB_UNEXPECT_RESEL;
> -	    printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
> -		    id, lun);
> -	    pDCB->pActiveSRB = pSRB;
> -	    dc390_EnableMsgOut_Abort ( pACB, pSRB );
> -	}
> -	else
> -	{
> -	    if( pDCB->DCBFlag & ABORT_DEV_ )
> -	    {
> -		pSRB->SRBState = SRB_ABORT_SENT;
> -		printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
> -			id, lun);
> -		dc390_EnableMsgOut_Abort( pACB, pSRB );
> -	    }
> -	    else
> -		pSRB->SRBState = SRB_DATA_XFER;
> -	}
> -    }
> -
> -    DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
> -    pSRB->ScsiPhase = SCSI_NOP0;
> -    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
> -    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> -    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> -    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
> -    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> -    DC390_write8 (CtrlReg4, pDCB->CtrlR4);	/* ; Glitch eater */
> -    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);	/* ;to release the /ACK signal */
> -}
> -
> -static int __inline__
> -dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> -	struct scsi_cmnd *pcmd;
> -
> -	pcmd = pSRB->pcmd;
> -
> -	REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
> -			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
> -
> -	pSRB->SRBFlag |= AUTO_REQSENSE;
> -	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
> -	pSRB->AdaptStatus = 0;
> -	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
> -
> -	/* We are called from SRBdone, original PCI mapping has been removed
> -	 * already, new one is set up from StartSCSI */
> -	pSRB->SGIndex = 0;
> -
> -	pSRB->TotalXferredLen = 0;
> -	pSRB->SGToBeXferLen = 0;
> -	return dc390_StartSCSI(pACB, pDCB, pSRB);
> -}
> -
> -
> -static void
> -dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
> -{
> -    u8 status;
> -    struct scsi_cmnd *pcmd;
> -
> -    pcmd = pSRB->pcmd;
> -    /* KG: Moved pci_unmap here */
> -    dc390_pci_unmap(pSRB);
> -
> -    status = pSRB->TargetStatus;
> -
> -    DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
> -    if(pSRB->SRBFlag & AUTO_REQSENSE)
> -    {	/* Last command was a Request Sense */
> -	pSRB->SRBFlag &= ~AUTO_REQSENSE;
> -	pSRB->AdaptStatus = 0;
> -	pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
> -
> -	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
> -	if (status == SAM_STAT_CHECK_CONDITION)
> -	    pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
> -	else /* Retry */
> -	{
> -	    if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
> -	    {
> -		/* Don't retry on TEST_UNIT_READY */
> -		pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
> -		REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
> -		       (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
> -	    } else {
> -		SET_RES_DRV(pcmd->result, DRIVER_SENSE);
> -		//pSRB->ScsiCmdLen	 = (u8) (pSRB->Segment1[0] >> 8);
> -		DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
> -		pSRB->TotalXferredLen = 0;
> -		SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> -	    }
> -	}
> -	goto cmd_done;
> -    }
> -    if( status )
> -    {
> -	if (status == SAM_STAT_CHECK_CONDITION)
> -	{
> -	    if (dc390_RequestSense(pACB, pDCB, pSRB)) {
> -		SET_RES_DID(pcmd->result, DID_ERROR);
> -		goto cmd_done;
> -	    }
> -	    return;
> -	}
> -	else if (status == SAM_STAT_TASK_SET_FULL)
> -	{
> -	    scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
> -	    DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
> -	    pSRB->TotalXferredLen = 0;
> -	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> -	}
> -	else if (status == SAM_STAT_BUSY &&
> -		 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
> -		 pACB->scan_devices)
> -	{
> -	    pSRB->AdaptStatus = 0;
> -	    pSRB->TargetStatus = status;
> -	    pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
> -	}
> -	else
> -	{   /* Another error */
> -	    pSRB->TotalXferredLen = 0;
> -	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> -	    goto cmd_done;
> -	}
> -    }
> -    else
> -    {	/*  Target status == 0 */
> -	status = pSRB->AdaptStatus;
> -	if (status == H_OVER_UNDER_RUN)
> -	{
> -	    pSRB->TargetStatus = 0;
> -	    SET_RES_DID(pcmd->result,DID_OK);
> -	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
> -	}
> -	else if (status == H_SEL_TIMEOUT)
> -	{
> -	    pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
> -	    /* Devices are removed below ... */
> -	}
> -	else if( pSRB->SRBStatus & PARITY_ERROR)
> -	{
> -	    //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
> -	    SET_RES_DID(pcmd->result,DID_PARITY);
> -	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
> -	}
> -	else		       /* No error */
> -	{
> -	    pSRB->AdaptStatus = 0;
> -	    pSRB->TargetStatus = 0;
> -	    SET_RES_DID(pcmd->result,DID_OK);
> -	}
> -    }
> -
> -cmd_done:
> -    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
> -
> -    dc390_Going_remove (pDCB, pSRB);
> -    /* Add to free list */
> -    dc390_Free_insert (pACB, pSRB);
> -
> -    DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
> -    pcmd->scsi_done (pcmd);
> -
> -    return;
> -}
> -
> -
> -/* Remove all SRBs from Going list and inform midlevel */
> -static void
> -dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
> -{
> -    struct dc390_dcb *pDCB, *pdcb;
> -    struct dc390_srb *psrb, *psrb2;
> -    int i;
> -    struct scsi_cmnd *pcmd;
> -
> -    pDCB = pACB->pLinkDCB;
> -    pdcb = pDCB;
> -    if (! pdcb) return;
> -    do
> -    {
> -	psrb = pdcb->pGoingSRB;
> -	for (i = 0; i < pdcb->GoingSRBCnt; i++)
> -	{
> -	    psrb2 = psrb->pNextSRB;
> -	    pcmd = psrb->pcmd;
> -	    dc390_Free_insert (pACB, psrb);
> -	    psrb  = psrb2;
> -	}
> -	pdcb->GoingSRBCnt = 0;
> -	pdcb->pGoingSRB = NULL;
> -	pdcb->TagMask = 0;
> -	pdcb = pdcb->pNextDCB;
> -    } while( pdcb != pDCB );
> -}
> -
> -
> -static void
> -dc390_ResetSCSIBus( struct dc390_acb* pACB )
> -{
> -    //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
> -    //udelay (250);
> -    //DC390_write8 (ScsiCmd, NOP_CMD);
> -
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -    DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
> -    pACB->Connected = 0;
> -
> -    return;
> -}
> -
> -static void
> -dc390_ScsiRstDetect( struct dc390_acb* pACB )
> -{
> -    printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
> -    //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
> -
> -    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -    /* Unlock before ? */
> -    /* delay half a second */
> -    udelay (1000);
> -    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> -    pACB->last_reset = jiffies + 5*HZ/2
> -		    + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> -    pACB->Connected = 0;
> -
> -    if( pACB->ACBFlag & RESET_DEV )
> -	pACB->ACBFlag |= RESET_DONE;
> -    else
> -    {   /* Reset was issued by sb else */
> -	pACB->ACBFlag |= RESET_DETECT;
> -
> -	dc390_ResetDevParam( pACB );
> -	dc390_DoingSRB_Done( pACB, NULL);
> -	//dc390_RecoverSRB( pACB );
> -	pACB->pActiveDCB = NULL;
> -	pACB->ACBFlag = 0;
> -    }
> -    return;
> -}
> -
> -static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
> -		void (*done)(struct scsi_cmnd *))
> -{
> -	struct scsi_device *sdev = cmd->device;
> -	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
> -	struct dc390_dcb *dcb = sdev->hostdata;
> -	struct dc390_srb *srb;
> -
> -	if (sdev->queue_depth <= dcb->GoingSRBCnt)
> -		goto device_busy;
> -	if (acb->pActiveDCB)
> -		goto host_busy;
> -	if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
> -		goto host_busy;
> -
> -	srb = acb->pFreeSRB;
> -	if (unlikely(srb == NULL))
> -		goto host_busy;
> -
> -	cmd->scsi_done = done;
> -	cmd->result = 0;
> -	acb->Cmds++;
> -
> -	acb->pFreeSRB = srb->pNextSRB;
> -	srb->pNextSRB = NULL;
> -
> -	srb->pSRBDCB = dcb;
> -	srb->pcmd = cmd;
> -	cmd->host_scribble = (char *)srb;
> -    
> -	srb->SGIndex = 0;
> -	srb->AdaptStatus = 0;
> -	srb->TargetStatus = 0;
> -	srb->MsgCnt = 0;
> -
> -	srb->SRBStatus = 0;
> -	srb->SRBFlag = 0;
> -	srb->SRBState = 0;
> -	srb->TotalXferredLen = 0;
> -	srb->SGBusAddr = 0;
> -	srb->SGToBeXferLen = 0;
> -	srb->ScsiPhase = 0;
> -	srb->EndMessage = 0;
> -	srb->TagNumber = SCSI_NO_TAG;
> -
> -	if (dc390_StartSCSI(acb, dcb, srb)) {
> -		dc390_Free_insert(acb, srb);
> -		goto host_busy;
> -	}
> -
> -	dc390_Going_append(dcb, srb);
> -
> -	return 0;
> -
> - host_busy:
> -	return SCSI_MLQUEUE_HOST_BUSY;
> -
> - device_busy:
> -	return SCSI_MLQUEUE_DEVICE_BUSY;
> -}
> -
> -static DEF_SCSI_QCMD(DC390_queuecommand)
> -
> -static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> -    struct pci_dev *pdev;
> -    u16 pstat;
> -
> -    if (!pDCB) pDCB = pACB->pActiveDCB;
> -    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
> -
> -    if (pSRB) 
> -    {
> -	printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",
> -		pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
> -		pSRB->ScsiPhase);
> -	printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
> -    }
> -    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);
> -    printk ("DC390: Register dump: SCSI block:\n");
> -    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
> -    printk ("DC390:  %06x   %02x   %02x   %02x",
> -	    DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
> -	    DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
> -    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",
> -	    DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
> -	    DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
> -    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
> -    if (DC390_read8(Current_Fifo) & 0x1f)
> -      {
> -	printk ("DC390: FIFO:");
> -	while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));
> -	printk ("\n");
> -      }
> -    printk ("DC390: Register dump: DMA engine:\n");
> -    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
> -    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
> -	    DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
> -	    DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
> -	    DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
> -    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> -    pdev = pACB->pdev;
> -    pci_read_config_word(pdev, PCI_STATUS, &pstat);
> -    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
> -    printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
> -}
> -
> -
> -static int DC390_abort(struct scsi_cmnd *cmd)
> -{
> -	struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
> -	struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
> -
> -	scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
> -
> -	/* abort() is too stupid for already sent commands at the moment. 
> -	 * If it's called we are in trouble anyway, so let's dump some info 
> -	 * into the syslog at least. (KG, 98/08/20,99/06/20) */
> -	dc390_dumpinfo(pACB, pDCB, NULL);
> -
> -	pDCB->DCBFlag |= ABORT_DEV_;
> -	printk(KERN_INFO "DC390: Aborted.\n");
> -
> -	return FAILED;
> -}
> -
> -
> -static void dc390_ResetDevParam( struct dc390_acb* pACB )
> -{
> -    struct dc390_dcb *pDCB, *pdcb;
> -
> -    pDCB = pACB->pLinkDCB;
> -    if (! pDCB) return;
> -    pdcb = pDCB;
> -    do
> -    {
> -	pDCB->SyncMode &= ~SYNC_NEGO_DONE;
> -	pDCB->SyncPeriod = 0;
> -	pDCB->SyncOffset = 0;
> -	pDCB->TagMask = 0;
> -	pDCB->CtrlR3 = FAST_CLK;
> -	pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
> -	pDCB->CtrlR4 |= pACB->glitch_cfg;
> -	pDCB = pDCB->pNextDCB;
> -    }
> -    while( pdcb != pDCB );
> -    pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT);
> -
> -}
> -
> -static int DC390_bus_reset (struct scsi_cmnd *cmd)
> -{
> -	struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
> -	u8   bval;
> -
> -	spin_lock_irq(cmd->device->host->host_lock);
> -
> -	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
> -	DC390_write8(CtrlReg1, bval);	/* disable IRQ on bus reset */
> -
> -	pACB->ACBFlag |= RESET_DEV;
> -	dc390_ResetSCSIBus(pACB);
> -
> -	dc390_ResetDevParam(pACB);
> -	mdelay(1);
> -	pACB->last_reset = jiffies + 3*HZ/2
> -		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> -
> -	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> -	DC390_read8(INT_Status);		/* Reset Pending INT */
> -
> -	dc390_DoingSRB_Done(pACB, cmd);
> -
> -	pACB->pActiveDCB = NULL;
> -	pACB->ACBFlag = 0;
> -
> -	bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
> -	DC390_write8(CtrlReg1, bval);	/* re-enable interrupt */
> -
> -	spin_unlock_irq(cmd->device->host->host_lock);
> -
> -	return SUCCESS;
> -}
> -
> -/**
> - * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
> - * scsi device that we need to deal with.
> - *
> - * @scsi_device: The new scsi device that we need to handle.
> - */
> -static int dc390_slave_alloc(struct scsi_device *scsi_device)
> -{
> -	struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
> -	struct dc390_dcb *pDCB, *pDCB2 = NULL;
> -	uint id = scsi_device->id;
> -	uint lun = scsi_device->lun;
> -
> -	pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
> -	if (!pDCB)
> -		return -ENOMEM;
> -
> -	if (!pACB->DCBCnt++) {
> -		pACB->pLinkDCB = pDCB;
> -		pACB->pDCBRunRobin = pDCB;
> -	} else {
> -		pACB->pLastDCB->pNextDCB = pDCB;
> -	}
> -   
> -	pDCB->pNextDCB = pACB->pLinkDCB;
> -	pACB->pLastDCB = pDCB;
> -
> -	pDCB->pDCBACB = pACB;
> -	pDCB->TargetID = id;
> -	pDCB->TargetLUN = lun;
> -
> -	/*
> -	 * Some values are for all LUNs: Copy them 
> -	 * In a clean way: We would have an own structure for a SCSI-ID 
> -	 */
> -	if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
> -		pDCB->DevMode = pDCB2->DevMode;
> -		pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
> -		pDCB->SyncPeriod = pDCB2->SyncPeriod;
> -		pDCB->SyncOffset = pDCB2->SyncOffset;
> -		pDCB->NegoPeriod = pDCB2->NegoPeriod;
> -      
> -		pDCB->CtrlR3 = pDCB2->CtrlR3;
> -		pDCB->CtrlR4 = pDCB2->CtrlR4;
> -	} else {
> -		u8 index = pACB->AdapterIndex;
> -		PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
> -
> -		pDCB->DevMode = prom->EE_MODE1;
> -		pDCB->NegoPeriod =
> -			(dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
> -		pDCB->CtrlR3 = FAST_CLK;
> -		pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
> -		if (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
> -			pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
> -	}
> -
> -	if (pDCB->DevMode & SYNC_NEGO_)
> -		pDCB->SyncMode |= SYNC_ENABLE;
> -	else {
> -		pDCB->SyncMode = 0;
> -		pDCB->SyncOffset &= ~0x0f;
> -	}
> -
> -	pDCB->CtrlR1 = pACB->pScsiHost->this_id;
> -	if (pDCB->DevMode & PARITY_CHK_)
> -		pDCB->CtrlR1 |= PARITY_ERR_REPO;
> -
> -	pACB->scan_devices = 1;
> -	scsi_device->hostdata = pDCB;
> -	return 0;
> -}
> -
> -/**
> - * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
> - * device that is going away.
> - *
> - * @scsi_device: The scsi device that we need to remove.
> - */
> -static void dc390_slave_destroy(struct scsi_device *scsi_device)
> -{
> -	struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
> -	struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
> -	struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
> -
> -	pACB->scan_devices = 0;
> -
> -	BUG_ON(pDCB->GoingSRBCnt > 1);
> -	
> -	if (pDCB == pACB->pLinkDCB) {
> -		if (pACB->pLastDCB == pDCB) {
> -			pDCB->pNextDCB = NULL;
> -			pACB->pLastDCB = NULL;
> -		}
> -		pACB->pLinkDCB = pDCB->pNextDCB;
> -	} else {
> -		while (pPrevDCB->pNextDCB != pDCB)
> -			pPrevDCB = pPrevDCB->pNextDCB;
> -		pPrevDCB->pNextDCB = pDCB->pNextDCB;
> -		if (pDCB == pACB->pLastDCB)
> -			pACB->pLastDCB = pPrevDCB;
> -	}
> -
> -	if (pDCB == pACB->pActiveDCB)
> -		pACB->pActiveDCB = NULL;
> -	if (pDCB == pACB->pLinkDCB)
> -		pACB->pLinkDCB = pDCB->pNextDCB;
> -	if (pDCB == pACB->pDCBRunRobin)
> -		pACB->pDCBRunRobin = pDCB->pNextDCB;
> -	kfree(pDCB); 
> -	
> -	pACB->DCBCnt--;
> -}
> -
> -static int dc390_slave_configure(struct scsi_device *sdev)
> -{
> -	struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
> -	struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
> -
> -	acb->scan_devices = 0;
> -
> -	/*
> -	 * XXX: Note that while this driver used to called scsi_activate_tcq,
> -	 * it never actually set a tag type, so emulate the old behavior.
> -	 */
> -	scsi_set_tag_type(sdev, 0);
> -
> -	if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
> -		dcb->SyncMode |= EN_TAG_QUEUEING;
> -		scsi_adjust_queue_depth(sdev, acb->TagMaxNum);
> -	}
> -
> -	return 0;
> -}
> -
> -static struct scsi_host_template driver_template = {
> -	.module			= THIS_MODULE,
> -	.proc_name		= "tmscsim", 
> -	.name			= DC390_BANNER " V" DC390_VERSION,
> -	.slave_alloc		= dc390_slave_alloc,
> -	.slave_configure	= dc390_slave_configure,
> -	.slave_destroy		= dc390_slave_destroy,
> -	.queuecommand		= DC390_queuecommand,
> -	.eh_abort_handler	= DC390_abort,
> -	.eh_bus_reset_handler	= DC390_bus_reset,
> -	.can_queue		= 1,
> -	.this_id		= 7,
> -	.sg_tablesize		= SG_ALL,
> -	.cmd_per_lun		= 1,
> -	.use_clustering		= ENABLE_CLUSTERING,
> -	.max_sectors		= 0x4000, /* 8MiB = 16 * 1024 * 512 */
> -	.use_blk_tags		= 1,
> -};
> -
> -/***********************************************************************
> - * Functions for access to DC390 EEPROM
> - * and some to emulate it
> - *
> - **********************************************************************/
> -
> -static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
> -{
> -	u8 carryFlag = 1, j = 0x80, bval;
> -	int i;
> -
> -	for (i = 0; i < 9; i++) {
> -		if (carryFlag) {
> -			pci_write_config_byte(pdev, 0x80, 0x40);
> -			bval = 0xc0;
> -		} else
> -			bval = 0x80;
> -
> -		udelay(160);
> -		pci_write_config_byte(pdev, 0x80, bval);
> -		udelay(160);
> -		pci_write_config_byte(pdev, 0x80, 0);
> -		udelay(160);
> -
> -		carryFlag = (cmd & j) ? 1 : 0;
> -		j >>= 1;
> -	}
> -}
> -
> -static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
> -{
> -	int i;
> -	u16 wval = 0;
> -	u8 bval;
> -
> -	for (i = 0; i < 16; i++) {
> -		wval <<= 1;
> -
> -		pci_write_config_byte(pdev, 0x80, 0x80);
> -		udelay(160);
> -		pci_write_config_byte(pdev, 0x80, 0x40);
> -		udelay(160);
> -		pci_read_config_byte(pdev, 0x00, &bval);
> -
> -		if (bval == 0x22)
> -			wval |= 1;
> -	}
> -
> -	return wval;
> -}
> -
> -static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
> -{
> -	u8 cmd = EEPROM_READ, i;
> -
> -	for (i = 0; i < 0x40; i++) {
> -		pci_write_config_byte(pdev, 0xc0, 0);
> -		udelay(160);
> -
> -		dc390_eeprom_prepare_read(pdev, cmd++);
> -		*ptr++ = dc390_eeprom_get_data(pdev);
> -
> -		pci_write_config_byte(pdev, 0x80, 0);
> -		pci_write_config_byte(pdev, 0x80, 0);
> -		udelay(160);
> -	}
> -}
> -
> -/* Override EEprom values with explicitly set values */
> -static void dc390_eeprom_override(u8 index)
> -{
> -	u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
> -
> -	/* Adapter Settings */
> -	if (tmscsim[0] != -2)
> -		ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0];	/* Adapter ID */
> -	if (tmscsim[3] != -2)
> -		ptr[EE_MODE2] = (u8)tmscsim[3];
> -	if (tmscsim[5] != -2)
> -		ptr[EE_DELAY] = tmscsim[5];		/* Reset delay */
> -	if (tmscsim[4] != -2)
> -		ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4];	/* Tagged Cmds */
> -
> -	/* Device Settings */
> -	for (id = 0; id < MAX_SCSI_ID; id++) {
> -		if (tmscsim[2] != -2)
> -			ptr[id << 2] = (u8)tmscsim[2];		/* EE_MODE1 */
> -		if (tmscsim[1] != -2)
> -			ptr[(id << 2) + 1] = (u8)tmscsim[1];	/* EE_Speed */
> -	}
> -}
> -
> -static int tmscsim_def[] = {
> -	7,
> -	0 /* 10MHz */,
> -	PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
> -	MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
> -	3 /* 16 Tags per LUN */,
> -	1 /* s delay after Reset */,
> -};
> -
> -/* Copy defaults over set values where missing */
> -static void dc390_fill_with_defaults (void)
> -{
> -	int i;
> -
> -	for (i = 0; i < 6; i++) {
> -		if (tmscsim[i] < 0 || tmscsim[i] > 255)
> -			tmscsim[i] = tmscsim_def[i];
> -	}
> -
> -	/* Sanity checks */
> -	if (tmscsim[0] > 7)
> -		tmscsim[0] = 7;
> -	if (tmscsim[1] > 7)
> -		tmscsim[1] = 4;
> -	if (tmscsim[4] > 5)
> -		tmscsim[4] = 4;
> -	if (tmscsim[5] > 180)
> -		tmscsim[5] = 180;
> -}
> -
> -static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
> -{
> -	u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
> -	u8 EEbuf[128];
> -	u16 *ptr = (u16 *)EEbuf, wval = 0;
> -	int i;
> -
> -	dc390_read_eeprom(pdev, ptr);
> -	memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
> -	memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], 
> -	       &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
> -
> -	dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
> -
> -	for (i = 0; i < 0x40; i++, ptr++)
> -		wval += *ptr;
> -
> -	/* no Tekram EEprom found */
> -	if (wval != 0x1234) {
> -		int speed;
> -
> -		printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
> -
> -		/*
> -		 * XXX(hch): bogus, because we might have tekram and
> -		 *           non-tekram hbas in a single machine.
> -		 */
> -		dc390_fill_with_defaults();
> -
> -		speed = dc390_clock_speed[tmscsim[1]];
> -		printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
> -		       "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
> -		       tmscsim[0], tmscsim[1], speed / 10, speed % 10,
> -		       (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
> -	}
> -}
> -
> -static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
> -{
> -	struct Scsi_Host *shost = pACB->pScsiHost;
> -	u8 dstate;
> -
> -	/* Disable SCSI bus reset interrupt */
> -	DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
> -
> -	if (pACB->Gmode2 & RST_SCSI_BUS) {
> -		dc390_ResetSCSIBus(pACB);
> -		udelay(1000);
> -		pACB->last_reset = jiffies + HZ/2 +
> -			HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> -	}
> -
> -	pACB->ACBFlag = 0;
> -
> -	/* Reset Pending INT */
> -	DC390_read8(INT_Status);
> -	
> -	/* 250ms selection timeout */
> -	DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
> -	
> -	/* Conversion factor = 0 , 40MHz clock */
> -	DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
> -	
> -	/* NOP cmd - clear command register */
> -	DC390_write8(ScsiCmd, NOP_CMD);
> -	
> -	/* Enable Feature and SCSI-2 */
> -	DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
> -	
> -	/* Fast clock */
> -	DC390_write8(CtrlReg3, FAST_CLK);
> -
> -	/* Negation */
> -	DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
> -		(dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
> -		 NEGATE_REQACKDATA : 0);
> -	
> -	/* Clear Transfer Count High: ID */
> -	DC390_write8(CtcReg_High, 0);
> -	DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
> -	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> -	DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> -	dstate = DC390_read8(DMA_Status);
> -	DC390_write8(DMA_Status, dstate);
> -}
> -
> -static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
> -{
> -	struct dc390_acb *pACB;
> -	struct Scsi_Host *shost;
> -	unsigned long io_port;
> -	int error = -ENODEV, i;
> -
> -	if (pci_enable_device(pdev))
> -		goto out;
> -
> -	pci_set_master(pdev);
> -
> -	error = -ENOMEM;
> -	if (disable_clustering)
> -		driver_template.use_clustering = DISABLE_CLUSTERING;
> -	shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
> -	if (!shost)
> -		goto out_disable_device;
> -
> -	pACB = (struct dc390_acb *)shost->hostdata;
> -	memset(pACB, 0, sizeof(struct dc390_acb));
> -
> -	dc390_check_eeprom(pdev, dc390_adapterCnt);
> -	dc390_eeprom_override(dc390_adapterCnt);
> -
> -	io_port = pci_resource_start(pdev, 0);
> -
> -	shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
> -	shost->io_port = io_port;
> -	shost->n_io_port = 0x80;
> -	shost->irq = pdev->irq;
> -	shost->base = io_port;
> -	shost->unique_id = io_port;
> -
> -	pACB->last_reset = jiffies;
> -	pACB->pScsiHost = shost;
> -	pACB->IOPortBase = (u16) io_port;
> -	pACB->IRQLevel = pdev->irq;
> -	
> -	shost->max_id = 8;
> -
> -	if (shost->max_id - 1 ==
> -	    dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
> -		shost->max_id--;
> -
> -	if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
> -		shost->max_lun = 8;
> -	else
> -		shost->max_lun = 1;
> -
> -	pACB->pFreeSRB = pACB->SRB_array;
> -	pACB->SRBCount = MAX_SRB_CNT;
> -	pACB->AdapterIndex = dc390_adapterCnt;
> -	pACB->TagMaxNum =
> -		2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
> -	pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
> -
> -	for (i = 0; i < pACB->SRBCount-1; i++)
> -		pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
> -	pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
> -	pACB->pTmpSRB = &pACB->TmpSRB;
> -
> -	pACB->sel_timeout = SEL_TIMEOUT;
> -	pACB->glitch_cfg = EATER_25NS;
> -	pACB->pdev = pdev;
> -
> -	if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
> -		printk(KERN_ERR "DC390: register IO ports error!\n");
> -		goto out_host_put;
> -	}
> -
> -	/* Reset Pending INT */
> -	DC390_read8_(INT_Status, io_port);
> -
> -	if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
> -				"tmscsim", pACB)) {
> -		printk(KERN_ERR "DC390: register IRQ error!\n");
> -		goto out_release_region;
> -	}
> -
> -	dc390_init_hw(pACB, dc390_adapterCnt);
> -	
> -	dc390_adapterCnt++;
> -
> -	pci_set_drvdata(pdev, shost);
> -
> -	error = scsi_add_host(shost, &pdev->dev);
> -	if (error)
> -		goto out_free_irq;
> -	scsi_scan_host(shost);
> -	return 0;
> -
> - out_free_irq:
> -	free_irq(pdev->irq, pACB);
> - out_release_region:
> -	release_region(io_port, shost->n_io_port);
> - out_host_put:
> -	scsi_host_put(shost);
> - out_disable_device:
> -	pci_disable_device(pdev);
> - out:
> -	return error;
> -}
> -
> -/**
> - * dc390_remove_one - Called to remove a single instance of the adapter.
> - *
> - * @dev: The PCI device to remove.
> - */
> -static void dc390_remove_one(struct pci_dev *dev)
> -{
> -	struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
> -	unsigned long iflags;
> -	struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
> -	u8 bval;
> -
> -	scsi_remove_host(scsi_host);
> -
> -	spin_lock_irqsave(scsi_host->host_lock, iflags);
> -	pACB->ACBFlag = RESET_DEV;
> -	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
> -	DC390_write8 (CtrlReg1, bval);	/* disable interrupt */
> -	if (pACB->Gmode2 & RST_SCSI_BUS)
> -		dc390_ResetSCSIBus(pACB);
> -	spin_unlock_irqrestore(scsi_host->host_lock, iflags);
> -
> -	free_irq(scsi_host->irq, pACB);
> -	release_region(scsi_host->io_port, scsi_host->n_io_port);
> -
> -	pci_disable_device(dev);
> -	scsi_host_put(scsi_host);
> -}
> -
> -static struct pci_device_id tmscsim_pci_tbl[] = {
> -	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
> -		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
> -
> -static struct pci_driver dc390_driver = {
> -	.name           = "tmscsim",
> -	.id_table       = tmscsim_pci_tbl,
> -	.probe          = dc390_probe_one,
> -	.remove         = dc390_remove_one,
> -};
> -
> -static int __init dc390_module_init(void)
> -{
> -	if (!disable_clustering) {
> -		printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
> -		printk(KERN_INFO "       with \"disable_clustering=1\" and report to maintainers\n");
> -	}
> -
> -	if (tmscsim[0] == -1 || tmscsim[0] > 15) {
> -		tmscsim[0] = 7;
> -		tmscsim[1] = 4;
> -		tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
> -		tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
> -		tmscsim[4] = 2;
> -		tmscsim[5] = 10;
> -		printk (KERN_INFO "DC390: Using safe settings.\n");
> -	}
> -
> -	return pci_register_driver(&dc390_driver);
> -}
> -
> -static void __exit dc390_module_exit(void)
> -{
> -	pci_unregister_driver(&dc390_driver);
> -}
> -
> -module_init(dc390_module_init);
> -module_exit(dc390_module_exit);
> -
> -#ifndef MODULE
> -static int __init dc390_setup (char *str)
> -{	
> -	int ints[8],i, im;
> -
> -	get_options(str, ARRAY_SIZE(ints), ints);
> -	im = ints[0];
> -
> -	if (im > 6) {
> -		printk (KERN_NOTICE "DC390: ignore extra params!\n");
> -		im = 6;
> -	}
> -
> -	for (i = 0; i < im; i++)
> -		tmscsim[i] = ints[i+1];
> -	/* dc390_checkparams (); */
> -	return 1;
> -}
> -
> -__setup("tmscsim=", dc390_setup);
> -#endif
> diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
> deleted file mode 100644
> index c9ad4bb..0000000
> --- a/drivers/scsi/tmscsim.h
> +++ /dev/null
> @@ -1,549 +0,0 @@
> -/***********************************************************************
> -;*	File Name : TMSCSIM.H					       *
> -;*		    TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter  *
> -;*		    Device Driver				       *
> -;***********************************************************************/
> -/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
> -
> -#ifndef _TMSCSIM_H
> -#define _TMSCSIM_H
> -
> -#include <linux/types.h>
> -
> -#define MAX_ADAPTER_NUM 	4
> -#define MAX_SG_LIST_BUF 	16	/* Not used */
> -#define MAX_SCSI_ID		8
> -#define MAX_SRB_CNT		50	/* Max number of started commands */
> -
> -#define SEL_TIMEOUT		153	/* 250 ms selection timeout (@ 40 MHz) */
> -
> -/*
> -;-----------------------------------------------------------------------
> -; SCSI Request Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_srb
> -{
> -//u8		CmdBlock[12];
> -
> -struct dc390_srb	*pNextSRB;
> -struct dc390_dcb	*pSRBDCB;
> -struct scsi_cmnd	*pcmd;
> -struct scatterlist	*pSegmentList;
> -
> -struct scatterlist Segmentx;	/* make a one entry of S/G list table */
> -
> -unsigned long	SGBusAddr;	/*;a segment starting address as seen by AM53C974A
> -				  in CPU endianness. We're only getting 32-bit bus
> -				  addresses by default */
> -unsigned long	SGToBeXferLen;	/*; to be xfer length */
> -unsigned long	TotalXferredLen;
> -unsigned long	SavedTotXLen;
> -unsigned long	Saved_Ptr;
> -u32		SRBState;
> -
> -u8		SRBStatus;
> -u8		SRBFlag;	/*; b0-AutoReqSense,b6-Read,b7-write */
> -				/*; b4-settimeout,b5-Residual valid */
> -u8		AdaptStatus;
> -u8		TargetStatus;
> -
> -u8		ScsiPhase;
> -s8		TagNumber;
> -u8		SGIndex;
> -u8		SGcount;
> -
> -u8		MsgCnt;
> -u8		EndMessage;
> -
> -u8		MsgInBuf[6];
> -u8		MsgOutBuf[6];
> -
> -//u8		IORBFlag;	/*;81h-Reset, 2-retry */
> -};
> -
> -
> -/*
> -;-----------------------------------------------------------------------
> -; Device Control Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_dcb
> -{
> -struct dc390_dcb	*pNextDCB;
> -struct dc390_acb	*pDCBACB;
> -
> -/* Queued SRBs */
> -struct dc390_srb	*pGoingSRB;
> -struct dc390_srb	*pGoingLast;
> -struct dc390_srb	*pActiveSRB;
> -u8		GoingSRBCnt;
> -
> -u32		TagMask;
> -
> -u8		TargetID;	/*; SCSI Target ID  (SCSI Only) */
> -u8		TargetLUN;	/*; SCSI Log.  Unit (SCSI Only) */
> -u8		DevMode;
> -u8		DCBFlag;
> -
> -u8		CtrlR1;
> -u8		CtrlR3;
> -u8		CtrlR4;
> -
> -u8		SyncMode;	/*; 0:async mode */
> -u8		NegoPeriod;	/*;for nego. */
> -u8		SyncPeriod;	/*;for reg. */
> -u8		SyncOffset;	/*;for reg. and nego.(low nibble) */
> -};
> -
> -
> -/*
> -;-----------------------------------------------------------------------
> -; Adapter Control Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_acb
> -{
> -struct Scsi_Host *pScsiHost;
> -u16		IOPortBase;
> -u8		IRQLevel;
> -u8		status;
> -
> -u8		SRBCount;
> -u8		AdapterIndex;	/*; nth Adapter this driver */
> -u8		DCBCnt;
> -
> -u8		TagMaxNum;
> -u8		ACBFlag;
> -u8		Gmode2;
> -u8		scan_devices;
> -
> -struct dc390_dcb	*pLinkDCB;
> -struct dc390_dcb	*pLastDCB;
> -struct dc390_dcb	*pDCBRunRobin;
> -
> -struct dc390_dcb	*pActiveDCB;
> -struct dc390_srb	*pFreeSRB;
> -struct dc390_srb	*pTmpSRB;
> -
> -u8		msgin123[4];
> -u8		Connected;
> -u8		pad;
> -
> -#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
> -spinlock_t	lock;
> -#endif
> -u8		sel_timeout;
> -u8		glitch_cfg;
> -
> -u8		MsgLen;
> -u8		Ignore_IRQ;	/* Not used */
> -
> -struct pci_dev	*pdev;
> -
> -unsigned long   last_reset;
> -unsigned long	Cmds;
> -u32		SelLost;
> -u32		SelConn;
> -u32		CmdInQ;
> -u32		CmdOutOfSRB;
> -
> -struct dc390_srb	TmpSRB;
> -struct dc390_srb	SRB_array[MAX_SRB_CNT]; 	/* 50 SRBs */
> -};
> -
> -
> -/*;-----------------------------------------------------------------------*/
> -
> -
> -#define BIT31	0x80000000
> -#define BIT30	0x40000000
> -#define BIT29	0x20000000
> -#define BIT28	0x10000000
> -#define BIT27	0x08000000
> -#define BIT26	0x04000000
> -#define BIT25	0x02000000
> -#define BIT24	0x01000000
> -#define BIT23	0x00800000
> -#define BIT22	0x00400000
> -#define BIT21	0x00200000
> -#define BIT20	0x00100000
> -#define BIT19	0x00080000
> -#define BIT18	0x00040000
> -#define BIT17	0x00020000
> -#define BIT16	0x00010000
> -#define BIT15	0x00008000
> -#define BIT14	0x00004000
> -#define BIT13	0x00002000
> -#define BIT12	0x00001000
> -#define BIT11	0x00000800
> -#define BIT10	0x00000400
> -#define BIT9	0x00000200
> -#define BIT8	0x00000100
> -#define BIT7	0x00000080
> -#define BIT6	0x00000040
> -#define BIT5	0x00000020
> -#define BIT4	0x00000010
> -#define BIT3	0x00000008
> -#define BIT2	0x00000004
> -#define BIT1	0x00000002
> -#define BIT0	0x00000001
> -
> -/*;---UnitCtrlFlag */
> -#define UNIT_ALLOCATED	BIT0
> -#define UNIT_INFO_CHANGED BIT1
> -#define FORMATING_MEDIA BIT2
> -#define UNIT_RETRY	BIT3
> -
> -/*;---UnitFlags */
> -#define DASD_SUPPORT	BIT0
> -#define SCSI_SUPPORT	BIT1
> -#define ASPI_SUPPORT	BIT2
> -
> -/*;----SRBState machine definition */
> -#define SRB_FREE	0
> -#define SRB_WAIT	BIT0
> -#define SRB_READY	BIT1
> -#define SRB_MSGOUT	BIT2	/*;arbitration+msg_out 1st byte*/
> -#define SRB_MSGIN	BIT3
> -#define SRB_MSGIN_MULTI BIT4
> -#define SRB_COMMAND	BIT5
> -#define SRB_START_	BIT6	/*;arbitration+msg_out+command_out*/
> -#define SRB_DISCONNECT	BIT7
> -#define SRB_DATA_XFER	BIT8
> -#define SRB_XFERPAD	BIT9
> -#define SRB_STATUS	BIT10
> -#define SRB_COMPLETED	BIT11
> -#define SRB_ABORT_SENT	BIT12
> -#define DO_SYNC_NEGO	BIT13
> -#define SRB_UNEXPECT_RESEL BIT14
> -
> -/*;---SRBstatus */
> -#define SRB_OK		BIT0
> -#define ABORTION	BIT1
> -#define OVER_RUN	BIT2
> -#define UNDER_RUN	BIT3
> -#define PARITY_ERROR	BIT4
> -#define SRB_ERROR	BIT5
> -
> -/*;---ACBFlag */
> -#define RESET_DEV	BIT0
> -#define RESET_DETECT	BIT1
> -#define RESET_DONE	BIT2
> -
> -/*;---DCBFlag */
> -#define ABORT_DEV_	BIT0
> -
> -/*;---SRBFlag */
> -#define DATAOUT 	BIT7
> -#define DATAIN		BIT6
> -#define RESIDUAL_VALID	BIT5
> -#define ENABLE_TIMER	BIT4
> -#define RESET_DEV0	BIT2
> -#define ABORT_DEV	BIT1
> -#define AUTO_REQSENSE	BIT0
> -
> -/*;---Adapter status */
> -#define H_STATUS_GOOD	 0
> -#define H_SEL_TIMEOUT	 0x11
> -#define H_OVER_UNDER_RUN 0x12
> -#define H_UNEXP_BUS_FREE 0x13
> -#define H_TARGET_PHASE_F 0x14
> -#define H_INVALID_CCB_OP 0x16
> -#define H_LINK_CCB_BAD	 0x17
> -#define H_BAD_TARGET_DIR 0x18
> -#define H_DUPLICATE_CCB  0x19
> -#define H_BAD_CCB_OR_SG  0x1A
> -#define H_ABORT 	 0x0FF
> -
> -/* cmd->result */
> -#define RES_TARGET		0x000000FF	/* Target State */
> -#define RES_TARGET_LNX		STATUS_MASK	/* Only official ... */
> -#define RES_ENDMSG		0x0000FF00	/* End Message */
> -#define RES_DID			0x00FF0000	/* DID_ codes */
> -#define RES_DRV			0xFF000000	/* DRIVER_ codes */
> -
> -#define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
> -#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
> -
> -#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
> -#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
> -#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
> -#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
> -#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
> -
> -/*;---Sync_Mode */
> -#define SYNC_DISABLE	0
> -#define SYNC_ENABLE	BIT0
> -#define SYNC_NEGO_DONE	BIT1
> -#define WIDE_ENABLE	BIT2	/* Not used ;-) */
> -#define WIDE_NEGO_DONE	BIT3	/* Not used ;-) */
> -#define EN_TAG_QUEUEING	BIT4
> -#define EN_ATN_STOP	BIT5
> -
> -#define SYNC_NEGO_OFFSET 15
> -
> -/*;---SCSI bus phase*/
> -#define SCSI_DATA_OUT	0
> -#define SCSI_DATA_IN	1
> -#define SCSI_COMMAND	2
> -#define SCSI_STATUS_	3
> -#define SCSI_NOP0	4
> -#define SCSI_NOP1	5
> -#define SCSI_MSG_OUT	6
> -#define SCSI_MSG_IN	7
> -
> -/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
> -#define ABORT_TAG	0x0d
> -
> -/*
> - *	SISC query queue
> - */
> -typedef struct {
> -	dma_addr_t		saved_dma_handle;
> -} dc390_cmd_scp_t;
> -
> -/*
> -;==========================================================
> -; EEPROM byte offset
> -;==========================================================
> -*/
> -typedef  struct  _EEprom
> -{
> -u8	EE_MODE1;
> -u8	EE_SPEED;
> -u8	xx1;
> -u8	xx2;
> -} EEprom, *PEEprom;
> -
> -#define REAL_EE_ADAPT_SCSI_ID 64
> -#define REAL_EE_MODE2	65
> -#define REAL_EE_DELAY	66
> -#define REAL_EE_TAG_CMD_NUM	67
> -
> -#define EE_ADAPT_SCSI_ID 32
> -#define EE_MODE2	33
> -#define EE_DELAY	34
> -#define EE_TAG_CMD_NUM	35
> -
> -#define EE_LEN		40
> -
> -/*; EE_MODE1 bits definition*/
> -#define PARITY_CHK_	BIT0
> -#define SYNC_NEGO_	BIT1
> -#define EN_DISCONNECT_	BIT2
> -#define SEND_START_	BIT3
> -#define TAG_QUEUEING_	BIT4
> -
> -/*; EE_MODE2 bits definition*/
> -#define MORE2_DRV	BIT0
> -#define GREATER_1G	BIT1
> -#define RST_SCSI_BUS	BIT2
> -#define ACTIVE_NEGATION BIT3
> -#define NO_SEEK 	BIT4
> -#define LUN_CHECK	BIT5
> -
> -#define ENABLE_CE	1
> -#define DISABLE_CE	0
> -#define EEPROM_READ	0x80
> -
> -/*
> -;==========================================================
> -;	AMD 53C974 Registers bit Definition
> -;==========================================================
> -*/
> -/*
> -;====================
> -; SCSI Register
> -;====================
> -*/
> -
> -/*; Command Reg.(+0CH) (rw) */
> -#define DMA_COMMAND		BIT7
> -#define NOP_CMD 		0
> -#define CLEAR_FIFO_CMD		1
> -#define RST_DEVICE_CMD		2
> -#define RST_SCSI_BUS_CMD	3
> -
> -#define INFO_XFER_CMD		0x10
> -#define INITIATOR_CMD_CMPLTE	0x11
> -#define MSG_ACCEPTED_CMD	0x12
> -#define XFER_PAD_BYTE		0x18
> -#define SET_ATN_CMD		0x1A
> -#define RESET_ATN_CMD		0x1B
> -
> -#define SEL_WO_ATN		0x41	/* currently not used */
> -#define SEL_W_ATN		0x42
> -#define SEL_W_ATN_STOP		0x43
> -#define SEL_W_ATN3		0x46
> -#define EN_SEL_RESEL		0x44
> -#define DIS_SEL_RESEL		0x45	/* currently not used */
> -#define RESEL			0x40	/* " */
> -#define RESEL_ATN3		0x47	/* " */
> -
> -#define DATA_XFER_CMD		INFO_XFER_CMD
> -
> -
> -/*; SCSI Status Reg.(+10H) (r) */
> -#define INTERRUPT		BIT7
> -#define ILLEGAL_OP_ERR		BIT6
> -#define PARITY_ERR		BIT5
> -#define COUNT_2_ZERO		BIT4
> -#define GROUP_CODE_VALID	BIT3
> -#define SCSI_PHASE_MASK 	(BIT2+BIT1+BIT0) 
> -/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
> -
> -/*; Interrupt Status Reg.(+14H) (r) */
> -#define SCSI_RESET		BIT7
> -#define INVALID_CMD		BIT6
> -#define DISCONNECTED		BIT5
> -#define SERVICE_REQUEST 	BIT4
> -#define SUCCESSFUL_OP		BIT3
> -#define RESELECTED		BIT2
> -#define SEL_ATTENTION		BIT1
> -#define SELECTED		BIT0
> -
> -/*; Internal State Reg.(+18H) (r) */
> -#define SYNC_OFFSET_FLAG	BIT3
> -#define INTRN_STATE_MASK	(BIT2+BIT1+BIT0)
> -/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
> -
> -/*; Clock Factor Reg.(+24H) (w) */
> -#define CLK_FREQ_40MHZ		0
> -#define CLK_FREQ_35MHZ		(BIT2+BIT1+BIT0)
> -#define CLK_FREQ_30MHZ		(BIT2+BIT1)
> -#define CLK_FREQ_25MHZ		(BIT2+BIT0)
> -#define CLK_FREQ_20MHZ		BIT2
> -#define CLK_FREQ_15MHZ		(BIT1+BIT0)
> -#define CLK_FREQ_10MHZ		BIT1
> -
> -/*; Control Reg. 1(+20H) (rw) */
> -#define EXTENDED_TIMING 	BIT7
> -#define DIS_INT_ON_SCSI_RST	BIT6
> -#define PARITY_ERR_REPO 	BIT4
> -#define SCSI_ID_ON_BUS		(BIT2+BIT1+BIT0) /* host adapter ID */
> -
> -/*; Control Reg. 2(+2CH) (rw) */
> -#define EN_FEATURE		BIT6
> -#define EN_SCSI2_CMD		BIT3
> -
> -/*; Control Reg. 3(+30H) (rw) */
> -#define ID_MSG_CHECK		BIT7
> -#define EN_QTAG_MSG		BIT6
> -#define EN_GRP2_CMD		BIT5
> -#define FAST_SCSI		BIT4	/* ;10MB/SEC */
> -#define FAST_CLK		BIT3	/* ;25 - 40 MHZ */
> -
> -/*; Control Reg. 4(+34H) (rw) */
> -#define EATER_12NS		0
> -#define EATER_25NS		BIT7
> -#define EATER_35NS		BIT6
> -#define EATER_0NS		(BIT7+BIT6)
> -#define REDUCED_POWER		BIT5
> -#define CTRL4_RESERVED		BIT4	/* must be 1 acc. to AM53C974.c */
> -#define NEGATE_REQACKDATA	BIT2
> -#define NEGATE_REQACK		BIT3
> -
> -#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
> -#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
> -
> -/*
> -;====================
> -; DMA Register
> -;====================
> -*/
> -/*; DMA Command Reg.(+40H) (rw) */
> -#define READ_DIRECTION		BIT7
> -#define WRITE_DIRECTION 	0
> -#define EN_DMA_INT		BIT6
> -#define EN_PAGE_INT		BIT5	/* page transfer interrupt enable */
> -#define MAP_TO_MDL		BIT4
> -#define DIAGNOSTIC		BIT2
> -#define DMA_IDLE_CMD		0
> -#define DMA_BLAST_CMD		BIT0
> -#define DMA_ABORT_CMD		BIT1
> -#define DMA_START_CMD		(BIT1+BIT0)
> -
> -/*; DMA Status Reg.(+54H) (r) */
> -#define PCI_MS_ABORT		BIT6
> -#define BLAST_COMPLETE		BIT5
> -#define SCSI_INTERRUPT		BIT4
> -#define DMA_XFER_DONE		BIT3
> -#define DMA_XFER_ABORT		BIT2
> -#define DMA_XFER_ERROR		BIT1
> -#define POWER_DOWN		BIT0
> -
> -/*; DMA SCSI Bus and Ctrl.(+70H) */
> -#define EN_INT_ON_PCI_ABORT	BIT25
> -#define WRT_ERASE_DMA_STAT	BIT24
> -#define PW_DOWN_CTRL		BIT21
> -#define SCSI_BUSY		BIT20
> -#define SCLK			BIT19
> -#define SCAM			BIT18
> -#define SCSI_LINES		0x0003ffff
> -
> -/*
> -;==========================================================
> -; SCSI Chip register address offset
> -;==========================================================
> -;Registers are rw unless declared otherwise 
> -*/
> -#define CtcReg_Low	0x00	/* r	curr. transfer count */
> -#define CtcReg_Mid	0x04	/* r */
> -#define CtcReg_High	0x38	/* r */
> -#define ScsiFifo	0x08
> -#define ScsiCmd 	0x0C
> -#define Scsi_Status	0x10	/* r */
> -#define INT_Status	0x14	/* r */
> -#define Sync_Period	0x18	/* w */
> -#define Sync_Offset	0x1C	/* w */
> -#define Clk_Factor	0x24	/* w */
> -#define CtrlReg1	0x20	
> -#define CtrlReg2	0x2C
> -#define CtrlReg3	0x30
> -#define CtrlReg4	0x34
> -#define DMA_Cmd 	0x40
> -#define DMA_XferCnt	0x44	/* rw	starting transfer count (32 bit) */
> -#define DMA_XferAddr	0x48	/* rw	starting physical address (32 bit) */
> -#define DMA_Wk_ByteCntr 0x4C	/* r	working byte counter */
> -#define DMA_Wk_AddrCntr 0x50	/* r	working address counter */
> -#define DMA_Status	0x54	/* r */
> -#define DMA_MDL_Addr	0x58	/* rw	starting MDL address */
> -#define DMA_Wk_MDL_Cntr 0x5C	/* r	working MDL counter */
> -#define DMA_ScsiBusCtrl 0x70	/* rw	SCSI Bus, PCI/DMA Ctrl */
> -
> -#define StcReg_Low	CtcReg_Low	/* w	start transfer count */
> -#define StcReg_Mid	CtcReg_Mid	/* w */
> -#define StcReg_High	CtcReg_High	/* w */
> -#define Scsi_Dest_ID	Scsi_Status	/* w */
> -#define Scsi_TimeOut	INT_Status	/* w */
> -#define Intern_State	Sync_Period	/* r */
> -#define Current_Fifo	Sync_Offset	/* r	Curr. FIFO / int. state */
> -
> -
> -#define DC390_read8(address)			\
> -	(inb (pACB->IOPortBase + (address)))
> -
> -#define DC390_read8_(address, base)		\
> -	(inb ((u16)(base) + (address)))
> -
> -#define DC390_read16(address)			\
> -	(inw (pACB->IOPortBase + (address)))
> -
> -#define DC390_read32(address)			\
> -	(inl (pACB->IOPortBase + (address)))
> -
> -#define DC390_write8(address,value)		\
> -	outb ((value), pACB->IOPortBase + (address))
> -
> -#define DC390_write8_(address,value,base)	\
> -	outb ((value), (u16)(base) + (address))
> -
> -#define DC390_write16(address,value)		\
> -	outw ((value), pACB->IOPortBase + (address))
> -
> -#define DC390_write32(address,value)		\
> -	outl ((value), pACB->IOPortBase + (address))
> -
> -
> -#endif /* _TMSCSIM_H */
> -- 
> 1.8.5.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 12/12] Replace tmscsim by am53c974
  2014-11-23 13:22   ` Guennadi Liakhovetski
@ 2014-11-23 18:45     ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2014-11-23 18:45 UTC (permalink / raw)
  To: g.liakhovetski; +Cc: hare, jbottomley, hch, pbonzini, linux-scsi


Please do not _EVER_ quote an entire huge patch just to add a signoff
or ACK.

This wastes tons of mailing list resources because it means that
the entire huge patch is sent once again to every single recipient
on the mailing list.

Instead, just at most quote the commit message, then add your
ACK, and remove the patch from the quoted material entirely.

Thanks.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCHv2 00/12] Re-implement am53c974 driver
  2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
                   ` (11 preceding siblings ...)
  2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
@ 2014-11-24  8:14 ` Christoph Hellwig
  2014-11-24  8:23   ` Hannes Reinecke
  2014-11-25 22:10   ` Guennadi Liakhovetski
  12 siblings, 2 replies; 36+ messages in thread
From: Christoph Hellwig @ 2014-11-24  8:14 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
	Guennadi Liakhovetski, David S. Miller, linux-scsi

I'm tempted to merge this into drivers-for-3.19 ASAP, any argument against
that?  Guennadi, do you have any additional hardware to Hannes one real and one
virtual adapter to test this new driver on before?

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCHv2 00/12] Re-implement am53c974 driver
  2014-11-24  8:14 ` [PATCHv2 00/12] Re-implement am53c974 driver Christoph Hellwig
@ 2014-11-24  8:23   ` Hannes Reinecke
  2014-11-25 22:10   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-24  8:23 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: James Bottomley, Paolo Bonzini, Guennadi Liakhovetski,
	David S. Miller, linux-scsi

On 11/24/2014 09:14 AM, Christoph Hellwig wrote:
> I'm tempted to merge this into drivers-for-3.19 ASAP, any argument against
> that?  Guennadi, do you have any additional hardware to Hannes one real and one
> virtual adapter to test this new driver on before?
> 
Certainly not from me :-)

It would be nice to have it in, as then I could do some more
in-depth testing for EH async aborts and the EH rework in general.
And qemu would finally have all SCSI HBAs working again :-)

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		      zSeries & Storage
hare@suse.de			      +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
@ 2014-11-24 13:36   ` Christoph Hellwig
  2014-11-24 13:42   ` Paolo Bonzini
  2014-11-24 13:50   ` Christoph Hellwig
  2 siblings, 0 replies; 36+ messages in thread
From: Christoph Hellwig @ 2014-11-24 13:36 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
	Guennadi Liakhovetski, David S. Miller, linux-scsi

Can someone give me a review for this patch as well?  Fortuately the
driver seems incredibly simple.


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
  2014-11-24 13:36   ` Christoph Hellwig
@ 2014-11-24 13:42   ` Paolo Bonzini
  2014-11-24 13:50   ` Christoph Hellwig
  2 siblings, 0 replies; 36+ messages in thread
From: Paolo Bonzini @ 2014-11-24 13:42 UTC (permalink / raw)
  To: Hannes Reinecke, James Bottomley
  Cc: Christoph Hellwig, Guennadi Liakhovetski, David S. Miller,
	linux-scsi



On 21/11/2014 13:41, Hannes Reinecke wrote:
> This patch adds a new implementation for the Tekram DC-390T /
> AMD AM53c974 SCSI controller, based on the generic
> esp_scsi infrastructure.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/scsi/Kconfig    |  18 ++
>  drivers/scsi/Makefile   |   1 +
>  drivers/scsi/am53c974.c | 531 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 550 insertions(+)
>  create mode 100644 drivers/scsi/am53c974.c
> 
> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index 60c67e1..519c3ef 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -1357,6 +1357,24 @@ config SCSI_DC390T
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called tmscsim.
>  
> +config SCSI_AM53C974
> +	tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
> +	depends on PCI && SCSI
> +	select SCSI_SPI_ATTRS
> +	---help---
> +	  This driver supports PCI SCSI host adapters based on the Am53C974A
> +	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
> +	  PCscsi/PCnet (Am53/79C974) solutions.
> +	  This is a new implementation base on the generic esp_scsi driver.
> +
> +	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
> +
> +	  Note that this driver does NOT support Tekram DC390W/U/F, which are
> +	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called am53c974.
> +
>  config SCSI_T128
>  	tristate "Trantor T128/T128F/T228 SCSI support"
>  	depends on ISA && SCSI
> diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
> index 59f1ce6..79a6571 100644
> --- a/drivers/scsi/Makefile
> +++ b/drivers/scsi/Makefile
> @@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
>  obj-$(CONFIG_SCSI_EATA)		+= eata.o
>  obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
>  obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
> +obj-$(CONFIG_SCSI_AM53C974)	+= esp_scsi.o	am53c974.o
>  obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
>  obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
>  obj-$(CONFIG_MEGARAID_SAS)	+= megaraid/
> diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
> new file mode 100644
> index 0000000..86c4c42
> --- /dev/null
> +++ b/drivers/scsi/am53c974.c
> @@ -0,0 +1,531 @@
> +/*
> + * AMD am53c974 driver.
> + * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/pci.h>
> +#include <linux/interrupt.h>
> +
> +#include <scsi/scsi_host.h>
> +
> +#include "esp_scsi.h"
> +
> +#define DRV_MODULE_NAME "am53c974"
> +#define DRV_MODULE_VERSION "1.00"
> +
> +// #define ESP_DMA_DEBUG
> +
> +#define ESP_DMA_CMD 0x10
> +#define ESP_DMA_STC 0x11
> +#define ESP_DMA_SPA 0x12
> +#define ESP_DMA_WBC 0x13
> +#define ESP_DMA_WAC 0x14
> +#define ESP_DMA_STATUS 0x15
> +#define ESP_DMA_SMDLA 0x16
> +#define ESP_DMA_WMAC 0x17
> +
> +#define ESP_DMA_CMD_IDLE 0x00
> +#define ESP_DMA_CMD_BLAST 0x01
> +#define ESP_DMA_CMD_ABORT 0x02
> +#define ESP_DMA_CMD_START 0x03
> +#define ESP_DMA_CMD_MASK  0x03
> +#define ESP_DMA_CMD_DIAG 0x04
> +#define ESP_DMA_CMD_MDL 0x10
> +#define ESP_DMA_CMD_INTE_P 0x20
> +#define ESP_DMA_CMD_INTE_D 0x40
> +#define ESP_DMA_CMD_DIR 0x80
> +
> +#define ESP_DMA_STAT_PWDN 0x01
> +#define ESP_DMA_STAT_ERROR 0x02
> +#define ESP_DMA_STAT_ABORT 0x04
> +#define ESP_DMA_STAT_DONE 0x08
> +#define ESP_DMA_STAT_SCSIINT 0x10
> +#define ESP_DMA_STAT_BCMPLT 0x20
> +
> +/* EEPROM is accessed with 16-bit values */
> +#define DC390_EEPROM_READ 0x80
> +#define DC390_EEPROM_LEN 0x40
> +
> +/*
> + * DC390 EEPROM
> + *
> + * 8 * 4 bytes of per-device options
> + * followed by HBA specific options
> + */
> +
> +/* Per-device options */
> +#define DC390_EE_MODE1 0x00
> +#define DC390_EE_SPEED 0x01
> +
> +/* HBA-specific options */
> +#define DC390_EE_ADAPT_SCSI_ID 0x40
> +#define DC390_EE_MODE2 0x41
> +#define DC390_EE_DELAY 0x42
> +#define DC390_EE_TAG_CMD_NUM 0x43
> +
> +#define DC390_EE_MODE1_PARITY_CHK   0x01
> +#define DC390_EE_MODE1_SYNC_NEGO    0x02
> +#define DC390_EE_MODE1_EN_DISC      0x04
> +#define DC390_EE_MODE1_SEND_START   0x08
> +#define DC390_EE_MODE1_TCQ          0x10
> +
> +#define DC390_EE_MODE2_MORE_2DRV    0x01
> +#define DC390_EE_MODE2_GREATER_1G   0x02
> +#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
> +#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
> +#define DC390_EE_MODE2_NO_SEEK      0x10
> +#define DC390_EE_MODE2_LUN_CHECK    0x20
> +
> +struct pci_esp_priv {
> +	struct esp *esp;
> +	u8 dma_status;
> +};
> +
> +#define PCI_ESP_GET_PRIV(esp) ((struct pci_esp_priv *) \
> +			       pci_get_drvdata((struct pci_dev *) \
> +					       (esp)->dev))
> +
> +static void pci_esp_dma_drain(struct esp *esp);
> +
> +static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
> +{
> +	iowrite8(val, esp->regs + (reg * 4UL));
> +}
> +
> +static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
> +{
> +	return ioread8(esp->regs + (reg * 4UL));
> +}
> +
> +static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
> +{
> +	return iowrite32(val, esp->regs + (reg * 4UL));
> +}
> +
> +static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
> +				     size_t sz, int dir)
> +{
> +	return pci_map_single(esp->dev, buf, sz, dir);
> +}
> +
> +static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
> +			  int num_sg, int dir)
> +{
> +	return pci_map_sg(esp->dev, sg, num_sg, dir);
> +}
> +
> +static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
> +				 size_t sz, int dir)
> +{
> +	pci_unmap_single(esp->dev, addr, sz, dir);
> +}
> +
> +static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
> +			     int num_sg, int dir)
> +{
> +	pci_unmap_sg(esp->dev, sg, num_sg, dir);
> +}
> +
> +static int pci_esp_irq_pending(struct esp *esp)
> +{
> +	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
> +
> +	pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
> +#ifdef ESP_DMA_DEBUG
> +	if (pep->dma_status)
> +		shost_printk(KERN_INFO, esp->host, "dma intr dreg[%02x]\n",
> +			     pep->dma_status);
> +#endif
> +	if (pep->dma_status & (ESP_DMA_STAT_ERROR |
> +			       ESP_DMA_STAT_ABORT |
> +			       ESP_DMA_STAT_DONE |
> +			       ESP_DMA_STAT_SCSIINT))
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static void pci_esp_reset_dma(struct esp *esp)
> +{
> +	/* Nothing to do ? */
> +}
> +
> +static void pci_esp_dma_drain(struct esp *esp)
> +{
> +	u8 resid;
> +	int lim = 1000;
> +
> +
> +	if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
> +	    (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
> +		/* Data-In or Data-Out, nothing to be done */
> +		return;
> +
> +	while (--lim > 0) {
> +		resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
> +		if (resid <= 1)
> +			break;
> +		cpu_relax();
> +	}
> +	if (resid > 1) {
> +		/* FIFO not cleared */
> +		shost_printk(KERN_INFO, esp->host,
> +			     "FIFO not cleared, %d bytes left\n",
> +			     resid);
> +	}
> +
> +	/*
> +	 * When there is a residual BCMPLT will never be set
> +	 * (obviously). But we still have to issue the BLAST
> +	 * command, otherwise the data will not being transferred.
> +	 * But we'll never know when the BLAST operation is
> +	 * finished. So check for some time and give up eventually.
> +	 */
> +	lim = 1000;
> +	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
> +	while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
> +		if (--lim == 0)
> +			break;
> +		cpu_relax();
> +	}
> +	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
> +#ifdef ESP_DMA_DEBUG
> +	shost_printk(KERN_INFO, esp->host,
> +		     "DMA blast done (%d tries, %d bytes left)\n", lim, resid);
> +#endif
> +}
> +
> +static void pci_esp_dma_invalidate(struct esp *esp)
> +{
> +	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
> +
> +#ifdef ESP_DMA_DEBUG
> +	shost_printk(KERN_INFO, esp->host, "invalidate DMA\n");
> +#endif
> +	pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
> +	pep->dma_status = 0;
> +}
> +
> +static int pci_esp_dma_error(struct esp *esp)
> +{
> +	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
> +
> +	if (pep->dma_status & ESP_DMA_STAT_ERROR) {
> +		u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
> +
> +		if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
> +			pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
> +
> +		return 1;
> +	}
> +	if (pep->dma_status & ESP_DMA_STAT_ABORT) {
> +		pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
> +		pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
> +				 u32 dma_count, int write, u8 cmd)
> +{
> +	struct pci_esp_priv *pep = PCI_ESP_GET_PRIV(esp);
> +	u32 val = 0;
> +
> +	BUG_ON(!(cmd & ESP_CMD_DMA));
> +
> +	pep->dma_status = 0;
> +
> +	/* Set DMA engine to IDLE */
> +	if (write)
> +		/* DMA write direction logic is inverted */
> +		val |= ESP_DMA_CMD_DIR;
> +	pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
> +
> +	pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> +	pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> +
> +	pci_esp_write32(esp, esp_count, ESP_DMA_STC);
> +	pci_esp_write32(esp, addr, ESP_DMA_SPA);
> +
> +#ifdef ESP_DMA_DEBUG
> +	shost_printk(KERN_INFO, esp->host, "start dma addr[%x] count[%d:%d]\n",
> +		     addr, esp_count, dma_count);
> +#endif
> +	scsi_esp_cmd(esp, cmd);
> +	/* Send DMA Start command */
> +	pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
> +}
> +
> +static const struct esp_driver_ops pci_esp_ops = {
> +	.esp_write8	=	pci_esp_write8,
> +	.esp_read8	=	pci_esp_read8,
> +	.map_single	=	pci_esp_map_single,
> +	.map_sg		=	pci_esp_map_sg,
> +	.unmap_single	=	pci_esp_unmap_single,
> +	.unmap_sg	=	pci_esp_unmap_sg,
> +	.irq_pending	=	pci_esp_irq_pending,
> +	.reset_dma	=	pci_esp_reset_dma,
> +	.dma_drain	=	pci_esp_dma_drain,
> +	.dma_invalidate	=	pci_esp_dma_invalidate,
> +	.send_dma_cmd	=	pci_esp_send_dma_cmd,
> +	.dma_error	=	pci_esp_dma_error,
> +};
> +
> +/*
> + * Read DC-390 eeprom
> + */
> +static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
> +{
> +	u8 carryFlag = 1, j = 0x80, bval;
> +	int i;
> +
> +	for (i = 0; i < 9; i++) {
> +		if (carryFlag) {
> +			pci_write_config_byte(pdev, 0x80, 0x40);
> +			bval = 0xc0;
> +		} else
> +			bval = 0x80;
> +
> +		udelay(160);
> +		pci_write_config_byte(pdev, 0x80, bval);
> +		udelay(160);
> +		pci_write_config_byte(pdev, 0x80, 0);
> +		udelay(160);
> +
> +		carryFlag = (cmd & j) ? 1 : 0;
> +		j >>= 1;
> +	}
> +}
> +
> +static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
> +{
> +	int i;
> +	u16 wval = 0;
> +	u8 bval;
> +
> +	for (i = 0; i < 16; i++) {
> +		wval <<= 1;
> +
> +		pci_write_config_byte(pdev, 0x80, 0x80);
> +		udelay(160);
> +		pci_write_config_byte(pdev, 0x80, 0x40);
> +		udelay(160);
> +		pci_read_config_byte(pdev, 0x00, &bval);
> +
> +		if (bval == 0x22)
> +			wval |= 1;
> +	}
> +
> +	return wval;
> +}
> +
> +static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
> +{
> +	u8 cmd = DC390_EEPROM_READ, i;
> +
> +	for (i = 0; i < DC390_EEPROM_LEN; i++) {
> +		pci_write_config_byte(pdev, 0xc0, 0);
> +		udelay(160);
> +
> +		dc390_eeprom_prepare_read(pdev, cmd++);
> +		*ptr++ = dc390_eeprom_get_data(pdev);
> +
> +		pci_write_config_byte(pdev, 0x80, 0);
> +		pci_write_config_byte(pdev, 0x80, 0);
> +		udelay(160);
> +	}
> +}
> +
> +static void dc390_check_eeprom(struct esp *esp)
> +{
> +	u8 EEbuf[128];
> +	u16 *ptr = (u16 *)EEbuf, wval = 0;
> +	int i;
> +
> +	dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
> +
> +	for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
> +		wval += *ptr;
> +
> +	/* no Tekram EEprom found */
> +	if (wval != 0x1234) {
> +		struct pci_dev *pdev = esp->dev;
> +		dev_printk(KERN_INFO, &pdev->dev,
> +			   "No valid Tekram EEprom found\n");
> +		return;
> +	}
> +	esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
> +	esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
> +}
> +
> +static int pci_esp_probe_one(struct pci_dev *pdev,
> +			      const struct pci_device_id *id)
> +{
> +	struct scsi_host_template *hostt = &scsi_esp_template;
> +	int err = -ENODEV;
> +	struct Scsi_Host *shost;
> +	struct esp *esp;
> +	struct pci_esp_priv *pep;
> +
> +	if (pci_enable_device(pdev)) {
> +		dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
> +		return -ENODEV;
> +	}
> +
> +	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
> +		dev_printk(KERN_INFO, &pdev->dev,
> +			   "failed to set 32bit DMA mask\n");
> +		goto fail_disable_device;
> +	}
> +
> +	shost = scsi_host_alloc(hostt, sizeof(struct esp));
> +	if (!shost) {
> +		dev_printk(KERN_INFO, &pdev->dev,
> +			   "failed to allocate scsi host\n");
> +		err = -ENOMEM;
> +		goto fail_disable_device;
> +	}
> +
> +	pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
> +	if (!pep) {
> +		dev_printk(KERN_INFO, &pdev->dev,
> +			   "failed to allocate esp_priv\n");
> +		err = -ENOMEM;
> +		goto fail_host_alloc;
> +	}
> +
> +	esp = shost_priv(shost);
> +	esp->host = shost;
> +	esp->dev = pdev;
> +	esp->ops = &pci_esp_ops;
> +	/*
> +	 * The am53c974 HBA has a design flaw of generating
> +	 * spurious DMA completion interrupts when using
> +	 * DMA for command submission.
> +	 */
> +	esp->flags |= ESP_FLAG_USE_FIFO;
> +	pep->esp = esp;
> +
> +	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
> +		dev_printk(KERN_ERR, &pdev->dev,
> +			   "pci memory selection failed\n");
> +		goto fail_priv_alloc;
> +	}
> +
> +	esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
> +	if (!esp->regs) {
> +		dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
> +		goto fail_release_regions;
> +	}
> +	esp->dma_regs = esp->regs;
> +
> +	pci_set_master(pdev);
> +
> +	esp->command_block = pci_alloc_consistent(pdev, 16,
> +						  &esp->command_block_dma);
> +	if (!esp->command_block) {
> +		dev_printk(KERN_ERR, &pdev->dev,
> +			   "failed to allocate command block\n");
> +		err = -ENOMEM;
> +		goto fail_unmap_regs;
> +	}
> +
> +	if (request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
> +			DRV_MODULE_NAME, esp)) {
> +		dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
> +		goto fail_unmap_command_block;
> +	}
> +
> +	esp->scsi_id = 7;
> +	dc390_check_eeprom(esp);
> +
> +	shost->this_id = esp->scsi_id;
> +	shost->max_id = 8;
> +	shost->irq = pdev->irq;
> +	shost->io_port = pci_resource_start(pdev, 0);
> +	shost->n_io_port = pci_resource_len(pdev, 0);
> +	shost->unique_id = shost->io_port;
> +	esp->scsi_id_mask = (1 << esp->scsi_id);
> +	/* Assume 40MHz clock */
> +	esp->cfreq = 40000000;
> +
> +	pci_set_drvdata(pdev, pep);
> +
> +	err = scsi_esp_register(esp, &pdev->dev);
> +	if (err)
> +		goto fail_free_irq;
> +
> +	return 0;
> +
> +fail_free_irq:
> +	free_irq(pdev->irq, esp);
> +fail_unmap_command_block:
> +	pci_free_consistent(pdev, 16, esp->command_block,
> +			    esp->command_block_dma);
> +fail_unmap_regs:
> +	pci_iounmap(pdev, esp->regs);
> +fail_release_regions:
> +	pci_release_regions(pdev);
> +fail_priv_alloc:
> +	kfree(pep);
> +fail_host_alloc:
> +	scsi_host_put(shost);
> +fail_disable_device:
> +	pci_disable_device(pdev);
> +
> +	return err;
> +}
> +
> +static void pci_esp_remove_one(struct pci_dev *pdev)
> +{
> +	struct pci_esp_priv *pep = pci_get_drvdata(pdev);
> +	struct esp *esp = pep->esp;
> +
> +	scsi_esp_unregister(esp);
> +	free_irq(pdev->irq, esp);
> +	pci_free_consistent(pdev, 16, esp->command_block,
> +			    esp->command_block_dma);
> +	pci_iounmap(pdev, esp->regs);
> +	pci_release_regions(pdev);
> +	pci_disable_device(pdev);
> +	kfree(pep);
> +
> +	scsi_host_put(esp->host);
> +}
> +
> +static struct pci_device_id am53c974_pci_tbl[] = {
> +	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
> +		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
> +
> +static struct pci_driver am53c974_driver = {
> +	.name           = DRV_MODULE_NAME,
> +	.id_table       = am53c974_pci_tbl,
> +	.probe          = pci_esp_probe_one,
> +	.remove         = pci_esp_remove_one,
> +};
> +
> +static int __init am53c974_module_init(void)
> +{
> +	return pci_register_driver(&am53c974_driver);
> +}
> +
> +static void __exit am53c974_module_exit(void)
> +{
> +	pci_unregister_driver(&am53c974_driver);
> +}
> +
> +MODULE_DESCRIPTION("AM53C974 SCSI driver");
> +MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(DRV_MODULE_VERSION);
> +
> +module_init(am53c974_module_init);
> +module_exit(am53c974_module_exit);
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
  2014-11-24 13:36   ` Christoph Hellwig
  2014-11-24 13:42   ` Paolo Bonzini
@ 2014-11-24 13:50   ` Christoph Hellwig
  2014-11-24 14:01     ` Hannes Reinecke
  2 siblings, 1 reply; 36+ messages in thread
From: Christoph Hellwig @ 2014-11-24 13:50 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
	Guennadi Liakhovetski, David S. Miller, linux-scsi

> +/*
> + * AMD am53c974 driver.
> + * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
> + */

Is there anything left from the old driver that should get credit here?

> +#define PCI_ESP_GET_PRIV(esp) ((struct pci_esp_priv *) \
> +			       pci_get_drvdata((struct pci_dev *) \
> +					       (esp)->dev))

I think an inline function would be a lot cleaner, especially as that
should avoid all these casts.

> +#ifdef ESP_DMA_DEBUG
> +	shost_printk(KERN_INFO, esp->host, "start dma addr[%x] count[%d:%d]\n",
> +		     addr, esp_count, dma_count);
> +#endif

Can you add a esp_dma_printk or similar instead of all these ifdefs?

> +	u8 carryFlag = 1, j = 0x80, bval;

carry_flag.

> +	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {

> +	if (request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
> +			DRV_MODULE_NAME, esp)) {

Please propagate the return values from these two.


Otherwise looks good.  Please resend with fixes for these and Dave's
style comment, and I'll apply it.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-24 13:50   ` Christoph Hellwig
@ 2014-11-24 14:01     ` Hannes Reinecke
  0 siblings, 0 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:01 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
	Guennadi Liakhovetski, David S. Miller, linux-scsi

On 11/24/2014 02:50 PM, Christoph Hellwig wrote:
>> +/*
>> + * AMD am53c974 driver.
>> + * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
>> + */
> 
> Is there anything left from the old driver that should get credit here?
> 
Hmm. I copied the EEprom handling more-or-less verbatim from the
tmscsim driver; not sure if that warrants a credit.

>> +#define PCI_ESP_GET_PRIV(esp) ((struct pci_esp_priv *) \
>> +			       pci_get_drvdata((struct pci_dev *) \
>> +					       (esp)->dev))
> 
> I think an inline function would be a lot cleaner, especially as that
> should avoid all these casts.
> 
Ok.

>> +#ifdef ESP_DMA_DEBUG
>> +	shost_printk(KERN_INFO, esp->host, "start dma addr[%x] count[%d:%d]\n",
>> +		     addr, esp_count, dma_count);
>> +#endif
> 
> Can you add a esp_dma_printk or similar instead of all these ifdefs?
> 
Yep, I can.

>> +	u8 carryFlag = 1, j = 0x80, bval;
> 
> carry_flag.
> 
As said, copied verbatim. Will be fixing it up.

>> +	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
> 
>> +	if (request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
>> +			DRV_MODULE_NAME, esp)) {
> 
> Please propagate the return values from these two.
> 
Ok.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		      zSeries & Storage
hare@suse.de			      +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 07/12] scsi: add 'am53c974' driver
  2014-11-24 14:37 [PATCHv3 " Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
  0 siblings, 0 replies; 36+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
  To: James Bottomley
  Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
	David S. Miller, linux-scsi, Hannes Reinecke

This patch adds a new implementation for the Tekram DC-390T /
AMD AM53c974 SCSI controller, based on the generic
esp_scsi infrastructure.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/Kconfig    |  18 ++
 drivers/scsi/Makefile   |   1 +
 drivers/scsi/am53c974.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 556 insertions(+)
 create mode 100644 drivers/scsi/am53c974.c

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 60c67e1..519c3ef 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1357,6 +1357,24 @@ config SCSI_DC390T
 	  To compile this driver as a module, choose M here: the
 	  module will be called tmscsim.
 
+config SCSI_AM53C974
+	tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
+	depends on PCI && SCSI
+	select SCSI_SPI_ATTRS
+	---help---
+	  This driver supports PCI SCSI host adapters based on the Am53C974A
+	  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
+	  PCscsi/PCnet (Am53/79C974) solutions.
+	  This is a new implementation base on the generic esp_scsi driver.
+
+	  Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
+
+	  Note that this driver does NOT support Tekram DC390W/U/F, which are
+	  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called am53c974.
+
 config SCSI_T128
 	tristate "Trantor T128/T128F/T228 SCSI support"
 	depends on ISA && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 59f1ce6..79a6571 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
 obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
+obj-$(CONFIG_SCSI_AM53C974)	+= esp_scsi.o	am53c974.o
 obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
 obj-$(CONFIG_MEGARAID_SAS)	+= megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
new file mode 100644
index 0000000..a16c9cf
--- /dev/null
+++ b/drivers/scsi/am53c974.c
@@ -0,0 +1,537 @@
+/*
+ * AMD am53c974 driver.
+ * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME "am53c974"
+#define DRV_MODULE_VERSION "1.00"
+
+static bool am53c974_debug;
+
+#define esp_dma_log(f, a...)						\
+	do {								\
+		if (am53c974_debug)					\
+			shost_printk(KERN_DEBUG, esp->host, f, ##a);	\
+	} while (0)
+
+#define ESP_DMA_CMD 0x10
+#define ESP_DMA_STC 0x11
+#define ESP_DMA_SPA 0x12
+#define ESP_DMA_WBC 0x13
+#define ESP_DMA_WAC 0x14
+#define ESP_DMA_STATUS 0x15
+#define ESP_DMA_SMDLA 0x16
+#define ESP_DMA_WMAC 0x17
+
+#define ESP_DMA_CMD_IDLE 0x00
+#define ESP_DMA_CMD_BLAST 0x01
+#define ESP_DMA_CMD_ABORT 0x02
+#define ESP_DMA_CMD_START 0x03
+#define ESP_DMA_CMD_MASK  0x03
+#define ESP_DMA_CMD_DIAG 0x04
+#define ESP_DMA_CMD_MDL 0x10
+#define ESP_DMA_CMD_INTE_P 0x20
+#define ESP_DMA_CMD_INTE_D 0x40
+#define ESP_DMA_CMD_DIR 0x80
+
+#define ESP_DMA_STAT_PWDN 0x01
+#define ESP_DMA_STAT_ERROR 0x02
+#define ESP_DMA_STAT_ABORT 0x04
+#define ESP_DMA_STAT_DONE 0x08
+#define ESP_DMA_STAT_SCSIINT 0x10
+#define ESP_DMA_STAT_BCMPLT 0x20
+
+/* EEPROM is accessed with 16-bit values */
+#define DC390_EEPROM_READ 0x80
+#define DC390_EEPROM_LEN 0x40
+
+/*
+ * DC390 EEPROM
+ *
+ * 8 * 4 bytes of per-device options
+ * followed by HBA specific options
+ */
+
+/* Per-device options */
+#define DC390_EE_MODE1 0x00
+#define DC390_EE_SPEED 0x01
+
+/* HBA-specific options */
+#define DC390_EE_ADAPT_SCSI_ID 0x40
+#define DC390_EE_MODE2 0x41
+#define DC390_EE_DELAY 0x42
+#define DC390_EE_TAG_CMD_NUM 0x43
+
+#define DC390_EE_MODE1_PARITY_CHK   0x01
+#define DC390_EE_MODE1_SYNC_NEGO    0x02
+#define DC390_EE_MODE1_EN_DISC      0x04
+#define DC390_EE_MODE1_SEND_START   0x08
+#define DC390_EE_MODE1_TCQ          0x10
+
+#define DC390_EE_MODE2_MORE_2DRV    0x01
+#define DC390_EE_MODE2_GREATER_1G   0x02
+#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
+#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
+#define DC390_EE_MODE2_NO_SEEK      0x10
+#define DC390_EE_MODE2_LUN_CHECK    0x20
+
+struct pci_esp_priv {
+	struct esp *esp;
+	u8 dma_status;
+};
+
+static void pci_esp_dma_drain(struct esp *esp);
+
+static inline struct pci_esp_priv *pci_esp_get_priv(struct esp *esp)
+{
+	struct pci_dev *pdev = esp->dev;
+
+	return pci_get_drvdata(pdev);
+}
+
+static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+	iowrite8(val, esp->regs + (reg * 4UL));
+}
+
+static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
+{
+	return ioread8(esp->regs + (reg * 4UL));
+}
+
+static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
+{
+	return iowrite32(val, esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
+				     size_t sz, int dir)
+{
+	return pci_map_single(esp->dev, buf, sz, dir);
+}
+
+static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+			  int num_sg, int dir)
+{
+	return pci_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+				 size_t sz, int dir)
+{
+	pci_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+			     int num_sg, int dir)
+{
+	pci_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int pci_esp_irq_pending(struct esp *esp)
+{
+	struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+	pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
+	esp_dma_log("dma intr dreg[%02x]\n", pep->dma_status);
+
+	if (pep->dma_status & (ESP_DMA_STAT_ERROR |
+			       ESP_DMA_STAT_ABORT |
+			       ESP_DMA_STAT_DONE |
+			       ESP_DMA_STAT_SCSIINT))
+		return 1;
+
+	return 0;
+}
+
+static void pci_esp_reset_dma(struct esp *esp)
+{
+	/* Nothing to do ? */
+}
+
+static void pci_esp_dma_drain(struct esp *esp)
+{
+	u8 resid;
+	int lim = 1000;
+
+
+	if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
+	    (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
+		/* Data-In or Data-Out, nothing to be done */
+		return;
+
+	while (--lim > 0) {
+		resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
+		if (resid <= 1)
+			break;
+		cpu_relax();
+	}
+	if (resid > 1) {
+		/* FIFO not cleared */
+		shost_printk(KERN_INFO, esp->host,
+			     "FIFO not cleared, %d bytes left\n",
+			     resid);
+	}
+
+	/*
+	 * When there is a residual BCMPLT will never be set
+	 * (obviously). But we still have to issue the BLAST
+	 * command, otherwise the data will not being transferred.
+	 * But we'll never know when the BLAST operation is
+	 * finished. So check for some time and give up eventually.
+	 */
+	lim = 1000;
+	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
+	while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
+		if (--lim == 0)
+			break;
+		cpu_relax();
+	}
+	pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+	esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+}
+
+static void pci_esp_dma_invalidate(struct esp *esp)
+{
+	struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+	esp_dma_log("invalidate DMA\n");
+
+	pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+	pep->dma_status = 0;
+}
+
+static int pci_esp_dma_error(struct esp *esp)
+{
+	struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+	if (pep->dma_status & ESP_DMA_STAT_ERROR) {
+		u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
+
+		if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
+			pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
+
+		return 1;
+	}
+	if (pep->dma_status & ESP_DMA_STAT_ABORT) {
+		pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+		pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
+		return 1;
+	}
+	return 0;
+}
+
+static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+				 u32 dma_count, int write, u8 cmd)
+{
+	struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+	u32 val = 0;
+
+	BUG_ON(!(cmd & ESP_CMD_DMA));
+
+	pep->dma_status = 0;
+
+	/* Set DMA engine to IDLE */
+	if (write)
+		/* DMA write direction logic is inverted */
+		val |= ESP_DMA_CMD_DIR;
+	pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
+
+	pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+	pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+
+	pci_esp_write32(esp, esp_count, ESP_DMA_STC);
+	pci_esp_write32(esp, addr, ESP_DMA_SPA);
+
+	esp_dma_log("start dma addr[%x] count[%d:%d]\n",
+		    addr, esp_count, dma_count);
+
+	scsi_esp_cmd(esp, cmd);
+	/* Send DMA Start command */
+	pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
+}
+
+static const struct esp_driver_ops pci_esp_ops = {
+	.esp_write8	=	pci_esp_write8,
+	.esp_read8	=	pci_esp_read8,
+	.map_single	=	pci_esp_map_single,
+	.map_sg		=	pci_esp_map_sg,
+	.unmap_single	=	pci_esp_unmap_single,
+	.unmap_sg	=	pci_esp_unmap_sg,
+	.irq_pending	=	pci_esp_irq_pending,
+	.reset_dma	=	pci_esp_reset_dma,
+	.dma_drain	=	pci_esp_dma_drain,
+	.dma_invalidate	=	pci_esp_dma_invalidate,
+	.send_dma_cmd	=	pci_esp_send_dma_cmd,
+	.dma_error	=	pci_esp_dma_error,
+};
+
+/*
+ * Read DC-390 eeprom
+ */
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+{
+	u8 carry_flag = 1, j = 0x80, bval;
+	int i;
+
+	for (i = 0; i < 9; i++) {
+		if (carry_flag) {
+			pci_write_config_byte(pdev, 0x80, 0x40);
+			bval = 0xc0;
+		} else
+			bval = 0x80;
+
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, bval);
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, 0);
+		udelay(160);
+
+		carry_flag = (cmd & j) ? 1 : 0;
+		j >>= 1;
+	}
+}
+
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
+{
+	int i;
+	u16 wval = 0;
+	u8 bval;
+
+	for (i = 0; i < 16; i++) {
+		wval <<= 1;
+
+		pci_write_config_byte(pdev, 0x80, 0x80);
+		udelay(160);
+		pci_write_config_byte(pdev, 0x80, 0x40);
+		udelay(160);
+		pci_read_config_byte(pdev, 0x00, &bval);
+
+		if (bval == 0x22)
+			wval |= 1;
+	}
+
+	return wval;
+}
+
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+{
+	u8 cmd = DC390_EEPROM_READ, i;
+
+	for (i = 0; i < DC390_EEPROM_LEN; i++) {
+		pci_write_config_byte(pdev, 0xc0, 0);
+		udelay(160);
+
+		dc390_eeprom_prepare_read(pdev, cmd++);
+		*ptr++ = dc390_eeprom_get_data(pdev);
+
+		pci_write_config_byte(pdev, 0x80, 0);
+		pci_write_config_byte(pdev, 0x80, 0);
+		udelay(160);
+	}
+}
+
+static void dc390_check_eeprom(struct esp *esp)
+{
+	u8 EEbuf[128];
+	u16 *ptr = (u16 *)EEbuf, wval = 0;
+	int i;
+
+	dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
+
+	for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
+		wval += *ptr;
+
+	/* no Tekram EEprom found */
+	if (wval != 0x1234) {
+		struct pci_dev *pdev = esp->dev;
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "No valid Tekram EEprom found\n");
+		return;
+	}
+	esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
+	esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+}
+
+static int pci_esp_probe_one(struct pci_dev *pdev,
+			      const struct pci_device_id *id)
+{
+	struct scsi_host_template *hostt = &scsi_esp_template;
+	int err = -ENODEV;
+	struct Scsi_Host *shost;
+	struct esp *esp;
+	struct pci_esp_priv *pep;
+
+	if (pci_enable_device(pdev)) {
+		dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
+		return -ENODEV;
+	}
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to set 32bit DMA mask\n");
+		goto fail_disable_device;
+	}
+
+	shost = scsi_host_alloc(hostt, sizeof(struct esp));
+	if (!shost) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to allocate scsi host\n");
+		err = -ENOMEM;
+		goto fail_disable_device;
+	}
+
+	pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
+	if (!pep) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "failed to allocate esp_priv\n");
+		err = -ENOMEM;
+		goto fail_host_alloc;
+	}
+
+	esp = shost_priv(shost);
+	esp->host = shost;
+	esp->dev = pdev;
+	esp->ops = &pci_esp_ops;
+	/*
+	 * The am53c974 HBA has a design flaw of generating
+	 * spurious DMA completion interrupts when using
+	 * DMA for command submission.
+	 */
+	esp->flags |= ESP_FLAG_USE_FIFO;
+	pep->esp = esp;
+
+	if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "pci memory selection failed\n");
+		goto fail_priv_alloc;
+	}
+
+	esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+	if (!esp->regs) {
+		dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
+		err = -EINVAL;
+		goto fail_release_regions;
+	}
+	esp->dma_regs = esp->regs;
+
+	pci_set_master(pdev);
+
+	esp->command_block = pci_alloc_consistent(pdev, 16,
+						  &esp->command_block_dma);
+	if (!esp->command_block) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "failed to allocate command block\n");
+		err = -ENOMEM;
+		goto fail_unmap_regs;
+	}
+
+	err = request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
+			  DRV_MODULE_NAME, esp);
+	if (err < 0) {
+		dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
+		goto fail_unmap_command_block;
+	}
+
+	esp->scsi_id = 7;
+	dc390_check_eeprom(esp);
+
+	shost->this_id = esp->scsi_id;
+	shost->max_id = 8;
+	shost->irq = pdev->irq;
+	shost->io_port = pci_resource_start(pdev, 0);
+	shost->n_io_port = pci_resource_len(pdev, 0);
+	shost->unique_id = shost->io_port;
+	esp->scsi_id_mask = (1 << esp->scsi_id);
+	/* Assume 40MHz clock */
+	esp->cfreq = 40000000;
+
+	pci_set_drvdata(pdev, pep);
+
+	err = scsi_esp_register(esp, &pdev->dev);
+	if (err)
+		goto fail_free_irq;
+
+	return 0;
+
+fail_free_irq:
+	free_irq(pdev->irq, esp);
+fail_unmap_command_block:
+	pci_free_consistent(pdev, 16, esp->command_block,
+			    esp->command_block_dma);
+fail_unmap_regs:
+	pci_iounmap(pdev, esp->regs);
+fail_release_regions:
+	pci_release_regions(pdev);
+fail_priv_alloc:
+	kfree(pep);
+fail_host_alloc:
+	scsi_host_put(shost);
+fail_disable_device:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void pci_esp_remove_one(struct pci_dev *pdev)
+{
+	struct pci_esp_priv *pep = pci_get_drvdata(pdev);
+	struct esp *esp = pep->esp;
+
+	scsi_esp_unregister(esp);
+	free_irq(pdev->irq, esp);
+	pci_free_consistent(pdev, 16, esp->command_block,
+			    esp->command_block_dma);
+	pci_iounmap(pdev, esp->regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(pep);
+
+	scsi_host_put(esp->host);
+}
+
+static struct pci_device_id am53c974_pci_tbl[] = {
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
+
+static struct pci_driver am53c974_driver = {
+	.name           = DRV_MODULE_NAME,
+	.id_table       = am53c974_pci_tbl,
+	.probe          = pci_esp_probe_one,
+	.remove         = pci_esp_remove_one,
+};
+
+static int __init am53c974_module_init(void)
+{
+	return pci_register_driver(&am53c974_driver);
+}
+
+static void __exit am53c974_module_exit(void)
+{
+	pci_unregister_driver(&am53c974_driver);
+}
+
+MODULE_DESCRIPTION("AM53C974 SCSI driver");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+module_param(am53c974_debug, bool, 0644);
+MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
+
+module_init(am53c974_module_init);
+module_exit(am53c974_module_exit);
-- 
1.8.5.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCHv2 00/12] Re-implement am53c974 driver
  2014-11-24  8:14 ` [PATCHv2 00/12] Re-implement am53c974 driver Christoph Hellwig
  2014-11-24  8:23   ` Hannes Reinecke
@ 2014-11-25 22:10   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 36+ messages in thread
From: Guennadi Liakhovetski @ 2014-11-25 22:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Hannes Reinecke, James Bottomley, Paolo Bonzini, David S. Miller,
	linux-scsi

Hi Christoph,

On Mon, 24 Nov 2014, Christoph Hellwig wrote:

> I'm tempted to merge this into drivers-for-3.19 ASAP, any argument against
> that?  Guennadi, do you have any additional hardware to Hannes one real and one
> virtual adapter to test this new driver on before?

I've got a similar / identical Tekram dc390 SCSI PCI card and a PC with an 
on-board am53c974 chip, but that is either a rather old (2 x PII @ 400MHz 
:)) or a very old (P @ 166MHz) PC of mine, don't think testing on any of 
those would be viable, even if I dig them out from the basement :) More 
interesting would be testing with different devices like tape streamers, 
scanners... But I'm really unsure anyone still uses those, even when I was 
fixing them, I was pretty much the only affected user :)

Thanks
Guennadi


^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2014-11-25 22:10 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-21 12:41 [PATCHv2 00/12] Re-implement am53c974 driver Hannes Reinecke
2014-11-21 12:41 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
2014-11-21 17:42   ` David Miller
2014-11-21 12:41 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
2014-11-21 17:42   ` David Miller
2014-11-21 12:41 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
2014-11-21 17:43   ` David Miller
2014-11-21 12:41 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
2014-11-21 17:43   ` David Miller
2014-11-21 12:41 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
2014-11-21 17:44   ` David Miller
2014-11-21 12:41 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
2014-11-21 13:09   ` Paolo Bonzini
2014-11-21 17:42   ` David Miller
2014-11-21 12:41 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
2014-11-24 13:36   ` Christoph Hellwig
2014-11-24 13:42   ` Paolo Bonzini
2014-11-24 13:50   ` Christoph Hellwig
2014-11-24 14:01     ` Hannes Reinecke
2014-11-21 12:41 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
2014-11-21 13:09   ` Paolo Bonzini
2014-11-21 17:45   ` David Miller
2014-11-21 12:41 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
2014-11-21 17:46   ` David Miller
2014-11-21 12:41 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
2014-11-21 17:47   ` David Miller
2014-11-21 12:41 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
2014-11-21 13:10   ` Paolo Bonzini
2014-11-21 17:47   ` David Miller
2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
2014-11-23 13:22   ` Guennadi Liakhovetski
2014-11-23 18:45     ` David Miller
2014-11-24  8:14 ` [PATCHv2 00/12] Re-implement am53c974 driver Christoph Hellwig
2014-11-24  8:23   ` Hannes Reinecke
2014-11-25 22:10   ` Guennadi Liakhovetski
  -- strict thread matches above, loose matches on Subject: below --
2014-11-24 14:37 [PATCHv3 " Hannes Reinecke
2014-11-24 14:37 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).