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

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