patch-2.3.7 linux/drivers/acorn/scsi/acornscsi.c

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

diff -u --recursive --new-file v2.3.6/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
@@ -21,6 +21,8 @@
  *  12-Oct-1997	RMK	Added catch for re-entering interrupt routine.
  *  15-Oct-1997	RMK	Improved handling of commands.
  *  27-Jun-1998	RMK	Changed asm/delay.h to linux/delay.h.
+ *  13-Dec-1998	RMK	Better abort code and command handling.  Extra state
+ *			transitions added to allow dodgy devices to work.
  */
 #define DEBUG_NO_WRITE	1
 #define DEBUG_QUEUES	2
@@ -35,7 +37,7 @@
 #define DEBUG_RESET	1024
 #define DEBUG_ALL	(DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\
 			 DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\
-			 DEBUG_DMA|DEBUG_QUEUES|DEBUG_NO_WRITE)
+			 DEBUG_DMA|DEBUG_QUEUES)
 
 /* DRIVER CONFIGURATION
  *
@@ -123,8 +125,8 @@
 #ifndef STRINGIFY
 #define STRINGIFY(x) #x
 #endif
-#define STR(x) STRINGIFY(x)
-#define NO_WRITE_STR STR(NO_WRITE)
+#define STRx(x) STRINGIFY(x)
+#define NO_WRITE_STR STRx(NO_WRITE)
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -142,6 +144,7 @@
 #include <asm/bitops.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/ecard.h>
 
 #include "../../scsi/scsi.h"
@@ -160,10 +163,6 @@
 #error "Yippee!  ABORT TAG is now defined!  Remove this error!"
 #endif
 
-#ifndef NO_IRQ
-#define NO_IRQ 255
-#endif
-
 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
 #error SCSI2 LINKed commands not supported (yet)!
 #endif
@@ -186,26 +185,7 @@
 #define DMAC_BUFFER_SIZE	65536
 #endif
 
-/*
- * This is used to dump the previous states of the SBIC
- */
-static struct status_entry {
-	unsigned long	when;
-	unsigned char	ssr;
-	unsigned char	ph;
-	unsigned char	irq;
-	unsigned char	unused;
-} status[9][16];
-static unsigned char status_ptr[9];
-
-#define ADD_STATUS(_q,_ssr,_ph,_irq) \
-({							\
-	status[(_q)][status_ptr[(_q)]].when = jiffies;	\
-	status[(_q)][status_ptr[(_q)]].ssr  = (_ssr);	\
-	status[(_q)][status_ptr[(_q)]].ph   = (_ph);	\
-	status[(_q)][status_ptr[(_q)]].irq  = (_irq);	\
-	status_ptr[(_q)] = (status_ptr[(_q)] + 1) & 15;	\
-})
+#define STATUS_BUFFER_TO_PRINT	24
 
 unsigned int sdtr_period = SDTR_PERIOD;
 unsigned int sdtr_size   = SDTR_SIZE;
@@ -214,31 +194,31 @@
 	PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-static void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
-static int acornscsi_reconnect_finish (AS_Host *host);
-static void acornscsi_dma_cleanup (AS_Host *host);
-static void acornscsi_abortcmd (AS_Host *host, unsigned char tag);
+static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
+static int acornscsi_reconnect_finish(AS_Host *host);
+static void acornscsi_dma_cleanup(AS_Host *host);
+static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
 
 /* ====================================================================================
  * Miscellaneous
  */
 
 static inline void
-sbic_arm_write (unsigned int io_port, int reg, int value)
+sbic_arm_write(unsigned int io_port, int reg, int value)
 {
-    outb_t (reg, io_port);
-    outb_t (value, io_port + 4);
+    outb_t(reg, io_port);
+    outb_t(value, io_port + 4);
 }
 
 #define sbic_arm_writenext(io,val) \
-	outb_t ((val), (io) + 4)
+	outb_t((val), (io) + 4)
 
 static inline
-int sbic_arm_read (unsigned int io_port, int reg)
+int sbic_arm_read(unsigned int io_port, int reg)
 {
     if(reg == ASR)
 	   return inl_t(io_port) & 255;
-    outb_t (reg, io_port);
+    outb_t(reg, io_port);
     return inl_t(io_port + 4) & 255;
 }
 
@@ -247,129 +227,165 @@
 
 #ifdef USE_DMAC
 #define dmac_read(io_port,reg) \
-	inb ((io_port) + (reg))
+	inb((io_port) + (reg))
 
 #define dmac_write(io_port,reg,value) \
-	({ outb ((value), (io_port) + (reg)); })
+	({ outb((value), (io_port) + (reg)); })
 
 #define dmac_clearintr(io_port) \
-	({ outb (0, (io_port)); })
+	({ outb(0, (io_port)); })
 
 static inline
-unsigned int dmac_address (unsigned int io_port)
+unsigned int dmac_address(unsigned int io_port)
 {
-    return dmac_read (io_port, TXADRHI) << 16 |
-	   dmac_read (io_port, TXADRMD) << 8 |
-	   dmac_read (io_port, TXADRLO);
+    return dmac_read(io_port, TXADRHI) << 16 |
+	   dmac_read(io_port, TXADRMD) << 8 |
+	   dmac_read(io_port, TXADRLO);
 }
 
 static
-void acornscsi_dumpdma (AS_Host *host, char *where)
+void acornscsi_dumpdma(AS_Host *host, char *where)
 {
 	unsigned int mode, addr, len;
 
-	mode = dmac_read (host->dma.io_port, MODECON);
-	addr = dmac_address (host->dma.io_port);
-	len  = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
-	       dmac_read (host->dma.io_port, TXCNTLO);
+	mode = dmac_read(host->dma.io_port, MODECON);
+	addr = dmac_address(host->dma.io_port);
+	len  = dmac_read(host->dma.io_port, TXCNTHI) << 8 |
+	       dmac_read(host->dma.io_port, TXCNTLO);
 
-	printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
+	printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
 		host->host->host_no, where,
 		mode, addr, (len + 1) & 0xffff,
-		dmac_read (host->dma.io_port, MASKREG));
+		dmac_read(host->dma.io_port, MASKREG));
 
-	printk ("DMA @%06x, ", host->dma.start_addr);
-	printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
+	printk("DMA @%06x, ", host->dma.start_addr);
+	printk("BH @%p +%04x, ", host->scsi.SCp.ptr,
 		host->scsi.SCp.this_residual);
-	printk ("DT @+%04x ST @+%04x", host->dma.transferred,
+	printk("DT @+%04x ST @+%04x", host->dma.transferred,
 		host->scsi.SCp.scsi_xferred);
-	printk ("\n");
+	printk("\n");
 }
 #endif
 
 static
-unsigned long acornscsi_sbic_xfcount (AS_Host *host)
+unsigned long acornscsi_sbic_xfcount(AS_Host *host)
 {
     unsigned long length;
 
-    length = sbic_arm_read (host->scsi.io_port, TRANSCNTH) << 16;
-    length |= sbic_arm_readnext (host->scsi.io_port) << 8;
-    length |= sbic_arm_readnext (host->scsi.io_port);
+    length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16;
+    length |= sbic_arm_readnext(host->scsi.io_port) << 8;
+    length |= sbic_arm_readnext(host->scsi.io_port);
 
     return length;
 }
 
-static
-int acornscsi_sbic_issuecmd (AS_Host *host, int command)
+static int
+acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
 {
-    int asr;
+	int asr;
 
-    do {
-	asr = sbic_arm_read (host->scsi.io_port, ASR);
-    } while (asr & ASR_CIP);
+	do {
+		asr = sbic_arm_read(host->scsi.io_port, ASR);
+
+		if ((asr & stat_mask) == stat)
+			return 0;
+
+		udelay(1);
+	} while (--timeout);
+
+	printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
+
+	return -1;
+}
 
-    sbic_arm_write (host->scsi.io_port, CMND, command);
+static
+int acornscsi_sbic_issuecmd(AS_Host *host, int command)
+{
+    if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
+	return -1;
+
+    sbic_arm_write(host->scsi.io_port, CMND, command);
 
     return 0;
 }
 
 static void
-acornscsi_csdelay (unsigned int cs)
+acornscsi_csdelay(unsigned int cs)
 {
     unsigned long target_jiffies, flags;
 
     target_jiffies = jiffies + 1 + cs * HZ / 100;
 
-    save_flags (flags);
-    sti ();
+    save_flags(flags);
+    sti();
 
     while (time_before(jiffies, target_jiffies)) barrier();
 
-    restore_flags (flags);
+    restore_flags(flags);
 }
 
 static
-void acornscsi_resetcard (AS_Host *host)
+void acornscsi_resetcard(AS_Host *host)
 {
-    unsigned int i;
+    unsigned int i, timeout;
 
     /* assert reset line */
     host->card.page_reg = 0x80;
-    outb (host->card.page_reg, host->card.io_page);
+    outb(host->card.page_reg, host->card.io_page);
 
     /* wait 3 cs.  SCSI standard says 25ms. */
-    acornscsi_csdelay (3);
+    acornscsi_csdelay(3);
 
     host->card.page_reg = 0;
-    outb (host->card.page_reg, host->card.io_page);
+    outb(host->card.page_reg, host->card.io_page);
 
     /*
      * Should get a reset from the card
      */
-    while (!(inb (host->card.io_intr) & 8));
-    sbic_arm_read (host->scsi.io_port, ASR);
-    sbic_arm_read (host->scsi.io_port, SSR);
+    timeout = 1000;
+    do {
+	if (inb(host->card.io_intr) & 8)
+	    break;
+	udelay(1);
+    } while (--timeout);
+
+    if (timeout == 0)
+	printk("scsi%d: timeout while resetting card\n",
+		host->host->host_no);
+
+    sbic_arm_read(host->scsi.io_port, ASR);
+    sbic_arm_read(host->scsi.io_port, SSR);
 
     /* setup sbic - WD33C93A */
-    sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
-    sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET);
+    sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
+    sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
 
     /*
      * Command should cause a reset interrupt
      */
-    while (!(inb (host->card.io_intr) & 8));
-    sbic_arm_read (host->scsi.io_port, ASR);
-    if (sbic_arm_read (host->scsi.io_port, SSR) != 0x01)
-	printk (KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
+    timeout = 1000;
+    do {
+	if (inb(host->card.io_intr) & 8)
+	    break;
+	udelay(1);
+    } while (--timeout);
+
+    if (timeout == 0)
+	printk("scsi%d: timeout while resetting card\n",
 		host->host->host_no);
 
-    sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
-    sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
-    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
-    sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+    sbic_arm_read(host->scsi.io_port, ASR);
+    if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01)
+	printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
+		host->host->host_no);
+
+    sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
+    sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
+    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
+    sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
 
     host->card.page_reg = 0x40;
-    outb (host->card.page_reg, host->card.io_page);
+    outb(host->card.page_reg, host->card.io_page);
 
     /* setup dmac - uPC71071 */
     dmac_write(host->dma.io_port, INIT, 0);
@@ -391,7 +407,7 @@
     }
 
     /* wait 25 cs.  SCSI standard says 250ms. */
