patch-1.3.60 linux/drivers/scsi/NCR5380.c

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

diff -u --recursive --new-file v1.3.59/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
@@ -1,4 +1,6 @@
-#define NDEBUG (NDEBUG_RESTART_SELECT)
+#ifndef NDEBUG
+#define NDEBUG (NDEBUG_RESTART_SELECT | NDEBUG_ABORT)
+#endif
 /* 
  * NCR 5380 generic driver routines.  These should make it *trivial*
  * 	to implement 5380 SCSI drivers under Linux with a non-trantor
@@ -66,6 +68,14 @@
  *      the high level code.
  */
 
+#if (NDEBUG & NDEBUG_LISTS)
+#define LIST(x,y) {printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }
+#define REMOVE(w,x,y,z) {printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }
+#else
+#define LIST(x,y)
+#define REMOVE(w,x,y,z)
+#endif
+
 #ifndef notyet
 #undef LINKED
 #undef USLEEP
@@ -284,6 +294,8 @@
  * code finishes, NCR5380_print_options should be called.
  */
 
+static int do_abort (struct Scsi_Host *host);
+static void do_reset (struct Scsi_Host *host);
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *the_template = NULL;
 
@@ -354,18 +366,22 @@
     icr = NCR5380_read(INITIATOR_COMMAND_REG);
     basr = NCR5380_read(BUS_AND_STATUS_REG);
     sti();
+    printk("STATUS_REG: %02x ", status);
     for (i = 0; signals[i].mask ; ++i) 
 	if (status & signals[i].mask)
-	    printk(" %s", signals[i].name);
+	    printk(",%s", signals[i].name);
+    printk("\nBASR: %02x ", basr);
     for (i = 0; basrs[i].mask ; ++i) 
 	if (basr & basrs[i].mask)
-	    printk(" %s", basrs[i].name);
+	    printk(",%s", basrs[i].name);
+    printk("\nICR: %02x ", icr);
     for (i = 0; icrs[i].mask; ++i) 
 	if (icr & icrs[i].mask)
-	    printk(" %s", icrs[i].name);
+	    printk(",%s", icrs[i].name);
+    printk("\nMODE: %02x ", mr);
     for (i = 0; mrs[i].mask; ++i) 
 	if (mr & mrs[i].mask)
-	    printk(" %s", mrs[i].name);
+	    printk(",%s", mrs[i].name);
     printk("\n");
 }
 
@@ -693,11 +709,9 @@
     printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
 #endif
     printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
-#ifdef NCR53C400
-    if (hostdata->flags & FLAG_NCR53C400) {
+    if (((struct NCR5380_hostdata *)instance->hostdata)->flags & FLAG_NCR53C400) {
 	printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
     }
-#endif
 }
 
 /*
@@ -762,7 +776,8 @@
 
 static void NCR5380_init (struct Scsi_Host *instance, int flags) {
     NCR5380_local_declare();
-    int i;
+    int i, pass;
+    unsigned long timeout;
     struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) 
 	instance->hostdata;
 
@@ -772,7 +787,7 @@
      */
 
     if (flags & FLAG_NCR53C400)
-	instance->io_port += 8;
+	instance->NCR5380_instance_name += NCR53C400_address_adjust;
 
     NCR5380_setup(instance);
 
@@ -792,7 +807,12 @@
     hostdata->connected = NULL;
     hostdata->issue_queue = NULL;
     hostdata->disconnected_queue = NULL;
