[135] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

NCR diffs against Linux 1.2.4

daemon@ATHENA.MIT.EDU (Drew Eckhardt)
Mon Apr 10 03:38:30 1995

To: ncr53c810@colorado.edu
cc: linux-scsi@vger.rutgers.edu
Date: Mon, 10 Apr 1995 00:11:24 MDT
From: Drew Eckhardt <drew@boulder.openware.com>


Changes : 
Sunday, April 9 : 
- Compiled as a module, the NCR driver can be loaded and unloaded
- The memory allocation code has changed.  NCR53c7x0_cmd
  structures are allocated at probe-time rather than with scsi_malloc
  or kmalloc.
Friday, April 7 :
- I added a halt() function which should abort whatever the NCR 
  chip is currently doing.  

  halt() is called :
  - On bootup.  I think that this might fix the "unable to boot from DOS->Linux
" 
	  problems that some people have been having; maybe not.  I don't use
	  the NCR DOS drivers, and can't check.  In any case, it doesn't 
	  wedge...
  - From the reset function
  - From the shutdown function
- I've also made the SCSI reset function functional, although I don't know 
  if it works (I don't suffer from lockups on my system).

The patches are against 1.2.4

--- 1.1	1995/04/08 04:17:05
+++ 53c7,8xx.c	1995/04/08 06:29:21
@@ -156,6 +156,10 @@
  *
  */
 
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
 #include <asm/io.h>
 #include <asm/system.h>
 #include <linux/delay.h>
@@ -177,6 +181,7 @@
 static int NCR53c8xx_run_tests (struct Scsi_Host *host);
 static int NCR53c8xx_script_len;
 static void NCR53c7x0_intr(int irq, struct pt_regs * regs);
+static int halt (struct Scsi_Host *host);
 static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
     *cmd);
 static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
@@ -208,10 +213,11 @@
 static int scan_scsis_buf_busy = 0;
 static char scan_scsis_buf[512];
 
