[135] in linux-scsi channel archive
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