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 * List of devices that the driver will recognise
114 */
115 #define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI }
116 /*
117 * ====================================================================================
118 */
119
120 #ifdef DEBUG_TARGET
121 #define DBG(cmd,xxx...) \
122 if (cmd->target == DEBUG_TARGET) { \
123 xxx; \
124 }
125 #else
126 #define DBG(cmd,xxx...) xxx
127 #endif
128
129 #ifndef STRINGIFY
130 #define STRINGIFY(x) #x
131 #endif
132 #define STRx(x) STRINGIFY(x)
133 #define NO_WRITE_STR STRx(NO_WRITE)
134
135 #include <linux/config.h>
136 #include <linux/module.h>
137 #include <linux/kernel.h>
138 #include <linux/sched.h>
139 #include <linux/string.h>
140 #include <linux/signal.h>
141 #include <linux/errno.h>
142 #include <linux/proc_fs.h>
143 #include <linux/stat.h>
144 #include <linux/ioport.h>
145 #include <linux/blk.h>
146 #include <linux/delay.h>
147 #include <linux/init.h>
148
149 #include <asm/bitops.h>
150 #include <asm/system.h>
151 #include <asm/io.h>
152 #include <asm/irq.h>
153 #include <asm/ecard.h>
154
155 #include "../../scsi/scsi.h"
156 #include "../../scsi/hosts.h"
157 #include "../../scsi/constants.h"
158 #include "acornscsi.h"
159 #include "msgqueue.h"
160
161 #include <scsi/scsicam.h>
162
163 #define VER_MAJOR 2
164 #define VER_MINOR 0
165 #define VER_PATCH 6
166
167 #ifndef ABORT_TAG
168 #define ABORT_TAG 0xd
169 #else
170 #error "Yippee! ABORT TAG is now defined! Remove this error!"
171 #endif
172
173 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
174 #error SCSI2 LINKed commands not supported (yet)!
175 #endif
176
177 #ifdef USE_DMAC
178 /*
179 * DMAC setup parameters
180 */
181 #define INIT_DEVCON0 (DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP)
182 #define INIT_DEVCON1 (DEVCON1_BHLD)
183 #define DMAC_READ (MODECON_READ)
184 #define DMAC_WRITE (MODECON_WRITE)
185 #define INIT_SBICDMA (CTRL_DMABURST)
186
187 #define scsi_xferred have_data_in
188
189 /*
190 * Size of on-board DMA buffer
191 */
192 #define DMAC_BUFFER_SIZE 65536
193 #endif
194
195 #define STATUS_BUFFER_TO_PRINT 24
196
197 unsigned int sdtr_period = SDTR_PERIOD;
198 unsigned int sdtr_size = SDTR_SIZE;
199
200 static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
201 static int acornscsi_reconnect_finish(AS_Host *host);
202 static void acornscsi_dma_cleanup(AS_Host *host);
203 static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
204
205 /* ====================================================================================
206 * Miscellaneous
207 */
208
209 static inline void
sbic_arm_write(unsigned int io_port,int reg,int value)210 sbic_arm_write(unsigned int io_port, int reg, int value)
211 {
212 __raw_writeb(reg, io_port);
213 __raw_writeb(value, io_port + 4);
214 }
215
216 #define sbic_arm_writenext(io,val) \
217 __raw_writeb((val), (io) + 4)
218
219 static inline
sbic_arm_read(unsigned int io_port,int reg)220 int sbic_arm_read(unsigned int io_port, int reg)
221 {
222 if(reg == ASR)
223 return __raw_readl(io_port) & 255;
224 __raw_writeb(reg, io_port);
225 return __raw_readl(io_port + 4) & 255;
226 }
227
228 #define sbic_arm_readnext(io) \
229 __raw_readb((io) + 4)
230
231 #ifdef USE_DMAC
232 #define dmac_read(io_port,reg) \
233 inb((io_port) + (reg))
234
235 #define dmac_write(io_port,reg,value) \
236 ({ outb((value), (io_port) + (reg)); })
237
238 #define dmac_clearintr(io_port) \
239 ({ outb(0, (io_port)); })
240
241 static inline
dmac_address(unsigned int io_port)242 unsigned int dmac_address(unsigned int io_port)
243 {
244 return dmac_read(io_port, TXADRHI) << 16 |
245 dmac_read(io_port, TXADRMD) << 8 |
246 dmac_read(io_port, TXADRLO);
247 }
248
249 static
acornscsi_dumpdma(AS_Host * host,char * where)250 void acornscsi_dumpdma(AS_Host *host, char *where)
251 {
252 unsigned int mode, addr, len;
253
254 mode = dmac_read(host->dma.io_port, MODECON);
255 addr = dmac_address(host->dma.io_port);
256 len = dmac_read(host->dma.io_port, TXCNTHI) << 8 |
257 dmac_read(host->dma.io_port, TXCNTLO);
258
259 printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
260 host->host->host_no, where,
261 mode, addr, (len + 1) & 0xffff,
262 dmac_read(host->dma.io_port, MASKREG));
263
264 printk("DMA @%06x, ", host->dma.start_addr);
265 printk("BH @%p +%04x, ", host->scsi.SCp.ptr,
266 host->scsi.SCp.this_residual);
267 printk("DT @+%04x ST @+%04x", host->dma.transferred,
268 host->scsi.SCp.scsi_xferred);
269 printk("\n");
270 }
271 #endif
272
273 static
acornscsi_sbic_xfcount(AS_Host * host)274 unsigned long acornscsi_sbic_xfcount(AS_Host *host)
275 {
276 unsigned long length;
277
278 length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16;
279 length |= sbic_arm_readnext(host->scsi.io_port) << 8;
280 length |= sbic_arm_readnext(host->scsi.io_port);
281
282 return length;
283 }
284
285 static int
acornscsi_sbic_wait(AS_Host * host,int stat_mask,int stat,int timeout,char * msg)286 acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
287 {
288 int asr;
289
290 do {
291 asr = sbic_arm_read(host->scsi.io_port, ASR);
292
293 if ((asr & stat_mask) == stat)
294 return 0;
295
296 udelay(1);
297 } while (--timeout);
298
299 printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
300
301 return -1;
302 }
303
304 static
acornscsi_sbic_issuecmd(AS_Host * host,int command)305 int acornscsi_sbic_issuecmd(AS_Host *host, int command)
306 {
307 if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
308 return -1;
309
310 sbic_arm_write(host->scsi.io_port, CMND, command);
311
312 return 0;
313 }
314
315 static void
acornscsi_csdelay(unsigned int cs)316 acornscsi_csdelay(unsigned int cs)
317 {
318 unsigned long target_jiffies, flags;
319
320 target_jiffies = jiffies + 1 + cs * HZ / 100;
321
322 save_flags(flags);
323 sti();
324
325 while (time_before(jiffies, target_jiffies)) barrier();
326
327 restore_flags(flags);
328 }
329
330 static
acornscsi_resetcard(AS_Host * host)331 void acornscsi_resetcard(AS_Host *host)
332 {
333 unsigned int i, timeout;
334
335 /* assert reset line */
336 host->card.page_reg = 0x80;
337 outb(host->card.page_reg, host->card.io_page);
338
339 /* wait 3 cs. SCSI standard says 25ms. */
340 acornscsi_csdelay(3);
341
342 host->card.page_reg = 0;
343 outb(host->card.page_reg, host->card.io_page);
344
345 /*
346 * Should get a reset from the card
347 */
348 timeout = 1000;
349 do {
350 if (inb(host->card.io_intr) & 8)
351 break;
352 udelay(1);
353 } while (--timeout);
354
355 if (timeout == 0)
356 printk("scsi%d: timeout while resetting card\n",
357 host->host->host_no);
358
359 sbic_arm_read(host->scsi.io_port, ASR);
360 sbic_arm_read(host->scsi.io_port, SSR);
361
362 /* setup sbic - WD33C93A */
363 sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
364 sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
365
366 /*
367 * Command should cause a reset interrupt
368 */
369 timeout = 1000;
370 do {
371 if (inb(host->card.io_intr) & 8)
372 break;
373 udelay(1);
374 } while (--timeout);
375
376 if (timeout == 0)
377 printk("scsi%d: timeout while resetting card\n",
378 host->host->host_no);
379
380 sbic_arm_read(host->scsi.io_port, ASR);
381 if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01)
382 printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
383 host->host->host_no);
384
385 sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
386 sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
387 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
388 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
389
390 host->card.page_reg = 0x40;
391 outb(host->card.page_reg, host->card.io_page);
392
393 /* setup dmac - uPC71071 */
394 dmac_write(host->dma.io_port, INIT, 0);
395 #ifdef USE_DMAC
396 dmac_write(host->dma.io_port, INIT, INIT_8BIT);
397 dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0);
398 dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0);
399 dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1);
400 #endif
401
402 host->SCpnt = NULL;
403 host->scsi.phase = PHASE_IDLE;
404 host->scsi.disconnectable = 0;
405
406 for (i = 0; i < 8; i++) {
407 host->busyluns[i] = 0;
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
print_scsi_status(unsigned int ssr)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
print_sbic_status(int asr,int ssr,int cmdphase)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
acornscsi_dumplogline(AS_Host * host,int target,int line)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
acornscsi_dumplog(AS_Host * host,int target)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
acornscsi_target(AS_Host * host)577 char acornscsi_target(AS_Host *host)
578 {
579 if (host->SCpnt)
580 return '0' + host->SCpnt->target;
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
acornscsi_cmdtype(int command)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
acornscsi_datadirection(int command)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
acornscsi_getperiod(unsigned char syncxfer)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
round_period(unsigned int period)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
calc_sync_xfer(unsigned int period,unsigned int offset)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
acornscsi_kick(AS_Host * host)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, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
747 sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target);
748 sbic_arm_write(host->scsi.io_port, 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->target,
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->tagged_queue) {
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->target * 8 + SCpnt->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
acornscsi_done(AS_Host * host,Scsi_Cmnd ** SCpntp,unsigned int result)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, 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 print_command(SCpnt->cmnd);
872 acornscsi_dumpdma(host, "done");
873 acornscsi_dumplog(host, SCpnt->target);
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->target * 8 + SCpnt->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
acornscsi_data_updateptr(AS_Host * host,Scsi_Pointer * SCp,unsigned int length)900 void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
901 {
902 SCp->ptr += length;
903 SCp->this_residual -= length;
904
905 if (!SCp->this_residual) {
906 if (SCp->buffers_residual) {
907 SCp->buffer++;
908 SCp->buffers_residual--;
909 SCp->ptr = (char *)SCp->buffer->address;
910 SCp->this_residual = SCp->buffer->length;
911 } else {
912 SCp->ptr = NULL;
913 host->dma.xfer_done = 1;
914 }
915 }
916 }
917
918 /*
919 * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
920 * unsigned int start_addr, unsigned int length)
921 * Purpose : read data from DMA RAM
922 * Params : host - host to transfer from
923 * ptr - DRAM address
924 * start_addr - host mem address
925 * length - number of bytes to transfer
926 * Notes : this will only be one SG entry or less
927 */
928 static
acornscsi_data_read(AS_Host * host,char * ptr,unsigned int start_addr,unsigned int length)929 void acornscsi_data_read(AS_Host *host, char *ptr,
930 unsigned int start_addr, unsigned int length)
931 {
932 extern void __acornscsi_in(int port, char *buf, int len);
933 unsigned int page, offset, len = length;
934
935 page = (start_addr >> 12);
936 offset = start_addr & ((1 << 12) - 1);
937
938 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
939
940 while (len > 0) {
941 unsigned int this_len;
942
943 if (len + offset > (1 << 12))
944 this_len = (1 << 12) - offset;
945 else
946 this_len = len;
947
948 __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
949
950 offset += this_len;
951 ptr += this_len;
952 len -= this_len;
953
954 if (offset == (1 << 12)) {
955 offset = 0;
956 page ++;
957 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
958 }
959 }
960 outb(host->card.page_reg, host->card.io_page);
961 }
962
963 /*
964 * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
965 * unsigned int start_addr, unsigned int length)
966 * Purpose : write data to DMA RAM
967 * Params : host - host to transfer from
968 * ptr - DRAM address
969 * start_addr - host mem address
970 * length - number of bytes to transfer
971 * Notes : this will only be one SG entry or less
972 */
973 static
acornscsi_data_write(AS_Host * host,char * ptr,unsigned int start_addr,unsigned int length)974 void acornscsi_data_write(AS_Host *host, char *ptr,
975 unsigned int start_addr, unsigned int length)
976 {
977 extern void __acornscsi_out(int port, char *buf, int len);
978 unsigned int page, offset, len = length;
979
980 page = (start_addr >> 12);
981 offset = start_addr & ((1 << 12) - 1);
982
983 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
984
985 while (len > 0) {
986 unsigned int this_len;
987
988 if (len + offset > (1 << 12))
989 this_len = (1 << 12) - offset;
990 else
991 this_len = len;
992
993 __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
994
995 offset += this_len;
996 ptr += this_len;
997 len -= this_len;
998
999 if (offset == (1 << 12)) {
1000 offset = 0;
1001 page ++;
1002 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
1003 }
1004 }
1005 outb(host->card.page_reg, host->card.io_page);
1006 }
1007
1008 /* =========================================================================================
1009 * On-board DMA routines
1010 */
1011 #ifdef USE_DMAC
1012 /*
1013 * Prototype: void acornscsi_dmastop(AS_Host *host)
1014 * Purpose : stop all DMA
1015 * Params : host - host on which to stop DMA
1016 * Notes : This is called when leaving DATA IN/OUT phase,
1017 * or when interface is RESET
1018 */
1019 static inline
acornscsi_dma_stop(AS_Host * host)1020 void acornscsi_dma_stop(AS_Host *host)
1021 {
1022 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1023 dmac_clearintr(host->dma.io_intr_clear);
1024
1025 #if (DEBUG & DEBUG_DMA)
1026 DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
1027 #endif
1028 }
1029
1030 /*
1031 * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1032 * Purpose : setup DMA controller for data transfer
1033 * Params : host - host to setup
1034 * direction - data transfer direction
1035 * Notes : This is called when entering DATA I/O phase, not
1036 * while we're in a DATA I/O phase
1037 */
1038 static
acornscsi_dma_setup(AS_Host * host,dmadir_t direction)1039 void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1040 {
1041 unsigned int address, length, mode;
1042
1043 host->dma.direction = direction;
1044
1045 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1046
1047 if (direction == DMA_OUT) {
1048 #if (DEBUG & DEBUG_NO_WRITE)
1049 if (NO_WRITE & (1 << host->SCpnt->target)) {
1050 printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
1051 host->host->host_no, acornscsi_target(host));
1052 return;
1053 }
1054 #endif
1055 mode = DMAC_WRITE;
1056 } else
1057 mode = DMAC_READ;
1058
1059 /*
1060 * Allocate some buffer space, limited to half the buffer size
1061 */
1062 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1063 if (length) {
1064 host->dma.start_addr = address = host->dma.free_addr;
1065 host->dma.free_addr = (host->dma.free_addr + length) &
1066 (DMAC_BUFFER_SIZE - 1);
1067
1068 /*
1069 * Transfer data to DMA memory
1070 */
1071 if (direction == DMA_OUT)
1072 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1073 length);
1074
1075 length -= 1;
1076 dmac_write(host->dma.io_port, TXCNTLO, length);
1077 dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
1078 dmac_write(host->dma.io_port, TXADRLO, address);
1079 dmac_write(host->dma.io_port, TXADRMD, address >> 8);
1080 dmac_write(host->dma.io_port, TXADRHI, 0);
1081 dmac_write(host->dma.io_port, MODECON, mode);
1082 dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
1083
1084 #if (DEBUG & DEBUG_DMA)
1085 DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
1086 #endif
1087 host->dma.xfer_setup = 1;
1088 }
1089 }
1090
1091 /*
1092 * Function: void acornscsi_dma_cleanup(AS_Host *host)
1093 * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
1094 * Params : host - host to finish
1095 * Notes : This is called when a command is:
1096 * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT
1097 * : This must not return until all transfers are completed.
1098 */
1099 static
acornscsi_dma_cleanup(AS_Host * host)1100 void acornscsi_dma_cleanup(AS_Host *host)
1101 {
1102 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1103 dmac_clearintr(host->dma.io_intr_clear);
1104
1105 /*
1106 * Check for a pending transfer
1107 */
1108 if (host->dma.xfer_required) {
1109 host->dma.xfer_required = 0;
1110 if (host->dma.direction == DMA_IN)
1111 acornscsi_data_read(host, host->dma.xfer_ptr,
1112 host->dma.xfer_start, host->dma.xfer_length);
1113 }
1114
1115 /*
1116 * Has a transfer been setup?
1117 */
1118 if (host->dma.xfer_setup) {
1119 unsigned int transferred;
1120
1121 host->dma.xfer_setup = 0;
1122
1123 #if (DEBUG & DEBUG_DMA)
1124 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
1125 #endif
1126
1127 /*
1128 * Calculate number of bytes transferred from DMA.
1129 */
1130 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1131 host->dma.transferred += transferred;
1132
1133 if (host->dma.direction == DMA_IN)
1134 acornscsi_data_read(host, host->scsi.SCp.ptr,
1135 host->dma.start_addr, transferred);
1136
1137 /*
1138 * Update SCSI pointers
1139 */
1140 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1141 #if (DEBUG & DEBUG_DMA)
1142 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
1143 #endif
1144 }
1145 }
1146
1147 /*
1148 * Function: void acornscsi_dmacintr(AS_Host *host)
1149 * Purpose : handle interrupts from DMAC device
1150 * Params : host - host to process
1151 * Notes : If reading, we schedule the read to main memory &
1152 * allow the transfer to continue.
1153 * : If writing, we fill the onboard DMA memory from main
1154 * memory.
1155 * : Called whenever DMAC finished it's current transfer.
1156 */
1157 static
acornscsi_dma_intr(AS_Host * host)1158 void acornscsi_dma_intr(AS_Host *host)
1159 {
1160 unsigned int address, length, transferred;
1161
1162 #if (DEBUG & DEBUG_DMA)
1163 DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
1164 #endif
1165
1166 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1167 dmac_clearintr(host->dma.io_intr_clear);
1168
1169 /*
1170 * Calculate amount transferred via DMA
1171 */
1172 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1173 host->dma.transferred += transferred;
1174
1175 /*
1176 * Schedule DMA transfer off board
1177 */
1178 if (host->dma.direction == DMA_IN) {
1179 host->dma.xfer_start = host->dma.start_addr;
1180 host->dma.xfer_length = transferred;
1181 host->dma.xfer_ptr = host->scsi.SCp.ptr;
1182 host->dma.xfer_required = 1;
1183 }
1184
1185 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1186
1187 /*
1188 * Allocate some buffer space, limited to half the on-board RAM size
1189 */
1190 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1191 if (length) {
1192 host->dma.start_addr = address = host->dma.free_addr;
1193 host->dma.free_addr = (host->dma.free_addr + length) &
1194 (DMAC_BUFFER_SIZE - 1);
1195
1196 /*
1197 * Transfer data to DMA memory
1198 */
1199 if (host->dma.direction == DMA_OUT)
1200 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1201 length);
1202
1203 length -= 1;
1204 dmac_write(host->dma.io_port, TXCNTLO, length);
1205 dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
1206 dmac_write(host->dma.io_port, TXADRLO, address);
1207 dmac_write(host->dma.io_port, TXADRMD, address >> 8);
1208 dmac_write(host->dma.io_port, TXADRHI, 0);
1209 dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
1210
1211 #if (DEBUG & DEBUG_DMA)
1212 DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
1213 #endif
1214 } else {
1215 host->dma.xfer_setup = 0;
1216 #if 0
1217 /*
1218 * If the interface still wants more, then this is an error.
1219 * We give it another byte, but we also attempt to raise an
1220 * attention condition. We continue giving one byte until
1221 * the device recognises the attention.
1222 */
1223 if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) {
1224 acornscsi_abortcmd(host, host->SCpnt->tag);
1225
1226 dmac_write(host->dma.io_port, TXCNTLO, 0);
1227 dmac_write(host->dma.io_port, TXCNTHI, 0);
1228 dmac_write(host->dma.io_port, TXADRLO, 0);
1229 dmac_write(host->dma.io_port, TXADRMD, 0);
1230 dmac_write(host->dma.io_port, TXADRHI, 0);
1231 dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
1232 }
1233 #endif
1234 }
1235 }
1236
1237 /*
1238 * Function: void acornscsi_dma_xfer(AS_Host *host)
1239 * Purpose : transfer data between AcornSCSI and memory
1240 * Params : host - host to process
1241 */
1242 static
acornscsi_dma_xfer(AS_Host * host)1243 void acornscsi_dma_xfer(AS_Host *host)
1244 {
1245 host->dma.xfer_required = 0;
1246
1247 if (host->dma.direction == DMA_IN)
1248 acornscsi_data_read(host, host->dma.xfer_ptr,
1249 host->dma.xfer_start, host->dma.xfer_length);
1250 }
1251
1252 /*
1253 * Function: void acornscsi_dma_adjust(AS_Host *host)
1254 * Purpose : adjust DMA pointers & count for bytes transferred to
1255 * SBIC but not SCSI bus.
1256 * Params : host - host to adjust DMA count for
1257 */
1258 static
acornscsi_dma_adjust(AS_Host * host)1259 void acornscsi_dma_adjust(AS_Host *host)
1260 {
1261 if (host->dma.xfer_setup) {
1262 signed long transferred;
1263 #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1264 DBG(host->SCpnt, acornscsi_dumpdma(host, "adji"));
1265 #endif
1266 /*
1267 * Calculate correct DMA address - DMA is ahead of SCSI bus while
1268 * writing.
1269 * host->scsi.SCp.scsi_xferred is the number of bytes
1270 * actually transferred to/from the SCSI bus.
1271 * host->dma.transferred is the number of bytes transferred
1272 * over DMA since host->dma.start_addr was last set.
1273 *
1274 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
1275 * - host->dma.transferred
1276 */
1277 transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
1278 if (transferred < 0)
1279 printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
1280 host->host->host_no, acornscsi_target(host), transferred);
1281 else if (transferred == 0)
1282 host->dma.xfer_setup = 0;
1283 else {
1284 transferred += host->dma.start_addr;
1285 dmac_write(host->dma.io_port, TXADRLO, transferred);
1286 dmac_write(host->dma.io_port, TXADRMD, transferred >> 8);
1287 dmac_write(host->dma.io_port, TXADRHI, transferred >> 16);
1288 #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1289 DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo"));
1290 #endif
1291 }
1292 }
1293 }
1294 #endif
1295
1296 /* =========================================================================================
1297 * Data I/O
1298 */
1299 static int
acornscsi_write_pio(AS_Host * host,char * bytes,int * ptr,int len,unsigned int max_timeout)1300 acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
1301 {
1302 unsigned int asr, timeout = max_timeout;
1303 int my_ptr = *ptr;
1304
1305 while (my_ptr < len) {
1306 asr = sbic_arm_read(host->scsi.io_port, ASR);
1307
1308 if (asr & ASR_DBR) {
1309 timeout = max_timeout;
1310
1311 sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]);
1312 } else if (asr & ASR_INT)
1313 break;
1314 else if (--timeout == 0)
1315 break;
1316 udelay(1);
1317 }
1318
1319 *ptr = my_ptr;
1320
1321 return (timeout == 0) ? -1 : 0;
1322 }
1323
1324 /*
1325 * Function: void acornscsi_sendcommand(AS_Host *host)
1326 * Purpose : send a command to a target
1327 * Params : host - host which is connected to target
1328 */
1329 static void
acornscsi_sendcommand(AS_Host * host)1330 acornscsi_sendcommand(AS_Host *host)
1331 {
1332 Scsi_Cmnd *SCpnt = host->SCpnt;
1333
1334 sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
1335 sbic_arm_writenext(host->scsi.io_port, 0);
1336 sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
1337
1338 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1339
1340 if (acornscsi_write_pio(host, SCpnt->cmnd,
1341 (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000))
1342 printk("scsi%d: timeout while sending command\n", host->host->host_no);
1343
1344 host->scsi.phase = PHASE_COMMAND;
1345 }
1346
1347 static
acornscsi_sendmessage(AS_Host * host)1348 void acornscsi_sendmessage(AS_Host *host)
1349 {
1350 unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
1351 unsigned int msgnr;
1352 struct message *msg;
1353
1354 #if (DEBUG & DEBUG_MESSAGES)
1355 printk("scsi%d.%c: sending message ",
1356 host->host->host_no, acornscsi_target(host));
1357 #endif
1358
1359 switch (message_length) {
1360 case 0:
1361 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1362
1363 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
1364
1365 sbic_arm_write(host->scsi.io_port, DATA, NOP);
1366
1367 host->scsi.last_message = NOP;
1368 #if (DEBUG & DEBUG_MESSAGES)
1369 printk("NOP");
1370 #endif
1371 break;
1372
1373 case 1:
1374 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1375 msg = msgqueue_getmsg(&host->scsi.msgs, 0);
1376
1377 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
1378
1379 sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]);
1380
1381 host->scsi.last_message = msg->msg[0];
1382 #if (DEBUG & DEBUG_MESSAGES)
1383 print_msg(msg->msg);
1384 #endif
1385 break;
1386
1387 default:
1388 /*
1389 * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14)
1390 * 'When a target sends this (MESSAGE_REJECT) message, it
1391 * shall change to MESSAGE IN phase and send this message
1392 * prior to requesting additional message bytes from the
1393 * initiator. This provides an interlock so that the
1394 * initiator can determine which message byte is rejected.
1395 */
1396 sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
1397 sbic_arm_writenext(host->scsi.io_port, 0);
1398 sbic_arm_writenext(host->scsi.io_port, message_length);
1399 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1400
1401 msgnr = 0;
1402 while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
1403 unsigned int i;
1404 #if (DEBUG & DEBUG_MESSAGES)
1405 print_msg(msg);
1406 #endif
1407 i = 0;
1408 if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
1409 printk("scsi%d: timeout while sending message\n", host->host->host_no);
1410
1411 host->scsi.last_message = msg->msg[0];
1412 if (msg->msg[0] == EXTENDED_MESSAGE)
1413 host->scsi.last_message |= msg->msg[2] << 8;
1414
1415 if (i != msg->length)
1416 break;
1417 }
1418 break;
1419 }
1420 #if (DEBUG & DEBUG_MESSAGES)
1421 printk("\n");
1422 #endif
1423 }
1424
1425 /*
1426 * Function: void acornscsi_readstatusbyte(AS_Host *host)
1427 * Purpose : Read status byte from connected target
1428 * Params : host - host connected to target
1429 */
1430 static
acornscsi_readstatusbyte(AS_Host * host)1431 void acornscsi_readstatusbyte(AS_Host *host)
1432 {
1433 acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT);
1434 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte");
1435 host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA);
1436 }
1437
1438 /*
1439 * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
1440 * Purpose : Read one message byte from connected target
1441 * Params : host - host connected to target
1442 */
1443 static
acornscsi_readmessagebyte(AS_Host * host)1444 unsigned char acornscsi_readmessagebyte(AS_Host *host)
1445 {
1446 unsigned char message;
1447
1448 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1449
1450 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
1451
1452 message = sbic_arm_read(host->scsi.io_port, DATA);
1453
1454 /* wait for MSGIN-XFER-PAUSED */
1455 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
1456
1457 sbic_arm_read(host->scsi.io_port, SSR);
1458
1459 return message;
1460 }
1461
1462 /*
1463 * Function: void acornscsi_message(AS_Host *host)
1464 * Purpose : Read complete message from connected target & action message
1465 * Params : host - host connected to target
1466 */
1467 static
acornscsi_message(AS_Host * host)1468 void acornscsi_message(AS_Host *host)
1469 {
1470 unsigned char message[16];
1471 unsigned int msgidx = 0, msglen = 1;
1472
1473 do {
1474 message[msgidx] = acornscsi_readmessagebyte(host);
1475
1476 switch (msgidx) {
1477 case 0:
1478 if (message[0] == EXTENDED_MESSAGE ||
1479 (message[0] >= 0x20 && message[0] <= 0x2f))
1480 msglen = 2;
1481 break;
1482
1483 case 1:
1484 if (message[0] == EXTENDED_MESSAGE)
1485 msglen += message[msgidx];
1486 break;
1487 }
1488 msgidx += 1;
1489 if (msgidx < msglen) {
1490 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1491
1492 /* wait for next msg-in */
1493 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack");
1494 sbic_arm_read(host->scsi.io_port, SSR);
1495 }
1496 } while (msgidx < msglen);
1497
1498 #if (DEBUG & DEBUG_MESSAGES)
1499 printk("scsi%d.%c: message in: ",
1500 host->host->host_no, acornscsi_target(host));
1501 print_msg(message);
1502 printk("\n");
1503 #endif
1504
1505 if (host->scsi.phase == PHASE_RECONNECTED) {
1506 /*
1507 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1508 * 'Whenever a target reconnects to an initiator to continue
1509 * a tagged I/O process, the SIMPLE QUEUE TAG message shall
1510 * be sent immediately following the IDENTIFY message...'
1511 */
1512 if (message[0] == SIMPLE_QUEUE_TAG)
1513 host->scsi.reconnected.tag = message[1];
1514 if (acornscsi_reconnect_finish(host))
1515 host->scsi.phase = PHASE_MSGIN;
1516 }
1517
1518 switch (message[0]) {
1519 case ABORT:
1520 case ABORT_TAG:
1521 case COMMAND_COMPLETE:
1522 if (host->scsi.phase != PHASE_STATUSIN) {
1523 printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
1524 host->host->host_no, acornscsi_target(host));
1525 acornscsi_dumplog(host, host->SCpnt->target);
1526 }
1527 host->scsi.phase = PHASE_DONE;
1528 host->scsi.SCp.Message = message[0];
1529 break;
1530
1531 case SAVE_POINTERS:
1532 /*
1533 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20)
1534 * 'The SAVE DATA POINTER message is sent from a target to
1535 * direct the initiator to copy the active data pointer to
1536 * the saved data pointer for the current I/O process.
1537 */
1538 acornscsi_dma_cleanup(host);
1539 host->SCpnt->SCp = host->scsi.SCp;
1540 host->SCpnt->SCp.sent_command = 0;
1541 host->scsi.phase = PHASE_MSGIN;
1542 break;
1543
1544 case RESTORE_POINTERS:
1545 /*
1546 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19)
1547 * 'The RESTORE POINTERS message is sent from a target to
1548 * direct the initiator to copy the most recently saved
1549 * command, data, and status pointers for the I/O process
1550 * to the corresponding active pointers. The command and
1551 * status pointers shall be restored to the beginning of
1552 * the present command and status areas.'
1553 */
1554 acornscsi_dma_cleanup(host);
1555 host->scsi.SCp = host->SCpnt->SCp;
1556 host->scsi.phase = PHASE_MSGIN;
1557 break;
1558
1559 case DISCONNECT:
1560 /*
1561 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2)
1562 * 'On those occasions when an error or exception condition occurs
1563 * and the target elects to repeat the information transfer, the
1564 * target may repeat the transfer either issuing a RESTORE POINTERS
1565 * message or by disconnecting without issuing a SAVE POINTERS
1566 * message. When reconnection is completed, the most recent
1567 * saved pointer values are restored.'
1568 */
1569 acornscsi_dma_cleanup(host);
1570 host->scsi.phase = PHASE_DISCONNECT;
1571 break;
1572
1573 case MESSAGE_REJECT:
1574 #if 0 /* this isn't needed any more */
1575 /*
1576 * If we were negociating sync transfer, we don't yet know if
1577 * this REJECT is for the sync transfer or for the tagged queue/wide
1578 * transfer. Re-initiate sync transfer negociation now, and if
1579 * we got a REJECT in response to SDTR, then it'll be set to DONE.
1580 */
1581 if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST)
1582 host->device[host->SCpnt->target].sync_state = SYNC_NEGOCIATE;
1583 #endif
1584
1585 /*
1586 * If we have any messages waiting to go out, then assert ATN now
1587 */
1588 if (msgqueue_msglength(&host->scsi.msgs))
1589 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1590
1591 switch (host->scsi.last_message) {
1592 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1593 case HEAD_OF_QUEUE_TAG:
1594 case ORDERED_QUEUE_TAG:
1595 case SIMPLE_QUEUE_TAG:
1596 /*
1597 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1598 * If a target does not implement tagged queuing and a queue tag
1599 * message is received, it shall respond with a MESSAGE REJECT
1600 * message and accept the I/O process as if it were untagged.
1601 */
1602 printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
1603 host->host->host_no, acornscsi_target(host));
1604 host->SCpnt->device->tagged_queue = 0;
1605 set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
1606 break;
1607 #endif
1608 case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
1609 /*
1610 * Target can't handle synchronous transfers
1611 */
1612 printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
1613 host->host->host_no, acornscsi_target(host));
1614 host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA;
1615 host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS;
1616 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
1617 break;
1618
1619 default:
1620 break;
1621 }
1622 break;
1623
1624 case QUEUE_FULL:
1625 /* TODO: target queue is full */
1626 break;
1627
1628 case SIMPLE_QUEUE_TAG:
1629 /* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */
1630 printk("scsi%d.%c: reconnect queue tag %02X\n",
1631 host->host->host_no, acornscsi_target(host),
1632 message[1]);
1633 break;
1634
1635 case EXTENDED_MESSAGE:
1636 switch (message[2]) {
1637 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1638 case EXTENDED_SDTR:
1639 if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) {
1640 /*
1641 * We requested synchronous transfers. This isn't quite right...
1642 * We can only say if this succeeded if we proceed on to execute the
1643 * command from this message. If we get a MESSAGE PARITY ERROR,
1644 * and the target retries fail, then we fallback to asynchronous mode
1645 */
1646 host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;
1647 printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
1648 host->host->host_no, acornscsi_target(host),
1649 message[4], message[3] * 4);
1650 host->device[host->SCpnt->target].sync_xfer =
1651 calc_sync_xfer(message[3] * 4, message[4]);
1652 } else {
1653 unsigned char period, length;
1654 /*
1655 * Target requested synchronous transfers. The agreement is only
1656 * to be in operation AFTER the target leaves message out phase.
1657 */
1658 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1659 period = max_t(unsigned int, message[3], sdtr_period / 4);
1660 length = min_t(unsigned int, message[4], sdtr_size);
1661 msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
1662 EXTENDED_SDTR, period, length);
1663 host->device[host->SCpnt->target].sync_xfer =
1664 calc_sync_xfer(period * 4, length);
1665 }
1666 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
1667 break;
1668 #else
1669 /* We do not accept synchronous transfers. Respond with a
1670 * MESSAGE_REJECT.
1671 */
1672 #endif
1673
1674 case EXTENDED_WDTR:
1675 /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT
1676 * to a wide data transfer request.
1677 */
1678 default:
1679 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1680 msgqueue_flush(&host->scsi.msgs);
1681 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1682 break;
1683 }
1684 break;
1685
1686 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
1687 case LINKED_CMD_COMPLETE:
1688 case LINKED_FLG_CMD_COMPLETE:
1689 /*
1690 * We don't support linked commands yet
1691 */
1692 if (0) {
1693 #if (DEBUG & DEBUG_LINK)
1694 printk("scsi%d.%c: lun %d tag %d linked command complete\n",
1695 host->host->host_no, acornscsi_target(host), host->SCpnt->tag);
1696 #endif
1697 /*
1698 * A linked command should only terminate with one of these messages
1699 * if there are more linked commands available.
1700 */
1701 if (!host->SCpnt->next_link) {
1702 printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
1703 instance->host_no, acornscsi_target(host), host->SCpnt->tag);
1704 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1705 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1706 } else {
1707 Scsi_Cmnd *SCpnt = host->SCpnt;
1708
1709 acornscsi_dma_cleanup(host);
1710
1711 host->SCpnt = host->SCpnt->next_link;
1712 host->SCpnt->tag = SCpnt->tag;
1713 SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;
1714 SCpnt->done(SCpnt);
1715
1716 /* initialise host->SCpnt->SCp */
1717 }
1718 break;
1719 }
1720 #endif
1721
1722 default: /* reject message */
1723 printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
1724 host->host->host_no, acornscsi_target(host),
1725 message[0]);
1726 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1727 msgqueue_flush(&host->scsi.msgs);
1728 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1729 host->scsi.phase = PHASE_MSGIN;
1730 break;
1731 }
1732 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1733 }
1734
1735 /*
1736 * Function: int acornscsi_buildmessages(AS_Host *host)
1737 * Purpose : build the connection messages for a host
1738 * Params : host - host to add messages to
1739 */
1740 static
acornscsi_buildmessages(AS_Host * host)1741 void acornscsi_buildmessages(AS_Host *host)
1742 {
1743 #if 0
1744 /* does the device need resetting? */
1745 if (cmd_reset) {
1746 msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
1747 return;
1748 }
1749 #endif
1750
1751 msgqueue_addmsg(&host->scsi.msgs, 1,
1752 IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,
1753 host->SCpnt->lun));
1754
1755 #if 0
1756 /* does the device need the current command aborted */
1757 if (cmd_aborted) {
1758 acornscsi_abortcmd(host->SCpnt->tag);
1759 return;
1760 }
1761 #endif
1762
1763 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1764 if (host->SCpnt->tag) {
1765 unsigned int tag_type;
1766
1767 if (host->SCpnt->cmnd[0] == REQUEST_SENSE ||
1768 host->SCpnt->cmnd[0] == TEST_UNIT_READY ||
1769 host->SCpnt->cmnd[0] == INQUIRY)
1770 tag_type = HEAD_OF_QUEUE_TAG;
1771 else
1772 tag_type = SIMPLE_QUEUE_TAG;
1773 msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
1774 }
1775 #endif
1776
1777 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1778 if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) {
1779 host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST;
1780 msgqueue_addmsg(&host->scsi.msgs, 5,
1781 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1782 sdtr_period / 4, sdtr_size);
1783 }
1784 #endif
1785 }
1786
1787 /*
1788 * Function: int acornscsi_starttransfer(AS_Host *host)
1789 * Purpose : transfer data to/from connected target
1790 * Params : host - host to which target is connected
1791 * Returns : 0 if failure
1792 */
1793 static
acornscsi_starttransfer(AS_Host * host)1794 int acornscsi_starttransfer(AS_Host *host)
1795 {
1796 int residual;
1797
1798 if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {
1799 printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
1800 host->host->host_no, acornscsi_target(host));
1801 return 0;
1802 }
1803
1804 residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
1805
1806 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
1807 sbic_arm_writenext(host->scsi.io_port, residual >> 16);
1808 sbic_arm_writenext(host->scsi.io_port, residual >> 8);
1809 sbic_arm_writenext(host->scsi.io_port, residual);
1810 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1811 return 1;
1812 }
1813
1814 /* =========================================================================================
1815 * Connection & Disconnection
1816 */
1817 /*
1818 * Function : acornscsi_reconnect(AS_Host *host)
1819 * Purpose : reconnect a previously disconnected command
1820 * Params : host - host specific data
1821 * Remarks : SCSI spec says:
1822 * 'The set of active pointers is restored from the set
1823 * of saved pointers upon reconnection of the I/O process'
1824 */
1825 static
acornscsi_reconnect(AS_Host * host)1826 int acornscsi_reconnect(AS_Host *host)
1827 {
1828 unsigned int target, lun, ok = 0;
1829
1830 target = sbic_arm_read(host->scsi.io_port, SOURCEID);
1831
1832 if (!(target & 8))
1833 printk(KERN_ERR "scsi%d: invalid source id after reselection "
1834 "- device fault?\n",
1835 host->host->host_no);
1836
1837 target &= 7;
1838
1839 if (host->SCpnt && !host->scsi.disconnectable) {
1840 printk(KERN_ERR "scsi%d.%d: reconnected while command in "
1841 "progress to target %d?\n",
1842 host->host->host_no, target, host->SCpnt->target);
1843 host->SCpnt = NULL;
1844 }
1845
1846 lun = sbic_arm_read(host->scsi.io_port, DATA) & 7;
1847
1848 host->scsi.reconnected.target = target;
1849 host->scsi.reconnected.lun = lun;
1850 host->scsi.reconnected.tag = 0;
1851
1852 if (host->scsi.disconnectable && host->SCpnt &&
1853 host->SCpnt->target == target && host->SCpnt->lun == lun)
1854 ok = 1;
1855
1856 if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
1857 ok = 1;
1858
1859 ADD_STATUS(target, 0x81, host->scsi.phase, 0);
1860
1861 if (ok) {
1862 host->scsi.phase = PHASE_RECONNECTED;
1863 } else {
1864 /* this doesn't seem to work */
1865 printk(KERN_ERR "scsi%d.%c: reselected with no command "
1866 "to reconnect with\n",
1867 host->host->host_no, '0' + target);
1868 acornscsi_dumplog(host, target);
1869 acornscsi_abortcmd(host, 0);
1870 if (host->SCpnt) {
1871 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1872 host->SCpnt = NULL;
1873 }
1874 }
1875 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1876 return !ok;
1877 }
1878
1879 /*
1880 * Function: int acornscsi_reconect_finish(AS_Host *host)
1881 * Purpose : finish reconnecting a command
1882 * Params : host - host to complete
1883 * Returns : 0 if failed
1884 */
1885 static
acornscsi_reconnect_finish(AS_Host * host)1886 int acornscsi_reconnect_finish(AS_Host *host)
1887 {
1888 if (host->scsi.disconnectable && host->SCpnt) {
1889 host->scsi.disconnectable = 0;
1890 if (host->SCpnt->target == host->scsi.reconnected.target &&
1891 host->SCpnt->lun == host->scsi.reconnected.lun &&
1892 host->SCpnt->tag == host->scsi.reconnected.tag) {
1893 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1894 DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
1895 host->host->host_no, acornscsi_target(host)));
1896 #endif
1897 } else {
1898 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1899 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1900 DBG(host->SCpnt, printk("scsi%d.%c: had to move command "
1901 "to disconnected queue\n",
1902 host->host->host_no, acornscsi_target(host)));
1903 #endif
1904 host->SCpnt = NULL;
1905 }
1906 }
1907 if (!host->SCpnt) {
1908 host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected,
1909 host->scsi.reconnected.target,
1910 host->scsi.reconnected.lun,
1911 host->scsi.reconnected.tag);
1912 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1913 DBG(host->SCpnt, printk("scsi%d.%c: had to get command",
1914 host->host->host_no, acornscsi_target(host)));
1915 #endif
1916 }
1917
1918 if (!host->SCpnt)
1919 acornscsi_abortcmd(host, host->scsi.reconnected.tag);
1920 else {
1921 /*
1922 * Restore data pointer from SAVED pointers.
1923 */
1924 host->scsi.SCp = host->SCpnt->SCp;
1925 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1926 printk(", data pointers: [%p, %X]",
1927 host->scsi.SCp.ptr, host->scsi.SCp.this_residual);
1928 #endif
1929 }
1930 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1931 printk("\n");
1932 #endif
1933
1934 host->dma.transferred = host->scsi.SCp.scsi_xferred;
1935
1936 return host->SCpnt != NULL;
1937 }
1938
1939 /*
1940 * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
1941 * Purpose : handle an unexpected disconnect
1942 * Params : host - host on which disconnect occurred
1943 */
1944 static
acornscsi_disconnect_unexpected(AS_Host * host)1945 void acornscsi_disconnect_unexpected(AS_Host *host)
1946 {
1947 printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n",
1948 host->host->host_no, acornscsi_target(host));
1949 #if (DEBUG & DEBUG_ABORT)
1950 acornscsi_dumplog(host, 8);
1951 #endif
1952
1953 acornscsi_done(host, &host->SCpnt, DID_ERROR);
1954 }
1955
1956 /*
1957 * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
1958 * Purpose : abort a currently executing command
1959 * Params : host - host with connected command to abort
1960 * tag - tag to abort
1961 */
1962 static
acornscsi_abortcmd(AS_Host * host,unsigned char tag)1963 void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
1964 {
1965 host->scsi.phase = PHASE_ABORTED;
1966 sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN);
1967
1968 msgqueue_flush(&host->scsi.msgs);
1969 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1970 if (tag)
1971 msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
1972 else
1973 #endif
1974 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1975 }
1976
1977 /* ==========================================================================================
1978 * Interrupt routines.
1979 */
1980 /*
1981 * Function: int acornscsi_sbicintr(AS_Host *host)
1982 * Purpose : handle interrupts from SCSI device
1983 * Params : host - host to process
1984 * Returns : INTR_PROCESS if expecting another SBIC interrupt
1985 * INTR_IDLE if no interrupt
1986 * INTR_NEXT_COMMAND if we have finished processing the command
1987 */
1988 static
acornscsi_sbicintr(AS_Host * host,int in_irq)1989 intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
1990 {
1991 unsigned int asr, ssr;
1992
1993 asr = sbic_arm_read(host->scsi.io_port, ASR);
1994 if (!(asr & ASR_INT))
1995 return INTR_IDLE;
1996
1997 ssr = sbic_arm_read(host->scsi.io_port, SSR);
1998
1999 #if (DEBUG & DEBUG_PHASES)
2000 print_sbic_status(asr, ssr, host->scsi.phase);
2001 #endif
2002
2003 ADD_STATUS(8, ssr, host->scsi.phase, in_irq);
2004
2005 if (host->SCpnt && !host->scsi.disconnectable)
2006 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
2007
2008 switch (ssr) {
2009 case 0x00: /* reset state - not advanced */
2010 printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
2011 host->host->host_no);
2012 /* setup sbic - WD33C93A */
2013 sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
2014 sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
2015 return INTR_IDLE;
2016
2017 case 0x01: /* reset state - advanced */
2018 sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
2019 sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
2020 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
2021 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
2022 msgqueue_flush(&host->scsi.msgs);
2023 return INTR_IDLE;
2024
2025 case 0x41: /* unexpected disconnect aborted command */
2026 acornscsi_disconnect_unexpected(host);
2027 return INTR_NEXT_COMMAND;
2028 }
2029
2030 switch (host->scsi.phase) {
2031 case PHASE_CONNECTING: /* STATE: command removed from issue queue */
2032 switch (ssr) {
2033 case 0x11: /* -> PHASE_CONNECTED */
2034 /* BUS FREE -> SELECTION */
2035 host->scsi.phase = PHASE_CONNECTED;
2036 msgqueue_flush(&host->scsi.msgs);
2037 host->dma.transferred = host->scsi.SCp.scsi_xferred;
2038 /* 33C93 gives next interrupt indicating bus phase */
2039 asr = sbic_arm_read(host->scsi.io_port, ASR);
2040 if (!(asr & ASR_INT))
2041 break;
2042 ssr = sbic_arm_read(host->scsi.io_port, SSR);
2043 ADD_STATUS(8, ssr, host->scsi.phase, 1);
2044 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1);
2045 goto connected;
2046
2047 case 0x42: /* select timed out */
2048 /* -> PHASE_IDLE */
2049 acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
2050 return INTR_NEXT_COMMAND;
2051
2052 case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2053 /* BUS FREE -> RESELECTION */
2054 host->origSCpnt = host->SCpnt;
2055 host->SCpnt = NULL;
2056 msgqueue_flush(&host->scsi.msgs);
2057 acornscsi_reconnect(host);
2058 break;
2059
2060 default:
2061 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
2062 host->host->host_no, acornscsi_target(host), ssr);
2063 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2064 acornscsi_abortcmd(host, host->SCpnt->tag);
2065 }
2066 return INTR_PROCESSING;
2067
2068 connected:
2069 case PHASE_CONNECTED: /* STATE: device selected ok */
2070 switch (ssr) {
2071 #ifdef NONSTANDARD
2072 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2073 /* SELECTION -> COMMAND */
2074 acornscsi_sendcommand(host);
2075 break;
2076
2077 case 0x8b: /* -> PHASE_STATUS */
2078 /* SELECTION -> STATUS */
2079 acornscsi_readstatusbyte(host);
2080 host->scsi.phase = PHASE_STATUSIN;
2081 break;
2082 #endif
2083
2084 case 0x8e: /* -> PHASE_MSGOUT */
2085 /* SELECTION ->MESSAGE OUT */
2086 host->scsi.phase = PHASE_MSGOUT;
2087 acornscsi_buildmessages(host);
2088 acornscsi_sendmessage(host);
2089 break;
2090
2091 /* these should not happen */
2092 case 0x85: /* target disconnected */
2093 acornscsi_done(host, &host->SCpnt, DID_ERROR);
2094 break;
2095
2096 default:
2097 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
2098 host->host->host_no, acornscsi_target(host), ssr);
2099 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2100 acornscsi_abortcmd(host, host->SCpnt->tag);
2101 }
2102 return INTR_PROCESSING;
2103
2104 case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */
2105 /*
2106 * SCSI standard says that MESSAGE OUT phases can be followed by a
2107 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
2108 */
2109 switch (ssr) {
2110 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2111 case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2112 /* MESSAGE OUT -> COMMAND */
2113 acornscsi_sendcommand(host);
2114 break;
2115
2116 case 0x8b: /* -> PHASE_STATUS */
2117 case 0x1b: /* -> PHASE_STATUS */
2118 /* MESSAGE OUT -> STATUS */
2119 acornscsi_readstatusbyte(host);
2120 host->scsi.phase = PHASE_STATUSIN;
2121 break;
2122
2123 case 0x8e: /* -> PHASE_MSGOUT */
2124 /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
2125 acornscsi_sendmessage(host);
2126 break;
2127
2128 case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2129 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2130 /* MESSAGE OUT -> MESSAGE IN */
2131 acornscsi_message(host);
2132 break;
2133
2134 default:
2135 printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
2136 host->host->host_no, acornscsi_target(host), ssr);
2137 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2138 }
2139 return INTR_PROCESSING;
2140
2141 case PHASE_COMMAND: /* STATE: connected & command sent */
2142 switch (ssr) {
2143 case 0x18: /* -> PHASE_DATAOUT */
2144 /* COMMAND -> DATA OUT */
2145 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2146 acornscsi_abortcmd(host, host->SCpnt->tag);
2147 acornscsi_dma_setup(host, DMA_OUT);
2148 if (!acornscsi_starttransfer(host))
2149 acornscsi_abortcmd(host, host->SCpnt->tag);
2150 host->scsi.phase = PHASE_DATAOUT;
2151 return INTR_IDLE;
2152
2153 case 0x19: /* -> PHASE_DATAIN */
2154 /* COMMAND -> DATA IN */
2155 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2156 acornscsi_abortcmd(host, host->SCpnt->tag);
2157 acornscsi_dma_setup(host, DMA_IN);
2158 if (!acornscsi_starttransfer(host))
2159 acornscsi_abortcmd(host, host->SCpnt->tag);
2160 host->scsi.phase = PHASE_DATAIN;
2161 return INTR_IDLE;
2162
2163 case 0x1b: /* -> PHASE_STATUS */
2164 /* COMMAND -> STATUS */
2165 acornscsi_readstatusbyte(host);
2166 host->scsi.phase = PHASE_STATUSIN;
2167 break;
2168
2169 case 0x1e: /* -> PHASE_MSGOUT */
2170 /* COMMAND -> MESSAGE OUT */
2171 acornscsi_sendmessage(host);
2172 break;
2173
2174 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2175 /* COMMAND -> MESSAGE IN */
2176 acornscsi_message(host);
2177 break;
2178
2179 default:
2180 printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
2181 host->host->host_no, acornscsi_target(host), ssr);
2182 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2183 }
2184 return INTR_PROCESSING;
2185
2186 case PHASE_DISCONNECT: /* STATE: connected, received DISCONNECT msg */
2187 if (ssr == 0x85) { /* -> PHASE_IDLE */
2188 host->scsi.disconnectable = 1;
2189 host->scsi.reconnected.tag = 0;
2190 host->scsi.phase = PHASE_IDLE;
2191 host->stats.disconnects += 1;
2192 } else {
2193 printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
2194 host->host->host_no, acornscsi_target(host), ssr);
2195 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2196 }
2197 return INTR_NEXT_COMMAND;
2198
2199 case PHASE_IDLE: /* STATE: disconnected */
2200 if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2201 acornscsi_reconnect(host);
2202 else {
2203 printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
2204 host->host->host_no, acornscsi_target(host), ssr);
2205 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2206 }
2207 return INTR_PROCESSING;
2208
2209 case PHASE_RECONNECTED: /* STATE: device reconnected to initiator */
2210 /*
2211 * Command reconnected - if MESGIN, get message - it may be
2212 * the tag. If not, get command out of disconnected queue
2213 */
2214 /*
2215 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
2216 * reconnect I_T_L command
2217 */
2218 if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
2219 return INTR_IDLE;
2220 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
2221 switch (ssr) {
2222 case 0x88: /* data out phase */
2223 /* -> PHASE_DATAOUT */
2224 /* MESSAGE IN -> DATA OUT */
2225 acornscsi_dma_setup(host, DMA_OUT);
2226 if (!acornscsi_starttransfer(host))
2227 acornscsi_abortcmd(host, host->SCpnt->tag);
2228 host->scsi.phase = PHASE_DATAOUT;
2229 return INTR_IDLE;
2230
2231 case 0x89: /* data in phase */
2232 /* -> PHASE_DATAIN */
2233 /* MESSAGE IN -> DATA IN */
2234 acornscsi_dma_setup(host, DMA_IN);
2235 if (!acornscsi_starttransfer(host))
2236 acornscsi_abortcmd(host, host->SCpnt->tag);
2237 host->scsi.phase = PHASE_DATAIN;
2238 return INTR_IDLE;
2239
2240 case 0x8a: /* command out */
2241 /* MESSAGE IN -> COMMAND */
2242 acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2243 break;
2244
2245 case 0x8b: /* status in */
2246 /* -> PHASE_STATUSIN */
2247 /* MESSAGE IN -> STATUS */
2248 acornscsi_readstatusbyte(host);
2249 host->scsi.phase = PHASE_STATUSIN;
2250 break;
2251
2252 case 0x8e: /* message out */
2253 /* -> PHASE_MSGOUT */
2254 /* MESSAGE IN -> MESSAGE OUT */
2255 acornscsi_sendmessage(host);
2256 break;
2257
2258 case 0x8f: /* message in */
2259 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2260 break;
2261
2262 default:
2263 printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
2264 host->host->host_no, acornscsi_target(host), ssr);
2265 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2266 }
2267 return INTR_PROCESSING;
2268
2269 case PHASE_DATAIN: /* STATE: transferred data in */
2270 /*
2271 * This is simple - if we disconnect then the DMA address & count is
2272 * correct.
2273 */
2274 switch (ssr) {
2275 case 0x19: /* -> PHASE_DATAIN */
2276 case 0x89: /* -> PHASE_DATAIN */
2277 acornscsi_abortcmd(host, host->SCpnt->tag);
2278 return INTR_IDLE;
2279
2280 case 0x1b: /* -> PHASE_STATUSIN */
2281 case 0x4b: /* -> PHASE_STATUSIN */
2282 case 0x8b: /* -> PHASE_STATUSIN */
2283 /* DATA IN -> STATUS */
2284 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2285 acornscsi_sbic_xfcount(host);
2286 acornscsi_dma_stop(host);
2287 acornscsi_readstatusbyte(host);
2288 host->scsi.phase = PHASE_STATUSIN;
2289 break;
2290
2291 case 0x1e: /* -> PHASE_MSGOUT */
2292 case 0x4e: /* -> PHASE_MSGOUT */
2293 case 0x8e: /* -> PHASE_MSGOUT */
2294 /* DATA IN -> MESSAGE OUT */
2295 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2296 acornscsi_sbic_xfcount(host);
2297 acornscsi_dma_stop(host);
2298 acornscsi_sendmessage(host);
2299 break;
2300
2301 case 0x1f: /* message in */
2302 case 0x4f: /* message in */
2303 case 0x8f: /* message in */
2304 /* DATA IN -> MESSAGE IN */
2305 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2306 acornscsi_sbic_xfcount(host);
2307 acornscsi_dma_stop(host);
2308 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2309 break;
2310
2311 default:
2312 printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
2313 host->host->host_no, acornscsi_target(host), ssr);
2314 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2315 }
2316 return INTR_PROCESSING;
2317
2318 case PHASE_DATAOUT: /* STATE: transferred data out */
2319 /*
2320 * This is more complicated - if we disconnect, the DMA could be 12
2321 * bytes ahead of us. We need to correct this.
2322 */
2323 switch (ssr) {
2324 case 0x18: /* -> PHASE_DATAOUT */
2325 case 0x88: /* -> PHASE_DATAOUT */
2326 acornscsi_abortcmd(host, host->SCpnt->tag);
2327 return INTR_IDLE;
2328
2329 case 0x1b: /* -> PHASE_STATUSIN */
2330 case 0x4b: /* -> PHASE_STATUSIN */
2331 case 0x8b: /* -> PHASE_STATUSIN */
2332 /* DATA OUT -> STATUS */
2333 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2334 acornscsi_sbic_xfcount(host);
2335 acornscsi_dma_stop(host);
2336 acornscsi_dma_adjust(host);
2337 acornscsi_readstatusbyte(host);
2338 host->scsi.phase = PHASE_STATUSIN;
2339 break;
2340
2341 case 0x1e: /* -> PHASE_MSGOUT */
2342 case 0x4e: /* -> PHASE_MSGOUT */
2343 case 0x8e: /* -> PHASE_MSGOUT */
2344 /* DATA OUT -> MESSAGE OUT */
2345 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2346 acornscsi_sbic_xfcount(host);
2347 acornscsi_dma_stop(host);
2348 acornscsi_dma_adjust(host);
2349 acornscsi_sendmessage(host);
2350 break;
2351
2352 case 0x1f: /* message in */
2353 case 0x4f: /* message in */
2354 case 0x8f: /* message in */
2355 /* DATA OUT -> MESSAGE IN */
2356 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2357 acornscsi_sbic_xfcount(host);
2358 acornscsi_dma_stop(host);
2359 acornscsi_dma_adjust(host);
2360 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2361 break;
2362
2363 default:
2364 printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
2365 host->host->host_no, acornscsi_target(host), ssr);
2366 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2367 }
2368 return INTR_PROCESSING;
2369
2370 case PHASE_STATUSIN: /* STATE: status in complete */
2371 switch (ssr) {
2372 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2373 case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2374 /* STATUS -> MESSAGE IN */
2375 acornscsi_message(host);
2376 break;
2377
2378 case 0x1e: /* -> PHASE_MSGOUT */
2379 case 0x8e: /* -> PHASE_MSGOUT */
2380 /* STATUS -> MESSAGE OUT */
2381 acornscsi_sendmessage(host);
2382 break;
2383
2384 default:
2385 printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
2386 host->host->host_no, acornscsi_target(host), ssr);
2387 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2388 }
2389 return INTR_PROCESSING;
2390
2391 case PHASE_MSGIN: /* STATE: message in */
2392 switch (ssr) {
2393 case 0x1e: /* -> PHASE_MSGOUT */
2394 case 0x4e: /* -> PHASE_MSGOUT */
2395 case 0x8e: /* -> PHASE_MSGOUT */
2396 /* MESSAGE IN -> MESSAGE OUT */
2397 acornscsi_sendmessage(host);
2398 break;
2399
2400 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2401 case 0x2f:
2402 case 0x4f:
2403 case 0x8f:
2404 acornscsi_message(host);
2405 break;
2406
2407 case 0x85:
2408 printk("scsi%d.%c: strange message in disconnection\n",
2409 host->host->host_no, acornscsi_target(host));
2410 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2411 acornscsi_done(host, &host->SCpnt, DID_ERROR);
2412 break;
2413
2414 default:
2415 printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
2416 host->host->host_no, acornscsi_target(host), ssr);
2417 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2418 }
2419 return INTR_PROCESSING;
2420
2421 case PHASE_DONE: /* STATE: received status & message */
2422 switch (ssr) {
2423 case 0x85: /* -> PHASE_IDLE */
2424 acornscsi_done(host, &host->SCpnt, DID_OK);
2425 return INTR_NEXT_COMMAND;
2426
2427 case 0x1e:
2428 case 0x8e:
2429 acornscsi_sendmessage(host);
2430 break;
2431
2432 default:
2433 printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
2434 host->host->host_no, acornscsi_target(host), ssr);
2435 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2436 }
2437 return INTR_PROCESSING;
2438
2439 case PHASE_ABORTED:
2440 switch (ssr) {
2441 case 0x85:
2442 if (host->SCpnt)
2443 acornscsi_done(host, &host->SCpnt, DID_ABORT);
2444 else {
2445 clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
2446 host->busyluns);
2447 host->scsi.phase = PHASE_IDLE;
2448 }
2449 return INTR_NEXT_COMMAND;
2450
2451 case 0x1e:
2452 case 0x2e:
2453 case 0x4e:
2454 case 0x8e:
2455 acornscsi_sendmessage(host);
2456 break;
2457
2458 default:
2459 printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
2460 host->host->host_no, acornscsi_target(host), ssr);
2461 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2462 }
2463 return INTR_PROCESSING;
2464
2465 default:
2466 printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
2467 host->host->host_no, acornscsi_target(host), ssr);
2468 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
2469 }
2470 return INTR_PROCESSING;
2471 }
2472
2473 /*
2474 * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
2475 * Purpose : handle interrupts from Acorn SCSI card
2476 * Params : irq - interrupt number
2477 * dev_id - device specific data (AS_Host structure)
2478 * regs - processor registers when interrupt occurred
2479 */
2480 static
acornscsi_intr(int irq,void * dev_id,struct pt_regs * regs)2481 void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
2482 {
2483 AS_Host *host = (AS_Host *)dev_id;
2484 intr_ret_t ret;
2485 int iostatus;
2486 int in_irq = 0;
2487
2488 if (host->scsi.interrupt)
2489 printk("scsi%d: interrupt re-entered\n", host->host->host_no);
2490 host->scsi.interrupt = 1;
2491
2492 do {
2493 ret = INTR_IDLE;
2494
2495 iostatus = inb(host->card.io_intr);
2496
2497 if (iostatus & 2) {
2498 acornscsi_dma_intr(host);
2499 iostatus = inb(host->card.io_intr);
2500 }
2501
2502 if (iostatus & 8)
2503 ret = acornscsi_sbicintr(host, in_irq);
2504
2505 /*
2506 * If we have a transfer pending, start it.
2507 * Only start it if the interface has already started transferring
2508 * it's data
2509 */
2510 if (host->dma.xfer_required)
2511 acornscsi_dma_xfer(host);
2512
2513 if (ret == INTR_NEXT_COMMAND)
2514 ret = acornscsi_kick(host);
2515
2516 in_irq = 1;
2517 } while (ret != INTR_IDLE);
2518
2519 host->scsi.interrupt = 0;
2520 }
2521
2522 /*=============================================================================================
2523 * Interfaces between interrupt handler and rest of scsi code
2524 */
2525
2526 /*
2527 * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
2528 * Purpose : queues a SCSI command
2529 * Params : cmd - SCSI command
2530 * done - function called on completion, with pointer to command descriptor
2531 * Returns : 0, or < 0 on error.
2532 */
acornscsi_queuecmd(Scsi_Cmnd * SCpnt,void (* done)(Scsi_Cmnd *))2533 int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2534 {
2535 AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
2536
2537 if (!done) {
2538 /* there should be some way of rejecting errors like this without panicing... */
2539 panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
2540 SCpnt->host->host_no, SCpnt);
2541 return -EINVAL;
2542 }
2543
2544 #if (DEBUG & DEBUG_NO_WRITE)
2545 if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
2546 printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
2547 SCpnt->host->host_no, '0' + SCpnt->target);
2548 SCpnt->result = DID_NO_CONNECT << 16;
2549 done(SCpnt);
2550 return 0;
2551 }
2552 #endif
2553
2554 SCpnt->scsi_done = done;
2555 SCpnt->host_scribble = NULL;
2556 SCpnt->result = 0;
2557 SCpnt->tag = 0;
2558 SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
2559 SCpnt->SCp.sent_command = 0;
2560 SCpnt->SCp.scsi_xferred = 0;
2561 SCpnt->SCp.Status = 0;
2562 SCpnt->SCp.Message = 0;
2563
2564 if (SCpnt->use_sg) {
2565 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
2566 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
2567 SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;
2568 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
2569 } else {
2570 SCpnt->SCp.buffer = NULL;
2571 SCpnt->SCp.buffers_residual = 0;
2572 SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
2573 SCpnt->SCp.this_residual = SCpnt->request_bufflen;
2574 }
2575
2576 host->stats.queues += 1;
2577
2578 {
2579 unsigned long flags;
2580
2581 if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
2582 SCpnt->result = DID_ERROR << 16;
2583 done(SCpnt);
2584 return 0;
2585 }
2586 save_flags_cli(flags);
2587 if (host->scsi.phase == PHASE_IDLE)
2588 acornscsi_kick(host);
2589 restore_flags(flags);
2590 }
2591 return 0;
2592 }
2593
2594 /*
2595 * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
2596 * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
2597 * Params : SCpntp1 - pointer to command to return
2598 * SCpntp2 - pointer to command to check
2599 * result - result to pass back to mid-level done function
2600 * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
2601 */
2602 static inline
acornscsi_reportstatus(Scsi_Cmnd ** SCpntp1,Scsi_Cmnd ** SCpntp2,int result)2603 void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
2604 {
2605 Scsi_Cmnd *SCpnt = *SCpntp1;
2606
2607 if (SCpnt) {
2608 *SCpntp1 = NULL;
2609
2610 SCpnt->result = result;
2611 SCpnt->scsi_done(SCpnt);
2612 }
2613
2614 if (SCpnt == *SCpntp2)
2615 *SCpntp2 = NULL;
2616 }
2617
2618 enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
2619
2620 /*
2621 * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt)
2622 * Purpose : abort a command on this host
2623 * Params : SCpnt - command to abort
2624 * Returns : our abort status
2625 */
2626 static enum res_abort
acornscsi_do_abort(AS_Host * host,Scsi_Cmnd * SCpnt)2627 acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
2628 {
2629 enum res_abort res = res_not_running;
2630
2631 if (queue_remove_cmd(&host->queues.issue, SCpnt)) {
2632 /*
2633 * The command was on the issue queue, and has not been
2634 * issued yet. We can remove the command from the queue,
2635 * and acknowledge the abort. Neither the devices nor the
2636 * interface know about the command.
2637 */
2638 //#if (DEBUG & DEBUG_ABORT)
2639 printk("on issue queue ");
2640 //#endif
2641 res = res_success;
2642 } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) {
2643 /*
2644 * The command was on the disconnected queue. Simply
2645 * acknowledge the abort condition, and when the target
2646 * reconnects, we will give it an ABORT message. The
2647 * target should then disconnect, and we will clear
2648 * the busylun bit.
2649 */
2650 //#if (DEBUG & DEBUG_ABORT)
2651 printk("on disconnected queue ");
2652 //#endif
2653 res = res_success;
2654 } else if (host->SCpnt == SCpnt) {
2655 unsigned long flags;
2656
2657 //#if (DEBUG & DEBUG_ABORT)
2658 printk("executing ");
2659 //#endif
2660
2661 save_flags(flags);
2662 cli();
2663 switch (host->scsi.phase) {
2664 /*
2665 * If the interface is idle, and the command is 'disconnectable',
2666 * then it is the same as on the disconnected queue. We simply
2667 * remove all traces of the command. When the target reconnects,
2668 * we will give it an ABORT message since the command could not
2669 * be found. When the target finally disconnects, we will clear
2670 * the busylun bit.
2671 */
2672 case PHASE_IDLE:
2673 if (host->scsi.disconnectable) {
2674 host->scsi.disconnectable = 0;
2675 host->SCpnt = NULL;
2676 res = res_success;
2677 }
2678 break;
2679
2680 /*
2681 * If the command has connected and done nothing further,
2682 * simply force a disconnect. We also need to clear the
2683 * busylun bit.
2684 */
2685 case PHASE_CONNECTED:
2686 sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT);
2687 host->SCpnt = NULL;
2688 res = res_success_clear;
2689 break;
2690
2691 default:
2692 acornscsi_abortcmd(host, host->SCpnt->tag);
2693 res = res_snooze;
2694 }
2695 restore_flags(flags);
2696 } else if (host->origSCpnt == SCpnt) {
2697 /*
2698 * The command will be executed next, but a command
2699 * is currently using the interface. This is similar to
2700 * being on the issue queue, except the busylun bit has
2701 * been set.
2702 */
2703 host->origSCpnt = NULL;
2704 //#if (DEBUG & DEBUG_ABORT)
2705 printk("waiting for execution ");
2706 //#endif
2707 res = res_success_clear;
2708 } else
2709 printk("unknown ");
2710
2711 return res;
2712 }
2713
2714 /*
2715 * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt)
2716 * Purpose : abort a command on this host
2717 * Params : SCpnt - command to abort
2718 * Returns : one of SCSI_ABORT_ macros
2719 */
acornscsi_abort(Scsi_Cmnd * SCpnt)2720 int acornscsi_abort(Scsi_Cmnd *SCpnt)
2721 {
2722 AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
2723 int result;
2724
2725 host->stats.aborts += 1;
2726
2727 #if (DEBUG & DEBUG_ABORT)
2728 {
2729 int asr, ssr;
2730 asr = sbic_arm_read(host->scsi.io_port, ASR);
2731 ssr = sbic_arm_read(host->scsi.io_port, SSR);
2732
2733 printk(KERN_WARNING "acornscsi_abort: ");
2734 print_sbic_status(asr, ssr, host->scsi.phase);
2735 acornscsi_dumplog(host, SCpnt->target);
2736 }
2737 #endif
2738
2739 printk("scsi%d: ", host->host->host_no);
2740
2741 switch (acornscsi_do_abort(host, SCpnt)) {
2742 /*
2743 * We managed to find the command and cleared it out.
2744 * We do not expect the command to be executing on the
2745 * target, but we have set the busylun bit.
2746 */
2747 case res_success_clear:
2748 //#if (DEBUG & DEBUG_ABORT)
2749 printk("clear ");
2750 //#endif
2751 clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
2752
2753 /*
2754 * We found the command, and cleared it out. Either
2755 * the command is still known to be executing on the
2756 * target, or the busylun bit is not set.
2757 */
2758 case res_success:
2759 //#if (DEBUG & DEBUG_ABORT)
2760 printk("success\n");
2761 //#endif
2762 SCpnt->result = DID_ABORT << 16;
2763 SCpnt->scsi_done(SCpnt);
2764 result = SCSI_ABORT_SUCCESS;
2765 break;
2766
2767 /*
2768 * We did find the command, but unfortunately we couldn't
2769 * unhook it from ourselves. Wait some more, and if it
2770 * still doesn't complete, reset the interface.
2771 */
2772 case res_snooze:
2773 //#if (DEBUG & DEBUG_ABORT)
2774 printk("snooze\n");
2775 //#endif
2776 result = SCSI_ABORT_SNOOZE;
2777 break;
2778
2779 /*
2780 * The command could not be found (either because it completed,
2781 * or it got dropped.
2782 */
2783 default:
2784 case res_not_running:
2785 acornscsi_dumplog(host, SCpnt->target);
2786 #if (DEBUG & DEBUG_ABORT)
2787 result = SCSI_ABORT_SNOOZE;
2788 #else
2789 result = SCSI_ABORT_NOT_RUNNING;
2790 #endif
2791 //#if (DEBUG & DEBUG_ABORT)
2792 printk("not running\n");
2793 //#endif
2794 break;
2795 }
2796
2797 return result;
2798 }
2799
2800 /*
2801 * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2802 * Purpose : reset a command on this host/reset this host
2803 * Params : SCpnt - command causing reset
2804 * result - what type of reset to perform
2805 * Returns : one of SCSI_RESET_ macros
2806 */
acornscsi_reset(Scsi_Cmnd * SCpnt,unsigned int reset_flags)2807 int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2808 {
2809 AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
2810 Scsi_Cmnd *SCptr;
2811
2812 host->stats.resets += 1;
2813
2814 #if (DEBUG & DEBUG_RESET)
2815 {
2816 int asr, ssr;
2817
2818 asr = sbic_arm_read(host->scsi.io_port, ASR);
2819 ssr = sbic_arm_read(host->scsi.io_port, SSR);
2820
2821 printk(KERN_WARNING "acornscsi_reset: ");
2822 print_sbic_status(asr, ssr, host->scsi.phase);
2823 acornscsi_dumplog(host, SCpnt->target);
2824 }
2825 #endif
2826
2827 acornscsi_dma_stop(host);
2828
2829 SCptr = host->SCpnt;
2830
2831 /*
2832 * do hard reset. This resets all devices on this host, and so we
2833 * must set the reset status on all commands.
2834 */
2835 acornscsi_resetcard(host);
2836
2837 /*
2838 * report reset on commands current connected/disconnected
2839 */
2840 acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET);
2841
2842 while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
2843 acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET);
2844
2845 if (SCpnt) {
2846 SCpnt->result = DID_RESET << 16;
2847 SCpnt->scsi_done(SCpnt);
2848 }
2849
2850 return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
2851 }
2852
2853 /*==============================================================================================
2854 * initialisation & miscellaneous support
2855 */
2856 static struct expansion_card *ecs[MAX_ECARDS];
2857
2858 /*
2859 * Prototype: void acornscsi_init(AS_Host *host)
2860 * Purpose : initialise the AS_Host structure for one interface & setup hardware
2861 * Params : host - host to setup
2862 */
2863 static
acornscsi_host_init(AS_Host * host)2864 void acornscsi_host_init(AS_Host *host)
2865 {
2866 memset(&host->stats, 0, sizeof (host->stats));
2867 queue_initialise(&host->queues.issue);
2868 queue_initialise(&host->queues.disconnected);
2869 msgqueue_initialise(&host->scsi.msgs);
2870
2871 acornscsi_resetcard(host);
2872 }
2873
acornscsi_detect(Scsi_Host_Template * tpnt)2874 int acornscsi_detect(Scsi_Host_Template * tpnt)
2875 {
2876 static const card_ids acornscsi_cids[] = { ACORNSCSI_LIST, { 0xffff, 0xffff } };
2877 int i, count = 0;
2878 struct Scsi_Host *instance;
2879 AS_Host *host;
2880
2881 tpnt->proc_name = "acornscsi";
2882
2883 for (i = 0; i < MAX_ECARDS; i++)
2884 ecs[i] = NULL;
2885
2886 ecard_startfind();
2887
2888 while(1) {
2889 ecs[count] = ecard_find(0, acornscsi_cids);
2890 if (!ecs[count])
2891 break;
2892
2893 if (ecs[count]->irq == 0xff) {
2894 printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
2895 continue;
2896 }
2897
2898 ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */
2899
2900 instance = scsi_register(tpnt, sizeof(AS_Host));
2901 host = (AS_Host *)instance->hostdata;
2902
2903 instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
2904 instance->irq = ecs[count]->irq;
2905
2906 host->host = instance;
2907 host->scsi.io_port = ioaddr(instance->io_port + 0x800);
2908 host->scsi.irq = instance->irq;
2909 host->card.io_intr = POD_SPACE(instance->io_port) + 0x800;
2910 host->card.io_page = POD_SPACE(instance->io_port) + 0xc00;
2911 host->card.io_ram = ioaddr(instance->io_port);
2912 host->dma.io_port = instance->io_port + 0xc00;
2913 host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
2914
2915 ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr);
2916 ecs[count]->irqmask = 0x0a;
2917
2918 if (!request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)"))
2919 goto err_1;
2920 if (!request_region(host->card.io_intr, 1, "acornscsi(intr)"))
2921 goto err_2;
2922 if (!request_region(host->card.io_page, 1, "acornscsi(page)"))
2923 goto err_3;
2924 #ifdef USE_DMAC
2925 if (!request_region(host->dma.io_port, 256, "acornscsi(dmac)"))
2926 goto err_4;
2927 #endif
2928 if (!request_region(instance->io_port, 2048, "acornscsi(ram)"))
2929 goto err_5;
2930
2931 if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) {
2932 printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n",
2933 instance->host_no, host->scsi.irq);
2934 host->scsi.irq = NO_IRQ;
2935 }
2936
2937 acornscsi_host_init(host);
2938
2939 ++count;
2940 }
2941 return count;
2942
2943 err_5:
2944 #ifdef USE_DMAC
2945 release_region(host->dma.io_port, 256);
2946 #endif
2947 err_4:
2948 release_region(host->card.io_page, 1);
2949 err_3:
2950 release_region(host->card.io_intr, 1);
2951 err_2:
2952 release_region(instance->io_port + 0x800, 2);
2953 err_1:
2954 scsi_unregister(instance);
2955 return 0;
2956 }
2957
2958 /*
2959 * Function: int acornscsi_release(struct Scsi_Host *host)
2960 * Purpose : release all resources used by this adapter
2961 * Params : host - driver structure to release
2962 * Returns : nothing of any consequence
2963 */
acornscsi_release(struct Scsi_Host * instance)2964 int acornscsi_release(struct Scsi_Host *instance)
2965 {
2966 AS_Host *host = (AS_Host *)instance->hostdata;
2967 int i;
2968
2969 /*
2970 * Put card into RESET state
2971 */
2972 outb(0x80, host->card.io_page);
2973
2974 if (host->scsi.irq != NO_IRQ)
2975 free_irq(host->scsi.irq, host);
2976
2977 release_region(instance->io_port + 0x800, 2);
2978 release_region(host->card.io_intr, 1);
2979 release_region(host->card.io_page, 1);
2980 release_region(host->dma.io_port, 256);
2981 release_region(instance->io_port, 2048);
2982
2983 for (i = 0; i < MAX_ECARDS; i++)
2984 if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0))
2985 ecard_release(ecs[i]);
2986
2987 msgqueue_free(&host->scsi.msgs);
2988 queue_free(&host->queues.disconnected);
2989 queue_free(&host->queues.issue);
2990
2991 return 0;
2992 }
2993
2994 /*
2995 * Function: char *acornscsi_info(struct Scsi_Host *host)
2996 * Purpose : return a string describing this interface
2997 * Params : host - host to give information on
2998 * Returns : a constant string
2999 */
3000 const
acornscsi_info(struct Scsi_Host * host)3001 char *acornscsi_info(struct Scsi_Host *host)
3002 {
3003 static char string[100], *p;
3004
3005 p = string;
3006
3007 p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d"
3008 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
3009 " SYNC"
3010 #endif
3011 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
3012 " TAG"
3013 #endif
3014 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
3015 " LINK"
3016 #endif
3017 #if (DEBUG & DEBUG_NO_WRITE)
3018 " NOWRITE ("NO_WRITE_STR")"
3019 #endif
3020 , host->hostt->name, host->io_port, host->irq,
3021 VER_MAJOR, VER_MINOR, VER_PATCH);
3022 return string;
3023 }
3024
acornscsi_proc_info(char * buffer,char ** start,off_t offset,int length,int host_no,int inout)3025 int acornscsi_proc_info(char *buffer, char **start, off_t offset,
3026 int length, int host_no, int inout)
3027 {
3028 int pos, begin = 0, devidx;
3029 struct Scsi_Host *instance = scsi_hostlist;
3030 Scsi_Device *scd;
3031 AS_Host *host;
3032 char *p = buffer;
3033
3034 for (instance = scsi_hostlist;
3035 instance && instance->host_no != host_no;
3036 instance = instance->next);
3037
3038 if (inout == 1 || !instance)
3039 return -EINVAL;
3040
3041 host = (AS_Host *)instance->hostdata;
3042
3043 p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
3044 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
3045 " SYNC"
3046 #endif
3047 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
3048 " TAG"
3049 #endif
3050 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
3051 " LINK"
3052 #endif
3053 #if (DEBUG & DEBUG_NO_WRITE)
3054 " NOWRITE ("NO_WRITE_STR")"
3055 #endif
3056 "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
3057
3058 p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n",
3059 host->scsi.io_port, host->scsi.irq);
3060 #ifdef USE_DMAC
3061 p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n",
3062 host->dma.io_port, host->scsi.irq);
3063 #endif
3064
3065 p += sprintf(p, "Statistics:\n"
3066 "Queued commands: %-10u Issued commands: %-10u\n"
3067 "Done commands : %-10u Reads : %-10u\n"
3068 "Writes : %-10u Others : %-10u\n"
3069 "Disconnects : %-10u Aborts : %-10u\n"
3070 "Resets : %-10u\n\nLast phases:",
3071 host->stats.queues, host->stats.removes,
3072 host->stats.fins, host->stats.reads,
3073 host->stats.writes, host->stats.miscs,
3074 host->stats.disconnects, host->stats.aborts,
3075 host->stats.resets);
3076
3077 for (devidx = 0; devidx < 9; devidx ++) {
3078 unsigned int statptr, prev;
3079
3080 p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
3081 statptr = host->status_ptr[devidx] - 10;
3082
3083 if ((signed int)statptr < 0)
3084 statptr += STATUS_BUFFER_SIZE;
3085
3086 prev = host->status[devidx][statptr].when;
3087
3088 for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
3089 if (host->status[devidx][statptr].when) {
3090 p += sprintf(p, "%c%02X:%02X+%2ld",
3091 host->status[devidx][statptr].irq ? '-' : ' ',
3092 host->status[devidx][statptr].ph,
3093 host->status[devidx][statptr].ssr,
3094 (host->status[devidx][statptr].when - prev) < 100 ?
3095 (host->status[devidx][statptr].when - prev) : 99);
3096 prev = host->status[devidx][statptr].when;
3097 }
3098 }
3099 }
3100
3101 p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
3102
3103 for (scd = instance->host_queue; scd; scd = scd->next) {
3104 int len;
3105
3106 proc_print_scsidevice(scd, p, &len, 0);
3107 p += len;
3108
3109 p += sprintf(p, "Extensions: ");
3110
3111 if (scd->tagged_supported)
3112 p += sprintf(p, "TAG %sabled [%d] ",
3113 scd->tagged_queue ? "en" : "dis", scd->current_tag);
3114 p += sprintf(p, "\nTransfers: ");
3115 if (host->device[scd->id].sync_xfer & 15)
3116 p += sprintf(p, "sync, offset %d, %d ns\n",
3117 host->device[scd->id].sync_xfer & 15,
3118 acornscsi_getperiod(host->device[scd->id].sync_xfer));
3119 else
3120 p += sprintf(p, "async\n");
3121
3122 pos = p - buffer;
3123 if (pos + begin < offset) {
3124 begin += pos;
3125 p = buffer;
3126 }
3127 pos = p - buffer;
3128 if (pos + begin > offset + length)
3129 break;
3130 }
3131
3132 pos = p - buffer;
3133
3134 *start = buffer + (offset - begin);
3135 pos -= offset - begin;
3136
3137 if (pos > length)
3138 pos = length;
3139
3140 return pos;
3141 }
3142
3143 static Scsi_Host_Template acornscsi_template = {
3144 module: THIS_MODULE,
3145 proc_info: acornscsi_proc_info,
3146 name: "AcornSCSI",
3147 detect: acornscsi_detect,
3148 release: acornscsi_release,
3149 info: acornscsi_info,
3150 queuecommand: acornscsi_queuecmd,
3151 abort: acornscsi_abort,
3152 reset: acornscsi_reset,
3153 bios_param: scsicam_bios_param,
3154 can_queue: 16,
3155 this_id: 7,
3156 sg_tablesize: SG_ALL,
3157 cmd_per_lun: 2,
3158 unchecked_isa_dma: 0,
3159 use_clustering: DISABLE_CLUSTERING
3160 };
3161
acornscsi_init(void)3162 static int __init acornscsi_init(void)
3163 {
3164 acornscsi_template.module = THIS_MODULE;
3165 scsi_register_module(MODULE_SCSI_HA, &acornscsi_template);
3166 if (acornscsi_template.present)
3167 return 0;
3168
3169 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
3170 return -ENODEV;
3171 }
3172
acornscsi_exit(void)3173 static void __exit acornscsi_exit(void)
3174 {
3175 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
3176 }
3177
3178 module_init(acornscsi_init);
3179 module_exit(acornscsi_exit);
3180
3181 MODULE_AUTHOR("Russell King");
3182 MODULE_DESCRIPTION("AcornSCSI driver");
3183 MODULE_LICENSE("GPL");
3184 EXPORT_NO_SYMBOLS;
3185