-
 /*
  * Spl-levels are evil. We shouldn't emulate braindamage.
  *		Linus
+ * I _like_ the idea of prioritized interrupts : in theory, they may
+ *	keep dainbramage from  hurting interrupt latency.
  */
 static int splx (int new_level)
 {
@@ -455,8 +461,8 @@
      * with another board.
      */
 
-    for (search = first_host; search && (search->hostt == the_template) &&
-	(search->irq != host->irq); search=search->next);
+    for (search = first_host; search && ((search->hostt != the_template) ||
+	(search->irq != host->irq)); search=search->next);
 
     if (!search) {
 	if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx")) {
@@ -479,6 +485,10 @@
     hostdata->istat = ((hostdata->chip / 100) == 8) ? 
     	ISTAT_REG_800 : ISTAT_REG_700;
 
+/* Only the ISTAT register is readable when the NCR is running, so make 
+   sure it's halted. */
+    halt(host);
+
 /* 
  * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc,
  *	as does the 710 with one bit per SCSI ID.  Conversely, the NCR
@@ -729,6 +739,11 @@
     size = sizeof(struct NCR53c7x0_hostdata) + script_len;
 
     instance = scsi_register (tpnt, size);
+
+    /* FIXME : if we ever support an ISA NCR53c7xx based board, we
+       need to check if it's running in a 16 bit mode, and if so 
+       unregister it if it is past the 16M (0x1000000) mark */
+   	
     hostdata = (struct NCR53c7x0_hostdata *) 
     	instance->hostdata;
     hostdata->size = size;
@@ -2164,7 +2179,8 @@
  * 
  */
 
-static void NCR53c8x0_soft_reset (struct Scsi_Host *host) {
+static void 
+NCR53c8x0_soft_reset (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
 	host->hostdata;
@@ -3204,7 +3220,8 @@
  *
  */
 
-static int abort_connected (struct Scsi_Host *host) {
+static int 
+abort_connected (struct Scsi_Host *host) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
 	host->hostdata;
 
@@ -3749,17 +3766,57 @@
  * Returns : 0 on success.
  */
  
-int NCR53c7xx_reset (Scsi_Cmnd *cmd) {
+int 
+NCR53c7xx_reset (Scsi_Cmnd *cmd) {
     NCR53c7x0_local_declare();
-    struct Scsi_Host *host = cmd ? cmd->host : NULL;
+    unsigned long flags;
+    int found;
+    struct NCR53c7x0_cmd * c;
+    Scsi_Cmnd *tmp;
+    struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = host ? 
-	(struct NCR53c7x0_hostdata *) host->hostdata : NULL;
-    if (host) NCR53c7x0_local_setup(host);
-    
+    (struct NCR53c7x0_hostdata *) host->hostdata : NULL;
+    NCR53c7x0_local_setup(host);
+    save_flags(flags);
+    halt (host);
+    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    udelay(25);	/* Minimum ammount of time to assert RST */
+    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    for (c = hostdata->running_list, found = 0; c; c=c->next)  {
+	tmp = c->cmd;
+	if (!scan_scsis_buf_busy) {
+#ifdef SCSI_MALLOC
+	    scsi_free ((void *) c->real, c->size);
+#else
+	    kfree_s ((void *) c->real, c->size);
+#endif
+	} else 
+	    scan_scsis_buf_busy = 0;
+	if (tmp == cmd)
+	    found = 1; 
+    	tmp->result = DID_RESET << 16;
+	tmp->scsi_done(tmp);
+    }
+    if (!found) {
+    	c = (struct NCR53c7x0_cmd *) cmd->host_scribble;
+    	if (c) {
+	    if (!scan_scsis_buf_busy) {
+#ifdef SCSI_MALLOC
+		scsi_free ((void *) c->real, c->size);
+#else
+		kfree_s ((void *) c->real, c->size);
+#endif
+	    } else 
+		scan_scsis_buf_busy = 0;
+    	}
+    	cmd->result = DID_RESET << 16;
+    	cmd->scsi_done(cmd);
+    }
+    restore_flags(flags);
 
     printk ("scsi%d : DANGER : NCR53c7xx_reset is NOP\n",
 	cmd->host->host_no);
-    return SCSI_RESET_SNOOZE;
+    return SCSI_RESET_SUCCESS;
 }
 
 /*
@@ -3790,3 +3847,107 @@
     }
 }
 
+/*
+ * Function : static int shutdown (struct Scsi_Host *host)
+ * 
+ * Purpose : does a clean (we hope) shutdown of the NCR SCSI 
+ *	chip.  Use prior to dumping core, unloading the NCR driver,
+ *	etc.
+ * 
+ * Returns : 0 on success
+ */
+
+static int 
+shutdown (struct Scsi_Host *host) {
+    NCR53c7x0_local_declare();
+    unsigned long flags;
+    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+	host->hostdata;
+    NCR53c7x0_local_setup(host);
+    save_flags (flags);
+    cli();
+    halt (host);
+    hostdata->soft_reset(host);
+/* 
+ * For now, we take the simplest solution : reset the SCSI bus. Eventually,
+ * - If a command is connected, kill it with an ABORT message
+ * - If commands are disconnected, connect to each target/LUN and 
+ *	do a ABORT, followed by a SOFT reset, followed by a hard 
+ *	reset.  
+ */
+    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    udelay(25);	/* Minimum ammount of time to assert RST */
+    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    restore_flags (flags);
+    return 0;
+}
+
+
+/*
+ * Function : static int halt (struct Scsi_Host *host)
+ * 
+ * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
+ *
+ * Inputs : host - SCSI chip to halt
+ *
+ * Returns : 0 on success
+ */
+
+static int 
+halt (struct Scsi_Host *host) {
+    NCR53c7x0_local_declare();
+    unsigned long flags;
+    unsigned char istat, tmp;
+    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+	host->hostdata;
+    NCR53c7x0_local_setup(host);
+
+    save_flags(flags);
+    cli();
+    NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
+    /* Eat interrupts until we find what we're looking for */
+    for (;;) {
+	istat = NCR53c7x0_read8 (hostdata->istat);
+	if (istat & ISTAT_SIP) {
+	    if ((hostdata->chip / 100) == 8) {
+		tmp = NCR53c7x0_read8(SIST0_REG_800);
+		udelay(1);
+		tmp = NCR53c7x0_read8(SIST1_REG_800);
+	    } else {
+		tmp = NCR53c7x0_read8(SSTAT0_REG);
+	    }
+	} else if (istat & ISTAT_DIP) {
+            NCR53c7x0_write8(hostdata->istat, 0);
+	    tmp = NCR53c7x0_read8(DSTAT_REG);
+	    if (tmp & DSTAT_ABRT)
+		break;
+	    else
+		panic("scsi%d: could not halt NCR chip\n");
+	}
+    }
+    hostdata->state = STATE_HALTED;
+    restore_flags(flags);
+    return 0;
+}
+
+#ifdef MODULE
+int NCR53c7x0_release(struct Scsi_Host *host) {
+    shutdown (host);
+/* FIXME : need to recursively free tpnt structure */
+    if (host->irq != IRQ_NONE)
+	{
+	    int irq_count;
+	    stuct Scsi_Host tmp;
+	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
+		if (tmp->hostt == the_template && tmp->irq = host->irq)
+		    ++irq_count;
+	    if (irq_count == 1)
+		free_irq(host->irq);
+	}
+    if (host->dma != DMA_NONE)
+	free_dma(host->dma);
+    return 1;
+}
+Scsi_Host_Template driver_template = NCR53c7xx;
+#include "scsi_module.c"
+#endif /* def MODULE */
--- 1.1	1995/04/08 04:58:18
+++ 53c7,8xx.h	1995/04/08 05:16:35
@@ -46,20 +46,27 @@
  * array.
  */
 
-#ifdef HOSTS_C 
+#if defined(HOSTS_C) || defined(MODULE)
 #include <linux/scsicam.h>
 extern int NCR53c7xx_abort(Scsi_Cmnd *);
 extern int NCR53c7xx_detect(Scsi_Host_Template *tpnt);
 extern int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int NCR53c7xx_reset(Scsi_Cmnd *);
+#ifdef MODULE
+extern int NCR53c7xx_release(Scsi_Host *);
+#else
+#define NCR53c7xx_release NULL
+#endif
 
 #define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 3)", NCR53c7xx_detect, 
	\
-    	NULL, NULL,						\
-	NULL, NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,\
-        NULL, scsicam_bios_param, 					\
-	/* can queue */ 1, /* id */ 7, 127 /* old SG_ALL */, 		\
-	/* cmd per lun */ 1 , 0, 0, DISABLE_CLUSTERING}
-#else
+    	NULL, /* info */ NULL, /* command, depricated */ NULL, 		\
+	NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,	\
+        NULL /* slave attach */, scsicam_bios_param, /* can queue */ 1, \
+	/* id */ 7, 127 /* old SG_ALL */, /* cmd per lun */ 1 , 	\
+        /* present */ 0, /* unchecked isa dma */ 0, DISABLE_CLUSTERING} 
+#endif /* defined(HOSTS_C) || defined(MODULE) */ 
+
+#ifndef HOSTS_C
 /* Register addresses, ordered numerically */
 
 
@@ -986,10 +993,12 @@
 /* Indicates that the NCR is executing other code. */
 #define STATE_RUNNING	2		
 /* 
- * Indicates that the NCR was being aborted.  Only used when running 
- * NCR53c700 compatible scripts.  
+ * Indicates that the NCR was being aborted.
  */
 #define STATE_ABORTING	3
+/* 
+ * Indicates that the NCR was successfully aborted. */
+#define STATE_ABORTED 4
     
 
 /* 
--- 1.1	1995/04/08 05:56:58
+++ Makefile	1995/04/08 05:57:24
@@ -125,6 +125,8 @@
 ifdef CONFIG_SCSI_NCR53C7xx
 SCSI_OBJS := $(SCSI_OBJS) 53c7,8xx.o 
 SCSI_SRCS := $(SCSI_SRCS) 53c7,8xx.c
+else
+SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) 53c7,8xx.o
 endif
 
 ifdef CONFIG_SCSI_PAS16


home help back first fref pref prev next nref lref last post