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