-    acornscsi_csdelay (25);
+    acornscsi_csdelay(25);
 }
 
 /*=============================================================================================
@@ -461,80 +477,101 @@
 };
 
 static
-void print_scsi_status (unsigned int ssr)
+void print_scsi_status(unsigned int ssr)
 {
     if (acornscsi_map[ssr] != -1)
-	printk ("%s:%s",
+	printk("%s:%s",
 		acornscsi_interrupttype[(ssr >> 4)],
 		acornscsi_interruptcode[acornscsi_map[ssr]]);
     else
-	printk ("%X:%X", ssr >> 4, ssr & 0x0f);    
+	printk("%X:%X", ssr >> 4, ssr & 0x0f);    
 }    
 #endif
 
 static
-void print_sbic_status (int asr, int ssr, int cmdphase)
+void print_sbic_status(int asr, int ssr, int cmdphase)
 {
 #ifdef CONFIG_ACORNSCSI_CONSTANTS
-    printk ("sbic: %c%c%c%c%c%c ",
+    printk("sbic: %c%c%c%c%c%c ",
 	    asr & ASR_INT ? 'I' : 'i',
 	    asr & ASR_LCI ? 'L' : 'l',
 	    asr & ASR_BSY ? 'B' : 'b',
 	    asr & ASR_CIP ? 'C' : 'c',
 	    asr & ASR_PE  ? 'P' : 'p',
 	    asr & ASR_DBR ? 'D' : 'd');
-    printk ("scsi: ");
-    print_scsi_status (ssr);
-    printk (" ph %02X\n", cmdphase);
+    printk("scsi: ");
+    print_scsi_status(ssr);
+    printk(" ph %02X\n", cmdphase);
 #else
-    printk ("sbic: %02X scsi: %X:%X ph: %02X\n",
+    printk("sbic: %02X scsi: %X:%X ph: %02X\n",
 	    asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);
 #endif
 }
 
-static
-void acornscsi_dumplog (AS_Host *host, int target)
+static void
+acornscsi_dumplogline(AS_Host *host, int target, int line)
 {
-    unsigned int prev;
-    do {
-	signed int statptr;
+	unsigned long prev;
+	signed int ptr;
 
-	printk ("%c:", target == 8 ? 'H' : ('0' + target));
-	statptr = status_ptr[target] - 10;
+	ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT;
+	if (ptr < 0)
+		ptr += STATUS_BUFFER_SIZE;
 
-	if (statptr < 0)
-	    statptr += 16;
+	printk("%c: %3s:", target == 8 ? 'H' : '0' + target,
+		line == 0 ? "ph" : line == 1 ? "ssr" : "int");
 
-	prev = status[target][statptr].when;
+	prev = host->status[target][ptr].when;
 
-	for (; statptr != status_ptr[target]; statptr = (statptr + 1) & 15) {
-	    if (status[target][statptr].when) {
-#ifdef CONFIG_ACORNSCSI_CONSTANTS
-		printk ("%c%02X:S=",
-			status[target][statptr].irq ? '-' : ' ',
-			status[target][statptr].ph);
-		print_scsi_status (status[target][statptr].ssr);
-#else
-		printk ("%c%02X:%02X",
-			status[target][statptr].irq ? '-' : ' ',
-			status[target][statptr].ph,
-			status[target][statptr].ssr);
-#endif
-		printk ("+%02ld",
-			(status[target][statptr].when - prev) < 100 ?
-				(status[target][statptr].when - prev) : 99);
-		prev = status[target][statptr].when;
-	    }
+	for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
+		unsigned long time_diff;
+
+		if (!host->status[target][ptr].when)
+			continue;
+
+		switch (line) {
+		case 0:
+			printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ',
+					 host->status[target][ptr].ph);
+			break;
+
+		case 1:
+			printk(" %02X", host->status[target][ptr].ssr);
+			break;
+
+		case 2:
+			time_diff = host->status[target][ptr].when - prev;
+			prev = host->status[target][ptr].when;
+			if (time_diff == 0)
+				printk("==^");
+			else if (time_diff >= 100)
+				printk("   ");
+			else
+				printk(" %02ld", time_diff);
+			break;
+		}
 	}
-	printk ("\n");
+
+	printk("\n");
+}
+
+static
+void acornscsi_dumplog(AS_Host *host, int target)
+{
+    do {
+	acornscsi_dumplogline(host, target, 0);
+	acornscsi_dumplogline(host, target, 1);
+	acornscsi_dumplogline(host, target, 2);
+
 	if (target == 8)
 	    break;
+
 	target = 8;
     } while (1);
 }
 
 static
-char acornscsi_target (AS_Host *host)
+char acornscsi_target(AS_Host *host)
 {
 	if (host->SCpnt)
 		return '0' + host->SCpnt->target;
@@ -542,7 +579,7 @@
 }
 
 /*
- * Prototype: cmdtype_t acornscsi_cmdtype (int command)
+ * Prototype: cmdtype_t acornscsi_cmdtype(int command)
  * Purpose  : differentiate READ from WRITE from other commands
  * Params   : command - command to interpret
  * Returns  : CMD_READ	- command reads data,
@@ -550,7 +587,7 @@
  *	      CMD_MISC	- everything else
  */
 static inline
-cmdtype_t acornscsi_cmdtype (int command)
+cmdtype_t acornscsi_cmdtype(int command)
 {
     switch (command) {
     case WRITE_6:  case WRITE_10:  case WRITE_12:
@@ -563,7 +600,7 @@
 }
 
 /*
- * Prototype: int acornscsi_datadirection (int command)
+ * Prototype: int acornscsi_datadirection(int command)
  * Purpose  : differentiate between commands that have a DATA IN phase
  *	      and a DATA OUT phase
  * Params   : command - command to interpret
@@ -571,7 +608,7 @@
  *	      DATADIR_IN  - data in phase expected
  */
 static
-datadir_t acornscsi_datadirection (int command)
+datadir_t acornscsi_datadirection(int command)
 {
     switch (command) {
     case CHANGE_DEFINITION:	case COMPARE:		case COPY:
@@ -605,13 +642,13 @@
 };
 
 /*
- * Prototype: int acornscsi_getperiod (unsigned char syncxfer)
+ * Prototype: int acornscsi_getperiod(unsigned char syncxfer)
  * Purpose  : period for the synchronous transfer setting
  * Params   : syncxfer SYNCXFER register value
  * Returns  : period in ns.
  */
 static
-int acornscsi_getperiod (unsigned char syncxfer)
+int acornscsi_getperiod(unsigned char syncxfer)
 {
     int i;
 
@@ -626,14 +663,14 @@
 }
 
 /*
- * Prototype: int round_period (unsigned int period)
+ * Prototype: int round_period(unsigned int period)
  * Purpose  : return index into above table for a required REQ period
  * Params   : period - time (ns) for REQ
  * Returns  : table index
  * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
  */
 static inline
-int round_period (unsigned int period)
+int round_period(unsigned int period)
 {
     int i;
 
@@ -646,7 +683,7 @@
 }
 
 /*
- * Prototype: unsigned char calc_sync_xfer (unsigned int period, unsigned int offset)
+ * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
  * Purpose  : calculate value for 33c93s SYNC register
  * Params   : period - time (ns) for REQ
  *	      offset - offset in bytes between REQ/ACK
@@ -654,7 +691,7 @@
  * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
  */
 static
-unsigned char calc_sync_xfer (unsigned int period, unsigned int offset)
+unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
 {
     return sync_xfer_table[round_period(period)].reg_value |
 		((offset < SDTR_SIZE) ? offset : SDTR_SIZE);
@@ -664,14 +701,14 @@
  * Command functions
  */
 /*
- * Function: acornscsi_kick (AS_Host *host)
+ * Function: acornscsi_kick(AS_Host *host)
  * Purpose : kick next command to interface
  * Params  : host - host to send command to
  * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING
  * Notes   : interrupts are always disabled!
  */
 static
-intr_ret_t acornscsi_kick (AS_Host *host)
+intr_ret_t acornscsi_kick(AS_Host *host)
 {
     int from_queue = 0;
     Scsi_Cmnd *SCpnt;
@@ -682,7 +719,7 @@
 
     /* retrieve next command */
     if (!SCpnt) {
-	SCpnt = queue_remove_exclude (&host->queues.issue, host->busyluns);
+	SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns);
 	if (!SCpnt)
 	    return INTR_IDLE;
 
@@ -690,11 +727,11 @@
     }
 
     if (host->scsi.disconnectable && host->SCpnt) {
-	queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt);
+	queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
 	host->scsi.disconnectable = 0;
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-	DBG(host->SCpnt, printk ("scsi%d.%c: moved command to disconnected queue\n",
-		host->host->host_no, acornscsi_target (host)));
+	DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n",
+		host->host->host_no, acornscsi_target(host)));
 #endif
 	host->SCpnt = NULL;
     }
@@ -703,9 +740,9 @@
      * If we have an interrupt pending, then we may have been reselected.
      * In this case, we don't want to write to the registers
      */
-    if (!(sbic_arm_read (host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
-	sbic_arm_write (host->scsi.io_port, DESTID, SCpnt->target);
-	sbic_arm_write (host->scsi.io_port, CMND, CMND_SELWITHATN);
+    if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
+	sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target);
+	sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN);
     }
 
     /*
@@ -717,9 +754,10 @@
     host->scsi.SCp = SCpnt->SCp;
     host->dma.xfer_setup = 0;
     host->dma.xfer_required = 0;
+    host->dma.xfer_done = 0;
 
 #if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT))
-    DBG(SCpnt,printk ("scsi%d.%c: starting cmd %02X\n",
+    DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n",
 	    host->host->host_no, '0' + SCpnt->target,
 	    SCpnt->cmnd[0]));
 #endif
@@ -736,11 +774,11 @@
 	    SCpnt->tag = SCpnt->device->current_tag;
 	} else
 #endif
-	    set_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+	    set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
 
 	host->stats.removes += 1;
 
-	switch (acornscsi_cmdtype (SCpnt->cmnd[0])) {
+	switch (acornscsi_cmdtype(SCpnt->cmnd[0])) {
 	case CMD_WRITE:
 	    host->stats.writes += 1;
 	    break;
@@ -757,25 +795,25 @@
 }    
 
 /*
- * Function: void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+ * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
  * Purpose : complete processing for command
  * Params  : host   - interface that completed
  *	     result - driver byte of result
  */
 static
-void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
 {
     Scsi_Cmnd *SCpnt = *SCpntp;
 
     /* clean up */
-    sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+    sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
 
     host->stats.fins += 1;
 
     if (SCpnt) {
 	*SCpntp = NULL;
 
-	acornscsi_dma_cleanup (host);
+	acornscsi_dma_cleanup(host);
 
 	SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status;
 
@@ -787,35 +825,63 @@
 	 * It doesn't appear to be set to something meaningful by the higher
 	 * levels all the time.
 	 */
-	if (host->scsi.SCp.ptr && result == DID_OK &&
-		acornscsi_cmdtype (SCpnt->cmnd[0]) != CMD_MISC) {
-	    switch (status_byte (SCpnt->result)) {
-	    case CHECK_CONDITION:
-	    case COMMAND_TERMINATED:
-	    case BUSY:
-	    case QUEUE_FULL:
-	    case RESERVATION_CONFLICT:
-		break;
+	if (result == DID_OK) {
+		int xfer_warn = 0;
 
-	    default:
-		printk (KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
-			host->host->host_no, SCpnt->result);
-		print_command (SCpnt->cmnd);
-		acornscsi_dumpdma (host, "done");
-	 	acornscsi_dumplog (host, SCpnt->target);
-		SCpnt->result &= 0xffff;
-		SCpnt->result |= DID_ERROR << 16;
-	    }
+		if (SCpnt->underflow == 0) {
+			if (host->scsi.SCp.ptr &&
+			    acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC)
+				xfer_warn = 1;
+		} else {
+			if (host->scsi.SCp.scsi_xferred < SCpnt->underflow ||
+			    host->scsi.SCp.scsi_xferred != host->dma.transferred)
+				xfer_warn = 1;
+		}
+
+		/* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6)
+		 *  Targets which break data transfers into multiple
+		 *  connections shall end each successful connection
+		 *  (except possibly the last) with a SAVE DATA
+		 *  POINTER - DISCONNECT message sequence.
+		 *
+		 * This makes it difficult to ensure that a transfer has
+		 * completed.  If we reach the end of a transfer during
+		 * the command, then we can only have finished the transfer.
+		 * therefore, if we seem to have some data remaining, this
+		 * is not a problem.
+		 */
+		if (host->dma.xfer_done)
+			xfer_warn = 0;
+
+		if (xfer_warn) {
+		    switch (status_byte(SCpnt->result)) {
+		    case CHECK_CONDITION:
+		    case COMMAND_TERMINATED:
+		    case BUSY:
+		    case QUEUE_FULL:
+		    case RESERVATION_CONFLICT:
+			break;
+
+		    default:
+			printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
+				host->host->host_no, SCpnt->result);
+			print_command(SCpnt->cmnd);
+			acornscsi_dumpdma(host, "done");
+		 	acornscsi_dumplog(host, SCpnt->target);
+			SCpnt->result &= 0xffff;
+			SCpnt->result |= DID_ERROR << 16;
+		    }
+		}
 	}
 
 	if (!SCpnt->scsi_done)
-	    panic ("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
+	    panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
 
-	clear_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+	clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
 
-	SCpnt->scsi_done (SCpnt);
+	SCpnt->scsi_done(SCpnt);
     } else
-	printk ("scsi%d: null command in acornscsi_done", host->host->host_no);
+	printk("scsi%d: null command in acornscsi_done", host->host->host_no);
 
     host->scsi.phase = PHASE_IDLE;
 }
@@ -828,7 +894,7 @@
  * Notes    : this will only be one SG entry or less
  */
 static
-void acornscsi_data_updateptr (AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
+void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
 {
     SCp->ptr += length;
     SCp->this_residual -= length;
@@ -839,13 +905,15 @@
 	    SCp->buffers_residual--;
 	    SCp->ptr = (char *)SCp->buffer->address;
 	    SCp->this_residual = SCp->buffer->length;
-	} else
+	} else {
 	    SCp->ptr = NULL;
+	    host->dma.xfer_done = 1;
+	}
     }
 }
 
 /*
- * Prototype: void acornscsi_data_read (AS_Host *host, char *ptr,
+ * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
  *				unsigned int start_addr, unsigned int length)
  * Purpose  : read data from DMA RAM
  * Params   : host - host to transfer from
@@ -855,16 +923,16 @@
  * Notes    : this will only be one SG entry or less
  */
 static
