root/drivers/scsi/wd33c93.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_wd33c93
  2. write_wd33c93
  3. write_wd33c93_cmd
  4. read_1_byte
  5. write_wd33c93_count
  6. read_wd33c93_count
  7. calc_sync_xfer
  8. wd33c93_queuecommand
  9. wd33c93_execute
  10. transfer_pio
  11. transfer_bytes
  12. wd33c93_intr
  13. reset_wd33c93
  14. wd33c93_reset
  15. wd33c93_abort
  16. wd33c93_setup
  17. wd33c93_init

   1 /*
   2  *    wd33c93.c - Linux-68k device driver for the Commodore
   3  *                Amiga A2091/590 SCSI controller card
   4  *
   5  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
   6  *    john@geolog.com
   7  *    jshiffle@netcom.com
   8  *
   9  * This program is free software; you can redistribute it and/or modify
  10  * it under the terms of the GNU General Public License as published by
  11  * the Free Software Foundation; either version 2, or (at your option)
  12  * any later version.
  13  *
  14  * This program is distributed in the hope that it will be useful,
  15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17  * GNU General Public License for more details.
  18  *
  19  *
  20  * Drew Eckhardt's excellent 'Generic NCR5380' sources from Linux-PC
  21  * provided much of the inspiration and some of the code for this
  22  * driver. Everything I know about Amiga DMA was gleaned from careful
  23  * reading of Hamish Mcdonald's original wd33c93 driver; in fact, I
  24  * borrowed shamelessly from all over that source. Thanks Hamish!
  25  *
  26  * _This_ driver is (I feel) an improvement over the old one in
  27  * several respects:
  28  *
  29  *    -  Target Disconnection/Reconnection  is now supported. Any
  30  *          system with more than one device active on the SCSI bus
  31  *          will benefit from this.
  32  *
  33  *    -  Synchronous data transfers are now supported. The driver
  34  *          automatically uses this faster protocol with any device
  35  *          able to handle it.
  36  *
  37  *    -  Runtime operating parameters can now be specified through
  38  *       either the 'amiboot' or the LILO command line. Something
  39  *       like:
  40  *          "wd33c93=0x0000"
  41  *       The value 0x0000 results in the defaults being used; bits
  42  *       are defined in wd33c93.h.
  43  *
  44  *    -  The old driver relied exclusively on what the Western Digital
  45  *          docs call "Combination Level 2 Commands", which are a great
  46  *          idea in that the CPU is relieved of a lot of interrupt
  47  *          overhead. However, by accepting a certain (user-settable)
  48  *          amount of additional interrupts, this driver achieves
  49  *          better control over the SCSI bus, and data transfers are
  50  *          almost as fast while being much easier to define, track,
  51  *          and debug.
  52  *
  53  *
  54  * TODO:
  55  *       more speed. tagged queuing.
  56  *
  57  *
  58  * People with bug reports, wish-lists, complaints, comments,
  59  * or improvements are asked to pah-leeez email me (John Shifflett)
  60  * at john@geolog.com or jshiffle@netcom.com! I'm anxious to get
  61  * this thing into as good a shape as possible, and I'm positive
  62  * there are lots of lurking bugs and "Stupid Places".
  63  *
  64  */
  65 
  66 #include <asm/system.h>
  67 #include <linux/sched.h>
  68 #include <linux/string.h>
  69 #include <linux/delay.h>
  70 #include <linux/blk.h>
  71 #include "scsi.h"
  72 #include "hosts.h"
  73 #include "wd33c93.h"
  74 
  75 
  76 #define SYNC_DEBUG
  77 
  78 #define DEBUGGING_ON
  79 
  80 #define WD33C93_VERSION    "1.17"
  81 #define WD33C93_DATE       "06/Feb/1996"
  82 
  83 #ifdef DEBUGGING_ON
  84 #define DB(f,a) if (hostdata->args & (f)) a;
  85 #else
  86 #define DB(f,a)
  87 #endif
  88 
  89 #define IS_DIR_OUT(cmd) ((cmd)->cmnd[0] == WRITE_6  || \
  90                          (cmd)->cmnd[0] == WRITE_10 || \
  91                          (cmd)->cmnd[0] == WRITE_12)
  92 
  93 
  94 /*
  95  * setup_default is a bunch of bits that define some of the operating
  96  * parameters and settings for this driver. It is used unless a LILO
  97  * or insmod command line has been specified, in which case setup_default
  98  * is _completely_ ignored. Take a look at the "defines for hostdata->args"
  99  * section in wd33c93.h - that stuff is what you'd use here if you want
 100  * to change the defaults.
 101  */
 102 
 103 static unsigned int setup_default = 0;
 104 
 105 
 106 inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108    regp->SASR = reg_num;
 109    return(regp->SCMD);
 110 }
 111 
 112 
 113 #define READ_AUX_STAT() (regp->SASR)
 114 
 115 
 116 inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118    regp->SASR = reg_num;
 119    regp->SCMD = value;
 120 }
 121 
 122 
 123 inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125    regp->SASR = WD_COMMAND;
 126    regp->SCMD = cmd;
 127 }
 128 
 129 
 130 inline uchar read_1_byte(wd33c93_regs *regp)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132 uchar asr;
 133 uchar x = 0;
 134 
 135    write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 136    write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO|0x80);
 137    do {
 138       asr = READ_AUX_STAT();
 139       if (asr & ASR_DBR)
 140          x = read_wd33c93(regp, WD_DATA);
 141       } while (!(asr & ASR_INT));
 142    return x;
 143 }
 144 
 145 
 146 void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148    regp->SASR = WD_TRANSFER_COUNT_MSB;
 149    regp->SCMD = value >> 16;
 150    regp->SCMD = value >> 8;
 151    regp->SCMD = value;
 152 }
 153 
 154 
 155 unsigned long read_wd33c93_count(wd33c93_regs *regp)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157 unsigned long value;
 158 
 159    regp->SASR = WD_TRANSFER_COUNT_MSB;
 160    value = regp->SCMD << 16;
 161    value |= regp->SCMD << 8;
 162    value |= regp->SCMD;
 163    return value;
 164 }
 165 
 166 
 167 
 168 static struct sx_period sx_table[] = {
 169    {  1, 0x20},
 170    {252, 0x20},
 171    {376, 0x30},
 172    {500, 0x40},
 173    {624, 0x50},
 174    {752, 0x60},
 175    {876, 0x70},
 176    {1000,0x00},
 177    {0,   0} };
 178 
 179 uchar calc_sync_xfer(unsigned int period, unsigned int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181 uchar result;
 182 int x;
 183 
 184    period *= 4;   /* convert SDTR code to ns */
 185    result = 0x00;
 186    for (x=1; sx_table[x].period_ns; x++) {
 187       if ((period <= sx_table[x-0].period_ns) &&
 188           (period >  sx_table[x-1].period_ns)) {
 189          result = sx_table[x].reg_value;
 190          break;
 191          }
 192       }
 193    result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF;
 194    return result;
 195 }
 196 
 197 
 198 
 199 static void wd33c93_execute(struct Scsi_Host *instance);
 200 
 201 int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203 struct WD33C93_hostdata *hostdata;
 204 Scsi_Cmnd *tmp;
 205 unsigned long flags;
 206 
 207    hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
 208 
 209 DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
 210 
 211 
 212 /*
 213  * Set up a few fields in the Scsi_Cmnd structure for our own use:
 214  *  - host_scribble is the pointer to the next cmd in the input queue
 215  *  - scsi_done points to the routine we call when a cmd is finished
 216  *  - result is what you'd expect
 217  */
 218 
 219    cmd->host_scribble = NULL;
 220    cmd->scsi_done = done;
 221    cmd->result = 0;
 222 
 223 /* We use the Scsi_Pointer structure that's included with each command
 224  * as a scratchpad (as it's intended to be used!). The handy thing about
 225  * the SCp.xxx fields is that they're always associated with a given
 226  * cmd, and are preserved across disconnect-reselect. This means we
 227  * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages
 228  * if we keep all the critical pointers and counters in SCp:
 229  *  - SCp.ptr is the pointer into the RAM buffer
 230  *  - SCp.this_residual is the size of that buffer
 231  *  - SCp.buffer points to the current scatter-gather buffer
 232  *  - SCp.buffers_residual tells us how many S.G. buffers there are
 233  */
 234 
 235    if (cmd->use_sg) {
 236       cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
 237       cmd->SCp.buffers_residual = cmd->use_sg - 1;
 238       cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
 239       cmd->SCp.this_residual = cmd->SCp.buffer->length;
 240       }
 241    else {
 242       cmd->SCp.buffer = NULL;
 243       cmd->SCp.buffers_residual = 0;
 244       cmd->SCp.ptr = (char *)cmd->request_buffer;
 245       cmd->SCp.this_residual = cmd->request_bufflen;
 246       }
 247 
 248 /* Preset the command status to GOOD, since that's the normal case */
 249 
 250    cmd->SCp.Status = GOOD;
 251 
 252    /*
 253     * Add the cmd to the end of 'input_Q'. Note that REQUEST SENSE
 254     * commands are added to the head of the queue so that the desired
 255     * sense data is not lost before REQUEST_SENSE executes.
 256     */
 257 
 258    save_flags(flags);
 259    cli();
 260    if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
 261       cmd->host_scribble = (uchar *)hostdata->input_Q;
 262       hostdata->input_Q = cmd;
 263       }
 264    else {
 265       for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble;
 266             tmp=(Scsi_Cmnd *)tmp->host_scribble)
 267          ;
 268       tmp->host_scribble = (uchar *)cmd;
 269       }
 270    restore_flags(flags);
 271 
 272 /* We know that there's at least one command in 'input_Q' now.
 273  * Go see if any of them are runnable!
 274  */
 275 
 276    wd33c93_execute(cmd->host);
 277 
 278 DB(DB_QUEUE_COMMAND,printk(")Q-%d-%02x-%ld ",cmd->target,cmd->cmnd[0],cmd->pid))
 279    return 0;
 280 }
 281 
 282 
 283 
 284 /*
 285  * This routine attempts to start a scsi command. If the host_card is
 286  * already connected, we give up immediately. Otherwise, look through
 287  * the input_Q, using the first command we find that's intended
 288  * for a currently non-busy target/lun.
 289  */
 290 static void wd33c93_execute (struct Scsi_Host *instance)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {
 292 struct WD33C93_hostdata *hostdata;
 293 wd33c93_regs *regp;
 294 Scsi_Cmnd *cmd, *prev;
 295 unsigned long flags;
 296 int i;
 297 
 298 
 299    save_flags(flags);
 300    cli();
 301    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
 302    regp = hostdata->regp;
 303 
 304 DB(DB_EXECUTE,printk("EX( "))
 305 
 306    if (hostdata->selecting || hostdata->connected) {
 307 DB(DB_EXECUTE,printk(")EX-0 "))
 308       restore_flags(flags);
 309       return;
 310       }
 311 
 312     /*
 313      * Search through the input_Q for a command destined
 314      * for an idle target/lun.
 315      */
 316 
 317    cmd = (Scsi_Cmnd *)hostdata->input_Q;
 318    prev = 0;
 319    while (cmd) {
 320       if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
 321          break;
 322       prev = cmd;
 323       cmd = (Scsi_Cmnd *)cmd->host_scribble;
 324       }
 325 
 326    /* quit if queue empty or all possible targets are busy */
 327 
 328    if (!cmd) {
 329 DB(DB_EXECUTE,printk(")EX-1 "))
 330       restore_flags(flags);
 331       return;
 332       }
 333 
 334    /*  remove command from queue, put it in selecting */
 335    
 336    if (prev)
 337       prev->host_scribble = cmd->host_scribble;
 338    else
 339       hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
 340    hostdata->selecting = cmd;
 341 
 342    /*
 343     * Start the selection process
 344     */
 345 
 346    if (IS_DIR_OUT(cmd))
 347       write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
 348    else
 349       write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
 350 
 351    write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
 352    write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 353    write_wd33c93_count(regp, 0); /* this guarantees a DATA_PHASE interrupt */
 354    hostdata->busy[cmd->target] |= (1 << cmd->lun);
 355 
 356    if ((hostdata->level2 == L2_NONE) ||
 357        (hostdata->sync_stat[cmd->target] == SS_UNSET)) {
 358 
 359          /*
 360           * Now do a 'Select-With-ATN' command. This will end with
 361           * one of the following interrupts:
 362           *    CSR_RESEL_AM:  failure - can try again later.
 363           *    CSR_TIMEOUT:   failure - give up.
 364           *    CSR_SELECT:    success - proceed.
 365           */
 366 
 367 /* Every target has its own synchronous transfer setting, kept in the
 368  * sync_xfer array, and a corresponding status byte in sync_stat[].
 369  * Each target's sync_stat[] entry is initialized to SX_UNSET, and its
 370  * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
 371  * means that the parameters are undetermined as yet, and that we
 372  * need to send an SDTR message to this device after selection is
 373  * complete. We set SS_FIRST to tell the interrupt routine to do so,
 374  * unless we've been asked not to try synchronous transfers on this
 375  * target (and _all_ luns within it): In this case we set SS_SET to
 376  * make the defaults final.
 377  */
 378       if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
 379          if (hostdata->args & (1 << cmd->target))
 380             hostdata->sync_stat[cmd->target] = SS_SET;
 381          else
 382             hostdata->sync_stat[cmd->target] = SS_FIRST;
 383          }
 384       hostdata->state = S_SELECTING;
 385       write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
 386       }
 387 
 388    else {
 389 
 390          /*
 391           * Now do a 'Select-With-ATN-Xfer' command. This will end with
 392           * one of the following interrupts:
 393           *    CSR_RESEL_AM:  failure - can try again later.
 394           *    CSR_TIMEOUT:   failure - give up.
 395           *    anything else: success - proceed.
 396           */
 397 
 398       hostdata->connected = cmd;
 399       hostdata->selecting = NULL;
 400       write_wd33c93(regp, WD_COMMAND_PHASE, 0);
 401 
 402    /* copy command_descriptor_block into WD chip */
 403 
 404       for (i=0; i<cmd->cmd_len; i++)
 405          write_wd33c93(regp, WD_CDB_1+i, cmd->cmnd[i]);
 406 
 407    /* The wd33c93 only knows about Group 0, 1, and 5 commands when
 408     * it's doing a 'select-and-transfer'. To be safe, we write the
 409     * size of the CDB into the OWN_ID register for every case. This
 410     * way there won't be problems with vendor-unique, audio, etc.
 411     */
 412 
 413       write_wd33c93(regp, WD_OWN_ID, cmd->cmd_len);
 414 
 415       hostdata->state = S_RUNNING_LEVEL2;
 416       write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
 417       }
 418 
 419    /*
 420     * Since the SCSI bus can handle only 1 connection at a time,
 421     * we get out of here now. If the selection fails, or when
 422     * the command disconnects, we'll come back to this routine
 423     * to search the input_Q again...
 424     */
 425       
 426 DB(DB_EXECUTE,printk(")EX-2 "))
 427    restore_flags(flags);
 428 }
 429 
 430 
 431 
 432 void transfer_pio(wd33c93_regs *regp, uchar **buf, int *cnt,
     /* [previous][next][first][last][top][bottom][index][help] */
 433                   int data_in_dir, struct WD33C93_hostdata *hostdata)
 434 {
 435 uchar *b, asr;
 436 int c;
 437 
 438    write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 439    b = *buf;
 440    c = *cnt;
 441 DB(DB_TRANSFER_DATA,printk("[[%p/%d]]",b,c))
 442    write_wd33c93_count(regp,c);
 443    write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
 444    if (data_in_dir) {
 445       do {
 446          asr = READ_AUX_STAT();
 447          if (asr & ASR_DBR)
 448             *b++ = read_wd33c93(regp, WD_DATA);
 449          } while (!(asr & ASR_INT));
 450       }
 451    else {
 452       do {
 453          asr = READ_AUX_STAT();
 454          if (asr & ASR_DBR)
 455             write_wd33c93(regp, WD_DATA, *b++);
 456          } while (!(asr & ASR_INT));
 457       }
 458 
 459 /* update original buffer pointer and original count */
 460 
 461    *cnt = read_wd33c93_count(regp);
 462    if (data_in_dir)
 463       *buf = b;
 464    else
 465       *buf += (c - *cnt);
 466 
 467    /* Note: we are returning with the interrupt UN-cleared.
 468    * Since (presumably) an entire I/O operation has
 469    * completed, the bus phase is probably different, and
 470    * the interrupt routine will discover this when it
 471    * responds to the uncleared int.
 472    */
 473 
 474 }
 475 
 476 
 477 
 478 void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480 struct WD33C93_hostdata *hostdata;
 481 
 482    hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
 483 
 484 /* Normally, you'd expect 'this_residual' to be non-zero here.
 485  * In a series of scatter-gather transfers, however, this
 486  * routine will usually be called with 'this_residual' equal
 487  * to 0 and 'buffers_residual' non-zero. This means that a
 488  * previous transfer completed, clearing 'this_residual', and
 489  * now we need to setup the next scatter-gather buffer as the
 490  * source or destination for THIS transfer.
 491  */
 492    if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
 493       ++cmd->SCp.buffer;
 494       --cmd->SCp.buffers_residual;
 495       cmd->SCp.this_residual = cmd->SCp.buffer->length;
 496       cmd->SCp.ptr = cmd->SCp.buffer->address;
 497       }
 498 
 499    write_wd33c93(regp,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
 500 
 501 /* 'dma_setup()' will return TRUE if we can't do DMA. */
 502 
 503    if (hostdata->dma_setup(cmd, data_in_dir)) {
 504       transfer_pio(regp, (uchar **)&cmd->SCp.ptr, &cmd->SCp.this_residual,
 505                          data_in_dir, hostdata);
 506       }
 507 
 508 /* We are able to do DMA (in fact, the Amiga hardware is
 509  * already going!), so start up the wd33c93 in DMA mode.
 510  * We set 'hostdata->dma' = D_DMA_RUNNING so that when the
 511  * transfer completes and causes an interrupt, we're
 512  * reminded to tell the Amiga to shut down its end. We'll
 513  * postpone the updating of 'this_residual' and 'ptr'
 514  * until then.
 515  */
 516 
 517    else {
 518       write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
 519 DB(DB_TRANSFER_DATA,printk("[%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual))
 520       write_wd33c93_count(regp,cmd->SCp.this_residual);
 521 
 522       if (hostdata->level2 >= L2_DATA) {
 523          write_wd33c93(regp, WD_COMMAND_PHASE, 0x41);
 524          write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
 525          hostdata->state = S_RUNNING_LEVEL2;
 526          }
 527       else
 528          write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
 529 
 530       hostdata->dma = D_DMA_RUNNING;
 531       }
 532 }
 533 
 534 
 535 
 536 void wd33c93_intr (struct Scsi_Host *instance)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538 struct WD33C93_hostdata *hostdata;
 539 Scsi_Cmnd *patch, *cmd;
 540 wd33c93_regs *regp;
 541 uchar asr, sr, phs, id, lun, *ucp, msg;
 542 unsigned long length;
 543 int i;
 544 
 545 
 546    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
 547    regp = hostdata->regp;
 548 
 549    asr = READ_AUX_STAT();
 550    if (!(asr & ASR_INT) || (asr & ASR_BSY))
 551       return;
 552 
 553    cmd = (Scsi_Cmnd *)hostdata->connected;   /* assume we're connected */
 554    sr = read_wd33c93(regp, WD_SCSI_STATUS);  /* clear the interrupt */
 555    phs = read_wd33c93(regp, WD_COMMAND_PHASE);
 556 
 557 DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
 558 
 559 /* After starting a DMA transfer, the next interrupt
 560  * is guaranteed to be in response to completion of
 561  * the transfer. Since the Amiga DMA hardware runs in
 562  * in an open-ended fashion, it needs to be told when
 563  * to stop; do that here if D_DMA_RUNNING is true.
 564  * Also, we have to update 'this_residual' and 'ptr'
 565  * based on the contents of the TRANSFER_COUNT register,
 566  * in case the device decided to do an intermediate
 567  * disconnect (a device may do this if it has to do a
 568  * seek, or just to be nice and let other devices have
 569  * some bus time during long transfers). After doing
 570  * whatever is needed, we go on and service the WD3393
 571  * interrupt normally.
 572  */
 573 
 574    if (hostdata->dma == D_DMA_RUNNING) {
 575 DB(DB_TRANSFER_DATA,printk("[%p/%d:",cmd->SCp.ptr,cmd->SCp.this_residual))
 576       hostdata->dma_stop(cmd->host, cmd, 1);
 577       hostdata->dma = D_DMA_OFF;
 578       length = cmd->SCp.this_residual;
 579       cmd->SCp.this_residual = read_wd33c93_count(regp);
 580       cmd->SCp.ptr += (length - cmd->SCp.this_residual);
 581 DB(DB_TRANSFER_DATA,printk("%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual))
 582       }
 583 
 584 /* Respond to the specific WD3393 interrupt - there are quite a few! */
 585 
 586    switch (sr) {
 587 
 588       case CSR_TIMEOUT:
 589          cli();
 590 DB(DB_INTR,printk("TIMEOUT"))
 591          if (hostdata->state == S_RUNNING_LEVEL2) {
 592             hostdata->connected = NULL;
 593             hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 594             }
 595          else {
 596             cmd = (Scsi_Cmnd *)hostdata->selecting;   /* get a valid cmd */
 597             hostdata->selecting = NULL;
 598             }
 599 
 600          cmd->result = DID_NO_CONNECT << 16;
 601          hostdata->selecting = NULL;
 602          hostdata->state = S_UNCONNECTED;
 603          cmd->scsi_done(cmd);    /* I think scsi_done() enables ints */
 604 
 605 /* We are not connected to a target - check to see if there
 606  * are commands waiting to be executed.
 607  */
 608 
 609          wd33c93_execute(instance);
 610          break;
 611 
 612 
 613 /* Note: this interrupt should not occur in a LEVEL2 command */
 614 
 615       case CSR_SELECT:
 616          cli();
 617 DB(DB_INTR,printk("SELECT"))
 618          hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
 619          hostdata->selecting = NULL;
 620 
 621       /* construct an IDENTIFY message with correct disconnect bit */
 622 
 623          if (hostdata->args & A_NO_DISCONNECT)
 624             hostdata->outgoing_msg[0] = (0x80 | cmd->lun);
 625          else
 626             hostdata->outgoing_msg[0] = (0x80 | 0x40 | cmd->lun);
 627 
 628          if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
 629 #ifdef SYNC_DEBUG
 630 printk(" sending SDTR ");
 631 #endif
 632 
 633             hostdata->sync_stat[cmd->target] = SS_WAITING;
 634 
 635       /* tack on a 2nd message to ask about synchronous transfers */
 636 
 637             hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
 638             hostdata->outgoing_msg[2] = 3;
 639             hostdata->outgoing_msg[3] = EXTENDED_SDTR;
 640             hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
 641             hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
 642             hostdata->outgoing_len = 6;
 643             }
 644          else
 645             hostdata->outgoing_len = 1;
 646 
 647          hostdata->state = S_CONNECTED;
 648          break;
 649 
 650 
 651       case CSR_XFER_DONE|PHS_DATA_IN:
 652       case CSR_UNEXP    |PHS_DATA_IN:
 653       case CSR_SRV_REQ  |PHS_DATA_IN:
 654 DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
 655          transfer_bytes(regp, cmd, DATA_IN_DIR);
 656          if (hostdata->state != S_RUNNING_LEVEL2)
 657             hostdata->state = S_CONNECTED;
 658          break;
 659 
 660 
 661       case CSR_XFER_DONE|PHS_DATA_OUT:
 662       case CSR_UNEXP    |PHS_DATA_OUT:
 663       case CSR_SRV_REQ  |PHS_DATA_OUT:
 664 DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
 665          transfer_bytes(regp, cmd, DATA_OUT_DIR);
 666          if (hostdata->state != S_RUNNING_LEVEL2)
 667             hostdata->state = S_CONNECTED;
 668          break;
 669 
 670 
 671 /* Note: this interrupt should not occur in a LEVEL2 command */
 672 
 673       case CSR_XFER_DONE|PHS_COMMAND:
 674       case CSR_SRV_REQ  |PHS_COMMAND:
 675 DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
 676          ucp = cmd->cmnd;
 677          i = cmd->cmd_len;
 678          transfer_pio(regp, &ucp, &i, DATA_OUT_DIR, hostdata);
 679          hostdata->state = S_CONNECTED;
 680          break;
 681 
 682 
 683       case CSR_XFER_DONE|PHS_STATUS:
 684       case CSR_UNEXP    |PHS_STATUS:
 685       case CSR_SRV_REQ  |PHS_STATUS:
 686 DB(DB_INTR,printk("STATUS"))
 687 
 688          cmd->SCp.Status = read_1_byte(regp);
 689          if (hostdata->level2 >= L2_BASIC) {
 690             sr = read_wd33c93(regp, WD_SCSI_STATUS);  /* clear interrupt */
 691             hostdata->state = S_RUNNING_LEVEL2;
 692             write_wd33c93(regp, WD_COMMAND_PHASE, 0x50);
 693             write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
 694             }
 695          else {
 696 DB(DB_INTR,printk("=%02x",cmd->SCp.Status))
 697             hostdata->state = S_CONNECTED;
 698             }
 699          break;
 700 
 701 
 702       case CSR_XFER_DONE|PHS_MESS_IN:
 703       case CSR_UNEXP    |PHS_MESS_IN:
 704       case CSR_SRV_REQ  |PHS_MESS_IN:
 705 DB(DB_INTR,printk("MSG_IN="))
 706 
 707          msg = read_1_byte(regp);
 708          sr = read_wd33c93(regp, WD_SCSI_STATUS);  /* clear interrupt */
 709 
 710          hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
 711          if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
 712             msg = EXTENDED_MESSAGE;
 713          else
 714             hostdata->incoming_ptr = 0;
 715 
 716          cmd->SCp.Message = msg;
 717          switch (msg) {
 718 
 719             case COMMAND_COMPLETE:
 720 DB(DB_INTR,printk("CCMP-%ld",cmd->pid))
 721                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 722                hostdata->state = S_PRE_CMP_DISC;
 723                break;
 724 
 725             case SAVE_POINTERS:
 726 DB(DB_INTR,printk("SDP"))
 727                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 728                hostdata->state = S_CONNECTED;
 729                break;
 730 
 731             case RESTORE_POINTERS:
 732 DB(DB_INTR,printk("RDP"))
 733 
 734                if (hostdata->level2 >= L2_BASIC) {
 735                   write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
 736                   write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
 737                   hostdata->state = S_RUNNING_LEVEL2;
 738                   }
 739                else {
 740                   write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
 741                   hostdata->state = S_CONNECTED;
 742                   }
 743                break;
 744 
 745             case DISCONNECT:
 746 DB(DB_INTR,printk("DIS"))
 747                cmd->device->disconnect = 1;
 748                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 749                hostdata->state = S_PRE_TMP_DISC;
 750                break;
 751 
 752             case MESSAGE_REJECT:
 753 DB(DB_INTR,printk("REJ"))
 754 #ifdef SYNC_DEBUG
 755 printk("-REJ-");
 756 #endif
 757                if (hostdata->sync_stat[cmd->target] == SS_WAITING)
 758                   hostdata->sync_stat[cmd->target] = SS_SET;
 759                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 760                hostdata->state = S_CONNECTED;
 761                break;
 762 
 763             case EXTENDED_MESSAGE:
 764 DB(DB_INTR,printk("EXT"))
 765 
 766                ucp = hostdata->incoming_msg;
 767 
 768 #ifdef SYNC_DEBUG
 769 printk("%02x",ucp[hostdata->incoming_ptr]);
 770 #endif
 771          /* Is this the last byte of the extended message? */
 772 
 773                if ((hostdata->incoming_ptr >= 2) &&
 774                    (hostdata->incoming_ptr == (ucp[1] + 1))) {
 775 
 776                   switch (ucp[2]) {   /* what's the EXTENDED code? */
 777                      case EXTENDED_SDTR:
 778                         id = calc_sync_xfer(ucp[3],ucp[4]);
 779                         if (hostdata->sync_stat[cmd->target] != SS_WAITING) {
 780                            printk("Rejecting target's SDTR message ");
 781                            write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
 782                            hostdata->outgoing_msg[0] = MESSAGE_REJECT;
 783                            hostdata->outgoing_len = 1;
 784                            }
 785                         else {
 786                            hostdata->sync_xfer[cmd->target] = id;
 787                            hostdata->sync_stat[cmd->target] = SS_SET;
 788                            }
 789 #ifdef SYNC_DEBUG
 790 printk("sync_xfer=%02x",id);
 791 #endif
 792                         write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 793                         hostdata->state = S_CONNECTED;
 794                         break;
 795                      default:
 796                         printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);
 797                         write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
 798                         hostdata->outgoing_msg[0] = MESSAGE_REJECT;
 799                         hostdata->outgoing_len = 1;
 800                         write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 801                         hostdata->state = S_CONNECTED;
 802                         break;
 803                      }
 804                   hostdata->incoming_ptr = 0;
 805                   }
 806 
 807          /* We need to read more MESS_IN bytes for the extended message */
 808 
 809                else {
 810                   hostdata->incoming_ptr++;
 811                   write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 812                   hostdata->state = S_CONNECTED;
 813                   }
 814                break;
 815 
 816             default:
 817                printk("Rejecting Unknown Message(%02x) ",ucp[0]);
 818                write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
 819                hostdata->outgoing_msg[0] = MESSAGE_REJECT;
 820                hostdata->outgoing_len = 1;
 821                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 822                hostdata->state = S_CONNECTED;
 823             }
 824          break;
 825 
 826 
 827 /* Note: this interrupt will occur only after a LEVEL2 command */
 828 
 829       case CSR_SEL_XFER_DONE:
 830          cli();
 831          if (phs == 0x60) {
 832 DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))
 833             cmd->SCp.Message = COMMAND_COMPLETE;
 834             lun = read_wd33c93(regp, WD_TARGET_LUN);
 835             if (cmd->SCp.Status == GOOD)
 836                cmd->SCp.Status = lun;
 837             hostdata->connected = NULL;
 838             if (cmd->cmnd[0] != REQUEST_SENSE)
 839                cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
 840             else if (cmd->SCp.Status != GOOD)
 841                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 842             hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 843             hostdata->state = S_UNCONNECTED;
 844             cmd->scsi_done(cmd);    /* I think scsi_done() enables ints */
 845 
 846 /* We are no longer  connected to a target - check to see if
 847  * there are commands waiting to be executed.
 848  */
 849 
 850             wd33c93_execute(instance);
 851             }
 852          else {
 853             printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
 854             }
 855          break;
 856 
 857 
 858 /* Note: this interrupt will occur only after a LEVEL2 command */
 859 
 860       case CSR_SDP:
 861 DB(DB_INTR,printk("SDP"))
 862             hostdata->state = S_RUNNING_LEVEL2;
 863             write_wd33c93(regp, WD_COMMAND_PHASE, 0x41);
 864             write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
 865          break;
 866 
 867 
 868       case CSR_XFER_DONE|PHS_MESS_OUT:
 869       case CSR_UNEXP    |PHS_MESS_OUT:
 870       case CSR_SRV_REQ  |PHS_MESS_OUT:
 871 DB(DB_INTR,printk("MSG_OUT="))
 872 
 873 /* To get here, we've probably requested MESSAGE_OUT and have
 874  * already put the correct bytes in outgoing_msg[] and filled
 875  * in outgoing_len. We simply send them out to the SCSI bus.
 876  * Sometimes we get MESSAGE_OUT phase when we're not expecting
 877  * it - like when our SDTR message is rejected by a target. Some
 878  * targets send the REJECT before receiving all of the extended
 879  * message, and then seem to go back to MESSAGE_OUT for a byte
 880  * or two. Not sure why, ot if I'm doing something wrong to
 881  * casue this to happen. Regardless, it seems that sending
 882  * NOP messages in these situations results in no harm and
 883  * makes everyone happy.
 884  */
 885 
 886          if (hostdata->outgoing_len == 0) {
 887             hostdata->outgoing_len = 1;
 888             hostdata->outgoing_msg[0] = NOP;
 889             }
 890          ucp = hostdata->outgoing_msg;
 891          i = hostdata->outgoing_len;
 892          transfer_pio(regp, &ucp, &i, DATA_OUT_DIR, hostdata);
 893 DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
 894          hostdata->outgoing_len = 0;
 895          hostdata->state = S_CONNECTED;
 896          break;
 897 
 898 
 899       case CSR_DISC:
 900 DB(DB_INTR,printk("DISC"))
 901          if (cmd == NULL) {
 902             printk(" - Already disconnected! ");
 903             hostdata->state = S_UNCONNECTED;
 904             return;
 905             }
 906          switch (hostdata->state) {
 907             case S_PRE_CMP_DISC:
 908                hostdata->connected = NULL;
 909                hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 910                hostdata->state = S_UNCONNECTED;
 911                if (cmd->cmnd[0] != REQUEST_SENSE)
 912                   cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
 913                else if (cmd->SCp.Status != GOOD)
 914                   cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 915                cmd->scsi_done(cmd);    /* I think scsi_done() enables ints */
 916                break;
 917             case S_PRE_TMP_DISC:
 918             case S_RUNNING_LEVEL2:
 919                cmd->host_scribble = (uchar *)hostdata->disconnected_Q;
 920                hostdata->disconnected_Q = cmd;
 921                hostdata->connected = NULL;
 922                hostdata->state = S_UNCONNECTED;
 923                break;
 924             default:
 925                printk("*** Unexpected DISCONNECT interrupt! ***");
 926                hostdata->state = S_UNCONNECTED;
 927             }
 928 
 929 /* We are no longer connected to a target - check to see if
 930  * there are commands waiting to be executed.
 931  */
 932 
 933          wd33c93_execute(instance);
 934          break;
 935 
 936 
 937       case CSR_RESEL_AM:
 938 DB(DB_INTR,printk("RESEL"))
 939 
 940          cli();
 941 
 942    /* First we have to make sure this reselection didn't */
 943    /* happen during Arbitration/Selection of some other device. */
 944    /* If yes, put losing command back on top of input_Q. */
 945 
 946          if (hostdata->level2 == L2_NONE) {
 947 
 948             if (hostdata->selecting) {
 949                cmd = (Scsi_Cmnd *)hostdata->selecting;
 950                hostdata->selecting = NULL;
 951                hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 952                cmd->host_scribble = (uchar *)hostdata->input_Q;
 953                hostdata->input_Q = cmd;
 954                }
 955             }
 956 
 957          else {
 958 
 959             if (cmd) {
 960                if (phs == 0x00) {
 961                   hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 962                   cmd->host_scribble = (uchar *)hostdata->input_Q;
 963                   hostdata->input_Q = cmd;
 964                   }
 965                else {
 966                   printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);
 967                   while (1)
 968                      printk("\r");
 969                   }
 970                }
 971 
 972             }
 973 
 974    /* OK - find out which device reslected us. */
 975 
 976          id = read_wd33c93(regp, WD_SOURCE_ID);
 977          id &= SRCID_MASK;
 978 
 979    /* and extract the lun from the ID message. (Note that we don't
 980     * bother to check for a valid message here - I guess this is
 981     * not the right way to go, but...)
 982     */
 983 
 984          lun = read_wd33c93(regp, WD_DATA);
 985          if (hostdata->level2 < L2_RESELECT)
 986             write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
 987          lun &= 7;
 988 
 989    /* Now we look for the command that's reconnecting. */
 990 
 991          cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;
 992          patch = NULL;
 993          while (cmd) {
 994             if (id == cmd->target && lun == cmd->lun)
 995                break;
 996             patch = cmd;
 997             cmd = (Scsi_Cmnd *)cmd->host_scribble;
 998             }
 999 
1000    /* Hmm. Couldn't find a valid command.... What to do? */
1001 
1002          if (!cmd) {
1003             printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
1004             return;
1005             }
1006 
1007    /* Ok, found the command - now start it up again. */
1008 
1009          if (patch)
1010             patch->host_scribble = cmd->host_scribble;
1011          else
1012             hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;
1013          hostdata->connected = cmd;
1014 
1015    /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'
1016     * because these things are preserved over a disconnect.
1017     * But we DO need to fix the DPD bit so it's correct for this command.
1018     */
1019 
1020          if (IS_DIR_OUT(cmd))
1021             write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
1022          else
1023             write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
1024          if (hostdata->level2 >= L2_RESELECT) {
1025             write_wd33c93_count(regp, 0);  /* we want a DATA_PHASE interrupt */
1026             write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
1027             write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
1028             hostdata->state = S_RUNNING_LEVEL2;
1029             }
1030          else
1031             hostdata->state = S_CONNECTED;
1032 
1033 DB(DB_INTR,printk("-%ld",cmd->pid))
1034          break;
1035          
1036       default:
1037          printk("\n---UNKNOWN INTERRUPT:%02x:%02x:%02x!!---",asr,sr,phs);
1038       }
1039 
1040 DB(DB_INTR,printk("} "))
1041 
1042 }
1043 
1044 
1045 
1046 void reset_wd33c93(struct Scsi_Host *instance)
     /* [previous][next][first][last][top][bottom][index][help] */
