patch-2.1.125 linux/drivers/scsi/53c7xx.c

Next file: linux/drivers/scsi/ChangeLog.ncr53c8xx
Previous file: linux/drivers/pci/oldproc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.124/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c
@@ -325,6 +325,7 @@
 static int disable (struct Scsi_Host *host);
 static int NCR53c7xx_run_tests (struct Scsi_Host *host);
 static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void NCR53c7x0_intfly (struct Scsi_Host *host);
 static int ncr_halt (struct Scsi_Host *host);
 static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
     *cmd);
@@ -847,7 +848,6 @@
     unsigned char revision;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
 	host->hostdata[0];
-    struct Scsi_Host *search;
     /* 
      * There are some things which we need to know about in order to provide
      * a semblance of support.  Print 'em if they aren't what we expect, 
@@ -1072,26 +1072,13 @@
 
     NCR53c7x0_driver_init (host);
 
-    /*
-     * Set up an interrupt handler if we aren't already sharing an IRQ
-     * with another board.
-     */
-
-    for (search = first_host; search && !(search->hostt == the_template &&
-	search->irq == host->irq && search != host); search=search->next);
-
-    if (!search) {
-	if (request_irq(host->irq, NCR53c7x0_intr, 0, "53c7xx", NCR53c7x0_intr))
-	{
-	    printk("scsi%d : IRQ%d not free, detaching\n",
+    if (request_irq(host->irq, NCR53c7x0_intr, 0, "53c7xx", host))
+    {
+	printk("scsi%d : IRQ%d not free, detaching\n",
 		host->host_no, host->irq);
-	    scsi_unregister (host);
-	    return -1;
-	} 
-    } else {
-	printk("scsi%d : using interrupt handler previously installed for scsi%d\n",
-	    host->host_no, search->host_no);
-    }
+	scsi_unregister (host);
+	return -1;
+    } 
 
     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
         (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
@@ -2509,18 +2496,7 @@
 	    abnormal_finished (cmd, DID_ERROR << 16);
 	return SPECIFIC_INT_NOTHING;
     case A_int_norm_emulateintfly:
-	/* I'm not sure this is the right ! thing to do, but it works
-	 * with the A4000T when copyback is disabled, and also the
-	 * WarpEngine with copyback enabled, so it looks as though
-	 * it does work to some extent.
-	 *
-	 * RGH:  I don't really like it - You get an interrupt which
-	 * calls NCR53c7x0_intr(), which calls this function (via
-	 * intr_dma()), which calls NCR53c7x0_intr().....
-	 * Anyway let's see how it goes for now.
-	 */
-	hostdata->emulated_intfly = 1;
-	NCR53c7x0_intr(host->irq, NULL, NULL);
+	NCR53c7x0_intfly(host);
 	return SPECIFIC_INT_NOTHING;
     case A_int_test_1:
     case A_int_test_2:
@@ -4141,288 +4117,230 @@
 }
 #endif
 
+
 /*
- * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
  *
- * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
- *	the same IRQ line.  
+ * Purpose : Scan command queue for specified host, looking for completed
+ *           commands.
  * 
- * Inputs : Since we're using the SA_INTERRUPT interrupt handler
- *	semantics, irq indicates the interrupt which invoked 
- *	this handler.  
+ * Inputs : Scsi_Host pointer.
  *
- * On the 710 we simualte an INTFLY with a script interrupt, and the
- * script interrupt handler will call back to this function.
+ * 	This is called from the interrupt handler, when a simulated INTFLY
+ * 	interrupt occurs.
  */
 
-static void 
-NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
+static void
+NCR53c7x0_intfly (struct Scsi_Host *host)
+{
     NCR53c7x0_local_declare();
-    struct Scsi_Host *host;			/* Host we are looking at */
-    unsigned char istat; 			/* Values of interrupt regs */
     struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
     struct NCR53c7x0_cmd *cmd,			/* command which halted */
 	**cmd_prev_ptr;
-    u32 *dsa;					/* DSA */
-    int done = 1;				/* Indicates when handler 
-						   should terminate */
-    int interrupted = 0;			/* This HA generated 
-						   an interrupt */
-    int have_intfly;				/* Don't print warning 
-						   messages when we stack
-						   INTFLYs */
     unsigned long flags;				
+    char search_found = 0;			/* Got at least one ? */
 
-#ifdef NCR_DEBUG
-    char buf[80];				/* Debugging sprintf buffer */
-    size_t buflen;				/* Length of same */
-#endif
-
-#if defined(CONFIG_AMIGA)
-    custom.intena = IF_PORTS;
-#endif
-
-    do {
-	done = 1;
-	for (host = first_host; host; host = host->next) 
-	    if (host->hostt == the_template
-#if defined(MVME16x_INTFLY)
-			/* We have two different interrupts pointing
-			 * at this routine, so remove this check */
-#else
-				&& host->irq == irq
-#endif
-							) {
-    	    NCR53c7x0_local_setup(host);
+    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+    NCR53c7x0_local_setup(host);
 
-	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
-	    hostdata->dsp_changed = 0;
-	    interrupted = 0;
-	    have_intfly = 0;
-
-	    do {
-		hostdata->dstat_valid = 0;
-		interrupted = 0;
-		/*
-		 * Only read istat once, since reading it again will unstack
-		 * interrupts?
-		 */
-		istat = NCR53c7x0_read8(hostdata->istat);
-
-		if ((hostdata->options & OPTION_INTFLY) && 
-#ifdef MVME16x_INTFLY
-                    /* the bit is set which indicates an on-the-fly int */
-                        (*(volatile unsigned long *)0xfff40068 & 0x8000))
-#else
-		    (hostdata->emulated_intfly != 0))
-#endif
-		{
-		    char search_found = 0;	/* Got at least one ? */
-		    done = 0;
-		    interrupted = 1;
+    if (hostdata->options & OPTION_DEBUG_INTR)
+    printk ("scsi%d : INTFLY\n", host->host_no); 
 
-#ifdef MVME16x_INTFLY
-                    /* clear the INTFLY bit */
-                    *(volatile unsigned long *)0xfff40074 = 0x8000;
-#endif
+    /*
+    * Traverse our list of running commands, and look
+    * for those with valid (non-0xff ff) status and message
+    * bytes encoded in the result which signify command
+    * completion.
+    */
 
-		    if (hostdata->options & OPTION_DEBUG_INTR)
-			printk ("scsi%d : INTFLY\n", host->host_no); 
+    save_flags(flags);
+    cli();
+restart:
+    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
+	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
+	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
+    	cmd = (struct NCR53c7x0_cmd *) cmd->next)
+    {
+	Scsi_Cmnd *tmp;
 
-		    /*
-		     * Traverse our list of running commands, and look
-		     * for those with valid (non-0xff ff) status and message
-		     * bytes encoded in the result which signify command
-		     * completion.
-		     */
+	if (!cmd) {
+	    printk("scsi%d : very weird.\n", host->host_no);
+	    break;
+	}
 
+	if (!(tmp = cmd->cmd)) {
+	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
+		    host->host_no);
+	    continue;
+	}
+	/* Copy the result over now; may not be complete,
+	 * but subsequent tests may as well be done on
+	 * cached memory.
+	 */
+	tmp->result = cmd->result;
 
-		    save_flags(flags);
-		    cli();
-restart:
-		    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **) 
-			 &(hostdata->running_list), cmd = 
-			 (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
-			 cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
-    	    	    	 cmd = (struct NCR53c7x0_cmd *) cmd->next) {
-			Scsi_Cmnd *tmp;
-
-			if (!cmd) {
-			    printk("scsi%d : very weird.\n", host->host_no);
-			    break;
-			}
-
-			if (!(tmp = cmd->cmd)) {
-			    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
-				host->host_no);
-				continue;
-			}
-                        /* Copy the result over now; may not be complete,
-			 * but subsequent tests may as well be done on
-                         * cached memory.
-                         */
-                        tmp->result = cmd->result;
-#if 0
-			printk ("scsi%d : looking at result of 0x%x\n",
-			    host->host_no, cmd->cmd->result);
-#endif
-		
-			if (((tmp->result & 0xff) == 0xff) ||
+	if (((tmp->result & 0xff) == 0xff) ||
 			    ((tmp->result & 0xff00) == 0xff00))
-			    continue;
+	    continue;
 
-			search_found = 1;
+	search_found = 1;
 
-			if (cmd->bounce.len)
-			    memcpy ((void *)cmd->bounce.addr,
+	if (cmd->bounce.len)
+	    memcpy ((void *)cmd->bounce.addr,
 				(void *)cmd->bounce.buf, cmd->bounce.len);
 
-			/* Important - remove from list _before_ done is called */
-			if (cmd_prev_ptr)
-			    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
-
-			--hostdata->busy[tmp->target][tmp->lun];
-    	    	    	cmd->next = hostdata->free;
-    	    	    	hostdata->free = cmd;
-
-    	    	    	tmp->host_scribble = NULL;
-
-			if (hostdata->options & OPTION_DEBUG_INTR) {
-			    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
-				host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result);
-			    print_command (tmp->cmnd);
-			}
+	/* Important - remove from list _before_ done is called */
+	if (cmd_prev_ptr)
+	    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
 
-#if 0
-			hostdata->options &= ~OPTION_DEBUG_INTR;
-#endif
-			tmp->scsi_done(tmp);
-			goto restart;
+	--hostdata->busy[tmp->target][tmp->lun];
+	cmd->next = hostdata->free;
+	hostdata->free = cmd;
 
-		    }
-		    restore_flags(flags);
-		   
-		    if (!search_found && !have_intfly)  {
-			printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
-			    host->host_no);
-		    } else if (!have_intfly)  {
-			have_intfly = 1; 
-    		    	run_process_issue_queue();
-		    }
-		}
+	tmp->host_scribble = NULL;
 
-		if (hostdata->emulated_intfly)
-		{
-			hostdata->emulated_intfly = 0;
-			return;
-		}
+	if (hostdata->options & OPTION_DEBUG_INTR) {
+	    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
+		  host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result);
+	    print_command (tmp->cmnd);
+	}
 