-    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
+
+    /* The CHECK code seems to break the 53C400. Will check it later maybe */
+    if (flags & FLAG_NCR53C400)
+	hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;
+    else
+	hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
 
     if (!the_template) {
 	the_template = instance->hostt;
@@ -816,11 +836,49 @@
     NCR5380_write(MODE_REG, MR_BASE);
     NCR5380_write(TARGET_COMMAND_REG, 0);
     NCR5380_write(SELECT_ENABLE_REG, 0);
-#ifdef NCR53C400
+
     if (hostdata->flags & FLAG_NCR53C400) {
 	NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
     }
-#endif
+
+    /* 
+     * Detect and correct bus wedge problems.
+     *
+     * If the system crashed, it may have crashed in a state 
+     * where a SCSI command was still executing, and the 
+     * SCSI bus is not in a BUS FREE STATE.
+     *
+     * If this is the case, we'll try to abort the currently
+     * established nexus which we know nothing about, and that
+     * failing, do a hard reset of the SCSI bus 
+     */
+
+    for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) &&
+	  pass <= 6 ; ++pass) {
+	switch (pass) {
+	case 1:
+	case 3:
+	case 5:
+	    printk("scsi%d: SCSI bus busy, waiting up to five seconds\n",
+		instance->host_no);
+	    timeout = jiffies + 500;
+	    while (jiffies < timeout && (NCR5380_read(STATUS_REG) & SR_BSY));
+	    break;
+	case 2:
+	    printk("scsi%d: bus busy, attempting abort\n",
+		instance->host_no);
+	    do_abort (instance);
+	    break;
+	case 4:
+	    printk("scsi%d: bus busy, attempting reset\n",
+		instance->host_no);
+	    do_reset (instance);
+	    break;
+	case 6:
+	    printk("scsi%d: bus locked solid or invalid override\n",
+		instance->host_no);
+	}
+    }
 }
 
 /* 
@@ -846,8 +904,9 @@
 static
 #endif
 int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) {
+    struct Scsi_Host *instance = cmd->host;
     struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	cmd->host->hostdata;
+	instance->hostdata;
     Scsi_Cmnd *tmp;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
@@ -883,11 +942,13 @@
 
     cli();
     if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+	LIST(cmd, hostdata->issue_queue);
 	cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
 	hostdata->issue_queue = cmd;
     } else {
 	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; 
 		tmp = (Scsi_Cmnd *) tmp->host_scribble);
+	LIST(cmd, tmp);
 	tmp->host_scribble = (unsigned char *) cmd;
     }
 #if (NDEBUG & NDEBUG_QUEUES)
@@ -945,16 +1006,29 @@
 		 * Search through the issue_queue for a command destined
 		 * for a target that's not busy.
 		 */
+#if (NDEBUG & NDEBUG_LISTS)
+		for (tmp= (Scsi_Cmnd *) hostdata->issue_queue, prev=NULL; tmp && (tmp != prev); prev=tmp, tmp=(Scsi_Cmnd*)tmp->host_scribble)
+		    ;
+		    /*printk("%p  ", tmp);*/
+		if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
+#endif
 		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
 		    prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
-		    tmp->host_scribble) 
+		    tmp->host_scribble) {
 
+#if (NDEBUG & NDEBUG_LISTS)
+		    if (prev != tmp)
+			printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);
+#endif
 		    /*  When we find one, remove it from the issue queue. */
 		    if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
-			    if (prev)
-				prev->host_scribble = tmp->host_scribble;
-			    else
-				hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
+			if (prev) {
+			    REMOVE(prev,prev->host_scribble,tmp,tmp->host_scribble);
+			    prev->host_scribble = tmp->host_scribble;
+			} else {
+			    REMOVE(-1,hostdata->issue_queue,tmp,tmp->host_scribble);
+			    hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
+			}
 			tmp->host_scribble = NULL;
 
 			/* reenable interrupts after finding one */
@@ -970,22 +1044,35 @@
 			printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n",
 			    instance->host_no, tmp->target, tmp->lun);
 #endif
+    		
+			/*
+			 * A successful selection is defined as one that 
+			 * leaves us with the command connected and 
+			 * in hostdata->connected, OR has terminated the
+			 * command.
+			 *
+			 * With successfull commands, we fall through
+			 * and see if we can do an information transfer,
+			 * with failures we will restart.
+			 */
+
+			if (!NCR5380_select(instance, tmp, 
     			/* 
     			 * REQUEST SENSE commands are issued without tagged
     			 * queueing, even on SCSI-II devices because the 
     			 * contingent allegiance condition exists for the 
     			 * entire unit.
     			 */
-    			
-			if (!NCR5380_select(instance, tmp, 
 			    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 
 			    TAG_NEXT)) {
 			    break;
 			} else {
 			    cli();
+			    LIST(tmp, hostdata->issue_queue);
 			    tmp->host_scribble = (unsigned char *) 
 				hostdata->issue_queue;
 			    hostdata->issue_queue = tmp;
+			    done = 0;
 			    sti();
 #if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
 			printk("scsi%d : main(): select() failed, returned to issue_queue\n",
@@ -993,6 +1080,7 @@
 #endif
 			}
 		    } /* if target/lun is not busy */
+		} /* for */
 	    } /* if (!hostdata->connected) */
 		
 	    if (hostdata->connected 
@@ -1108,7 +1196,8 @@
 				     && jiffies < timeout)
 				;
 			      if (jiffies >= timeout)