1047 {
1048 struct WD33C93_hostdata *hostdata;
1049 wd33c93_regs *regp;
1050 uchar sr;
1051 
1052    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1053    regp = hostdata->regp;
1054 
1055    write_wd33c93(regp, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
1056                  instance->this_id | hostdata->clock_freq);
1057    write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1058    write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
1059                  calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF));
1060    write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET);
1061 
1062    while (!(READ_AUX_STAT() & ASR_INT))
1063       ;
1064    sr = read_wd33c93(regp, WD_SCSI_STATUS);
1065 
1066    hostdata->microcode = read_wd33c93(regp, WD_CDB_1);
1067    if (sr == 0x00)
1068       hostdata->chip = C_WD33C93;
1069    else if (sr == 0x01) {
1070       write_wd33c93(regp, WD_QUEUE_TAG, 0xa5);  /* any random number */
1071       sr = read_wd33c93(regp, WD_QUEUE_TAG);
1072       if (sr == 0xa5) {
1073          hostdata->chip = C_WD33C93B;
1074          write_wd33c93(regp, WD_QUEUE_TAG, 0);
1075          }
1076       else
1077          hostdata->chip = C_WD33C93A;
1078       }
1079    else
1080       hostdata->chip = C_UNKNOWN_CHIP;
1081 
1082    write_wd33c93(regp, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1083    if (hostdata->args & A_NO_DISCONNECT)
1084       write_wd33c93(regp, WD_SOURCE_ID, 0);
1085    else
1086       write_wd33c93(regp, WD_SOURCE_ID, SRCID_ER);
1087    write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1088 }
1089 
1090 
1091 
1092 int wd33c93_reset(Scsi_Cmnd *SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1093 {
1094 unsigned long flags;
1095 struct Scsi_Host *instance;
1096 
1097    instance = SCpnt->host;
1098 
1099    printk("scsi%d: reset. ", instance->host_no);
1100    save_flags(flags);
1101    cli();
1102    ((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);
1103    reset_wd33c93(instance);
1104    SCpnt->result = DID_RESET << 16;
1105    restore_flags(flags);
1106    return 0;
1107 }
1108 
1109 
1110 
1111 int wd33c93_abort (Scsi_Cmnd *cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
1112 {
1113 struct Scsi_Host *instance;
1114 struct WD33C93_hostdata *hostdata;
1115 wd33c93_regs *regp;
1116 Scsi_Cmnd *tmp, **prev;
1117 unsigned long flags;
1118 
1119    instance = cmd->host;
1120    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1121    regp = hostdata->regp;
1122 
1123    printk ("scsi%d: abort. ", instance->host_no);
1124 
1125    save_flags (flags);
1126    cli();
1127 
1128 /*
1129  * Case 1 : If the command hasn't been issued yet, we simply remove it
1130  *     from the issue queue.
1131  */
1132    for (prev=(Scsi_Cmnd **)&(hostdata->input_Q),tmp=(Scsi_Cmnd *)hostdata->input_Q;
1133          tmp;
1134          prev=(Scsi_Cmnd **)&(tmp->host_scribble),tmp=(Scsi_Cmnd *)tmp->host_scribble)
1135       if (cmd == tmp) {
1136          (*prev) = (Scsi_Cmnd *)tmp->host_scribble;
1137          tmp->host_scribble = NULL;
1138          tmp->result = DID_ABORT << 16;
1139          restore_flags(flags);
1140          printk("scsi%d : abort removed command from issue queue. ",
1141            instance->host_no);
1142          tmp->scsi_done(tmp);
1143          return SCSI_ABORT_SUCCESS;
1144          }
1145 
1146 /*
1147  * Case 2 : If any commands are connected, we're going to fail the abort
1148  *     and let the high level SCSI driver retry at a later time or
1149  *     issue a reset.
1150  *
1151  *     Timeouts, and therefore aborted commands, will be highly unlikely
1152  *     and handling them cleanly in this situation would make the common
1153  *     case of noresets less efficient, and would pollute our code.  So,
1154  *     we fail.
1155  */
1156 
1157    if (hostdata->connected == cmd) {
1158       uchar sr, asr;
1159       unsigned long timeout;
1160 
1161       printk("scsi%d : aborting connected command. ", instance->host_no);
1162 
1163       if (hostdata->dma == D_DMA_RUNNING) {
1164          hostdata->dma_stop(instance, cmd, 0);
1165          hostdata->dma = D_DMA_OFF;
1166          }
1167 
1168          printk("scsi%d : wd33c93 asr is %x. ", instance->host_no, READ_AUX_STAT());
1169 
1170       write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1171       write_wd33c93_cmd(regp, WD_CMD_ABORT);
1172 
1173 /* Now we have to attempt to flush out the FIFO... */
1174 
1175       timeout = 1000000;
1176       do {
1177          asr = READ_AUX_STAT();
1178          if (asr & ASR_DBR)
1179             read_wd33c93(regp, WD_DATA);
1180          } while (!(asr & ASR_INT) && timeout-- > 0);
1181       sr = read_wd33c93(regp, WD_SCSI_STATUS);
1182       printk("scsi%d : wd33c93 sr is %x. ", instance->host_no,
1183          read_wd33c93(regp, WD_SCSI_STATUS));
1184 
1185       if (sr >= (CSR_ABORT|PHS_DATA_OUT) && sr <= (CSR_ABORT|PHS_MESS_IN)) {
1186    /*
1187     * Abort command processed.
1188     * Still connected.
1189     * We must disconnect.
1190     */
1191          printk("scsi%d : count was %ld. ", instance->host_no,
1192             read_wd33c93_count(regp));
1193 
1194          timeout = 1000000;
1195          while ((asr & ASR_CIP) && timeout-- > 0)
1196             asr = READ_AUX_STAT();
1197          write_wd33c93_cmd(regp, WD_CMD_DISCONNECT);
1198          asr = READ_AUX_STAT();
1199          if (asr & ASR_LCI)
1200             printk ("scsi%d: disconnect command ignored. ",
1201                instance->host_no);
1202          timeout = 1000000;
1203          while ((asr & ASR_CIP) && timeout-- > 0)
1204             asr = READ_AUX_STAT();
1205          }
1206       asr = READ_AUX_STAT();
1207       sr = read_wd33c93(regp, WD_SCSI_STATUS);
1208       printk("scsi%d : asr is %x, sr is %x. ",instance->host_no,asr,sr);
1209       write_wd33c93_cmd(regp, WD_CMD_DISCONNECT);
1210       timeout = 1000000;
1211       while ((asr & ASR_CIP) && timeout-- > 0)
1212          asr = READ_AUX_STAT();
1213       sr = read_wd33c93(regp, WD_SCSI_STATUS);
1214       printk("scsi%d : asr is %x, sr is %x. ",instance->host_no,asr,sr);
1215       reset_wd33c93(instance);
1216       cmd->result = DID_ABORT << 16;
1217       cmd->scsi_done(cmd);
1218       hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1219       hostdata->connected = NULL;
1220       hostdata->state = S_UNCONNECTED;
1221       wd33c93_execute (instance);
1222       restore_flags(flags);
1223       return SCSI_ABORT_SUCCESS;
1224       }
1225 
1226 /*
1227  * Case 3: If the command is currently disconnected from the bus,
1228  * we're not going to expend much effort here: Let's just return
1229  * an ABORT_SNOOZE and hope for the best...
1230  */
1231 
1232    for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp;
1233          tmp=(Scsi_Cmnd *)tmp->host_scribble)
1234       if (cmd == tmp) {
1235          restore_flags(flags);
1236          return SCSI_ABORT_SNOOZE;
1237          }
1238 
1239 /*
1240  * Case 4 : If we reached this point, the command was not found in any of
1241  *     the queues.
1242  *
1243  * We probably reached this point because of an unlikely race condition
1244  * between the command completing successfully and the abortion code,
1245  * so we won't panic, but we will notify the user in case somethign really
1246  * broke.
1247  */
1248 
1249    restore_flags(flags);
1250    printk("scsi%d : warning : SCSI command probably completed successfully\n"
1251       "         before abortion. ", instance->host_no);
1252    return SCSI_ABORT_NOT_RUNNING;
1253 }
1254 
1255 
1256 
1257 #define MAX_WD33C93_HOSTS 8
1258 static unsigned int setup_args_array[MAX_WD33C93_HOSTS];
1259 static int setup_args_array_x = 0;
1260 
1261 void wd33c93_setup (char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
1262 {
1263 int i;
1264 
1265    for (i=0; i<ints[0]; i++) {
1266       setup_args_array[i] = ints[i+1];
1267       }
1268 }
1269 
1270 
1271 
1272 void wd33c93_init (struct Scsi_Host *instance, wd33c93_regs *regs,
     /* [previous][next][first][last][top][bottom][index][help] */
1273          dma_setup_t setup, dma_stop_t stop, int clock_freq)
1274 {
1275 struct WD33C93_hostdata *hostdata;
1276 int i;
1277 
1278    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1279 
1280    hostdata->regp = regs;
1281    hostdata->clock_freq = clock_freq;
1282    hostdata->dma_setup = setup;
1283    hostdata->dma_stop = stop;
1284    hostdata->dma_bounce_buffer = NULL;
1285    hostdata->dma_bounce_len = 0;
1286    for (i = 0; i < 8; i++) {
1287       hostdata->busy[i] = 0;
1288       hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
1289       hostdata->sync_stat[i] = SS_UNSET;  /* using default sync values */
1290       }
1291    hostdata->input_Q = NULL;
1292    hostdata->selecting = NULL;
1293    hostdata->connected = NULL;
1294    hostdata->disconnected_Q = NULL;
1295    hostdata->state = S_UNCONNECTED;
1296    hostdata->dma = D_DMA_OFF;
1297    hostdata->incoming_ptr = 0;
1298    hostdata->outgoing_len = 0;
1299 
1300    hostdata->args = setup_default;
1301    if ((setup_args_array_x < MAX_WD33C93_HOSTS) &&
1302        (setup_args_array[setup_args_array_x]))
1303       hostdata->args = setup_args_array[setup_args_array_x];
1304    setup_args_array_x++;
1305 
1306    i = hostdata->args & (A_LEVEL2_0 | A_LEVEL2_1 | A_LEVEL2_2);
1307    i >>= 8;
1308    if (i == 0)
1309       i = L2_DEFAULT;
1310    hostdata->level2 = i;
1311 
1312    cli();
1313    reset_wd33c93(instance);
1314    sti();
1315 
1316    printk("wd33c93-%d: ",instance->host_no);
1317    switch (hostdata->chip) {
1318       case C_WD33C93:
1319          printk("Found WD33c93 chip! This driver probably needs at least the 'A' version!\n");
1320          break;
1321       case C_WD33C93A:
1322          printk("Found WD33c93A chip: microcode=%02x\n",hostdata->microcode);
1323          break;
1324       case C_WD33C93B:
1325          printk("Found WD33c93B chip: microcode=%02x\n",hostdata->microcode);
1326          break;
1327       default:
1328          printk("Unknown 3393 chip!\n");
1329       }
1330    printk("wd33c93-%d: LEVEL2 commands %s (%d)\n",instance->host_no,
1331             (hostdata->level2 == L2_NONE)?"disabled":"enabled",
1332             hostdata->level2);
1333 #ifdef DEBUGGING_ON
1334    printk("wd33c93-%d: debug_flags = %04x\n",instance->host_no,hostdata->args);
1335 #endif
1336    printk("wd33c93-%d: driver version %s - %s\n",instance->host_no,
1337                      WD33C93_VERSION,WD33C93_DATE);
1338 }
1339 

/* [previous][next][first][last][top][bottom][index][help] */