-		if (istat & (ISTAT_SIP|ISTAT_DIP)) {
-		    done = 0;
-		    interrupted = 1;
-    	    	    hostdata->state = STATE_HALTED;
+	tmp->scsi_done(tmp);
+	goto restart;
+    }
+    restore_flags(flags);
 
-		    if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
-			printk ("scsi%d : SCSI FIFO not empty\n", 
+    if (!search_found)  {
+	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
 			    host->host_no);
+    } else {
+	run_process_issue_queue();
+    }
+    return;
+}
 
-		    /*
-		     * NCR53c700 and NCR53c700-66 change the current SCSI
-		     * process, hostdata->ncrcurrent, in the Linux driver so
-		     * cmd = hostdata->ncrcurrent.
-		     *
-		     * With other chips, we must look through the commands
-		     * executing and find the command structure which 
-		     * corresponds to the DSA register.
-		     */
-
-		    if (hostdata->options & OPTION_700) {
-			cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
-		    } else {
-			dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-			for (cmd = (struct NCR53c7x0_cmd *) 
-			    hostdata->running_list; cmd &&
-    	    	    	    (dsa + (hostdata->dsa_start / sizeof(u32))) != 
-    	    	    	    	cmd->dsa;
-			    cmd = (struct NCR53c7x0_cmd *)(cmd->next));
-		    }
-		    if (hostdata->options & OPTION_DEBUG_INTR) {
-			if (cmd) {
-			    printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
-				host->host_no, cmd->cmd->pid, (int) cmd->cmd->target,
-				(int) cmd->cmd->lun);
-			    print_command (cmd->cmd->cmnd);
-			} else {
-			    printk("scsi%d : no active command\n", host->host_no);
-			}
-		    }
+/*
+ * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ *
+ * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
+ *	the same IRQ line.  
+ * 
+ * Inputs : Since we're using the SA_INTERRUPT interrupt handler
+ *	semantics, irq indicates the interrupt which invoked 
+ *	this handler.  
+ *
+ * On the 710 we simualte an INTFLY with a script interrupt, and the
+ * script interrupt handler will call back to this function.
+ */
 