-				printk("scsi: timeout at %d\n", __LINE__);
+			        printk("scsi%d: timeout at NCR5380.c:%d\n", 
+				    host->host_no, __LINE__);
 			    }
 #else /* NCR_TIMEOUT */
 			    while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
@@ -1294,6 +1383,12 @@
      */
     NCR5380_write(SELECT_ENABLE_REG, 0);
 
+    /*
+     * The initiator shall then wait at least two deskew delays and release 
+     * the BSY signal.
+     */
+    udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
+
     /* Reset BSY */
     NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | 
 	ICR_ASSERT_ATN | ICR_ASSERT_SEL));
@@ -1310,6 +1405,9 @@
      * the 1 us delay is arbitrary, and only used because this delay will 
      * be the same on other platforms and since it works here, it should 
      * work there.
+     *
+     * wingel suggests that this could be due to failing to wait
+     * one deskew delay.
      */
 
     udelay(1);
@@ -1344,6 +1442,14 @@
 	    return -1;
     }
 
+    /* 
+     * No less than two deskew delays after the initiator detects the 
+     * BSY signal is true, it shall release the SEL signal and may 
+     * change the DATA BUS.                                     -wingel
+     */
+
+    udelay(1);
+
     NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 
     if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
@@ -1387,7 +1493,21 @@
      */
 
     /* Wait for start of REQ/ACK handshake */
+#ifdef NCR_TIMEOUT
+    {
+      unsigned long timeout = jiffies + NCR_TIMEOUT;
+ 
+      while (!(NCR5380_read(STATUS_REG) & SR_REQ) && jiffies < timeout);
+
+      if (jiffies >= timeout) {
+        printk("scsi%d: timeout at NCR5380.c:%d\n", __LINE__);
+        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+        return -1;
+      }
+    }
+#else /* NCR_TIMEOUT */
     while (!(NCR5380_read(STATUS_REG) & SR_REQ));
+#endif /* def NCR_TIMEOUT */
 
 #if (NDEBUG & NDEBUG_SELECTION)
     printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n",
@@ -1470,6 +1590,13 @@
     register unsigned char *d = *data;
     NCR5380_setup(instance);
 
