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