-		    if (istat & ISTAT_SIP) {
-			if (hostdata->options & OPTION_DEBUG_INTR) 
-			    printk ("scsi%d : ISTAT_SIP\n", host->host_no);
-			intr_scsi (host, cmd);
-		    }
-		
-		    if (istat & ISTAT_DIP) {
-			if (hostdata->options & OPTION_DEBUG_INTR) 
-			    printk ("scsi%d : ISTAT_DIP\n", host->host_no);
-			intr_dma (host, cmd);
-		    }
+static void 
+NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
+    NCR53c7x0_local_declare();
+    struct Scsi_Host *host;			/* Host we are looking at */
+    unsigned char istat; 			/* Values of interrupt regs */
+    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
+    struct NCR53c7x0_cmd *cmd;			/* command which halted */
+    u32 *dsa;					/* DSA */
 
-		    if (!hostdata->dstat_valid) {
-			hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-			hostdata->dstat_valid = 1;
-		    }
+#ifdef NCR_DEBUG
+    char buf[80];				/* Debugging sprintf buffer */
+    size_t buflen;				/* Length of same */
+#endif
 
-		    if (!(hostdata->dstat & DSTAT_DFE)) {
-		      printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-		      /* Really need to check this out for 710 RGH */
-                      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-                      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
-		      hostdata->dstat |= DSTAT_DFE;
-		    }
-		}
-	    } while (interrupted);
+    host     = (struct Scsi_Host *)dev_id;
+    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+    NCR53c7x0_local_setup(host);
 
