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