-void acornscsi_data_read (AS_Host *host, char *ptr,
+void acornscsi_data_read(AS_Host *host, char *ptr,
 				 unsigned int start_addr, unsigned int length)
 {
-    extern void __acornscsi_in (int port, char *buf, int len);
+    extern void __acornscsi_in(int port, char *buf, int len);
     unsigned int page, offset, len = length;
 
     page = (start_addr >> 12);
     offset = start_addr & ((1 << 12) - 1);
 
-    outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
 
     while (len > 0) {
 	unsigned int this_len;
@@ -874,7 +942,7 @@
 	else
 	    this_len = len;
 
-	__acornscsi_in (host->card.io_ram + (offset << 1), ptr, this_len);
+	__acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
 
 	offset += this_len;
 	ptr += this_len;
@@ -883,14 +951,14 @@
 	if (offset == (1 << 12)) {
 	    offset = 0;
 	    page ++;
-	    outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+	    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
 	}
     }
-    outb (host->card.page_reg, host->card.io_page);
+    outb(host->card.page_reg, host->card.io_page);
 }
 
 /*
- * Prototype: void acornscsi_data_write (AS_Host *host, char *ptr,
+ * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
  *				unsigned int start_addr, unsigned int length)
  * Purpose  : write data to DMA RAM
  * Params   : host - host to transfer from
@@ -900,16 +968,16 @@
  * Notes    : this will only be one SG entry or less
  */
 static
-void acornscsi_data_write (AS_Host *host, char *ptr,
+void acornscsi_data_write(AS_Host *host, char *ptr,
 				 unsigned int start_addr, unsigned int length)
 {
-    extern void __acornscsi_out (int port, char *buf, int len);
+    extern void __acornscsi_out(int port, char *buf, int len);
     unsigned int page, offset, len = length;
 
     page = (start_addr >> 12);
     offset = start_addr & ((1 << 12) - 1);
 
-    outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
 
     while (len > 0) {
 	unsigned int this_len;
@@ -919,7 +987,7 @@
 	else
 	    this_len = len;
 
-	__acornscsi_out (host->card.io_ram + (offset << 1), ptr, this_len);
+	__acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
 
 	offset += this_len;
 	ptr += this_len;
@@ -928,10 +996,10 @@
 	if (offset == (1 << 12)) {
 	    offset = 0;
 	    page ++;
-	    outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+	    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
 	}
     }
-    outb (host->card.page_reg, host->card.io_page);
+    outb(host->card.page_reg, host->card.io_page);
 }
 
 /* =========================================================================================
@@ -939,25 +1007,25 @@
  */
 #ifdef USE_DMAC
 /*
- * Prototype: void acornscsi_dmastop (AS_Host *host)
+ * Prototype: void acornscsi_dmastop(AS_Host *host)
  * Purpose  : stop all DMA
  * Params   : host - host on which to stop DMA
  * Notes    : This is called when leaving DATA IN/OUT phase,
  *	      or when interface is RESET
  */
 static inline
-void acornscsi_dma_stop (AS_Host *host)
+void acornscsi_dma_stop(AS_Host *host)
 {
-    dmac_write (host->dma.io_port, MASKREG, MASK_ON);
-    dmac_clearintr (host->dma.io_intr_clear);
+    dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+    dmac_clearintr(host->dma.io_intr_clear);
 
 #if (DEBUG & DEBUG_DMA)
-    DBG(host->SCpnt, acornscsi_dumpdma (host, "stop"));
+    DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
 #endif
 }
 
 /*
- * Function: void acornscsi_dma_setup (AS_Host *host, dmadir_t direction)
+ * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
  * Purpose : setup DMA controller for data transfer
  * Params  : host - host to setup
  *	     direction - data transfer direction
@@ -965,19 +1033,19 @@
  *	     while we're in a DATA I/O phase
  */
 static
-void acornscsi_dma_setup (AS_Host *host, dmadir_t direction)
+void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
 {
     unsigned int address, length, mode;
 
     host->dma.direction = direction;
 
-    dmac_write (host->dma.io_port, MASKREG, MASK_ON);
+    dmac_write(host->dma.io_port, MASKREG, MASK_ON);
 
     if (direction == DMA_OUT) {
 #if (DEBUG & DEBUG_NO_WRITE)
 	if (NO_WRITE & (1 << host->SCpnt->target)) {
-	    printk (KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
-		    host->host->host_no, acornscsi_target (host));
+	    printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
+		    host->host->host_no, acornscsi_target(host));
 	    return;
 	}
 #endif
@@ -988,7 +1056,7 @@
     /*
      * Allocate some buffer space, limited to half the buffer size
      */
-    length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
+    length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
     if (length) {
 	host->dma.start_addr = address = host->dma.free_addr;
 	host->dma.free_addr = (host->dma.free_addr + length) &
@@ -998,27 +1066,27 @@
 	 * Transfer data to DMA memory
 	 */
 	if (direction == DMA_OUT)
-	    acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr,
+	    acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
 				length);
 
 	length -= 1;
-	dmac_write (host->dma.io_port, TXCNTLO, length);
-	dmac_write (host->dma.io_port, TXCNTHI, length >> 8);
-	dmac_write (host->dma.io_port, TXADRLO, address);
-	dmac_write (host->dma.io_port, TXADRMD, address >> 8);
-	dmac_write (host->dma.io_port, TXADRHI, 0);
-	dmac_write (host->dma.io_port, MODECON, mode);
-	dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+	dmac_write(host->dma.io_port, TXCNTLO, length);
+	dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
+	dmac_write(host->dma.io_port, TXADRLO, address);
+	dmac_write(host->dma.io_port, TXADRMD, address >> 8);
+	dmac_write(host->dma.io_port, TXADRHI, 0);
+	dmac_write(host->dma.io_port, MODECON, mode);
+	dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
 
 #if (DEBUG & DEBUG_DMA)
-	DBG(host->SCpnt, acornscsi_dumpdma (host, "strt"));
+	DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
 #endif
 	host->dma.xfer_setup = 1;
     }
 }
 
 /*
- * Function: void acornscsi_dma_cleanup (AS_Host *host)
+ * Function: void acornscsi_dma_cleanup(AS_Host *host)
  * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
  * Params  : host - host to finish
  * Notes   : This is called when a command is:
@@ -1026,10 +1094,10 @@
  *	   : This must not return until all transfers are completed.
  */
 static
-void acornscsi_dma_cleanup (AS_Host *host)
+void acornscsi_dma_cleanup(AS_Host *host)
 {
-    dmac_write (host->dma.io_port, MASKREG, MASK_ON);
-    dmac_clearintr (host->dma.io_intr_clear);
+    dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+    dmac_clearintr(host->dma.io_intr_clear);
 
     /*
      * Check for a pending transfer
@@ -1037,7 +1105,7 @@
     if (host->dma.xfer_required) {
 	host->dma.xfer_required = 0;
 	if (host->dma.direction == DMA_IN)
-	    acornscsi_data_read (host, host->dma.xfer_ptr,
+	    acornscsi_data_read(host, host->dma.xfer_ptr,
 				 host->dma.xfer_start, host->dma.xfer_length);
     }
 
@@ -1056,17 +1124,17 @@
 	/*
 	 * Calculate number of bytes transferred from DMA.
 	 */
-	transferred = dmac_address (host->dma.io_port) - host->dma.start_addr;
+	transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
 	host->dma.transferred += transferred;
 
 	if (host->dma.direction == DMA_IN)
-	    acornscsi_data_read (host, host->scsi.SCp.ptr,
+	    acornscsi_data_read(host, host->scsi.SCp.ptr,
 				 host->dma.start_addr, transferred);
 
 	/*
 	 * Update SCSI pointers
 	 */
-	acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+	acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
 #if (DEBUG & DEBUG_DMA)
 	DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
 #endif
@@ -1074,7 +1142,7 @@
 }
 
 /*
- * Function: void acornscsi_dmacintr (AS_Host *host)
+ * Function: void acornscsi_dmacintr(AS_Host *host)
  * Purpose : handle interrupts from DMAC device
  * Params  : host - host to process
  * Notes   : If reading, we schedule the read to main memory &
@@ -1084,21 +1152,21 @@
  *	   : Called whenever DMAC finished it's current transfer.
  */
 static
-void acornscsi_dma_intr (AS_Host *host)
+void acornscsi_dma_intr(AS_Host *host)
 {
     unsigned int address, length, transferred;
 
 #if (DEBUG & DEBUG_DMA)
-    DBG(host->SCpnt, acornscsi_dumpdma (host, "inti"));
+    DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
 #endif
 
-    dmac_write (host->dma.io_port, MASKREG, MASK_ON);
-    dmac_clearintr (host->dma.io_intr_clear);
+    dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+    dmac_clearintr(host->dma.io_intr_clear);
 
     /*
      * Calculate amount transferred via DMA
      */
-    transferred = dmac_address (host->dma.io_port) - host->dma.start_addr;
+    transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
     host->dma.transferred += transferred;
 
     /*
@@ -1111,12 +1179,12 @@
 	host->dma.xfer_required = 1;
     }
 
-    acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+    acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
 
     /*
      * Allocate some buffer space, limited to half the on-board RAM size
      */
-    length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
+    length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
     if (length) {
 	host->dma.start_addr = address = host->dma.free_addr;
 	host->dma.free_addr = (host->dma.free_addr + length) &
@@ -1126,19 +1194,19 @@
 	 * Transfer data to DMA memory
 	 */
 	if (host->dma.direction == DMA_OUT)
-	    acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr,
+	    acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
 				length);
 
 	length -= 1;
-	dmac_write (host->dma.io_port, TXCNTLO, length);
-	dmac_write (host->dma.io_port, TXCNTHI, length >> 8);
-	dmac_write (host->dma.io_port, TXADRLO, address);
-	dmac_write (host->dma.io_port, TXADRMD, address >> 8);
-	dmac_write (host->dma.io_port, TXADRHI, 0);
-	dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+	dmac_write(host->dma.io_port, TXCNTLO, length);
+	dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
+	dmac_write(host->dma.io_port, TXADRLO, address);
+	dmac_write(host->dma.io_port, TXADRMD, address >> 8);
+	dmac_write(host->dma.io_port, TXADRHI, 0);
+	dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
 
 #if (DEBUG & DEBUG_DMA)
-	DBG(host->SCpnt, acornscsi_dumpdma (host, "into"));
+	DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
 #endif
     } else {
 	host->dma.xfer_setup = 0;
@@ -1149,48 +1217,48 @@
 	 * attention condition.  We continue giving one byte until
 	 * the device recognises the attention.
 	 */
-	if (dmac_read (host->dma.io_port, STATUS) & STATUS_RQ0) {
-	    acornscsi_abortcmd (host, host->SCpnt->tag);
+	if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) {
+	    acornscsi_abortcmd(host, host->SCpnt->tag);
 
-	    dmac_write (host->dma.io_port, TXCNTLO, 0);
-	    dmac_write (host->dma.io_port, TXCNTHI, 0);
-	    dmac_write (host->dma.io_port, TXADRLO, 0);
-	    dmac_write (host->dma.io_port, TXADRMD, 0);
-	    dmac_write (host->dma.io_port, TXADRHI, 0);
-	    dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+	    dmac_write(host->dma.io_port, TXCNTLO, 0);
+	    dmac_write(host->dma.io_port, TXCNTHI, 0);
+	    dmac_write(host->dma.io_port, TXADRLO, 0);
+	    dmac_write(host->dma.io_port, TXADRMD, 0);
+	    dmac_write(host->dma.io_port, TXADRHI, 0);
+	    dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
 	}
 #endif
     }
 }
 
 /*
- * Function: void acornscsi_dma_xfer (AS_Host *host)
+ * Function: void acornscsi_dma_xfer(AS_Host *host)
  * Purpose : transfer data between AcornSCSI and memory
  * Params  : host - host to process
  */
 static
-void acornscsi_dma_xfer (AS_Host *host)
+void acornscsi_dma_xfer(AS_Host *host)
 {
     host->dma.xfer_required = 0;
 
     if (host->dma.direction == DMA_IN)
-	acornscsi_data_read (host, host->dma.xfer_ptr,
+	acornscsi_data_read(host, host->dma.xfer_ptr,
 				host->dma.xfer_start, host->dma.xfer_length);
 }
 
 /*
- * Function: void acornscsi_dma_adjust (AS_Host *host)
+ * Function: void acornscsi_dma_adjust(AS_Host *host)
  * Purpose : adjust DMA pointers & count for bytes transfered to
  *	     SBIC but not SCSI bus.
  * Params  : host - host to adjust DMA count for
  */
 static
-void acornscsi_dma_adjust (AS_Host *host)
+void acornscsi_dma_adjust(AS_Host *host)
 {
     if (host->dma.xfer_setup) {
 	signed long transferred;
 #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
-	DBG(host->SCpnt, acornscsi_dumpdma (host, "adji"));
+	DBG(host->SCpnt, acornscsi_dumpdma(host, "adji"));
 #endif
 	/*
 	 * Calculate correct DMA address - DMA is ahead of SCSI bus while
@@ -1205,17 +1273,17 @@
 	 */
 	transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
 	if (transferred < 0)
-	    printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
-		    host->host->host_no, acornscsi_target (host), transferred);
+	    printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
+		    host->host->host_no, acornscsi_target(host), transferred);
 	else if (transferred == 0)
 	    host->dma.xfer_setup = 0;
 	else {
 	    transferred += host->dma.start_addr;
-	    dmac_write (host->dma.io_port, TXADRLO, transferred);
-	    dmac_write (host->dma.io_port, TXADRMD, transferred >> 8);
-	    dmac_write (host->dma.io_port, TXADRHI, transferred >> 16);
+	    dmac_write(host->dma.io_port, TXADRLO, transferred);
+	    dmac_write(host->dma.io_port, TXADRMD, transferred >> 8);
+	    dmac_write(host->dma.io_port, TXADRHI, transferred >> 16);
 #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
-	    DBG(host->SCpnt, acornscsi_dumpdma (host, "adjo"));
+	    DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo"));
 #endif
 	}
     }
@@ -1225,66 +1293,88 @@
 /* =========================================================================================
  * Data I/O
  */
+static int
+acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
+{
+	unsigned int asr, timeout = max_timeout;
+	int my_ptr = *ptr;
+
+	while (my_ptr < len) {
+		asr = sbic_arm_read(host->scsi.io_port, ASR);
+
+		if (asr & ASR_DBR) {
+			timeout = max_timeout;
+
+			sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]);
+		} else if (asr & ASR_INT)
+			break;
+		else if (--timeout == 0)
+			break;
+		udelay(1);
+	}
+
+	*ptr = my_ptr;
+
+	return (timeout == 0) ? -1 : 0;
+}
+
 /*
- * Function: void acornscsi_sendcommand (AS_Host *host)
+ * Function: void acornscsi_sendcommand(AS_Host *host)
  * Purpose : send a command to a target
  * Params  : host - host which is connected to target
  */