+#if (NDEBUG & NDEBUG_PIO)
+    if (!(p & SR_IO))
+      printk("scsi%d : pio write %d bytes\n", instance->host_no, c);
+    else
+      printk("scsi%d : pio read %d bytes\n", instance->host_no, c);
+#endif
+
     /* 
      * The NCR5380 chip will only drive the SCSI bus when the 
      * phase specified in the appropriate bits of the TARGET COMMAND
@@ -1581,6 +1708,73 @@
 	return -1;
 }
 
+static void do_reset (struct Scsi_Host *host) {
+    NCR5380_local_declare();
+    NCR5380_setup(host);
+
+    cli();
+    NCR5380_write(TARGET_COMMAND_REG, 
+	PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
+    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+    udelay(25);
+    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+    sti();
+}
+
+/*
+ * Function : do_abort (Scsi_Host *host)
+ * 
+ * Purpose : abort the currently established nexus.  Should only be 
+ * 	called from a routine which can drop into a 
+ * 
+ * Returns : 0 on success, -1 on failure.
+ */
+
+static int do_abort (struct Scsi_Host *host) {
+    NCR5380_local_declare();
+    unsigned char tmp, *msgptr, phase;
+    int len;
+    NCR5380_setup(host);
+
+
+    /* Request message out phase */
+    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+
+    /* 
+     * Wait for the target to indicate a valid phase by asserting 
+     * REQ.  Once this happens, we'll have either a MSGOUT phase 
+     * and can immediately send the ABORT message, or we'll have some 
+     * other phase and will have to source/sink data.
+     * 
+     * We really don't care what value was on the bus or what value
+     * the target see's, so we just handshake.
+     */
+    
+    while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
+
+    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+    if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
+	    ICR_ASSERT_ACK);
+	while (NCR5380_read(STATUS_REG) & SR_REQ);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+    }
+   
+    tmp = ABORT;
+    msgptr = &tmp;
+    len = 1;
+    phase = PHASE_MSGOUT;
+    NCR5380_transfer_pio (host, &phase, &len, &msgptr);
+
+    /*
+     * If we got here, and the command completed successfully,
+     * we're about to go into bus free state.
+     */
+
+    return len ? -1 : 0;
+}
+
 #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL)
 /* 
  * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, 
@@ -1656,7 +1850,13 @@
 #if defined(PSEUDO_DMA) && !defined(UNSAFE)
     cli();
 #endif
-    NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
+    /* KLL May need eop and parity in 53c400 */
+    if (hostdata->flags & FLAG_NCR53C400)
+	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK
+	| MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE
+	| MR_MONITOR_BSY);
+    else
+	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
 #endif /* def REAL_DMA */
 
 #if (NDEBUG & NDEBUG_DMA) & 0
@@ -1798,7 +1998,12 @@
     return 0;
 #else /* defined(REAL_DMA_POLL) */
     if (p & SR_IO) {
-	if (!(foo = NCR5380_pread(instance, d, c - 1))) {
+	int diff = 1;
+	if (hostdata->flags & FLAG_NCR53C400) {
+	    diff=0;
+	}
+
+	if (!(foo = NCR5380_pread(instance, d, c - diff))) {
 	    /*
 	     * We can't disable DMA mode after successfully transferring 
 	     * what we plan to be the last byte, since that would open up
@@ -1821,13 +2026,18 @@
 	     * byte.
     	     */
 
-	    while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ));
-	    /* Wait for clean handshake */
-	    while (NCR5380_read(STATUS_REG) & SR_REQ);
-	    d[c - 1] = NCR5380_read(INPUT_DATA_REG);
+	    if (!(hostdata->flags & FLAG_NCR53C400)) {
+		while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ));
+		/* Wait for clean handshake */
+		while (NCR5380_read(STATUS_REG) & SR_REQ);
+		d[c - 1] = NCR5380_read(INPUT_DATA_REG);
+	    }
 	}
     } else {
 	int timeout;
+#if (NDEBUG & NDEBUG_C400_PWRITE)
+	printk("About to pwrite %d bytes\n", c);
+#endif
 	if (!(foo = NCR5380_pwrite(instance, d, c))) {
 	    /*
 	     * Wait for the last byte to be sent.  If REQ is being asserted for 
@@ -1868,20 +2078,44 @@
 #endif
 		    }
 		}
-	    } else 
+	    } else  {
+#if (NDEBUG & NDEBUG_C400_PWRITE)
+		printk("Waiting for LASTBYTE\n");
+#endif
 		while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
+#if (NDEBUG & NDEBUG_C400_PWRITE)
+		printk("Got LASTBYTE\n");
+#endif
+	    }
 #else
 	    udelay (5);
 #endif
 	}
     }
 
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
     NCR5380_write(MODE_REG, MR_BASE);
+    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+    if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) {
+#if (NDEBUG & NDEBUG_C400_PWRITE)
+	printk("53C400w: Checking for IRQ\n");
+#endif
+	if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) {
+#if (NDEBUG & NDEBUG_C400_PWRITE)
+	    printk("53C400w:    got it, reading reset interupt reg\n");
+#endif
+	    NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+	} else {
+	    printk("53C400w:    IRQ NOT THERE!\n");
+	}
+    }
 
     *data = d + c;
     *count = 0;
     *phase = (NCR5380_read(STATUS_REG & PHASE_MASK));
+#if 0
+    NCR5380_print_phase(instance);
+#endif
 #if defined(PSEUDO_DMA) && !defined(UNSAFE)
     sti();
 #endif /* defined(REAL_DMA_POLL) */
@@ -1953,9 +2187,10 @@
 		printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n",
 		    instance->host_no);
 		sink = 1;
-		msgout = ABORT;
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-		break;
+		do_abort(instance);
+		cmd->result = DID_ERROR  << 16;
+		cmd->done(cmd);
+		return;
 #endif
 		/* 
 		 * If there is no room left in the current buffer in the
@@ -1985,8 +2220,16 @@
 		 */
 
 #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
+		/* KLL
+		 * PSEUDO_DMA is defined here. If this is the g_NCR5380
+		 * driver then it will always be defined, so the
+		 * FLAG_NO_PSEUDO_DMA is used to inhibit PDMA in the base
+		 * NCR5380 case.  I think this is a fairly clean solution.
+		 * We supplement these 2 if's with the flag.
+		 */
 #ifdef NCR5380_dma_xfer_len
 		if (!cmd->device->borken &&
+		    !(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
 		    (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
 #else
 		transfersize = cmd->transfersize;
@@ -1997,6 +2240,7 @@
 #endif  /* LIMIT_TRANSFERSIZE */
 
 		if (!cmd->device->borken && transfersize && 
+		    !(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
 		    cmd->SCp.this_residual && !(cmd->SCp.this_residual % 
 		    transfersize)) {
 #endif
@@ -2013,7 +2257,9 @@
 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
 			    ICR_ASSERT_ATN);
 			sink = 1;
-			msgout = ABORT;
+			do_abort(instance);
+			cmd->result = DID_ERROR  << 16;
+			cmd->done(cmd);
 			/* XXX - need to source or sink data here, as appropriate */
 		    } else
 			cmd->SCp.this_residual -= transfersize - len;
@@ -2060,10 +2306,8 @@
 			 printk("scsi%d : target %d lun %d linked command complete, no next_link\n"
 			    instance->host_no, cmd->target, cmd->lun);
 			    sink = 1;
-			    msgout = ABORT;
-			    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-				ICR_ASSERT_ATN);
-			    break;
+			    do_abort (instance);
+			    return;
 		    }
 
 		    initialize_SCp(cmd->next_link);
@@ -2081,6 +2325,7 @@
 		case ABORT:
 		case COMMAND_COMPLETE: 
 		    /* Accept message by clearing ACK */
+		    sink = 1;
 		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		    hostdata->connected = NULL;
 #if (NDEBUG & NDEBUG_QUEUES)
@@ -2130,12 +2375,13 @@
 			cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
 
 			cli();
+			LIST(cmd,hostdata->issue_queue);
 			cmd->host_scribble = (unsigned char *) 
 			    hostdata->issue_queue;
 			hostdata->issue_queue = (Scsi_Cmnd *) cmd;
 			sti();
 #if (NDEBUG & NDEBUG_QUEUES)
-			printk("scsi%d : REQUEST SENSE added to head of issue queue\n");
+			printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no);
 #endif
 		   } else
 #endif /* def AUTOSENSE */
@@ -2169,6 +2415,7 @@
 		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		    cmd->device->disconnect = 1;
 		    cli();
+		    LIST(cmd,hostdata->disconnected_queue);
 		    cmd->host_scribble = (unsigned char *) 
 			hostdata->disconnected_queue;
 		    hostdata->connected = NULL;
@@ -2190,6 +2437,9 @@
 		    /* Wait for bus free to avoid nasty timeouts */
 		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
 		    	barrier();
