acornscsi.c revision a796ef7035c6c5cc5726c3e4e8d71175c13828df
1/*
2 *  linux/drivers/acorn/scsi/acornscsi.c
3 *
4 *  Acorn SCSI 3 driver
5 *  By R.M.King.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Abandoned using the Select and Transfer command since there were
12 * some nasty races between our software and the target devices that
13 * were not easy to solve, and the device errata had a lot of entries
14 * for this command, some of them quite nasty...
15 *
16 * Changelog:
17 *  26-Sep-1997	RMK	Re-jigged to use the queue module.
18 *			Re-coded state machine to be based on driver
19 *			state not scsi state.  Should be easier to debug.
20 *			Added acornscsi_release to clean up properly.
21 *			Updated proc/scsi reporting.
22 *  05-Oct-1997	RMK	Implemented writing to SCSI devices.
23 *  06-Oct-1997	RMK	Corrected small (non-serious) bug with the connect/
24 *			reconnect race condition causing a warning message.
25 *  12-Oct-1997	RMK	Added catch for re-entering interrupt routine.
26 *  15-Oct-1997	RMK	Improved handling of commands.
27 *  27-Jun-1998	RMK	Changed asm/delay.h to linux/delay.h.
28 *  13-Dec-1998	RMK	Better abort code and command handling.  Extra state
29 *			transitions added to allow dodgy devices to work.
30 */
31#define DEBUG_NO_WRITE	1
32#define DEBUG_QUEUES	2
33#define DEBUG_DMA	4
34#define DEBUG_ABORT	8
35#define DEBUG_DISCON	16
36#define DEBUG_CONNECT	32
37#define DEBUG_PHASES	64
38#define DEBUG_WRITE	128
39#define DEBUG_LINK	256
40#define DEBUG_MESSAGES	512
41#define DEBUG_RESET	1024
42#define DEBUG_ALL	(DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\
43			 DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\
44			 DEBUG_DMA|DEBUG_QUEUES)
45
46/* DRIVER CONFIGURATION
47 *
48 * SCSI-II Tagged queue support.
49 *
50 * I don't have any SCSI devices that support it, so it is totally untested
51 * (except to make sure that it doesn't interfere with any non-tagging
52 * devices).  It is not fully implemented either - what happens when a
53 * tagging device reconnects???
54 *
55 * You can tell if you have a device that supports tagged queueing my
56 * cating (eg) /proc/scsi/acornscsi/0 and see if the SCSI revision is reported
57 * as '2 TAG'.
58 *
59 * Also note that CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE is normally set in the config
60 * scripts, but disabled here.  Once debugged, remove the #undef, otherwise to debug,
61 * comment out the undef.
62 */
63#undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
64/*
65 * SCSI-II Linked command support.
66 *
67 * The higher level code doesn't support linked commands yet, and so the option
68 * is undef'd here.
69 */
70#undef CONFIG_SCSI_ACORNSCSI_LINK
71/*
72 * SCSI-II Synchronous transfer support.
73 *
74 * Tried and tested...
75 *
76 * SDTR_SIZE	  - maximum number of un-acknowledged bytes (0 = off, 12 = max)
77 * SDTR_PERIOD	  - period of REQ signal (min=125, max=1020)
78 * DEFAULT_PERIOD - default REQ period.
79 */
80#define SDTR_SIZE	12
81#define SDTR_PERIOD	125
82#define DEFAULT_PERIOD	500
83
84/*
85 * Debugging information
86 *
87 * DEBUG	  - bit mask from list above
88 * DEBUG_TARGET   - is defined to the target number if you want to debug
89 *		    a specific target. [only recon/write/dma].
90 */
91#define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE)
92/* only allow writing to SCSI device 0 */
93#define NO_WRITE 0xFE
94/*#define DEBUG_TARGET 2*/
95/*
96 * Select timeout time (in 10ms units)
97 *
98 * This is the timeout used between the start of selection and the WD33C93
99 * chip deciding that the device isn't responding.
100 */
101#define TIMEOUT_TIME 10
102/*
103 * Define this if you want to have verbose explaination of SCSI
104 * status/messages.
105 */
106#undef CONFIG_ACORNSCSI_CONSTANTS
107/*
108 * Define this if you want to use the on board DMAC [don't remove this option]
109 * If not set, then use PIO mode (not currently supported).
110 */
111#define USE_DMAC
112
113/*
114 * ====================================================================================
115 */
116
117#ifdef DEBUG_TARGET
118#define DBG(cmd,xxx...) \
119  if (cmd->device->id == DEBUG_TARGET) { \
120    xxx; \
121  }
122#else
123#define DBG(cmd,xxx...) xxx
124#endif
125
126#include <linux/module.h>
127#include <linux/kernel.h>
128#include <linux/string.h>
129#include <linux/signal.h>
130#include <linux/errno.h>
131#include <linux/proc_fs.h>
132#include <linux/ioport.h>
133#include <linux/blkdev.h>
134#include <linux/delay.h>
135#include <linux/interrupt.h>
136#include <linux/init.h>
137#include <linux/bitops.h>
138#include <linux/stringify.h>
139
140#include <asm/system.h>
141#include <asm/io.h>
142#include <asm/ecard.h>
143
144#include "../scsi.h"
145#include <scsi/scsi_dbg.h>
146#include <scsi/scsi_host.h>
147#include <scsi/scsi_transport_spi.h>
148#include "acornscsi.h"
149#include "msgqueue.h"
150#include "scsi.h"
151
152#include <scsi/scsicam.h>
153
154#define VER_MAJOR 2
155#define VER_MINOR 0
156#define VER_PATCH 6
157
158#ifndef ABORT_TAG
159#define ABORT_TAG 0xd
160#else
161#error "Yippee!  ABORT TAG is now defined!  Remove this error!"
162#endif
163
164#ifdef CONFIG_SCSI_ACORNSCSI_LINK
165#error SCSI2 LINKed commands not supported (yet)!
166#endif
167
168#ifdef USE_DMAC
169/*
170 * DMAC setup parameters
171 */
172#define INIT_DEVCON0	(DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP)
173#define INIT_DEVCON1	(DEVCON1_BHLD)
174#define DMAC_READ	(MODECON_READ)
175#define DMAC_WRITE	(MODECON_WRITE)
176#define INIT_SBICDMA	(CTRL_DMABURST)
177
178#define scsi_xferred	have_data_in
179
180/*
181 * Size of on-board DMA buffer
182 */
183#define DMAC_BUFFER_SIZE	65536
184#endif
185
186#define STATUS_BUFFER_TO_PRINT	24
187
188unsigned int sdtr_period = SDTR_PERIOD;
189unsigned int sdtr_size   = SDTR_SIZE;
190
191static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
192			   unsigned int result);
193static int acornscsi_reconnect_finish(AS_Host *host);
194static void acornscsi_dma_cleanup(AS_Host *host);
195static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
196
197/* ====================================================================================
198 * Miscellaneous
199 */
200
201static inline void sbic_arm_write(AS_Host *host, unsigned int reg, unsigned int value)
202{
203    __raw_writeb(reg, host->scsi.io_port);
204    __raw_writeb(value, host->scsi.io_port + 4);
205}
206
207#define sbic_arm_writenext(host,val) \
208	__raw_writeb((val), (host)->scsi.io_port + 4)
209
210static inline int sbic_arm_read(AS_Host *host, unsigned int reg)
211{
212    if(reg == SBIC_ASR)
213	   return __raw_readl(host->scsi.io_port) & 255;
214    __raw_writeb(reg, host->scsi.io_port);
215    return __raw_readl(host->scsi.io_port + 4) & 255;
216}
217
218#define sbic_arm_readnext(host) \
219	__raw_readb((host)->scsi.io_port + 4)
220
221#ifdef USE_DMAC
222#define dmac_read(host,reg) \
223	inb((host)->dma.io_port + (reg))
224
225#define dmac_write(host,reg,value) \
226	({ outb((value), (host)->dma.io_port + (reg)); })
227
228#define dmac_clearintr(host) \
229	({ outb(0, (host)->dma.io_intr_clear); })
230
231static inline unsigned int dmac_address(AS_Host *host)
232{
233    return dmac_read(host, DMAC_TXADRHI) << 16 |
234	   dmac_read(host, DMAC_TXADRMD) << 8 |
235	   dmac_read(host, DMAC_TXADRLO);
236}
237
238static
239void acornscsi_dumpdma(AS_Host *host, char *where)
240{
241	unsigned int mode, addr, len;
242
243	mode = dmac_read(host, DMAC_MODECON);
244	addr = dmac_address(host);
245	len  = dmac_read(host, DMAC_TXCNTHI) << 8 |
246	       dmac_read(host, DMAC_TXCNTLO);
247
248	printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
249		host->host->host_no, where,
250		mode, addr, (len + 1) & 0xffff,
251		dmac_read(host, DMAC_MASKREG));
252
253	printk("DMA @%06x, ", host->dma.start_addr);
254	printk("BH @%p +%04x, ", host->scsi.SCp.ptr,
255		host->scsi.SCp.this_residual);
256	printk("DT @+%04x ST @+%04x", host->dma.transferred,
257		host->scsi.SCp.scsi_xferred);
258	printk("\n");
259}
260#endif
261
262static
263unsigned long acornscsi_sbic_xfcount(AS_Host *host)
264{
265    unsigned long length;
266
267    length = sbic_arm_read(host, SBIC_TRANSCNTH) << 16;
268    length |= sbic_arm_readnext(host) << 8;
269    length |= sbic_arm_readnext(host);
270
271    return length;
272}
273
274static int
275acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
276{
277	int asr;
278
279	do {
280		asr = sbic_arm_read(host, SBIC_ASR);
281
282		if ((asr & stat_mask) == stat)
283			return 0;
284
285		udelay(1);
286	} while (--timeout);
287
288	printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
289
290	return -1;
291}
292
293static
294int acornscsi_sbic_issuecmd(AS_Host *host, int command)
295{
296    if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
297	return -1;
298
299    sbic_arm_write(host, SBIC_CMND, command);
300
301    return 0;
302}
303
304static void
305acornscsi_csdelay(unsigned int cs)
306{
307    unsigned long target_jiffies, flags;
308
309    target_jiffies = jiffies + 1 + cs * HZ / 100;
310
311    local_save_flags(flags);
312    local_irq_enable();
313
314    while (time_before(jiffies, target_jiffies)) barrier();
315
316    local_irq_restore(flags);
317}
318
319static
320void acornscsi_resetcard(AS_Host *host)
321{
322    unsigned int i, timeout;
323
324    /* assert reset line */
325    host->card.page_reg = 0x80;
326    outb(host->card.page_reg, host->card.io_page);
327
328    /* wait 3 cs.  SCSI standard says 25ms. */
329    acornscsi_csdelay(3);
330
331    host->card.page_reg = 0;
332    outb(host->card.page_reg, host->card.io_page);
333
334    /*
335     * Should get a reset from the card
336     */
337    timeout = 1000;
338    do {
339	if (inb(host->card.io_intr) & 8)
340	    break;
341	udelay(1);
342    } while (--timeout);
343
344    if (timeout == 0)
345	printk("scsi%d: timeout while resetting card\n",
346		host->host->host_no);
347
348    sbic_arm_read(host, SBIC_ASR);
349    sbic_arm_read(host, SBIC_SSR);
350
351    /* setup sbic - WD33C93A */
352    sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id);
353    sbic_arm_write(host, SBIC_CMND, CMND_RESET);
354
355    /*
356     * Command should cause a reset interrupt
357     */
358    timeout = 1000;
359    do {
360	if (inb(host->card.io_intr) & 8)
361	    break;
362	udelay(1);
363    } while (--timeout);
364
365    if (timeout == 0)
366	printk("scsi%d: timeout while resetting card\n",
367		host->host->host_no);
368
369    sbic_arm_read(host, SBIC_ASR);
370    if (sbic_arm_read(host, SBIC_SSR) != 0x01)
371	printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
372		host->host->host_no);
373
374    sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI);
375    sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME);
376    sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
377    sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
378
379    host->card.page_reg = 0x40;
380    outb(host->card.page_reg, host->card.io_page);
381
382    /* setup dmac - uPC71071 */
383    dmac_write(host, DMAC_INIT, 0);
384#ifdef USE_DMAC
385    dmac_write(host, DMAC_INIT, INIT_8BIT);
386    dmac_write(host, DMAC_CHANNEL, CHANNEL_0);
387    dmac_write(host, DMAC_DEVCON0, INIT_DEVCON0);
388    dmac_write(host, DMAC_DEVCON1, INIT_DEVCON1);
389#endif
390
391    host->SCpnt = NULL;
392    host->scsi.phase = PHASE_IDLE;
393    host->scsi.disconnectable = 0;
394
395    memset(host->busyluns, 0, sizeof(host->busyluns));
396
397    for (i = 0; i < 8; i++) {
398	host->device[i].sync_state = SYNC_NEGOCIATE;
399	host->device[i].disconnect_ok = 1;
400    }
401
402    /* wait 25 cs.  SCSI standard says 250ms. */
403    acornscsi_csdelay(25);
404}
405
406/*=============================================================================================
407 * Utility routines (eg. debug)
408 */
409#ifdef CONFIG_ACORNSCSI_CONSTANTS
410static char *acornscsi_interrupttype[] = {
411  "rst",  "suc",  "p/a",  "3",
412  "term", "5",	  "6",	  "7",
413  "serv", "9",	  "a",	  "b",
414  "c",	  "d",	  "e",	  "f"
415};
416
417static signed char acornscsi_map[] = {
418  0,  1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
419 -1,  2, -1, -1,  -1, -1,  3, -1,   4,	5,  6,	7,   8,  9, 10, 11,
420 12, 13, 14, -1,  -1, -1, -1, -1,   4,	5,  6,	7,   8,  9, 10, 11,
421 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
422 15, 16, 17, 18,  19, -1, -1, 20,   4,	5,  6,	7,   8,  9, 10, 11,
423 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
424 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
425 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
426 21, 22, -1, -1,  -1, 23, -1, -1,   4,	5,  6,	7,   8,  9, 10, 11,
427 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
428 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
429 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
430 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
431 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
432 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,
433 -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1
434};
435
436static char *acornscsi_interruptcode[] = {
437    /* 0 */
438    "reset - normal mode",	/* 00 */
439    "reset - advanced mode",	/* 01 */
440
441    /* 2 */
442    "sel",			/* 11 */
443    "sel+xfer", 		/* 16 */
444    "data-out", 		/* 18 */
445    "data-in",			/* 19 */
446    "cmd",			/* 1A */
447    "stat",			/* 1B */
448    "??-out",			/* 1C */
449    "??-in",			/* 1D */
450    "msg-out",			/* 1E */
451    "msg-in",			/* 1F */
452
453    /* 12 */
454    "/ACK asserted",		/* 20 */
455    "save-data-ptr",		/* 21 */
456    "{re}sel",			/* 22 */
457
458    /* 15 */
459    "inv cmd",			/* 40 */
460    "unexpected disconnect",	/* 41 */
461    "sel timeout",		/* 42 */
462    "P err",			/* 43 */
463    "P err+ATN",		/* 44 */
464    "bad status byte",		/* 47 */
465
466    /* 21 */
467    "resel, no id",		/* 80 */
468    "resel",			/* 81 */
469    "discon",			/* 85 */
470};
471
472static
473void print_scsi_status(unsigned int ssr)
474{
475    if (acornscsi_map[ssr] != -1)
476	printk("%s:%s",
477		acornscsi_interrupttype[(ssr >> 4)],
478		acornscsi_interruptcode[acornscsi_map[ssr]]);
479    else
480	printk("%X:%X", ssr >> 4, ssr & 0x0f);
481}
482#endif
483
484static
485void print_sbic_status(int asr, int ssr, int cmdphase)
486{
487#ifdef CONFIG_ACORNSCSI_CONSTANTS
488    printk("sbic: %c%c%c%c%c%c ",
489	    asr & ASR_INT ? 'I' : 'i',
490	    asr & ASR_LCI ? 'L' : 'l',
491	    asr & ASR_BSY ? 'B' : 'b',
492	    asr & ASR_CIP ? 'C' : 'c',
493	    asr & ASR_PE  ? 'P' : 'p',
494	    asr & ASR_DBR ? 'D' : 'd');
495    printk("scsi: ");
496    print_scsi_status(ssr);
497    printk(" ph %02X\n", cmdphase);
498#else
499    printk("sbic: %02X scsi: %X:%X ph: %02X\n",
500	    asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);
501#endif
502}
503
504static void
505acornscsi_dumplogline(AS_Host *host, int target, int line)
506{
507	unsigned long prev;
508	signed int ptr;
509
510	ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT;
511	if (ptr < 0)
512		ptr += STATUS_BUFFER_SIZE;
513
514	printk("%c: %3s:", target == 8 ? 'H' : '0' + target,
515		line == 0 ? "ph" : line == 1 ? "ssr" : "int");
516
517	prev = host->status[target][ptr].when;
518
519	for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
520		unsigned long time_diff;
521
522		if (!host->status[target][ptr].when)
523			continue;
524
525		switch (line) {
526		case 0:
527			printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ',
528					 host->status[target][ptr].ph);
529			break;
530
531		case 1:
532			printk(" %02X", host->status[target][ptr].ssr);
533			break;
534
535		case 2:
536			time_diff = host->status[target][ptr].when - prev;
537			prev = host->status[target][ptr].when;
538			if (time_diff == 0)
539				printk("==^");
540			else if (time_diff >= 100)
541				printk("   ");
542			else
543				printk(" %02ld", time_diff);
544			break;
545		}
546	}
547
548	printk("\n");
549}
550
551static
552void acornscsi_dumplog(AS_Host *host, int target)
553{
554    do {
555	acornscsi_dumplogline(host, target, 0);
556	acornscsi_dumplogline(host, target, 1);
557	acornscsi_dumplogline(host, target, 2);
558
559	if (target == 8)
560	    break;
561
562	target = 8;
563    } while (1);
564}
565
566static
567char acornscsi_target(AS_Host *host)
568{
569	if (host->SCpnt)
570		return '0' + host->SCpnt->device->id;
571	return 'H';
572}
573
574/*
575 * Prototype: cmdtype_t acornscsi_cmdtype(int command)
576 * Purpose  : differentiate READ from WRITE from other commands
577 * Params   : command - command to interpret
578 * Returns  : CMD_READ	- command reads data,
579 *	      CMD_WRITE - command writes data,
580 *	      CMD_MISC	- everything else
581 */
582static inline
583cmdtype_t acornscsi_cmdtype(int command)
584{
585    switch (command) {
586    case WRITE_6:  case WRITE_10:  case WRITE_12:
587	return CMD_WRITE;
588    case READ_6:   case READ_10:   case READ_12:
589	return CMD_READ;
590    default:
591	return CMD_MISC;
592    }
593}
594
595/*
596 * Prototype: int acornscsi_datadirection(int command)
597 * Purpose  : differentiate between commands that have a DATA IN phase
598 *	      and a DATA OUT phase
599 * Params   : command - command to interpret
600 * Returns  : DATADIR_OUT - data out phase expected
601 *	      DATADIR_IN  - data in phase expected
602 */
603static
604datadir_t acornscsi_datadirection(int command)
605{
606    switch (command) {
607    case CHANGE_DEFINITION:	case COMPARE:		case COPY:
608    case COPY_VERIFY:		case LOG_SELECT:	case MODE_SELECT:
609    case MODE_SELECT_10:	case SEND_DIAGNOSTIC:	case WRITE_BUFFER:
610    case FORMAT_UNIT:		case REASSIGN_BLOCKS:	case RESERVE:
611    case SEARCH_EQUAL:		case SEARCH_HIGH:	case SEARCH_LOW:
612    case WRITE_6:		case WRITE_10:		case WRITE_VERIFY:
613    case UPDATE_BLOCK:		case WRITE_LONG:	case WRITE_SAME:
614    case SEARCH_HIGH_12:	case SEARCH_EQUAL_12:	case SEARCH_LOW_12:
615    case WRITE_12:		case WRITE_VERIFY_12:	case SET_WINDOW:
616    case MEDIUM_SCAN:		case SEND_VOLUME_TAG:	case 0xea:
617	return DATADIR_OUT;
618    default:
619	return DATADIR_IN;
620    }
621}
622
623/*
624 * Purpose  : provide values for synchronous transfers with 33C93.
625 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
626 *	Modified by Russell King for 8MHz WD33C93A
627 */
628static struct sync_xfer_tbl {
629    unsigned int period_ns;
630    unsigned char reg_value;
631} sync_xfer_table[] = {
632    {	1, 0x20 },    { 249, 0x20 },	{ 374, 0x30 },
633    { 499, 0x40 },    { 624, 0x50 },	{ 749, 0x60 },
634    { 874, 0x70 },    { 999, 0x00 },	{   0,	  0 }
635};
636
637/*
638 * Prototype: int acornscsi_getperiod(unsigned char syncxfer)
639 * Purpose  : period for the synchronous transfer setting
640 * Params   : syncxfer SYNCXFER register value
641 * Returns  : period in ns.
642 */
643static
644int acornscsi_getperiod(unsigned char syncxfer)
645{
646    int i;
647
648    syncxfer &= 0xf0;
649    if (syncxfer == 0x10)
650	syncxfer = 0;
651
652    for (i = 1; sync_xfer_table[i].period_ns; i++)
653	if (syncxfer == sync_xfer_table[i].reg_value)
654	    return sync_xfer_table[i].period_ns;
655    return 0;
656}
657
658/*
659 * Prototype: int round_period(unsigned int period)
660 * Purpose  : return index into above table for a required REQ period
661 * Params   : period - time (ns) for REQ
662 * Returns  : table index
663 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
664 */
665static inline
666int round_period(unsigned int period)
667{
668    int i;
669
670    for (i = 1; sync_xfer_table[i].period_ns; i++) {
671	if ((period <= sync_xfer_table[i].period_ns) &&
672	    (period > sync_xfer_table[i - 1].period_ns))
673	    return i;
674    }
675    return 7;
676}
677
678/*
679 * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
680 * Purpose  : calculate value for 33c93s SYNC register
681 * Params   : period - time (ns) for REQ
682 *	      offset - offset in bytes between REQ/ACK
683 * Returns  : value for SYNC register
684 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
685 */
686static
687unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
688{
689    return sync_xfer_table[round_period(period)].reg_value |
690		((offset < SDTR_SIZE) ? offset : SDTR_SIZE);
691}
692
693/* ====================================================================================
694 * Command functions
695 */
696/*
697 * Function: acornscsi_kick(AS_Host *host)
698 * Purpose : kick next command to interface
699 * Params  : host - host to send command to
700 * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING
701 * Notes   : interrupts are always disabled!
702 */
703static
704intr_ret_t acornscsi_kick(AS_Host *host)
705{
706    int from_queue = 0;
707    struct scsi_cmnd *SCpnt;
708
709    /* first check to see if a command is waiting to be executed */
710    SCpnt = host->origSCpnt;
711    host->origSCpnt = NULL;
712
713    /* retrieve next command */
714    if (!SCpnt) {
715	SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns);
716	if (!SCpnt)
717	    return INTR_IDLE;
718
719	from_queue = 1;
720    }
721
722    if (host->scsi.disconnectable && host->SCpnt) {
723	queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
724	host->scsi.disconnectable = 0;
725#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
726	DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n",
727		host->host->host_no, acornscsi_target(host)));
728#endif
729	host->SCpnt = NULL;
730    }
731
732    /*
733     * If we have an interrupt pending, then we may have been reselected.
734     * In this case, we don't want to write to the registers
735     */
736    if (!(sbic_arm_read(host, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
737	sbic_arm_write(host, SBIC_DESTID, SCpnt->device->id);
738	sbic_arm_write(host, SBIC_CMND, CMND_SELWITHATN);
739    }
740
741    /*
742     * claim host busy - all of these must happen atomically wrt
743     * our interrupt routine.  Failure means command loss.
744     */
745    host->scsi.phase = PHASE_CONNECTING;
746    host->SCpnt = SCpnt;
747    host->scsi.SCp = SCpnt->SCp;
748    host->dma.xfer_setup = 0;
749    host->dma.xfer_required = 0;
750    host->dma.xfer_done = 0;
751
752#if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT))
753    DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n",
754	    host->host->host_no, '0' + SCpnt->device->id,
755	    SCpnt->cmnd[0]));
756#endif
757
758    if (from_queue) {
759#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
760	/*
761	 * tagged queueing - allocate a new tag to this command
762	 */
763	if (SCpnt->device->simple_tags) {
764	    SCpnt->device->current_tag += 1;
765	    if (SCpnt->device->current_tag == 0)
766		SCpnt->device->current_tag = 1;
767	    SCpnt->tag = SCpnt->device->current_tag;
768	} else
769#endif
770	    set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
771
772	host->stats.removes += 1;
773
774	switch (acornscsi_cmdtype(SCpnt->cmnd[0])) {
775	case CMD_WRITE:
776	    host->stats.writes += 1;
777	    break;
778	case CMD_READ:
779	    host->stats.reads += 1;
780	    break;
781	case CMD_MISC:
782	    host->stats.miscs += 1;
783	    break;
784	}
785    }
786
787    return INTR_PROCESSING;
788}
789
790/*
791 * Function: void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, unsigned int result)
792 * Purpose : complete processing for command
793 * Params  : host   - interface that completed
794 *	     result - driver byte of result
795 */
796static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
797			   unsigned int result)
798{
799	struct scsi_cmnd *SCpnt = *SCpntp;
800
801    /* clean up */
802    sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
803
804    host->stats.fins += 1;
805
806    if (SCpnt) {
807	*SCpntp = NULL;
808
809	acornscsi_dma_cleanup(host);
810
811	SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status;
812
813	/*
814	 * In theory, this should not happen.  In practice, it seems to.
815	 * Only trigger an error if the device attempts to report all happy
816	 * but with untransferred buffers...  If we don't do something, then
817	 * data loss will occur.  Should we check SCpnt->underflow here?
818	 * It doesn't appear to be set to something meaningful by the higher
819	 * levels all the time.
820	 */
821	if (result == DID_OK) {
822		int xfer_warn = 0;
823
824		if (SCpnt->underflow == 0) {
825			if (host->scsi.SCp.ptr &&
826			    acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC)
827				xfer_warn = 1;
828		} else {
829			if (host->scsi.SCp.scsi_xferred < SCpnt->underflow ||
830			    host->scsi.SCp.scsi_xferred != host->dma.transferred)
831				xfer_warn = 1;
832		}
833
834		/* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6)
835		 *  Targets which break data transfers into multiple
836		 *  connections shall end each successful connection
837		 *  (except possibly the last) with a SAVE DATA
838		 *  POINTER - DISCONNECT message sequence.
839		 *
840		 * This makes it difficult to ensure that a transfer has
841		 * completed.  If we reach the end of a transfer during
842		 * the command, then we can only have finished the transfer.
843		 * therefore, if we seem to have some data remaining, this
844		 * is not a problem.
845		 */
846		if (host->dma.xfer_done)
847			xfer_warn = 0;
848
849		if (xfer_warn) {
850		    switch (status_byte(SCpnt->result)) {
851		    case CHECK_CONDITION:
852		    case COMMAND_TERMINATED:
853		    case BUSY:
854		    case QUEUE_FULL:
855		    case RESERVATION_CONFLICT:
856			break;
857
858		    default:
859			printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
860				host->host->host_no, SCpnt->result);
861			__scsi_print_command(SCpnt->cmnd);
862			acornscsi_dumpdma(host, "done");
863		 	acornscsi_dumplog(host, SCpnt->device->id);
864			SCpnt->result &= 0xffff;
865			SCpnt->result |= DID_ERROR << 16;
866		    }
867		}
868	}
869
870	if (!SCpnt->scsi_done)
871	    panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
872
873	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
874
875	SCpnt->scsi_done(SCpnt);
876    } else
877	printk("scsi%d: null command in acornscsi_done", host->host->host_no);
878
879    host->scsi.phase = PHASE_IDLE;
880}
881
882/* ====================================================================================
883 * DMA routines
884 */
885/*
886 * Purpose  : update SCSI Data Pointer
887 * Notes    : this will only be one SG entry or less
888 */
889static
890void acornscsi_data_updateptr(AS_Host *host, struct scsi_pointer *SCp, unsigned int length)
891{
892    SCp->ptr += length;
893    SCp->this_residual -= length;
894
895    if (SCp->this_residual == 0 && next_SCp(SCp) == 0)
896	host->dma.xfer_done = 1;
897}
898
899/*
900 * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
901 *				unsigned int start_addr, unsigned int length)
902 * Purpose  : read data from DMA RAM
903 * Params   : host - host to transfer from
904 *	      ptr  - DRAM address
905 *	      start_addr - host mem address
906 *	      length - number of bytes to transfer
907 * Notes    : this will only be one SG entry or less
908 */
909static
910void acornscsi_data_read(AS_Host *host, char *ptr,
911				 unsigned int start_addr, unsigned int length)
912{
913    extern void __acornscsi_in(int port, char *buf, int len);
914    unsigned int page, offset, len = length;
915
916    page = (start_addr >> 12);
917    offset = start_addr & ((1 << 12) - 1);
918
919    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
920
921    while (len > 0) {
922	unsigned int this_len;
923
924	if (len + offset > (1 << 12))
925	    this_len = (1 << 12) - offset;
926	else
927	    this_len = len;
928
929	__acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
930
931	offset += this_len;
932	ptr += this_len;
933	len -= this_len;
934
935	if (offset == (1 << 12)) {
936	    offset = 0;
937	    page ++;
938	    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
939	}
940    }
941    outb(host->card.page_reg, host->card.io_page);
942}
943
944/*
945 * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
946 *				unsigned int start_addr, unsigned int length)
947 * Purpose  : write data to DMA RAM
948 * Params   : host - host to transfer from
949 *	      ptr  - DRAM address
950 *	      start_addr - host mem address
951 *	      length - number of bytes to transfer
952 * Notes    : this will only be one SG entry or less
953 */
954static
955void acornscsi_data_write(AS_Host *host, char *ptr,
956				 unsigned int start_addr, unsigned int length)
957{
958    extern void __acornscsi_out(int port, char *buf, int len);
959    unsigned int page, offset, len = length;
960
961    page = (start_addr >> 12);
962    offset = start_addr & ((1 << 12) - 1);
963
964    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
965
966    while (len > 0) {
967	unsigned int this_len;
968
969	if (len + offset > (1 << 12))
970	    this_len = (1 << 12) - offset;
971	else
972	    this_len = len;
973
974	__acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
975
976	offset += this_len;
977	ptr += this_len;
978	len -= this_len;
979
980	if (offset == (1 << 12)) {
981	    offset = 0;
982	    page ++;
983	    outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
984	}
985    }
986    outb(host->card.page_reg, host->card.io_page);
987}
988
989/* =========================================================================================
990 * On-board DMA routines
991 */
992#ifdef USE_DMAC
993/*
994 * Prototype: void acornscsi_dmastop(AS_Host *host)
995 * Purpose  : stop all DMA
996 * Params   : host - host on which to stop DMA
997 * Notes    : This is called when leaving DATA IN/OUT phase,
998 *	      or when interface is RESET
999 */
1000static inline
1001void acornscsi_dma_stop(AS_Host *host)
1002{
1003    dmac_write(host, DMAC_MASKREG, MASK_ON);
1004    dmac_clearintr(host);
1005
1006#if (DEBUG & DEBUG_DMA)
1007    DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
1008#endif
1009}
1010
1011/*
1012 * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1013 * Purpose : setup DMA controller for data transfer
1014 * Params  : host - host to setup
1015 *	     direction - data transfer direction
1016 * Notes   : This is called when entering DATA I/O phase, not
1017 *	     while we're in a DATA I/O phase
1018 */
1019static
1020void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1021{
1022    unsigned int address, length, mode;
1023
1024    host->dma.direction = direction;
1025
1026    dmac_write(host, DMAC_MASKREG, MASK_ON);
1027
1028    if (direction == DMA_OUT) {
1029#if (DEBUG & DEBUG_NO_WRITE)
1030	if (NO_WRITE & (1 << host->SCpnt->device->id)) {
1031	    printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
1032		    host->host->host_no, acornscsi_target(host));
1033	    return;
1034	}
1035#endif
1036	mode = DMAC_WRITE;
1037    } else
1038	mode = DMAC_READ;
1039
1040    /*
1041     * Allocate some buffer space, limited to half the buffer size
1042     */
1043    length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1044    if (length) {
1045	host->dma.start_addr = address = host->dma.free_addr;
1046	host->dma.free_addr = (host->dma.free_addr + length) &
1047				(DMAC_BUFFER_SIZE - 1);
1048
1049	/*
1050	 * Transfer data to DMA memory
1051	 */
1052	if (direction == DMA_OUT)
1053	    acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1054				length);
1055
1056	length -= 1;
1057	dmac_write(host, DMAC_TXCNTLO, length);
1058	dmac_write(host, DMAC_TXCNTHI, length >> 8);
1059	dmac_write(host, DMAC_TXADRLO, address);
1060	dmac_write(host, DMAC_TXADRMD, address >> 8);
1061	dmac_write(host, DMAC_TXADRHI, 0);
1062	dmac_write(host, DMAC_MODECON, mode);
1063	dmac_write(host, DMAC_MASKREG, MASK_OFF);
1064
1065#if (DEBUG & DEBUG_DMA)
1066	DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
1067#endif
1068	host->dma.xfer_setup = 1;
1069    }
1070}
1071
1072/*
1073 * Function: void acornscsi_dma_cleanup(AS_Host *host)
1074 * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
1075 * Params  : host - host to finish
1076 * Notes   : This is called when a command is:
1077 *		terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT
1078 *	   : This must not return until all transfers are completed.
1079 */
1080static
1081void acornscsi_dma_cleanup(AS_Host *host)
1082{
1083    dmac_write(host, DMAC_MASKREG, MASK_ON);
1084    dmac_clearintr(host);
1085
1086    /*
1087     * Check for a pending transfer
1088     */
1089    if (host->dma.xfer_required) {
1090	host->dma.xfer_required = 0;
1091	if (host->dma.direction == DMA_IN)
1092	    acornscsi_data_read(host, host->dma.xfer_ptr,
1093				 host->dma.xfer_start, host->dma.xfer_length);
1094    }
1095
1096    /*
1097     * Has a transfer been setup?
1098     */
1099    if (host->dma.xfer_setup) {
1100	unsigned int transferred;
1101
1102	host->dma.xfer_setup = 0;
1103
1104#if (DEBUG & DEBUG_DMA)
1105	DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
1106#endif
1107
1108	/*
1109	 * Calculate number of bytes transferred from DMA.
1110	 */
1111	transferred = dmac_address(host) - host->dma.start_addr;
1112	host->dma.transferred += transferred;
1113
1114	if (host->dma.direction == DMA_IN)
1115	    acornscsi_data_read(host, host->scsi.SCp.ptr,
1116				 host->dma.start_addr, transferred);
1117
1118	/*
1119	 * Update SCSI pointers
1120	 */
1121	acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1122#if (DEBUG & DEBUG_DMA)
1123	DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
1124#endif
1125    }
1126}
1127
1128/*
1129 * Function: void acornscsi_dmacintr(AS_Host *host)
1130 * Purpose : handle interrupts from DMAC device
1131 * Params  : host - host to process
1132 * Notes   : If reading, we schedule the read to main memory &
1133 *	     allow the transfer to continue.
1134 *	   : If writing, we fill the onboard DMA memory from main
1135 *	     memory.
1136 *	   : Called whenever DMAC finished it's current transfer.
1137 */
1138static
1139void acornscsi_dma_intr(AS_Host *host)
1140{
1141    unsigned int address, length, transferred;
1142
1143#if (DEBUG & DEBUG_DMA)
1144    DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
1145#endif
1146
1147    dmac_write(host, DMAC_MASKREG, MASK_ON);
1148    dmac_clearintr(host);
1149
1150    /*
1151     * Calculate amount transferred via DMA
1152     */
1153    transferred = dmac_address(host) - host->dma.start_addr;
1154    host->dma.transferred += transferred;
1155
1156    /*
1157     * Schedule DMA transfer off board
1158     */
1159    if (host->dma.direction == DMA_IN) {
1160	host->dma.xfer_start = host->dma.start_addr;
1161	host->dma.xfer_length = transferred;
1162	host->dma.xfer_ptr = host->scsi.SCp.ptr;
1163	host->dma.xfer_required = 1;
1164    }
1165
1166    acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1167
1168    /*
1169     * Allocate some buffer space, limited to half the on-board RAM size
1170     */
1171    length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1172    if (length) {
1173	host->dma.start_addr = address = host->dma.free_addr;
1174	host->dma.free_addr = (host->dma.free_addr + length) &
1175				(DMAC_BUFFER_SIZE - 1);
1176
1177	/*
1178	 * Transfer data to DMA memory
1179	 */
1180	if (host->dma.direction == DMA_OUT)
1181	    acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1182				length);
1183
1184	length -= 1;
1185	dmac_write(host, DMAC_TXCNTLO, length);
1186	dmac_write(host, DMAC_TXCNTHI, length >> 8);
1187	dmac_write(host, DMAC_TXADRLO, address);
1188	dmac_write(host, DMAC_TXADRMD, address >> 8);
1189	dmac_write(host, DMAC_TXADRHI, 0);
1190	dmac_write(host, DMAC_MASKREG, MASK_OFF);
1191
1192#if (DEBUG & DEBUG_DMA)
1193	DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
1194#endif
1195    } else {
1196	host->dma.xfer_setup = 0;
1197#if 0
1198	/*
1199	 * If the interface still wants more, then this is an error.
1200	 * We give it another byte, but we also attempt to raise an
1201	 * attention condition.  We continue giving one byte until
1202	 * the device recognises the attention.
1203	 */
1204	if (dmac_read(host, DMAC_STATUS) & STATUS_RQ0) {
1205	    acornscsi_abortcmd(host, host->SCpnt->tag);
1206
1207	    dmac_write(host, DMAC_TXCNTLO, 0);
1208	    dmac_write(host, DMAC_TXCNTHI, 0);
1209	    dmac_write(host, DMAC_TXADRLO, 0);
1210	    dmac_write(host, DMAC_TXADRMD, 0);
1211	    dmac_write(host, DMAC_TXADRHI, 0);
1212	    dmac_write(host, DMAC_MASKREG, MASK_OFF);
1213	}
1214#endif
1215    }
1216}
1217
1218/*
1219 * Function: void acornscsi_dma_xfer(AS_Host *host)
1220 * Purpose : transfer data between AcornSCSI and memory
1221 * Params  : host - host to process
1222 */
1223static
1224void acornscsi_dma_xfer(AS_Host *host)
1225{
1226    host->dma.xfer_required = 0;
1227
1228    if (host->dma.direction == DMA_IN)
1229	acornscsi_data_read(host, host->dma.xfer_ptr,
1230				host->dma.xfer_start, host->dma.xfer_length);
1231}
1232
1233/*
1234 * Function: void acornscsi_dma_adjust(AS_Host *host)
1235 * Purpose : adjust DMA pointers & count for bytes transferred to
1236 *	     SBIC but not SCSI bus.
1237 * Params  : host - host to adjust DMA count for
1238 */
1239static
1240void acornscsi_dma_adjust(AS_Host *host)
1241{
1242    if (host->dma.xfer_setup) {
1243	signed long transferred;
1244#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1245	DBG(host->SCpnt, acornscsi_dumpdma(host, "adji"));
1246#endif
1247	/*
1248	 * Calculate correct DMA address - DMA is ahead of SCSI bus while
1249	 * writing.
1250	 *  host->scsi.SCp.scsi_xferred is the number of bytes
1251	 *  actually transferred to/from the SCSI bus.
1252	 *  host->dma.transferred is the number of bytes transferred
1253	 *  over DMA since host->dma.start_addr was last set.
1254	 *
1255	 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
1256	 *		   - host->dma.transferred
1257	 */
1258	transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
1259	if (transferred < 0)
1260	    printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
1261		    host->host->host_no, acornscsi_target(host), transferred);
1262	else if (transferred == 0)
1263	    host->dma.xfer_setup = 0;
1264	else {
1265	    transferred += host->dma.start_addr;
1266	    dmac_write(host, DMAC_TXADRLO, transferred);
1267	    dmac_write(host, DMAC_TXADRMD, transferred >> 8);
1268	    dmac_write(host, DMAC_TXADRHI, transferred >> 16);
1269#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1270	    DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo"));
1271#endif
1272	}
1273    }
1274}
1275#endif
1276
1277/* =========================================================================================
1278 * Data I/O
1279 */
1280static int
1281acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
1282{
1283	unsigned int asr, timeout = max_timeout;
1284	int my_ptr = *ptr;
1285
1286	while (my_ptr < len) {
1287		asr = sbic_arm_read(host, SBIC_ASR);
1288
1289		if (asr & ASR_DBR) {
1290			timeout = max_timeout;
1291
1292			sbic_arm_write(host, SBIC_DATA, bytes[my_ptr++]);
1293		} else if (asr & ASR_INT)
1294			break;
1295		else if (--timeout == 0)
1296			break;
1297		udelay(1);
1298	}
1299
1300	*ptr = my_ptr;
1301
1302	return (timeout == 0) ? -1 : 0;
1303}
1304
1305/*
1306 * Function: void acornscsi_sendcommand(AS_Host *host)
1307 * Purpose : send a command to a target
1308 * Params  : host - host which is connected to target
1309 */
1310static void
1311acornscsi_sendcommand(AS_Host *host)
1312{
1313	struct scsi_cmnd *SCpnt = host->SCpnt;
1314
1315    sbic_arm_write(host, SBIC_TRANSCNTH, 0);
1316    sbic_arm_writenext(host, 0);
1317    sbic_arm_writenext(host, SCpnt->cmd_len - host->scsi.SCp.sent_command);
1318
1319    acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1320
1321    if (acornscsi_write_pio(host, SCpnt->cmnd,
1322	(int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000))
1323	printk("scsi%d: timeout while sending command\n", host->host->host_no);
1324
1325    host->scsi.phase = PHASE_COMMAND;
1326}
1327
1328static
1329void acornscsi_sendmessage(AS_Host *host)
1330{
1331    unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
1332    unsigned int msgnr;
1333    struct message *msg;
1334
1335#if (DEBUG & DEBUG_MESSAGES)
1336    printk("scsi%d.%c: sending message ",
1337	    host->host->host_no, acornscsi_target(host));
1338#endif
1339
1340    switch (message_length) {
1341    case 0:
1342	acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1343
1344	acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
1345
1346	sbic_arm_write(host, SBIC_DATA, NOP);
1347
1348	host->scsi.last_message = NOP;
1349#if (DEBUG & DEBUG_MESSAGES)
1350	printk("NOP");
1351#endif
1352	break;
1353
1354    case 1:
1355	acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1356	msg = msgqueue_getmsg(&host->scsi.msgs, 0);
1357
1358	acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
1359
1360	sbic_arm_write(host, SBIC_DATA, msg->msg[0]);
1361
1362	host->scsi.last_message = msg->msg[0];
1363#if (DEBUG & DEBUG_MESSAGES)
1364	spi_print_msg(msg->msg);
1365#endif
1366	break;
1367
1368    default:
1369	/*
1370	 * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14)
1371	 * 'When a target sends this (MESSAGE_REJECT) message, it
1372	 *  shall change to MESSAGE IN phase and send this message
1373	 *  prior to requesting additional message bytes from the
1374	 *  initiator.  This provides an interlock so that the
1375	 *  initiator can determine which message byte is rejected.
1376	 */
1377	sbic_arm_write(host, SBIC_TRANSCNTH, 0);
1378	sbic_arm_writenext(host, 0);
1379	sbic_arm_writenext(host, message_length);
1380	acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1381
1382	msgnr = 0;
1383	while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
1384	    unsigned int i;
1385#if (DEBUG & DEBUG_MESSAGES)
1386	    spi_print_msg(msg);
1387#endif
1388	    i = 0;
1389	    if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
1390		printk("scsi%d: timeout while sending message\n", host->host->host_no);
1391
1392	    host->scsi.last_message = msg->msg[0];
1393	    if (msg->msg[0] == EXTENDED_MESSAGE)
1394		host->scsi.last_message |= msg->msg[2] << 8;
1395
1396	    if (i != msg->length)
1397		break;
1398	}
1399	break;
1400    }
1401#if (DEBUG & DEBUG_MESSAGES)
1402    printk("\n");
1403#endif
1404}
1405
1406/*
1407 * Function: void acornscsi_readstatusbyte(AS_Host *host)
1408 * Purpose : Read status byte from connected target
1409 * Params  : host - host connected to target
1410 */
1411static
1412void acornscsi_readstatusbyte(AS_Host *host)
1413{
1414    acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT);
1415    acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte");
1416    host->scsi.SCp.Status = sbic_arm_read(host, SBIC_DATA);
1417}
1418
1419/*
1420 * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
1421 * Purpose : Read one message byte from connected target
1422 * Params  : host - host connected to target
1423 */
1424static
1425unsigned char acornscsi_readmessagebyte(AS_Host *host)
1426{
1427    unsigned char message;
1428
1429    acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1430
1431    acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
1432
1433    message = sbic_arm_read(host, SBIC_DATA);
1434
1435    /* wait for MSGIN-XFER-PAUSED */
1436    acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
1437
1438    sbic_arm_read(host, SBIC_SSR);
1439
1440    return message;
1441}
1442
1443/*
1444 * Function: void acornscsi_message(AS_Host *host)
1445 * Purpose : Read complete message from connected target & action message
1446 * Params  : host - host connected to target
1447 */
1448static
1449void acornscsi_message(AS_Host *host)
1450{
1451    unsigned char message[16];
1452    unsigned int msgidx = 0, msglen = 1;
1453
1454    do {
1455	message[msgidx] = acornscsi_readmessagebyte(host);
1456
1457	switch (msgidx) {
1458	case 0:
1459	    if (message[0] == EXTENDED_MESSAGE ||
1460		(message[0] >= 0x20 && message[0] <= 0x2f))
1461		msglen = 2;
1462	    break;
1463
1464	case 1:
1465	    if (message[0] == EXTENDED_MESSAGE)
1466		msglen += message[msgidx];
1467	    break;
1468	}
1469	msgidx += 1;
1470	if (msgidx < msglen) {
1471	    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1472
1473	    /* wait for next msg-in */
1474	    acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack");
1475	    sbic_arm_read(host, SBIC_SSR);
1476	}
1477    } while (msgidx < msglen);
1478
1479#if (DEBUG & DEBUG_MESSAGES)
1480    printk("scsi%d.%c: message in: ",
1481	    host->host->host_no, acornscsi_target(host));
1482    spi_print_msg(message);
1483    printk("\n");
1484#endif
1485
1486    if (host->scsi.phase == PHASE_RECONNECTED) {
1487	/*
1488	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1489	 * 'Whenever a target reconnects to an initiator to continue
1490	 *  a tagged I/O process, the SIMPLE QUEUE TAG message shall
1491	 *  be sent immediately following the IDENTIFY message...'
1492	 */
1493	if (message[0] == SIMPLE_QUEUE_TAG)
1494	    host->scsi.reconnected.tag = message[1];
1495	if (acornscsi_reconnect_finish(host))
1496	    host->scsi.phase = PHASE_MSGIN;
1497    }
1498
1499    switch (message[0]) {
1500    case ABORT:
1501    case ABORT_TAG:
1502    case COMMAND_COMPLETE:
1503	if (host->scsi.phase != PHASE_STATUSIN) {
1504	    printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
1505		    host->host->host_no, acornscsi_target(host));
1506	    acornscsi_dumplog(host, host->SCpnt->device->id);
1507	}
1508	host->scsi.phase = PHASE_DONE;
1509	host->scsi.SCp.Message = message[0];
1510	break;
1511
1512    case SAVE_POINTERS:
1513	/*
1514	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20)
1515	 * 'The SAVE DATA POINTER message is sent from a target to
1516	 *  direct the initiator to copy the active data pointer to
1517	 *  the saved data pointer for the current I/O process.
1518	 */
1519	acornscsi_dma_cleanup(host);
1520	host->SCpnt->SCp = host->scsi.SCp;
1521	host->SCpnt->SCp.sent_command = 0;
1522	host->scsi.phase = PHASE_MSGIN;
1523	break;
1524
1525    case RESTORE_POINTERS:
1526	/*
1527	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19)
1528	 * 'The RESTORE POINTERS message is sent from a target to
1529	 *  direct the initiator to copy the most recently saved
1530	 *  command, data, and status pointers for the I/O process
1531	 *  to the corresponding active pointers.  The command and
1532	 *  status pointers shall be restored to the beginning of
1533	 *  the present command and status areas.'
1534	 */
1535	acornscsi_dma_cleanup(host);
1536	host->scsi.SCp = host->SCpnt->SCp;
1537	host->scsi.phase = PHASE_MSGIN;
1538	break;
1539
1540    case DISCONNECT:
1541	/*
1542	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2)
1543	 * 'On those occasions when an error or exception condition occurs
1544	 *  and the target elects to repeat the information transfer, the
1545	 *  target may repeat the transfer either issuing a RESTORE POINTERS
1546	 *  message or by disconnecting without issuing a SAVE POINTERS
1547	 *  message.  When reconnection is completed, the most recent
1548	 *  saved pointer values are restored.'
1549	 */
1550	acornscsi_dma_cleanup(host);
1551	host->scsi.phase = PHASE_DISCONNECT;
1552	break;
1553
1554    case MESSAGE_REJECT:
1555#if 0 /* this isn't needed any more */
1556	/*
1557	 * If we were negociating sync transfer, we don't yet know if
1558	 * this REJECT is for the sync transfer or for the tagged queue/wide
1559	 * transfer.  Re-initiate sync transfer negociation now, and if
1560	 * we got a REJECT in response to SDTR, then it'll be set to DONE.
1561	 */
1562	if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST)
1563	    host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE;
1564#endif
1565
1566	/*
1567	 * If we have any messages waiting to go out, then assert ATN now
1568	 */
1569	if (msgqueue_msglength(&host->scsi.msgs))
1570	    acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1571
1572	switch (host->scsi.last_message) {
1573#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1574	case HEAD_OF_QUEUE_TAG:
1575	case ORDERED_QUEUE_TAG:
1576	case SIMPLE_QUEUE_TAG:
1577	    /*
1578	     * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1579	     *  If a target does not implement tagged queuing and a queue tag
1580	     *  message is received, it shall respond with a MESSAGE REJECT
1581	     *  message and accept the I/O process as if it were untagged.
1582	     */
1583	    printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
1584		    host->host->host_no, acornscsi_target(host));
1585	    host->SCpnt->device->simple_tags = 0;
1586	    set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
1587	    break;
1588#endif
1589	case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
1590	    /*
1591	     * Target can't handle synchronous transfers
1592	     */
1593	    printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
1594		    host->host->host_no, acornscsi_target(host));
1595	    host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA;
1596	    host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS;
1597	    sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1598	    break;
1599
1600	default:
1601	    break;
1602	}
1603	break;
1604
1605    case QUEUE_FULL:
1606	/* TODO: target queue is full */
1607	break;
1608
1609    case SIMPLE_QUEUE_TAG:
1610	/* tag queue reconnect... message[1] = queue tag.  Print something to indicate something happened! */
1611	printk("scsi%d.%c: reconnect queue tag %02X\n",
1612		host->host->host_no, acornscsi_target(host),
1613		message[1]);
1614	break;
1615
1616    case EXTENDED_MESSAGE:
1617	switch (message[2]) {
1618#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1619	case EXTENDED_SDTR:
1620	    if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) {
1621		/*
1622		 * We requested synchronous transfers.  This isn't quite right...
1623		 * We can only say if this succeeded if we proceed on to execute the
1624		 * command from this message.  If we get a MESSAGE PARITY ERROR,
1625		 * and the target retries fail, then we fallback to asynchronous mode
1626		 */
1627		host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED;
1628		printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
1629			host->host->host_no, acornscsi_target(host),
1630			message[4], message[3] * 4);
1631		host->device[host->SCpnt->device->id].sync_xfer =
1632			calc_sync_xfer(message[3] * 4, message[4]);
1633	    } else {
1634		unsigned char period, length;
1635		/*
1636		 * Target requested synchronous transfers.  The agreement is only
1637		 * to be in operation AFTER the target leaves message out phase.
1638		 */
1639		acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1640		period = max_t(unsigned int, message[3], sdtr_period / 4);
1641		length = min_t(unsigned int, message[4], sdtr_size);
1642		msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
1643				 EXTENDED_SDTR, period, length);
1644		host->device[host->SCpnt->device->id].sync_xfer =
1645			calc_sync_xfer(period * 4, length);
1646	    }
1647	    sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1648	    break;
1649#else
1650	    /* We do not accept synchronous transfers.  Respond with a
1651	     * MESSAGE_REJECT.
1652	     */
1653#endif
1654
1655	case EXTENDED_WDTR:
1656	    /* The WD33C93A is only 8-bit.  We respond with a MESSAGE_REJECT
1657	     * to a wide data transfer request.
1658	     */
1659	default:
1660	    acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1661	    msgqueue_flush(&host->scsi.msgs);
1662	    msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1663	    break;
1664	}
1665	break;
1666
1667#ifdef CONFIG_SCSI_ACORNSCSI_LINK
1668    case LINKED_CMD_COMPLETE:
1669    case LINKED_FLG_CMD_COMPLETE:
1670	/*
1671	 * We don't support linked commands yet
1672	 */
1673	if (0) {
1674#if (DEBUG & DEBUG_LINK)
1675	    printk("scsi%d.%c: lun %d tag %d linked command complete\n",
1676		    host->host->host_no, acornscsi_target(host), host->SCpnt->tag);
1677#endif
1678	    /*
1679	     * A linked command should only terminate with one of these messages
1680	     * if there are more linked commands available.
1681	     */
1682	    if (!host->SCpnt->next_link) {
1683		printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
1684			instance->host_no, acornscsi_target(host), host->SCpnt->tag);
1685		acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1686		msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1687	    } else {
1688		struct scsi_cmnd *SCpnt = host->SCpnt;
1689
1690		acornscsi_dma_cleanup(host);
1691
1692		host->SCpnt = host->SCpnt->next_link;
1693		host->SCpnt->tag = SCpnt->tag;
1694		SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;
1695		SCpnt->done(SCpnt);
1696
1697		/* initialise host->SCpnt->SCp */
1698	    }
1699	    break;
1700	}
1701#endif
1702
1703    default: /* reject message */
1704	printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
1705		host->host->host_no, acornscsi_target(host),
1706		message[0]);
1707	acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1708	msgqueue_flush(&host->scsi.msgs);
1709	msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1710	host->scsi.phase = PHASE_MSGIN;
1711	break;
1712    }
1713    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1714}
1715
1716/*
1717 * Function: int acornscsi_buildmessages(AS_Host *host)
1718 * Purpose : build the connection messages for a host
1719 * Params  : host - host to add messages to
1720 */
1721static
1722void acornscsi_buildmessages(AS_Host *host)
1723{
1724#if 0
1725    /* does the device need resetting? */
1726    if (cmd_reset) {
1727	msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
1728	return;
1729    }
1730#endif
1731
1732    msgqueue_addmsg(&host->scsi.msgs, 1,
1733		     IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok,
1734			     host->SCpnt->device->lun));
1735
1736#if 0
1737    /* does the device need the current command aborted */
1738    if (cmd_aborted) {
1739	acornscsi_abortcmd(host->SCpnt->tag);
1740	return;
1741    }
1742#endif
1743
1744#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1745    if (host->SCpnt->tag) {
1746	unsigned int tag_type;
1747
1748	if (host->SCpnt->cmnd[0] == REQUEST_SENSE ||
1749	    host->SCpnt->cmnd[0] == TEST_UNIT_READY ||
1750	    host->SCpnt->cmnd[0] == INQUIRY)
1751	    tag_type = HEAD_OF_QUEUE_TAG;
1752	else
1753	    tag_type = SIMPLE_QUEUE_TAG;
1754	msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
1755    }
1756#endif
1757
1758#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1759    if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) {
1760	host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST;
1761	msgqueue_addmsg(&host->scsi.msgs, 5,
1762			 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1763			 sdtr_period / 4, sdtr_size);
1764    }
1765#endif
1766}
1767
1768/*
1769 * Function: int acornscsi_starttransfer(AS_Host *host)
1770 * Purpose : transfer data to/from connected target
1771 * Params  : host - host to which target is connected
1772 * Returns : 0 if failure
1773 */
1774static
1775int acornscsi_starttransfer(AS_Host *host)
1776{
1777    int residual;
1778
1779    if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {
1780	printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
1781		host->host->host_no, acornscsi_target(host));
1782	return 0;
1783    }
1784
1785    residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred;
1786
1787    sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1788    sbic_arm_writenext(host, residual >> 16);
1789    sbic_arm_writenext(host, residual >> 8);
1790    sbic_arm_writenext(host, residual);
1791    acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1792    return 1;
1793}
1794
1795/* =========================================================================================
1796 * Connection & Disconnection
1797 */
1798/*
1799 * Function : acornscsi_reconnect(AS_Host *host)
1800 * Purpose  : reconnect a previously disconnected command
1801 * Params   : host - host specific data
1802 * Remarks  : SCSI spec says:
1803 *		'The set of active pointers is restored from the set
1804 *		 of saved pointers upon reconnection of the I/O process'
1805 */
1806static
1807int acornscsi_reconnect(AS_Host *host)
1808{
1809    unsigned int target, lun, ok = 0;
1810
1811    target = sbic_arm_read(host, SBIC_SOURCEID);
1812
1813    if (!(target & 8))
1814	printk(KERN_ERR "scsi%d: invalid source id after reselection "
1815		"- device fault?\n",
1816		host->host->host_no);
1817
1818    target &= 7;
1819
1820    if (host->SCpnt && !host->scsi.disconnectable) {
1821	printk(KERN_ERR "scsi%d.%d: reconnected while command in "
1822		"progress to target %d?\n",
1823		host->host->host_no, target, host->SCpnt->device->id);
1824	host->SCpnt = NULL;
1825    }
1826
1827    lun = sbic_arm_read(host, SBIC_DATA) & 7;
1828
1829    host->scsi.reconnected.target = target;
1830    host->scsi.reconnected.lun = lun;
1831    host->scsi.reconnected.tag = 0;
1832
1833    if (host->scsi.disconnectable && host->SCpnt &&
1834	host->SCpnt->device->id == target && host->SCpnt->device->lun == lun)
1835	ok = 1;
1836
1837    if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
1838	ok = 1;
1839
1840    ADD_STATUS(target, 0x81, host->scsi.phase, 0);
1841
1842    if (ok) {
1843	host->scsi.phase = PHASE_RECONNECTED;
1844    } else {
1845	/* this doesn't seem to work */
1846	printk(KERN_ERR "scsi%d.%c: reselected with no command "
1847		"to reconnect with\n",
1848		host->host->host_no, '0' + target);
1849	acornscsi_dumplog(host, target);
1850	acornscsi_abortcmd(host, 0);
1851	if (host->SCpnt) {
1852	    queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1853	    host->SCpnt = NULL;
1854	}
1855    }
1856    acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1857    return !ok;
1858}
1859
1860/*
1861 * Function: int acornscsi_reconect_finish(AS_Host *host)
1862 * Purpose : finish reconnecting a command
1863 * Params  : host - host to complete
1864 * Returns : 0 if failed
1865 */
1866static
1867int acornscsi_reconnect_finish(AS_Host *host)
1868{
1869    if (host->scsi.disconnectable && host->SCpnt) {
1870	host->scsi.disconnectable = 0;
1871	if (host->SCpnt->device->id  == host->scsi.reconnected.target &&
1872	    host->SCpnt->device->lun == host->scsi.reconnected.lun &&
1873	    host->SCpnt->tag         == host->scsi.reconnected.tag) {
1874#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1875	    DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
1876		    host->host->host_no, acornscsi_target(host)));
1877#endif
1878	} else {
1879	    queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1880#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1881	    DBG(host->SCpnt, printk("scsi%d.%c: had to move command "
1882		    "to disconnected queue\n",
1883		    host->host->host_no, acornscsi_target(host)));
1884#endif
1885	    host->SCpnt = NULL;
1886	}
1887    }
1888    if (!host->SCpnt) {
1889	host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected,
1890				host->scsi.reconnected.target,
1891				host->scsi.reconnected.lun,
1892				host->scsi.reconnected.tag);
1893#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1894	DBG(host->SCpnt, printk("scsi%d.%c: had to get command",
1895		host->host->host_no, acornscsi_target(host)));
1896#endif
1897    }
1898
1899    if (!host->SCpnt)
1900	acornscsi_abortcmd(host, host->scsi.reconnected.tag);
1901    else {
1902	/*
1903	 * Restore data pointer from SAVED pointers.
1904	 */
1905	host->scsi.SCp = host->SCpnt->SCp;
1906#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1907	printk(", data pointers: [%p, %X]",
1908		host->scsi.SCp.ptr, host->scsi.SCp.this_residual);
1909#endif
1910    }
1911#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1912    printk("\n");
1913#endif
1914
1915    host->dma.transferred = host->scsi.SCp.scsi_xferred;
1916
1917    return host->SCpnt != NULL;
1918}
1919
1920/*
1921 * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
1922 * Purpose : handle an unexpected disconnect
1923 * Params  : host - host on which disconnect occurred
1924 */
1925static
1926void acornscsi_disconnect_unexpected(AS_Host *host)
1927{
1928    printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n",
1929	    host->host->host_no, acornscsi_target(host));
1930#if (DEBUG & DEBUG_ABORT)
1931    acornscsi_dumplog(host, 8);
1932#endif
1933
1934    acornscsi_done(host, &host->SCpnt, DID_ERROR);
1935}
1936
1937/*
1938 * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
1939 * Purpose : abort a currently executing command
1940 * Params  : host - host with connected command to abort
1941 *	     tag  - tag to abort
1942 */
1943static
1944void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
1945{
1946    host->scsi.phase = PHASE_ABORTED;
1947    sbic_arm_write(host, SBIC_CMND, CMND_ASSERTATN);
1948
1949    msgqueue_flush(&host->scsi.msgs);
1950#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1951    if (tag)
1952	msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
1953    else
1954#endif
1955	msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1956}
1957
1958/* ==========================================================================================
1959 * Interrupt routines.
1960 */
1961/*
1962 * Function: int acornscsi_sbicintr(AS_Host *host)
1963 * Purpose : handle interrupts from SCSI device
1964 * Params  : host - host to process
1965 * Returns : INTR_PROCESS if expecting another SBIC interrupt
1966 *	     INTR_IDLE if no interrupt
1967 *	     INTR_NEXT_COMMAND if we have finished processing the command
1968 */
1969static
1970intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
1971{
1972    unsigned int asr, ssr;
1973
1974    asr = sbic_arm_read(host, SBIC_ASR);
1975    if (!(asr & ASR_INT))
1976	return INTR_IDLE;
1977
1978    ssr = sbic_arm_read(host, SBIC_SSR);
1979
1980#if (DEBUG & DEBUG_PHASES)
1981    print_sbic_status(asr, ssr, host->scsi.phase);
1982#endif
1983
1984    ADD_STATUS(8, ssr, host->scsi.phase, in_irq);
1985
1986    if (host->SCpnt && !host->scsi.disconnectable)
1987	ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
1988
1989    switch (ssr) {
1990    case 0x00:				/* reset state - not advanced			*/
1991	printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
1992		host->host->host_no);
1993	/* setup sbic - WD33C93A */
1994	sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id);
1995	sbic_arm_write(host, SBIC_CMND, CMND_RESET);
1996	return INTR_IDLE;
1997
1998    case 0x01:				/* reset state - advanced			*/
1999	sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI);
2000	sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME);
2001	sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
2002	sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
2003	msgqueue_flush(&host->scsi.msgs);
2004	return INTR_IDLE;
2005
2006    case 0x41:				/* unexpected disconnect aborted command	*/
2007	acornscsi_disconnect_unexpected(host);
2008	return INTR_NEXT_COMMAND;
2009    }
2010
2011    switch (host->scsi.phase) {
2012    case PHASE_CONNECTING:		/* STATE: command removed from issue queue	*/
2013	switch (ssr) {
2014	case 0x11:			/* -> PHASE_CONNECTED				*/
2015	    /* BUS FREE -> SELECTION */
2016	    host->scsi.phase = PHASE_CONNECTED;
2017	    msgqueue_flush(&host->scsi.msgs);
2018	    host->dma.transferred = host->scsi.SCp.scsi_xferred;
2019	    /* 33C93 gives next interrupt indicating bus phase */
2020	    asr = sbic_arm_read(host, SBIC_ASR);
2021	    if (!(asr & ASR_INT))
2022		break;
2023	    ssr = sbic_arm_read(host, SBIC_SSR);
2024	    ADD_STATUS(8, ssr, host->scsi.phase, 1);
2025	    ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1);
2026	    goto connected;
2027
2028	case 0x42:			/* select timed out				*/
2029					/* -> PHASE_IDLE				*/
2030	    acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
2031	    return INTR_NEXT_COMMAND;
2032
2033	case 0x81:			/* -> PHASE_RECONNECTED or PHASE_ABORTED	*/
2034	    /* BUS FREE -> RESELECTION */
2035	    host->origSCpnt = host->SCpnt;
2036	    host->SCpnt = NULL;
2037	    msgqueue_flush(&host->scsi.msgs);
2038	    acornscsi_reconnect(host);
2039	    break;
2040
2041	default:
2042	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
2043		    host->host->host_no, acornscsi_target(host), ssr);
2044	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2045	    acornscsi_abortcmd(host, host->SCpnt->tag);
2046	}
2047	return INTR_PROCESSING;
2048
2049    connected:
2050    case PHASE_CONNECTED:		/* STATE: device selected ok			*/
2051	switch (ssr) {
2052#ifdef NONSTANDARD
2053	case 0x8a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
2054	    /* SELECTION -> COMMAND */
2055	    acornscsi_sendcommand(host);
2056	    break;
2057
2058	case 0x8b:			/* -> PHASE_STATUS				*/
2059	    /* SELECTION -> STATUS */
2060	    acornscsi_readstatusbyte(host);
2061	    host->scsi.phase = PHASE_STATUSIN;
2062	    break;
2063#endif
2064
2065	case 0x8e:			/* -> PHASE_MSGOUT				*/
2066	    /* SELECTION ->MESSAGE OUT */
2067	    host->scsi.phase = PHASE_MSGOUT;
2068	    acornscsi_buildmessages(host);
2069	    acornscsi_sendmessage(host);
2070	    break;
2071
2072	/* these should not happen */
2073	case 0x85:			/* target disconnected				*/
2074	    acornscsi_done(host, &host->SCpnt, DID_ERROR);
2075	    break;
2076
2077	default:
2078	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
2079		    host->host->host_no, acornscsi_target(host), ssr);
2080	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2081	    acornscsi_abortcmd(host, host->SCpnt->tag);
2082	}
2083	return INTR_PROCESSING;
2084
2085    case PHASE_MSGOUT:			/* STATE: connected & sent IDENTIFY message	*/
2086	/*
2087	 * SCSI standard says that MESSAGE OUT phases can be followed by a
2088	 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
2089	 */
2090	switch (ssr) {
2091	case 0x8a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
2092	case 0x1a:			/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
2093	    /* MESSAGE OUT -> COMMAND */
2094	    acornscsi_sendcommand(host);
2095	    break;
2096
2097	case 0x8b:			/* -> PHASE_STATUS				*/
2098	case 0x1b:			/* -> PHASE_STATUS				*/
2099	    /* MESSAGE OUT -> STATUS */
2100	    acornscsi_readstatusbyte(host);
2101	    host->scsi.phase = PHASE_STATUSIN;
2102	    break;
2103
2104	case 0x8e:			/* -> PHASE_MSGOUT				*/
2105	    /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
2106	    acornscsi_sendmessage(host);
2107	    break;
2108
2109	case 0x4f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2110	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2111	    /* MESSAGE OUT -> MESSAGE IN */
2112	    acornscsi_message(host);
2113	    break;
2114
2115	default:
2116	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
2117		    host->host->host_no, acornscsi_target(host), ssr);
2118	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2119	}
2120	return INTR_PROCESSING;
2121
2122    case PHASE_COMMAND: 		/* STATE: connected & command sent		*/
2123	switch (ssr) {
2124	case 0x18:			/* -> PHASE_DATAOUT				*/
2125	    /* COMMAND -> DATA OUT */
2126	    if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2127		acornscsi_abortcmd(host, host->SCpnt->tag);
2128	    acornscsi_dma_setup(host, DMA_OUT);
2129	    if (!acornscsi_starttransfer(host))
2130		acornscsi_abortcmd(host, host->SCpnt->tag);
2131	    host->scsi.phase = PHASE_DATAOUT;
2132	    return INTR_IDLE;
2133
2134	case 0x19:			/* -> PHASE_DATAIN				*/
2135	    /* COMMAND -> DATA IN */
2136	    if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2137		acornscsi_abortcmd(host, host->SCpnt->tag);
2138	    acornscsi_dma_setup(host, DMA_IN);
2139	    if (!acornscsi_starttransfer(host))
2140		acornscsi_abortcmd(host, host->SCpnt->tag);
2141	    host->scsi.phase = PHASE_DATAIN;
2142	    return INTR_IDLE;
2143
2144	case 0x1b:			/* -> PHASE_STATUS				*/
2145	    /* COMMAND -> STATUS */
2146	    acornscsi_readstatusbyte(host);
2147	    host->scsi.phase = PHASE_STATUSIN;
2148	    break;
2149
2150	case 0x1e:			/* -> PHASE_MSGOUT				*/
2151	    /* COMMAND -> MESSAGE OUT */
2152	    acornscsi_sendmessage(host);
2153	    break;
2154
2155	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2156	    /* COMMAND -> MESSAGE IN */
2157	    acornscsi_message(host);
2158	    break;
2159
2160	default:
2161	    printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
2162		    host->host->host_no, acornscsi_target(host), ssr);
2163	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2164	}
2165	return INTR_PROCESSING;
2166
2167    case PHASE_DISCONNECT:		/* STATE: connected, received DISCONNECT msg	*/
2168	if (ssr == 0x85) {		/* -> PHASE_IDLE				*/
2169	    host->scsi.disconnectable = 1;
2170	    host->scsi.reconnected.tag = 0;
2171	    host->scsi.phase = PHASE_IDLE;
2172	    host->stats.disconnects += 1;
2173	} else {
2174	    printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
2175		    host->host->host_no, acornscsi_target(host), ssr);
2176	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2177	}
2178	return INTR_NEXT_COMMAND;
2179
2180    case PHASE_IDLE:			/* STATE: disconnected				*/
2181	if (ssr == 0x81)		/* -> PHASE_RECONNECTED or PHASE_ABORTED	*/
2182	    acornscsi_reconnect(host);
2183	else {
2184	    printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
2185		    host->host->host_no, acornscsi_target(host), ssr);
2186	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2187	}
2188	return INTR_PROCESSING;
2189
2190    case PHASE_RECONNECTED:		/* STATE: device reconnected to initiator	*/
2191	/*
2192	 * Command reconnected - if MESGIN, get message - it may be
2193	 * the tag.  If not, get command out of disconnected queue
2194	 */
2195	/*
2196	 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
2197	 * reconnect I_T_L command
2198	 */
2199	if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
2200	    return INTR_IDLE;
2201	ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
2202	switch (ssr) {
2203	case 0x88:			/* data out phase				*/
2204					/* -> PHASE_DATAOUT				*/
2205	    /* MESSAGE IN -> DATA OUT */
2206	    acornscsi_dma_setup(host, DMA_OUT);
2207	    if (!acornscsi_starttransfer(host))
2208		acornscsi_abortcmd(host, host->SCpnt->tag);
2209	    host->scsi.phase = PHASE_DATAOUT;
2210	    return INTR_IDLE;
2211
2212	case 0x89:			/* data in phase				*/
2213					/* -> PHASE_DATAIN				*/
2214	    /* MESSAGE IN -> DATA IN */
2215	    acornscsi_dma_setup(host, DMA_IN);
2216	    if (!acornscsi_starttransfer(host))
2217		acornscsi_abortcmd(host, host->SCpnt->tag);
2218	    host->scsi.phase = PHASE_DATAIN;
2219	    return INTR_IDLE;
2220
2221	case 0x8a:			/* command out					*/
2222	    /* MESSAGE IN -> COMMAND */
2223	    acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED	*/
2224	    break;
2225
2226	case 0x8b:			/* status in					*/
2227					/* -> PHASE_STATUSIN				*/
2228	    /* MESSAGE IN -> STATUS */
2229	    acornscsi_readstatusbyte(host);
2230	    host->scsi.phase = PHASE_STATUSIN;
2231	    break;
2232
2233	case 0x8e:			/* message out					*/
2234					/* -> PHASE_MSGOUT				*/
2235	    /* MESSAGE IN -> MESSAGE OUT */
2236	    acornscsi_sendmessage(host);
2237	    break;
2238
2239	case 0x8f:			/* message in					*/
2240	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2241	    break;
2242
2243	default:
2244	    printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
2245		    host->host->host_no, acornscsi_target(host), ssr);
2246	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2247	}
2248	return INTR_PROCESSING;
2249
2250    case PHASE_DATAIN:			/* STATE: transferred data in			*/
2251	/*
2252	 * This is simple - if we disconnect then the DMA address & count is
2253	 * correct.
2254	 */
2255	switch (ssr) {
2256	case 0x19:			/* -> PHASE_DATAIN				*/
2257	case 0x89:			/* -> PHASE_DATAIN				*/
2258	    acornscsi_abortcmd(host, host->SCpnt->tag);
2259	    return INTR_IDLE;
2260
2261	case 0x1b:			/* -> PHASE_STATUSIN				*/
2262	case 0x4b:			/* -> PHASE_STATUSIN				*/
2263	case 0x8b:			/* -> PHASE_STATUSIN				*/
2264	    /* DATA IN -> STATUS */
2265	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2266					  acornscsi_sbic_xfcount(host);
2267	    acornscsi_dma_stop(host);
2268	    acornscsi_readstatusbyte(host);
2269	    host->scsi.phase = PHASE_STATUSIN;
2270	    break;
2271
2272	case 0x1e:			/* -> PHASE_MSGOUT				*/
2273	case 0x4e:			/* -> PHASE_MSGOUT				*/
2274	case 0x8e:			/* -> PHASE_MSGOUT				*/
2275	    /* DATA IN -> MESSAGE OUT */
2276	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2277					  acornscsi_sbic_xfcount(host);
2278	    acornscsi_dma_stop(host);
2279	    acornscsi_sendmessage(host);
2280	    break;
2281
2282	case 0x1f:			/* message in					*/
2283	case 0x4f:			/* message in					*/
2284	case 0x8f:			/* message in					*/
2285	    /* DATA IN -> MESSAGE IN */
2286	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2287					  acornscsi_sbic_xfcount(host);
2288	    acornscsi_dma_stop(host);
2289	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2290	    break;
2291
2292	default:
2293	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
2294		    host->host->host_no, acornscsi_target(host), ssr);
2295	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2296	}
2297	return INTR_PROCESSING;
2298
2299    case PHASE_DATAOUT: 		/* STATE: transferred data out			*/
2300	/*
2301	 * This is more complicated - if we disconnect, the DMA could be 12
2302	 * bytes ahead of us.  We need to correct this.
2303	 */
2304	switch (ssr) {
2305	case 0x18:			/* -> PHASE_DATAOUT				*/
2306	case 0x88:			/* -> PHASE_DATAOUT				*/
2307	    acornscsi_abortcmd(host, host->SCpnt->tag);
2308	    return INTR_IDLE;
2309
2310	case 0x1b:			/* -> PHASE_STATUSIN				*/
2311	case 0x4b:			/* -> PHASE_STATUSIN				*/
2312	case 0x8b:			/* -> PHASE_STATUSIN				*/
2313	    /* DATA OUT -> STATUS */
2314	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2315					  acornscsi_sbic_xfcount(host);
2316	    acornscsi_dma_stop(host);
2317	    acornscsi_dma_adjust(host);
2318	    acornscsi_readstatusbyte(host);
2319	    host->scsi.phase = PHASE_STATUSIN;
2320	    break;
2321
2322	case 0x1e:			/* -> PHASE_MSGOUT				*/
2323	case 0x4e:			/* -> PHASE_MSGOUT				*/
2324	case 0x8e:			/* -> PHASE_MSGOUT				*/
2325	    /* DATA OUT -> MESSAGE OUT */
2326	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2327					  acornscsi_sbic_xfcount(host);
2328	    acornscsi_dma_stop(host);
2329	    acornscsi_dma_adjust(host);
2330	    acornscsi_sendmessage(host);
2331	    break;
2332
2333	case 0x1f:			/* message in					*/
2334	case 0x4f:			/* message in					*/
2335	case 0x8f:			/* message in					*/
2336	    /* DATA OUT -> MESSAGE IN */
2337	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
2338					  acornscsi_sbic_xfcount(host);
2339	    acornscsi_dma_stop(host);
2340	    acornscsi_dma_adjust(host);
2341	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
2342	    break;
2343
2344	default:
2345	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
2346		    host->host->host_no, acornscsi_target(host), ssr);
2347	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2348	}
2349	return INTR_PROCESSING;
2350
2351    case PHASE_STATUSIN:		/* STATE: status in complete			*/
2352	switch (ssr) {
2353	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2354	case 0x8f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2355	    /* STATUS -> MESSAGE IN */
2356	    acornscsi_message(host);
2357	    break;
2358
2359	case 0x1e:			/* -> PHASE_MSGOUT				*/
2360	case 0x8e:			/* -> PHASE_MSGOUT				*/
2361	    /* STATUS -> MESSAGE OUT */
2362	    acornscsi_sendmessage(host);
2363	    break;
2364
2365	default:
2366	    printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
2367		    host->host->host_no, acornscsi_target(host), ssr);
2368	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2369	}
2370	return INTR_PROCESSING;
2371
2372    case PHASE_MSGIN:			/* STATE: message in				*/
2373	switch (ssr) {
2374	case 0x1e:			/* -> PHASE_MSGOUT				*/
2375	case 0x4e:			/* -> PHASE_MSGOUT				*/
2376	case 0x8e:			/* -> PHASE_MSGOUT				*/
2377	    /* MESSAGE IN -> MESSAGE OUT */
2378	    acornscsi_sendmessage(host);
2379	    break;
2380
2381	case 0x1f:			/* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2382	case 0x2f:
2383	case 0x4f:
2384	case 0x8f:
2385	    acornscsi_message(host);
2386	    break;
2387
2388	case 0x85:
2389	    printk("scsi%d.%c: strange message in disconnection\n",
2390		host->host->host_no, acornscsi_target(host));
2391	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2392	    acornscsi_done(host, &host->SCpnt, DID_ERROR);
2393	    break;
2394
2395	default:
2396	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
2397		    host->host->host_no, acornscsi_target(host), ssr);
2398	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2399	}
2400	return INTR_PROCESSING;
2401
2402    case PHASE_DONE:			/* STATE: received status & message		*/
2403	switch (ssr) {
2404	case 0x85:			/* -> PHASE_IDLE				*/
2405	    acornscsi_done(host, &host->SCpnt, DID_OK);
2406	    return INTR_NEXT_COMMAND;
2407
2408	case 0x1e:
2409	case 0x8e:
2410	    acornscsi_sendmessage(host);
2411	    break;
2412
2413	default:
2414	    printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
2415		    host->host->host_no, acornscsi_target(host), ssr);
2416	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2417	}
2418	return INTR_PROCESSING;
2419
2420    case PHASE_ABORTED:
2421	switch (ssr) {
2422	case 0x85:
2423	    if (host->SCpnt)
2424		acornscsi_done(host, &host->SCpnt, DID_ABORT);
2425	    else {
2426		clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
2427			  host->busyluns);
2428		host->scsi.phase = PHASE_IDLE;
2429	    }
2430	    return INTR_NEXT_COMMAND;
2431
2432	case 0x1e:
2433	case 0x2e:
2434	case 0x4e:
2435	case 0x8e:
2436	    acornscsi_sendmessage(host);
2437	    break;
2438
2439	default:
2440	    printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
2441		    host->host->host_no, acornscsi_target(host), ssr);
2442	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2443	}
2444	return INTR_PROCESSING;
2445
2446    default:
2447	printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
2448		host->host->host_no, acornscsi_target(host), ssr);
2449	acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2450    }
2451    return INTR_PROCESSING;
2452}
2453
2454/*
2455 * Prototype: void acornscsi_intr(int irq, void *dev_id)
2456 * Purpose  : handle interrupts from Acorn SCSI card
2457 * Params   : irq    - interrupt number
2458 *	      dev_id - device specific data (AS_Host structure)
2459 */
2460static irqreturn_t
2461acornscsi_intr(int irq, void *dev_id)
2462{
2463    AS_Host *host = (AS_Host *)dev_id;
2464    intr_ret_t ret;
2465    int iostatus;
2466    int in_irq = 0;
2467
2468    do {
2469	ret = INTR_IDLE;
2470
2471	iostatus = inb(host->card.io_intr);
2472
2473	if (iostatus & 2) {
2474	    acornscsi_dma_intr(host);
2475	    iostatus = inb(host->card.io_intr);
2476	}
2477
2478	if (iostatus & 8)
2479	    ret = acornscsi_sbicintr(host, in_irq);
2480
2481	/*
2482	 * If we have a transfer pending, start it.
2483	 * Only start it if the interface has already started transferring
2484	 * it's data
2485	 */
2486	if (host->dma.xfer_required)
2487	    acornscsi_dma_xfer(host);
2488
2489	if (ret == INTR_NEXT_COMMAND)
2490	    ret = acornscsi_kick(host);
2491
2492	in_irq = 1;
2493    } while (ret != INTR_IDLE);
2494
2495    return IRQ_HANDLED;
2496}
2497
2498/*=============================================================================================
2499 * Interfaces between interrupt handler and rest of scsi code
2500 */
2501
2502/*
2503 * Function : acornscsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
2504 * Purpose  : queues a SCSI command
2505 * Params   : cmd  - SCSI command
2506 *	      done - function called on completion, with pointer to command descriptor
2507 * Returns  : 0, or < 0 on error.
2508 */
2509int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
2510		       void (*done)(struct scsi_cmnd *))
2511{
2512    AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
2513
2514    if (!done) {
2515	/* there should be some way of rejecting errors like this without panicing... */
2516	panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
2517		host->host->host_no, SCpnt);
2518	return -EINVAL;
2519    }
2520
2521#if (DEBUG & DEBUG_NO_WRITE)
2522    if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) {
2523	printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
2524	    host->host->host_no, '0' + SCpnt->device->id);
2525	SCpnt->result = DID_NO_CONNECT << 16;
2526	done(SCpnt);
2527	return 0;
2528    }
2529#endif
2530
2531    SCpnt->scsi_done = done;
2532    SCpnt->host_scribble = NULL;
2533    SCpnt->result = 0;
2534    SCpnt->tag = 0;
2535    SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
2536    SCpnt->SCp.sent_command = 0;
2537    SCpnt->SCp.scsi_xferred = 0;
2538
2539    init_SCp(SCpnt);
2540
2541    host->stats.queues += 1;
2542
2543    {
2544	unsigned long flags;
2545
2546	if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
2547	    SCpnt->result = DID_ERROR << 16;
2548	    done(SCpnt);
2549	    return 0;
2550	}
2551	local_irq_save(flags);
2552	if (host->scsi.phase == PHASE_IDLE)
2553	    acornscsi_kick(host);
2554	local_irq_restore(flags);
2555    }
2556    return 0;
2557}
2558
2559/*
2560 * Prototype: void acornscsi_reportstatus(struct scsi_cmnd **SCpntp1, struct scsi_cmnd **SCpntp2, int result)
2561 * Purpose  : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
2562 * Params   : SCpntp1 - pointer to command to return
2563 *	      SCpntp2 - pointer to command to check
2564 *	      result  - result to pass back to mid-level done function
2565 * Returns  : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
2566 */
2567static inline void acornscsi_reportstatus(struct scsi_cmnd **SCpntp1,
2568					  struct scsi_cmnd **SCpntp2,
2569					  int result)
2570{
2571	struct scsi_cmnd *SCpnt = *SCpntp1;
2572
2573    if (SCpnt) {
2574	*SCpntp1 = NULL;
2575
2576	SCpnt->result = result;
2577	SCpnt->scsi_done(SCpnt);
2578    }
2579
2580    if (SCpnt == *SCpntp2)
2581	*SCpntp2 = NULL;
2582}
2583
2584enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
2585
2586/*
2587 * Prototype: enum res acornscsi_do_abort(struct scsi_cmnd *SCpnt)
2588 * Purpose  : abort a command on this host
2589 * Params   : SCpnt - command to abort
2590 * Returns  : our abort status
2591 */
2592static enum res_abort acornscsi_do_abort(AS_Host *host, struct scsi_cmnd *SCpnt)
2593{
2594	enum res_abort res = res_not_running;
2595
2596	if (queue_remove_cmd(&host->queues.issue, SCpnt)) {
2597		/*
2598		 * The command was on the issue queue, and has not been
2599		 * issued yet.  We can remove the command from the queue,
2600		 * and acknowledge the abort.  Neither the devices nor the
2601		 * interface know about the command.
2602		 */
2603//#if (DEBUG & DEBUG_ABORT)
2604		printk("on issue queue ");
2605//#endif
2606		res = res_success;
2607	} else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) {
2608		/*
2609		 * The command was on the disconnected queue.  Simply
2610		 * acknowledge the abort condition, and when the target
2611		 * reconnects, we will give it an ABORT message.  The
2612		 * target should then disconnect, and we will clear
2613		 * the busylun bit.
2614		 */
2615//#if (DEBUG & DEBUG_ABORT)
2616		printk("on disconnected queue ");
2617//#endif
2618		res = res_success;
2619	} else if (host->SCpnt == SCpnt) {
2620		unsigned long flags;
2621
2622//#if (DEBUG & DEBUG_ABORT)
2623		printk("executing ");
2624//#endif
2625
2626		local_irq_save(flags);
2627		switch (host->scsi.phase) {
2628		/*
2629		 * If the interface is idle, and the command is 'disconnectable',
2630		 * then it is the same as on the disconnected queue.  We simply
2631		 * remove all traces of the command.  When the target reconnects,
2632		 * we will give it an ABORT message since the command could not
2633		 * be found.  When the target finally disconnects, we will clear
2634		 * the busylun bit.
2635		 */
2636		case PHASE_IDLE:
2637			if (host->scsi.disconnectable) {
2638				host->scsi.disconnectable = 0;
2639				host->SCpnt = NULL;
2640				res = res_success;
2641			}
2642			break;
2643
2644		/*
2645		 * If the command has connected and done nothing further,
2646		 * simply force a disconnect.  We also need to clear the
2647		 * busylun bit.
2648		 */
2649		case PHASE_CONNECTED:
2650			sbic_arm_write(host, SBIC_CMND, CMND_DISCONNECT);
2651			host->SCpnt = NULL;
2652			res = res_success_clear;
2653			break;
2654
2655		default:
2656			acornscsi_abortcmd(host, host->SCpnt->tag);
2657			res = res_snooze;
2658		}
2659		local_irq_restore(flags);
2660	} else if (host->origSCpnt == SCpnt) {
2661		/*
2662		 * The command will be executed next, but a command
2663		 * is currently using the interface.  This is similar to
2664		 * being on the issue queue, except the busylun bit has
2665		 * been set.
2666		 */
2667		host->origSCpnt = NULL;
2668//#if (DEBUG & DEBUG_ABORT)
2669		printk("waiting for execution ");
2670//#endif
2671		res = res_success_clear;
2672	} else
2673		printk("unknown ");
2674
2675	return res;
2676}
2677
2678/*
2679 * Prototype: int acornscsi_abort(struct scsi_cmnd *SCpnt)
2680 * Purpose  : abort a command on this host
2681 * Params   : SCpnt - command to abort
2682 * Returns  : one of SCSI_ABORT_ macros
2683 */
2684int acornscsi_abort(struct scsi_cmnd *SCpnt)
2685{
2686	AS_Host *host = (AS_Host *) SCpnt->device->host->hostdata;
2687	int result;
2688
2689	host->stats.aborts += 1;
2690
2691#if (DEBUG & DEBUG_ABORT)
2692	{
2693		int asr, ssr;
2694		asr = sbic_arm_read(host, SBIC_ASR);
2695		ssr = sbic_arm_read(host, SBIC_SSR);
2696
2697		printk(KERN_WARNING "acornscsi_abort: ");
2698		print_sbic_status(asr, ssr, host->scsi.phase);
2699		acornscsi_dumplog(host, SCpnt->device->id);
2700	}
2701#endif
2702
2703	printk("scsi%d: ", host->host->host_no);
2704
2705	switch (acornscsi_do_abort(host, SCpnt)) {
2706	/*
2707	 * We managed to find the command and cleared it out.
2708	 * We do not expect the command to be executing on the
2709	 * target, but we have set the busylun bit.
2710	 */
2711	case res_success_clear:
2712//#if (DEBUG & DEBUG_ABORT)
2713		printk("clear ");
2714//#endif
2715		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
2716
2717	/*
2718	 * We found the command, and cleared it out.  Either
2719	 * the command is still known to be executing on the
2720	 * target, or the busylun bit is not set.
2721	 */
2722	case res_success:
2723//#if (DEBUG & DEBUG_ABORT)
2724		printk("success\n");
2725//#endif
2726		result = SUCCESS;
2727		break;
2728
2729	/*
2730	 * We did find the command, but unfortunately we couldn't
2731	 * unhook it from ourselves.  Wait some more, and if it
2732	 * still doesn't complete, reset the interface.
2733	 */
2734	case res_snooze:
2735//#if (DEBUG & DEBUG_ABORT)
2736		printk("snooze\n");
2737//#endif
2738		result = FAILED;
2739		break;
2740
2741	/*
2742	 * The command could not be found (either because it completed,
2743	 * or it got dropped.
2744	 */
2745	default:
2746	case res_not_running:
2747		acornscsi_dumplog(host, SCpnt->device->id);
2748		result = FAILED;
2749//#if (DEBUG & DEBUG_ABORT)
2750		printk("not running\n");
2751//#endif
2752		break;
2753	}
2754
2755	return result;
2756}
2757
2758/*
2759 * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt)
2760 * Purpose  : reset a command on this host/reset this host
2761 * Params   : SCpnt  - command causing reset
2762 * Returns  : one of SCSI_RESET_ macros
2763 */
2764int acornscsi_bus_reset(struct scsi_cmnd *SCpnt)
2765{
2766	AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
2767	struct scsi_cmnd *SCptr;
2768
2769    host->stats.resets += 1;
2770
2771#if (DEBUG & DEBUG_RESET)
2772    {
2773	int asr, ssr;
2774
2775	asr = sbic_arm_read(host, SBIC_ASR);
2776	ssr = sbic_arm_read(host, SBIC_SSR);
2777
2778	printk(KERN_WARNING "acornscsi_reset: ");
2779	print_sbic_status(asr, ssr, host->scsi.phase);
2780	acornscsi_dumplog(host, SCpnt->device->id);
2781    }
2782#endif
2783
2784    acornscsi_dma_stop(host);
2785
2786    /*
2787     * do hard reset.  This resets all devices on this host, and so we
2788     * must set the reset status on all commands.
2789     */
2790    acornscsi_resetcard(host);
2791
2792    while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
2793	;
2794
2795    return SUCCESS;
2796}
2797
2798/*==============================================================================================
2799 * initialisation & miscellaneous support
2800 */
2801
2802/*
2803 * Function: char *acornscsi_info(struct Scsi_Host *host)
2804 * Purpose : return a string describing this interface
2805 * Params  : host - host to give information on
2806 * Returns : a constant string
2807 */
2808const
2809char *acornscsi_info(struct Scsi_Host *host)
2810{
2811    static char string[100], *p;
2812
2813    p = string;
2814
2815    p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d"
2816#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
2817    " SYNC"
2818#endif
2819#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
2820    " TAG"
2821#endif
2822#ifdef CONFIG_SCSI_ACORNSCSI_LINK
2823    " LINK"
2824#endif
2825#if (DEBUG & DEBUG_NO_WRITE)
2826    " NOWRITE (" __stringify(NO_WRITE) ")"
2827#endif
2828		, host->hostt->name, host->io_port, host->irq,
2829		VER_MAJOR, VER_MINOR, VER_PATCH);
2830    return string;
2831}
2832
2833int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
2834			int length, int inout)
2835{
2836    int pos, begin = 0, devidx;
2837    struct scsi_device *scd;
2838    AS_Host *host;
2839    char *p = buffer;
2840
2841    if (inout == 1)
2842	return -EINVAL;
2843
2844    host  = (AS_Host *)instance->hostdata;
2845
2846    p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
2847#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
2848    " SYNC"
2849#endif
2850#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
2851    " TAG"
2852#endif
2853#ifdef CONFIG_SCSI_ACORNSCSI_LINK
2854    " LINK"
2855#endif
2856#if (DEBUG & DEBUG_NO_WRITE)
2857    " NOWRITE (" __stringify(NO_WRITE) ")"
2858#endif
2859		"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
2860
2861    p += sprintf(p,	"SBIC: WD33C93A  Address: %08X  IRQ : %d\n",
2862			host->scsi.io_port, host->scsi.irq);
2863#ifdef USE_DMAC
2864    p += sprintf(p,	"DMAC: uPC71071  Address: %08X  IRQ : %d\n\n",
2865			host->dma.io_port, host->scsi.irq);
2866#endif
2867
2868    p += sprintf(p,	"Statistics:\n"
2869			"Queued commands: %-10u    Issued commands: %-10u\n"
2870			"Done commands  : %-10u    Reads          : %-10u\n"
2871			"Writes         : %-10u    Others         : %-10u\n"
2872			"Disconnects    : %-10u    Aborts         : %-10u\n"
2873			"Resets         : %-10u\n\nLast phases:",
2874			host->stats.queues,		host->stats.removes,
2875			host->stats.fins,		host->stats.reads,
2876			host->stats.writes,		host->stats.miscs,
2877			host->stats.disconnects,	host->stats.aborts,
2878			host->stats.resets);
2879
2880    for (devidx = 0; devidx < 9; devidx ++) {
2881	unsigned int statptr, prev;
2882
2883	p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
2884	statptr = host->status_ptr[devidx] - 10;
2885
2886	if ((signed int)statptr < 0)
2887	    statptr += STATUS_BUFFER_SIZE;
2888
2889	prev = host->status[devidx][statptr].when;
2890
2891	for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
2892	    if (host->status[devidx][statptr].when) {
2893		p += sprintf(p, "%c%02X:%02X+%2ld",
2894			host->status[devidx][statptr].irq ? '-' : ' ',
2895			host->status[devidx][statptr].ph,
2896			host->status[devidx][statptr].ssr,
2897			(host->status[devidx][statptr].when - prev) < 100 ?
2898				(host->status[devidx][statptr].when - prev) : 99);
2899		prev = host->status[devidx][statptr].when;
2900	    }
2901	}
2902    }
2903
2904    p += sprintf(p, "\nAttached devices:\n");
2905
2906    shost_for_each_device(scd, instance) {
2907	p += sprintf(p, "Device/Lun TaggedQ      Sync\n");
2908	p += sprintf(p, "     %d/%d   ", scd->id, scd->lun);
2909	if (scd->tagged_supported)
2910		p += sprintf(p, "%3sabled(%3d) ",
2911			     scd->simple_tags ? "en" : "dis",
2912			     scd->current_tag);
2913	else
2914		p += sprintf(p, "unsupported  ");
2915
2916	if (host->device[scd->id].sync_xfer & 15)
2917		p += sprintf(p, "offset %d, %d ns\n",
2918			     host->device[scd->id].sync_xfer & 15,
2919			     acornscsi_getperiod(host->device[scd->id].sync_xfer));
2920	else
2921		p += sprintf(p, "async\n");
2922
2923	pos = p - buffer;
2924	if (pos + begin < offset) {
2925	    begin += pos;
2926	    p = buffer;
2927	}
2928	pos = p - buffer;
2929	if (pos + begin > offset + length) {
2930	    scsi_device_put(scd);
2931	    break;
2932	}
2933    }
2934
2935    pos = p - buffer;
2936
2937    *start = buffer + (offset - begin);
2938    pos -= offset - begin;
2939
2940    if (pos > length)
2941	pos = length;
2942
2943    return pos;
2944}
2945
2946static struct scsi_host_template acornscsi_template = {
2947	.module			= THIS_MODULE,
2948	.proc_info		= acornscsi_proc_info,
2949	.name			= "AcornSCSI",
2950	.info			= acornscsi_info,
2951	.queuecommand		= acornscsi_queuecmd,
2952	.eh_abort_handler	= acornscsi_abort,
2953	.eh_bus_reset_handler	= acornscsi_bus_reset,
2954	.can_queue		= 16,
2955	.this_id		= 7,
2956	.sg_tablesize		= SG_ALL,
2957	.cmd_per_lun		= 2,
2958	.use_clustering		= DISABLE_CLUSTERING,
2959	.proc_name		= "acornscsi",
2960};
2961
2962static int __devinit
2963acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
2964{
2965	struct Scsi_Host *host;
2966	AS_Host *ashost;
2967	int ret = -ENOMEM;
2968
2969	host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host));
2970	if (!host)
2971		goto out;
2972
2973	ashost = (AS_Host *)host->hostdata;
2974
2975	host->io_port = ecard_address(ec, ECARD_MEMC, 0);
2976	host->irq = ec->irq;
2977
2978	ashost->host		= host;
2979	ashost->scsi.io_port	= ioaddr(host->io_port + 0x800);
2980	ashost->scsi.irq	= host->irq;
2981	ashost->card.io_intr	= POD_SPACE(host->io_port) + 0x800;
2982	ashost->card.io_page	= POD_SPACE(host->io_port) + 0xc00;
2983	ashost->card.io_ram	= ioaddr(host->io_port);
2984	ashost->dma.io_port	= host->io_port + 0xc00;
2985	ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800;
2986
2987	ec->irqaddr	= (char *)ioaddr(ashost->card.io_intr);
2988	ec->irqmask	= 0x0a;
2989
2990	ret = -EBUSY;
2991	if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)"))
2992		goto err_1;
2993	if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)"))
2994		goto err_2;
2995	if (!request_region(ashost->card.io_page, 1, "acornscsi(page)"))
2996		goto err_3;
2997#ifdef USE_DMAC
2998	if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)"))
2999		goto err_4;
3000#endif
3001	if (!request_region(host->io_port, 2048, "acornscsi(ram)"))
3002		goto err_5;
3003
3004	ret = request_irq(host->irq, acornscsi_intr, IRQF_DISABLED, "acornscsi", ashost);
3005	if (ret) {
3006		printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n",
3007			host->host_no, ashost->scsi.irq, ret);
3008		goto err_6;
3009	}
3010
3011	memset(&ashost->stats, 0, sizeof (ashost->stats));
3012	queue_initialise(&ashost->queues.issue);
3013	queue_initialise(&ashost->queues.disconnected);
3014	msgqueue_initialise(&ashost->scsi.msgs);
3015
3016	acornscsi_resetcard(ashost);
3017
3018	ret = scsi_add_host(host, &ec->dev);
3019	if (ret)
3020		goto err_7;
3021
3022	scsi_scan_host(host);
3023	goto out;
3024
3025 err_7:
3026	free_irq(host->irq, ashost);
3027 err_6:
3028	release_region(host->io_port, 2048);
3029 err_5:
3030#ifdef USE_DMAC
3031	release_region(ashost->dma.io_port, 256);
3032#endif
3033 err_4:
3034	release_region(ashost->card.io_page, 1);
3035 err_3:
3036	release_region(ashost->card.io_intr, 1);
3037 err_2:
3038	release_region(host->io_port + 0x800, 2);
3039 err_1:
3040	scsi_host_put(host);
3041 out:
3042	return ret;
3043}
3044
3045static void __devexit acornscsi_remove(struct expansion_card *ec)
3046{
3047	struct Scsi_Host *host = ecard_get_drvdata(ec);
3048	AS_Host *ashost = (AS_Host *)host->hostdata;
3049
3050	ecard_set_drvdata(ec, NULL);
3051	scsi_remove_host(host);
3052
3053	/*
3054	 * Put card into RESET state
3055	 */
3056	outb(0x80, ashost->card.io_page);
3057
3058	free_irq(host->irq, ashost);
3059
3060	release_region(host->io_port + 0x800, 2);
3061	release_region(ashost->card.io_intr, 1);
3062	release_region(ashost->card.io_page, 1);
3063	release_region(ashost->dma.io_port, 256);
3064	release_region(host->io_port, 2048);
3065
3066	msgqueue_free(&ashost->scsi.msgs);
3067	queue_free(&ashost->queues.disconnected);
3068	queue_free(&ashost->queues.issue);
3069	scsi_host_put(host);
3070}
3071
3072static const struct ecard_id acornscsi_cids[] = {
3073	{ MANU_ACORN, PROD_ACORN_SCSI },
3074	{ 0xffff, 0xffff },
3075};
3076
3077static struct ecard_driver acornscsi_driver = {
3078	.probe		= acornscsi_probe,
3079	.remove		= __devexit_p(acornscsi_remove),
3080	.id_table	= acornscsi_cids,
3081	.drv = {
3082		.name		= "acornscsi",
3083	},
3084};
3085
3086static int __init acornscsi_init(void)
3087{
3088	return ecard_register_driver(&acornscsi_driver);
3089}
3090
3091static void __exit acornscsi_exit(void)
3092{
3093	ecard_remove_driver(&acornscsi_driver);
3094}
3095
3096module_init(acornscsi_init);
3097module_exit(acornscsi_exit);
3098
3099MODULE_AUTHOR("Russell King");
3100MODULE_DESCRIPTION("AcornSCSI driver");
3101MODULE_LICENSE("GPL");
3102