-static
-void acornscsi_sendcommand (AS_Host *host)
+static void
+acornscsi_sendcommand(AS_Host *host)
 {
     Scsi_Cmnd *SCpnt = host->SCpnt;
-    unsigned int asr;
-    unsigned char *cmdptr, *cmdend;
 
-    sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0);
-    sbic_arm_writenext (host->scsi.io_port, 0);
-    sbic_arm_writenext (host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
-    acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
-
-    cmdptr = SCpnt->cmnd + host->scsi.SCp.sent_command;
-    cmdend = SCpnt->cmnd + SCpnt->cmd_len;
-
-    while (cmdptr < cmdend) {
-	asr = sbic_arm_read (host->scsi.io_port, ASR);
-	if (asr & ASR_DBR)
-	    sbic_arm_write (host->scsi.io_port, DATA, *cmdptr++);
-	else if (asr & ASR_INT)
-	    break;
-    }
-    if (cmdptr >= cmdend)
-	host->scsi.SCp.sent_command = cmdptr - SCpnt->cmnd;
+    sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
+    sbic_arm_writenext(host->scsi.io_port, 0);
+    sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
+
+    acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
+
+    if (acornscsi_write_pio(host, SCpnt->cmnd,
+	(int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000))
+	printk("scsi%d: timeout while sending command\n", host->host->host_no);
+
     host->scsi.phase = PHASE_COMMAND;
 }
 
 static
-void acornscsi_sendmessage (AS_Host *host)
+void acornscsi_sendmessage(AS_Host *host)
 {
-    unsigned int message_length = msgqueue_msglength (&host->scsi.msgs);
-    int msgnr;
+    unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
+    unsigned int msgnr;
     struct message *msg;
 
 #if (DEBUG & DEBUG_MESSAGES)
-    printk ("scsi%d.%c: sending message ",
-	    host->host->host_no, acornscsi_target (host));
+    printk("scsi%d.%c: sending message ",
+	    host->host->host_no, acornscsi_target(host));
 #endif
 
     switch (message_length) {
     case 0:
-	acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
-	while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
-	sbic_arm_write (host->scsi.io_port, DATA, NOP);
+	acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
+
+	acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
+
+	sbic_arm_write(host->scsi.io_port, DATA, NOP);
+
 	host->scsi.last_message = NOP;
 #if (DEBUG & DEBUG_MESSAGES)
-	printk ("NOP");
+	printk("NOP");
 #endif
 	break;
 
     case 1:
-	acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
+	acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
 	msg = msgqueue_getmsg(&host->scsi.msgs, 0);
-	while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
-	sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]);
+
+	acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
+
+	sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]);
+
 	host->scsi.last_message = msg->msg[0];
 #if (DEBUG & DEBUG_MESSAGES)
 	print_msg(msg->msg);
@@ -1300,86 +1390,85 @@
 	 *  initiator.  This provides an interlock so that the
 	 *  initiator can determine which message byte is rejected.
 	 */
-	sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0);
-	sbic_arm_writenext (host->scsi.io_port, 0);
-	sbic_arm_writenext (host->scsi.io_port, message_length);
-	acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
+	sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
+	sbic_arm_writenext(host->scsi.io_port, 0);
+	sbic_arm_writenext(host->scsi.io_port, message_length);
+	acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
 
 	msgnr = 0;
 	while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
-	    unsigned int asr, i;
+	    unsigned int i;
 #if (DEBUG & DEBUG_MESSAGES)
-	    print_msg (msg);
+	    print_msg(msg);
 #endif
-	    for (i = 0; i < msg->length;) {
-		asr = sbic_arm_read (host->scsi.io_port, ASR);
-		if (asr & ASR_DBR)
-		    sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]);
-		if (asr & ASR_INT)
-		    break;
-	    }
+	    i = 0;
+	    if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
+		printk("scsi%d: timeout while sending message\n", host->host->host_no);
+
 	    host->scsi.last_message = msg->msg[0];
 	    if (msg->msg[0] == EXTENDED_MESSAGE)
 		host->scsi.last_message |= msg->msg[2] << 8;
-	    if (asr & ASR_INT)
+
+	    if (i != msg->length)
 		break;
 	}
 	break;
     }
 #if (DEBUG & DEBUG_MESSAGES)
-    printk ("\n");
+    printk("\n");
 #endif
 }
 
 /*
- * Function: void acornscsi_readstatusbyte (AS_Host *host)
+ * Function: void acornscsi_readstatusbyte(AS_Host *host)
  * Purpose : Read status byte from connected target
  * Params  : host - host connected to target
  */
 static
-void acornscsi_readstatusbyte (AS_Host *host)
+void acornscsi_readstatusbyte(AS_Host *host)
 {
-    acornscsi_sbic_issuecmd (host, CMND_XFERINFO|CMND_SBT);
-    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
-
-    host->scsi.SCp.Status = sbic_arm_read (host->scsi.io_port, DATA);
+    acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT);
+    acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte");
+    host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA);
 }
 
 /*
- * Function: unsigned char acornscsi_readmessagebyte (AS_Host *host)
+ * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
  * Purpose : Read one message byte from connected target
  * Params  : host - host connected to target
  */
 static
-unsigned char acornscsi_readmessagebyte (AS_Host *host)
+unsigned char acornscsi_readmessagebyte(AS_Host *host)
 {
     unsigned char message;
 
-    acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
-    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
+    acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
+
+    acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
 
-    message = sbic_arm_read (host->scsi.io_port, DATA);
+    message = sbic_arm_read(host->scsi.io_port, DATA);
 
     /* wait for MSGIN-XFER-PAUSED */
-    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);
-    sbic_arm_read (host->scsi.io_port, SSR);
+    acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
+
+    sbic_arm_read(host->scsi.io_port, SSR);
 
     return message;
 }
 
 /*
- * Function: void acornscsi_message (AS_Host *host)
+ * Function: void acornscsi_message(AS_Host *host)
  * Purpose : Read complete message from connected target & action message
  * Params  : host - host connected to target
  */
 static
-void acornscsi_message (AS_Host *host)
+void acornscsi_message(AS_Host *host)
 {
     unsigned char message[16];
     unsigned int msgidx = 0, msglen = 1;
 
     do {
-	message[msgidx] = acornscsi_readmessagebyte (host);
+	message[msgidx] = acornscsi_readmessagebyte(host);
 
 	switch (msgidx) {
 	case 0:
@@ -1395,17 +1484,17 @@
 	}
 	msgidx += 1;
 	if (msgidx < msglen) {
-	    acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+	    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
 
 	    /* wait for next msg-in */
-	    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);
-	    sbic_arm_read (host->scsi.io_port, SSR);
+	    acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack");
+	    sbic_arm_read(host->scsi.io_port, SSR);
 	}
     } while (msgidx < msglen);
 
 #if (DEBUG & DEBUG_MESSAGES)
     printk("scsi%d.%c: message in: ",
-	    host->host->host_no, acornscsi_target (host));
+	    host->host->host_no, acornscsi_target(host));
     print_msg(message);
     printk("\n");
 #endif
@@ -1419,7 +1508,7 @@
 	 */
 	if (message[0] == SIMPLE_QUEUE_TAG)
 	    host->scsi.reconnected.tag = message[1];
-	if (acornscsi_reconnect_finish (host))
+	if (acornscsi_reconnect_finish(host))
 	    host->scsi.phase = PHASE_MSGIN;
     }
 
@@ -1429,7 +1518,7 @@
     case COMMAND_COMPLETE:
 	if (host->scsi.phase != PHASE_STATUSIN) {
 	    printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
-		    host->host->host_no, acornscsi_target (host));
+		    host->host->host_no, acornscsi_target(host));
 	    acornscsi_dumplog(host, host->SCpnt->target);
 	}
 	host->scsi.phase = PHASE_DONE;
@@ -1443,7 +1532,7 @@
 	 *  direct the initiator to copy the active data pointer to
 	 *  the saved data pointer for the current I/O process.
 	 */
-	acornscsi_dma_cleanup (host);
+	acornscsi_dma_cleanup(host);
 	host->SCpnt->SCp = host->scsi.SCp;
 	host->SCpnt->SCp.sent_command = 0;
 	host->scsi.phase = PHASE_MSGIN;
@@ -1459,7 +1548,7 @@
 	 *  status pointers shall be restored to the beginning of
 	 *  the present command and status areas.'
 	 */
-	acornscsi_dma_cleanup (host);
+	acornscsi_dma_cleanup(host);
 	host->scsi.SCp = host->SCpnt->SCp;
 	host->scsi.phase = PHASE_MSGIN;
 	break;
@@ -1474,7 +1563,7 @@
 	 *  message.  When reconnection is completed, the most recent
 	 *  saved pointer values are restored.'
 	 */
-	acornscsi_dma_cleanup (host);
+	acornscsi_dma_cleanup(host);
 	host->scsi.phase = PHASE_DISCONNECT;
 	break;
 
@@ -1493,8 +1582,8 @@
 	/*
 	 * If we have any messages waiting to go out, then assert ATN now
 	 */
-	if (msgqueue_msglength (&host->scsi.msgs))
-	    acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
+	if (msgqueue_msglength(&host->scsi.msgs))
+	    acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
 
 	switch (host->scsi.last_message) {
 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
@@ -1507,21 +1596,21 @@
 	     *  message is received, it shall respond with a MESSAGE REJECT
 	     *  message and accept the I/O process as if it were untagged.
 	     */
-	    printk (KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
-		    host->host->host_no, acornscsi_target (host));
+	    printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
+		    host->host->host_no, acornscsi_target(host));
 	    host->SCpnt->device->tagged_queue = 0;
-	    set_bit (host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
+	    set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
 	    break;
 #endif
 	case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
 	    /*
 	     * Target can't handle synchronous transfers
 	     */
-	    printk (KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
-		    host->host->host_no, acornscsi_target (host));
+	    printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
+		    host->host->host_no, acornscsi_target(host));
 	    host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA;
 	    host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS;
-	    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
 	    break;
 
 	default:
@@ -1535,8 +1624,8 @@
 
     case SIMPLE_QUEUE_TAG:
 	/* tag queue reconnect... message[1] = queue tag.  Print something to indicate something happened! */
-	printk ("scsi%d.%c: reconnect queue tag %02X\n",
-		host->host->host_no, acornscsi_target (host),
+	printk("scsi%d.%c: reconnect queue tag %02X\n",
+		host->host->host_no, acornscsi_target(host),
 		message[1]);
 	break;
 
@@ -1552,26 +1641,26 @@
 		 * and the target retries fail, then we fallback to asynchronous mode
 		 */
 		host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;
-		printk (KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
+		printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
 			host->host->host_no, acornscsi_target(host),
 			message[4], message[3] * 4);
 		host->device[host->SCpnt->target].sync_xfer =
-			calc_sync_xfer (message[3] * 4, message[4]);
+			calc_sync_xfer(message[3] * 4, message[4]);
 	    } else {
 		unsigned char period, length;
 		/*
 		 * Target requested synchronous transfers.  The agreement is only
 		 * to be in operation AFTER the target leaves message out phase.
 		 */
-		acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
-		period = max (message[3], sdtr_period / 4);
-		length = min (message[4], sdtr_size);
-		msgqueue_addmsg (&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
+		acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+		period = max(message[3], sdtr_period / 4);
+		length = min(message[4], sdtr_size);
+		msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
 				 EXTENDED_SDTR, period, length);
 		host->device[host->SCpnt->target].sync_xfer =
-			calc_sync_xfer (period * 4, length);
+			calc_sync_xfer(period * 4, length);
 	    }
-	    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
 	    break;
 #else
 	    /* We do not accept synchronous transfers.  Respond with a
@@ -1584,9 +1673,9 @@
 	     * to a wide data transfer request.
 	     */
 	default:
-	    acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
-	    msgqueue_flush (&host->scsi.msgs);
-	    msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);
+	    acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+	    msgqueue_flush(&host->scsi.msgs);
+	    msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
 	    break;
 	}
 	break;
@@ -1607,19 +1696,19 @@
 	     * if there are more linked commands available.
 	     */
 	    if (!host->SCpnt->next_link) {
-		printk (KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
-			instance->host_no, acornscsi_target (host), host->SCpnt->tag);
-		acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
-		msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
+		printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
+			instance->host_no, acornscsi_target(host), host->SCpnt->tag);
+		acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+		msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
 	    } else {
 		Scsi_Cmnd *SCpnt = host->SCpnt;
 
-		acornscsi_dma_cleanup (host);
+		acornscsi_dma_cleanup(host);
 
 		host->SCpnt = host->SCpnt->next_link;
 		host->SCpnt->tag = SCpnt->tag;
 		SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;
-		SCpnt->done (SCpnt);
+		SCpnt->done(SCpnt);
 
 		/* initialise host->SCpnt->SCp */
 	    }
@@ -1628,42 +1717,42 @@
 #endif
 
     default: /* reject message */
-	printk (KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
-		host->host->host_no, acornscsi_target (host),
+	printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
+		host->host->host_no, acornscsi_target(host),
 		message[0]);
-	acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
-	msgqueue_flush (&host->scsi.msgs);
-	msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);
+	acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+	msgqueue_flush(&host->scsi.msgs);
+	msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
 	host->scsi.phase = PHASE_MSGIN;
 	break;
     }
-    acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
 }
 
 /*
- * Function: int acornscsi_buildmessages (AS_Host *host)
+ * Function: int acornscsi_buildmessages(AS_Host *host)
  * Purpose : build the connection messages for a host
  * Params  : host - host to add messages to
  */
 static
-void acornscsi_buildmessages (AS_Host *host)
+void acornscsi_buildmessages(AS_Host *host)
 {
 #if 0
     /* does the device need resetting? */
     if (cmd_reset) {
-	msgqueue_addmsg (&host->scsi.msgs, 1, BUS_DEVICE_RESET);
+	msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
 	return;
     }
 #endif
 
-    msgqueue_addmsg (&host->scsi.msgs, 1,
+    msgqueue_addmsg(&host->scsi.msgs, 1,
 		     IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,
 			     host->SCpnt->lun));
 
 #if 0
     /* does the device need the current command aborted */
     if (cmd_aborted) {
-	acornscsi_abortcmd (host->SCpnt->tag);
+	acornscsi_abortcmd(host->SCpnt->tag);
 	return;
     }
 #endif
@@ -1678,14 +1767,14 @@
 	    tag_type = HEAD_OF_QUEUE_TAG;
 	else
 	    tag_type = SIMPLE_QUEUE_TAG;
-	msgqueue_addmsg (&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
+	msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
     }
 #endif
 
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) {
 	host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST;
-	msgqueue_addmsg (&host->scsi.msgs, 5,
+	msgqueue_addmsg(&host->scsi.msgs, 5,
 			 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
 			 sdtr_period / 4, sdtr_size);
     }
@@ -1693,29 +1782,29 @@
 }
 
 /*
- * Function: int acornscsi_starttransfer (AS_Host *host)
+ * Function: int acornscsi_starttransfer(AS_Host *host)
  * Purpose : transfer data to/from connected target
  * Params  : host - host to which target is connected
  * Returns : 0 if failure
  */
 static
-int acornscsi_starttransfer (AS_Host *host)
+int acornscsi_starttransfer(AS_Host *host)
 {
     int residual;
 
     if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {
-	printk (KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
-		host->host->host_no, acornscsi_target (host));
+	printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
+		host->host->host_no, acornscsi_target(host));
 	return 0;
     }
 
     residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
 
-    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
-    sbic_arm_writenext (host->scsi.io_port, residual >> 16);
-    sbic_arm_writenext (host->scsi.io_port, residual >> 8);
-    sbic_arm_writenext (host->scsi.io_port, residual);
-    acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
+    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+    sbic_arm_writenext(host->scsi.io_port, residual >> 16);
+    sbic_arm_writenext(host->scsi.io_port, residual >> 8);
+    sbic_arm_writenext(host->scsi.io_port, residual);
+    acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
     return 1;
 }
 
@@ -1723,7 +1812,7 @@
  * Connection & Disconnection
  */
 /*
- * Function : acornscsi_reconnect (AS_Host *host)
+ * Function : acornscsi_reconnect(AS_Host *host)
  * Purpose  : reconnect a previously disconnected command
  * Params   : host - host specific data
  * Remarks  : SCSI spec says:
@@ -1731,27 +1820,27 @@
  *		 of saved pointers upon reconnection of the I/O process'
  */
 static
-int acornscsi_reconnect (AS_Host *host)
+int acornscsi_reconnect(AS_Host *host)
 {
     unsigned int target, lun, ok = 0;
 
-    target = sbic_arm_read (host->scsi.io_port, SOURCEID);
+    target = sbic_arm_read(host->scsi.io_port, SOURCEID);
 
     if (!(target & 8))
-	printk (KERN_ERR "scsi%d: invalid source id after reselection "
+	printk(KERN_ERR "scsi%d: invalid source id after reselection "
 		"- device fault?\n",
 		host->host->host_no);
 
     target &= 7;
 
     if (host->SCpnt && !host->scsi.disconnectable) {
-	printk (KERN_ERR "scsi%d.%d: reconnected while command in "
+	printk(KERN_ERR "scsi%d.%d: reconnected while command in "
 		"progress to target %d?\n",
 		host->host->host_no, target, host->SCpnt->target);
 	host->SCpnt = NULL;
     }
 
-    lun = sbic_arm_read (host->scsi.io_port, DATA) & 7;
+    lun = sbic_arm_read(host->scsi.io_port, DATA) & 7;
 
     host->scsi.reconnected.target = target;
     host->scsi.reconnected.lun = lun;
@@ -1761,7 +1850,7 @@
 	host->SCpnt->target == target && host->SCpnt->lun == lun)
 	ok = 1;
 
-    if (!ok && queue_probetgtlun (&host->queues.disconnected, target, lun))
+    if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
 	ok = 1;
 
     ADD_STATUS(target, 0x81, host->scsi.phase, 0);
@@ -1770,26 +1859,28 @@
 	host->scsi.phase = PHASE_RECONNECTED;
     } else {
 	/* this doesn't seem to work */
-	printk (KERN_ERR "scsi%d.%c: reselected with no command "
+	printk(KERN_ERR "scsi%d.%c: reselected with no command "
 		"to reconnect with\n",
 		host->host->host_no, '0' + target);
-	acornscsi_dumplog (host, target);
-	acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
-	msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
-	host->scsi.phase = PHASE_ABORTED;
+	acornscsi_dumplog(host, target);
+	acornscsi_abortcmd(host, 0);
+	if (host->SCpnt) {
+	    queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
+	    host->SCpnt = NULL;
+	}
     }
-    acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
     return !ok;
 }
 
 /*
- * Function: int acornscsi_reconect_finish (AS_Host *host)
+ * Function: int acornscsi_reconect_finish(AS_Host *host)
  * Purpose : finish reconnecting a command
  * Params  : host - host to complete
  * Returns : 0 if failed
  */
 static
-int acornscsi_reconnect_finish (AS_Host *host)
+int acornscsi_reconnect_finish(AS_Host *host)
 {
     if (host->scsi.disconnectable && host->SCpnt) {
 	host->scsi.disconnectable = 0;
@@ -1797,45 +1888,44 @@
 	    host->SCpnt->lun	== host->scsi.reconnected.lun &&
 	    host->SCpnt->tag	== host->scsi.reconnected.tag) {
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-	    DBG(host->SCpnt, printk ("scsi%d.%c: reconnected",
-		    host->host->host_no, acornscsi_target (host)));
+	    DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
+		    host->host->host_no, acornscsi_target(host)));
 #endif
 	} else {
-	    queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt);
+	    queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-	    DBG(host->SCpnt, printk ("scsi%d.%c: had to move command "
+	    DBG(host->SCpnt, printk("scsi%d.%c: had to move command "
 		    "to disconnected queue\n",
-		    host->host->host_no, acornscsi_target (host)));
+		    host->host->host_no, acornscsi_target(host)));
 #endif
 	    host->SCpnt = NULL;
 	}
     }
     if (!host->SCpnt) {
-	host->SCpnt = queue_remove_tgtluntag (&host->queues.disconnected,
+	host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected,
 				host->scsi.reconnected.target,
 				host->scsi.reconnected.lun,
 				host->scsi.reconnected.tag);
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-	DBG(host->SCpnt, printk ("scsi%d.%c: had to get command",
-		host->host->host_no, acornscsi_target (host)));
+	DBG(host->SCpnt, printk("scsi%d.%c: had to get command",
+		host->host->host_no, acornscsi_target(host)));
 #endif
     }
 
-    if (!host->SCpnt) {
-	acornscsi_abortcmd (host, host->scsi.reconnected.tag);
-	host->scsi.phase = PHASE_ABORTED;
-    } else {
+    if (!host->SCpnt)
+	acornscsi_abortcmd(host, host->scsi.reconnected.tag);
+    else {
 	/*
 	 * Restore data pointer from SAVED pointers.
 	 */
 	host->scsi.SCp = host->SCpnt->SCp;
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-	printk (", data pointers: [%p, %X]",
+	printk(", data pointers: [%p, %X]",
 		host->scsi.SCp.ptr, host->scsi.SCp.this_residual);
 #endif
     }
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
-    printk ("\n");
+    printk("\n");
 #endif
 
     host->dma.transferred = host->scsi.SCp.scsi_xferred;
@@ -1844,47 +1934,48 @@
 }
 
 /*
- * Function: void acornscsi_disconnect_unexpected (AS_Host *host)
+ * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
  * Purpose : handle an unexpected disconnect
  * Params  : host - host on which disconnect occurred
  */
 static
-void acornscsi_disconnect_unexpected (AS_Host *host)
+void acornscsi_disconnect_unexpected(AS_Host *host)
 {
-    printk (KERN_ERR "scsi%d.%c: unexpected disconnect\n",
-	    host->host->host_no, acornscsi_target (host));
+    printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n",
+	    host->host->host_no, acornscsi_target(host));
 #if (DEBUG & DEBUG_ABORT)
-    acornscsi_dumplog (host, 8);
+    acornscsi_dumplog(host, 8);
 #endif
 
-    acornscsi_done (host, &host->SCpnt, DID_ABORT);
+    acornscsi_done(host, &host->SCpnt, DID_ERROR);
 }
 
 /*
- * Function: void acornscsi_abortcmd (AS_host *host, unsigned char tag)
+ * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
  * Purpose : abort a currently executing command
  * Params  : host - host with connected command to abort
  *	     tag  - tag to abort
  */
 static
-void acornscsi_abortcmd (AS_Host *host, unsigned char tag)
+void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
 {
-    sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);
+    host->scsi.phase = PHASE_ABORTED;
+    sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN);
 
-    msgqueue_flush (&host->scsi.msgs);
+    msgqueue_flush(&host->scsi.msgs);
 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
     if (tag)
-	msgqueue_addmsg (&host->scsi.msgs, 2, ABORT_TAG, tag);
+	msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
     else
 #endif
-	msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
+	msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
 }
 
 /* ==========================================================================================
  * Interrupt routines.
  */
 /*
- * Function: int acornscsi_sbicintr (AS_Host *host)
+ * Function: int acornscsi_sbicintr(AS_Host *host)
  * Purpose : handle interrupts from SCSI device
  * Params  : host - host to process
  * Returns : INTR_PROCESS if expecting another SBIC interrupt
@@ -1892,15 +1983,15 @@
  *	     INTR_NEXT_COMMAND if we have finished processing the command
  */
 static
-intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
+intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
 {
     unsigned int asr, ssr;
 
-    asr = sbic_arm_read (host->scsi.io_port, ASR);
+    asr = sbic_arm_read(host->scsi.io_port, ASR);
     if (!(asr & ASR_INT))
 	return INTR_IDLE;
 
-    ssr = sbic_arm_read (host->scsi.io_port, SSR);
+    ssr = sbic_arm_read(host->scsi.io_port, SSR);
 
 #if (DEBUG & DEBUG_PHASES)
     print_sbic_status(asr, ssr, host->scsi.phase);
@@ -1913,23 +2004,23 @@
 
     switch (ssr) {
     case 0x00:				/* reset state - not advanced			*/
-	printk (KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
+	printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
 		host->host->host_no);
 	/* setup sbic - WD33C93A */
-	sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
-	sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET);
+	sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
+	sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
 	return INTR_IDLE;
 
     case 0x01:				/* reset state - advanced			*/
-	sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
-	sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
-	sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
-	sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
-	msgqueue_flush (&host->scsi.msgs);
+	sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
+	sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
+	sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
+	sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+	msgqueue_flush(&host->scsi.msgs);
 	return INTR_IDLE;
 
     case 0x41:				/* unexpected disconnect aborted command	*/
-	acornscsi_disconnect_unexpected (host);
+	acornscsi_disconnect_unexpected(host);
 	return INTR_NEXT_COMMAND;
     }
 
@@ -1939,35 +2030,35 @@
 	case 0x11:			/* -> PHASE_CONNECTED				*/
 	    /* BUS FREE -> SELECTION */
 	    host->scsi.phase = PHASE_CONNECTED;
-	    msgqueue_flush (&host->scsi.msgs);
+	    msgqueue_flush(&host->scsi.msgs);
 	    host->dma.transferred = host->scsi.SCp.scsi_xferred;
 	    /* 33C93 gives next interrupt indicating bus phase */
-	    asr = sbic_arm_read (host->scsi.io_port, ASR);
+	    asr = sbic_arm_read(host->scsi.io_port, ASR);
 	    if (!(asr & ASR_INT))
 		break;
-	    ssr = sbic_arm_read (host->scsi.io_port, SSR);
+	    ssr = sbic_arm_read(host->scsi.io_port, SSR);
 	    ADD_STATUS(8, ssr, host->scsi.phase, 1);
 	    ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1);
 	    goto connected;
 	    
 	case 0x42:			/* select timed out				*/
 					/* -> PHASE_IDLE				*/
-	    acornscsi_done (host, &host->SCpnt, DID_NO_CONNECT);
+	    acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
 	    return INTR_NEXT_COMMAND;
 
 	case 0x81:			/* -> PHASE_RECONNECTED or PHASE_ABORTED	*/
 	    /* BUS FREE -> RESELECTION */
 	    host->origSCpnt = host->SCpnt;
 	    host->SCpnt = NULL;
-	    msgqueue_flush (&host->scsi.msgs);
-	    acornscsi_reconnect (host);
+	    msgqueue_flush(&host->scsi.msgs);
+	    acornscsi_reconnect(host);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
-	    acornscsi_abortcmd (host, host->SCpnt->tag);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	}
 	return INTR_PROCESSING;
 
@@ -1977,12 +2068,12 @@
 #ifdef NONSTANDARD
 	case 0x8a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
 	    /* SELECTION -> COMMAND */
-	    acornscsi_sendcommand (host);
+	    acornscsi_sendcommand(host);
 	    break;
 
 	case 0x8b:			/* -> PHASE_STATUS				*/
 	    /* SELECTION -> STATUS */
