2 * linux/drivers/acorn/scsi/acornscsi.c
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.
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...
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.
31 #define DEBUG_NO_WRITE 1
32 #define DEBUG_QUEUES 2
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)
46 /* DRIVER CONFIGURATION
48 * SCSI-II Tagged queue support.
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???
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
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.
63 #undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
65 * SCSI-II Linked command support.
67 * The higher level code doesn't support linked commands yet, and so the option
70 #undef CONFIG_SCSI_ACORNSCSI_LINK
72 * SCSI-II Synchronous transfer support.
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.
81 #define SDTR_PERIOD 125
82 #define DEFAULT_PERIOD 500
85 * Debugging information
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].
91 #define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE)
92 /* only allow writing to SCSI device 0 */
94 /*#define DEBUG_TARGET 2*/
96 * Select timeout time (in 10ms units)
98 * This is the timeout used between the start of selection and the WD33C93
99 * chip deciding that the device isn't responding.
101 #define TIMEOUT_TIME 10
103 * Define this if you want to have verbose explaination of SCSI
106 #undef CONFIG_ACORNSCSI_CONSTANTS
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).
113 * List of devices that the driver will recognise
115 #define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI }
117 * ====================================================================================
121 #define DBG(cmd,xxx...) \
122 if (cmd->target == DEBUG_TARGET) { \
126 #define DBG(cmd,xxx...) xxx
130 #define STRINGIFY(x) #x
132 #define STRx(x) STRINGIFY(x)
133 #define NO_WRITE_STR STRx(NO_WRITE)
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>
149 #include <asm/bitops.h>
150 #include <asm/system.h>
153 #include <asm/ecard.h>
155 #include "../../scsi/scsi.h"
156 #include "../../scsi/hosts.h"
157 #include "../../scsi/constants.h"
158 #include "acornscsi.h"
159 #include "msgqueue.h"
161 #include <scsi/scsicam.h>
168 #define ABORT_TAG 0xd
170 #error "Yippee! ABORT TAG is now defined! Remove this error!"
173 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
174 #error SCSI2 LINKed commands not supported (yet)!
179 * DMAC setup parameters
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)
187 #define scsi_xferred have_data_in
190 * Size of on-board DMA buffer
192 #define DMAC_BUFFER_SIZE 65536
195 #define STATUS_BUFFER_TO_PRINT 24
197 unsigned int sdtr_period = SDTR_PERIOD;
198 unsigned int sdtr_size = SDTR_SIZE;
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);
205 /* ====================================================================================
210 sbic_arm_write(unsigned int io_port, int reg, int value)
212 __raw_writeb(reg, io_port);
213 __raw_writeb(value, io_port + 4);
216 #define sbic_arm_writenext(io,val) \
217 __raw_writeb((val), (io) + 4)
220 int sbic_arm_read(unsigned int io_port, int reg)
223 return __raw_readl(io_port) & 255;
224 __raw_writeb(reg, io_port);
225 return __raw_readl(io_port + 4) & 255;
228 #define sbic_arm_readnext(io) \
229 __raw_readb((io) + 4)
232 #define dmac_read(io_port,reg) \
233 inb((io_port) + (reg))
235 #define dmac_write(io_port,reg,value) \
236 ({ outb((value), (io_port) + (reg)); })
238 #define dmac_clearintr(io_port) \
239 ({ outb(0, (io_port)); })
242 unsigned int dmac_address(unsigned int io_port)
244 return dmac_read(io_port, TXADRHI) << 16 |
245 dmac_read(io_port, TXADRMD) << 8 |
246 dmac_read(io_port, TXADRLO);
250 void acornscsi_dumpdma(AS_Host *host, char *where)
252 unsigned int mode, addr, len;
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);
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));
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);
274 unsigned long acornscsi_sbic_xfcount(AS_Host *host)
276 unsigned long length;
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);
286 acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
291 asr = sbic_arm_read(host->scsi.io_port, ASR);
293 if ((asr & stat_mask) == stat)
299 printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
305 int acornscsi_sbic_issuecmd(AS_Host *host, int command)
307 if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
310 sbic_arm_write(host->scsi.io_port, CMND, command);
316 acornscsi_csdelay(unsigned int cs)
318 unsigned long target_jiffies, flags;
320 target_jiffies = jiffies + 1 + cs * HZ / 100;
325 while (time_before(jiffies, target_jiffies)) barrier();
327 restore_flags(flags);
331 void acornscsi_resetcard(AS_Host *host)
333 unsigned int i, timeout;
335 /* assert reset line */
336 host->card.page_reg = 0x80;
337 outb(host->card.page_reg, host->card.io_page);
339 /* wait 3 cs. SCSI standard says 25ms. */
340 acornscsi_csdelay(3);
342 host->card.page_reg = 0;
343 outb(host->card.page_reg, host->card.io_page);
346 * Should get a reset from the card
350 if (inb(host->card.io_intr) & 8)
356 printk("scsi%d: timeout while resetting card\n",
357 host->host->host_no);
359 sbic_arm_read(host->scsi.io_port, ASR);
360 sbic_arm_read(host->scsi.io_port, SSR);
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);
367 * Command should cause a reset interrupt
371 if (inb(host->card.io_intr) & 8)
377 printk("scsi%d: timeout while resetting card\n",
378 host->host->host_no);
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);
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);
390 host->card.page_reg = 0x40;
391 outb(host->card.page_reg, host->card.io_page);
393 /* setup dmac - uPC71071 */
394 dmac_write(host->dma.io_port, INIT, 0);
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);
403 host->scsi.phase = PHASE_IDLE;
404 host->scsi.disconnectable = 0;
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;
412 /* wait 25 cs. SCSI standard says 250ms. */
413 acornscsi_csdelay(25);
416 /*=============================================================================================
417 * Utility routines (eg. debug)
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",
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
446 static char *acornscsi_interruptcode[] = {
448 "reset - normal mode", /* 00 */
449 "reset - advanced mode", /* 01 */
464 "/ACK asserted", /* 20 */
465 "save-data-ptr", /* 21 */
470 "unexpected disconnect", /* 41 */
471 "sel timeout", /* 42 */
473 "P err+ATN", /* 44 */
474 "bad status byte", /* 47 */
477 "resel, no id", /* 80 */
483 void print_scsi_status(unsigned int ssr)
485 if (acornscsi_map[ssr] != -1)
487 acornscsi_interrupttype[(ssr >> 4)],
488 acornscsi_interruptcode[acornscsi_map[ssr]]);
490 printk("%X:%X", ssr >> 4, ssr & 0x0f);
495 void print_sbic_status(int asr, int ssr, int cmdphase)
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');
506 print_scsi_status(ssr);
507 printk(" ph %02X\n", cmdphase);
509 printk("sbic: %02X scsi: %X:%X ph: %02X\n",
510 asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);
515 acornscsi_dumplogline(AS_Host *host, int target, int line)
520 ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT;
522 ptr += STATUS_BUFFER_SIZE;
524 printk("%c: %3s:", target == 8 ? 'H' : '0' + target,
525 line == 0 ? "ph" : line == 1 ? "ssr" : "int");
527 prev = host->status[target][ptr].when;
529 for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
530 unsigned long time_diff;
532 if (!host->status[target][ptr].when)
537 printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ',
538 host->status[target][ptr].ph);
542 printk(" %02X", host->status[target][ptr].ssr);
546 time_diff = host->status[target][ptr].when - prev;
547 prev = host->status[target][ptr].when;
550 else if (time_diff >= 100)
553 printk(" %02ld", time_diff);
562 void acornscsi_dumplog(AS_Host *host, int target)
565 acornscsi_dumplogline(host, target, 0);
566 acornscsi_dumplogline(host, target, 1);
567 acornscsi_dumplogline(host, target, 2);
577 char acornscsi_target(AS_Host *host)
580 return '0' + host->SCpnt->target;
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
593 cmdtype_t acornscsi_cmdtype(int command)
596 case WRITE_6: case WRITE_10: case WRITE_12:
598 case READ_6: case READ_10: case READ_12:
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
614 datadir_t acornscsi_datadirection(int 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:
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
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 }
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.
654 int acornscsi_getperiod(unsigned char syncxfer)
659 if (syncxfer == 0x10)
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;
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
676 int round_period(unsigned int period)
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))
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
697 unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
699 return sync_xfer_table[round_period(period)].reg_value |
700 ((offset < SDTR_SIZE) ? offset : SDTR_SIZE);
703 /* ====================================================================================
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!
714 intr_ret_t acornscsi_kick(AS_Host *host)
719 /* first check to see if a command is waiting to be executed */
720 SCpnt = host->origSCpnt;
721 host->origSCpnt = NULL;
723 /* retrieve next command */
725 SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns);
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)));
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
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);
752 * claim host busy - all of these must happen atomically wrt
753 * our interrupt routine. Failure means command loss.
755 host->scsi.phase = PHASE_CONNECTING;
757 host->scsi.SCp = SCpnt->SCp;
758 host->dma.xfer_setup = 0;
759 host->dma.xfer_required = 0;
760 host->dma.xfer_done = 0;
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,
769 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
771 * tagged queueing - allocate a new tag to this command
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;
780 set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
782 host->stats.removes += 1;
784 switch (acornscsi_cmdtype(SCpnt->cmnd[0])) {
786 host->stats.writes += 1;
789 host->stats.reads += 1;
792 host->stats.miscs += 1;
797 return INTR_PROCESSING;
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
807 void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
809 Scsi_Cmnd *SCpnt = *SCpntp;
812 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
814 host->stats.fins += 1;
819 acornscsi_dma_cleanup(host);
821 SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status;
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.
831 if (result == DID_OK) {
834 if (SCpnt->underflow == 0) {
835 if (host->scsi.SCp.ptr &&
836 acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC)
839 if (host->scsi.SCp.scsi_xferred < SCpnt->underflow ||
840 host->scsi.SCp.scsi_xferred != host->dma.transferred)
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.
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
856 if (host->dma.xfer_done)
860 switch (status_byte(SCpnt->result)) {
861 case CHECK_CONDITION:
862 case COMMAND_TERMINATED:
865 case RESERVATION_CONFLICT:
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;
880 if (!SCpnt->scsi_done)
881 panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
883 clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
885 SCpnt->scsi_done(SCpnt);
887 printk("scsi%d: null command in acornscsi_done", host->host->host_no);
889 host->scsi.phase = PHASE_IDLE;
892 /* ====================================================================================
896 * Purpose : update SCSI Data Pointer
897 * Notes : this will only be one SG entry or less
900 void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
903 SCp->this_residual -= length;
905 if (!SCp->this_residual) {
906 if (SCp->buffers_residual) {
908 SCp->buffers_residual--;
909 SCp->ptr = (char *)SCp->buffer->address;
910 SCp->this_residual = SCp->buffer->length;
913 host->dma.xfer_done = 1;
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
924 * start_addr - host mem address
925 * length - number of bytes to transfer
926 * Notes : this will only be one SG entry or less
929 void acornscsi_data_read(AS_Host *host, char *ptr,
930 unsigned int start_addr, unsigned int length)
932 extern void __acornscsi_in(int port, char *buf, int len);
933 unsigned int page, offset, len = length;
935 page = (start_addr >> 12);
936 offset = start_addr & ((1 << 12) - 1);
938 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
941 unsigned int this_len;
943 if (len + offset > (1 << 12))
944 this_len = (1 << 12) - offset;
948 __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
954 if (offset == (1 << 12)) {
957 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
960 outb(host->card.page_reg, host->card.io_page);
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
969 * start_addr - host mem address
970 * length - number of bytes to transfer
971 * Notes : this will only be one SG entry or less
974 void acornscsi_data_write(AS_Host *host, char *ptr,
975 unsigned int start_addr, unsigned int length)
977 extern void __acornscsi_out(int port, char *buf, int len);
978 unsigned int page, offset, len = length;
980 page = (start_addr >> 12);
981 offset = start_addr & ((1 << 12) - 1);
983 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
986 unsigned int this_len;
988 if (len + offset > (1 << 12))
989 this_len = (1 << 12) - offset;
993 __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
999 if (offset == (1 << 12)) {
1002 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
1005 outb(host->card.page_reg, host->card.io_page);
1008 /* =========================================================================================
1009 * On-board DMA routines
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
1020 void acornscsi_dma_stop(AS_Host *host)
1022 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1023 dmac_clearintr(host->dma.io_intr_clear);
1025 #if (DEBUG & DEBUG_DMA)
1026 DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
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
1039 void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1041 unsigned int address, length, mode;
1043 host->dma.direction = direction;
1045 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
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));
1060 * Allocate some buffer space, limited to half the buffer size
1062 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
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);
1069 * Transfer data to DMA memory
1071 if (direction == DMA_OUT)
1072 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
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);
1084 #if (DEBUG & DEBUG_DMA)
1085 DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
1087 host->dma.xfer_setup = 1;
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.
1100 void acornscsi_dma_cleanup(AS_Host *host)
1102 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1103 dmac_clearintr(host->dma.io_intr_clear);
1106 * Check for a pending transfer
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);
1116 * Has a transfer been setup?
1118 if (host->dma.xfer_setup) {
1119 unsigned int transferred;
1121 host->dma.xfer_setup = 0;
1123 #if (DEBUG & DEBUG_DMA)
1124 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
1128 * Calculate number of bytes transferred from DMA.
1130 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1131 host->dma.transferred += transferred;
1133 if (host->dma.direction == DMA_IN)
1134 acornscsi_data_read(host, host->scsi.SCp.ptr,
1135 host->dma.start_addr, transferred);
1138 * Update SCSI pointers
1140 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1141 #if (DEBUG & DEBUG_DMA)
1142 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
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
1155 * : Called whenever DMAC finished it's current transfer.
1158 void acornscsi_dma_intr(AS_Host *host)
1160 unsigned int address, length, transferred;
1162 #if (DEBUG & DEBUG_DMA)
1163 DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
1166 dmac_write(host->dma.io_port, MASKREG, MASK_ON);
1167 dmac_clearintr(host->dma.io_intr_clear);
1170 * Calculate amount transferred via DMA
1172 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1173 host->dma.transferred += transferred;
1176 * Schedule DMA transfer off board
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;
1185 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1188 * Allocate some buffer space, limited to half the on-board RAM size
1190 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
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);
1197 * Transfer data to DMA memory
1199 if (host->dma.direction == DMA_OUT)
1200 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
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);
1211 #if (DEBUG & DEBUG_DMA)
1212 DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
1215 host->dma.xfer_setup = 0;
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.
1223 if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) {
1224 acornscsi_abortcmd(host, host->SCpnt->tag);
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);
1238 * Function: void acornscsi_dma_xfer(AS_Host *host)
1239 * Purpose : transfer data between AcornSCSI and memory
1240 * Params : host - host to process
1243 void acornscsi_dma_xfer(AS_Host *host)
1245 host->dma.xfer_required = 0;
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);
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
1259 void acornscsi_dma_adjust(AS_Host *host)
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"));
1267 * Calculate correct DMA address - DMA is ahead of SCSI bus while
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.
1274 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
1275 * - host->dma.transferred
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;
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"));
1296 /* =========================================================================================
1300 acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
1302 unsigned int asr, timeout = max_timeout;
1305 while (my_ptr < len) {
1306 asr = sbic_arm_read(host->scsi.io_port, ASR);
1308 if (asr & ASR_DBR) {
1309 timeout = max_timeout;
1311 sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]);
1312 } else if (asr & ASR_INT)
1314 else if (--timeout == 0)
1321 return (timeout == 0) ? -1 : 0;
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
1330 acornscsi_sendcommand(AS_Host *host)
1332 Scsi_Cmnd *SCpnt = host->SCpnt;
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);
1338 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
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);
1344 host->scsi.phase = PHASE_COMMAND;
1348 void acornscsi_sendmessage(AS_Host *host)
1350 unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
1352 struct message *msg;
1354 #if (DEBUG & DEBUG_MESSAGES)
1355 printk("scsi%d.%c: sending message ",
1356 host->host->host_no, acornscsi_target(host));
1359 switch (message_length) {
1361 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1363 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
1365 sbic_arm_write(host->scsi.io_port, DATA, NOP);
1367 host->scsi.last_message = NOP;
1368 #if (DEBUG & DEBUG_MESSAGES)
1374 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1375 msg = msgqueue_getmsg(&host->scsi.msgs, 0);
1377 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
1379 sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]);
1381 host->scsi.last_message = msg->msg[0];
1382 #if (DEBUG & DEBUG_MESSAGES)
1383 print_msg(msg->msg);
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.
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);
1402 while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
1404 #if (DEBUG & DEBUG_MESSAGES)
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);
1411 host->scsi.last_message = msg->msg[0];
1412 if (msg->msg[0] == EXTENDED_MESSAGE)
1413 host->scsi.last_message |= msg->msg[2] << 8;
1415 if (i != msg->length)
1420 #if (DEBUG & DEBUG_MESSAGES)
1426 * Function: void acornscsi_readstatusbyte(AS_Host *host)
1427 * Purpose : Read status byte from connected target
1428 * Params : host - host connected to target
1431 void acornscsi_readstatusbyte(AS_Host *host)
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);
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
1444 unsigned char acornscsi_readmessagebyte(AS_Host *host)
1446 unsigned char message;
1448 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1450 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
1452 message = sbic_arm_read(host->scsi.io_port, DATA);
1454 /* wait for MSGIN-XFER-PAUSED */
1455 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
1457 sbic_arm_read(host->scsi.io_port, SSR);
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
1468 void acornscsi_message(AS_Host *host)
1470 unsigned char message[16];
1471 unsigned int msgidx = 0, msglen = 1;
1474 message[msgidx] = acornscsi_readmessagebyte(host);
1478 if (message[0] == EXTENDED_MESSAGE ||
1479 (message[0] >= 0x20 && message[0] <= 0x2f))
1484 if (message[0] == EXTENDED_MESSAGE)
1485 msglen += message[msgidx];
1489 if (msgidx < msglen) {
1490 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
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);
1496 } while (msgidx < msglen);
1498 #if (DEBUG & DEBUG_MESSAGES)
1499 printk("scsi%d.%c: message in: ",
1500 host->host->host_no, acornscsi_target(host));
1505 if (host->scsi.phase == PHASE_RECONNECTED) {
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...'
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;
1518 switch (message[0]) {
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);
1527 host->scsi.phase = PHASE_DONE;
1528 host->scsi.SCp.Message = message[0];
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.
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;
1544 case RESTORE_POINTERS:
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.'
1554 acornscsi_dma_cleanup(host);
1555 host->scsi.SCp = host->SCpnt->SCp;
1556 host->scsi.phase = PHASE_MSGIN;
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.'
1569 acornscsi_dma_cleanup(host);
1570 host->scsi.phase = PHASE_DISCONNECT;
1573 case MESSAGE_REJECT:
1574 #if 0 /* this isn't needed any more */
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.
1581 if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST)
1582 host->device[host->SCpnt->target].sync_state = SYNC_NEGOCIATE;
1586 * If we have any messages waiting to go out, then assert ATN now
1588 if (msgqueue_msglength(&host->scsi.msgs))
1589 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
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:
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.
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);
1608 case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
1610 * Target can't handle synchronous transfers
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);
1625 /* TODO: target queue is full */
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),
1635 case EXTENDED_MESSAGE:
1636 switch (message[2]) {
1637 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1639 if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) {
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
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]);
1653 unsigned char period, length;
1655 * Target requested synchronous transfers. The agreement is only
1656 * to be in operation AFTER the target leaves message out phase.
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);
1666 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
1669 /* We do not accept synchronous transfers. Respond with a
1675 /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT
1676 * to a wide data transfer request.
1679 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1680 msgqueue_flush(&host->scsi.msgs);
1681 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1686 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
1687 case LINKED_CMD_COMPLETE:
1688 case LINKED_FLG_CMD_COMPLETE:
1690 * We don't support linked commands yet
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);
1698 * A linked command should only terminate with one of these messages
1699 * if there are more linked commands available.
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);
1707 Scsi_Cmnd *SCpnt = host->SCpnt;
1709 acornscsi_dma_cleanup(host);
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;
1716 /* initialise host->SCpnt->SCp */
1722 default: /* reject message */
1723 printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
1724 host->host->host_no, acornscsi_target(host),
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;
1732 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
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
1741 void acornscsi_buildmessages(AS_Host *host)
1744 /* does the device need resetting? */
1746 msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
1751 msgqueue_addmsg(&host->scsi.msgs, 1,
1752 IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,
1756 /* does the device need the current command aborted */
1758 acornscsi_abortcmd(host->SCpnt->tag);
1763 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1764 if (host->SCpnt->tag) {
1765 unsigned int tag_type;
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;
1772 tag_type = SIMPLE_QUEUE_TAG;
1773 msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
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);
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
1794 int acornscsi_starttransfer(AS_Host *host)
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));
1804 residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
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);
1814 /* =========================================================================================
1815 * Connection & Disconnection
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'
1826 int acornscsi_reconnect(AS_Host *host)
1828 unsigned int target, lun, ok = 0;
1830 target = sbic_arm_read(host->scsi.io_port, SOURCEID);
1833 printk(KERN_ERR "scsi%d: invalid source id after reselection "
1834 "- device fault?\n",
1835 host->host->host_no);
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);
1846 lun = sbic_arm_read(host->scsi.io_port, DATA) & 7;
1848 host->scsi.reconnected.target = target;
1849 host->scsi.reconnected.lun = lun;
1850 host->scsi.reconnected.tag = 0;
1852 if (host->scsi.disconnectable && host->SCpnt &&
1853 host->SCpnt->target == target && host->SCpnt->lun == lun)
1856 if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
1859 ADD_STATUS(target, 0x81, host->scsi.phase, 0);
1862 host->scsi.phase = PHASE_RECONNECTED;
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);
1871 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1875 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
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
1886 int acornscsi_reconnect_finish(AS_Host *host)
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)));
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)));
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)));
1919 acornscsi_abortcmd(host, host->scsi.reconnected.tag);
1922 * Restore data pointer from SAVED pointers.
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);
1930 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1934 host->dma.transferred = host->scsi.SCp.scsi_xferred;
1936 return host->SCpnt != NULL;
1940 * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
1941 * Purpose : handle an unexpected disconnect
1942 * Params : host - host on which disconnect occurred
1945 void acornscsi_disconnect_unexpected(AS_Host *host)
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);
1953 acornscsi_done(host, &host->SCpnt, DID_ERROR);
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
1963 void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
1965 host->scsi.phase = PHASE_ABORTED;
1966 sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN);
1968 msgqueue_flush(&host->scsi.msgs);
1969 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1971 msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
1974 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1977 /* ==========================================================================================
1978 * Interrupt routines.
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
1989 intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
1991 unsigned int asr, ssr;
1993 asr = sbic_arm_read(host->scsi.io_port, ASR);
1994 if (!(asr & ASR_INT))
1997 ssr = sbic_arm_read(host->scsi.io_port, SSR);
1999 #if (DEBUG & DEBUG_PHASES)
2000 print_sbic_status(asr, ssr, host->scsi.phase);
2003 ADD_STATUS(8, ssr, host->scsi.phase, in_irq);
2005 if (host->SCpnt && !host->scsi.disconnectable)
2006 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
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);
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);
2025 case 0x41: /* unexpected disconnect aborted command */
2026 acornscsi_disconnect_unexpected(host);
2027 return INTR_NEXT_COMMAND;
2030 switch (host->scsi.phase) {
2031 case PHASE_CONNECTING: /* STATE: command removed from issue queue */
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))
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);
2047 case 0x42: /* select timed out */
2049 acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
2050 return INTR_NEXT_COMMAND;
2052 case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2053 /* BUS FREE -> RESELECTION */
2054 host->origSCpnt = host->SCpnt;
2056 msgqueue_flush(&host->scsi.msgs);
2057 acornscsi_reconnect(host);
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);
2066 return INTR_PROCESSING;
2069 case PHASE_CONNECTED: /* STATE: device selected ok */
2072 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2073 /* SELECTION -> COMMAND */
2074 acornscsi_sendcommand(host);
2077 case 0x8b: /* -> PHASE_STATUS */
2078 /* SELECTION -> STATUS */
2079 acornscsi_readstatusbyte(host);
2080 host->scsi.phase = PHASE_STATUSIN;
2084 case 0x8e: /* -> PHASE_MSGOUT */
2085 /* SELECTION ->MESSAGE OUT */
2086 host->scsi.phase = PHASE_MSGOUT;
2087 acornscsi_buildmessages(host);
2088 acornscsi_sendmessage(host);
2091 /* these should not happen */
2092 case 0x85: /* target disconnected */
2093 acornscsi_done(host, &host->SCpnt, DID_ERROR);
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);
2102 return INTR_PROCESSING;
2104 case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */
2106 * SCSI standard says that MESSAGE OUT phases can be followed by a
2107 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
2110 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2111 case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2112 /* MESSAGE OUT -> COMMAND */
2113 acornscsi_sendcommand(host);
2116 case 0x8b: /* -> PHASE_STATUS */
2117 case 0x1b: /* -> PHASE_STATUS */
2118 /* MESSAGE OUT -> STATUS */
2119 acornscsi_readstatusbyte(host);
2120 host->scsi.phase = PHASE_STATUSIN;
2123 case 0x8e: /* -> PHASE_MSGOUT */
2124 /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
2125 acornscsi_sendmessage(host);
2128 case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2129 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2130 /* MESSAGE OUT -> MESSAGE IN */
2131 acornscsi_message(host);
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);
2139 return INTR_PROCESSING;
2141 case PHASE_COMMAND: /* STATE: connected & command sent */
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;
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;
2163 case 0x1b: /* -> PHASE_STATUS */
2164 /* COMMAND -> STATUS */
2165 acornscsi_readstatusbyte(host);
2166 host->scsi.phase = PHASE_STATUSIN;
2169 case 0x1e: /* -> PHASE_MSGOUT */
2170 /* COMMAND -> MESSAGE OUT */
2171 acornscsi_sendmessage(host);
2174 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2175 /* COMMAND -> MESSAGE IN */
2176 acornscsi_message(host);
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);
2184 return INTR_PROCESSING;
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;
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);
2197 return INTR_NEXT_COMMAND;
2199 case PHASE_IDLE: /* STATE: disconnected */
2200 if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2201 acornscsi_reconnect(host);
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);
2207 return INTR_PROCESSING;
2209 case PHASE_RECONNECTED: /* STATE: device reconnected to initiator */
2211 * Command reconnected - if MESGIN, get message - it may be
2212 * the tag. If not, get command out of disconnected queue
2215 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
2216 * reconnect I_T_L command
2218 if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
2220 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
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;
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;
2240 case 0x8a: /* command out */
2241 /* MESSAGE IN -> COMMAND */
2242 acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2245 case 0x8b: /* status in */
2246 /* -> PHASE_STATUSIN */
2247 /* MESSAGE IN -> STATUS */
2248 acornscsi_readstatusbyte(host);
2249 host->scsi.phase = PHASE_STATUSIN;
2252 case 0x8e: /* message out */
2253 /* -> PHASE_MSGOUT */
2254 /* MESSAGE IN -> MESSAGE OUT */
2255 acornscsi_sendmessage(host);
2258 case 0x8f: /* message in */
2259 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
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);
2267 return INTR_PROCESSING;
2269 case PHASE_DATAIN: /* STATE: transferred data in */
2271 * This is simple - if we disconnect then the DMA address & count is
2275 case 0x19: /* -> PHASE_DATAIN */
2276 case 0x89: /* -> PHASE_DATAIN */
2277 acornscsi_abortcmd(host, host->SCpnt->tag);
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;
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);
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 */
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);
2316 return INTR_PROCESSING;
2318 case PHASE_DATAOUT: /* STATE: transferred data out */
2320 * This is more complicated - if we disconnect, the DMA could be 12
2321 * bytes ahead of us. We need to correct this.
2324 case 0x18: /* -> PHASE_DATAOUT */
2325 case 0x88: /* -> PHASE_DATAOUT */
2326 acornscsi_abortcmd(host, host->SCpnt->tag);
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;
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);
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 */
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);
2368 return INTR_PROCESSING;
2370 case PHASE_STATUSIN: /* STATE: status in complete */
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);
2378 case 0x1e: /* -> PHASE_MSGOUT */
2379 case 0x8e: /* -> PHASE_MSGOUT */
2380 /* STATUS -> MESSAGE OUT */
2381 acornscsi_sendmessage(host);
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);
2389 return INTR_PROCESSING;
2391 case PHASE_MSGIN: /* STATE: message in */
2393 case 0x1e: /* -> PHASE_MSGOUT */
2394 case 0x4e: /* -> PHASE_MSGOUT */
2395 case 0x8e: /* -> PHASE_MSGOUT */
2396 /* MESSAGE IN -> MESSAGE OUT */
2397 acornscsi_sendmessage(host);
2400 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2404 acornscsi_message(host);
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);
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);
2419 return INTR_PROCESSING;
2421 case PHASE_DONE: /* STATE: received status & message */
2423 case 0x85: /* -> PHASE_IDLE */
2424 acornscsi_done(host, &host->SCpnt, DID_OK);
2425 return INTR_NEXT_COMMAND;
2429 acornscsi_sendmessage(host);
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);
2437 return INTR_PROCESSING;
2443 acornscsi_done(host, &host->SCpnt, DID_ABORT);
2445 clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
2447 host->scsi.phase = PHASE_IDLE;
2449 return INTR_NEXT_COMMAND;
2455 acornscsi_sendmessage(host);
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);
2463 return INTR_PROCESSING;
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);
2470 return INTR_PROCESSING;
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
2481 void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
2483 AS_Host *host = (AS_Host *)dev_id;
2488 if (host->scsi.interrupt)
2489 printk("scsi%d: interrupt re-entered\n", host->host->host_no);
2490 host->scsi.interrupt = 1;
2495 iostatus = inb(host->card.io_intr);
2498 acornscsi_dma_intr(host);
2499 iostatus = inb(host->card.io_intr);
2503 ret = acornscsi_sbicintr(host, in_irq);
2506 * If we have a transfer pending, start it.
2507 * Only start it if the interface has already started transferring
2510 if (host->dma.xfer_required)
2511 acornscsi_dma_xfer(host);
2513 if (ret == INTR_NEXT_COMMAND)
2514 ret = acornscsi_kick(host);
2517 } while (ret != INTR_IDLE);
2519 host->scsi.interrupt = 0;
2522 /*=============================================================================================
2523 * Interfaces between interrupt handler and rest of scsi code
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.
2533 int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2535 AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
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);
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;
2554 SCpnt->scsi_done = done;
2555 SCpnt->host_scribble = NULL;
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;
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;
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;
2576 host->stats.queues += 1;
2579 unsigned long flags;
2581 if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
2582 SCpnt->result = DID_ERROR << 16;
2586 save_flags_cli(flags);
2587 if (host->scsi.phase == PHASE_IDLE)
2588 acornscsi_kick(host);
2589 restore_flags(flags);
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.
2603 void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
2605 Scsi_Cmnd *SCpnt = *SCpntp1;
2610 SCpnt->result = result;
2611 SCpnt->scsi_done(SCpnt);
2614 if (SCpnt == *SCpntp2)
2618 enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
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
2626 static enum res_abort
2627 acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
2629 enum res_abort res = res_not_running;
2631 if (queue_remove_cmd(&host->queues.issue, SCpnt)) {
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.
2638 //#if (DEBUG & DEBUG_ABORT)
2639 printk("on issue queue ");
2642 } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) {
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
2650 //#if (DEBUG & DEBUG_ABORT)
2651 printk("on disconnected queue ");
2654 } else if (host->SCpnt == SCpnt) {
2655 unsigned long flags;
2657 //#if (DEBUG & DEBUG_ABORT)
2658 printk("executing ");
2663 switch (host->scsi.phase) {
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
2673 if (host->scsi.disconnectable) {
2674 host->scsi.disconnectable = 0;
2681 * If the command has connected and done nothing further,
2682 * simply force a disconnect. We also need to clear the
2685 case PHASE_CONNECTED:
2686 sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT);
2688 res = res_success_clear;
2692 acornscsi_abortcmd(host, host->SCpnt->tag);
2695 restore_flags(flags);
2696 } else if (host->origSCpnt == SCpnt) {
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
2703 host->origSCpnt = NULL;
2704 //#if (DEBUG & DEBUG_ABORT)
2705 printk("waiting for execution ");
2707 res = res_success_clear;
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
2720 int acornscsi_abort(Scsi_Cmnd *SCpnt)
2722 AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
2725 host->stats.aborts += 1;
2727 #if (DEBUG & DEBUG_ABORT)
2730 asr = sbic_arm_read(host->scsi.io_port, ASR);
2731 ssr = sbic_arm_read(host->scsi.io_port, SSR);
2733 printk(KERN_WARNING "acornscsi_abort: ");
2734 print_sbic_status(asr, ssr, host->scsi.phase);
2735 acornscsi_dumplog(host, SCpnt->target);
2739 printk("scsi%d: ", host->host->host_no);
2741 switch (acornscsi_do_abort(host, SCpnt)) {
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.
2747 case res_success_clear:
2748 //#if (DEBUG & DEBUG_ABORT)
2751 clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
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.
2759 //#if (DEBUG & DEBUG_ABORT)
2760 printk("success\n");
2762 SCpnt->result = DID_ABORT << 16;
2763 SCpnt->scsi_done(SCpnt);
2764 result = SCSI_ABORT_SUCCESS;
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.
2773 //#if (DEBUG & DEBUG_ABORT)
2776 result = SCSI_ABORT_SNOOZE;
2780 * The command could not be found (either because it completed,
2781 * or it got dropped.
2784 case res_not_running:
2785 acornscsi_dumplog(host, SCpnt->target);
2786 #if (DEBUG & DEBUG_ABORT)
2787 result = SCSI_ABORT_SNOOZE;
2789 result = SCSI_ABORT_NOT_RUNNING;
2791 //#if (DEBUG & DEBUG_ABORT)
2792 printk("not running\n");
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
2807 int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2809 AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
2812 host->stats.resets += 1;
2814 #if (DEBUG & DEBUG_RESET)
2818 asr = sbic_arm_read(host->scsi.io_port, ASR);
2819 ssr = sbic_arm_read(host->scsi.io_port, SSR);
2821 printk(KERN_WARNING "acornscsi_reset: ");
2822 print_sbic_status(asr, ssr, host->scsi.phase);
2823 acornscsi_dumplog(host, SCpnt->target);
2827 acornscsi_dma_stop(host);
2829 SCptr = host->SCpnt;
2832 * do hard reset. This resets all devices on this host, and so we
2833 * must set the reset status on all commands.
2835 acornscsi_resetcard(host);
2838 * report reset on commands current connected/disconnected
2840 acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET);
2842 while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
2843 acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET);
2846 SCpnt->result = DID_RESET << 16;
2847 SCpnt->scsi_done(SCpnt);
2850 return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
2853 /*==============================================================================================
2854 * initialisation & miscellaneous support
2856 static struct expansion_card *ecs[MAX_ECARDS];
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
2864 void acornscsi_host_init(AS_Host *host)
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);
2871 acornscsi_resetcard(host);
2874 int acornscsi_detect(Scsi_Host_Template * tpnt)
2876 static const card_ids acornscsi_cids[] = { ACORNSCSI_LIST, { 0xffff, 0xffff } };
2878 struct Scsi_Host *instance;
2881 tpnt->proc_name = "acornscsi";
2883 for (i = 0; i < MAX_ECARDS; i++)
2889 ecs[count] = ecard_find(0, acornscsi_cids);
2893 if (ecs[count]->irq == 0xff) {
2894 printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
2898 ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */
2900 instance = scsi_register(tpnt, sizeof(AS_Host));
2901 host = (AS_Host *)instance->hostdata;
2903 instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
2904 instance->irq = ecs[count]->irq;
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;
2915 ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr);
2916 ecs[count]->irqmask = 0x0a;
2918 if (!request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)"))
2920 if (!request_region(host->card.io_intr, 1, "acornscsi(intr)"))
2922 if (!request_region(host->card.io_page, 1, "acornscsi(page)"))
2925 if (!request_region(host->dma.io_port, 256, "acornscsi(dmac)"))
2928 if (!request_region(instance->io_port, 2048, "acornscsi(ram)"))
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;
2937 acornscsi_host_init(host);
2945 release_region(host->dma.io_port, 256);
2948 release_region(host->card.io_page, 1);
2950 release_region(host->card.io_intr, 1);
2952 release_region(instance->io_port + 0x800, 2);
2954 scsi_unregister(instance);
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
2964 int acornscsi_release(struct Scsi_Host *instance)
2966 AS_Host *host = (AS_Host *)instance->hostdata;
2970 * Put card into RESET state
2972 outb(0x80, host->card.io_page);
2974 if (host->scsi.irq != NO_IRQ)
2975 free_irq(host->scsi.irq, host);
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);
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]);
2987 msgqueue_free(&host->scsi.msgs);
2988 queue_free(&host->queues.disconnected);
2989 queue_free(&host->queues.issue);
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
3001 char *acornscsi_info(struct Scsi_Host *host)
3003 static char string[100], *p;
3007 p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d"
3008 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
3011 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
3014 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
3017 #if (DEBUG & DEBUG_NO_WRITE)
3018 " NOWRITE ("NO_WRITE_STR")"
3020 , host->hostt->name, host->io_port, host->irq,
3021 VER_MAJOR, VER_MINOR, VER_PATCH);
3025 int acornscsi_proc_info(char *buffer, char **start, off_t offset,
3026 int length, int host_no, int inout)
3028 int pos, begin = 0, devidx;
3029 struct Scsi_Host *instance = scsi_hostlist;
3034 for (instance = scsi_hostlist;
3035 instance && instance->host_no != host_no;
3036 instance = instance->next);
3038 if (inout == 1 || !instance)
3041 host = (AS_Host *)instance->hostdata;
3043 p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
3044 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
3047 #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
3050 #ifdef CONFIG_SCSI_ACORNSCSI_LINK
3053 #if (DEBUG & DEBUG_NO_WRITE)
3054 " NOWRITE ("NO_WRITE_STR")"
3056 "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
3058 p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n",
3059 host->scsi.io_port, host->scsi.irq);
3061 p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n",
3062 host->dma.io_port, host->scsi.irq);
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);
3077 for (devidx = 0; devidx < 9; devidx ++) {
3078 unsigned int statptr, prev;
3080 p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
3081 statptr = host->status_ptr[devidx] - 10;
3083 if ((signed int)statptr < 0)
3084 statptr += STATUS_BUFFER_SIZE;
3086 prev = host->status[devidx][statptr].when;
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;
3101 p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
3103 for (scd = instance->host_queue; scd; scd = scd->next) {
3106 proc_print_scsidevice(scd, p, &len, 0);
3109 p += sprintf(p, "Extensions: ");
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));
3120 p += sprintf(p, "async\n");
3123 if (pos + begin < offset) {
3128 if (pos + begin > offset + length)
3134 *start = buffer + (offset - begin);
3135 pos -= offset - begin;
3143 static Scsi_Host_Template acornscsi_template = {
3144 module: THIS_MODULE,
3145 proc_info: acornscsi_proc_info,
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,
3156 sg_tablesize: SG_ALL,
3158 unchecked_isa_dma: 0,
3159 use_clustering: DISABLE_CLUSTERING
3162 static int __init acornscsi_init(void)
3164 acornscsi_template.module = THIS_MODULE;
3165 scsi_register_module(MODULE_SCSI_HA, &acornscsi_template);
3166 if (acornscsi_template.present)
3169 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
3173 static void __exit acornscsi_exit(void)
3175 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
3178 module_init(acornscsi_init);
3179 module_exit(acornscsi_exit);
3181 MODULE_AUTHOR("Russell King");
3182 MODULE_DESCRIPTION("AcornSCSI driver");
3183 MODULE_LICENSE("GPL");