root/kernel/blk_drv/scsi/fdomain.c

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

DEFINITIONS

This source file includes following definitions.
  1. outw
  2. do_pause
  3. fdomain_make_bus_idle
  4. fdomain_is_valid_port
  5. fdomain_test_loopback
  6. fdomain_16x0_detect
  7. fdomain_16x0_info
  8. fdomain_arbitrate
  9. fdomain_select
  10. my_done
  11. fdomain_16x0_intr
  12. fdomain_16x0_queue
  13. fdomain_16x0_command
  14. fdomain_16x0_abort
  15. fdomain_16x0_reset
  16. fdomain_16x0_biosparam

   1 /* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
   2  * Created: Sun May  3 18:53:19 1992 by faith
   3  * Revised: Sun Jan 10 01:23:29 1993 by root
   4  * Author: Rickard E. Faith, faith@cs.unc.edu
   5  * Copyright 1992, 1993 Rickard E. Faith
   6  *
   7  * $Log$
   8 
   9  * This program is free software; you can redistribute it and/or modify it
  10  * under the terms of the GNU General Public License as published by the
  11  * Free Software Foundation; either version 2, or (at your option) any
  12  * later version.
  13 
  14  * This program is distributed in the hope that it will be useful, but
  15  * WITHOUT ANY WARRANTY; without even the implied warranty of
  16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17  * General Public License for more details.
  18 
  19  **************************************************************************
  20 
  21 
  22  DESCRIPTION:
  23 
  24  This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680
  25  and TMC-1670 SCSI host adapters.
  26 
  27 
  28  REFERENCES USED:
  29 
  30  "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation,
  31  1990.
  32 
  33  "LXT SCSI Products: Specifications and OEM Technical Manual (Revision
  34  B/September 1991)", Maxtor Corporation, 1991.
  35 
  36  "7213S product Manual (Revision P3)", Maxtor Corporation, 1992.
  37 
  38  Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric
  39  Youngdale (eric@tantalus.nrl.navy.mil), 1992.
  40 
  41 
  42  NOTES ON REFERENCES:
  43 
  44  The Maxtor manuals were free.  Maxtor telephone technical support is
  45  great!
  46 
  47  The Future Domain manual is $25.  It documents the chip, not the TMC-16x0
  48  boards, so some information I had to guess at.  Future Domain sells DOS
  49  BIOS source for $250 and the UN*X driver source was $750, but these
  50  require a non-disclosure agreement, so even if I could afford them, they
  51  would *not* have been useful for writing this publically distributable
  52  driver.  Future Domain technical support has provided some information on
  53  the phone, and this has been somewhat helpful.
  54 
  55 
  56  ALPHA TESTERS:
  57 
  58  Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken
  59  Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@dutiba.tudelft.nl),
  60  Sakari Aaltonen (sakaria@vipunen.hit.fi), John Rice
  61  (rice@xanth.cs.odu.edu), and Brad Yearwood (brad@optilink.com).
  62 
  63 
  64  NOTES ON USER DEFINABLE OPTIONS:
  65 
  66  DEBUG: This turns on the printing of various debug informaiton.
  67 
  68  ENABLE_PARITY: This turns on SCSI parity checking.  With the current
  69  driver, all attached devices must support SCSI parity.  If none of your
  70  devices support parity, then you can probably get the driver to work by
  71  turning this option off.  I have no way of testing this, however.
  72 
  73  QUEUE: Enable "command queueing."  This is supported by the higher level
  74  SCSI code, and allows the kernel to continue to schedule tasks while the
  75  SCSI request is pending.  If this option is turned off, then everything
  76  will "freeze" during SCSI requests, and system performance will become
  77  unbearable.  Later, this will allow multiple outstanding SCSI requests.  I
  78  have received reports that if this option is turned off, the driver will
  79  no longer function correctly.  I have not had time to track down this bug,
  80  since I hope to make the driver work for everyone with QUEUE on.
  81 
  82  FIFO_COUNT: The host adapter has an 8K cache.  When this many 512 byte
  83  blocks are filled by the SCSI device, an interrupt will be raised.
  84  Therefore, this could be as low as 0, or as high as 16.  Note, however,
  85  that values which are too high or too low seem to prevent any interrupts
  86  from occuring, and thereby lock up the machine.  I have found that 2 is a
  87  good number, but throughput may be increased by changing this value to
  88  values which are close to 2.  Please let me know if you try any different
  89  values.
  90 
  91  DO_DETECT: This activates some old scan code which was needed before the
  92  high level drivers got fixed.  If you are having toruble with the driver,
  93  turning this on should not hurt, and might help.  Please let me know if
  94  this is the case, since this code will be removed from future drivers.
  95 
  96  RESELECTION: DO *NOT* USE THIS OPTION!  This turns on SCSI device
  97  disconnect and reselection, which does not work at this time.  When I get
  98  this working, it will support multiple outstanding SCSI commands.
  99 
 100  **************************************************************************/
 101 
 102 #include <linux/sched.h>
 103 #include <asm/io.h>
 104 #include "../blk.h"
 105 #include "scsi.h"
 106 #include "hosts.h"
 107 #include "fdomain.h"
 108 #include <asm/system.h>
 109 #include <linux/errno.h>
 110 
 111 #define VERSION          "3.3"  /* Change with each revision */
 112 
 113 /* START OF USER DEFINABLE OPTIONS */
 114 
 115 #define DEBUG            1      /* Enable debugging output */
 116 #define ENABLE_PARITY    1      /* Enable SCSI Parity */
 117 #define QUEUE            1      /* Enable command queueing */
 118 #define FIFO_COUNT       2      /* Number of 512 byte blocks before INTR */
 119 #define DO_DETECT        0      /* Do device detection here (see scsi.c) */
 120 #define RESELECTION      0      /* Support RESELECTION PHASE (NOT stable) */
 121 
 122 /* END OF USER DEFINABLE OPTIONS */
 123 
 124 #if DEBUG
 125 #define EVERY_ACCESS     0      /* Write a line on every scsi access */
 126 #define ERRORS_ONLY      1      /* Only write a line if there is an error */
 127 #define DEBUG_DETECT     0      /* Debug fdomain_16x0_detect() */
 128 #define DEBUG_MESSAGES   0      /* Debug MESSAGE IN PHASE */
 129 #define DEBUG_ABORT      1      /* Debug abort() routine */
 130 #else
 131 #define EVERY_ACCESS     0      /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
 132 #define ERRORS_ONLY      0
 133 #define DEBUG_DETECT     0
 134 #define DEBUG_MESSAGES   0
 135 #define DEBUG_ABORT      0
 136 #endif
 137 
 138 /* Errors are reported on the line, so we don't need to report them again */
 139 #if EVERY_ACCESS
 140 #undef ERRORS_ONLY
 141 #define ERRORS_ONLY      0
 142 #endif
 143 
 144 #if ENABLE_PARITY
 145 #define PARITY_MASK      0x08
 146 #else
 147 #define PARITY_MASK      0x00
 148 #endif
 149 
 150 static int               port_base = 0;
 151 static void              *bios_base = NULL;
 152 static int               interrupt_level = 0;
 153 
 154 static int               Data_Mode_Cntl_port;
 155 static int               FIFO_Data_Count_port;
 156 static int               Interrupt_Cntl_port;
 157 static int               Interrupt_Mask_port;
 158 static int               Read_FIFO_port;
 159 static int               Read_SCSI_Data_port;
 160 static int               SCSI_Cntl_port;
 161 static int               SCSI_Data_NoACK_port;
 162 static int               SCSI_Status_port;
 163 static int               TMC_Cntl_port;
 164 static int               TMC_Status_port;
 165 static int               Write_FIFO_port;
 166 static int               Write_SCSI_Data_port;
 167 
 168 static int               this_host = 0;
 169 static int               can_queue = QUEUE;
 170 
 171 static volatile int      in_command = 0;
 172 static volatile int      in_interrupt_code = 0;
 173 static Scsi_Cmnd         *current_SC = NULL;
 174 
 175 enum { non_queueing   = 0x01,
 176        in_arbitration = 0x02,
 177        in_selection   = 0x04,
 178        in_other       = 0x08,
 179        disconnect     = 0x10,
 180        aborted        = 0x20,
 181        sent_ident     = 0x40,
 182      };
 183 
 184 extern void              fdomain_16x0_intr( int unused );
 185 
 186 enum in_port_type { Read_SCSI_Data = 0, SCSI_Status = 1, TMC_Status = 2,
 187                           LSB_ID_Code = 5, MSB_ID_Code = 6, Read_Loopback = 7,
 188                           SCSI_Data_NoACK = 8, Interrupt_Mask = 9,
 189                           Option_Select = 10, Read_FIFO = 12,
 190                           FIFO_Data_Count = 14 };
 191 
 192 enum out_port_type { Write_SCSI_Data = 0, SCSI_Cntl = 1, Interrupt_Cntl = 2,
 193                            Data_Mode_Cntl = 3, TMC_Cntl = 4, Write_Loopback = 7,
 194                            Write_FIFO = 12 };
 195 
 196 static void *addresses[] = {
 197    (void *)0xc8000,
 198    (void *)0xca000,
 199    (void *)0xce000,
 200    (void *)0xde000 };
 201 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
 202                        
 203 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
 204 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
 205 
 206 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 207 
 208 /*
 209 
 210   READ THIS BEFORE YOU ADD A SIGNATURE!
 211 
 212   READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
 213 
 214   READ EVERY WORD, ESPECIALLY THE WORD *NOT*
 215 
 216   This driver works *ONLY* for Future Domain cards using the TMC-1800 chip.
 217   This includes models TMC-1660, 1670, and 1680 *ONLY*.
 218 
 219   The following BIOS signatures have been tried with this driver.  These
 220   signatures are for boards which do *NOT* work with this driver (but the
 221   first one should work with the Seagate driver):
 222 
 223       FUTURE DOMAIN COPR. (C) 1986-1989 V6.0A7/28/90
 224       FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
 225       FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
 226 
 227   */
 228 
 229 struct signature {
 230    char *signature;
 231    int  sig_offset;
 232    int  sig_length;
 233 } signatures[] = {
 234    /*          1         2         3         4         5         6 */
 235    /* 123456789012345678901234567890123456789012345678901234567890 */
 236    { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50 },
 237    { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44 },
 238    /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE */
 239 };
 240 
 241 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
 242 
 243 
 244 /* These functions are based on include/asm/io.h */
 245 
 246 inline static unsigned short inw( unsigned short port )
 247 {
 248    unsigned short _v;
 249    
 250    __asm__ volatile ("inw %1,%0"
 251                      :"=a" (_v):"d" ((unsigned short) port));
 252    return _v;
 253 }
 254 
 255 inline static void outw( unsigned short value, unsigned short port )
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257    __asm__ volatile ("outw %0,%1"
 258                      ::"a" ((unsigned short) value),
 259                      "d" ((unsigned short) port));
 260 }
 261 
 262 
 263 /* These defines are copied from kernel/blk_drv/hd.c */
 264 
 265 #define insw( buf, count, port ) \
 266       __asm__ volatile \
 267       ( "cld;rep;insw"::"d" (port),"D" (buf),"c" (count):"cx","di" )
 268 
 269 #define outsw( buf, count, port ) \
 270       __asm__ volatile \
 271       ("cld;rep;outsw"::"d" (port),"S" (buf),"c" (count):"cx","si")
 272 
 273 
 274 static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
     /* [previous][next][first][last][top][bottom][index][help] */
 275 {
 276    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 277 
 278    while (jiffies < the_time);
 279 }
 280 
 281 inline static void fdomain_make_bus_idle( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283    outb( 0, SCSI_Cntl_port );
 284    outb( 0, Data_Mode_Cntl_port );
 285    outb( 1 | PARITY_MASK, TMC_Cntl_port );
 286 }
 287 
 288 static int fdomain_is_valid_port( int port )
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290    int options;
 291 
 292 #if DEBUG_DETECT 
 293    printk( " (%x%x),",
 294           inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
 295 #endif
 296 
 297    /* The MCA ID is a unique id for each MCA compatible board.  We
 298       are using ISA boards, but Future Domain provides the MCA ID
 299       anyway.  We can use this ID to ensure that this is a Future
 300       Domain TMC-1660/TMC-1680.
 301     */
 302 
 303    if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
 304       if (inb( port + LSB_ID_Code ) != 0x27) return 0;
 305       if (inb( port + MSB_ID_Code ) != 0x61) return 0;
 306    } else {                                 /* test for 0xe960 id */
 307       if (inb( port + MSB_ID_Code ) != 0x60) return 0;
 308    }
 309 
 310    /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
 311       Now, check to be sure the bios_base matches these ports.
 312       If someone was unlucky enough to have purchased more than one
 313       Future Domain board, then they will have to modify this code, as
 314       we only detect one board here.  [The one with the lowest bios_base.]
 315     */
 316 
 317    options = inb( port + Option_Select );
 318 
 319 #if DEBUG_DETECT
 320    printk( " Options = %x,", options );
 321 #endif
 322 
 323    if (addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
 324    interrupt_level = ints[ (options & 0x0e) >> 1 ];
 325 
 326    return 1;
 327 }
 328 
 329 static int fdomain_test_loopback( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 330 {
 331    int i;
 332    int result;
 333 
 334    for (i = 0; i < 255; i++) {
 335       outb( i, port_base + Write_Loopback );
 336       result = inb( port_base + Read_Loopback );
 337       if (i != result) return 1;
 338    }
 339    return 0;
 340 }
 341 
 342 int fdomain_16x0_detect( int hostnum )
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344    int              i, j;
 345    int              flag;
 346    struct sigaction sa;
 347    int              retcode;
 348 #if DO_DETECT
 349    const int        buflen = 255;
 350    Scsi_Cmnd        SCinit;
 351    unsigned char    do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
 352    unsigned char    do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
 353    unsigned char    do_read_capacity[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 354    unsigned char    buf[buflen];
 355 #endif
 356 
 357 #if DEBUG_DETECT
 358    printk( "SCSI: fdomain_16x0_detect()," );
 359 #endif
 360 
 361    for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
 362 #if DEBUG_DETECT
 363       printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
 364 #endif
 365       for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
 366          if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
 367                     signatures[j].signature, signatures[j].sig_length )) {
 368             bios_base = addresses[i];
 369          }
 370       }
 371    }
 372 
 373    if (!bios_base) {
 374 #if DEBUG_DETECT
 375       printk( " FAILED: NO BIOS\n" );
 376 #endif
 377       return 0;
 378    }
 379 
 380    /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 381       Assuming the ROM is enabled (otherwise we wouldn't have been
 382       able to read the ROM signature :-), then the ROM sets up the
 383       RAM area with some magic numbers, such as a list of port
 384       base addresses and a list of the disk "geometry" reported to
 385       DOS (this geometry has nothing to do with physical geometry).
 386     */
 387 
 388    port_base = *((char *)bios_base + 0x1fcc)
 389          + (*((char *)bios_base + 0x1fcd) << 8);
 390    
 391 #if DEBUG_DETECT
 392    printk( " %x,", port_base );
 393 #endif
 394 
 395    for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 396       if (port_base == ports[i]) ++flag;
 397    }
 398 
 399    if (flag) flag = fdomain_is_valid_port( port_base );
 400 
 401    if (!flag) {                 /* Cannot get port base from BIOS RAM */
 402       
 403       /* This is a bad sign.  It usually means that someone patched the
 404          BIOS signature list (the signatures variable) to contain a BIOS
 405          signature for a board *OTHER THAN* the TMC-1660/TMC-1680.
 406        */
 407       
 408 #if DEBUG_DETECT
 409       printk( " RAM FAILED, " );
 410 #endif
 411 
 412       /* Anyway, the alternative to finding the address in the RAM is
 413          to just search through every possible port address for one
 414          that is attached to the Future Domain card.  Don't panic,
 415          though, about reading all these random port addresses--there
 416          are rumors that the Future Domain BIOS does something very
 417          similar.
 418        */
 419 
 420       for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 421          port_base = ports[i];
 422 #if DEBUG_DETECT
 423          printk( " %x,", port_base );
 424 #endif
 425          flag = fdomain_is_valid_port( port_base );
 426       }
 427    }
 428 
 429    if (!flag) {
 430 #if DEBUG_DETECT
 431       printk( " FAILED: NO PORT\n" );
 432 #endif
 433       return 0;         /* Cannot find valid set of ports */
 434    }
 435 
 436 #if DEBUG_DETECT
 437    printk( "\n" );
 438    printk( "SCSI: bios_base = %x, port_base = %x, interrupt_level = %d\n",
 439           (unsigned)bios_base, port_base, interrupt_level );
 440 #endif
 441 
 442    if (interrupt_level) {
 443       printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
 444              (unsigned)bios_base, port_base, interrupt_level );
 445    } else {
 446       printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
 447              (unsigned)bios_base, port_base );
 448    }
 449    
 450    Data_Mode_Cntl_port  = port_base + Data_Mode_Cntl;
 451    FIFO_Data_Count_port = port_base + FIFO_Data_Count;
 452    Interrupt_Cntl_port  = port_base + Interrupt_Cntl;
 453    Interrupt_Mask_port  = port_base + Interrupt_Mask;
 454    Read_FIFO_port       = port_base + Read_FIFO;
 455    Read_SCSI_Data_port  = port_base + Read_SCSI_Data;
 456    SCSI_Cntl_port       = port_base + SCSI_Cntl;
 457    SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
 458    SCSI_Status_port     = port_base + SCSI_Status;
 459    TMC_Cntl_port        = port_base + TMC_Cntl;
 460    TMC_Status_port      = port_base + TMC_Status;
 461    Write_FIFO_port      = port_base + Write_FIFO;
 462    Write_SCSI_Data_port = port_base + Write_SCSI_Data;
 463 
 464     fdomain_16x0_reset();
 465 
 466    if (fdomain_test_loopback()) {
 467 #if DEBUG_DETECT
 468       printk( "SCSI: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
 469 #endif
 470       return 0;
 471    }
 472 
 473 #if DO_DETECT
 474 
 475    /* These routines are here because of the way the SCSI bus behaves after
 476       a reset.  This appropriate behavior was not handled correctly by the
 477       higher level SCSI routines when I first wrote this driver.  Now,
 478       however, correct scan routines are part of scsi.c and these routines
 479       are no longer needed.  However, this code is still good for
 480       debugging.
 481     */
 482 
 483    SCinit.request_buffer = SCinit.buffer = buf;
 484    SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
 485    SCinit.use_sg = 0;
 486    SCinit.lun = 0;
 487 
 488    printk( "Future Domain detection routine scanning for devices:\n" );
 489    for (i = 0; i < 8; i++) {
 490       SCinit.target = i;
 491       if (i == 6) continue;     /* The host adapter is at SCSI ID 6 */
 492       memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 493       retcode = fdomain_16x0_command(&SCinit);
 494       if (!retcode) {
 495          memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
 496          retcode = fdomain_16x0_command(&SCinit);
 497          if (!retcode) {
 498             printk( "     SCSI ID %d: ", i );
 499             for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
 500                   printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
 501             memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
 502             retcode = fdomain_16x0_command(&SCinit);
 503             if (!retcode) {
 504                unsigned long blocks, size, capacity;
 505                
 506                blocks = (buf[0] << 24) | (buf[1] << 16)
 507                      | (buf[2] << 8) | buf[3];
 508                size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
 509                capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
 510 
 511                printk( "%lu MB (%lu byte blocks)",
 512                       ((capacity + 5L) / 10L), size );
 513             } else {
 514                memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 515                retcode = fdomain_16x0_command(&SCinit);
 516             }
 517             printk ("\n" );
 518          } else {
 519             memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 520             retcode = fdomain_16x0_command(&SCinit);
 521          }
 522       }
 523    }
 524 #endif
 525 
 526    this_host      = hostnum;
 527    
 528    if (!QUEUE || !interrupt_level) {
 529       printk( "Future Domain: *NO* interrupt level selected!\n" );
 530       printk( "               COMMAND QUEUEING DISABLED!\n" );
 531       can_queue = scsi_hosts[this_host].can_queue = 0;
 532       scsi_hosts[this_host].sg_tablesize = SG_NONE;
 533    } else {
 534       /* Register the IRQ with the kernel */
 535 
 536       sa.sa_handler  = fdomain_16x0_intr;
 537       sa.sa_flags    = SA_INTERRUPT;
 538       sa.sa_mask     = 0;
 539       sa.sa_restorer = NULL;
 540       
 541       retcode = irqaction( interrupt_level, &sa );
 542 
 543       if (retcode < 0) {
 544          if (retcode == -EINVAL) {
 545             printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
 546             printk( "               This shouldn't happen: REPORT TO RIK!\n" );
 547          } else if (retcode == -EBUSY) {
 548             printk( "Future Domain: IRQ %d is already in use!\n",
 549                    interrupt_level );
 550             printk( "               Please use another IRQ for the FD card!\n" );
 551          } else {
 552             printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
 553             printk( "               This shouldn't happen: REPORT TO RIK!\n" );
 554          }
 555          printk( "               COMMAND QUEUEING DISABLED!\n" );
 556       
 557          can_queue = scsi_hosts[this_host].can_queue = 0;
 558          scsi_hosts[this_host].sg_tablesize = SG_NONE;
 559       } else {
 560          printk( "Future Domain: IRQ %d requested from kernel\n",
 561                 interrupt_level );
 562       }
 563    }
 564    
 565    return 1;
 566 }
 567 
 568 const char *fdomain_16x0_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 569 {
 570    static char buffer[] =
 571          "Future Domain TMC-16x0 SCSI driver version "
 572                VERSION
 573                      "\n";
 574    return buffer;
 575 }
 576 
 577 static int fdomain_arbitrate( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 578 {
 579    int           status = 0;
 580    unsigned long timeout;
 581 
 582 #if EVERY_ACCESS
 583    printk( "SCSI: fdomain_arbitrate()\n" );
 584 #endif
 585    
 586    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
 587    outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
 588    outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
 589 
 590    timeout = jiffies + 50;                    /* 500 mS */
 591    while (jiffies < timeout) {
 592       status = inb( TMC_Status_port );        /* Read adapter status */
 593       if (status & 0x02) return 0;            /* Arbitration complete */
 594    }
 595 
 596    /* Make bus idle */
 597    fdomain_make_bus_idle();
 598 
 599 #if EVERY_ACCESS
 600    printk( "Arbitration failed, status = %x\n", status );
 601 #endif
 602 #if ERRORS_ONLY
 603    printk( "SCSI (Future Domain): Arbitration failed, status = %x",
 604           status );
 605 #endif
 606    return 1;
 607 }
 608 
 609 static int fdomain_select( int target )
     /* [previous][next][first][last][top][bottom][index][help] */
 610 {
 611    int           status;
 612    unsigned long timeout;
 613 
 614    /* Send our address OR'd with target address */
 615    outb( 0x40 | (1 << target), SCSI_Data_NoACK_port );
 616 
 617    if (RESELECTION && can_queue)
 618          outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
 619    else
 620          outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 621 
 622    /* Stop arbitration (also set FIFO for output and enable parity) */
 623    outb( 0xc0 | PARITY_MASK, TMC_Cntl_port ); 
 624 
 625    timeout = jiffies + 25;              /* 250mS */
 626    while (jiffies < timeout) {
 627       status = inb( SCSI_Status_port ); /* Read adapter status */
 628       if (status & 1) {                 /* Busy asserted */
 629          /* Enable SCSI Bus (on error, should make bus idle with 0) */
 630          outb( 0x80, SCSI_Cntl_port );
 631          return 0;
 632       }
 633    }
 634    /* Make bus idle */
 635    fdomain_make_bus_idle();
 636 #if EVERY_ACCESS
 637    if (!target) printk( "Selection failed\n" );
 638 #endif
 639 #if ERRORS_ONLY
 640    if (!target) printk( "SCSI (Future Domain): Selection failed" );
 641 #endif
 642    return 1;
 643 }
 644 
 645 void my_done( int error )
     /* [previous][next][first][last][top][bottom][index][help] */
 646 {
 647    if (in_command) {
 648       in_command = 0;
 649       in_interrupt_code = 0;
 650       outb( 0x00, Interrupt_Cntl_port );
 651       fdomain_make_bus_idle();
 652       current_SC->result = error;
 653       if (current_SC->scsi_done) current_SC->scsi_done( current_SC );
 654       else panic( "SCSI (Future Domain): current_SC->scsi_done() == NULL" );
 655    } else {
 656       panic( "SCSI (Future Domain): my_done() called outside of command\n" );
 657    }
 658 }
 659 
 660 void fdomain_16x0_intr( int unused )
     /* [previous][next][first][last][top][bottom][index][help] */
 661 {
 662    int      status;
 663    int      done = 0;
 664    unsigned data_count;
 665 
 666    sti();
 667 
 668    if (in_interrupt_code)
 669          panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
 670    else
 671          ++in_interrupt_code;
 672    
 673    outb( 0x00, Interrupt_Cntl_port );
 674 
 675    if (current_SC->SCp.phase & aborted) {
 676 #if EVERY_ACCESS
 677       if (current_SC->SCp.phase & (in_other || disconnect))
 678             printk( "aborted (%s) = %d, ",
 679                    current_SC->SCp.phase & in_other
 680                    ? "in_other" : "disconnect",
 681                    current_SC->result );
 682       else
 683             printk( "aborted = %d, ",
 684                    current_SC->result );
 685 #endif
 686       /* Force retry for timeouts after selection complete */
 687       if (current_SC->SCp.phase & (in_other || disconnect)) {
 688          fdomain_16x0_reset();
 689          my_done( DID_RESET << 16 );
 690       } else {
 691          my_done( current_SC->result << 16 );
 692       }
 693       return;
 694    }
 695 
 696    /* We usually have one spurious interrupt after each command.  Ignore it. */
 697    if (!in_command) {           /* Spurious interrupt */
 698       in_interrupt_code = 0;
 699       return;
 700    }
 701 
 702 #if RESELECTION
 703    if (current_SC->SCp.phase & disconnect) {
 704       printk( " RECON %x ", inb( SCSI_Data_NoACK_port ) );
 705       current_SC->SCp.phase = in_other;
 706       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 707       outb( 0x84, SCSI_Cntl_port );
 708       while ( (status = inb( SCSI_Status_port )) & 0x20 ) {
 709          printk( "s = %x, ", status );
 710       }
 711       outb( 0x80, SCSI_Cntl_port );
 712    } else
 713 #endif
 714          if (current_SC->SCp.phase & in_arbitration) {
 715       status = inb( TMC_Status_port );        /* Read adapter status */
 716       if (!(status & 0x02)) {
 717 #if EVERY_ACCESS
 718          printk( " AFAIL " );
 719 #endif
 720          my_done( DID_BUS_BUSY << 16 );
 721          return;
 722       }
 723       current_SC->SCp.phase = in_selection;
 724 
 725       outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
 726 
 727       outb( 0x40 | (1 << current_SC->target), SCSI_Data_NoACK_port );
 728 
 729 #if RESELECTION
 730       outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
 731 #else
 732       outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 733 #endif
 734 
 735       /* Stop arbitration (also set FIFO for output and enable parity) */
 736       outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 737 
 738       in_interrupt_code = 0;
 739       return;
 740    } else if (current_SC->SCp.phase & in_selection) {
 741       status = inb( SCSI_Status_port );
 742       if (!(status & 0x01)) {
 743          /* Try again, for slow devices */
 744          if (fdomain_select( current_SC->target )) {
 745 #if EVERY_ACCESS
 746             printk( " SFAIL " );
 747 #endif
 748             my_done( DID_NO_CONNECT << 16 );
 749             return;
 750          } else {
 751 #if EVERY_ACCESS
 752          printk( " AltSel " );
 753 #endif
 754          /* Stop arbitration (also set FIFO for output and enable parity) */
 755          outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 756        }
 757       }
 758       current_SC->SCp.phase = in_other;
 759       in_interrupt_code = 0;
 760       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 761 #if RESELECTION
 762       outb( 0x88, SCSI_Cntl_port );
 763 #else
 764       outb( 0x80, SCSI_Cntl_port );
 765 #endif
 766       return;
 767    }
 768 
 769    /* current_SC->SCp.phase == in_other: this is the body of the routine */
 770 
 771    switch (current_SC->cmnd[0]) {
 772    case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
 773    case 0x2e: case 0x3b: case 0xea: case 0x3f:
 774       while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
 775 #if EVERY_ACCESS
 776          printk( "DC=%d, ", data_count );
 777 #endif
 778          if (data_count > current_SC->SCp.this_residual)
 779                data_count = current_SC->SCp.this_residual;
 780          if (data_count > 0) {
 781 #if EVERY_ACCESS
 782             printk( "%d OUT, ", data_count );
 783 #endif
 784             if (data_count == 1) {
 785                outb( *current_SC->SCp.ptr++, Write_FIFO_port );
 786                --current_SC->SCp.this_residual;
 787             } else {
 788                data_count >>= 1;
 789                outsw( current_SC->SCp.ptr, data_count, Write_FIFO_port );
 790                current_SC->SCp.ptr += 2 * data_count;
 791                current_SC->SCp.this_residual -= 2 * data_count;
 792             }
 793          }
 794          if (!current_SC->SCp.this_residual) {
 795             if (current_SC->SCp.buffers_residual) {
 796                --current_SC->SCp.buffers_residual;
 797                ++current_SC->SCp.buffer;
 798                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 799                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 800             } else
 801                   break;
 802          }
 803       }
 804       break;
 805    default:
 806       if (!current_SC->SCp.have_data_in) {
 807          outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
 808          ++current_SC->SCp.have_data_in;
 809       } else {
 810          while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
 811 #if EVERY_ACCESS
 812             printk( "DC=%d, ", data_count );
 813 #endif
 814             if (data_count > current_SC->SCp.this_residual)
 815                   data_count = current_SC->SCp.this_residual;
 816             if (data_count) {
 817 #if EVERY_ACCESS
 818                printk( "%d IN, ", data_count );
 819 #endif
 820                if (data_count == 1) {
 821                   *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
 822                   --current_SC->SCp.this_residual;
 823                } else {
 824                   data_count >>= 1; /* Number of words */
 825                   insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
 826                   current_SC->SCp.ptr += 2 * data_count;
 827                   current_SC->SCp.this_residual -= 2 * data_count;
 828                }
 829             }
 830             if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
 831                --current_SC->SCp.buffers_residual;
 832                ++current_SC->SCp.buffer;
 833                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 834                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 835             }
 836          }
 837       }
 838       break;
 839    }
 840 
 841    status = inb( SCSI_Status_port );
 842 
 843    if (status & 0x10) { /* REQ */
 844       
 845       switch (status & 0x0e) {
 846       case 0x08:                /* COMMAND OUT */
 847 #if 0
 848          if (!current_SC->SCp.sent_command) {
 849             int i;
 850             
 851             ++current_SC->SCp.sent_command;
 852             
 853             for (i = 0; i < COMMAND_SIZE( current_SC->cmnd[0] ); i++) {
 854                outb( current_SC->cmnd[i], Write_SCSI_Data_port );
 855 #if EVERY_ACCESS
 856                printk( "CMD = %x,", current_SC->cmnd[i] );
 857 #endif
 858             }
 859          }
 860 #else
 861          outb( current_SC->cmnd[current_SC->SCp.sent_command++],
 862                Write_SCSI_Data_port );
 863 #if EVERY_ACCESS
 864          printk( "CMD = %x,",
 865                  current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
 866 #endif
 867             
 868 #endif
 869          break;
 870       case 0x0c:                /* STATUS IN */
 871          current_SC->SCp.Status = inb( Read_SCSI_Data_port );
 872 #if EVERY_ACCESS
 873          printk( "Status = %x, ", current_SC->SCp.Status );
 874 #endif
 875 #if ERRORS_ONLY
 876          if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
 877             printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
 878                    current_SC->target, current_SC->cmnd[0], current_SC->SCp.Status );
 879          }
 880 #endif
 881          break;
 882       case 0x0a:                /* MESSAGE OUT */
 883 #if RESELECTION
 884          if (!(current_SC->SCp.phase & sent_ident)) {
 885 #if EVERY_ACCESS
 886             printk( " IDENT " );
 887 #endif
 888             outb( 0x80, SCSI_Cntl_port );
 889             outb( IDENTIFY( 1, 0 ), Write_SCSI_Data_port );
 890             current_SC->SCp.phase |= sent_ident;
 891          } else
 892 #else
 893                outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
 894 #endif
 895          break;
 896       case 0x0e:                /* MESSAGE IN */
 897          current_SC->SCp.Message = inb( Read_SCSI_Data_port );
 898 #if EVERY_ACCESS
 899          printk( "Message = %x, ", current_SC->SCp.Message );
 900 #endif
 901          if (!current_SC->SCp.Message) ++done;
 902 #if RESELECTION
 903          if (current_SC->SCp.Message == DISCONNECT) {
 904             printk( " DISCON " );
 905             current_SC->SCp.phase = disconnect;
 906          }
 907 #endif
 908 #if DEBUG_MESSAGES || EVERY_ACCESS
 909          if (current_SC->SCp.Message) {
 910             printk( "SCSI (Future Domain): Message = %x\n",
 911                    current_SC->SCp.Message );
 912          }
 913 #endif
 914          break;
 915       }
 916    }
 917 
 918    if (done) {
 919 #if EVERY_ACCESS
 920       printk( " ** IN DONE ** " );
 921 #endif
 922 
 923       if (current_SC->SCp.have_data_in) {
 924          while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
 925             if (data_count > current_SC->SCp.this_residual)
 926                   data_count = current_SC->SCp.this_residual;
 927 
 928             if (data_count) {
 929 #if EVERY_ACCESS
 930                printk( "%d IN, ", data_count );
 931 #endif
 932                if (data_count == 1) {
 933                   *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
 934                   --current_SC->SCp.this_residual;
 935                } else {
 936                   data_count >>= 1; /* Number of words */
 937                   insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
 938                   current_SC->SCp.this_residual -= 2 * data_count;
 939                }
 940             }
 941 
 942             if (!current_SC->SCp.this_residual
 943                 && current_SC->SCp.buffers_residual) {
 944                
 945                --current_SC->SCp.buffers_residual;
 946                ++current_SC->SCp.buffer;
 947                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 948                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 949             }
 950          }
 951       }
 952 #if EVERY_ACCESS
 953       printk( "AFTER DATA GET\n" );
 954 #endif
 955       
 956 #if ERRORS_ONLY
 957       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
 958          if ((unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f) {
 959             unsigned char key;
 960             unsigned char code;
 961 
 962             key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f;
 963             code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
 964 
 965             if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
 966                 && !(key == ILLEGAL_REQUEST && (code == 0x25 || !code)))
 967                 
 968                 printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
 969                        key, code );
 970          }
 971       }
 972 #endif
 973 #if EVERY_ACCESS
 974       printk( "BEFORE MY_DONE. . ." );
 975 #endif
 976       my_done( (current_SC->SCp.Status & 0xff) | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
 977 #if EVERY_ACCESS
 978       printk( "RETURNING.\n" );
 979 #endif
 980       
 981    } else {
 982       in_interrupt_code = 0;
 983       if (current_SC->SCp.phase & disconnect) {
 984          outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
 985          outb( 0x00, SCSI_Cntl_port );
 986       } else {
 987          outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 988       }
 989    }
 990 
 991    return;
 992 }
 993 
 994 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 995 {
 996    if (in_command) {
 997       panic( "SCSI (Future Domain): fdomain_16x0_queue() NOT REENTRANT!\n" );
 998    }
 999 #if EVERY_ACCESS
1000    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1001            SCpnt->target,
1002            *(unsigned char *)SCpnt->cmnd,
1003            SCpnt->use_sg,
1004            SCpnt->request_bufflen );
1005 #endif
1006 
1007    fdomain_make_bus_idle();
1008 
1009    current_SC            = SCpnt; /* Save this for the done function */
1010    current_SC->scsi_done = done;
1011 
1012    /* Initialize static data */
1013 
1014    if (current_SC->use_sg) {
1015       current_SC->SCp.buffer =
1016             (struct scatterlist *)current_SC->request_buffer;
1017       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
1018       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
1019       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1020    } else {
1021       current_SC->SCp.ptr              = current_SC->request_buffer;
1022       current_SC->SCp.this_residual    = current_SC->request_bufflen;
1023       current_SC->SCp.buffer           = NULL;
1024       current_SC->SCp.buffers_residual = 0;
1025    }
1026          
1027    
1028    current_SC->SCp.Status              = 0;
1029    current_SC->SCp.Message             = 0;
1030    current_SC->SCp.have_data_in        = 0;
1031    current_SC->SCp.sent_command        = 0;
1032    current_SC->SCp.phase               = in_arbitration;
1033 
1034    /* Start arbitration */
1035    outb( 0x00, Interrupt_Cntl_port );
1036    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
1037    outb( 0x40, SCSI_Data_NoACK_port );        /* Set our id bit */
1038    ++in_command;
1039    outb( 0x20, Interrupt_Cntl_port );
1040    outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1041 
1042    return 0;
1043 }
1044 
1045 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1046 {
1047    const char     *cmd_pt = SCpnt->cmnd;
1048    const char     *the_command = SCpnt->cmnd;
1049    unsigned char  *out_buf_pt = SCpnt->request_buffer;
1050    unsigned char  *in_buf_pt = SCpnt->request_buffer;
1051    unsigned char  target = SCpnt->target;
1052    void           *buff = SCpnt->request_buffer;
1053    int            bufflen = SCpnt->request_bufflen;
1054    int            Status = 0;
1055    int            Message = 0;
1056    int            status;
1057    int            done = 0;
1058    unsigned long  timeout;
1059    unsigned       data_sent = 0;
1060    unsigned       data_count;
1061    int            have_data_in = 0;
1062 
1063    current_SC = SCpnt;
1064 
1065 #if EVERY_ACCESS
1066    printk( "fdomain_command(%d, %x): ", target, (unsigned char)*the_command );
1067 #endif
1068 
1069    if (fdomain_arbitrate()) {
1070 #if ERRORS_ONLY
1071       printk( ", target = %d, command = %x\n",
1072              target, (unsigned char)*the_command );
1073 #endif
1074       return DID_TIME_OUT << 16;
1075    }
1076 
1077    if (fdomain_select( target )) {
1078 #if ERRORS_ONLY
1079       if (!target) printk( ", target = %d, command = %x\n",
1080                          target, (unsigned char)*the_command );
1081 #endif
1082       return DID_NO_CONNECT << 16;
1083    }
1084 
1085    timeout = jiffies + 500;     /* 5000 mS -- For Maxtor after a RST */
1086    current_SC->SCp.phase = non_queueing;
1087 
1088    switch ((unsigned char)*the_command) {
1089    case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
1090    case 0x2e: case 0x3b: case 0xea: case 0x3f:
1091       data_count = 0x2000 - inw( FIFO_Data_Count_port );
1092       if (bufflen - data_sent < data_count)
1093             data_count = bufflen - data_sent;
1094       if (data_count == 1) {
1095          outb( *out_buf_pt++, Write_FIFO_port );
1096          ++data_sent;
1097       } else {
1098          data_count >>= 1;
1099          outsw( out_buf_pt, data_count, Write_FIFO_port );
1100          out_buf_pt += 2 * data_count;
1101          data_sent += 2 * data_count;
1102       }
1103       break;
1104    default:
1105       outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
1106       ++have_data_in;
1107       break;
1108    }
1109    
1110    while (((status = inb( SCSI_Status_port )) & 1)
1111           && !done && !(current_SC->SCp.phase & aborted)
1112           && jiffies < timeout) {
1113       
1114       if (status & 0x10) {      /* REQ */
1115 
1116          switch (status & 0x0e) {
1117          case 0x00:             /* DATA OUT */
1118             data_count = 0x2000 - inw( FIFO_Data_Count_port );
1119             if (bufflen - data_sent < data_count)
1120                   data_count = bufflen - data_sent;
1121             if (data_count == 1) {
1122                outb( *out_buf_pt++, Write_FIFO_port );
1123                ++data_sent;
1124             } else {
1125                data_count >>= 1;
1126                outsw( out_buf_pt, data_count, Write_FIFO_port );
1127                out_buf_pt += 2 * data_count;
1128                data_sent += 2 * data_count;
1129             }
1130             break;
1131          case 0x04:             /* DATA IN */
1132             if (!have_data_in) {
1133                outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
1134                ++have_data_in;
1135             }
1136             data_count = inw( FIFO_Data_Count_port );
1137             if (data_count == 1) {
1138                *in_buf_pt++ = inb( Read_FIFO_port );
1139             } else {
1140                data_count >>= 1; /* Number of words */
1141                insw( in_buf_pt, data_count, Read_FIFO_port );
1142                in_buf_pt += 2 * data_count;
1143             }
1144             break;
1145          case 0x08:             /* COMMAND OUT */
1146             outb( *cmd_pt++, Write_SCSI_Data_port );
1147 #if EVERY_ACCESS
1148             printk( "%x,", (unsigned char)cmd_pt[-1] );
1149 #endif
1150             break;
1151          case 0x0c:             /* STATUS IN */
1152             Status = inb( Read_SCSI_Data_port );
1153 #if EVERY_ACCESS
1154             printk( "Status = %x, ", Status );
1155 #endif
1156 #if ERRORS_ONLY
1157             if (Status) {
1158                printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
1159                       target, (unsigned char)*the_command, Status );
1160             }
1161 #endif
1162             break;
1163          case 0x0a:             /* MESSAGE OUT */
1164             outb( 0x07, Write_SCSI_Data_port ); /* Reject */
1165             break;
1166          case 0x0e:             /* MESSAGE IN */
1167             Message = inb( Read_SCSI_Data_port );
1168 #if EVERY_ACCESS
1169             printk( "Message = %x, ", Message );
1170 #endif
1171             if (!Message) ++done;
1172             if (Message == DISCONNECT) printk( "DISCONNECT\n" );
1173             break;
1174          }
1175       }
1176    }
1177 
1178    if (jiffies >= timeout) {
1179 #if EVERY_ACCESS
1180       printk( "Time out, status = %x\n", status );
1181 #endif
1182 #if ERRORS_ONLY
1183       printk( "SCSI (Future Domain): "
1184              "Time out, status = %x (target = %d, command = %x)\n",
1185              status, target, (unsigned char)*the_command );
1186 #endif
1187       fdomain_make_bus_idle();
1188       return DID_BUS_BUSY << 16;
1189    }
1190 
1191    if (current_SC->SCp.phase & aborted) {
1192 #if EVERY_ACCESS
1193       printk( "Aborted\n" );
1194 #endif
1195 #if ERRORS_ONLY
1196       printk( "SCSI (Future Domain): Aborted (command = %x)\n",
1197              (unsigned char)*the_command );
1198 #endif
1199       fdomain_16x0_reset();
1200       return DID_RESET << 16;
1201    }
1202    
1203    if (have_data_in) {
1204       while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
1205          if (data_count == 1) {
1206             *in_buf_pt++ = inb( Read_FIFO_port );
1207          } else {
1208             data_count >>= 1; /* Number of words */
1209             insw( in_buf_pt, data_count, Read_FIFO_port );
1210             in_buf_pt += 2 * data_count;
1211          }
1212       }
1213    }
1214 
1215    fdomain_make_bus_idle();
1216 
1217 #if EVERY_ACCESS
1218    printk( "Retcode = %x\n",
1219           (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );
1220 #endif
1221 #if ERRORS_ONLY
1222    if (*the_command == REQUEST_SENSE && !Status) {
1223       if ((unsigned char)(*((char *)buff + 2)) & 0x0f) {
1224          printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
1225                 (unsigned char)(*((char *)buff + 2)) & 0x0f,
1226                 (unsigned char)(*((char *)buff + 12)) );
1227       }
1228    }
1229 #endif
1230 
1231    return (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16);
1232 }
1233 
1234 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
     /* [previous][next][first][last][top][bottom][index][help] */