+    /*
+     * Only read istat once per loop, since reading it again will unstack
+     * interrupts
+     */
 
+    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
+	hostdata->dsp_changed = 0;
+	hostdata->dstat_valid = 0;
+    	hostdata->state = STATE_HALTED;
 
-	    if (hostdata->intrs != -1)
-		hostdata->intrs++;
-#if 0
-	    if (hostdata->intrs > 40) {
-		printk("scsi%d : too many interrupts, halting", host->host_no);
-		disable(host);
+	if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
+	    printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
+
+	/*
+	 * NCR53c700 and NCR53c700-66 change the current SCSI
+	 * process, hostdata->ncrcurrent, in the Linux driver so
+	 * cmd = hostdata->ncrcurrent.
+	 *
+	 * With other chips, we must look through the commands
+	 * executing and find the command structure which 
+	 * corresponds to the DSA register.
+	 */
+
+	if (hostdata->options & OPTION_700) {
+	    cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
+	} else {
+	    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
+	    for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
+		cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
+		    cmd = (struct NCR53c7x0_cmd *)(cmd->next))
+		;
+	}
+	if (hostdata->options & OPTION_DEBUG_INTR) {
+	    if (cmd) {
+		printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
+		    host->host_no, cmd->cmd->pid, (int) cmd->cmd->target,
+		    (int) cmd->cmd->lun);
+		print_command (cmd->cmd->cmnd);
+	    } else {
+		printk("scsi%d : no active command\n", host->host_no);
 	    }
-#endif
+	}
+	
+	if (istat & ISTAT_SIP) {
+	    if (hostdata->options & OPTION_DEBUG_INTR) 
+		printk ("scsi%d : ISTAT_SIP\n", host->host_no);
+	    intr_scsi (host, cmd);
+	}
+	
+	if (istat & ISTAT_DIP) {
+	    if (hostdata->options & OPTION_DEBUG_INTR) 
+		printk ("scsi%d : ISTAT_DIP\n", host->host_no);
+	    intr_dma (host, cmd);
+	}
+	
+	if (!hostdata->dstat_valid) {
+	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
+	    hostdata->dstat_valid = 1;
+	}
+	
+	if (!(hostdata->dstat & DSTAT_DFE)) {
+	    printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
+	    /* Really need to check this out for 710 RGH */
+	    NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
+	    while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
+		;
+	    hostdata->dstat |= DSTAT_DFE;
+	}
 
-	    if (!hostdata->idle && hostdata->state == STATE_HALTED) {
-		if (!hostdata->dsp_changed) {
-		    hostdata->dsp = (u32 *) 
-			bus_to_virt(NCR53c7x0_read32(DSP_REG));
-		}
-			
+	if (!hostdata->idle && hostdata->state == STATE_HALTED) {
+	    if (!hostdata->dsp_changed)
+		hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
 #if 0
-		printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
-		    host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
+	    printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
+		host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
 #endif
 		
-		hostdata->state = STATE_RUNNING;
-		NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
-		if (hostdata->options & OPTION_DEBUG_TRACE) {
+	    hostdata->state = STATE_RUNNING;
+	    NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
+	    if (hostdata->options & OPTION_DEBUG_TRACE) {
 #ifdef CYCLIC_TRACE
-		    log_insn (hostdata->dsp);
+		log_insn (hostdata->dsp);
 #else
-	    	    print_insn (host, hostdata->dsp, "t ", 1);
+	    	print_insn (host, hostdata->dsp, "t ", 1);
 #endif
-		    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-		}
+		NCR53c7x0_write8 (DCNTL_REG,
+			hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
 	    }
 	}
-    } while (!done);
-#ifdef CONFIG_AMIGA
-	custom.intena = IF_SETCLR | IF_PORTS;
-#endif
+    }
 }
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov