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

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