1235 {
1236 
1237 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1238    printk( "SCSI (Future Domain): Abort " );
1239 #endif
1240 
1241 #if DEBUG_ABORT
1242    printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1243     current_SC->SCp.phase,
1244     in_interrupt_code,
1245     current_SC->target,
1246     *(unsigned char *)current_SC->cmnd,
1247     current_SC->use_sg,
1248     current_SC->request_bufflen );
1249    printk( "IMR = 0x%02x%02x\n", inb( 0x0a1 ), inb( 0x21 ) );
1250    outb( 0x0a, 0xa0 );
1251    printk( "IRR = 0x%02x", inb( 0xa0 ) );
1252    outb( 0x0a, 0x20 );
1253    printk( "%02x\n", inb( 0x20 ) );
1254    outb( 0x0b, 0xa0 );
1255    printk( "ISR = 0x%02x", inb( 0xa0 ) );
1256    outb( 0x0b, 0x20 );
1257    printk( "%02x\n", inb( 0x20 ) );
1258    printk( "SCSI Status    = %x\n", inb( SCSI_Status_port ) );
1259    printk( "TMC Status     = %x\n", inb( TMC_Status_port ) );
1260    printk( "Interrupt Mask = %x\n", inb( Interrupt_Mask_port ) );
1261 #else
1262    cli();
1263    if (!in_command) {
1264 #if EVERY_ACCESS || ERRORS_ONLY
1265       printk( " (not in command)\n" );
1266 #endif
1267       sti();
1268       return 0;
1269    } else {
1270 #if EVERY_ACCESS || ERRORS_ONLY
1271       printk( " code = %d\n", code );
1272 #endif
1273    }
1274 
1275    current_SC->SCp.phase |= aborted;
1276 
1277    current_SC->result = code ? code : DID_ABORT;
1278 
1279    sti();
1280    
1281    /* Aborts are not done well. . . */
1282    my_done( code << 16 );
1283 #endif
1284    return 0;
1285 }
1286 
1287 int fdomain_16x0_reset( void )
     /* [previous][next][first][last][top][bottom][index][help] */