-	    acornscsi_readstatusbyte (host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 #endif
@@ -1990,55 +2081,57 @@
 	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* SELECTION ->MESSAGE OUT */
 	    host->scsi.phase = PHASE_MSGOUT;
-	    acornscsi_buildmessages (host);
-	    acornscsi_sendmessage (host);
+	    acornscsi_buildmessages(host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	/* these should not happen */
 	case 0x85:			/* target disconnected				*/
-	    acornscsi_done (host, &host->SCpnt, DID_ERROR);
+	    acornscsi_done(host, &host->SCpnt, DID_ERROR);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
-	    acornscsi_abortcmd (host, host->SCpnt->tag);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	}
 	return INTR_PROCESSING;
 
     case PHASE_MSGOUT:			/* STATE: connected & sent IDENTIFY message	*/
 	/*
-	 * SCSI standard says th at a MESSAGE OUT phases can be followed by a DATA phase
+	 * SCSI standard says that MESSAGE OUT phases can be followed by a
+	 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
 	 */
 	switch (ssr) {
-	case 0x8a:
+	case 0x8a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
 	case 0x1a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
 	    /* MESSAGE OUT -> COMMAND */
-	    acornscsi_sendcommand (host);
+	    acornscsi_sendcommand(host);
 	    break;
 
+	case 0x8b:			/* -> PHASE_STATUS				*/
 	case 0x1b:			/* -> PHASE_STATUS				*/
 	    /* MESSAGE OUT -> STATUS */
-	    acornscsi_readstatusbyte (host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 
 	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
-        case 0x4f:
+	case 0x4f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	    /* MESSAGE OUT -> MESSAGE IN */
-	    acornscsi_message (host);
+	    acornscsi_message(host);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2047,43 +2140,43 @@
 	case 0x18:			/* -> PHASE_DATAOUT				*/
 	    /* COMMAND -> DATA OUT */
 	    if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
-		acornscsi_abortcmd (host, host->SCpnt->tag);
-	    acornscsi_dma_setup (host, DMA_OUT);
-	    if (!acornscsi_starttransfer (host))
-		acornscsi_abortcmd (host, host->SCpnt->tag);
+		acornscsi_abortcmd(host, host->SCpnt->tag);
+	    acornscsi_dma_setup(host, DMA_OUT);
+	    if (!acornscsi_starttransfer(host))
+		acornscsi_abortcmd(host, host->SCpnt->tag);
 	    host->scsi.phase = PHASE_DATAOUT;
 	    return INTR_IDLE;
 
 	case 0x19:			/* -> PHASE_DATAIN				*/
 	    /* COMMAND -> DATA IN */
 	    if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
-		acornscsi_abortcmd (host, host->SCpnt->tag);
-	    acornscsi_dma_setup (host, DMA_IN);
-	    if (!acornscsi_starttransfer (host))
-		acornscsi_abortcmd (host, host->SCpnt->tag);
+		acornscsi_abortcmd(host, host->SCpnt->tag);
+	    acornscsi_dma_setup(host, DMA_IN);
+	    if (!acornscsi_starttransfer(host))
+		acornscsi_abortcmd(host, host->SCpnt->tag);
 	    host->scsi.phase = PHASE_DATAIN;
 	    return INTR_IDLE;
 
 	case 0x1b:			/* -> PHASE_STATUS				*/
 	    /* COMMAND -> STATUS */
-	    acornscsi_readstatusbyte (host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	    /* COMMAND -> MESSAGE OUT */
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	    /* COMMAND -> MESSAGE IN */
-	    acornscsi_message (host);
+	    acornscsi_message(host);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2094,19 +2187,19 @@
 	    host->scsi.phase = PHASE_IDLE;
 	    host->stats.disconnects += 1;
 	} else {
-	    printk (KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_NEXT_COMMAND;
 
     case PHASE_IDLE:			/* STATE: disconnected				*/
 	if (ssr == 0x81)		/* -> PHASE_RECONNECTED or PHASE_ABORTED	*/
-	    acornscsi_reconnect (host);
+	    acornscsi_reconnect(host);
 	else {
-	    printk (KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2119,54 +2212,54 @@
 	 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
 	 * reconnect I_T_L command
 	 */
-	if (ssr != 0x8f && !acornscsi_reconnect_finish (host))
+	if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
 	    return INTR_IDLE;
 	ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
 	switch (ssr) {
 	case 0x88:			/* data out phase				*/
 					/* -> PHASE_DATAOUT				*/
 	    /* MESSAGE IN -> DATA OUT */
-	    acornscsi_dma_setup (host, DMA_OUT);
-	    if (!acornscsi_starttransfer (host))
-		acornscsi_abortcmd (host, host->SCpnt->tag);
+	    acornscsi_dma_setup(host, DMA_OUT);
+	    if (!acornscsi_starttransfer(host))
+		acornscsi_abortcmd(host, host->SCpnt->tag);
 	    host->scsi.phase = PHASE_DATAOUT;
 	    return INTR_IDLE;
 
 	case 0x89:			/* data in phase				*/
 					/* -> PHASE_DATAIN				*/
 	    /* MESSAGE IN -> DATA IN */
-	    acornscsi_dma_setup (host, DMA_IN);
-	    if (!acornscsi_starttransfer (host))
-		acornscsi_abortcmd (host, host->SCpnt->tag);
+	    acornscsi_dma_setup(host, DMA_IN);
+	    if (!acornscsi_starttransfer(host))
+		acornscsi_abortcmd(host, host->SCpnt->tag);
 	    host->scsi.phase = PHASE_DATAIN;
 	    return INTR_IDLE;
 
 	case 0x8a:			/* command out					*/
 	    /* MESSAGE IN -> COMMAND */
-	    acornscsi_sendcommand (host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
+	    acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
 	    break;
 
 	case 0x8b:			/* status in					*/
 					/* -> PHASE_STATUSIN				*/
 	    /* MESSAGE IN -> STATUS */
-	    acornscsi_readstatusbyte (host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 
 	case 0x8e:			/* message out					*/
 					/* -> PHASE_MSGOUT				*/
 	    /* MESSAGE IN -> MESSAGE OUT */
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	case 0x8f:			/* message in					*/
-	    acornscsi_message (host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
+	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2177,41 +2270,45 @@
 	 */
 	switch (ssr) {
 	case 0x19:			/* -> PHASE_DATAIN				*/
-	    acornscsi_abortcmd (host, host->SCpnt->tag);
+	case 0x89:			/* -> PHASE_DATAIN				*/
+	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	    return INTR_IDLE;
 
-	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x1b:			/* -> PHASE_STATUSIN				*/
+	case 0x4b:			/* -> PHASE_STATUSIN				*/
+	case 0x8b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA IN -> STATUS */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_readstatusbyte (host);
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
+	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA IN -> MESSAGE OUT */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_sendmessage (host);
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	case 0x1f:			/* message in					*/
 	case 0x4f:			/* message in					*/
+	case 0x8f:			/* message in					*/
 	    /* DATA IN -> MESSAGE IN */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_message (host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2222,58 +2319,69 @@
 	 */
 	switch (ssr) {
 	case 0x18:			/* -> PHASE_DATAOUT				*/
-	    acornscsi_abortcmd (host, host->SCpnt->tag);
+	case 0x88:			/* -> PHASE_DATAOUT				*/
+	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	    return INTR_IDLE;
 
-	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x1b:			/* -> PHASE_STATUSIN				*/
+	case 0x4b:			/* -> PHASE_STATUSIN				*/
+	case 0x8b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA OUT -> STATUS */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_dma_adjust (host);
-	    acornscsi_readstatusbyte (host);
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_dma_adjust(host);
+	    acornscsi_readstatusbyte(host);
 	    host->scsi.phase = PHASE_STATUSIN;
 	    break;
 
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
+	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA OUT -> MESSAGE OUT */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_dma_adjust (host);
-	    acornscsi_sendmessage (host);
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_dma_adjust(host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	case 0x1f:			/* message in					*/
 	case 0x4f:			/* message in					*/
+	case 0x8f:			/* message in					*/
 	    /* DATA OUT -> MESSAGE IN */
 	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
-					  acornscsi_sbic_xfcount (host);
-	    acornscsi_dma_stop (host);
-	    acornscsi_dma_adjust (host);
-	    acornscsi_message (host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
+					  acornscsi_sbic_xfcount(host);
+	    acornscsi_dma_stop(host);
+	    acornscsi_dma_adjust(host);
+	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
     case PHASE_STATUSIN:		/* STATE: status in complete			*/
-	if (ssr == 0x1f)		/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
+	switch (ssr) {
+	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
+	case 0x8f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
 	    /* STATUS -> MESSAGE IN */
-	    acornscsi_message (host);
-	else if (ssr == 0x1e)		/* -> PHASE_MSGOUT				*/
+	    acornscsi_message(host);
+	    break;
+
+	case 0x1e:			/* -> PHASE_MSGOUT				*/
+	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* STATUS -> MESSAGE OUT */
-	    acornscsi_sendmessage (host);
-	else {
-	    printk (KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_sendmessage(host);
+	    break;
+
+	default:
+	    printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2281,78 +2389,93 @@
 	switch (ssr) {
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
+	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* MESSAGE IN -> MESSAGE OUT */
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
 	case 0x2f:
 	case 0x4f:
 	case 0x8f:
-	    acornscsi_message (host);
+	    acornscsi_message(host);
+	    break;
+
+	case 0x85:
+	    printk("scsi%d.%c: strange message in disconnection\n",
+		host->host->host_no, acornscsi_target(host));
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_done(host, &host->SCpnt, DID_ERROR);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
     case PHASE_DONE:			/* STATE: received status & message		*/
 	switch (ssr) {
 	case 0x85:			/* -> PHASE_IDLE				*/
-	    acornscsi_done (host, &host->SCpnt, DID_OK);
+	    acornscsi_done(host, &host->SCpnt, DID_OK);
 	    return INTR_NEXT_COMMAND;
 
+	case 0x1e:
 	case 0x8e:
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
     case PHASE_ABORTED:
 	switch (ssr) {
 	case 0x85:
-	    acornscsi_done (host, &host->SCpnt, DID_ABORT);
+	    if (host->SCpnt)
+		acornscsi_done(host, &host->SCpnt, DID_ABORT);
+	    else {
+		clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
+			  host->busyluns);
+		host->scsi.phase = PHASE_IDLE;
+	    }
 	    return INTR_NEXT_COMMAND;
 
 	case 0x1e:
 	case 0x2e:
 	case 0x4e:
 	case 0x8e:
-	    acornscsi_sendmessage (host);
+	    acornscsi_sendmessage(host);
 	    break;
 
 	default:
-	    printk (KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
-		    host->host->host_no, acornscsi_target (host), ssr);
-	    acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	    printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
+		    host->host->host_no, acornscsi_target(host), ssr);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
 	}
 	return INTR_PROCESSING;
 
     default:
-	printk (KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
-		host->host->host_no, acornscsi_target (host), ssr);
-	acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+	printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
+		host->host->host_no, acornscsi_target(host), ssr);
+	acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
     }
     return INTR_PROCESSING;
 }
 
 /*
- * Prototype: void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs)
+ * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
  * Purpose  : handle interrupts from Acorn SCSI card
  * Params   : irq    - interrupt number
  *	      dev_id - device specific data (AS_Host structure)
  *	      regs   - processor registers when interrupt occurred
  */
 static
-void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs)
+void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
     AS_Host *host = (AS_Host *)dev_id;
     intr_ret_t ret;
@@ -2360,21 +2483,21 @@
     int in_irq = 0;
 
     if (host->scsi.interrupt)
-	printk ("scsi%d: interrupt re-entered\n", host->host->host_no);
+	printk("scsi%d: interrupt re-entered\n", host->host->host_no);
     host->scsi.interrupt = 1;
 
     do {
 	ret = INTR_IDLE;
 
-	iostatus = inb (host->card.io_intr);
+	iostatus = inb(host->card.io_intr);
 
 	if (iostatus & 2) {
-	    acornscsi_dma_intr (host);
-	    iostatus = inb (host->card.io_intr);
+	    acornscsi_dma_intr(host);
+	    iostatus = inb(host->card.io_intr);
 	}
 
 	if (iostatus & 8)
-	    ret = acornscsi_sbicintr (host, in_irq);
+	    ret = acornscsi_sbicintr(host, in_irq);
 
 	/*
 	 * If we have a transfer pending, start it.
@@ -2382,10 +2505,10 @@
 	 * it's data
 	 */
 	if (host->dma.xfer_required)
-	    acornscsi_dma_xfer (host);
+	    acornscsi_dma_xfer(host);
 
 	if (ret == INTR_NEXT_COMMAND)
-	    ret = acornscsi_kick (host);
+	    ret = acornscsi_kick(host);
 
 	in_irq = 1;
     } while (ret != INTR_IDLE);
@@ -2398,29 +2521,29 @@
  */
 
 /*
- * Function : acornscsi_queuecmd (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+ * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
  * Purpose  : queues a SCSI command
  * Params   : cmd  - SCSI command
  *	      done - function called on completion, with pointer to command descriptor
  * Returns  : 0, or < 0 on error.
  */
-int acornscsi_queuecmd (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
     AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
 
     if (!done) {
 	/* there should be some way of rejecting errors like this without panicing... */
-	panic ("scsi%d: queuecommand called with NULL done function [cmd=%p]",
+	panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
 		SCpnt->host->host_no, SCpnt);
 	return -EINVAL;
     }
 
 #if (DEBUG & DEBUG_NO_WRITE)
-    if (acornscsi_cmdtype (SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
-	printk (KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
+    if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
+	printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
 	    SCpnt->host->host_no, '0' + SCpnt->target);
 	SCpnt->result = DID_NO_CONNECT << 16;
-	done (SCpnt);
+	done(SCpnt);
 	return 0;
     }
 #endif
@@ -2429,7 +2552,7 @@
     SCpnt->host_scribble = NULL;
     SCpnt->result = 0;
     SCpnt->tag = 0;
-    SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]);
+    SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
     SCpnt->SCp.sent_command = 0;
     SCpnt->SCp.scsi_xferred = 0;
     SCpnt->SCp.Status = 0;
@@ -2452,21 +2575,21 @@
     {
 	unsigned long flags;
 
-	if (!queue_add_cmd_ordered (&host->queues.issue, SCpnt)) {
+	if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
 	    SCpnt->result = DID_ERROR << 16;
-	    done (SCpnt);
+	    done(SCpnt);
 	    return 0;
 	}
-	save_flags_cli (flags);
+	save_flags_cli(flags);
 	if (host->scsi.phase == PHASE_IDLE)
-	    acornscsi_kick (host);
-	restore_flags (flags);
+	    acornscsi_kick(host);
+	restore_flags(flags);
     }
     return 0;
 }
 
 /*
- * Prototype: void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+ * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
  * Purpose  : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
  * Params   : SCpntp1 - pointer to command to return
  *	      SCpntp2 - pointer to command to check
@@ -2474,7 +2597,7 @@
  * Returns  : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
  */
 static inline
-void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
 {
     Scsi_Cmnd *SCpnt = *SCpntp1;
 
@@ -2482,80 +2605,203 @@
 	*SCpntp1 = NULL;
 
 	SCpnt->result = result;
-	SCpnt->scsi_done (SCpnt);
+	SCpnt->scsi_done(SCpnt);
     }
 
     if (SCpnt == *SCpntp2)
 	*SCpntp2 = NULL;
 }
 
+enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
+
+/*
+ * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt)
+ * Purpose  : abort a command on this host
+ * Params   : SCpnt - command to abort
+ * Returns  : our abort status
+ */
+static enum res_abort
+acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
+{
+	enum res_abort res = res_not_running;
+
+	if (queue_removecmd(&host->queues.issue, SCpnt)) {
+		/*
+		 * The command was on the issue queue, and has not been
+		 * issued yet.  We can remove the command from the queue,
+		 * and acknowledge the abort.  Neither the devices nor the
+		 * interface know about the command.
+		 */
+//#if (DEBUG & DEBUG_ABORT)
+		printk("on issue queue ");
+//#endif
+		res = res_success;
+	} else if (queue_removecmd(&host->queues.disconnected, SCpnt)) {
+		/*
+		 * The command was on the disconnected queue.  Simply
+		 * acknowledge the abort condition, and when the target
+		 * reconnects, we will give it an ABORT message.  The
+		 * target should then disconnect, and we will clear
+		 * the busylun bit.
+		 */
+//#if (DEBUG & DEBUG_ABORT)
+		printk("on disconnected queue ");
+//#endif
+		res = res_success;
+	} else if (host->SCpnt == SCpnt) {
+		unsigned long flags;
+
+//#if (DEBUG & DEBUG_ABORT)
+		printk("executing ");
+//#endif
+
+		save_flags(flags);
+		cli();
+		switch (host->scsi.phase) {
+		/*
+		 * If the interface is idle, and the command is 'disconnectable',
+		 * then it is the same as on the disconnected queue.  We simply
+		 * remove all traces of the command.  When the target reconnects,
+		 * we will give it an ABORT message since the command could not
+		 * be found.  When the target finally disconnects, we will clear
+		 * the busylun bit.
+		 */
+		case PHASE_IDLE:
+			if (host->scsi.disconnectable) {
+				host->scsi.disconnectable = 0;
+				host->SCpnt = NULL;
+				res = res_success;
+			}
+			break;
+
+		/*
+		 * If the command has connected and done nothing further,
+		 * simply force a disconnect.  We also need to clear the
+		 * busylun bit.
+		 */
+		case PHASE_CONNECTED:
+			sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT);
+			host->SCpnt = NULL;
+			res = res_success_clear;
+			break;
+
+		default:
+			acornscsi_abortcmd(host, host->SCpnt->tag);
+			res = res_snooze;
+		}
+		restore_flags(flags);
+	} else if (host->origSCpnt == SCpnt) {
+		/*
+		 * The command will be executed next, but a command
+		 * is currently using the interface.  This is similar to
+		 * being on the issue queue, except the busylun bit has
+		 * been set.
+		 */
+		host->origSCpnt = NULL;
+//#if (DEBUG & DEBUG_ABORT)
+		printk("waiting for execution ");
+//#endif
+		res = res_success_clear;
+	} else
+		printk("unknown ");
+
+	return res;
+}
+
 /*
- * Prototype: int acornscsi_abort (Scsi_Cmnd *SCpnt)
+ * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt)
  * Purpose  : abort a command on this host
  * Params   : SCpnt - command to abort
  * Returns  : one of SCSI_ABORT_ macros
  */
-int acornscsi_abort (Scsi_Cmnd *SCpnt)
+int acornscsi_abort(Scsi_Cmnd *SCpnt)
 {
-    AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
-    int result = SCSI_ABORT_NOT_RUNNING;
+	AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
+	int result;
 
-    host->stats.aborts += 1;
+	host->stats.aborts += 1;
 
 #if (DEBUG & DEBUG_ABORT)
-    {
-	int asr, ssr;
-	asr = sbic_arm_read (host->scsi.io_port, ASR);
-	ssr = sbic_arm_read (host->scsi.io_port, SSR);
+	{
+		int asr, ssr;
+		asr = sbic_arm_read(host->scsi.io_port, ASR);
+		ssr = sbic_arm_read(host->scsi.io_port, SSR);
 
-	printk (KERN_WARNING "acornscsi_abort: ");
-	print_sbic_status(asr, ssr, host->scsi.phase);
-	acornscsi_dumplog (host, SCpnt->target);
-    }
+		printk(KERN_WARNING "acornscsi_abort: ");
+		print_sbic_status(asr, ssr, host->scsi.phase);
+		acornscsi_dumplog(host, SCpnt->target);
+	}
 #endif
 
-    if (queue_removecmd (&host->queues.issue, SCpnt)) {
-	SCpnt->result = DID_ABORT << 16;
-	SCpnt->scsi_done (SCpnt);
-#if (DEBUG & DEBUG_ABORT)
-	printk ("scsi%d: command on issue queue\n", host->host->host_no);
-#endif
-	result = SCSI_ABORT_SUCCESS;
-    } else if (queue_cmdonqueue (&host->queues.disconnected, SCpnt)) {
-	printk ("scsi%d: command on disconnected queue\n", host->host->host_no);
-	result = SCSI_ABORT_SNOOZE;
-    } else if (host->SCpnt == SCpnt) {
-	acornscsi_abortcmd (host, host->SCpnt->tag);
-	printk ("scsi%d: command executing\n", host->host->host_no);
-	result = SCSI_ABORT_SNOOZE;
-    } else if (host->origSCpnt == SCpnt) {
-	host->origSCpnt = NULL;
-	SCpnt->result = DID_ABORT << 16;
-	SCpnt->scsi_done (SCpnt);
-#if (DEBUG & DEBUG_ABORT)
-	printk ("scsi%d: command waiting for execution\n", host->host->host_no);
-#endif
-	result = SCSI_ABORT_SUCCESS;
-    }
+	printk("scsi%d: ", host->host->host_no);
+
+	switch (acornscsi_do_abort(host, SCpnt)) {
+	/*
+	 * We managed to find the command and cleared it out.
+	 * We do not expect the command to be executing on the
+	 * target, but we have set the busylun bit.
+	 */
+	case res_success_clear:
+//#if (DEBUG & DEBUG_ABORT)
+		printk("clear ");
+//#endif
+		clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+
+	/*
+	 * We found the command, and cleared it out.  Either
+	 * the command is still known to be executing on the
+	 * target, or the busylun bit is not set.
+	 */
+	case res_success:
+//#if (DEBUG & DEBUG_ABORT)
+		printk("success\n");
+//#endif
+		SCpnt->result = DID_ABORT << 16;
+		SCpnt->scsi_done(SCpnt);
+		result = SCSI_ABORT_SUCCESS;
+		break;
 
-    if (result == SCSI_ABORT_NOT_RUNNING) {
-	printk ("scsi%d: abort(): command not running\n", host->host->host_no);
-	acornscsi_dumplog (host, SCpnt->target);
+	/*
+	 * We did find the command, but unfortunately we couldn't
+	 * unhook it from ourselves.  Wait some more, and if it
+	 * still doesn't complete, reset the interface.
+	 */
+	case res_snooze:
+//#if (DEBUG & DEBUG_ABORT)
+		printk("snooze\n");
+//#endif
+		result = SCSI_ABORT_SNOOZE;
+		break;
+
+	/*
+	 * The command could not be found (either because it completed,
+	 * or it got dropped.
+	 */
+	default:
+	case res_not_running:
+		acornscsi_dumplog(host, SCpnt->target);
 #if (DEBUG & DEBUG_ABORT)
-	result = SCSI_ABORT_SNOOZE;
+		result = SCSI_ABORT_SNOOZE;
+#else
+		result = SCSI_ABORT_NOT_RUNNING;
 #endif
-    }
-    return result;
+//#if (DEBUG & DEBUG_ABORT)
+		printk("not running\n");
+//#endif
+		break;
+	}
+
+	return result;
 }
 
 /*
- * Prototype: int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+ * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  * Purpose  : reset a command on this host/reset this host
  * Params   : SCpnt  - command causing reset
  *	      result - what type of reset to perform
  * Returns  : one of SCSI_RESET_ macros
  */
-int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
 {
     AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
     Scsi_Cmnd *SCptr;
@@ -2566,16 +2812,16 @@
     {
 	int asr, ssr;
 
-	asr = sbic_arm_read (host->scsi.io_port, ASR);
-	ssr = sbic_arm_read (host->scsi.io_port, SSR);
+	asr = sbic_arm_read(host->scsi.io_port, ASR);
+	ssr = sbic_arm_read(host->scsi.io_port, SSR);
 
-	printk (KERN_WARNING "acornscsi_reset: ");
+	printk(KERN_WARNING "acornscsi_reset: ");
 	print_sbic_status(asr, ssr, host->scsi.phase);
-	acornscsi_dumplog (host, SCpnt->target);
+	acornscsi_dumplog(host, SCpnt->target);
     }
 #endif
 
-    acornscsi_dma_stop (host);
+    acornscsi_dma_stop(host);
 
     SCptr = host->SCpnt;
 
@@ -2583,19 +2829,19 @@
      * do hard reset.  This resets all devices on this host, and so we
      * must set the reset status on all commands.
      */
-    acornscsi_resetcard (host);
+    acornscsi_resetcard(host);
 
     /*
      * report reset on commands current connected/disconnected
      */
-    acornscsi_reportstatus (&host->SCpnt, &SCptr, DID_RESET);
+    acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET);
 
-    while ((SCptr = queue_remove (&host->queues.disconnected)) != NULL)
-	acornscsi_reportstatus (&SCptr, &SCpnt, DID_RESET);
+    while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
+	acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET);
 
     if (SCpnt) {
 	SCpnt->result = DID_RESET << 16;
-	SCpnt->scsi_done (SCpnt);
+	SCpnt->scsi_done(SCpnt);
     }
 
     return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
@@ -2607,19 +2853,19 @@
 static struct expansion_card *ecs[MAX_ECARDS];
 
 /*
- * Prototype: void acornscsi_init (AS_Host *host)
+ * Prototype: void acornscsi_init(AS_Host *host)
  * Purpose  : initialise the AS_Host structure for one interface & setup hardware
  * Params   : host - host to setup
  */
 static
-void acornscsi_init (AS_Host *host)
+void acornscsi_init(AS_Host *host)
 {
-    memset (&host->stats, 0, sizeof (host->stats));
-    queue_initialise (&host->queues.issue);
-    queue_initialise (&host->queues.disconnected);
-    msgqueue_initialise (&host->scsi.msgs);
+    memset(&host->stats, 0, sizeof (host->stats));
+    queue_initialise(&host->queues.issue);
+    queue_initialise(&host->queues.disconnected);
+    msgqueue_initialise(&host->scsi.msgs);
 
-    acornscsi_resetcard (host);
+    acornscsi_resetcard(host);
 }
 
 int acornscsi_detect(Scsi_Host_Template * tpnt)
@@ -2634,7 +2880,7 @@
     for (i = 0; i < MAX_ECARDS; i++)
 	ecs[i] = NULL;
 
-    ecard_startfind ();
+    ecard_startfind();
 
     while(1) {
 	ecs[count] = ecard_find(0, acornscsi_cids);
@@ -2642,37 +2888,37 @@
 	    break;
 
 	if (ecs[count]->irq == 0xff) {
-	    printk ("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
+	    printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
 	    continue;
 	}
 
 	ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */
 
-	instance = scsi_register (tpnt, sizeof(AS_Host));
+	instance = scsi_register(tpnt, sizeof(AS_Host));
 	host = (AS_Host *)instance->hostdata;
 
-	instance->io_port = ecard_address (ecs[count], ECARD_MEMC, 0);
+	instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
 	instance->irq = ecs[count]->irq;
 
 	host->host		= instance;
-	host->scsi.io_port	= ioaddr (instance->io_port + 0x800);
+	host->scsi.io_port	= ioaddr(instance->io_port + 0x800);
 	host->scsi.irq		= instance->irq;
 	host->card.io_intr	= POD_SPACE(instance->io_port) + 0x800;
 	host->card.io_page	= POD_SPACE(instance->io_port) + 0xc00;
-	host->card.io_ram	= ioaddr (instance->io_port);
+	host->card.io_ram	= ioaddr(instance->io_port);
 	host->dma.io_port	= instance->io_port + 0xc00;
 	host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
 
 	ecs[count]->irqaddr	= (char *)ioaddr(host->card.io_intr);
 	ecs[count]->irqmask	= 0x0a;
 
-	request_region (instance->io_port + 0x800,  2, "acornscsi(sbic)");
-	request_region (host->card.io_intr,  1, "acornscsi(intr)");
-	request_region (host->card.io_page,  1, "acornscsi(page)");
+	request_region(instance->io_port + 0x800,  2, "acornscsi(sbic)");
+	request_region(host->card.io_intr,  1, "acornscsi(intr)");
+	request_region(host->card.io_page,  1, "acornscsi(page)");
 #ifdef USE_DMAC
-	request_region (host->dma.io_port, 256, "acornscsi(dmac)");
+	request_region(host->dma.io_port, 256, "acornscsi(dmac)");
 #endif
-	request_region (instance->io_port, 2048, "acornscsi(ram)");
+	request_region(instance->io_port, 2048, "acornscsi(ram)");
 
 	if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) {
 	    printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n",
@@ -2680,7 +2926,7 @@
 	    host->scsi.irq = NO_IRQ;
 	}
 
-	acornscsi_init (host);
+	acornscsi_init(host);
 
 	++count;
     }
@@ -2688,12 +2934,12 @@
 }
 
 /*
- * Function: int acornscsi_release (struct Scsi_Host *host)
+ * Function: int acornscsi_release(struct Scsi_Host *host)
  * Purpose : release all resources used by this adapter
  * Params  : host - driver structure to release
  * Returns : nothing of any consequence
  */
-int acornscsi_release (struct Scsi_Host *instance)
+int acornscsi_release(struct Scsi_Host *instance)
 {
     AS_Host *host = (AS_Host *)instance->hostdata;
     int i;
@@ -2701,30 +2947,30 @@
     /*
      * Put card into RESET state
      */
-    outb (0x80, host->card.io_page);
+    outb(0x80, host->card.io_page);
 
     if (host->scsi.irq != NO_IRQ)
-	free_irq (host->scsi.irq, host);
+	free_irq(host->scsi.irq, host);
 
-    release_region (instance->io_port + 0x800, 2);
-    release_region (host->card.io_intr, 1);
-    release_region (host->card.io_page, 1);
-    release_region (host->dma.io_port, 256);
-    release_region (instance->io_port, 2048);
+    release_region(instance->io_port + 0x800, 2);
+    release_region(host->card.io_intr, 1);
+    release_region(host->card.io_page, 1);
+    release_region(host->dma.io_port, 256);
+    release_region(instance->io_port, 2048);
 
     for (i = 0; i < MAX_ECARDS; i++)
-	if (ecs[i] && instance->io_port == ecard_address (ecs[i], ECARD_MEMC, 0))
-	    ecard_release (ecs[i]);
+	if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0))
+	    ecard_release(ecs[i]);
 
-    msgqueue_free (&host->scsi.msgs);
-    queue_free (&host->queues.disconnected);
-    queue_free (&host->queues.issue);
+    msgqueue_free(&host->scsi.msgs);
+    queue_free(&host->queues.disconnected);
+    queue_free(&host->queues.issue);
 
     return 0;
 }
 
 /*
- * Function: char *acornscsi_info (struct Scsi_Host *host)
+ * Function: char *acornscsi_info(struct Scsi_Host *host)
  * Purpose : return a string describing this interface
  * Params  : host - host to give information on
  * Returns : a constant string
@@ -2736,7 +2982,7 @@
 
     p = string;
     
-    p += sprintf (string, "%s at port %lX irq %d v%d.%d.%d"
+    p += sprintf(string, "%s at port %X irq %d v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
@@ -2772,7 +3018,7 @@
 
     host  = (AS_Host *)instance->hostdata;
     
-    p += sprintf (p, "AcornSCSI driver v%d.%d.%d"
+    p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
@@ -2787,14 +3033,14 @@
 #endif
 		"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
 
-    p += sprintf (p,	"SBIC: WD33C93A  Address: %08X  IRQ : %d\n",
+    p += sprintf(p,	"SBIC: WD33C93A  Address: %08X  IRQ : %d\n",
 			host->scsi.io_port, host->scsi.irq);
 #ifdef USE_DMAC
-    p += sprintf (p,	"DMAC: uPC71071  Address: %08X  IRQ : %d\n\n",
+    p += sprintf(p,	"DMAC: uPC71071  Address: %08X  IRQ : %d\n\n",
 			host->dma.io_port, host->scsi.irq);
 #endif
 
-    p += sprintf (p,	"Statistics:\n"
+    p += sprintf(p,	"Statistics:\n"
 			"Queued commands: %-10u    Issued commands: %-10u\n"
 			"Done commands  : %-10u    Reads          : %-10u\n"
 			"Writes         : %-10u    Others         : %-10u\n"
@@ -2809,47 +3055,47 @@
     for (devidx = 0; devidx < 9; devidx ++) {
 	unsigned int statptr, prev;
 
-	p += sprintf (p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
-	statptr = status_ptr[devidx] - 10;
+	p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
+	statptr = host->status_ptr[devidx] - 10;
 
 	if ((signed int)statptr < 0)
-	    statptr += 16;
+	    statptr += STATUS_BUFFER_SIZE;
 
-	prev = status[devidx][statptr].when;
+	prev = host->status[devidx][statptr].when;
 
-	for (; statptr != status_ptr[devidx]; statptr = (statptr + 1) & 15) {
-	    if (status[devidx][statptr].when) {
-		p += sprintf (p, "%c%02X:%02X+%2ld",
-			status[devidx][statptr].irq ? '-' : ' ',
-			status[devidx][statptr].ph,
-			status[devidx][statptr].ssr,
-			(status[devidx][statptr].when - prev) < 100 ?
-				(status[devidx][statptr].when - prev) : 99);
-		prev = status[devidx][statptr].when;
+	for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
+	    if (host->status[devidx][statptr].when) {
+		p += sprintf(p, "%c%02X:%02X+%2ld",
+			host->status[devidx][statptr].irq ? '-' : ' ',
+			host->status[devidx][statptr].ph,
+			host->status[devidx][statptr].ssr,
+			(host->status[devidx][statptr].when - prev) < 100 ?
+				(host->status[devidx][statptr].when - prev) : 99);
+		prev = host->status[devidx][statptr].when;
 	    }
 	}
     }
 
-    p += sprintf (p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
+    p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
 
     for (scd = instance->host_queue; scd; scd = scd->next) {
 	int len;
 
-	proc_print_scsidevice (scd, p, &len, 0);
+	proc_print_scsidevice(scd, p, &len, 0);
 	p += len;
 
-	p += sprintf (p, "Extensions: ");
+	p += sprintf(p, "Extensions: ");
 
 	if (scd->tagged_supported)
-	    p += sprintf (p, "TAG %sabled [%d] ",
+	    p += sprintf(p, "TAG %sabled [%d] ",
 			  scd->tagged_queue ? "en" : "dis", scd->current_tag);
-	p += sprintf (p, "\nTransfers: ");
+	p += sprintf(p, "\nTransfers: ");
 	if (host->device[scd->id].sync_xfer & 15)
-	    p += sprintf (p, "sync, offset %d, %d ns\n",
+	    p += sprintf(p, "sync, offset %d, %d ns\n",
 			  host->device[scd->id].sync_xfer & 15,
-			  acornscsi_getperiod (host->device[scd->id].sync_xfer));
+			  acornscsi_getperiod(host->device[scd->id].sync_xfer));
 	else
-	    p += sprintf (p, "async\n");
+	    p += sprintf(p, "async\n");
 
 	pos = p - buffer;
 	if (pos + begin < offset) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)