Annotation of Gnu-Mach/linux/src/drivers/scsi/in2000.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *    in2000.c -  Linux device driver for the
        !             3:  *                Always IN2000 ISA SCSI card.
        !             4:  *
        !             5:  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
        !             6:  *    [email protected]
        !             7:  *    [email protected]
        !             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 provided
        !            21:  * much of the inspiration and some of the code for this driver.
        !            22:  * The Linux IN2000 driver distributed in the Linux kernels through
        !            23:  * version 1.2.13 was an extremely valuable reference on the arcane
        !            24:  * (and still mysterious) workings of the IN2000's fifo. It also
        !            25:  * is where I lifted in2000_biosparam(), the gist of the card
        !            26:  * detection scheme, and other bits of code. Many thanks to the
        !            27:  * talented and courageous people who wrote, contributed to, and
        !            28:  * maintained that driver (including Brad McLean, Shaun Savage,
        !            29:  * Bill Earnest, Larry Doolittle, Roger Sunshine, John Luckey,
        !            30:  * Matt Postiff, Peter Lu, [email protected], and Eric
        !            31:  * Youngdale). I should also mention the driver written by
        !            32:  * Hamish Macdonald for the (GASP!) Amiga A2091 card, included
        !            33:  * in the Linux-m68k distribution; it gave me a good initial
        !            34:  * understanding of the proper way to run a WD33c93 chip, and I
        !            35:  * ended up stealing lots of code from it.
        !            36:  *
        !            37:  * _This_ driver is (I feel) an improvement over the old one in
        !            38:  * several respects:
        !            39:  *    -  All problems relating to the data size of a SCSI request are
        !            40:  *          gone (as far as I know). The old driver couldn't handle
        !            41:  *          swapping to partitions because that involved 4k blocks, nor
        !            42:  *          could it deal with the st.c tape driver unmodified, because
        !            43:  *          that usually involved 4k - 32k blocks. The old driver never
        !            44:  *          quite got away from a morbid dependence on 2k block sizes -
        !            45:  *          which of course is the size of the card's fifo.
        !            46:  *
        !            47:  *    -  Target Disconnection/Reconnection is now supported. Any
        !            48:  *          system with more than one device active on the SCSI bus
        !            49:  *          will benefit from this. The driver defaults to what I'm
        !            50:  *          calling 'adaptive disconnect' - meaning that each command
        !            51:  *          is evaluated individually as to whether or not it should
        !            52:  *          be run with the option to disconnect/reselect (if the
        !            53:  *          device chooses), or as a "SCSI-bus-hog".
        !            54:  *
        !            55:  *    -  Synchronous data transfers are now supported. Because there
        !            56:  *          are a few devices (and many improperly terminated systems)
        !            57:  *          that choke when doing sync, the default is sync DISABLED
        !            58:  *          for all devices. This faster protocol can (and should!)
        !            59:  *          be enabled on selected devices via the command-line.
        !            60:  *
        !            61:  *    -  Runtime operating parameters can now be specified through
        !            62:  *       either the LILO or the 'insmod' command line. For LILO do:
        !            63:  *          "in2000=blah,blah,blah"
        !            64:  *       and with insmod go like:
        !            65:  *          "insmod /usr/src/linux/modules/in2000.o setup_strings=blah,blah"
        !            66:  *       The defaults should be good for most people. See the comment
        !            67:  *       for 'setup_strings' below for more details.
        !            68:  *
        !            69:  *    -  The old driver relied exclusively on what the Western Digital
        !            70:  *          docs call "Combination Level 2 Commands", which are a great
        !            71:  *          idea in that the CPU is relieved of a lot of interrupt
        !            72:  *          overhead. However, by accepting a certain (user-settable)
        !            73:  *          amount of additional interrupts, this driver achieves
        !            74:  *          better control over the SCSI bus, and data transfers are
        !            75:  *          almost as fast while being much easier to define, track,
        !            76:  *          and debug.
        !            77:  *
        !            78:  *    -  You can force detection of a card whose BIOS has been disabled.
        !            79:  *
        !            80:  *    -  Multiple IN2000 cards might almost be supported. I've tried to
        !            81:  *       keep it in mind, but have no way to test...
        !            82:  *
        !            83:  *
        !            84:  * TODO:
        !            85:  *       tagged queuing. multiple cards.
        !            86:  *
        !            87:  *
        !            88:  * NOTE:
        !            89:  *       When using this or any other SCSI driver as a module, you'll
        !            90:  *       find that with the stock kernel, at most _two_ SCSI hard
        !            91:  *       drives will be linked into the device list (ie, usable).
        !            92:  *       If your IN2000 card has more than 2 disks on its bus, you
        !            93:  *       might want to change the define of 'SD_EXTRA_DEVS' in the
        !            94:  *       'hosts.h' file from 2 to whatever is appropriate. It took
        !            95:  *       me a while to track down this surprisingly obscure and
        !            96:  *       undocumented little "feature".
        !            97:  *
        !            98:  *
        !            99:  * People with bug reports, wish-lists, complaints, comments,
        !           100:  * or improvements are asked to pah-leeez email me (John Shifflett)
        !           101:  * at [email protected] or [email protected]! I'm anxious to get
        !           102:  * this thing into as good a shape as possible, and I'm positive
        !           103:  * there are lots of lurking bugs and "Stupid Places".
        !           104:  *
        !           105:  */
        !           106: 
        !           107: #include <linux/module.h>
        !           108: 
        !           109: #include <asm/system.h>
        !           110: #include <linux/sched.h>
        !           111: #include <linux/string.h>
        !           112: #include <linux/delay.h>
        !           113: #include <linux/proc_fs.h>
        !           114: #include <asm/io.h>
        !           115: #include <linux/ioport.h>
        !           116: #include <linux/blkdev.h>
        !           117: 
        !           118: #include <linux/blk.h>
        !           119: #include <linux/stat.h>
        !           120: 
        !           121: #include "scsi.h"
        !           122: #include "sd.h"
        !           123: #include "hosts.h"
        !           124: 
        !           125: #define IN2000_VERSION    "1.33"
        !           126: #define IN2000_DATE       "26/August/1998"
        !           127: 
        !           128: #include "in2000.h"
        !           129: 
        !           130: 
        !           131: /*
        !           132:  * 'setup_strings' is a single string used to pass operating parameters and
        !           133:  * settings from the kernel/module command-line to the driver. 'setup_args[]'
        !           134:  * is an array of strings that define the compile-time default values for
        !           135:  * these settings. If Linux boots with a LILO or insmod command-line, those
        !           136:  * settings are combined with 'setup_args[]'. Note that LILO command-lines
        !           137:  * are prefixed with "in2000=" while insmod uses a "setup_strings=" prefix.
        !           138:  * The driver recognizes the following keywords (lower case required) and
        !           139:  * arguments:
        !           140:  *
        !           141:  * -  ioport:addr    -Where addr is IO address of a (usually ROM-less) card.
        !           142:  * -  noreset        -No optional args. Prevents SCSI bus reset at boot time.
        !           143:  * -  nosync:x       -x is a bitmask where the 1st 7 bits correspond with
        !           144:  *                    the 7 possible SCSI devices (bit 0 for device #0, etc).
        !           145:  *                    Set a bit to PREVENT sync negotiation on that device.
        !           146:  *                    The driver default is sync DISABLED on all devices.
        !           147:  * -  period:ns      -ns is the minimum # of nanoseconds in a SCSI data transfer
        !           148:  *                    period. Default is 500; acceptable values are 250 - 1000.
        !           149:  * -  disconnect:x   -x = 0 to never allow disconnects, 2 to always allow them.
        !           150:  *                    x = 1 does 'adaptive' disconnects, which is the default
        !           151:  *                    and generally the best choice.
        !           152:  * -  debug:x        -If 'DEBUGGING_ON' is defined, x is a bitmask that causes
        !           153:  *                    various types of debug output to printed - see the DB_xxx
        !           154:  *                    defines in in2000.h
        !           155:  * -  proc:x         -If 'PROC_INTERFACE' is defined, x is a bitmask that
        !           156:  *                    determines how the /proc interface works and what it
        !           157:  *                    does - see the PR_xxx defines in in2000.h
        !           158:  *
        !           159:  * Syntax Notes:
        !           160:  * -  Numeric arguments can be decimal or the '0x' form of hex notation. There
        !           161:  *    _must_ be a colon between a keyword and its numeric argument, with no
        !           162:  *    spaces.
        !           163:  * -  Keywords are separated by commas, no spaces, in the standard kernel
        !           164:  *    command-line manner.
        !           165:  * -  A keyword in the 'nth' comma-separated command-line member will overwrite
        !           166:  *    the 'nth' element of setup_args[]. A blank command-line member (in
        !           167:  *    other words, a comma with no preceding keyword) will _not_ overwrite
        !           168:  *    the corresponding setup_args[] element.
        !           169:  *
        !           170:  * A few LILO examples (for insmod, use 'setup_strings' instead of 'in2000'):
        !           171:  * -  in2000=ioport:0x220,noreset
        !           172:  * -  in2000=period:250,disconnect:2,nosync:0x03
        !           173:  * -  in2000=debug:0x1e
        !           174:  * -  in2000=proc:3
        !           175:  */
        !           176: 
        !           177: /* Normally, no defaults are specified... */
        !           178: static char *setup_args[] =
        !           179:       {"","","","","","","","",""};
        !           180: 
        !           181: /* filled in by 'insmod' */
        !           182: static char *setup_strings = 0;
        !           183: 
        !           184: #ifdef MODULE_PARM
        !           185: MODULE_PARM(setup_strings, "s");
        !           186: #endif
        !           187: 
        !           188: 
        !           189: static struct Scsi_Host *instance_list = 0;
        !           190: 
        !           191: 
        !           192: 
        !           193: static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num)
        !           194: {
        !           195:    write1_io(reg_num,IO_WD_ADDR);
        !           196:    return read1_io(IO_WD_DATA);
        !           197: }
        !           198: 
        !           199: 
        !           200: #define READ_AUX_STAT() read1_io(IO_WD_ASR)
        !           201: 
        !           202: 
        !           203: static inline void write_3393(struct IN2000_hostdata *hostdata, uchar reg_num, uchar value)
        !           204: {
        !           205:    write1_io(reg_num,IO_WD_ADDR);
        !           206:    write1_io(value,IO_WD_DATA);
        !           207: }
        !           208: 
        !           209: 
        !           210: static inline void write_3393_cmd(struct IN2000_hostdata *hostdata, uchar cmd)
        !           211: {
        !           212: /*   while (READ_AUX_STAT() & ASR_CIP)
        !           213:       printk("|");*/
        !           214:    write1_io(WD_COMMAND,IO_WD_ADDR);
        !           215:    write1_io(cmd,IO_WD_DATA);
        !           216: }
        !           217: 
        !           218: 
        !           219: static uchar read_1_byte(struct IN2000_hostdata *hostdata)
        !           220: {
        !           221: uchar asr, x = 0;
        !           222: 
        !           223:    write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        !           224:    write_3393_cmd(hostdata,WD_CMD_TRANS_INFO|0x80);
        !           225:    do {
        !           226:       asr = READ_AUX_STAT();
        !           227:       if (asr & ASR_DBR)
        !           228:          x = read_3393(hostdata,WD_DATA);
        !           229:       } while (!(asr & ASR_INT));
        !           230:    return x;
        !           231: }
        !           232: 
        !           233: 
        !           234: static void write_3393_count(struct IN2000_hostdata *hostdata, unsigned long value)
        !           235: {
        !           236:    write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR);
        !           237:    write1_io((value >> 16),IO_WD_DATA);
        !           238:    write1_io((value >> 8),IO_WD_DATA);
        !           239:    write1_io(value,IO_WD_DATA);
        !           240: }
        !           241: 
        !           242: 
        !           243: static unsigned long read_3393_count(struct IN2000_hostdata *hostdata)
        !           244: {
        !           245: unsigned long value;
        !           246: 
        !           247:    write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR);
        !           248:    value = read1_io(IO_WD_DATA) << 16;
        !           249:    value |= read1_io(IO_WD_DATA) << 8;
        !           250:    value |= read1_io(IO_WD_DATA);
        !           251:    return value;
        !           252: }
        !           253: 
        !           254: 
        !           255: /* The 33c93 needs to be told which direction a command transfers its
        !           256:  * data; we use this function to figure it out. Returns true if there
        !           257:  * will be a DATA_OUT phase with this command, false otherwise.
        !           258:  * (Thanks to Joerg Dorchain for the research and suggestion.)
        !           259:  */
        !           260: static int is_dir_out(Scsi_Cmnd *cmd)
        !           261: {
        !           262:    switch (cmd->cmnd[0]) {
        !           263:       case WRITE_6:           case WRITE_10:          case WRITE_12:
        !           264:       case WRITE_LONG:        case WRITE_SAME:        case WRITE_BUFFER:
        !           265:       case WRITE_VERIFY:      case WRITE_VERIFY_12:      
        !           266:       case COMPARE:           case COPY:              case COPY_VERIFY:
        !           267:       case SEARCH_EQUAL:      case SEARCH_HIGH:       case SEARCH_LOW:
        !           268:       case SEARCH_EQUAL_12:   case SEARCH_HIGH_12:    case SEARCH_LOW_12:      
        !           269:       case FORMAT_UNIT:       case REASSIGN_BLOCKS:   case RESERVE:
        !           270:       case MODE_SELECT:       case MODE_SELECT_10:    case LOG_SELECT:
        !           271:       case SEND_DIAGNOSTIC:   case CHANGE_DEFINITION: case UPDATE_BLOCK:
        !           272:       case SET_WINDOW:        case MEDIUM_SCAN:       case SEND_VOLUME_TAG:
        !           273:       case 0xea:
        !           274:          return 1;
        !           275:       default:
        !           276:          return 0;
        !           277:       }
        !           278: }
        !           279: 
        !           280: 
        !           281: 
        !           282: static struct sx_period sx_table[] = {
        !           283:    {  1, 0x20},
        !           284:    {252, 0x20},
        !           285:    {376, 0x30},
        !           286:    {500, 0x40},
        !           287:    {624, 0x50},
        !           288:    {752, 0x60},
        !           289:    {876, 0x70},
        !           290:    {1000,0x00},
        !           291:    {0,   0} };
        !           292: 
        !           293: static int round_period(unsigned int period)
        !           294: {
        !           295: int x;
        !           296: 
        !           297:    for (x=1; sx_table[x].period_ns; x++) {
        !           298:       if ((period <= sx_table[x-0].period_ns) &&
        !           299:           (period >  sx_table[x-1].period_ns)) {
        !           300:          return x;
        !           301:          }
        !           302:       }
        !           303:    return 7;
        !           304: }
        !           305: 
        !           306: static uchar calc_sync_xfer(unsigned int period, unsigned int offset)
        !           307: {
        !           308: uchar result;
        !           309: 
        !           310:    period *= 4;   /* convert SDTR code to ns */
        !           311:    result = sx_table[round_period(period)].reg_value;
        !           312:    result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF;
        !           313:    return result;
        !           314: }
        !           315: 
        !           316: 
        !           317: 
        !           318: static void in2000_execute(struct Scsi_Host *instance);
        !           319: 
        !           320: int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
        !           321: {
        !           322: struct IN2000_hostdata *hostdata;
        !           323: Scsi_Cmnd *tmp;
        !           324: unsigned long flags;
        !           325: 
        !           326:    hostdata = (struct IN2000_hostdata *)cmd->host->hostdata;
        !           327: 
        !           328: DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
        !           329: 
        !           330: /* Set up a few fields in the Scsi_Cmnd structure for our own use:
        !           331:  *  - host_scribble is the pointer to the next cmd in the input queue
        !           332:  *  - scsi_done points to the routine we call when a cmd is finished
        !           333:  *  - result is what you'd expect
        !           334:  */
        !           335: 
        !           336:    cmd->host_scribble = NULL;
        !           337:    cmd->scsi_done = done;
        !           338:    cmd->result = 0;
        !           339: 
        !           340: /* We use the Scsi_Pointer structure that's included with each command
        !           341:  * as a scratchpad (as it's intended to be used!). The handy thing about
        !           342:  * the SCp.xxx fields is that they're always associated with a given
        !           343:  * cmd, and are preserved across disconnect-reselect. This means we
        !           344:  * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages
        !           345:  * if we keep all the critical pointers and counters in SCp:
        !           346:  *  - SCp.ptr is the pointer into the RAM buffer
        !           347:  *  - SCp.this_residual is the size of that buffer
        !           348:  *  - SCp.buffer points to the current scatter-gather buffer
        !           349:  *  - SCp.buffers_residual tells us how many S.G. buffers there are
        !           350:  *  - SCp.have_data_in helps keep track of >2048 byte transfers
        !           351:  *  - SCp.sent_command is not used
        !           352:  *  - SCp.phase records this command's SRCID_ER bit setting
        !           353:  */
        !           354: 
        !           355:    if (cmd->use_sg) {
        !           356:       cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
        !           357:       cmd->SCp.buffers_residual = cmd->use_sg - 1;
        !           358:       cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
        !           359:       cmd->SCp.this_residual = cmd->SCp.buffer->length;
        !           360:       }
        !           361:    else {
        !           362:       cmd->SCp.buffer = NULL;
        !           363:       cmd->SCp.buffers_residual = 0;
        !           364:       cmd->SCp.ptr = (char *)cmd->request_buffer;
        !           365:       cmd->SCp.this_residual = cmd->request_bufflen;
        !           366:       }
        !           367:    cmd->SCp.have_data_in = 0;
        !           368: 
        !           369: /* We don't set SCp.phase here - that's done in in2000_execute() */
        !           370: 
        !           371: /* WD docs state that at the conclusion of a "LEVEL2" command, the
        !           372:  * status byte can be retrieved from the LUN register. Apparently,
        !           373:  * this is the case only for *uninterrupted* LEVEL2 commands! If
        !           374:  * there are any unexpected phases entered, even if they are 100%
        !           375:  * legal (different devices may choose to do things differently),
        !           376:  * the LEVEL2 command sequence is exited. This often occurs prior
        !           377:  * to receiving the status byte, in which case the driver does a
        !           378:  * status phase interrupt and gets the status byte on its own.
        !           379:  * While such a command can then be "resumed" (ie restarted to
        !           380:  * finish up as a LEVEL2 command), the LUN register will NOT be
        !           381:  * a valid status byte at the command's conclusion, and we must
        !           382:  * use the byte obtained during the earlier interrupt. Here, we
        !           383:  * preset SCp.Status to an illegal value (0xff) so that when
        !           384:  * this command finally completes, we can tell where the actual
        !           385:  * status byte is stored.
        !           386:  */
        !           387: 
        !           388:    cmd->SCp.Status = ILLEGAL_STATUS_BYTE;
        !           389: 
        !           390: /* We need to disable interrupts before messing with the input
        !           391:  * queue and calling in2000_execute().
        !           392:  */
        !           393: 
        !           394:    save_flags(flags);
        !           395:    cli();
        !           396: 
        !           397:    /*
        !           398:     * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE
        !           399:     * commands are added to the head of the queue so that the desired
        !           400:     * sense data is not lost before REQUEST_SENSE executes.
        !           401:     */
        !           402: 
        !           403:    if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
        !           404:       cmd->host_scribble = (uchar *)hostdata->input_Q;
        !           405:       hostdata->input_Q = cmd;
        !           406:       }
        !           407:    else {   /* find the end of the queue */
        !           408:       for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble;
        !           409:             tmp=(Scsi_Cmnd *)tmp->host_scribble)
        !           410:          ;
        !           411:       tmp->host_scribble = (uchar *)cmd;
        !           412:       }
        !           413: 
        !           414: /* We know that there's at least one command in 'input_Q' now.
        !           415:  * Go see if any of them are runnable!
        !           416:  */
        !           417: 
        !           418:    in2000_execute(cmd->host);
        !           419: 
        !           420: DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
        !           421: 
        !           422:    restore_flags(flags);
        !           423:    return 0;
        !           424: }
        !           425: 
        !           426: 
        !           427: 
        !           428: /*
        !           429:  * This routine attempts to start a scsi command. If the host_card is
        !           430:  * already connected, we give up immediately. Otherwise, look through
        !           431:  * the input_Q, using the first command we find that's intended
        !           432:  * for a currently non-busy target/lun.
        !           433:  * Note that this function is always called with interrupts already
        !           434:  * disabled (either from in2000_queuecommand() or in2000_intr()).
        !           435:  */
        !           436: static void in2000_execute (struct Scsi_Host *instance)
        !           437: {
        !           438: struct IN2000_hostdata *hostdata;
        !           439: Scsi_Cmnd *cmd, *prev;
        !           440: int i;
        !           441: unsigned short *sp;
        !           442: unsigned short f;
        !           443: unsigned short flushbuf[16];
        !           444: 
        !           445: 
        !           446:    hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !           447: 
        !           448: DB(DB_EXECUTE,printk("EX("))
        !           449: 
        !           450:    if (hostdata->selecting || hostdata->connected) {
        !           451: 
        !           452: DB(DB_EXECUTE,printk(")EX-0 "))
        !           453: 
        !           454:       return;
        !           455:       }
        !           456: 
        !           457:     /*
        !           458:      * Search through the input_Q for a command destined
        !           459:      * for an idle target/lun.
        !           460:      */
        !           461: 
        !           462:    cmd = (Scsi_Cmnd *)hostdata->input_Q;
        !           463:    prev = 0;
        !           464:    while (cmd) {
        !           465:       if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
        !           466:          break;
        !           467:       prev = cmd;
        !           468:       cmd = (Scsi_Cmnd *)cmd->host_scribble;
        !           469:       }
        !           470: 
        !           471:    /* quit if queue empty or all possible targets are busy */
        !           472: 
        !           473:    if (!cmd) {
        !           474: 
        !           475: DB(DB_EXECUTE,printk(")EX-1 "))
        !           476: 
        !           477:       return;
        !           478:       }
        !           479: 
        !           480:    /*  remove command from queue */
        !           481:    
        !           482:    if (prev)
        !           483:       prev->host_scribble = cmd->host_scribble;
        !           484:    else
        !           485:       hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
        !           486: 
        !           487: #ifdef PROC_STATISTICS
        !           488:    hostdata->cmd_cnt[cmd->target]++;
        !           489: #endif
        !           490: 
        !           491: /*
        !           492:  * Start the selection process
        !           493:  */
        !           494: 
        !           495:    if (is_dir_out(cmd))
        !           496:       write_3393(hostdata,WD_DESTINATION_ID, cmd->target);
        !           497:    else
        !           498:       write_3393(hostdata,WD_DESTINATION_ID, cmd->target | DSTID_DPD);
        !           499: 
        !           500: /* Now we need to figure out whether or not this command is a good
        !           501:  * candidate for disconnect/reselect. We guess to the best of our
        !           502:  * ability, based on a set of hierarchical rules. When several
        !           503:  * devices are operating simultaneously, disconnects are usually
        !           504:  * an advantage. In a single device system, or if only 1 device
        !           505:  * is being accessed, transfers usually go faster if disconnects
        !           506:  * are not allowed:
        !           507:  *
        !           508:  * + Commands should NEVER disconnect if hostdata->disconnect =
        !           509:  *   DIS_NEVER (this holds for tape drives also), and ALWAYS
        !           510:  *   disconnect if hostdata->disconnect = DIS_ALWAYS.
        !           511:  * + Tape drive commands should always be allowed to disconnect.
        !           512:  * + Disconnect should be allowed if disconnected_Q isn't empty.
        !           513:  * + Commands should NOT disconnect if input_Q is empty.
        !           514:  * + Disconnect should be allowed if there are commands in input_Q
        !           515:  *   for a different target/lun. In this case, the other commands
        !           516:  *   should be made disconnect-able, if not already.
        !           517:  *
        !           518:  * I know, I know - this code would flunk me out of any
        !           519:  * "C Programming 101" class ever offered. But it's easy
        !           520:  * to change around and experiment with for now.
        !           521:  */
        !           522: 
        !           523:    cmd->SCp.phase = 0;  /* assume no disconnect */
        !           524:    if (hostdata->disconnect == DIS_NEVER)
        !           525:       goto no;
        !           526:    if (hostdata->disconnect == DIS_ALWAYS)
        !           527:       goto yes;
        !           528:    if (cmd->device->type == 1)   /* tape drive? */
        !           529:       goto yes;
        !           530:    if (hostdata->disconnected_Q) /* other commands disconnected? */
        !           531:       goto yes;
        !           532:    if (!(hostdata->input_Q))     /* input_Q empty? */
        !           533:       goto no;
        !           534:    for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
        !           535:          prev=(Scsi_Cmnd *)prev->host_scribble) {
        !           536:       if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) {
        !           537:          for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
        !           538:                prev=(Scsi_Cmnd *)prev->host_scribble)
        !           539:             prev->SCp.phase = 1;
        !           540:          goto yes;
        !           541:          }
        !           542:       }
        !           543:    goto no;
        !           544: 
        !           545: yes:
        !           546:    cmd->SCp.phase = 1;
        !           547: 
        !           548: #ifdef PROC_STATISTICS
        !           549:    hostdata->disc_allowed_cnt[cmd->target]++;
        !           550: #endif
        !           551: 
        !           552: no:
        !           553:    write_3393(hostdata,WD_SOURCE_ID,((cmd->SCp.phase)?SRCID_ER:0));
        !           554: 
        !           555:    write_3393(hostdata,WD_TARGET_LUN, cmd->lun);
        !           556:    write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
        !           557:    hostdata->busy[cmd->target] |= (1 << cmd->lun);
        !           558: 
        !           559:    if ((hostdata->level2 <= L2_NONE) ||
        !           560:        (hostdata->sync_stat[cmd->target] == SS_UNSET)) {
        !           561: 
        !           562:          /*
        !           563:           * Do a 'Select-With-ATN' command. This will end with
        !           564:           * one of the following interrupts:
        !           565:           *    CSR_RESEL_AM:  failure - can try again later.
        !           566:           *    CSR_TIMEOUT:   failure - give up.
        !           567:           *    CSR_SELECT:    success - proceed.
        !           568:           */
        !           569: 
        !           570:       hostdata->selecting = cmd;
        !           571: 
        !           572: /* Every target has its own synchronous transfer setting, kept in
        !           573:  * the sync_xfer array, and a corresponding status byte in sync_stat[].
        !           574:  * Each target's sync_stat[] entry is initialized to SS_UNSET, and its
        !           575:  * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
        !           576:  * means that the parameters are undetermined as yet, and that we
        !           577:  * need to send an SDTR message to this device after selection is
        !           578:  * complete. We set SS_FIRST to tell the interrupt routine to do so,
        !           579:  * unless we don't want to even _try_ synchronous transfers: In this
        !           580:  * case we set SS_SET to make the defaults final.
        !           581:  */
        !           582:       if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
        !           583:          if (hostdata->sync_off & (1 << cmd->target))
        !           584:             hostdata->sync_stat[cmd->target] = SS_SET;
        !           585:          else
        !           586:             hostdata->sync_stat[cmd->target] = SS_FIRST;
        !           587:          }
        !           588:       hostdata->state = S_SELECTING;
        !           589:       write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */
        !           590:       write_3393_cmd(hostdata,WD_CMD_SEL_ATN);
        !           591:       }
        !           592: 
        !           593:    else {
        !           594: 
        !           595:          /*
        !           596:           * Do a 'Select-With-ATN-Xfer' command. This will end with
        !           597:           * one of the following interrupts:
        !           598:           *    CSR_RESEL_AM:  failure - can try again later.
        !           599:           *    CSR_TIMEOUT:   failure - give up.
        !           600:           *    anything else: success - proceed.
        !           601:           */
        !           602: 
        !           603:       hostdata->connected = cmd;
        !           604:       write_3393(hostdata,WD_COMMAND_PHASE, 0);
        !           605: 
        !           606:    /* copy command_descriptor_block into WD chip
        !           607:     * (take advantage of auto-incrementing)
        !           608:     */
        !           609: 
        !           610:       write1_io(WD_CDB_1, IO_WD_ADDR);
        !           611:       for (i=0; i<cmd->cmd_len; i++)
        !           612:          write1_io(cmd->cmnd[i], IO_WD_DATA);
        !           613: 
        !           614:    /* The wd33c93 only knows about Group 0, 1, and 5 commands when
        !           615:     * it's doing a 'select-and-transfer'. To be safe, we write the
        !           616:     * size of the CDB into the OWN_ID register for every case. This
        !           617:     * way there won't be problems with vendor-unique, audio, etc.
        !           618:     */
        !           619: 
        !           620:       write_3393(hostdata, WD_OWN_ID, cmd->cmd_len);
        !           621: 
        !           622:    /* When doing a non-disconnect command, we can save ourselves a DATA
        !           623:     * phase interrupt later by setting everything up now. With writes we
        !           624:     * need to pre-fill the fifo; if there's room for the 32 flush bytes,
        !           625:     * put them in there too - that'll avoid a fifo interrupt. Reads are
        !           626:     * somewhat simpler.
        !           627:     * KLUDGE NOTE: It seems that you can't completely fill the fifo here:
        !           628:     * This results in the IO_FIFO_COUNT register rolling over to zero,
        !           629:     * and apparently the gate array logic sees this as empty, not full,
        !           630:     * so the 3393 chip is never signalled to start reading from the
        !           631:     * fifo. Or maybe it's seen as a permanent fifo interrupt condition.
        !           632:     * Regardless, we fix this by temporarily pretending that the fifo
        !           633:     * is 16 bytes smaller. (I see now that the old driver has a comment
        !           634:     * about "don't fill completely" in an analogous place - must be the
        !           635:     * same deal.) This results in CDROM, swap partitions, and tape drives
        !           636:     * needing an extra interrupt per write command - I think we can live
        !           637:     * with that!
        !           638:     */
        !           639: 
        !           640:       if (!(cmd->SCp.phase)) {
        !           641:          write_3393_count(hostdata, cmd->SCp.this_residual);
        !           642:          write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS);
        !           643:          write1_io(0, IO_FIFO_WRITE);  /* clear fifo counter, write mode */
        !           644: 
        !           645:          if (is_dir_out(cmd)) {
        !           646:             hostdata->fifo = FI_FIFO_WRITING;
        !           647:             if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16) )
        !           648:                i = IN2000_FIFO_SIZE - 16;
        !           649:             cmd->SCp.have_data_in = i;    /* this much data in fifo */
        !           650:             i >>= 1;                      /* Gulp. Assuming modulo 2. */
        !           651:             sp = (unsigned short *)cmd->SCp.ptr;
        !           652:             f = hostdata->io_base + IO_FIFO;
        !           653: 
        !           654: #ifdef FAST_WRITE_IO
        !           655: 
        !           656:             FAST_WRITE2_IO();
        !           657: #else
        !           658:             while (i--)
        !           659:                write2_io(*sp++,IO_FIFO);
        !           660: 
        !           661: #endif
        !           662: 
        !           663:       /* Is there room for the flush bytes? */
        !           664: 
        !           665:             if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) {
        !           666:                sp = flushbuf;
        !           667:                i = 16;
        !           668: 
        !           669: #ifdef FAST_WRITE_IO
        !           670: 
        !           671:                FAST_WRITE2_IO();
        !           672: #else
        !           673:                while (i--)
        !           674:                   write2_io(0,IO_FIFO);
        !           675: 
        !           676: #endif
        !           677: 
        !           678:                }
        !           679:             }
        !           680: 
        !           681:          else {
        !           682:             write1_io(0, IO_FIFO_READ);   /* put fifo in read mode */
        !           683:             hostdata->fifo = FI_FIFO_READING;
        !           684:             cmd->SCp.have_data_in = 0;    /* nothing transfered yet */
        !           685:             }
        !           686: 
        !           687:          }
        !           688:       else {
        !           689:          write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */
        !           690:          }
        !           691:       hostdata->state = S_RUNNING_LEVEL2;
        !           692:       write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !           693:       }
        !           694: 
        !           695:    /*
        !           696:     * Since the SCSI bus can handle only 1 connection at a time,
        !           697:     * we get out of here now. If the selection fails, or when
        !           698:     * the command disconnects, we'll come back to this routine
        !           699:     * to search the input_Q again...
        !           700:     */
        !           701:       
        !           702: DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
        !           703: 
        !           704: }
        !           705: 
        !           706: 
        !           707: 
        !           708: static void transfer_pio(uchar *buf, int cnt,
        !           709:                   int data_in_dir, struct IN2000_hostdata *hostdata)
        !           710: {
        !           711: uchar asr;
        !           712: 
        !           713: DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out"))
        !           714: 
        !           715:    write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        !           716:    write_3393_count(hostdata,cnt);
        !           717:    write_3393_cmd(hostdata,WD_CMD_TRANS_INFO);
        !           718:    if (data_in_dir) {
        !           719:       do {
        !           720:          asr = READ_AUX_STAT();
        !           721:          if (asr & ASR_DBR)
        !           722:             *buf++ = read_3393(hostdata,WD_DATA);
        !           723:          } while (!(asr & ASR_INT));
        !           724:       }
        !           725:    else {
        !           726:       do {
        !           727:          asr = READ_AUX_STAT();
        !           728:          if (asr & ASR_DBR)
        !           729:             write_3393(hostdata,WD_DATA, *buf++);
        !           730:          } while (!(asr & ASR_INT));
        !           731:       }
        !           732: 
        !           733:    /* Note: we are returning with the interrupt UN-cleared.
        !           734:    * Since (presumably) an entire I/O operation has
        !           735:    * completed, the bus phase is probably different, and
        !           736:    * the interrupt routine will discover this when it
        !           737:    * responds to the uncleared int.
        !           738:    */
        !           739: 
        !           740: }
        !           741: 
        !           742: 
        !           743: 
        !           744: static void transfer_bytes(Scsi_Cmnd *cmd, int data_in_dir)
        !           745: {
        !           746: struct IN2000_hostdata *hostdata;
        !           747: unsigned short *sp;
        !           748: unsigned short f;
        !           749: int i;
        !           750: 
        !           751:    hostdata = (struct IN2000_hostdata *)cmd->host->hostdata;
        !           752: 
        !           753: /* Normally, you'd expect 'this_residual' to be non-zero here.
        !           754:  * In a series of scatter-gather transfers, however, this
        !           755:  * routine will usually be called with 'this_residual' equal
        !           756:  * to 0 and 'buffers_residual' non-zero. This means that a
        !           757:  * previous transfer completed, clearing 'this_residual', and
        !           758:  * now we need to setup the next scatter-gather buffer as the
        !           759:  * source or destination for THIS transfer.
        !           760:  */
        !           761:    if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
        !           762:       ++cmd->SCp.buffer;
        !           763:       --cmd->SCp.buffers_residual;
        !           764:       cmd->SCp.this_residual = cmd->SCp.buffer->length;
        !           765:       cmd->SCp.ptr = cmd->SCp.buffer->address;
        !           766:       }
        !           767: 
        !           768: /* Set up hardware registers */
        !           769: 
        !           770:    write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
        !           771:    write_3393_count(hostdata,cmd->SCp.this_residual);
        !           772:    write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS);
        !           773:    write1_io(0,IO_FIFO_WRITE); /* zero counter, assume write */
        !           774: 
        !           775: /* Reading is easy. Just issue the command and return - we'll
        !           776:  * get an interrupt later when we have actual data to worry about.
        !           777:  */
        !           778: 
        !           779:    if (data_in_dir) {
        !           780:       write1_io(0,IO_FIFO_READ);
        !           781:       if ((hostdata->level2 >= L2_DATA) ||
        !           782:           (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
        !           783:          write_3393(hostdata,WD_COMMAND_PHASE,0x45);
        !           784:          write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !           785:          hostdata->state = S_RUNNING_LEVEL2;
        !           786:          }
        !           787:       else
        !           788:          write_3393_cmd(hostdata,WD_CMD_TRANS_INFO);
        !           789:       hostdata->fifo = FI_FIFO_READING;
        !           790:       cmd->SCp.have_data_in = 0;
        !           791:       return;
        !           792:       }
        !           793: 
        !           794: /* Writing is more involved - we'll start the WD chip and write as
        !           795:  * much data to the fifo as we can right now. Later interrupts will
        !           796:  * write any bytes that don't make it at this stage.
        !           797:  */
        !           798: 
        !           799:       if ((hostdata->level2 >= L2_DATA) ||
        !           800:           (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
        !           801:       write_3393(hostdata,WD_COMMAND_PHASE,0x45);
        !           802:       write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !           803:       hostdata->state = S_RUNNING_LEVEL2;
        !           804:       }
        !           805:    else
        !           806:       write_3393_cmd(hostdata,WD_CMD_TRANS_INFO);
        !           807:    hostdata->fifo = FI_FIFO_WRITING;
        !           808:    sp = (unsigned short *)cmd->SCp.ptr;
        !           809: 
        !           810:    if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE)
        !           811:       i = IN2000_FIFO_SIZE;
        !           812:    cmd->SCp.have_data_in = i;
        !           813:    i >>= 1;    /* Gulp. We assume this_residual is modulo 2 */
        !           814:    f = hostdata->io_base + IO_FIFO;
        !           815: 
        !           816: #ifdef FAST_WRITE_IO
        !           817: 
        !           818:    FAST_WRITE2_IO();
        !           819: #else
        !           820:    while (i--)
        !           821:       write2_io(*sp++,IO_FIFO);
        !           822: 
        !           823: #endif
        !           824: 
        !           825: }
        !           826: 
        !           827: 
        !           828: /* We need to use spin_lock_irqsave() & spin_unlock_irqrestore() in this
        !           829:  * function in order to work in an SMP environment. (I'd be surprised
        !           830:  * if the driver is ever used by anyone on a real multi-CPU motherboard,
        !           831:  * but it _does_ need to be able to compile and run in an SMP kernel.)
        !           832:  */
        !           833: 
        !           834: static void in2000_intr (int irqnum, void * dev_id, struct pt_regs *ptregs)
        !           835: {
        !           836: struct Scsi_Host *instance;
        !           837: struct IN2000_hostdata *hostdata;
        !           838: Scsi_Cmnd *patch, *cmd;
        !           839: uchar asr, sr, phs, id, lun, *ucp, msg;
        !           840: int i,j;
        !           841: unsigned long length;
        !           842: unsigned short *sp;
        !           843: unsigned short f;
        !           844: unsigned long flags;
        !           845: 
        !           846:    for (instance = instance_list; instance; instance = instance->next) {
        !           847:       if (instance->irq == irqnum)
        !           848:          break;
        !           849:       }
        !           850:    if (!instance) {
        !           851:       printk("*** Hmm... interrupts are screwed up! ***\n");
        !           852:       return;
        !           853:       }
        !           854:    hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !           855: 
        !           856: /* Get the spin_lock and disable further ints, for SMP */
        !           857: 
        !           858:    CLISPIN_LOCK(flags);
        !           859: 
        !           860: #ifdef PROC_STATISTICS
        !           861:    hostdata->int_cnt++;
        !           862: #endif
        !           863: 
        !           864: /* The IN2000 card has 2 interrupt sources OR'ed onto its IRQ line - the
        !           865:  * WD3393 chip and the 2k fifo (which is actually a dual-port RAM combined
        !           866:  * with a big logic array, so it's a little different than what you might
        !           867:  * expect). As far as I know, there's no reason that BOTH can't be active
        !           868:  * at the same time, but there's a problem: while we can read the 3393
        !           869:  * to tell if _it_ wants an interrupt, I don't know of a way to ask the
        !           870:  * fifo the same question. The best we can do is check the 3393 and if
        !           871:  * it _isn't_ the source of the interrupt, then we can be pretty sure
        !           872:  * that the fifo is the culprit.
        !           873:  *  UPDATE: I have it on good authority (Bill Earnest) that bit 0 of the
        !           874:  *          IO_FIFO_COUNT register mirrors the fifo interrupt state. I
        !           875:  *          assume that bit clear means interrupt active. As it turns
        !           876:  *          out, the driver really doesn't need to check for this after
        !           877:  *          all, so my remarks above about a 'problem' can safely be
        !           878:  *          ignored. The way the logic is set up, there's no advantage
        !           879:  *          (that I can see) to worrying about it.
        !           880:  *
        !           881:  * It seems that the fifo interrupt signal is negated when we extract
        !           882:  * bytes during read or write bytes during write.
        !           883:  *  - fifo will interrupt when data is moving from it to the 3393, and
        !           884:  *    there are 31 (or less?) bytes left to go. This is sort of short-
        !           885:  *    sighted: what if you don't WANT to do more? In any case, our
        !           886:  *    response is to push more into the fifo - either actual data or
        !           887:  *    dummy bytes if need be. Note that we apparently have to write at
        !           888:  *    least 32 additional bytes to the fifo after an interrupt in order
        !           889:  *    to get it to release the ones it was holding on to - writing fewer
        !           890:  *    than 32 will result in another fifo int.
        !           891:  *  UPDATE: Again, info from Bill Earnest makes this more understandable:
        !           892:  *          32 bytes = two counts of the fifo counter register. He tells
        !           893:  *          me that the fifo interrupt is a non-latching signal derived
        !           894:  *          from a straightforward boolean interpretation of the 7
        !           895:  *          highest bits of the fifo counter and the fifo-read/fifo-write
        !           896:  *          state. Who'd a thought?
        !           897:  */
        !           898: 
        !           899:    write1_io(0, IO_LED_ON);
        !           900:    asr = READ_AUX_STAT();
        !           901:    if (!(asr & ASR_INT)) {    /* no WD33c93 interrupt? */
        !           902: 
        !           903: /* Ok. This is definitely a FIFO-only interrupt.
        !           904:  *
        !           905:  * If FI_FIFO_READING is set, there are up to 2048 bytes waiting to be read,
        !           906:  * maybe more to come from the SCSI bus. Read as many as we can out of the
        !           907:  * fifo and into memory at the location of SCp.ptr[SCp.have_data_in], and
        !           908:  * update have_data_in afterwards.
        !           909:  *
        !           910:  * If we have FI_FIFO_WRITING, the FIFO has almost run out of bytes to move
        !           911:  * into the WD3393 chip (I think the interrupt happens when there are 31
        !           912:  * bytes left, but it may be fewer...). The 3393 is still waiting, so we
        !           913:  * shove some more into the fifo, which gets things moving again. If the
        !           914:  * original SCSI command specified more than 2048 bytes, there may still
        !           915:  * be some of that data left: fine - use it (from SCp.ptr[SCp.have_data_in]).
        !           916:  * Don't forget to update have_data_in. If we've already written out the
        !           917:  * entire buffer, feed 32 dummy bytes to the fifo - they're needed to
        !           918:  * push out the remaining real data.
        !           919:  *    (Big thanks to Bill Earnest for getting me out of the mud in here.)
        !           920:  */
        !           921: 
        !           922:       cmd = (Scsi_Cmnd *)hostdata->connected;   /* assume we're connected */
        !           923: CHECK_NULL(cmd,"fifo_int")
        !           924: 
        !           925:       if (hostdata->fifo == FI_FIFO_READING) {
        !           926: 
        !           927: DB(DB_FIFO,printk("{R:%02x} ",read1_io(IO_FIFO_COUNT)))
        !           928: 
        !           929:          sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in);
        !           930:          i = read1_io(IO_FIFO_COUNT) & 0xfe;
        !           931:          i <<= 2;    /* # of words waiting in the fifo */
        !           932:          f = hostdata->io_base + IO_FIFO;
        !           933: 
        !           934: #ifdef FAST_READ_IO
        !           935: 
        !           936:          FAST_READ2_IO();
        !           937: #else
        !           938:          while (i--)
        !           939:             *sp++ = read2_io(IO_FIFO);
        !           940: 
        !           941: #endif
        !           942: 
        !           943:          i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in);
        !           944:          i <<= 1;
        !           945:          cmd->SCp.have_data_in += i;
        !           946:          }
        !           947: 
        !           948:       else if (hostdata->fifo == FI_FIFO_WRITING) {
        !           949: 
        !           950: DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
        !           951: 
        !           952: /* If all bytes have been written to the fifo, flush out the stragglers.
        !           953:  * Note that while writing 16 dummy words seems arbitrary, we don't
        !           954:  * have another choice that I can see. What we really want is to read
        !           955:  * the 3393 transfer count register (that would tell us how many bytes
        !           956:  * needed flushing), but the TRANSFER_INFO command hasn't completed
        !           957:  * yet (not enough bytes!) and that register won't be accessible. So,
        !           958:  * we use 16 words - a number obtained through trial and error.
        !           959:  *  UPDATE: Bill says this is exactly what Always does, so there.
        !           960:  *          More thanks due him for help in this section.
        !           961:  */
        !           962: 
        !           963:          if (cmd->SCp.this_residual == cmd->SCp.have_data_in) {
        !           964:             i = 16;
        !           965:             while (i--)          /* write 32 dummy bytes */
        !           966:                write2_io(0,IO_FIFO);
        !           967:             }
        !           968: 
        !           969: /* If there are still bytes left in the SCSI buffer, write as many as we
        !           970:  * can out to the fifo.
        !           971:  */
        !           972: 
        !           973:          else {
        !           974:             sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in);
        !           975:             i = cmd->SCp.this_residual - cmd->SCp.have_data_in;   /* bytes yet to go */
        !           976:             j = read1_io(IO_FIFO_COUNT) & 0xfe;
        !           977:             j <<= 2;    /* how many words the fifo has room for */
        !           978:             if ((j << 1) > i)
        !           979:                j = (i >> 1);
        !           980:             while (j--)
        !           981:                write2_io(*sp++,IO_FIFO);
        !           982: 
        !           983:             i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in);
        !           984:             i <<= 1;
        !           985:             cmd->SCp.have_data_in += i;
        !           986:             }
        !           987:          }
        !           988: 
        !           989:       else {
        !           990:             printk("*** Spurious FIFO interrupt ***");
        !           991:             }
        !           992: 
        !           993:       write1_io(0, IO_LED_OFF);
        !           994: 
        !           995: /* release the SMP spin_lock and restore irq state */
        !           996:       CLISPIN_UNLOCK(flags);
        !           997:       return;
        !           998:       }
        !           999: 
        !          1000: /* This interrupt was triggered by the WD33c93 chip. The fifo interrupt
        !          1001:  * may also be asserted, but we don't bother to check it: we get more
        !          1002:  * detailed info from FIFO_READING and FIFO_WRITING (see below).
        !          1003:  */
        !          1004: 
        !          1005:    cmd = (Scsi_Cmnd *)hostdata->connected;   /* assume we're connected */
        !          1006:    sr = read_3393(hostdata,WD_SCSI_STATUS);  /* clear the interrupt */
        !          1007:    phs = read_3393(hostdata,WD_COMMAND_PHASE);
        !          1008: 
        !          1009:    if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) {
        !          1010:       printk("\nNR:wd-intr-1\n");
        !          1011:       write1_io(0, IO_LED_OFF);
        !          1012: 
        !          1013: /* release the SMP spin_lock and restore irq state */
        !          1014:       CLISPIN_UNLOCK(flags);
        !          1015:       return;
        !          1016:       }
        !          1017: 
        !          1018: DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
        !          1019: 
        !          1020: /* After starting a FIFO-based transfer, the next _WD3393_ interrupt is
        !          1021:  * guaranteed to be in response to the completion of the transfer.
        !          1022:  * If we were reading, there's probably data in the fifo that needs
        !          1023:  * to be copied into RAM - do that here. Also, we have to update
        !          1024:  * 'this_residual' and 'ptr' based on the contents of the
        !          1025:  * TRANSFER_COUNT register, in case the device decided to do an
        !          1026:  * intermediate disconnect (a device may do this if it has to
        !          1027:  * do a seek,  or just to be nice and let other devices have
        !          1028:  * some bus time during long transfers).
        !          1029:  * After doing whatever is necessary with the fifo, we go on and
        !          1030:  * service the WD3393 interrupt normally.
        !          1031:  */
        !          1032: 
        !          1033:    if (hostdata->fifo == FI_FIFO_READING) {
        !          1034: 
        !          1035: /* buffer index = start-of-buffer + #-of-bytes-already-read */
        !          1036: 
        !          1037:       sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in);
        !          1038: 
        !          1039: /* bytes remaining in fifo = (total-wanted - #-not-got) - #-already-read */
        !          1040: 
        !          1041:       i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in;
        !          1042:       i >>= 1;    /* Gulp. We assume this will always be modulo 2 */
        !          1043:       f = hostdata->io_base + IO_FIFO;
        !          1044: 
        !          1045: #ifdef FAST_READ_IO
        !          1046: 
        !          1047:       FAST_READ2_IO();
        !          1048: #else
        !          1049:       while (i--)
        !          1050:          *sp++ = read2_io(IO_FIFO);
        !          1051: 
        !          1052: #endif
        !          1053: 
        !          1054:       hostdata->fifo = FI_FIFO_UNUSED;
        !          1055:       length = cmd->SCp.this_residual;
        !          1056:       cmd->SCp.this_residual = read_3393_count(hostdata);
        !          1057:       cmd->SCp.ptr += (length - cmd->SCp.this_residual);
        !          1058: 
        !          1059: DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual))
        !          1060: 
        !          1061:       }
        !          1062: 
        !          1063:    else if (hostdata->fifo == FI_FIFO_WRITING) {
        !          1064:       hostdata->fifo = FI_FIFO_UNUSED;
        !          1065:       length = cmd->SCp.this_residual;
        !          1066:       cmd->SCp.this_residual = read_3393_count(hostdata);
        !          1067:       cmd->SCp.ptr += (length - cmd->SCp.this_residual);
        !          1068: 
        !          1069: DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual))
        !          1070: 
        !          1071:       }
        !          1072: 
        !          1073: /* Respond to the specific WD3393 interrupt - there are quite a few! */
        !          1074: 
        !          1075:    switch (sr) {
        !          1076: 
        !          1077:       case CSR_TIMEOUT:
        !          1078: DB(DB_INTR,printk("TIMEOUT"))
        !          1079: 
        !          1080:          if (hostdata->state == S_RUNNING_LEVEL2)
        !          1081:             hostdata->connected = NULL;
        !          1082:          else {
        !          1083:             cmd = (Scsi_Cmnd *)hostdata->selecting;   /* get a valid cmd */
        !          1084: CHECK_NULL(cmd,"csr_timeout")
        !          1085:             hostdata->selecting = NULL;
        !          1086:             }
        !          1087: 
        !          1088:          cmd->result = DID_NO_CONNECT << 16;
        !          1089:          hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1090:          hostdata->state = S_UNCONNECTED;
        !          1091:          cmd->scsi_done(cmd);
        !          1092: 
        !          1093: /* We are not connected to a target - check to see if there
        !          1094:  * are commands waiting to be executed.
        !          1095:  */
        !          1096: 
        !          1097:          in2000_execute(instance);
        !          1098:          break;
        !          1099: 
        !          1100: 
        !          1101: /* Note: this interrupt should not occur in a LEVEL2 command */
        !          1102: 
        !          1103:       case CSR_SELECT:
        !          1104: DB(DB_INTR,printk("SELECT"))
        !          1105:          hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
        !          1106: CHECK_NULL(cmd,"csr_select")
        !          1107:          hostdata->selecting = NULL;
        !          1108: 
        !          1109:       /* construct an IDENTIFY message with correct disconnect bit */
        !          1110: 
        !          1111:          hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);
        !          1112:          if (cmd->SCp.phase)
        !          1113:             hostdata->outgoing_msg[0] |= 0x40;
        !          1114: 
        !          1115:          if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
        !          1116: #ifdef SYNC_DEBUG
        !          1117: printk(" sending SDTR ");
        !          1118: #endif
        !          1119: 
        !          1120:             hostdata->sync_stat[cmd->target] = SS_WAITING;
        !          1121: 
        !          1122:       /* tack on a 2nd message to ask about synchronous transfers */
        !          1123: 
        !          1124:             hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
        !          1125:             hostdata->outgoing_msg[2] = 3;
        !          1126:             hostdata->outgoing_msg[3] = EXTENDED_SDTR;
        !          1127:             hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
        !          1128:             hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
        !          1129:             hostdata->outgoing_len = 6;
        !          1130:             }
        !          1131:          else
        !          1132:             hostdata->outgoing_len = 1;
        !          1133: 
        !          1134:          hostdata->state = S_CONNECTED;
        !          1135:          break;
        !          1136: 
        !          1137: 
        !          1138:       case CSR_XFER_DONE|PHS_DATA_IN:
        !          1139:       case CSR_UNEXP    |PHS_DATA_IN:
        !          1140:       case CSR_SRV_REQ  |PHS_DATA_IN:
        !          1141: DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
        !          1142:          transfer_bytes(cmd, DATA_IN_DIR);
        !          1143:          if (hostdata->state != S_RUNNING_LEVEL2)
        !          1144:             hostdata->state = S_CONNECTED;
        !          1145:          break;
        !          1146: 
        !          1147: 
        !          1148:       case CSR_XFER_DONE|PHS_DATA_OUT:
        !          1149:       case CSR_UNEXP    |PHS_DATA_OUT:
        !          1150:       case CSR_SRV_REQ  |PHS_DATA_OUT:
        !          1151: DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
        !          1152:          transfer_bytes(cmd, DATA_OUT_DIR);
        !          1153:          if (hostdata->state != S_RUNNING_LEVEL2)
        !          1154:             hostdata->state = S_CONNECTED;
        !          1155:          break;
        !          1156: 
        !          1157: 
        !          1158: /* Note: this interrupt should not occur in a LEVEL2 command */
        !          1159: 
        !          1160:       case CSR_XFER_DONE|PHS_COMMAND:
        !          1161:       case CSR_UNEXP    |PHS_COMMAND:
        !          1162:       case CSR_SRV_REQ  |PHS_COMMAND:
        !          1163: DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
        !          1164:          transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
        !          1165:          hostdata->state = S_CONNECTED;
        !          1166:          break;
        !          1167: 
        !          1168: 
        !          1169:       case CSR_XFER_DONE|PHS_STATUS:
        !          1170:       case CSR_UNEXP    |PHS_STATUS:
        !          1171:       case CSR_SRV_REQ  |PHS_STATUS:
        !          1172: DB(DB_INTR,printk("STATUS="))
        !          1173: 
        !          1174:          cmd->SCp.Status = read_1_byte(hostdata);
        !          1175: DB(DB_INTR,printk("%02x",cmd->SCp.Status))
        !          1176:          if (hostdata->level2 >= L2_BASIC) {
        !          1177:             sr = read_3393(hostdata,WD_SCSI_STATUS);  /* clear interrupt */
        !          1178:             hostdata->state = S_RUNNING_LEVEL2;
        !          1179:             write_3393(hostdata,WD_COMMAND_PHASE, 0x50);
        !          1180:             write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !          1181:             }
        !          1182:          else {
        !          1183:             hostdata->state = S_CONNECTED;
        !          1184:             }
        !          1185:          break;
        !          1186: 
        !          1187: 
        !          1188:       case CSR_XFER_DONE|PHS_MESS_IN:
        !          1189:       case CSR_UNEXP    |PHS_MESS_IN:
        !          1190:       case CSR_SRV_REQ  |PHS_MESS_IN:
        !          1191: DB(DB_INTR,printk("MSG_IN="))
        !          1192: 
        !          1193:          msg = read_1_byte(hostdata);
        !          1194:          sr = read_3393(hostdata,WD_SCSI_STATUS);  /* clear interrupt */
        !          1195: 
        !          1196:          hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
        !          1197:          if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
        !          1198:             msg = EXTENDED_MESSAGE;
        !          1199:          else
        !          1200:             hostdata->incoming_ptr = 0;
        !          1201: 
        !          1202:          cmd->SCp.Message = msg;
        !          1203:          switch (msg) {
        !          1204: 
        !          1205:             case COMMAND_COMPLETE:
        !          1206: DB(DB_INTR,printk("CCMP-%ld",cmd->pid))
        !          1207:                write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1208:                hostdata->state = S_PRE_CMP_DISC;
        !          1209:                break;
        !          1210: 
        !          1211:             case SAVE_POINTERS:
        !          1212: DB(DB_INTR,printk("SDP"))
        !          1213:                write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1214:                hostdata->state = S_CONNECTED;
        !          1215:                break;
        !          1216: 
        !          1217:             case RESTORE_POINTERS:
        !          1218: DB(DB_INTR,printk("RDP"))
        !          1219:                if (hostdata->level2 >= L2_BASIC) {
        !          1220:                   write_3393(hostdata,WD_COMMAND_PHASE, 0x45);
        !          1221:                   write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !          1222:                   hostdata->state = S_RUNNING_LEVEL2;
        !          1223:                   }
        !          1224:                else {
        !          1225:                   write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1226:                   hostdata->state = S_CONNECTED;
        !          1227:                   }
        !          1228:                break;
        !          1229: 
        !          1230:             case DISCONNECT:
        !          1231: DB(DB_INTR,printk("DIS"))
        !          1232:                cmd->device->disconnect = 1;
        !          1233:                write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1234:                hostdata->state = S_PRE_TMP_DISC;
        !          1235:                break;
        !          1236: 
        !          1237:             case MESSAGE_REJECT:
        !          1238: DB(DB_INTR,printk("REJ"))
        !          1239: #ifdef SYNC_DEBUG
        !          1240: printk("-REJ-");
        !          1241: #endif
        !          1242:                if (hostdata->sync_stat[cmd->target] == SS_WAITING)
        !          1243:                   hostdata->sync_stat[cmd->target] = SS_SET;
        !          1244:                write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1245:                hostdata->state = S_CONNECTED;
        !          1246:                break;
        !          1247: 
        !          1248:             case EXTENDED_MESSAGE:
        !          1249: DB(DB_INTR,printk("EXT"))
        !          1250: 
        !          1251:                ucp = hostdata->incoming_msg;
        !          1252: 
        !          1253: #ifdef SYNC_DEBUG
        !          1254: printk("%02x",ucp[hostdata->incoming_ptr]);
        !          1255: #endif
        !          1256:          /* Is this the last byte of the extended message? */
        !          1257: 
        !          1258:                if ((hostdata->incoming_ptr >= 2) &&
        !          1259:                    (hostdata->incoming_ptr == (ucp[1] + 1))) {
        !          1260: 
        !          1261:                   switch (ucp[2]) {   /* what's the EXTENDED code? */
        !          1262:                      case EXTENDED_SDTR:
        !          1263:                         id = calc_sync_xfer(ucp[3],ucp[4]);
        !          1264:                         if (hostdata->sync_stat[cmd->target] != SS_WAITING) {
        !          1265: 
        !          1266: /* A device has sent an unsolicited SDTR message; rather than go
        !          1267:  * through the effort of decoding it and then figuring out what
        !          1268:  * our reply should be, we're just gonna say that we have a
        !          1269:  * synchronous fifo depth of 0. This will result in asynchronous
        !          1270:  * transfers - not ideal but so much easier.
        !          1271:  * Actually, this is OK because it assures us that if we don't
        !          1272:  * specifically ask for sync transfers, we won't do any.
        !          1273:  */
        !          1274: 
        !          1275:                            write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
        !          1276:                            hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
        !          1277:                            hostdata->outgoing_msg[1] = 3;
        !          1278:                            hostdata->outgoing_msg[2] = EXTENDED_SDTR;
        !          1279:                            hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;
        !          1280:                            hostdata->outgoing_msg[4] = 0;
        !          1281:                            hostdata->outgoing_len = 5;
        !          1282:                            hostdata->sync_xfer[cmd->target] =
        !          1283:                                        calc_sync_xfer(hostdata->default_sx_per/4,0);
        !          1284:                            }
        !          1285:                         else {
        !          1286:                            hostdata->sync_xfer[cmd->target] = id;
        !          1287:                            }
        !          1288: #ifdef SYNC_DEBUG
        !          1289: printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
        !          1290: #endif
        !          1291:                         hostdata->sync_stat[cmd->target] = SS_SET;
        !          1292:                         write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1293:                         hostdata->state = S_CONNECTED;
        !          1294:                         break;
        !          1295:                      case EXTENDED_WDTR:
        !          1296:                         write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
        !          1297:                         printk("sending WDTR ");
        !          1298:                         hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
        !          1299:                         hostdata->outgoing_msg[1] = 2;
        !          1300:                         hostdata->outgoing_msg[2] = EXTENDED_WDTR;
        !          1301:                         hostdata->outgoing_msg[3] = 0;   /* 8 bit transfer width */
        !          1302:                         hostdata->outgoing_len = 4;
        !          1303:                         write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1304:                         hostdata->state = S_CONNECTED;
        !          1305:                         break;
        !          1306:                      default:
        !          1307:                         write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
        !          1308:                         printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);
        !          1309:                         hostdata->outgoing_msg[0] = MESSAGE_REJECT;
        !          1310:                         hostdata->outgoing_len = 1;
        !          1311:                         write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1312:                         hostdata->state = S_CONNECTED;
        !          1313:                         break;
        !          1314:                      }
        !          1315:                   hostdata->incoming_ptr = 0;
        !          1316:                   }
        !          1317: 
        !          1318:          /* We need to read more MESS_IN bytes for the extended message */
        !          1319: 
        !          1320:                else {
        !          1321:                   hostdata->incoming_ptr++;
        !          1322:                   write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1323:                   hostdata->state = S_CONNECTED;
        !          1324:                   }
        !          1325:                break;
        !          1326: 
        !          1327:             default:
        !          1328:                printk("Rejecting Unknown Message(%02x) ",msg);
        !          1329:                write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */
        !          1330:                hostdata->outgoing_msg[0] = MESSAGE_REJECT;
        !          1331:                hostdata->outgoing_len = 1;
        !          1332:                write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1333:                hostdata->state = S_CONNECTED;
        !          1334:             }
        !          1335:          break;
        !          1336: 
        !          1337: 
        !          1338: /* Note: this interrupt will occur only after a LEVEL2 command */
        !          1339: 
        !          1340:       case CSR_SEL_XFER_DONE:
        !          1341: 
        !          1342: /* Make sure that reselection is enabled at this point - it may
        !          1343:  * have been turned off for the command that just completed.
        !          1344:  */
        !          1345: 
        !          1346:          write_3393(hostdata,WD_SOURCE_ID, SRCID_ER);
        !          1347:          if (phs == 0x60) {
        !          1348: DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))
        !          1349:             cmd->SCp.Message = COMMAND_COMPLETE;
        !          1350:             lun = read_3393(hostdata,WD_TARGET_LUN);
        !          1351: DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
        !          1352:             hostdata->connected = NULL;
        !          1353:             hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1354:             hostdata->state = S_UNCONNECTED;
        !          1355:             if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)
        !          1356:                cmd->SCp.Status = lun;
        !          1357:             if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
        !          1358:                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
        !          1359:             else
        !          1360:                cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
        !          1361:             cmd->scsi_done(cmd);
        !          1362: 
        !          1363: /* We are no longer connected to a target - check to see if
        !          1364:  * there are commands waiting to be executed.
        !          1365:  */
        !          1366: 
        !          1367:             in2000_execute(instance);
        !          1368:             }
        !          1369:          else {
        !          1370:             printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
        !          1371:             }
        !          1372:          break;
        !          1373: 
        !          1374: 
        !          1375: /* Note: this interrupt will occur only after a LEVEL2 command */
        !          1376: 
        !          1377:       case CSR_SDP:
        !          1378: DB(DB_INTR,printk("SDP"))
        !          1379:             hostdata->state = S_RUNNING_LEVEL2;
        !          1380:             write_3393(hostdata,WD_COMMAND_PHASE, 0x41);
        !          1381:             write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !          1382:          break;
        !          1383: 
        !          1384: 
        !          1385:       case CSR_XFER_DONE|PHS_MESS_OUT:
        !          1386:       case CSR_UNEXP    |PHS_MESS_OUT:
        !          1387:       case CSR_SRV_REQ  |PHS_MESS_OUT:
        !          1388: DB(DB_INTR,printk("MSG_OUT="))
        !          1389: 
        !          1390: /* To get here, we've probably requested MESSAGE_OUT and have
        !          1391:  * already put the correct bytes in outgoing_msg[] and filled
        !          1392:  * in outgoing_len. We simply send them out to the SCSI bus.
        !          1393:  * Sometimes we get MESSAGE_OUT phase when we're not expecting
        !          1394:  * it - like when our SDTR message is rejected by a target. Some
        !          1395:  * targets send the REJECT before receiving all of the extended
        !          1396:  * message, and then seem to go back to MESSAGE_OUT for a byte
        !          1397:  * or two. Not sure why, or if I'm doing something wrong to
        !          1398:  * cause this to happen. Regardless, it seems that sending
        !          1399:  * NOP messages in these situations results in no harm and
        !          1400:  * makes everyone happy.
        !          1401:  */
        !          1402: 
        !          1403:          if (hostdata->outgoing_len == 0) {
        !          1404:             hostdata->outgoing_len = 1;
        !          1405:             hostdata->outgoing_msg[0] = NOP;
        !          1406:             }
        !          1407:          transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len,
        !          1408:                       DATA_OUT_DIR, hostdata);
        !          1409: DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
        !          1410:          hostdata->outgoing_len = 0;
        !          1411:          hostdata->state = S_CONNECTED;
        !          1412:          break;
        !          1413: 
        !          1414:  
        !          1415:       case CSR_UNEXP_DISC:
        !          1416: 
        !          1417: /* I think I've seen this after a request-sense that was in response
        !          1418:  * to an error condition, but not sure. We certainly need to do
        !          1419:  * something when we get this interrupt - the question is 'what?'.
        !          1420:  * Let's think positively, and assume some command has finished
        !          1421:  * in a legal manner (like a command that provokes a request-sense),
        !          1422:  * so we treat it as a normal command-complete-disconnect.
        !          1423:  */
        !          1424: 
        !          1425: 
        !          1426: /* Make sure that reselection is enabled at this point - it may
        !          1427:  * have been turned off for the command that just completed.
        !          1428:  */
        !          1429: 
        !          1430:          write_3393(hostdata,WD_SOURCE_ID, SRCID_ER);
        !          1431:          if (cmd == NULL) {
        !          1432:             printk(" - Already disconnected! ");
        !          1433:             hostdata->state = S_UNCONNECTED;
        !          1434: 
        !          1435: /* release the SMP spin_lock and restore irq state */
        !          1436:             CLISPIN_UNLOCK(flags);
        !          1437:             return;
        !          1438:             }
        !          1439: DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
        !          1440:          hostdata->connected = NULL;
        !          1441:          hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1442:          hostdata->state = S_UNCONNECTED;
        !          1443:          if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
        !          1444:             cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
        !          1445:          else
        !          1446:             cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
        !          1447:          cmd->scsi_done(cmd);
        !          1448: 
        !          1449: /* We are no longer connected to a target - check to see if
        !          1450:  * there are commands waiting to be executed.
        !          1451:  */
        !          1452: 
        !          1453:          in2000_execute(instance);
        !          1454:          break;
        !          1455: 
        !          1456: 
        !          1457:       case CSR_DISC:
        !          1458: 
        !          1459: /* Make sure that reselection is enabled at this point - it may
        !          1460:  * have been turned off for the command that just completed.
        !          1461:  */
        !          1462: 
        !          1463:          write_3393(hostdata,WD_SOURCE_ID, SRCID_ER);
        !          1464: DB(DB_INTR,printk("DISC-%ld",cmd->pid))
        !          1465:          if (cmd == NULL) {
        !          1466:             printk(" - Already disconnected! ");
        !          1467:             hostdata->state = S_UNCONNECTED;
        !          1468:             }
        !          1469:          switch (hostdata->state) {
        !          1470:             case S_PRE_CMP_DISC:
        !          1471:                hostdata->connected = NULL;
        !          1472:                hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1473:                hostdata->state = S_UNCONNECTED;
        !          1474: DB(DB_INTR,printk(":%d",cmd->SCp.Status))
        !          1475:                if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
        !          1476:                   cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
        !          1477:                else
        !          1478:                   cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
        !          1479:                cmd->scsi_done(cmd);
        !          1480:                break;
        !          1481:             case S_PRE_TMP_DISC:
        !          1482:             case S_RUNNING_LEVEL2:
        !          1483:                cmd->host_scribble = (uchar *)hostdata->disconnected_Q;
        !          1484:                hostdata->disconnected_Q = cmd;
        !          1485:                hostdata->connected = NULL;
        !          1486:                hostdata->state = S_UNCONNECTED;
        !          1487: 
        !          1488: #ifdef PROC_STATISTICS
        !          1489:                hostdata->disc_done_cnt[cmd->target]++;
        !          1490: #endif
        !          1491: 
        !          1492:                break;
        !          1493:             default:
        !          1494:                printk("*** Unexpected DISCONNECT interrupt! ***");
        !          1495:                hostdata->state = S_UNCONNECTED;
        !          1496:             }
        !          1497: 
        !          1498: /* We are no longer connected to a target - check to see if
        !          1499:  * there are commands waiting to be executed.
        !          1500:  */
        !          1501: 
        !          1502:          in2000_execute(instance);
        !          1503:          break;
        !          1504: 
        !          1505: 
        !          1506:       case CSR_RESEL_AM:
        !          1507: DB(DB_INTR,printk("RESEL"))
        !          1508: 
        !          1509:    /* First we have to make sure this reselection didn't */
        !          1510:    /* happen during Arbitration/Selection of some other device. */
        !          1511:    /* If yes, put losing command back on top of input_Q. */
        !          1512: 
        !          1513:          if (hostdata->level2 <= L2_NONE) {
        !          1514: 
        !          1515:             if (hostdata->selecting) {
        !          1516:                cmd = (Scsi_Cmnd *)hostdata->selecting;
        !          1517:                hostdata->selecting = NULL;
        !          1518:                hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1519:                cmd->host_scribble = (uchar *)hostdata->input_Q;
        !          1520:                hostdata->input_Q = cmd;
        !          1521:                }
        !          1522:             }
        !          1523: 
        !          1524:          else {
        !          1525: 
        !          1526:             if (cmd) {
        !          1527:                if (phs == 0x00) {
        !          1528:                   hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1529:                   cmd->host_scribble = (uchar *)hostdata->input_Q;
        !          1530:                   hostdata->input_Q = cmd;
        !          1531:                   }
        !          1532:                else {
        !          1533:                   printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);
        !          1534:                   while (1)
        !          1535:                      printk("\r");
        !          1536:                   }
        !          1537:                }
        !          1538: 
        !          1539:             }
        !          1540: 
        !          1541:    /* OK - find out which device reselected us. */
        !          1542: 
        !          1543:          id = read_3393(hostdata,WD_SOURCE_ID);
        !          1544:          id &= SRCID_MASK;
        !          1545: 
        !          1546:    /* and extract the lun from the ID message. (Note that we don't
        !          1547:     * bother to check for a valid message here - I guess this is
        !          1548:     * not the right way to go, but....)
        !          1549:     */
        !          1550: 
        !          1551:          lun = read_3393(hostdata,WD_DATA);
        !          1552:          if (hostdata->level2 < L2_RESELECT)
        !          1553:             write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);
        !          1554:          lun &= 7;
        !          1555: 
        !          1556:    /* Now we look for the command that's reconnecting. */
        !          1557: 
        !          1558:          cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;
        !          1559:          patch = NULL;
        !          1560:          while (cmd) {
        !          1561:             if (id == cmd->target && lun == cmd->lun)
        !          1562:                break;
        !          1563:             patch = cmd;
        !          1564:             cmd = (Scsi_Cmnd *)cmd->host_scribble;
        !          1565:             }
        !          1566: 
        !          1567:    /* Hmm. Couldn't find a valid command.... What to do? */
        !          1568: 
        !          1569:          if (!cmd) {
        !          1570:             printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
        !          1571:             break;
        !          1572:             }
        !          1573: 
        !          1574:    /* Ok, found the command - now start it up again. */
        !          1575: 
        !          1576:          if (patch)
        !          1577:             patch->host_scribble = cmd->host_scribble;
        !          1578:          else
        !          1579:             hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;
        !          1580:          hostdata->connected = cmd;
        !          1581: 
        !          1582:    /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'
        !          1583:     * because these things are preserved over a disconnect.
        !          1584:     * But we DO need to fix the DPD bit so it's correct for this command.
        !          1585:     */
        !          1586: 
        !          1587:          if (is_dir_out(cmd))
        !          1588:             write_3393(hostdata,WD_DESTINATION_ID,cmd->target);
        !          1589:          else
        !          1590:             write_3393(hostdata,WD_DESTINATION_ID,cmd->target | DSTID_DPD);
        !          1591:          if (hostdata->level2 >= L2_RESELECT) {
        !          1592:             write_3393_count(hostdata,0); /* we want a DATA_PHASE interrupt */
        !          1593:             write_3393(hostdata,WD_COMMAND_PHASE, 0x45);
        !          1594:             write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);
        !          1595:             hostdata->state = S_RUNNING_LEVEL2;
        !          1596:             }
        !          1597:          else
        !          1598:             hostdata->state = S_CONNECTED;
        !          1599: 
        !          1600: DB(DB_INTR,printk("-%ld",cmd->pid))
        !          1601:          break;
        !          1602: 
        !          1603:       default:
        !          1604:          printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
        !          1605:       }
        !          1606: 
        !          1607:    write1_io(0, IO_LED_OFF);
        !          1608: 
        !          1609: DB(DB_INTR,printk("} "))
        !          1610: 
        !          1611: /* release the SMP spin_lock and restore irq state */
        !          1612:    CLISPIN_UNLOCK(flags);
        !          1613: 
        !          1614: }
        !          1615: 
        !          1616: 
        !          1617: 
        !          1618: #define RESET_CARD         0
        !          1619: #define RESET_CARD_AND_BUS 1
        !          1620: #define B_FLAG 0x80
        !          1621: 
        !          1622: static int reset_hardware(struct Scsi_Host *instance, int type)
        !          1623: {
        !          1624: struct IN2000_hostdata *hostdata;
        !          1625: int qt,x;
        !          1626: unsigned long flags;
        !          1627: 
        !          1628:    hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !          1629: 
        !          1630:    write1_io(0, IO_LED_ON);
        !          1631:    if (type == RESET_CARD_AND_BUS) {
        !          1632:       write1_io(0,IO_CARD_RESET);
        !          1633:       x = read1_io(IO_HARDWARE);
        !          1634:       }
        !          1635:    x = read_3393(hostdata,WD_SCSI_STATUS);   /* clear any WD intrpt */
        !          1636:    write_3393(hostdata,WD_OWN_ID, instance->this_id |
        !          1637:                            OWNID_EAF | OWNID_RAF | OWNID_FS_8);
        !          1638:    write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        !          1639:    write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,
        !          1640:               calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
        !          1641:    save_flags(flags);
        !          1642:    cli();
        !          1643:    write1_io(0,IO_FIFO_WRITE);            /* clear fifo counter */
        !          1644:    write1_io(0,IO_FIFO_READ);             /* start fifo out in read mode */
        !          1645:    write_3393(hostdata,WD_COMMAND, WD_CMD_RESET);
        !          1646:    while (!(READ_AUX_STAT() & ASR_INT))
        !          1647:       ;                                   /* wait for RESET to complete */
        !          1648: 
        !          1649:    x = read_3393(hostdata,WD_SCSI_STATUS);   /* clear interrupt */
        !          1650:    restore_flags(flags);
        !          1651:    write_3393(hostdata,WD_QUEUE_TAG,0xa5);   /* any random number */
        !          1652:    qt = read_3393(hostdata,WD_QUEUE_TAG);
        !          1653:    if (qt == 0xa5) {
        !          1654:       x |= B_FLAG;
        !          1655:       write_3393(hostdata,WD_QUEUE_TAG,0);
        !          1656:       }
        !          1657:    write_3393(hostdata,WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
        !          1658:    write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        !          1659:    write1_io(0, IO_LED_OFF);
        !          1660:    return x;
        !          1661: }
        !          1662: 
        !          1663: 
        !          1664: 
        !          1665: int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags)
        !          1666: {
        !          1667: unsigned long flags;
        !          1668: struct Scsi_Host *instance;
        !          1669: struct IN2000_hostdata *hostdata;
        !          1670: int x;
        !          1671: 
        !          1672:    instance = cmd->host;
        !          1673:    hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !          1674: 
        !          1675:    printk("scsi%d: Reset. ", instance->host_no);
        !          1676:    save_flags(flags);
        !          1677:    cli();
        !          1678: 
        !          1679:    /* do scsi-reset here */
        !          1680: 
        !          1681:    reset_hardware(instance, RESET_CARD_AND_BUS);
        !          1682:    for (x = 0; x < 8; x++) {
        !          1683:       hostdata->busy[x] = 0;
        !          1684:       hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
        !          1685:       hostdata->sync_stat[x] = SS_UNSET;  /* using default sync values */
        !          1686:       }
        !          1687:    hostdata->input_Q = NULL;
        !          1688:    hostdata->selecting = NULL;
        !          1689:    hostdata->connected = NULL;
        !          1690:    hostdata->disconnected_Q = NULL;
        !          1691:    hostdata->state = S_UNCONNECTED;
        !          1692:    hostdata->fifo = FI_FIFO_UNUSED;
        !          1693:    hostdata->incoming_ptr = 0;
        !          1694:    hostdata->outgoing_len = 0;
        !          1695: 
        !          1696:    cmd->result = DID_RESET << 16;
        !          1697:    restore_flags(flags);
        !          1698:    return 0;
        !          1699: }
        !          1700: 
        !          1701: 
        !          1702: 
        !          1703: int in2000_abort (Scsi_Cmnd *cmd)
        !          1704: {
        !          1705: struct Scsi_Host *instance;
        !          1706: struct IN2000_hostdata *hostdata;
        !          1707: Scsi_Cmnd *tmp, *prev;
        !          1708: unsigned long flags;
        !          1709: uchar sr, asr;
        !          1710: unsigned long timeout;
        !          1711: 
        !          1712:    save_flags (flags);
        !          1713:    cli();
        !          1714: 
        !          1715:    instance = cmd->host;
        !          1716:    hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !          1717: 
        !          1718:    printk ("scsi%d: Abort-", instance->host_no);
        !          1719:    printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ",
        !          1720:             READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual,
        !          1721:             cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT));
        !          1722: 
        !          1723: /*
        !          1724:  * Case 1 : If the command hasn't been issued yet, we simply remove it
        !          1725:  *     from the inout_Q.
        !          1726:  */
        !          1727: 
        !          1728:    tmp = (Scsi_Cmnd *)hostdata->input_Q;
        !          1729:    prev = 0;
        !          1730:    while (tmp) {
        !          1731:       if (tmp == cmd) {
        !          1732:          if (prev)
        !          1733:             prev->host_scribble = cmd->host_scribble;
        !          1734:          cmd->host_scribble = NULL;
        !          1735:          cmd->result = DID_ABORT << 16;
        !          1736:          printk("scsi%d: Abort - removing command %ld from input_Q. ",
        !          1737:            instance->host_no, cmd->pid);
        !          1738:          cmd->scsi_done(cmd);
        !          1739:          restore_flags(flags);
        !          1740:          return SCSI_ABORT_SUCCESS;
        !          1741:          }
        !          1742:       prev = tmp;
        !          1743:       tmp = (Scsi_Cmnd *)tmp->host_scribble;
        !          1744:       }
        !          1745: 
        !          1746: /*
        !          1747:  * Case 2 : If the command is connected, we're going to fail the abort
        !          1748:  *     and let the high level SCSI driver retry at a later time or
        !          1749:  *     issue a reset.
        !          1750:  *
        !          1751:  *     Timeouts, and therefore aborted commands, will be highly unlikely
        !          1752:  *     and handling them cleanly in this situation would make the common
        !          1753:  *     case of noresets less efficient, and would pollute our code.  So,
        !          1754:  *     we fail.
        !          1755:  */
        !          1756: 
        !          1757:    if (hostdata->connected == cmd) {
        !          1758: 
        !          1759:       printk("scsi%d: Aborting connected command %ld - ",
        !          1760:               instance->host_no, cmd->pid);
        !          1761: 
        !          1762:       printk("sending wd33c93 ABORT command - ");
        !          1763:       write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
        !          1764:       write_3393_cmd(hostdata, WD_CMD_ABORT);
        !          1765: 
        !          1766: /* Now we have to attempt to flush out the FIFO... */
        !          1767: 
        !          1768:       printk("flushing fifo - ");
        !          1769:       timeout = 1000000;
        !          1770:       do {
        !          1771:          asr = READ_AUX_STAT();
        !          1772:          if (asr & ASR_DBR)
        !          1773:             read_3393(hostdata, WD_DATA);
        !          1774:          } while (!(asr & ASR_INT) && timeout-- > 0);
        !          1775:       sr = read_3393(hostdata, WD_SCSI_STATUS);
        !          1776:       printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
        !          1777:              asr, sr, read_3393_count(hostdata), timeout);
        !          1778: 
        !          1779:    /*
        !          1780:     * Abort command processed.
        !          1781:     * Still connected.
        !          1782:     * We must disconnect.
        !          1783:     */
        !          1784: 
        !          1785:       printk("sending wd33c93 DISCONNECT command - ");
        !          1786:       write_3393_cmd(hostdata, WD_CMD_DISCONNECT);
        !          1787: 
        !          1788:       timeout = 1000000;
        !          1789:       asr = READ_AUX_STAT();
        !          1790:       while ((asr & ASR_CIP) && timeout-- > 0)
        !          1791:          asr = READ_AUX_STAT();
        !          1792:       sr = read_3393(hostdata, WD_SCSI_STATUS);
        !          1793:       printk("asr=%02x, sr=%02x.",asr,sr);
        !          1794: 
        !          1795:       hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
        !          1796:       hostdata->connected = NULL;
        !          1797:       hostdata->state = S_UNCONNECTED;
        !          1798:       cmd->result = DID_ABORT << 16;
        !          1799:       cmd->scsi_done(cmd);
        !          1800: 
        !          1801:       in2000_execute (instance);
        !          1802: 
        !          1803:       restore_flags(flags);
        !          1804:       return SCSI_ABORT_SUCCESS;
        !          1805:       }
        !          1806: 
        !          1807: /*
        !          1808:  * Case 3: If the command is currently disconnected from the bus,
        !          1809:  * we're not going to expend much effort here: Let's just return
        !          1810:  * an ABORT_SNOOZE and hope for the best...
        !          1811:  */
        !          1812: 
        !          1813:    for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp;
        !          1814:          tmp=(Scsi_Cmnd *)tmp->host_scribble)
        !          1815:       if (cmd == tmp) {
        !          1816:          restore_flags(flags);
        !          1817:          printk("Sending ABORT_SNOOZE. ");
        !          1818:          return SCSI_ABORT_SNOOZE;
        !          1819:          }
        !          1820: 
        !          1821: /*
        !          1822:  * Case 4 : If we reached this point, the command was not found in any of
        !          1823:  *     the queues.
        !          1824:  *
        !          1825:  * We probably reached this point because of an unlikely race condition
        !          1826:  * between the command completing successfully and the abortion code,
        !          1827:  * so we won't panic, but we will notify the user in case something really
        !          1828:  * broke.
        !          1829:  */
        !          1830: 
        !          1831:    in2000_execute (instance);
        !          1832: 
        !          1833:    restore_flags(flags);
        !          1834:    printk("scsi%d: warning : SCSI command probably completed successfully"
        !          1835:       "         before abortion. ", instance->host_no);
        !          1836:    return SCSI_ABORT_NOT_RUNNING;
        !          1837: }
        !          1838: 
        !          1839: 
        !          1840: 
        !          1841: #define MAX_IN2000_HOSTS 3
        !          1842: #define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *))
        !          1843: #define SETUP_BUFFER_SIZE 200
        !          1844: static char setup_buffer[SETUP_BUFFER_SIZE];
        !          1845: static char setup_used[MAX_SETUP_ARGS];
        !          1846: static int done_setup = 0;
        !          1847: 
        !          1848: in2000__INITFUNC( void in2000_setup (char *str, int *ints) )
        !          1849: {
        !          1850: int i;
        !          1851: char *p1,*p2;
        !          1852: 
        !          1853:    strncpy(setup_buffer,str,SETUP_BUFFER_SIZE);
        !          1854:    setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
        !          1855:    p1 = setup_buffer;
        !          1856:    i = 0;
        !          1857:    while (*p1 && (i < MAX_SETUP_ARGS)) {
        !          1858:       p2 = strchr(p1, ',');
        !          1859:       if (p2) {
        !          1860:          *p2 = '\0';
        !          1861:          if (p1 != p2)
        !          1862:             setup_args[i] = p1;
        !          1863:          p1 = p2 + 1;
        !          1864:          i++;
        !          1865:          }
        !          1866:       else {
        !          1867:          setup_args[i] = p1;
        !          1868:          break;
        !          1869:          }
        !          1870:       }
        !          1871:    for (i=0; i<MAX_SETUP_ARGS; i++)
        !          1872:       setup_used[i] = 0;
        !          1873:    done_setup = 1;
        !          1874: }
        !          1875: 
        !          1876: 
        !          1877: /* check_setup_args() returns index if key found, 0 if not
        !          1878:  */
        !          1879: 
        !          1880: in2000__INITFUNC( static int check_setup_args(char *key, int *flags, int *val, char *buf) )
        !          1881: {
        !          1882: int x;
        !          1883: char *cp;
        !          1884: 
        !          1885:    for  (x=0; x<MAX_SETUP_ARGS; x++) {
        !          1886:       if (setup_used[x])
        !          1887:          continue;
        !          1888:       if (!strncmp(setup_args[x], key, strlen(key)))
        !          1889:          break;
        !          1890:       }
        !          1891:    if (x == MAX_SETUP_ARGS)
        !          1892:       return 0;
        !          1893:    setup_used[x] = 1;
        !          1894:    cp = setup_args[x] + strlen(key);
        !          1895:    *val = -1;
        !          1896:    if (*cp != ':')
        !          1897:       return ++x;
        !          1898:    cp++;
        !          1899:    if ((*cp >= '0') && (*cp <= '9')) {
        !          1900:       *val = simple_strtoul(cp,NULL,0);
        !          1901:       }
        !          1902:    return ++x;
        !          1903: }
        !          1904: 
        !          1905: 
        !          1906: 
        !          1907: /* The "correct" (ie portable) way to access memory-mapped hardware
        !          1908:  * such as the IN2000 EPROM and dip switch is through the use of
        !          1909:  * special macros declared in 'asm/io.h'. We use readb() and readl()
        !          1910:  * when reading from the card's BIOS area in in2000_detect().
        !          1911:  */
        !          1912: static const unsigned int *bios_tab[] in2000__INITDATA = {
        !          1913:    (unsigned int *)0xc8000,
        !          1914:    (unsigned int *)0xd0000,
        !          1915:    (unsigned int *)0xd8000,
        !          1916:    0
        !          1917:    };
        !          1918: 
        !          1919: static const unsigned short base_tab[] in2000__INITDATA = {
        !          1920:    0x220,
        !          1921:    0x200,
        !          1922:    0x110,
        !          1923:    0x100,
        !          1924:    };
        !          1925: 
        !          1926: static const int int_tab[] in2000__INITDATA = {
        !          1927:    15,
        !          1928:    14,
        !          1929:    11,
        !          1930:    10
        !          1931:    };
        !          1932: 
        !          1933: 
        !          1934: in2000__INITFUNC( int in2000_detect(Scsi_Host_Template * tpnt) )
        !          1935: {
        !          1936: struct Scsi_Host *instance;
        !          1937: struct IN2000_hostdata *hostdata;
        !          1938: int detect_count;
        !          1939: int bios;
        !          1940: int x;
        !          1941: unsigned short base;
        !          1942: uchar switches;
        !          1943: uchar hrev;
        !          1944: int flags;
        !          1945: int val;
        !          1946: char buf[32];
        !          1947: 
        !          1948: /* Thanks to help from Bill Earnest, probing for IN2000 cards is a
        !          1949:  * pretty straightforward and fool-proof operation. There are 3
        !          1950:  * possible locations for the IN2000 EPROM in memory space - if we
        !          1951:  * find a BIOS signature, we can read the dip switch settings from
        !          1952:  * the byte at BIOS+32 (shadowed in by logic on the card). From 2
        !          1953:  * of the switch bits we get the card's address in IO space. There's
        !          1954:  * an image of the dip switch there, also, so we have a way to back-
        !          1955:  * check that this really is an IN2000 card. Very nifty. Use the
        !          1956:  * 'ioport:xx' command-line parameter if your BIOS EPROM is absent
        !          1957:  * or disabled.
        !          1958:  */
        !          1959: 
        !          1960:    if (!done_setup && setup_strings)
        !          1961:       in2000_setup(setup_strings,0);
        !          1962: 
        !          1963:    detect_count = 0;
        !          1964:    for (bios = 0; bios_tab[bios]; bios++) {
        !          1965:       if (check_setup_args("ioport",&flags,&val,buf)) {
        !          1966:          base = val;
        !          1967:          switches = ~inb(base + IO_SWITCHES) & 0xff;
        !          1968:          printk("Forcing IN2000 detection at IOport 0x%x ",base);
        !          1969:          bios = 2;
        !          1970:          }
        !          1971: /*
        !          1972:  * There have been a couple of BIOS versions with different layouts
        !          1973:  * for the obvious ID strings. We look for the 2 most common ones and
        !          1974:  * hope that they cover all the cases...
        !          1975:  */
        !          1976:       else if (readl(bios_tab[bios]+0x04) == 0x41564f4e ||
        !          1977:                readl(bios_tab[bios]+0x0c) == 0x61776c41) {
        !          1978:          printk("Found IN2000 BIOS at 0x%x ",(unsigned int)bios_tab[bios]);
        !          1979: 
        !          1980: /* Read the switch image that's mapped into EPROM space */
        !          1981: 
        !          1982:          switches = ~((readb(bios_tab[bios]+0x08) & 0xff));
        !          1983: 
        !          1984: /* Find out where the IO space is */
        !          1985: 
        !          1986:          x = switches & (SW_ADDR0 | SW_ADDR1);
        !          1987:          base = base_tab[x];
        !          1988: 
        !          1989: /* Check for the IN2000 signature in IO space. */
        !          1990: 
        !          1991:          x = ~inb(base + IO_SWITCHES) & 0xff;
        !          1992:          if (x != switches) {
        !          1993:             printk("Bad IO signature: %02x vs %02x.\n",x,switches);
        !          1994:             continue;
        !          1995:             }
        !          1996:          }
        !          1997:       else
        !          1998:          continue;
        !          1999: 
        !          2000: /* OK. We have a base address for the IO ports - run a few safety checks */
        !          2001: 
        !          2002:       if (!(switches & SW_BIT7)) {        /* I _think_ all cards do this */
        !          2003:          printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n",base);
        !          2004:          continue;
        !          2005:          }
        !          2006: 
        !          2007: /* Let's assume any hardware version will work, although the driver
        !          2008:  * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll
        !          2009:  * print out the rev number for reference later, but accept them all.
        !          2010:  */
        !          2011: 
        !          2012:       hrev = inb(base + IO_HARDWARE);
        !          2013: 
        !          2014:   /* Bit 2 tells us if interrupts are disabled */
        !          2015:       if (switches & SW_DISINT) {
        !          2016:          printk("The IN-2000 SCSI card at IOport 0x%03x ",base);
        !          2017:          printk("is not configured for interrupt operation!\n");
        !          2018:          printk("This driver requires an interrupt: cancelling detection.\n");
        !          2019:          continue;
        !          2020:          }
        !          2021: 
        !          2022: /* Ok. We accept that there's an IN2000 at ioaddr 'base'. Now
        !          2023:  * initialize it.
        !          2024:  */
        !          2025: 
        !          2026:       tpnt->proc_dir = &proc_scsi_in2000; /* done more than once? harmless. */
        !          2027:       detect_count++;
        !          2028:       instance  = scsi_register(tpnt, sizeof(struct IN2000_hostdata));
        !          2029:       if (!instance_list)
        !          2030:          instance_list = instance;
        !          2031:       hostdata = (struct IN2000_hostdata *)instance->hostdata;
        !          2032:       instance->io_port = hostdata->io_base = base;
        !          2033:       hostdata->dip_switch = switches;
        !          2034:       hostdata->hrev = hrev;
        !          2035: 
        !          2036:       write1_io(0,IO_FIFO_WRITE);            /* clear fifo counter */
        !          2037:       write1_io(0,IO_FIFO_READ);             /* start fifo out in read mode */
        !          2038:       write1_io(0,IO_INTR_MASK);    /* allow all ints */
        !          2039:       x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT];
        !          2040:       if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000", NULL)) {
        !          2041:          printk("in2000_detect: Unable to allocate IRQ.\n");
        !          2042:          detect_count--;
        !          2043:          continue;
        !          2044:          }
        !          2045:       instance->irq = x;
        !          2046:       instance->n_io_port = 13;
        !          2047:       request_region(base, 13, "in2000"); /* lock in this IO space for our use */
        !          2048: 
        !          2049:       for (x = 0; x < 8; x++) {
        !          2050:          hostdata->busy[x] = 0;
        !          2051:          hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
        !          2052:          hostdata->sync_stat[x] = SS_UNSET;  /* using default sync values */
        !          2053: #ifdef PROC_STATISTICS
        !          2054:          hostdata->cmd_cnt[x] = 0;
        !          2055:          hostdata->disc_allowed_cnt[x] = 0;
        !          2056:          hostdata->disc_done_cnt[x] = 0;
        !          2057: #endif
        !          2058:          }
        !          2059:       hostdata->input_Q = NULL;
        !          2060:       hostdata->selecting = NULL;
        !          2061:       hostdata->connected = NULL;
        !          2062:       hostdata->disconnected_Q = NULL;
        !          2063:       hostdata->state = S_UNCONNECTED;
        !          2064:       hostdata->fifo = FI_FIFO_UNUSED;
        !          2065:       hostdata->level2 = L2_BASIC;
        !          2066:       hostdata->disconnect = DIS_ADAPTIVE;
        !          2067:       hostdata->args = DEBUG_DEFAULTS;
        !          2068:       hostdata->incoming_ptr = 0;
        !          2069:       hostdata->outgoing_len = 0;
        !          2070:       hostdata->default_sx_per = DEFAULT_SX_PER;
        !          2071: 
        !          2072: /* Older BIOS's had a 'sync on/off' switch - use its setting */
        !          2073: 
        !          2074:       if (readl(bios_tab[bios]+0x04) == 0x41564f4e && (switches & SW_SYNC_DOS5))
        !          2075:          hostdata->sync_off = 0x00;    /* sync defaults to on */
        !          2076:       else
        !          2077:          hostdata->sync_off = 0xff;    /* sync defaults to off */
        !          2078: 
        !          2079: #ifdef PROC_INTERFACE
        !          2080:       hostdata->proc = PR_VERSION|PR_INFO|PR_STATISTICS|
        !          2081:                        PR_CONNECTED|PR_INPUTQ|PR_DISCQ|
        !          2082:                        PR_STOP;
        !          2083: #ifdef PROC_STATISTICS
        !          2084:       hostdata->int_cnt = 0;
        !          2085: #endif
        !          2086: #endif
        !          2087: 
        !          2088:       if (check_setup_args("nosync",&flags,&val,buf))
        !          2089:          hostdata->sync_off = val;
        !          2090: 
        !          2091:       if (check_setup_args("period",&flags,&val,buf))
        !          2092:          hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns;
        !          2093: 
        !          2094:       if (check_setup_args("disconnect",&flags,&val,buf)) {
        !          2095:          if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
        !          2096:             hostdata->disconnect = val;
        !          2097:          else
        !          2098:             hostdata->disconnect = DIS_ADAPTIVE;
        !          2099:          }
        !          2100: 
        !          2101:       if (check_setup_args("noreset",&flags,&val,buf))
        !          2102:          hostdata->args ^= A_NO_SCSI_RESET;
        !          2103: 
        !          2104:       if (check_setup_args("level2",&flags,&val,buf))
        !          2105:          hostdata->level2 = val;
        !          2106: 
        !          2107:       if (check_setup_args("debug",&flags,&val,buf))
        !          2108:          hostdata->args = (val & DB_MASK);
        !          2109: 
        !          2110: #ifdef PROC_INTERFACE
        !          2111:       if (check_setup_args("proc",&flags,&val,buf))
        !          2112:          hostdata->proc = val;
        !          2113: #endif
        !          2114: 
        !          2115: 
        !          2116:       x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS);
        !          2117: 
        !          2118:       hostdata->microcode = read_3393(hostdata,WD_CDB_1);
        !          2119:       if (x & 0x01) {
        !          2120:          if (x & B_FLAG)
        !          2121:             hostdata->chip = C_WD33C93B;
        !          2122:          else
        !          2123:             hostdata->chip = C_WD33C93A;
        !          2124:          }
        !          2125:       else
        !          2126:          hostdata->chip = C_WD33C93;
        !          2127: 
        !          2128:       printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ",
        !          2129:                   (switches & 0x7f),
        !          2130:                   instance->irq,hostdata->io_base,
        !          2131:                   (switches & SW_FLOPPY)?"Yes":"No",
        !          2132:                   (switches & SW_SYNC_DOS5)?"Yes":"No");
        !          2133:       printk("hardware_ver=%02x chip=%s microcode=%02x\n",
        !          2134:                   hrev,
        !          2135:                   (hostdata->chip==C_WD33C93)?"WD33c93":
        !          2136:                   (hostdata->chip==C_WD33C93A)?"WD33c93A":
        !          2137:                   (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
        !          2138:                   hostdata->microcode);
        !          2139: #ifdef DEBUGGING_ON
        !          2140:       printk("setup_args = ");
        !          2141:       for (x=0; x<MAX_SETUP_ARGS; x++)
        !          2142:          printk("%s,",setup_args[x]);
        !          2143:       printk("\n");
        !          2144: #endif
        !          2145:       if (hostdata->sync_off == 0xff)
        !          2146:          printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n");
        !          2147:       printk("IN2000 driver version %s - %s\n",IN2000_VERSION,IN2000_DATE);
        !          2148:       }
        !          2149: 
        !          2150:    return detect_count;
        !          2151: }
        !          2152: 
        !          2153: 
        !          2154: /* NOTE: I lifted this function straight out of the old driver,
        !          2155:  *       and have not tested it. Presumably it does what it's
        !          2156:  *       supposed to do...
        !          2157:  */
        !          2158: 
        !          2159: int in2000_biosparam(Disk *disk, kdev_t dev, int *iinfo)
        !          2160: {
        !          2161: int size;
        !          2162: 
        !          2163:    size  = disk->capacity;
        !          2164:    iinfo[0] = 64;
        !          2165:    iinfo[1] = 32;
        !          2166:    iinfo[2] = size >> 11;
        !          2167: 
        !          2168: /* This should approximate the large drive handling that the DOS ASPI manager
        !          2169:    uses.  Drives very near the boundaries may not be handled correctly (i.e.
        !          2170:    near 2.0 Gb and 4.0 Gb) */
        !          2171: 
        !          2172:    if (iinfo[2] > 1024) {
        !          2173:       iinfo[0] = 64;
        !          2174:       iinfo[1] = 63;
        !          2175:       iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
        !          2176:       }
        !          2177:    if (iinfo[2] > 1024) {
        !          2178:       iinfo[0] = 128;
        !          2179:       iinfo[1] = 63;
        !          2180:       iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
        !          2181:       }
        !          2182:    if (iinfo[2] > 1024) {
        !          2183:       iinfo[0] = 255;
        !          2184:       iinfo[1] = 63;
        !          2185:       iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]);
        !          2186:       }
        !          2187:     return 0;
        !          2188: }
        !          2189: 
        !          2190: 
        !          2191: 
        !          2192: struct proc_dir_entry proc_scsi_in2000 = {
        !          2193:    PROC_SCSI_IN2000, 6, "in2000",
        !          2194:    S_IFDIR | S_IRUGO | S_IXUGO, 2
        !          2195:    };
        !          2196: 
        !          2197: 
        !          2198: int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
        !          2199: {
        !          2200: 
        !          2201: #ifdef PROC_INTERFACE
        !          2202: 
        !          2203: char *bp;
        !          2204: char tbuf[128];
        !          2205: unsigned long flags;
        !          2206: struct Scsi_Host *instance;
        !          2207: struct IN2000_hostdata *hd;
        !          2208: Scsi_Cmnd *cmd;
        !          2209: int x,i;
        !          2210: static int stop = 0;
        !          2211: 
        !          2212:    for (instance=instance_list; instance; instance=instance->next) {
        !          2213:       if (instance->host_no == hn)
        !          2214:          break;
        !          2215:       }
        !          2216:    if (!instance) {
        !          2217:       printk("*** Hmm... Can't find host #%d!\n",hn);
        !          2218:       return (-ESRCH);
        !          2219:       }
        !          2220:    hd = (struct IN2000_hostdata *)instance->hostdata;
        !          2221: 
        !          2222: /* If 'in' is TRUE we need to _read_ the proc file. We accept the following
        !          2223:  * keywords (same format as command-line, but only ONE per read):
        !          2224:  *    debug
        !          2225:  *    disconnect
        !          2226:  *    period
        !          2227:  *    resync
        !          2228:  *    proc
        !          2229:  */
        !          2230: 
        !          2231:    if (in) {
        !          2232:       buf[len] = '\0';
        !          2233:       bp = buf;
        !          2234:       if (!strncmp(bp,"debug:",6)) {
        !          2235:          bp += 6;
        !          2236:          hd->args = simple_strtoul(bp,NULL,0) & DB_MASK;
        !          2237:          }
        !          2238:       else if (!strncmp(bp,"disconnect:",11)) {
        !          2239:          bp += 11;
        !          2240:          x = simple_strtoul(bp,NULL,0);
        !          2241:          if (x < DIS_NEVER || x > DIS_ALWAYS)
        !          2242:             x = DIS_ADAPTIVE;
        !          2243:          hd->disconnect = x;
        !          2244:          }
        !          2245:       else if (!strncmp(bp,"period:",7)) {
        !          2246:          bp += 7;
        !          2247:          x = simple_strtoul(bp,NULL,0);
        !          2248:          hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns;
        !          2249:          }
        !          2250:       else if (!strncmp(bp,"resync:",7)) {
        !          2251:          bp += 7;
        !          2252:          x = simple_strtoul(bp,NULL,0);
        !          2253:          for (i=0; i<7; i++)
        !          2254:             if (x & (1<<i))
        !          2255:                hd->sync_stat[i] = SS_UNSET;
        !          2256:          }
        !          2257:       else if (!strncmp(bp,"proc:",5)) {
        !          2258:          bp += 5;
        !          2259:          hd->proc = simple_strtoul(bp,NULL,0);
        !          2260:          }
        !          2261:       else if (!strncmp(bp,"level2:",7)) {
        !          2262:          bp += 7;
        !          2263:          hd->level2 = simple_strtoul(bp,NULL,0);
        !          2264:          }
        !          2265:       return len;
        !          2266:       }
        !          2267: 
        !          2268:    save_flags(flags);
        !          2269:    cli();
        !          2270:    bp = buf;
        !          2271:    *bp = '\0';
        !          2272:    if (hd->proc & PR_VERSION) {
        !          2273:       sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s",
        !          2274:             IN2000_VERSION,IN2000_DATE,__DATE__,__TIME__);
        !          2275:       strcat(bp,tbuf);
        !          2276:       }
        !          2277:    if (hd->proc & PR_INFO) {
        !          2278:       sprintf(tbuf,"\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s",
        !          2279:                   (hd->dip_switch & 0x7f), instance->irq, hd->io_base,
        !          2280:                   (hd->dip_switch & 0x40)?"Yes":"No",
        !          2281:                   (hd->dip_switch & 0x20)?"Yes":"No");
        !          2282:       strcat(bp,tbuf);
        !          2283:       strcat(bp,"\nsync_xfer[] =       ");
        !          2284:       for (x=0; x<7; x++) {
        !          2285:          sprintf(tbuf,"\t%02x",hd->sync_xfer[x]);
        !          2286:          strcat(bp,tbuf);
        !          2287:          }
        !          2288:       strcat(bp,"\nsync_stat[] =       ");
        !          2289:       for (x=0; x<7; x++) {
        !          2290:          sprintf(tbuf,"\t%02x",hd->sync_stat[x]);
        !          2291:          strcat(bp,tbuf);
        !          2292:          }
        !          2293:       }
        !          2294: #ifdef PROC_STATISTICS
        !          2295:    if (hd->proc & PR_STATISTICS) {
        !          2296:       strcat(bp,"\ncommands issued:    ");
        !          2297:       for (x=0; x<7; x++) {
        !          2298:          sprintf(tbuf,"\t%ld",hd->cmd_cnt[x]);
        !          2299:          strcat(bp,tbuf);
        !          2300:          }
        !          2301:       strcat(bp,"\ndisconnects allowed:");
        !          2302:       for (x=0; x<7; x++) {
        !          2303:          sprintf(tbuf,"\t%ld",hd->disc_allowed_cnt[x]);
        !          2304:          strcat(bp,tbuf);
        !          2305:          }
        !          2306:       strcat(bp,"\ndisconnects done:   ");
        !          2307:       for (x=0; x<7; x++) {
        !          2308:          sprintf(tbuf,"\t%ld",hd->disc_done_cnt[x]);
        !          2309:          strcat(bp,tbuf);
        !          2310:          }
        !          2311:       sprintf(tbuf,"\ninterrupts:      \t%ld",hd->int_cnt);
        !          2312:       strcat(bp,tbuf);
        !          2313:       }
        !          2314: #endif
        !          2315:    if (hd->proc & PR_CONNECTED) {
        !          2316:       strcat(bp,"\nconnected:     ");
        !          2317:       if (hd->connected) {
        !          2318:          cmd = (Scsi_Cmnd *)hd->connected;
        !          2319:          sprintf(tbuf," %ld-%d:%d(%02x)",
        !          2320:                cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
        !          2321:          strcat(bp,tbuf);
        !          2322:          }
        !          2323:       }
        !          2324:    if (hd->proc & PR_INPUTQ) {
        !          2325:       strcat(bp,"\ninput_Q:       ");
        !          2326:       cmd = (Scsi_Cmnd *)hd->input_Q;
        !          2327:       while (cmd) {
        !          2328:          sprintf(tbuf," %ld-%d:%d(%02x)",
        !          2329:                cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
        !          2330:          strcat(bp,tbuf);
        !          2331:          cmd = (Scsi_Cmnd *)cmd->host_scribble;
        !          2332:          }
        !          2333:       }
        !          2334:    if (hd->proc & PR_DISCQ) {
        !          2335:       strcat(bp,"\ndisconnected_Q:");
        !          2336:       cmd = (Scsi_Cmnd *)hd->disconnected_Q;
        !          2337:       while (cmd) {
        !          2338:          sprintf(tbuf," %ld-%d:%d(%02x)",
        !          2339:                cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
        !          2340:          strcat(bp,tbuf);
        !          2341:          cmd = (Scsi_Cmnd *)cmd->host_scribble;
        !          2342:          }
        !          2343:       }
        !          2344:    if (hd->proc & PR_TEST) {
        !          2345:       ;  /* insert your own custom function here */
        !          2346:       }
        !          2347:    strcat(bp,"\n");
        !          2348:    restore_flags(flags);
        !          2349:    *start = buf;
        !          2350:    if (stop) {
        !          2351:       stop = 0;
        !          2352:       return 0;         /* return 0 to signal end-of-file */
        !          2353:       }
        !          2354:    if (off > 0x40000)   /* ALWAYS stop after 256k bytes have been read */
        !          2355:       stop = 1;;
        !          2356:    if (hd->proc & PR_STOP)    /* stop every other time */
        !          2357:       stop = 1;
        !          2358:    return strlen(bp);
        !          2359: 
        !          2360: #else    /* PROC_INTERFACE */
        !          2361: 
        !          2362:    return 0;
        !          2363: 
        !          2364: #endif   /* PROC_INTERFACE */
        !          2365: 
        !          2366: }
        !          2367: 
        !          2368: 
        !          2369: #ifdef MODULE
        !          2370: 
        !          2371: Scsi_Host_Template driver_template = IN2000;
        !          2372: 
        !          2373: #include "scsi_module.c"
        !          2374: 
        !          2375: #endif
        !          2376: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.