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