[308] in linux-scsi channel archive
Linux 1.2.10 NCR53c810 patch
daemon@ATHENA.MIT.EDU (Drew Eckhardt)
Wed Jun 28 03:03:01 1995
To: ncr53c810@Colorado.EDU
cc: linux-scsi@vger.rutgers.edu
Date: Wed, 28 Jun 1995 00:05:31 -0600
From: Drew Eckhardt <drew@poohsticks.org>
The following patches "should" (I haven't started swapping cables
arround yet to put SCSI devices off my second NCR interface) fix
the problems people have had trying to run multiple NCR boards in the
same system; interrupts are working, the tests all pass, etc. I'll
throw my RZ55 on there tomorrow and fix the target initiated SDTR bug
and see how it really works...
The halt() code no longer panics when it sees interrupts it thinks
it shouldn't.
Fatal errors don't panic the system anymore; they just disable the NCR
driver and cause all commands to return errors. This shouldn't help
normal users too much, but means I don't need to wait for my disks to
fsck when I screw up.
The messages which preceed a fatal error are now all printed at
priority KERN_ALERT, so we get them on the console and you don't
end up with part of a "panic()" message, and the rest off in a
syslog file which never gets comitted to disk.
If your NCR BIOS is doing flakey things, like not initializing the
initiator SCSI ID register, we cope with them a bit more gracefullly.
Enjoy.
--- 53c7,8xx.c 1995/06/23 05:58:11 1.1
+++ 53c7,8xx.c 1995/06/28 05:53:26
@@ -23,7 +23,7 @@
* Copyright 1993, 1994, 1995 Drew Eckhardt
* Visionary Computing
* (Unix and Linux consulting and custom programming)
- * drew@Colorado.EDU
+ * drew@PoohSticks.ORG
* +1 (303) 786-7975
*
* TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
@@ -176,7 +176,9 @@
#include "constants.h"
#include "sd.h"
+static int shutdown (struct Scsi_Host *host);
static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
+static int disable (struct Scsi_Host *host);
static int NCR53c8xx_run_tests (struct Scsi_Host *host);
static int NCR53c8xx_script_len;
static int NCR53c8xx_dsa_len;
@@ -185,7 +187,8 @@
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);
-static void print_dsa (struct Scsi_Host *host, unsigned long *dsa);
+static void print_dsa (struct Scsi_Host *host, unsigned long *dsa,
+ const char *prefix);
static int print_insn (struct Scsi_Host *host, unsigned long *insn,
char *prefix, int kernel);
@@ -432,26 +435,6 @@
hostdata->NCR53c7xx_msg_abort = ABORT;
hostdata->NCR53c7xx_msg_nop = NOP;
- /*
- * 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=search->next);
-
- if (!search) {
- if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx")) {
- 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);
- }
-
printk ("scsi%d : using %s mapped access\n", host->host_no,
(hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" :
"io");
@@ -480,6 +463,13 @@
host->this_id = NCR53c7x0_read8(SCID_REG) & 7;
hostdata->this_id_mask = 1 << host->this_id;
#endif
+
+ if (!host->this_id) {
+ printk("scsi%d : initiator ID was set to 0, changing to 7\n",
+ host->host_no);
+ host->this_id = 7;
+ hostdata->this_id_mask = 1 << 7;
+ };
printk("scsi%d : using initiator ID %d\n", host->host_no,
host->this_id);
@@ -640,6 +630,27 @@
hostdata->expecting_iid = 0;
hostdata->expecting_sto = 0;
+ /*
+ * 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, SA_INTERRUPT, "53c7,8xx")) {
+ 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);
+ }
+
+
if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
(hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
/* XXX Should disable interrupts, etc. here */
@@ -812,6 +823,7 @@
}
instance->irq = irq;
instance->dma_channel = dma;
+ instance->next = NULL;
hostdata->options = options;
hostdata->dsa_size = dsa_len;
@@ -2273,9 +2285,9 @@
#if 0
NCR53c7x0_write8(STIME0_REG_800,
((14 << STIME0_800_SEL_SHIFT) & STIME0_800_SEL_MASK)
-/* Disable HTH interrupt */
| ((15 << STIME0_800_HTH_SHIFT) & STIME0_800_HTH_MASK));
#else
+/* Disable HTH interrupt */
NCR53c7x0_write8(STIME0_REG_800,
((14 << STIME0_800_SEL_SHIFT) & STIME0_800_SEL_MASK));
#endif
@@ -3033,14 +3045,10 @@
size_t buflen; /* Length of same */
#endif
-#if 0
- printk("interrupt %d received\n", irq);
-#endif
-
do {
done = 1;
- for (host = first_host; host; host = hostdata->next ?
- hostdata->next : NULL) {
+ for (host = first_host; host; host = host->next)
+ if (host->hostt == the_template && host->irq == irq) {
NCR53c7x0_local_setup(host);
hostdata = (struct NCR53c7x0_hostdata *) host->hostdata;
@@ -3513,10 +3521,10 @@
} else
#endif
{
- printk("scsi%d : unexpected abort interrupt at\n"
+ printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n"
" ", host->host_no);
- print_insn (host, dsp, "s ", 1);
- panic(" ");
+ print_insn (host, dsp, KERN_ALERT "s ", 1);
+ FATAL (host);
}
}
@@ -3537,10 +3545,11 @@
~DCNTL_SSM) | DCNTL_STD);
restore_flags(flags);
} else {
- printk("scsi%d : unexpected single step interrupt at\n"
+ printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
" ", host->host_no);
- print_insn (host, dsp, "", 1);
- panic(" mail drew@colorad.edu\n");
+ print_insn (host, dsp, KERN_ALERT "", 1);
+ printk(KERN_ALERT " mail drew@colorado.edu\n");
+ FATAL (host);
}
}
@@ -3585,16 +3594,17 @@
hostdata->expecting_sto = 1;
}
} else {
- printk("scsi%d : illegal instruction ", host->host_no);
- print_insn (host, dsp, "", 1);
- printk("scsi%d : DSP=0x%lx, DCMD|DBC=0x%lx, DSA=0x%lx\n"
+ printk(KERN_ALERT "scsi%d : illegal instruction ", host->host_no);
+ print_insn (host, dsp, KERN_ALERT "", 1);
+ printk(KERN_ALERT "scsi%d : DSP=0x%lx, DCMD|DBC=0x%lx, DSA=0x%lx\n"
" DSPS=0x%lx, TEMP=0x%lx, DMODE=0x%x,\n"
" DNAD=0x%lx\n",
host->host_no, (unsigned long) dsp, dbc_dcmd,
(unsigned long) dsa, NCR53c7x0_read32(DSPS_REG),
NCR53c7x0_read32(TEMP_REG), (int) NCR53c7x0_read8(hostdata->dmode),
NCR53c7x0_read32(DNAD_REG));
- panic(" mail drew@Colorado.EDU\n");
+ printk(KERN_ALERT " mail drew@PoohSticks.ORG\n");
+ FATAL (host);
}
}
@@ -3604,17 +3614,18 @@
*/
if (dstat & DSTAT_800_BF) {
- printk("scsi%d : BUS FAULT, DSP=0x%lx, DCMD|DBC=0x%lx, DSA=0x%lx\n"
+ printk(KERN_ALERT "scsi%d : BUS FAULT, DSP=0x%lx, DCMD|DBC=0x%lx, DSA=0x%lx\n"
" DSPS=0x%lx, TEMP=0x%lx, DMODE=0x%x\n",
host->host_no, (unsigned long) dsp, NCR53c7x0_read32(DBC_REG),
(unsigned long) dsa, NCR53c7x0_read32(DSPS_REG),
NCR53c7x0_read32(TEMP_REG), (int) NCR53c7x0_read8(hostdata->dmode));
- print_dsa (host, dsa);
- printk("scsi%d : DSP->\n", host->host_no);
- print_insn(host, dsp, "", 1);
- print_insn(host, next_dsp, "", 1);
+ print_dsa (host, dsa, KERN_ALERT "");
+ printk(KERN_ALERT "scsi%d : DSP->\n", host->host_no);
+ print_insn(host, dsp, KERN_ALERT "", 1);
+ print_insn(host, next_dsp, KERN_ALERT "", 1);
#if 0
- panic(" mail drew@Colorado.EDU\n");
+ printk(KERN_ALERT " mail drew@PoohSticks.ORG\n");
+ FATAL (host);
#else
hostdata->idle = 1;
hostdata->options |= OPTION_DEBUG_INIT_ONLY;
@@ -3641,18 +3652,20 @@
abort_connected(host);
break;
case SPECIFIC_INT_PANIC:
- printk("scsi%d : failure at ", host->host_no);
- print_insn (host, dsp, "", 1);
- panic(" dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
+ printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
+ print_insn (host, dsp, KERN_ALERT "", 1);
+ printk(KERN_ALERT " dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
+ FATAL (host);
break;
case SPECIFIC_INT_BREAK:
intr_break (host, cmd);
break;
default:
- printk("scsi%d : failure at ", host->host_no);
- print_insn (host, dsp, "", 1);
- panic(" dstat_sir_intr() returned unknown value %d\n",
+ printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
+ print_insn (host, dsp, KERN_ALERT "", 1);
+ printk(KERN_ALERT" dstat_sir_intr() returned unknown value %d\n",
tmp);
+ FATAL (host);
}
}
@@ -3857,14 +3870,17 @@
* therefore shares the scsicam_bios_param function.
*/
-static void print_dsa (struct Scsi_Host *host, unsigned long *dsa) {
+static void
+print_dsa (struct Scsi_Host *host, unsigned long *dsa,
+ const char *prefix) {
struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
host->hostdata;
int i, len;
char *ptr;
- printk("scsi%d : dsa at 0x%x\n"
+ printk("%sscsi%d : dsa at 0x%x\n"
" + %ld : dsa_msgout length = %lu, data = 0x%lx\n" ,
+ prefix ? prefix : "",
host->host_no, (unsigned) dsa, hostdata->dsa_msgout,
dsa[hostdata->dsa_msgout / sizeof(long)],
dsa[hostdata->dsa_msgout / sizeof(long) + 1]);
@@ -3909,11 +3925,38 @@
NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
udelay(25); /* Minimum amount of time to assert RST */
NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+
+ disable (host);
restore_flags (flags);
return 0;
}
#endif
+/*
+ * Function : static int disable (struct Scsi_Host *host)
+ *
+ * Purpose : disables the given NCR host, causing all commands
+ * to return a driver error. Call this so we can unload the
+ * module during development and try again. Eventually,
+ * we should be able to find clean workarrounds for these
+ * problems.
+ *
+ * Inputs : host - hostadapter to twiddle
+ *
+ * Returns : 0 on success.
+ */
+
+static int
+disable (struct Scsi_Host *host) {
+ struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ host->hostdata;
+ hostdata->options |= OPTION_DEBUG_PROBE_ONLY;
+ printk (KERN_ALERT "scsi%d: disabled. Unload and reload\n",
+ host->host_no);
+ /* Should see that pending commands return errors too */
+ return 0;
+}
+
/*
* Function : static int halt (struct Scsi_Host *host)
@@ -3932,13 +3975,17 @@
unsigned char istat, tmp;
struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
host->hostdata;
+ int stage;
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 (;;) {
+ for (stage = 0;;) {
+ if (stage == 1) {
+ NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
+ ++stage;
+ }
istat = NCR53c7x0_read8 (hostdata->istat);
if (istat & ISTAT_SIP) {
if ((hostdata->chip / 100) == 8) {
@@ -3949,13 +3996,20 @@
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", host->host_no);
+ if (stage == 2) {
+ if (tmp & DSTAT_ABRT)
+ NCR53c7x0_write8(hostdata->istat, 0);
+ else {
+ printk(KERN_ALERT "scsi%d: could not halt NCR chip\n",
+ host->host_no);
+ disable (host);
+ }
+ }
+ break;
}
+ if (stage == 0 && !(istat & (ISTAT_SIP|ISTAT_DIP)))
+ ++stage;
}
hostdata->state = STATE_HALTED;
restore_flags(flags);
--- 53c7,8xx.h 1995/06/23 05:58:11 1.1
+++ 53c7,8xx.h 1995/06/27 19:29:24
@@ -58,7 +58,7 @@
#define NCR53c7xx_release NULL
#endif
-#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 4)", NCR53c7xx_detect, \
+#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 5)", NCR53c7xx_detect, \
NULL, /* info */ NULL, /* command, deprecated */ NULL, \
NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset, \
NULL /* slave attach */, scsicam_bios_param, /* can queue */ 1, \
@@ -1362,10 +1362,10 @@
if (hostdata->options & OPTION_DEBUG_DSA) \
printk("scsi : dsa %s symbol %s(%ld) word %d now 0x%lx\n", \
#dsa, #symbol, (long) hostdata->##symbol, \
- (int) (word), (long) (value)); \
+ (int) (word), (long) (value)); \
}
-
+#define FATAL(host) shutdown((host));
#endif /* NCR53c7x0_C */
#endif /* NCR53c7x0_H */