root/drivers/scsi/fdomain.c

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

DEFINITIONS

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

   1 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
   2  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
   3  * Revised: Sat Jul 30 22:06:37 1994 by faith@cs.unc.edu
   4  * Author: Rickard E. Faith, faith@cs.unc.edu
   5  * Copyright 1992, 1993, 1994 Rickard E. Faith
   6  *
   7  * $Id: fdomain.c,v 5.18 1994/07/31 03:09:15 faith Exp $
   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  * You should have received a copy of the GNU General Public License along
  20  * with this program; if not, write to the Free Software Foundation, Inc.,
  21  * 675 Mass Ave, Cambridge, MA 02139, USA.
  22 
  23  **************************************************************************
  24  
  25  DESCRIPTION:
  26 
  27  This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680
  28  TMC-1650/1670, and TMC-3260 SCSI host adapters.  The 1650 and 1670 have a
  29  25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin
  30  high-density external connector.  The 1670 and 1680 have floppy disk
  31  controllers built in.  The TMC-3260 is a PCI bus card.
  32 
  33  Future Domain's older boards are based on the TMC-1800 chip, and this
  34  driver was originally written for a TMC-1680 board with the TMC-1800 chip.
  35  More recently, boards are being produced with the TMC-18C50 and TMC-18C30
  36  chips.  The latest and greatest board may not work with this driver.  If
  37  you have to patch this driver so that it will recognize your board's BIOS
  38  signature, then the driver may fail to function after the board is
  39  detected.
  40 
  41  The following BIOS versions are supported: 2.0, 3.0, 3.2, and 3.4.
  42  The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30.
  43  Reports suggest that the driver will also work with the 36C70 chip.
  44 
  45  If you have a TMC-8xx or TMC-9xx board, then this is not the driver for
  46  your board.  Please refer to the Seagate driver for more information and
  47  possible support.
  48 
  49  
  50 
  51  REFERENCES USED:
  52 
  53  "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation,
  54  1990.
  55 
  56  "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain
  57  Corporation, January 1992.
  58 
  59  "LXT SCSI Products: Specifications and OEM Technical Manual (Revision
  60  B/September 1991)", Maxtor Corporation, 1991.
  61 
  62  "7213S product Manual (Revision P3)", Maxtor Corporation, 1992.
  63 
  64  "Draft Proposed American National Standard: Small Computer System
  65  Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109,
  66  revision 10h, October 17, 1991)
  67 
  68  Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric
  69  Youngdale (ericy@cais.com), 1992.
  70 
  71  Private communication, Tuong Le (Future Domain Engineering department),
  72  1994. (Disk geometry computations for Future Domain BIOS version 3.4, and
  73  TMC-18C30 detection.)
  74 
  75  Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page
  76  60 (2.39: Disk Partition Table Layout).
  77 
  78  "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page
  79  6-1.
  80 
  81 
  82  
  83  NOTES ON REFERENCES:
  84 
  85  The Maxtor manuals were free.  Maxtor telephone technical support is
  86  great!
  87 
  88  The Future Domain manuals were $25 and $35.  They document the chip, not
  89  the TMC-16x0 boards, so some information I had to guess at.  In 1992,
  90  Future Domain sold DOS BIOS source for $250 and the UN*X driver source was
  91  $750, but these required a non-disclosure agreement, so even if I could
  92  have afforded them, they would *not* have been useful for writing this
  93  publically distributable driver.  Future Domain technical support has
  94  provided some information on the phone and have sent a few useful FAXs.
  95  They have been much more helpful since they started to recognize that the
  96  word "Linux" refers to an operating system :-).
  97 
  98  
  99 
 100  ALPHA TESTERS:
 101 
 102  There are many other alpha testers that come and go as the driver
 103  develops.  The people listed here were most helpful in times of greatest
 104  need (mostly early on -- I've probably left out a few worthy people in
 105  more recent times):
 106 
 107  Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken
 108  Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari
 109  Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad
 110  Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com).
 111 
 112  Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me
 113  his 18C50-based card for debugging.  He is the sole reason that this
 114  driver works with the 18C50 chip.
 115 
 116  Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for
 117  the version 3.4 BIOS.
 118 
 119  Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for providing
 120  patches that support the TMC-3260, a PCI bus card with the 36C70 chip.
 121  The 36C70 chip appears to be "completely compatible" with the 18C30 chip.
 122  
 123  All of the alpha testers deserve much thanks.
 124 
 125 
 126 
 127  NOTES ON USER DEFINABLE OPTIONS:
 128 
 129  DEBUG: This turns on the printing of various debug informaiton.
 130 
 131  ENABLE_PARITY: This turns on SCSI parity checking.  With the current
 132  driver, all attached devices must support SCSI parity.  If none of your
 133  devices support parity, then you can probably get the driver to work by
 134  turning this option off.  I have no way of testing this, however.
 135 
 136  FIFO_COUNT: The host adapter has an 8K cache.  When this many 512 byte
 137  blocks are filled by the SCSI device, an interrupt will be raised.
 138  Therefore, this could be as low as 0, or as high as 16.  Note, however,
 139  that values which are too high or too low seem to prevent any interrupts
 140  from occuring, and thereby lock up the machine.  I have found that 2 is a
 141  good number, but throughput may be increased by changing this value to
 142  values which are close to 2.  Please let me know if you try any different
 143  values.
 144 
 145  DO_DETECT: This activates some old scan code which was needed before the
 146  high level drivers got fixed.  If you are having toruble with the driver,
 147  turning this on should not hurt, and might help.  Please let me know if
 148  this is the case, since this code will be removed from future drivers.
 149 
 150  RESELECTION: This is no longer an option, since I gave up trying to
 151  implement it in version 4.x of this driver.  It did not improve
 152  performance at all and made the driver unstable (because I never found one
 153  of the two race conditions which were introduced by multiple outstanding
 154  commands).  The instability seems a very high price to pay just so that
 155  you don't have to wait for the tape to rewind.  When I have time, I will
 156  work on this again.  In the interim, if anyone wants to work on the code,
 157  I can give them my latest version.
 158 
 159  **************************************************************************/
 160 
 161 #include <linux/sched.h>
 162 #include <asm/io.h>
 163 #include "../block/blk.h"
 164 #include "scsi.h"
 165 #include "hosts.h"
 166 #include "fdomain.h"
 167 #include <asm/system.h>
 168 #include <linux/errno.h>
 169 #include <linux/string.h>
 170 #include <linux/ioport.h>
 171 
 172 #define VERSION          "$Revision: 5.18 $"
 173 
 174 /* START OF USER DEFINABLE OPTIONS */
 175 
 176 #define DEBUG            1      /* Enable debugging output */
 177 #define ENABLE_PARITY    1      /* Enable SCSI Parity */
 178 #define FIFO_COUNT       2      /* Number of 512 byte blocks before INTR */
 179 #define DO_DETECT        0      /* Do device detection here (see scsi.c) */
 180 
 181 /* END OF USER DEFINABLE OPTIONS */
 182 
 183 #if DEBUG
 184 #define EVERY_ACCESS     0      /* Write a line on every scsi access */
 185 #define ERRORS_ONLY      1      /* Only write a line if there is an error */
 186 #define DEBUG_DETECT     0      /* Debug fdomain_16x0_detect() */
 187 #define DEBUG_MESSAGES   1      /* Debug MESSAGE IN phase */
 188 #define DEBUG_ABORT      1      /* Debug abort() routine */
 189 #define DEBUG_RESET      1      /* Debug reset() routine */
 190 #define DEBUG_RACE       1      /* Debug interrupt-driven race condition */
 191 #else
 192 #define EVERY_ACCESS     0      /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
 193 #define ERRORS_ONLY      0
 194 #define DEBUG_DETECT     0
 195 #define DEBUG_MESSAGES   0
 196 #define DEBUG_ABORT      0
 197 #define DEBUG_RESET      0
 198 #define DEBUG_RACE       0
 199 #endif
 200 
 201 /* Errors are reported on the line, so we don't need to report them again */
 202 #if EVERY_ACCESS
 203 #undef ERRORS_ONLY
 204 #define ERRORS_ONLY      0
 205 #endif
 206 
 207 #if ENABLE_PARITY
 208 #define PARITY_MASK      0x08
 209 #else
 210 #define PARITY_MASK      0x00
 211 #endif
 212 
 213 enum chip_type {
 214    unknown          = 0x00,
 215    tmc1800          = 0x01,
 216    tmc18c50         = 0x02,
 217    tmc18c30         = 0x03,
 218 };
 219 
 220 enum {
 221    in_arbitration   = 0x02,
 222    in_selection     = 0x04,
 223    in_other         = 0x08,
 224    disconnect       = 0x10,
 225    aborted          = 0x20,
 226    sent_ident       = 0x40,
 227 };
 228 
 229 enum in_port_type {
 230    Read_SCSI_Data   =  0,
 231    SCSI_Status      =  1,
 232    TMC_Status       =  2,
 233    FIFO_Status      =  3,       /* tmc18c50/tmc18c30 only */
 234    Interrupt_Cond   =  4,       /* tmc18c50/tmc18c30 only */
 235    LSB_ID_Code      =  5,
 236    MSB_ID_Code      =  6,
 237    Read_Loopback    =  7,
 238    SCSI_Data_NoACK  =  8,
 239    Interrupt_Status =  9,
 240    Configuration1   = 10,
 241    Configuration2   = 11,       /* tmc18c50/tmc18c30 only */
 242    Read_FIFO        = 12,
 243    FIFO_Data_Count  = 14
 244 };
 245 
 246 enum out_port_type {
 247    Write_SCSI_Data  =  0,
 248    SCSI_Cntl        =  1,
 249    Interrupt_Cntl   =  2,
 250    SCSI_Mode_Cntl   =  3,
 251    TMC_Cntl         =  4,
 252    Memory_Cntl      =  5,       /* tmc18c50/tmc18c30 only */
 253    Write_Loopback   =  7,
 254    IO_Control       = 11,       /* tmc18c30 only */
 255    Write_FIFO       = 12
 256 };
 257 
 258 static int               port_base         = 0;
 259 static void              *bios_base        = NULL;
 260 static int               bios_major        = 0;
 261 static int               bios_minor        = 0;
 262 static int               PCI_bus           = 0;
 263 static int               interrupt_level   = 0;
 264 static volatile int      in_command        = 0;
 265 static Scsi_Cmnd         *current_SC       = NULL;
 266 static enum chip_type    chip              = unknown;
 267 static int               adapter_mask      = 0x40;
 268 #if DEBUG_RACE
 269 static volatile int      in_interrupt_flag = 0;
 270 #endif
 271 
 272 static int               SCSI_Mode_Cntl_port;
 273 static int               FIFO_Data_Count_port;
 274 static int               Interrupt_Cntl_port;
 275 static int               Interrupt_Status_port;
 276 static int               Read_FIFO_port;
 277 static int               Read_SCSI_Data_port;
 278 static int               SCSI_Cntl_port;
 279 static int               SCSI_Data_NoACK_port;
 280 static int               SCSI_Status_port;
 281 static int               TMC_Cntl_port;
 282 static int               TMC_Status_port;
 283 static int               Write_FIFO_port;
 284 static int               Write_SCSI_Data_port;
 285 
 286 static int               FIFO_Size = 0x2000; /* 8k FIFO for
 287                                                 pre-tmc18c30 chips */
 288 
 289 extern void              fdomain_16x0_intr( int unused );
 290 
 291 static void *addresses[] = {
 292    (void *)0xc8000,
 293    (void *)0xca000,
 294    (void *)0xce000,
 295    (void *)0xde000 };
 296 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
 297                        
 298 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
 299 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
 300 
 301 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 302 
 303 /*
 304 
 305   READ THIS BEFORE YOU ADD A SIGNATURE!
 306 
 307   READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
 308 
 309   READ EVERY WORD, ESPECIALLY THE WORD *NOT*
 310 
 311   This driver works *ONLY* for Future Domain cards using the TMC-1800,
 312   TMC-18C50, or TMC-18C30 chip.  This includes models TMC-1650, 1660, 1670,
 313   and 1680.
 314 
 315   The following BIOS signature signatures are for boards which do *NOT*
 316   work with this driver (these TMC-8xx and TMC-9xx boards may work with the
 317   Seagate driver):
 318 
 319   FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88
 320   FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89
 321   FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89
 322   FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90
 323   FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
 324   FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
 325   FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92
 326 
 327 */
 328 
 329 struct signature {
 330    char *signature;
 331    int  sig_offset;
 332    int  sig_length;
 333    int  major_bios_version;
 334    int  minor_bios_version;
 335    int  PCI_bus;
 336 } signatures[] = {
 337    /*          1         2         3         4         5         6 */
 338    /* 123456789012345678901234567890123456789012345678901234567890 */
 339    { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89",  5, 50,  2,  0, 0 },
 340    { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89",  5, 50,  2,  0, 0 },
 341    { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92",        5, 44,  3,  0, 0 },
 342    { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93",        5, 44,  3,  2, 0 },
 343    { "Future Domain Corp. V1.0008/18/93",                   5, 33,  3,  4, 0 },
 344    { "Future Domain Corp. V1.0008/18/93",                  26, 33,  3,  4, 1 },
 345    { "FUTURE DOMAIN TMC-18XX",                              5, 22, -1, -1, 0 },
 346 
 347    /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE
 348     Also, fix the disk geometry code for your signature and send your
 349     changes for faith@cs.unc.edu.  Above all, do *NOT* change any old
 350     signatures!
 351 
 352     Note that the last line will match a "generic" 18XX bios.  Because
 353     Future Domain has changed the host SCSI ID and/or the location of the
 354     geometry information in the on-board RAM area for each of the first
 355     three BIOS's, it is still important to enter a fully qualified
 356     signature in the table for any new BIOS's (after the host SCSI ID and
 357     geometry location are verified.) */
 358 };
 359 
 360 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
 361 
 362 static void print_banner( void )
 363 {
 364    printk( "%s", fdomain_16x0_info() );
 365    printk( "Future Domain: BIOS version %d.%d, %s\n",
 366            bios_major, bios_minor,
 367            chip == tmc1800 ? "TMC-1800"
 368            : (chip == tmc18c50 ? "TMC-18C50"
 369               : (chip == tmc18c30 ? "TMC-18C30" : "Unknown")) );
 370    
 371    if (interrupt_level) {
 372       printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
 373               (unsigned)bios_base, port_base, interrupt_level );
 374    } else {
 375       printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
 376               (unsigned)bios_base, port_base );
 377    }
 378 }
 379 
 380 static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
     /* [previous][next][first][last][top][bottom][index][help] */
 381 {
 382    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 383 
 384    while (jiffies < the_time);
 385 }
 386 
 387 inline static void fdomain_make_bus_idle( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389    outb( 0, SCSI_Cntl_port );
 390    outb( 0, SCSI_Mode_Cntl_port );
 391    if (chip == tmc18c50 || chip == tmc18c30)
 392          outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
 393    else
 394          outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
 395 }
 396 
 397 static int fdomain_is_valid_port( int port )
     /* [previous][next][first][last][top][bottom][index][help] */
 398 {
 399    int options;
 400 
 401 #if DEBUG_DETECT 
 402    printk( " (%x%x),",
 403            inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
 404 #endif
 405 
 406    /* The MCA ID is a unique id for each MCA compatible board.  We
 407       are using ISA boards, but Future Domain provides the MCA ID
 408       anyway.  We can use this ID to ensure that this is a Future
 409       Domain TMC-1660/TMC-1680.
 410     */
 411 
 412    if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
 413       if (inb( port + LSB_ID_Code ) != 0x27) return 0;
 414       if (inb( port + MSB_ID_Code ) != 0x61) return 0;
 415       chip = tmc1800;
 416    } else {                                 /* test for 0xe960 id */
 417       if (inb( port + MSB_ID_Code ) != 0x60) return 0;
 418       chip = tmc18c50;
 419 
 420 #if 0
 421 
 422                                 /* Try to toggle 32-bit mode.  This only
 423                                    works on an 18c30 chip.  (User reports
 424                                    say that this doesn't work at all, so
 425                                    we'll use the other method.) */
 426 
 427       outb( 0x80, port + IO_Control );
 428       if (inb( port + Configuration2 ) & 0x80 == 0x80) {
 429          outb( 0x00, port + IO_Control );
 430          if (inb( port + Configuration2 ) & 0x80 == 0x00) {
 431             chip = tmc18c30;
 432             FIFO_Size = 0x800;  /* 2k FIFO */
 433          }
 434       }
 435 #else
 436 
 437                                 /* That should have worked, but appears to
 438                                    have problems.  Lets assume it is an
 439                                    18c30 if the RAM is disabled. */
 440 
 441       if (inb( port + Configuration2 ) & 0x02) {
 442          chip      = tmc18c30;
 443          FIFO_Size = 0x800;     /* 2k FIFO */
 444       }
 445 #endif
 446                                 /* If that failed, we are an 18c50. */
 447    }
 448 
 449    /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
 450       Now, check to be sure the bios_base matches these ports.  If someone
 451       was unlucky enough to have purchased more than one Future Domain
 452       board, then they will have to modify this code, as we only detect one
 453       board here.  [The one with the lowest bios_base.]  */
 454 
 455    options = inb( port + Configuration1 );
 456 
 457 #if DEBUG_DETECT
 458    printk( " Options = %x\n", options );
 459 #endif
 460 
 461                                 /* Check for board with lowest bios_base --
 462                                    this isn't valid for the 18c30, so just
 463                                    assume we have the right board. */
 464 
 465    if (chip != tmc18c30 && addresses[ (options & 0xc0) >> 6 ] != bios_base)
 466          return 0;
 467 
 468    interrupt_level = ints[ (options & 0x0e) >> 1 ];
 469 
 470    return 1;
 471 }
 472 
 473 static int fdomain_test_loopback( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 474 {
 475    int i;
 476    int result;
 477 
 478    for (i = 0; i < 255; i++) {
 479       outb( i, port_base + Write_Loopback );
 480       result = inb( port_base + Read_Loopback );
 481       if (i != result)
 482             return 1;
 483    }
 484    return 0;
 485 }
 486 
 487 int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489    int              i, j;
 490    int              flag = 0;
 491    struct sigaction sa;
 492    int              retcode;
 493 #if DO_DETECT
 494    const int        buflen = 255;
 495    Scsi_Cmnd        SCinit;
 496    unsigned char    do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
 497    unsigned char    do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
 498    unsigned char    do_read_capacity[] = { READ_CAPACITY,
 499                                            0, 0, 0, 0, 0, 0, 0, 0, 0 };
 500    unsigned char    buf[buflen];
 501 #endif
 502 
 503 #if DEBUG_DETECT
 504    printk( "fdomain_16x0_detect()," );
 505 #endif
 506 
 507    for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
 508 #if DEBUG_DETECT
 509       printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
 510 #endif
 511       for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
 512          if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
 513                       signatures[j].signature, signatures[j].sig_length )) {
 514             bios_major = signatures[j].major_bios_version;
 515             bios_minor = signatures[j].minor_bios_version;
 516             PCI_bus    = signatures[j].PCI_bus;
 517             bios_base  = addresses[i];
 518          }
 519       }
 520    }
 521 
 522    if (!bios_base) {
 523 #if DEBUG_DETECT
 524       printk( " FAILED: NO BIOS\n" );
 525 #endif
 526       return 0;
 527    }
 528 
 529    if (bios_major == 2) {
 530       /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 531          Assuming the ROM is enabled (otherwise we wouldn't have been
 532          able to read the ROM signature :-), then the ROM sets up the
 533          RAM area with some magic numbers, such as a list of port
 534          base addresses and a list of the disk "geometry" reported to
 535          DOS (this geometry has nothing to do with physical geometry).
 536        */
 537 
 538       port_base = *((char *)bios_base + 0x1fcc)
 539             + (*((char *)bios_base + 0x1fcd) << 8);
 540    
 541 #if DEBUG_DETECT
 542       printk( " %x,", port_base );
 543 #endif
 544 
 545       for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 546          if (port_base == ports[i])
 547                ++flag;
 548       }
 549 
 550       if (flag)
 551             flag = fdomain_is_valid_port( port_base );
 552    }
 553 
 554    if (!flag) {                 /* Cannot get port base from BIOS RAM */
 555       
 556       /* This is a bad sign.  It usually means that someone patched the
 557          BIOS signature list (the signatures variable) to contain a BIOS
 558          signature for a board *OTHER THAN* the TMC-1660/TMC-1680.  It
 559          also means that we don't have a Version 2.0 BIOS :-)
 560        */
 561       
 562 #if DEBUG_DETECT
 563       if (bios_major != 2) printk( " RAM FAILED, " );
 564 #endif
 565 
 566       /* Anyway, the alternative to finding the address in the RAM is to
 567          just search through every possible port address for one that is
 568          attached to the Future Domain card.  Don't panic, though, about
 569          reading all these random port addresses -- there are rumors that
 570          the Future Domain BIOS does something very similar.
 571 
 572          Do not, however, check ports which the kernel knows are being used
 573          by another driver. */
 574 
 575       if (!PCI_bus) {
 576          for (i = 0; !flag && i < PORT_COUNT; i++) {
 577             port_base = ports[i];
 578             if (check_region( port_base, 0x10 )) {
 579 #if DEBUG_DETECT
 580                printk( " (%x inuse),", port_base );
 581 #endif
 582                continue;
 583             }
 584 #if DEBUG_DETECT
 585             printk( " %x,", port_base );
 586 #endif
 587             flag = fdomain_is_valid_port( port_base );
 588          }
 589       } else {
 590 
 591          /* The proper way of doing this is to use the PCI BIOS call
 592             (interrupt 0x1a) to determine the device IRQ and interrupt
 593             level.  Then the port_base will be in configuration register
 594             0x10 (and configuration register 0x30 will contain the value of
 595             bios_base).
 596 
 597             Until the Linux kernel supports this sort of PCI bus query, we
 598             scan down a bunch of addresses (Future Domain folks say we
 599             should find the address before we get to 0xf800).  This works
 600             fine on some systems -- other systems may have to scan more
 601             addresses.  If you have to modify this section for your
 602             installation, please send mail to faith@cs.unc.edu. */
 603 
 604          for (i = 0xff00; !flag && i > 0xf000; i -= 8) {
 605             port_base = i;
 606             if (check_region( port_base, 0x10 )) {
 607 #if DEBUG_DETECT
 608                printk( " (%x inuse)," , port_base );
 609 #endif
 610                continue;
 611             }
 612             flag = fdomain_is_valid_port( port_base );
 613          }
 614       }
 615    }
 616 
 617    if (!flag) {
 618 #if DEBUG_DETECT
 619       printk( " FAILED: NO PORT\n" );
 620 #endif
 621       return 0;         /* Cannot find valid set of ports */
 622    }
 623 
 624    print_banner();
 625 
 626    SCSI_Mode_Cntl_port   = port_base + SCSI_Mode_Cntl;
 627    FIFO_Data_Count_port  = port_base + FIFO_Data_Count;
 628    Interrupt_Cntl_port   = port_base + Interrupt_Cntl;
 629    Interrupt_Status_port = port_base + Interrupt_Status;
 630    Read_FIFO_port        = port_base + Read_FIFO;
 631    Read_SCSI_Data_port   = port_base + Read_SCSI_Data;
 632    SCSI_Cntl_port        = port_base + SCSI_Cntl;
 633    SCSI_Data_NoACK_port  = port_base + SCSI_Data_NoACK;
 634    SCSI_Status_port      = port_base + SCSI_Status;
 635    TMC_Cntl_port         = port_base + TMC_Cntl;
 636    TMC_Status_port       = port_base + TMC_Status;
 637    Write_FIFO_port       = port_base + Write_FIFO;
 638    Write_SCSI_Data_port  = port_base + Write_SCSI_Data;
 639 
 640    fdomain_16x0_reset( NULL );
 641 
 642    if (fdomain_test_loopback()) {
 643 #if DEBUG_DETECT
 644       printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
 645 #endif
 646       return 0;
 647    }                            /* Log IRQ with kernel */
 648    
 649    if (!interrupt_level) {
 650       panic( "Future Domain: *NO* interrupt level selected!\n" );
 651    } else {
 652       /* Register the IRQ with the kernel */
 653 
 654       sa.sa_handler  = fdomain_16x0_intr;
 655       sa.sa_flags    = SA_INTERRUPT;
 656       sa.sa_mask     = 0;
 657       sa.sa_restorer = NULL;
 658       
 659       retcode = irqaction( interrupt_level, &sa );
 660 
 661       if (retcode < 0) {
 662          if (retcode == -EINVAL) {
 663             printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
 664             printk( "               This shouldn't happen!\n" );
 665             printk( "               Send mail to faith@cs.unc.edu\n" );
 666          } else if (retcode == -EBUSY) {
 667             printk( "Future Domain: IRQ %d is already in use!\n",
 668                     interrupt_level );
 669             printk( "               Please use another IRQ!\n" );
 670          } else {
 671             printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
 672             printk( "               This shouldn't happen!\n" );
 673             printk( "               Send mail to faith@cs.unc.edu\n" );
 674          }
 675          panic( "Future Domain: Driver requires interruptions\n" );
 676       } else {
 677          printk( "Future Domain: IRQ %d requested from kernel\n",
 678                  interrupt_level );
 679       }
 680    }
 681 
 682                                 /* Log I/O ports with kernel */
 683 
 684    snarf_region( port_base, 0x10 );
 685 
 686    if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
 687       adapter_mask = 0x80;
 688       tpnt->this_id = 7;
 689    }
 690    
 691 #if DO_DETECT
 692 
 693    /* These routines are here because of the way the SCSI bus behaves after
 694       a reset.  This appropriate behavior was not handled correctly by the
 695       higher level SCSI routines when I first wrote this driver.  Now,
 696       however, correct scan routines are part of scsi.c and these routines
 697       are no longer needed.  However, this code is still good for
 698       debugging.  */
 699 
 700    SCinit.request_buffer  = SCinit.buffer = buf;
 701    SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
 702    SCinit.use_sg          = 0;
 703    SCinit.lun             = 0;
 704 
 705    printk( "Future Domain detection routine scanning for devices:\n" );
 706    for (i = 0; i < 8; i++) {
 707       SCinit.target = i;
 708       if (i == tpnt->this_id)   /* Skip host adapter */
 709             continue;
 710       memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 711       retcode = fdomain_16x0_command(&SCinit);
 712       if (!retcode) {
 713          memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
 714          retcode = fdomain_16x0_command(&SCinit);
 715          if (!retcode) {
 716             printk( "     SCSI ID %d: ", i );
 717             for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
 718                   printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
 719             memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
 720             retcode = fdomain_16x0_command(&SCinit);
 721             if (!retcode) {
 722                unsigned long blocks, size, capacity;
 723                
 724                blocks = (buf[0] << 24) | (buf[1] << 16)
 725                      | (buf[2] << 8) | buf[3];
 726                size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
 727                capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
 728                
 729                printk( "%lu MB (%lu byte blocks)",
 730                        ((capacity + 5L) / 10L), size );
 731             } else {
 732                memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 733                retcode = fdomain_16x0_command(&SCinit);
 734             }
 735             printk ("\n" );
 736          } else {
 737             memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 738             retcode = fdomain_16x0_command(&SCinit);
 739          }
 740       }
 741    }
 742 #endif
 743 
 744    return 1;
 745 }
 746 
 747 const char *fdomain_16x0_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 748 {
 749    static char buffer[80];
 750    char        *pt;
 751    
 752    strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
 753    if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
 754       strcat( buffer, strchr( VERSION, ':' ) + 1 );
 755       pt = strrchr( buffer, '$') - 1;
 756       if (!pt)                  /* Stripped RCS Revision string? */
 757             pt = buffer + strlen( buffer ) - 1;
 758       if (*pt != ' ')
 759             ++pt;
 760       *pt++ = '\n';
 761       *pt = '\0';
 762    } else {                     /* Assume VERSION is a number */
 763       strcat( buffer, " " VERSION "\n" );
 764    }
 765       
 766    return buffer;
 767 }
 768 
 769 #if 0
 770 static int fdomain_arbitrate( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 771 {
 772    int           status = 0;
 773    unsigned long timeout;
 774 
 775 #if EVERY_ACCESS
 776    printk( "fdomain_arbitrate()\n" );
 777 #endif
 778    
 779    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
 780    outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */
 781    outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
 782 
 783    timeout = jiffies + 50;                    /* 500 mS */
 784    while (jiffies < timeout) {
 785       status = inb( TMC_Status_port );        /* Read adapter status */
 786       if (status & 0x02)                      /* Arbitration complete */
 787             return 0;   
 788    }
 789 
 790    /* Make bus idle */
 791    fdomain_make_bus_idle();
 792 
 793 #if EVERY_ACCESS
 794    printk( "Arbitration failed, status = %x\n", status );
 795 #endif
 796 #if ERRORS_ONLY
 797    printk( "Future Domain: Arbitration failed, status = %x\n", status );
 798 #endif
 799    return 1;
 800 }
 801 #endif
 802 
 803 static int fdomain_select( int target )
     /* [previous][next][first][last][top][bottom][index][help] */
 804 {
 805    int           status;
 806    unsigned long timeout;
 807 
 808 
 809    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 810    outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
 811 
 812    /* Stop arbitration and enable parity */
 813    outb( PARITY_MASK, TMC_Cntl_port ); 
 814 
 815 #if 0
 816    timeout = jiffies + 25;              /* 250mS */
 817 #else
 818    timeout = jiffies + 35;              /* 350mS -- because of timeouts */
 819 #endif
 820    while (jiffies < timeout) {
 821       status = inb( SCSI_Status_port ); /* Read adapter status */
 822       if (status & 1) {                 /* Busy asserted */
 823          /* Enable SCSI Bus (on error, should make bus idle with 0) */
 824          outb( 0x80, SCSI_Cntl_port );
 825          return 0;
 826       }
 827    }
 828    /* Make bus idle */
 829    fdomain_make_bus_idle();
 830 #if EVERY_ACCESS
 831    if (!target) printk( "Selection failed\n" );
 832 #endif
 833 #if ERRORS_ONLY
 834    if (!target) printk( "Future Domain: Selection failed\n" );
 835 #endif
 836    return 1;
 837 }
 838 
 839 void my_done( int error )
     /* [previous][next][first][last][top][bottom][index][help] */
 840 {
 841    if (in_command) {
 842       in_command = 0;
 843       outb( 0x00, Interrupt_Cntl_port );
 844       fdomain_make_bus_idle();
 845       current_SC->result = error;
 846       if (current_SC->scsi_done)
 847             current_SC->scsi_done( current_SC );
 848       else panic( "Future Domain: current_SC->scsi_done() == NULL" );
 849    } else {
 850       panic( "Future Domain: my_done() called outside of command\n" );
 851    }
 852 #if DEBUG_RACE
 853    in_interrupt_flag = 0;
 854 #endif
 855 }
 856 
 857 void fdomain_16x0_intr( int unused )
     /* [previous][next][first][last][top][bottom][index][help] */
 858 {
 859    int      status;
 860    int      done = 0;
 861    unsigned data_count;
 862 
 863    sti();
 864    
 865    outb( 0x00, Interrupt_Cntl_port );
 866 
 867    /* We usually have one spurious interrupt after each command.  Ignore it. */
 868    if (!in_command || !current_SC) {    /* Spurious interrupt */
 869 #if EVERY_ACCESS
 870       printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
 871               in_command, current_SC );
 872 #endif
 873       return;
 874    }
 875 
 876    /* Abort calls my_done, so we do nothing here. */
 877    if (current_SC->SCp.phase & aborted) {
 878 #if DEBUG_ABORT
 879       printk( "Interrupt after abort, ignoring\n" );
 880 #endif
 881       /*
 882       return; */
 883    }
 884 
 885 #if DEBUG_RACE
 886    ++in_interrupt_flag;
 887 #endif
 888 
 889    if (current_SC->SCp.phase & in_arbitration) {
 890       status = inb( TMC_Status_port );        /* Read adapter status */
 891       if (!(status & 0x02)) {
 892 #if EVERY_ACCESS
 893          printk( " AFAIL " );
 894 #endif
 895          my_done( DID_BUS_BUSY << 16 );
 896          return;
 897       }
 898       current_SC->SCp.phase = in_selection;
 899       
 900       outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
 901 
 902       outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 903       outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
 904       
 905       /* Stop arbitration and enable parity */
 906       outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
 907 #if DEBUG_RACE
 908       in_interrupt_flag = 0;
 909 #endif
 910       return;
 911    } else if (current_SC->SCp.phase & in_selection) {
 912       status = inb( SCSI_Status_port );
 913       if (!(status & 0x01)) {
 914          /* Try again, for slow devices */
 915          if (fdomain_select( current_SC->target )) {
 916 #if EVERY_ACCESS
 917             printk( " SFAIL " );
 918 #endif
 919             my_done( DID_NO_CONNECT << 16 );
 920             return;
 921          } else {
 922 #if EVERY_ACCESS
 923             printk( " AltSel " );
 924 #endif
 925             /* Stop arbitration and enable parity */
 926             outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
 927          }
 928       }
 929       current_SC->SCp.phase = in_other;
 930       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 931       outb( 0x80, SCSI_Cntl_port );
 932 #if DEBUG_RACE
 933       in_interrupt_flag = 0;
 934 #endif
 935       return;
 936    }
 937    
 938    /* current_SC->SCp.phase == in_other: this is the body of the routine */
 939    
 940    status = inb( SCSI_Status_port );
 941    
 942    if (status & 0x10) { /* REQ */
 943       
 944       switch (status & 0x0e) {
 945        
 946       case 0x08:                /* COMMAND OUT */
 947          outb( current_SC->cmnd[current_SC->SCp.sent_command++],
 948                Write_SCSI_Data_port );
 949 #if EVERY_ACCESS
 950          printk( "CMD = %x,",
 951                  current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
 952 #endif
 953          break;
 954       case 0x00:                /* DATA OUT -- tmc18c50/tmc18c30 only */
 955          if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 956             current_SC->SCp.have_data_in = -1;
 957             outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 958          }
 959          break;
 960       case 0x04:                /* DATA IN -- tmc18c50/tmc18c30 only */
 961          if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 962             current_SC->SCp.have_data_in = 1;
 963             outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
 964          }
 965          break;
 966       case 0x0c:                /* STATUS IN */
 967          current_SC->SCp.Status = inb( Read_SCSI_Data_port );
 968 #if EVERY_ACCESS
 969          printk( "Status = %x, ", current_SC->SCp.Status );
 970 #endif
 971 #if ERRORS_ONLY
 972          if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
 973             printk( "Future Domain: target = %d, command = %x, "
 974                     "Status = %x\n",
 975                     current_SC->target, current_SC->cmnd[0],
 976                     current_SC->SCp.Status );
 977          }
 978 #endif
 979                break;
 980       case 0x0a:                /* MESSAGE OUT */
 981          outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
 982          break;
 983       case 0x0e:                /* MESSAGE IN */
 984          current_SC->SCp.Message = inb( Read_SCSI_Data_port );
 985 #if EVERY_ACCESS
 986          printk( "Message = %x, ", current_SC->SCp.Message );
 987 #endif
 988          if (!current_SC->SCp.Message) ++done;
 989 #if DEBUG_MESSAGES || EVERY_ACCESS
 990          if (current_SC->SCp.Message) {
 991             printk( "Future Domain: Message = %x\n",
 992                     current_SC->SCp.Message );
 993          }
 994 #endif
 995          break;
 996       }
 997    }
 998 
 999    if (chip == tmc1800
1000        && !current_SC->SCp.have_data_in
1001        && (current_SC->SCp.sent_command
1002            >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
1003                                 /* We have to get the FIFO direction
1004                                    correct, so I've made a table based
1005                                    on the SCSI Standard of which commands
1006                                    appear to require a DATA OUT phase.
1007                                  */
1008       /*
1009         p. 94: Command for all device types
1010         CHANGE DEFINITION            40 DATA OUT
1011         COMPARE                      39 DATA OUT
1012         COPY                         18 DATA OUT
1013         COPY AND VERIFY              3a DATA OUT
1014         INQUIRY                      12 
1015         LOG SELECT                   4c DATA OUT
1016         LOG SENSE                    4d
1017         MODE SELECT (6)              15 DATA OUT
1018         MODE SELECT (10)             55 DATA OUT
1019         MODE SENSE (6)               1a
1020         MODE SENSE (10)              5a
1021         READ BUFFER                  3c
1022         RECEIVE DIAGNOSTIC RESULTS   1c
1023         REQUEST SENSE                03
1024         SEND DIAGNOSTIC              1d DATA OUT
1025         TEST UNIT READY              00
1026         WRITE BUFFER                 3b DATA OUT
1027 
1028         p.178: Commands for direct-access devices (not listed on p. 94)
1029         FORMAT UNIT                  04 DATA OUT
1030         LOCK-UNLOCK CACHE            36
1031         PRE-FETCH                    34
1032         PREVENT-ALLOW MEDIUM REMOVAL 1e
1033         READ (6)/RECEIVE             08
1034         READ (10)                    3c
1035         READ CAPACITY                25
1036         READ DEFECT DATA (10)        37
1037         READ LONG                    3e
1038         REASSIGN BLOCKS              07 DATA OUT
1039         RELEASE                      17
1040         RESERVE                      16 DATA OUT
1041         REZERO UNIT/REWIND           01
1042         SEARCH DATA EQUAL (10)       31 DATA OUT
1043         SEARCH DATA HIGH (10)        30 DATA OUT
1044         SEARCH DATA LOW (10)         32 DATA OUT
1045         SEEK (6)                     0b
1046         SEEK (10)                    2b
1047         SET LIMITS (10)              33
1048         START STOP UNIT              1b
1049         SYNCHRONIZE CACHE            35
1050         VERIFY (10)                  2f
1051         WRITE (6)/PRINT/SEND         0a DATA OUT
1052         WRITE (10)/SEND              2a DATA OUT
1053         WRITE AND VERIFY (10)        2e DATA OUT
1054         WRITE LONG                   3f DATA OUT
1055         WRITE SAME                   41 DATA OUT ?
1056 
1057         p. 261: Commands for sequential-access devices (not previously listed)
1058         ERASE                        19
1059         LOAD UNLOAD                  1b
1060         LOCATE                       2b
1061         READ BLOCK LIMITS            05
1062         READ POSITION                34
1063         READ REVERSE                 0f
1064         RECOVER BUFFERED DATA        14
1065         SPACE                        11
1066         WRITE FILEMARKS              10 ?
1067 
1068         p. 298: Commands for printer devices (not previously listed)
1069         ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
1070         SLEW AND PRINT               0b DATA OUT  -- same as seek
1071         STOP PRINT                   1b
1072         SYNCHRONIZE BUFFER           10
1073 
1074         p. 315: Commands for processor devices (not previously listed)
1075         
1076         p. 321: Commands for write-once devices (not previously listed)
1077         MEDIUM SCAN                  38
1078         READ (12)                    a8
1079         SEARCH DATA EQUAL (12)       b1 DATA OUT
1080         SEARCH DATA HIGH (12)        b0 DATA OUT
1081         SEARCH DATA LOW (12)         b2 DATA OUT
1082         SET LIMITS (12)              b3
1083         VERIFY (12)                  af
1084         WRITE (12)                   aa DATA OUT
1085         WRITE AND VERIFY (12)        ae DATA OUT
1086 
1087         p. 332: Commands for CD-ROM devices (not previously listed)
1088         PAUSE/RESUME                 4b
1089         PLAY AUDIO (10)              45
1090         PLAY AUDIO (12)              a5
1091         PLAY AUDIO MSF               47
1092         PLAY TRACK RELATIVE (10)     49
1093         PLAY TRACK RELATIVE (12)     a9
1094         READ HEADER                  44
1095         READ SUB-CHANNEL             42
1096         READ TOC                     43
1097 
1098         p. 370: Commands for scanner devices (not previously listed)
1099         GET DATA BUFFER STATUS       34
1100         GET WINDOW                   25
1101         OBJECT POSITION              31
1102         SCAN                         1b
1103         SET WINDOW                   24 DATA OUT
1104 
1105         p. 391: Commands for optical memory devices (not listed)
1106         ERASE (10)                   2c
1107         ERASE (12)                   ac
1108         MEDIUM SCAN                  38 DATA OUT
1109         READ DEFECT DATA (12)        b7
1110         READ GENERATION              29
1111         READ UPDATED BLOCK           2d
1112         UPDATE BLOCK                 3d DATA OUT
1113 
1114         p. 419: Commands for medium changer devices (not listed)
1115         EXCHANGE MEDIUM              46
1116         INITIALIZE ELEMENT STATUS    07
1117         MOVE MEDIUM                  a5
1118         POSITION TO ELEMENT          2b
1119         READ ELEMENT STATUS          b8
1120         REQUEST VOL. ELEMENT ADDRESS b5
1121         SEND VOLUME TAG              b6 DATA OUT
1122 
1123         p. 454: Commands for communications devices (not listed previously)
1124         GET MESSAGE (6)              08
1125         GET MESSAGE (10)             28
1126         GET MESSAGE (12)             a8
1127       */
1128         
1129       switch (current_SC->cmnd[0]) {
1130       case CHANGE_DEFINITION: case COMPARE:         case COPY:
1131       case COPY_VERIFY:       case LOG_SELECT:      case MODE_SELECT:
1132       case MODE_SELECT_10:    case SEND_DIAGNOSTIC: case WRITE_BUFFER:
1133 
1134       case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
1135       case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
1136       case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
1137       case 0x3f:              case 0x41:
1138 
1139       case 0xb1:              case 0xb0:            case 0xb2:
1140       case 0xaa:              case 0xae:
1141 
1142       case 0x24:
1143 
1144       case 0x38:              case 0x3d:
1145 
1146       case 0xb6:
1147          
1148       case 0xea:                /* alternate number for WRITE LONG */
1149          
1150          current_SC->SCp.have_data_in = -1;
1151          outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1152          break;
1153 
1154       case 0x00:
1155       default:
1156          
1157          current_SC->SCp.have_data_in = 1;
1158          outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1159          break;
1160       }
1161    }
1162 
1163    if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
1164       while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
1165 #if EVERY_ACCESS
1166          printk( "DC=%d, ", data_count ) ;
1167 #endif
1168          if (data_count > current_SC->SCp.this_residual)
1169                data_count = current_SC->SCp.this_residual;
1170          if (data_count > 0) {
1171 #if EVERY_ACCESS
1172             printk( "%d OUT, ", data_count );
1173 #endif
1174             if (data_count == 1) {
1175                outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1176                --current_SC->SCp.this_residual;
1177             } else {
1178                data_count >>= 1;
1179                outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1180                current_SC->SCp.ptr += 2 * data_count;
1181                current_SC->SCp.this_residual -= 2 * data_count;
1182             }
1183          }
1184          if (!current_SC->SCp.this_residual) {
1185             if (current_SC->SCp.buffers_residual) {
1186                --current_SC->SCp.buffers_residual;
1187                ++current_SC->SCp.buffer;
1188                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1189                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1190             } else
1191                   break;
1192          }
1193       }
1194    }
1195    
1196    if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
1197       while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1198 #if EVERY_ACCESS
1199          printk( "DC=%d, ", data_count );
1200 #endif
1201          if (data_count > current_SC->SCp.this_residual)
1202                data_count = current_SC->SCp.this_residual;
1203          if (data_count) {
1204 #if EVERY_ACCESS
1205             printk( "%d IN, ", data_count );
1206 #endif
1207             if (data_count == 1) {
1208                *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1209                --current_SC->SCp.this_residual;
1210             } else {
1211                data_count >>= 1; /* Number of words */
1212                insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1213                current_SC->SCp.ptr += 2 * data_count;
1214                current_SC->SCp.this_residual -= 2 * data_count;
1215             }
1216          }
1217          if (!current_SC->SCp.this_residual
1218              && current_SC->SCp.buffers_residual) {
1219             --current_SC->SCp.buffers_residual;
1220             ++current_SC->SCp.buffer;
1221             current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1222             current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1223          }
1224       }
1225    }
1226    
1227    if (done) {
1228 #if EVERY_ACCESS
1229       printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1230 #endif
1231 
1232 #if ERRORS_ONLY
1233       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1234          if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1235             unsigned char key;
1236             unsigned char code;
1237             unsigned char qualifier;
1238 
1239             key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1240                   & 0x0f;
1241             code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1242             qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1243                                           + 13));
1244 
1245             if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1246                 && !(key == NOT_READY
1247                      && code == 0x04
1248                      && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1249                 && !(key == ILLEGAL_REQUEST && (code == 0x25
1250                                                 || code == 0x24
1251                                                 || !code)))
1252                   
1253                   printk( "Future Domain: REQUEST SENSE "
1254                           "Key = %x, Code = %x, Qualifier = %x\n",
1255                           key, code, qualifier );
1256          }
1257       }
1258 #endif
1259 #if EVERY_ACCESS
1260       printk( "BEFORE MY_DONE. . ." );
1261 #endif
1262       my_done( (current_SC->SCp.Status & 0xff)
1263                | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1264 #if EVERY_ACCESS
1265       printk( "RETURNING.\n" );
1266 #endif
1267       
1268    } else {
1269       if (current_SC->SCp.phase & disconnect) {
1270          outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1271          outb( 0x00, SCSI_Cntl_port );
1272       } else {
1273          outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1274       }
1275    }
1276 #if DEBUG_RACE
1277    in_interrupt_flag = 0;
1278 #endif
1279    return;
1280 }
1281 
1282 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
1283 {
1284    if (in_command) {
1285       panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1286    }
1287 #if EVERY_ACCESS
1288    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1289            SCpnt->target,
1290            *(unsigned char *)SCpnt->cmnd,
1291            SCpnt->use_sg,
1292            SCpnt->request_bufflen );
1293 #endif
1294 
1295    fdomain_make_bus_idle();
1296 
1297    current_SC            = SCpnt; /* Save this for the done function */
1298    current_SC->scsi_done = done;
1299 
1300    /* Initialize static data */
1301 
1302    if (current_SC->use_sg) {
1303       current_SC->SCp.buffer =
1304             (struct scatterlist *)current_SC->request_buffer;
1305       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
1306       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
1307       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1308    } else {
1309       current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
1310       current_SC->SCp.this_residual    = current_SC->request_bufflen;
1311       current_SC->SCp.buffer           = NULL;
1312       current_SC->SCp.buffers_residual = 0;
1313    }
1314          
1315    
1316    current_SC->SCp.Status              = 0;
1317    current_SC->SCp.Message             = 0;
1318    current_SC->SCp.have_data_in        = 0;
1319    current_SC->SCp.sent_command        = 0;
1320    current_SC->SCp.phase               = in_arbitration;
1321 
1322    /* Start arbitration */
1323    outb( 0x00, Interrupt_Cntl_port );
1324    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
1325    outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
1326    ++in_command;
1327    outb( 0x20, Interrupt_Cntl_port );
1328    outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1329 
1330    return 0;
1331 }
1332 
1333 /* The following code, which simulates the old-style command function, was
1334    taken from Tommy Thorn's aha1542.c file.  This code is Copyright (C)
1335    1992 Tommy Thorn. */
1336 
1337 static volatile int internal_done_flag    = 0;
1338 static volatile int internal_done_errcode = 0;
1339 
1340 static void internal_done( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1341 {
1342     internal_done_errcode = SCpnt->result;
1343     ++internal_done_flag;
1344 }
1345 
1346 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1347 {
1348     fdomain_16x0_queue( SCpnt, internal_done );
1349 
1350     while (!internal_done_flag)
1351           ;
1352     internal_done_flag = 0;
1353     return internal_done_errcode;
1354 }
1355 
1356 /* End of code derived from Tommy Thorn's work. */
1357 
1358 void print_info( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1359 {
1360    unsigned int imr;
1361    unsigned int irr;
1362    unsigned int isr;
1363    
1364    print_banner();
1365    switch (SCpnt->SCp.phase) {
1366    case in_arbitration: printk( "arbitration " ); break;
1367    case in_selection:   printk( "selection " );   break;
1368    case in_other:       printk( "other " );       break;
1369    default:             printk( "unknown " );     break;
1370    }
1371 
1372    printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1373            SCpnt->SCp.phase,
1374            SCpnt->target,
1375            *(unsigned char *)SCpnt->cmnd,
1376            SCpnt->use_sg,
1377            SCpnt->request_bufflen );
1378    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1379            SCpnt->SCp.sent_command,
1380            SCpnt->SCp.have_data_in,
1381            SCpnt->timeout );
1382 #if DEBUG_RACE
1383    printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1384 #endif
1385 
1386    imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1387    outb( 0x0a, 0xa0 );
1388    irr = inb( 0xa0 ) << 8;
1389    outb( 0x0a, 0x20 );
1390    irr += inb( 0x20 );
1391    outb( 0x0b, 0xa0 );
1392    isr = inb( 0xa0 ) << 8;
1393    outb( 0x0b, 0x20 );
1394    isr += inb( 0x20 );
1395 
1396                                 /* Print out interesting information */
1397    printk( "IMR = 0x%04x", imr );
1398    if (imr & (1 << interrupt_level))
1399          printk( " (masked)" );
1400    printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1401 
1402    printk( "SCSI Status      = 0x%02x\n", inb( SCSI_Status_port ) );
1403    printk( "TMC Status       = 0x%02x", inb( TMC_Status_port ) );
1404    if (inb( TMC_Status_port & 1))
1405          printk( " (interrupt)" );
1406    printk( "\n" );
1407    printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1408    if (inb( Interrupt_Status_port ) & 0x08)
1409          printk( " (enabled)" );
1410    printk( "\n" );
1411    if (chip == tmc18c50 || chip == tmc18c30) {
1412       printk( "FIFO Status      = 0x%02x\n", inb( port_base + FIFO_Status ) );
1413       printk( "Int. Condition   = 0x%02x\n",
1414               inb( port_base + Interrupt_Cond ) );
1415    }
1416    printk( "Configuration 1  = 0x%02x\n", inb( port_base + Configuration1 ) );
1417    if (chip == tmc18c50 || chip == tmc18c30)
1418          printk( "Configuration 2  = 0x%02x\n",
1419                  inb( port_base + Configuration2 ) );
1420 }
1421 
1422 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1423 {
1424 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1425    printk( "Future Domain: Abort " );
1426 #endif
1427 
1428    cli();
1429    if (!in_command) {
1430 #if EVERY_ACCESS || ERRORS_ONLY
1431       printk( " (not in command)\n" );
1432 #endif
1433       sti();
1434       return SCSI_ABORT_NOT_RUNNING;
1435    }
1436 
1437 #if DEBUG_ABORT
1438    print_info( SCpnt );
1439 #endif
1440 
1441    fdomain_make_bus_idle();
1442 
1443    current_SC->SCp.phase |= aborted;
1444 
1445    current_SC->result = DID_ABORT << 16;
1446 
1447    sti();
1448    
1449    /* Aborts are not done well. . . */
1450    my_done( DID_ABORT << 16 );
1451 
1452    return SCSI_ABORT_SUCCESS;
1453 }
1454 
1455 int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1456 {
1457 #if DEBUG_RESET
1458    static int called_once = 0;
1459 #endif
1460 
1461 #if ERRORS_ONLY
1462    printk( "Future Domain: SCSI Bus Reset\n" );
1463 #endif
1464 
1465 #if DEBUG_RESET
1466    if (called_once) print_info( current_SC );
1467    called_once = 1;
1468 #endif
1469    
1470    outb( 1, SCSI_Cntl_port );
1471    do_pause( 2 );
1472    outb( 0, SCSI_Cntl_port );
1473    do_pause( 115 );
1474    outb( 0, SCSI_Mode_Cntl_port );
1475    outb( PARITY_MASK, TMC_Cntl_port );
1476 
1477    /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1478       is probably hosed at this point.  We will, however, try to keep
1479       things going by informing the high-level code that we need help. */
1480 
1481    return SCSI_RESET_WAKEUP;
1482 }
1483 
1484 #include "sd.h"
1485 #include "scsi_ioctl.h"
1486 
1487 int fdomain_16x0_biosparam( Scsi_Disk *disk, int dev, int *info_array )
     /* [previous][next][first][last][top][bottom][index][help] */