1288 {
1289 #if ERRORS_ONLY
1290    printk( "Future Domain: SCSI Bus Reset\n" );
1291 #endif
1292    outb( 1, SCSI_Cntl_port );
1293    do_pause( 2 );
1294    outb( 0, SCSI_Cntl_port );
1295    do_pause( 115 );
1296    outb( 0, Data_Mode_Cntl_port );
1297    outb( PARITY_MASK, TMC_Cntl_port );
1298    return 0;
1299 }
1300 
1301 int fdomain_16x0_biosparam( int size, int dev, int *info )
     /* [previous][next][first][last][top][bottom][index][help] */
1302 {
1303    int    drive;
1304    struct drive_info {
1305       unsigned short cylinders;
1306       unsigned char  heads;
1307       unsigned char  sectors;
1308    } *i;
1309 
1310    /* NOTES:
1311       The RAM area starts at 0x1f00 from the bios_base address.
1312       The drive parameter table seems to start at 0x1f30.
1313       The first byte's purpose is not known.
1314       Next is the cylinder, head, and sector information.
1315       The last 4 bytes appear to be the drive's size in sectors.
1316       The other bytes in the drive parameter table are unknown.
1317       If anyone figures them out, please send me mail, and I will
1318       update these notes.
1319 
1320       Tape drives do not get placed in this table.
1321 
1322       There is another table at 0x1fea:
1323       If the byte is 0x01, then the SCSI ID is not in use.
1324       If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1325       although tapes don't seem to be in this table.  I haven't
1326       seen any other numbers (in a limited sample).
1327 
1328       0x1f2d is a drive count (i.e., not including tapes)
1329 
1330       The table at 0x1fcc are I/O ports addresses for the various
1331       operations.  I calculate these by hand in this driver code.
1332     */
1333 
1334    drive = MINOR(dev) / 16;
1335    i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1336    info[0] = i->heads;
1337    info[1] = i->sectors;
1338    info[2] = i->cylinders;
1339    return 0;
1340 }

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