+#if 0
+		    NCR5380_print_status(instance);
+#endif
 		    return;
 		/* 
 		 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
@@ -2287,7 +2537,7 @@
 		    else
 			printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n",
 			    instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun);
-   
+
 		    msgout = MESSAGE_REJECT;
 		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
 			ICR_ASSERT_ATN);
@@ -2462,10 +2712,13 @@
 	    && (tag == tmp->tag) 
 #endif
 ) {
-	    if (prev)
+	    if (prev) {
+		REMOVE(prev,prev->host_scribble,tmp,tmp->host_scribble);
 		prev->host_scribble = tmp->host_scribble;
-	    else
+	    } else {
+		REMOVE(-1,hostdata->disconnected_queue,tmp,tmp->host_scribble);
 		hostdata->disconnected_queue = (Scsi_Cmnd *) tmp->host_scribble;
+	    }
 	    tmp->host_scribble = NULL;
 	    break;
 	}
@@ -2487,16 +2740,11 @@
     }
 
     if (abort) {
-	msg[0] = ABORT;
-	len = 1;
-	data = msg;
-	phase = PHASE_MSGOUT;
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-	NCR5380_transfer_pio(instance, &phase, &len, &data);
+	do_abort (instance);
     } else {
 	hostdata->connected = tmp;
 #if (NDEBUG & NDEBUG_RESELECTION)
-	printk"scsi%d : nexus established, target = %d, lun = %d, tag = %d\n",
+	printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n",
 	    instance->host_no, tmp->target, tmp->lun, tmp->tag);
 #endif
     }
@@ -2576,8 +2824,11 @@
     struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
 	instance->hostdata;
     Scsi_Cmnd *tmp, **prev;
-    unsigned char msg, phase, *msgptr;
-    int len;
+
+    printk("scsi%d : aborting command\n", instance->host_no);
+    print_Scsi_Cmnd (cmd);
+
+    NCR5380_print_status (instance);
 
     printk("scsi%d : aborting command\n", instance->host_no);
     print_Scsi_Cmnd (cmd);
@@ -2630,11 +2881,16 @@
  * Case 2 : If the command hasn't been issued yet, we simply remove it 
  * 	    from the issue queue.
  */
+#if (NDEBUG & NDEBUG_ABORT)
+    /* KLL */
+    printk("scsi%d : abort going into loop.\n", instance->host_no);
+#endif
     for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), 
 	tmp = (Scsi_Cmnd *) hostdata->issue_queue;
 	tmp; prev = (Scsi_Cmnd **) &(tmp->host_scribble), tmp = 
 	(Scsi_Cmnd *) tmp->host_scribble) 
 	if (cmd == tmp) {
+	    REMOVE(5,*prev,tmp,tmp->host_scribble);
 	    (*prev) = (Scsi_Cmnd *) tmp->host_scribble;
 	    tmp->host_scribble = NULL;
 	    tmp->result = DID_ABORT << 16;
@@ -2646,6 +2902,10 @@
 	    tmp->done(tmp);
 	    return SCSI_ABORT_SUCCESS;
 	}
+#if (NDEBUG  & NDEBUG_ABORT)
+    /* KLL */
+    	else if (prev == tmp) printk("scsi%d : LOOP\n", instance->host_no);
+#endif
 
 /* 
  * Case 3 : If any commands are connected, we're going to fail the abort
@@ -2706,12 +2966,7 @@
     printk("scsi%d : nexus reestablished.\n", instance->host_no);
 #endif
 
-	    msg = ABORT;
-	    msgptr = &msg;
-	    len = 1;
-	    phase = PHASE_MSGOUT;
-	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-	    NCR5380_transfer_pio (instance, &phase, &len, &msgptr);
+	    do_abort (instance);
 
 	    cli();
 	    for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), 
@@ -2719,6 +2974,7 @@
 		tmp; prev = (Scsi_Cmnd **) &(tmp->host_scribble), tmp = 
 		(Scsi_Cmnd *) tmp->host_scribble) 
 		    if (cmd == tmp) {
+		    REMOVE(5,*prev,tmp,tmp->host_scribble);
 		    *prev = (Scsi_Cmnd *) tmp->host_scribble;
 		    tmp->host_scribble = NULL;
 		    tmp->result = DID_ABORT << 16;
@@ -2762,12 +3018,7 @@
     NCR5380_setup(cmd->host);
 
     NCR5380_print_status (cmd->host);
-
-    cli();
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
-    udelay(25);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-    sti();
+    do_reset (cmd->host);
 
     return SCSI_RESET_WAKEUP;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this