1488 {
1489    int              drive;
1490    unsigned char    buf[512 + sizeof( int ) * 2];
1491    int              size      = disk->capacity;
1492    int              *sizes    = (int *)buf;
1493    unsigned char    *data     = (unsigned char *)(sizes + 2);
1494    unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
1495    int              retcode;
1496    struct drive_info {
1497       unsigned short cylinders;
1498       unsigned char  heads;
1499       unsigned char  sectors;
1500    } *i;
1501    
1502    /* NOTES:
1503       The RAM area starts at 0x1f00 from the bios_base address.
1504 
1505       For BIOS Version 2.0:
1506       
1507       The drive parameter table seems to start at 0x1f30.
1508       The first byte's purpose is not known.
1509       Next is the cylinder, head, and sector information.
1510       The last 4 bytes appear to be the drive's size in sectors.
1511       The other bytes in the drive parameter table are unknown.
1512       If anyone figures them out, please send me mail, and I will
1513       update these notes.
1514 
1515       Tape drives do not get placed in this table.
1516 
1517       There is another table at 0x1fea:
1518       If the byte is 0x01, then the SCSI ID is not in use.
1519       If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1520       although tapes don't seem to be in this table.  I haven't
1521       seen any other numbers (in a limited sample).
1522 
1523       0x1f2d is a drive count (i.e., not including tapes)
1524 
1525       The table at 0x1fcc are I/O ports addresses for the various
1526       operations.  I calculate these by hand in this driver code.
1527 
1528       For BIOS Version 3.2:
1529 
1530       The drive parameter table starts at 0x1f70.  Each entry is
1531       0x0a bytes long.  Heads are one less than we need to report.
1532     */
1533 
1534    drive = MINOR(dev) / 16;
1535 
1536    if (bios_major == 2) {
1537       i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1538       info_array[0] = i->heads;
1539       info_array[1] = i->sectors;
1540       info_array[2] = i->cylinders;
1541    } else if (bios_major == 3 && bios_minor < 4) { /* 3.0 and 3.2 BIOS */
1542       i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1543       info_array[0] = i->heads + 1;
1544       info_array[1] = i->sectors;
1545       info_array[2] = i->cylinders;
1546    } else {                     /* 3.4 BIOS (and up?) */
1547       /* This algorithm was provided by Future Domain (much thanks!). */
1548 
1549       sizes[0] = 0;             /* zero bytes out */
1550       sizes[1] = 512;           /* one sector in */
1551       memcpy( data, do_read, sizeof( do_read ) );
1552       retcode = kernel_scsi_ioctl( disk->device,
1553                                    SCSI_IOCTL_SEND_COMMAND,
1554                                    (void *)buf );
1555       if (!retcode                                  /* SCSI command ok */
1556           && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
1557           && data[0x1c2]) {                         /* Partition type */
1558 
1559          /* The partition table layout is as follows:
1560 
1561             Start: 0x1b3h
1562             Offset: 0 = partition status
1563                     1 = starting head
1564                     2 = starting sector and cylinder (word, encoded)
1565                     4 = partition type
1566                     5 = ending head
1567                     6 = ending sector and cylinder (word, encoded)
1568                     8 = starting absolute sector (double word)
1569                     c = number of sectors (double word)
1570             Signature: 0x1fe = 0x55aa
1571 
1572             So, this algorithm assumes:
1573             1) the first partition table is in use,
1574             2) the data in the first entry is correct, and
1575             3) partitions never divide cylinders
1576 
1577             Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1578             as well as for Linux.  Note also, that Linux doesn't pay any
1579             attention to the fields that are used by this algorithm -- it
1580             only uses the absolute sector data.  Recent versions of Linux's
1581             fdisk(1) will fill this data in correctly, and forthcoming
1582             versions will check for consistency.
1583 
1584             Checking for a non-zero partition type is not part of the
1585             Future Domain algorithm, but it seemed to be a reasonable thing
1586             to do, especially in the Linux and BSD worlds. */
1587 
1588          info_array[0] = data[0x1c3] + 1;           /* heads */
1589          info_array[1] = data[0x1c4] & 0x3f;        /* sectors */
1590       } else {
1591 
1592          /* Note that this new method guarantees that there will always be
1593             less than 1024 cylinders on a platter.  This is good for drives
1594             up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1595 
1596          if ((unsigned int)size >= 0x7e0000U) {
1597             info_array[0] = 0xff; /* heads   = 255 */
1598             info_array[1] = 0x3f; /* sectors =  63 */
1599          } else if ((unsigned int)size >= 0x200000U) {
1600             info_array[0] = 0x80; /* heads   = 128 */
1601             info_array[1] = 0x3f; /* sectors =  63 */
1602          } else {
1603             info_array[0] = 0x40; /* heads   =  64 */
1604             info_array[1] = 0x20; /* sectors =  32 */
1605          }
1606       }
1607                                 /* For both methods, compute the cylinders */
1608       info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1609    }
1610    
1611    return 0;
1612 }

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