acornscsi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:89k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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