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