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 information.
 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 trouble 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 SIGNATURE
 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    int              retcode;
 492 #if DO_DETECT
 493    const int        buflen = 255;
 494    Scsi_Cmnd        SCinit;
 495    unsigned char    do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
 496    unsigned char    do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
 497    unsigned char    do_read_capacity[] = { READ_CAPACITY,
 498                                            0, 0, 0, 0, 0, 0, 0, 0, 0 };
 499    unsigned char    buf[buflen];
 500 #endif
 501 
 502 #if DEBUG_DETECT
 503    printk( "fdomain_16x0_detect()," );
 504 #endif
 505 
 506    for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
 507 #if DEBUG_DETECT
 508       printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
 509 #endif
 510       for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
 511          if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
 512                       signatures[j].signature, signatures[j].sig_length )) {
 513             bios_major = signatures[j].major_bios_version;
 514             bios_minor = signatures[j].minor_bios_version;
 515             PCI_bus    = signatures[j].PCI_bus;
 516             bios_base  = addresses[i];
 517          }
 518       }
 519    }
 520 
 521    if (!bios_base) {
 522 #if DEBUG_DETECT
 523       printk( " FAILED: NO BIOS\n" );
 524 #endif
 525       return 0;
 526    }
 527 
 528    if (bios_major == 2) {
 529       /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 530          Assuming the ROM is enabled (otherwise we wouldn't have been
 531          able to read the ROM signature :-), then the ROM sets up the
 532          RAM area with some magic numbers, such as a list of port
 533          base addresses and a list of the disk "geometry" reported to
 534          DOS (this geometry has nothing to do with physical geometry).
 535        */
 536 
 537       port_base = *((char *)bios_base + 0x1fcc)
 538             + (*((char *)bios_base + 0x1fcd) << 8);
 539    
 540 #if DEBUG_DETECT
 541       printk( " %x,", port_base );
 542 #endif
 543 
 544       for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 545          if (port_base == ports[i])
 546                ++flag;
 547       }
 548 
 549       if (flag)
 550             flag = fdomain_is_valid_port( port_base );
 551    }
 552 
 553    if (!flag) {                 /* Cannot get port base from BIOS RAM */
 554       
 555       /* This is a bad sign.  It usually means that someone patched the
 556          BIOS signature list (the signatures variable) to contain a BIOS
 557          signature for a board *OTHER THAN* the TMC-1660/TMC-1680.  It
 558          also means that we don't have a Version 2.0 BIOS :-)
 559        */
 560       
 561 #if DEBUG_DETECT
 562       if (bios_major != 2) printk( " RAM FAILED, " );
 563 #endif
 564 
 565       /* Anyway, the alternative to finding the address in the RAM is to
 566          just search through every possible port address for one that is
 567          attached to the Future Domain card.  Don't panic, though, about
 568          reading all these random port addresses -- there are rumors that
 569          the Future Domain BIOS does something very similar.
 570 
 571          Do not, however, check ports which the kernel knows are being used
 572          by another driver. */
 573 
 574       if (!PCI_bus) {
 575          for (i = 0; !flag && i < PORT_COUNT; i++) {
 576             port_base = ports[i];
 577             if (check_region( port_base, 0x10 )) {
 578 #if DEBUG_DETECT
 579                printk( " (%x inuse),", port_base );
 580 #endif
 581                continue;
 582             }
 583 #if DEBUG_DETECT
 584             printk( " %x,", port_base );
 585 #endif
 586             flag = fdomain_is_valid_port( port_base );
 587          }
 588       } else {
 589 
 590          /* The proper way of doing this is to use the PCI BIOS call
 591             (interrupt 0x1a) to determine the device IRQ and interrupt
 592             level.  Then the port_base will be in configuration register
 593             0x10 (and configuration register 0x30 will contain the value of
 594             bios_base).
 595 
 596             Until the Linux kernel supports this sort of PCI bus query, we
 597             scan down a bunch of addresses (Future Domain folks say we
 598             should find the address before we get to 0xf800).  This works
 599             fine on some systems -- other systems may have to scan more
 600             addresses.  If you have to modify this section for your
 601             installation, please send mail to faith@cs.unc.edu. */
 602 
 603          for (i = 0xff00; !flag && i > 0xf000; i -= 8) {
 604             port_base = i;
 605             if (check_region( port_base, 0x10 )) {
 606 #if DEBUG_DETECT
 607                printk( " (%x inuse)," , port_base );
 608 #endif
 609                continue;
 610             }
 611             flag = fdomain_is_valid_port( port_base );
 612          }
 613       }
 614    }
 615 
 616    if (!flag) {
 617 #if DEBUG_DETECT
 618       printk( " FAILED: NO PORT\n" );
 619 #endif
 620       return 0;         /* Cannot find valid set of ports */
 621    }
 622 
 623    print_banner();
 624 
 625    SCSI_Mode_Cntl_port   = port_base + SCSI_Mode_Cntl;
 626    FIFO_Data_Count_port  = port_base + FIFO_Data_Count;
 627    Interrupt_Cntl_port   = port_base + Interrupt_Cntl;
 628    Interrupt_Status_port = port_base + Interrupt_Status;
 629    Read_FIFO_port        = port_base + Read_FIFO;
 630    Read_SCSI_Data_port   = port_base + Read_SCSI_Data;
 631    SCSI_Cntl_port        = port_base + SCSI_Cntl;
 632    SCSI_Data_NoACK_port  = port_base + SCSI_Data_NoACK;
 633    SCSI_Status_port      = port_base + SCSI_Status;
 634    TMC_Cntl_port         = port_base + TMC_Cntl;
 635    TMC_Status_port       = port_base + TMC_Status;
 636    Write_FIFO_port       = port_base + Write_FIFO;
 637    Write_SCSI_Data_port  = port_base + Write_SCSI_Data;
 638 
 639    fdomain_16x0_reset( NULL );
 640 
 641    if (fdomain_test_loopback()) {
 642 #if DEBUG_DETECT
 643       printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
 644 #endif
 645       return 0;
 646    }                            /* Log IRQ with kernel */
 647    
 648    if (!interrupt_level) {
 649       panic( "Future Domain: *NO* interrupt level selected!\n" );
 650    } else {
 651       /* Register the IRQ with the kernel */
 652 
 653       retcode = request_irq( interrupt_level, fdomain_16x0_intr, SA_INTERRUPT, "FDomain");
 654 
 655       if (retcode < 0) {
 656          if (retcode == -EINVAL) {
 657             printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
 658             printk( "               This shouldn't happen!\n" );
 659             printk( "               Send mail to faith@cs.unc.edu\n" );
 660          } else if (retcode == -EBUSY) {
 661             printk( "Future Domain: IRQ %d is already in use!\n",
 662                     interrupt_level );
 663             printk( "               Please use another IRQ!\n" );
 664          } else {
 665             printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
 666             printk( "               This shouldn't happen!\n" );
 667             printk( "               Send mail to faith@cs.unc.edu\n" );
 668          }
 669          panic( "Future Domain: Driver requires interruptions\n" );
 670       } else {
 671          printk( "Future Domain: IRQ %d requested from kernel\n",
 672                  interrupt_level );
 673       }
 674    }
 675 
 676                                 /* Log I/O ports with kernel */
 677 
 678    snarf_region( port_base, 0x10 );
 679 
 680    if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
 681       adapter_mask = 0x80;
 682       tpnt->this_id = 7;
 683    }
 684    
 685 #if DO_DETECT
 686 
 687    /* These routines are here because of the way the SCSI bus behaves after
 688       a reset.  This appropriate behavior was not handled correctly by the
 689       higher level SCSI routines when I first wrote this driver.  Now,
 690       however, correct scan routines are part of scsi.c and these routines
 691       are no longer needed.  However, this code is still good for
 692       debugging.  */
 693 
 694    SCinit.request_buffer  = SCinit.buffer = buf;
 695    SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
 696    SCinit.use_sg          = 0;
 697    SCinit.lun             = 0;
 698 
 699    printk( "Future Domain detection routine scanning for devices:\n" );
 700    for (i = 0; i < 8; i++) {
 701       SCinit.target = i;
 702       if (i == tpnt->this_id)   /* Skip host adapter */
 703             continue;
 704       memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 705       retcode = fdomain_16x0_command(&SCinit);
 706       if (!retcode) {
 707          memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
 708          retcode = fdomain_16x0_command(&SCinit);
 709          if (!retcode) {
 710             printk( "     SCSI ID %d: ", i );
 711             for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
 712                   printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
 713             memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
 714             retcode = fdomain_16x0_command(&SCinit);
 715             if (!retcode) {
 716                unsigned long blocks, size, capacity;
 717                
 718                blocks = (buf[0] << 24) | (buf[1] << 16)
 719                      | (buf[2] << 8) | buf[3];
 720                size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
 721                capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
 722                
 723                printk( "%lu MB (%lu byte blocks)",
 724                        ((capacity + 5L) / 10L), size );
 725             } else {
 726                memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 727                retcode = fdomain_16x0_command(&SCinit);
 728             }
 729             printk ("\n" );
 730          } else {
 731             memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 732             retcode = fdomain_16x0_command(&SCinit);
 733          }
 734       }
 735    }
 736 #endif
 737 
 738    return 1;
 739 }
 740 
 741 const char *fdomain_16x0_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 742 {
 743    static char buffer[80];
 744    char        *pt;
 745    
 746    strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
 747    if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
 748       strcat( buffer, strchr( VERSION, ':' ) + 1 );
 749       pt = strrchr( buffer, '$') - 1;
 750       if (!pt)                  /* Stripped RCS Revision string? */
 751             pt = buffer + strlen( buffer ) - 1;
 752       if (*pt != ' ')
 753             ++pt;
 754       *pt++ = '\n';
 755       *pt = '\0';
 756    } else {                     /* Assume VERSION is a number */
 757       strcat( buffer, " " VERSION "\n" );
 758    }
 759       
 760    return buffer;
 761 }
 762 
 763 #if 0
 764 static int fdomain_arbitrate( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 765 {
 766    int           status = 0;
 767    unsigned long timeout;
 768 
 769 #if EVERY_ACCESS
 770    printk( "fdomain_arbitrate()\n" );
 771 #endif
 772    
 773    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
 774    outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */
 775    outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
 776 
 777    timeout = jiffies + 50;                    /* 500 mS */
 778    while (jiffies < timeout) {
 779       status = inb( TMC_Status_port );        /* Read adapter status */
 780       if (status & 0x02)                      /* Arbitration complete */
 781             return 0;   
 782    }
 783 
 784    /* Make bus idle */
 785    fdomain_make_bus_idle();
 786 
 787 #if EVERY_ACCESS
 788    printk( "Arbitration failed, status = %x\n", status );
 789 #endif
 790 #if ERRORS_ONLY
 791    printk( "Future Domain: Arbitration failed, status = %x\n", status );
 792 #endif
 793    return 1;
 794 }
 795 #endif
 796 
 797 static int fdomain_select( int target )
     /* [previous][next][first][last][top][bottom][index][help] */
 798 {
 799    int           status;
 800    unsigned long timeout;
 801 
 802 
 803    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 804    outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
 805 
 806    /* Stop arbitration and enable parity */
 807    outb( PARITY_MASK, TMC_Cntl_port ); 
 808 
 809 #if 0
 810    timeout = jiffies + 25;              /* 250mS */
 811 #else
 812    timeout = jiffies + 35;              /* 350mS -- because of timeouts */
 813 #endif
 814    while (jiffies < timeout) {
 815       status = inb( SCSI_Status_port ); /* Read adapter status */
 816       if (status & 1) {                 /* Busy asserted */
 817          /* Enable SCSI Bus (on error, should make bus idle with 0) */
 818          outb( 0x80, SCSI_Cntl_port );
 819          return 0;
 820       }
 821    }
 822    /* Make bus idle */
 823    fdomain_make_bus_idle();
 824 #if EVERY_ACCESS
 825    if (!target) printk( "Selection failed\n" );
 826 #endif
 827 #if ERRORS_ONLY
 828    if (!target) printk( "Future Domain: Selection failed\n" );
 829 #endif
 830    return 1;
 831 }
 832 
 833 void my_done( int error )
     /* [previous][next][first][last][top][bottom][index][help] */
 834 {
 835    if (in_command) {
 836       in_command = 0;
 837       outb( 0x00, Interrupt_Cntl_port );
 838       fdomain_make_bus_idle();
 839       current_SC->result = error;
 840       if (current_SC->scsi_done)
 841             current_SC->scsi_done( current_SC );
 842       else panic( "Future Domain: current_SC->scsi_done() == NULL" );
 843    } else {
 844       panic( "Future Domain: my_done() called outside of command\n" );
 845    }
 846 #if DEBUG_RACE
 847    in_interrupt_flag = 0;
 848 #endif
 849 }
 850 
 851 void fdomain_16x0_intr( int unused )
     /* [previous][next][first][last][top][bottom][index][help] */
 852 {
 853    int      status;
 854    int      done = 0;
 855    unsigned data_count;
 856 
 857    sti();
 858    
 859    outb( 0x00, Interrupt_Cntl_port );
 860 
 861    /* We usually have one spurious interrupt after each command.  Ignore it. */
 862    if (!in_command || !current_SC) {    /* Spurious interrupt */
 863 #if EVERY_ACCESS
 864       printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
 865               in_command, current_SC );
 866 #endif
 867       return;
 868    }
 869 
 870    /* Abort calls my_done, so we do nothing here. */
 871    if (current_SC->SCp.phase & aborted) {
 872 #if DEBUG_ABORT
 873       printk( "Interrupt after abort, ignoring\n" );
 874 #endif
 875       /*
 876       return; */
 877    }
 878 
 879 #if DEBUG_RACE
 880    ++in_interrupt_flag;
 881 #endif
 882 
 883    if (current_SC->SCp.phase & in_arbitration) {
 884       status = inb( TMC_Status_port );        /* Read adapter status */
 885       if (!(status & 0x02)) {
 886 #if EVERY_ACCESS
 887          printk( " AFAIL " );
 888 #endif
 889          my_done( DID_BUS_BUSY << 16 );
 890          return;
 891       }
 892       current_SC->SCp.phase = in_selection;
 893       
 894       outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
 895 
 896       outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 897       outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
 898       
 899       /* Stop arbitration and enable parity */
 900       outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
 901 #if DEBUG_RACE
 902       in_interrupt_flag = 0;
 903 #endif
 904       return;
 905    } else if (current_SC->SCp.phase & in_selection) {
 906       status = inb( SCSI_Status_port );
 907       if (!(status & 0x01)) {
 908          /* Try again, for slow devices */
 909          if (fdomain_select( current_SC->target )) {
 910 #if EVERY_ACCESS
 911             printk( " SFAIL " );
 912 #endif
 913             my_done( DID_NO_CONNECT << 16 );
 914             return;
 915          } else {
 916 #if EVERY_ACCESS
 917             printk( " AltSel " );
 918 #endif
 919             /* Stop arbitration and enable parity */
 920             outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
 921          }
 922       }
 923       current_SC->SCp.phase = in_other;
 924       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 925       outb( 0x80, SCSI_Cntl_port );
 926 #if DEBUG_RACE
 927       in_interrupt_flag = 0;
 928 #endif
 929       return;
 930    }
 931    
 932    /* current_SC->SCp.phase == in_other: this is the body of the routine */
 933    
 934    status = inb( SCSI_Status_port );
 935    
 936    if (status & 0x10) { /* REQ */
 937       
 938       switch (status & 0x0e) {
 939        
 940       case 0x08:                /* COMMAND OUT */
 941          outb( current_SC->cmnd[current_SC->SCp.sent_command++],
 942                Write_SCSI_Data_port );
 943 #if EVERY_ACCESS
 944          printk( "CMD = %x,",
 945                  current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
 946 #endif
 947          break;
 948       case 0x00:                /* DATA OUT -- tmc18c50/tmc18c30 only */
 949          if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 950             current_SC->SCp.have_data_in = -1;
 951             outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 952          }
 953          break;
 954       case 0x04:                /* DATA IN -- tmc18c50/tmc18c30 only */
 955          if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 956             current_SC->SCp.have_data_in = 1;
 957             outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
 958          }
 959          break;
 960       case 0x0c:                /* STATUS IN */
 961          current_SC->SCp.Status = inb( Read_SCSI_Data_port );
 962 #if EVERY_ACCESS
 963          printk( "Status = %x, ", current_SC->SCp.Status );
 964 #endif
 965 #if ERRORS_ONLY
 966          if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
 967             printk( "Future Domain: target = %d, command = %x, "
 968                     "Status = %x\n",
 969                     current_SC->target, current_SC->cmnd[0],
 970                     current_SC->SCp.Status );
 971          }
 972 #endif
 973                break;
 974       case 0x0a:                /* MESSAGE OUT */
 975          outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
 976          break;
 977       case 0x0e:                /* MESSAGE IN */
 978          current_SC->SCp.Message = inb( Read_SCSI_Data_port );
 979 #if EVERY_ACCESS
 980          printk( "Message = %x, ", current_SC->SCp.Message );
 981 #endif
 982          if (!current_SC->SCp.Message) ++done;
 983 #if DEBUG_MESSAGES || EVERY_ACCESS
 984          if (current_SC->SCp.Message) {
 985             printk( "Future Domain: Message = %x\n",
 986                     current_SC->SCp.Message );
 987          }
 988 #endif
 989          break;
 990       }
 991    }
 992 
 993    if (chip == tmc1800
 994        && !current_SC->SCp.have_data_in
 995        && (current_SC->SCp.sent_command
 996            >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
 997                                 /* We have to get the FIFO direction
 998                                    correct, so I've made a table based
 999                                    on the SCSI Standard of which commands
1000                                    appear to require a DATA OUT phase.
1001                                  */
1002       /*
1003         p. 94: Command for all device types
1004         CHANGE DEFINITION            40 DATA OUT
1005         COMPARE                      39 DATA OUT
1006         COPY                         18 DATA OUT
1007         COPY AND VERIFY              3a DATA OUT
1008         INQUIRY                      12 
1009         LOG SELECT                   4c DATA OUT
1010         LOG SENSE                    4d
1011         MODE SELECT (6)              15 DATA OUT
1012         MODE SELECT (10)             55 DATA OUT
1013         MODE SENSE (6)               1a
1014         MODE SENSE (10)              5a
1015         READ BUFFER                  3c
1016         RECEIVE DIAGNOSTIC RESULTS   1c
1017         REQUEST SENSE                03
1018         SEND DIAGNOSTIC              1d DATA OUT
1019         TEST UNIT READY              00
1020         WRITE BUFFER                 3b DATA OUT
1021 
1022         p.178: Commands for direct-access devices (not listed on p. 94)
1023         FORMAT UNIT                  04 DATA OUT
1024         LOCK-UNLOCK CACHE            36
1025         PRE-FETCH                    34
1026         PREVENT-ALLOW MEDIUM REMOVAL 1e
1027         READ (6)/RECEIVE             08
1028         READ (10)                    3c
1029         READ CAPACITY                25
1030         READ DEFECT DATA (10)        37
1031         READ LONG                    3e
1032         REASSIGN BLOCKS              07 DATA OUT
1033         RELEASE                      17
1034         RESERVE                      16 DATA OUT
1035         REZERO UNIT/REWIND           01
1036         SEARCH DATA EQUAL (10)       31 DATA OUT
1037         SEARCH DATA HIGH (10)        30 DATA OUT
1038         SEARCH DATA LOW (10)         32 DATA OUT
1039         SEEK (6)                     0b
1040         SEEK (10)                    2b
1041         SET LIMITS (10)              33
1042         START STOP UNIT              1b
1043         SYNCHRONIZE CACHE            35
1044         VERIFY (10)                  2f
1045         WRITE (6)/PRINT/SEND         0a DATA OUT
1046         WRITE (10)/SEND              2a DATA OUT
1047         WRITE AND VERIFY (10)        2e DATA OUT
1048         WRITE LONG                   3f DATA OUT
1049         WRITE SAME                   41 DATA OUT ?
1050 
1051         p. 261: Commands for sequential-access devices (not previously listed)
1052         ERASE                        19
1053         LOAD UNLOAD                  1b
1054         LOCATE                       2b
1055         READ BLOCK LIMITS            05
1056         READ POSITION                34
1057         READ REVERSE                 0f
1058         RECOVER BUFFERED DATA        14
1059         SPACE                        11
1060         WRITE FILEMARKS              10 ?
1061 
1062         p. 298: Commands for printer devices (not previously listed)
1063         ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
1064         SLEW AND PRINT               0b DATA OUT  -- same as seek
1065         STOP PRINT                   1b
1066         SYNCHRONIZE BUFFER           10
1067 
1068         p. 315: Commands for processor devices (not previously listed)
1069         
1070         p. 321: Commands for write-once devices (not previously listed)
1071         MEDIUM SCAN                  38
1072         READ (12)                    a8
1073         SEARCH DATA EQUAL (12)       b1 DATA OUT
1074         SEARCH DATA HIGH (12)        b0 DATA OUT
1075         SEARCH DATA LOW (12)         b2 DATA OUT
1076         SET LIMITS (12)              b3
1077         VERIFY (12)                  af
1078         WRITE (12)                   aa DATA OUT
1079         WRITE AND VERIFY (12)        ae DATA OUT
1080 
1081         p. 332: Commands for CD-ROM devices (not previously listed)
1082         PAUSE/RESUME                 4b
1083         PLAY AUDIO (10)              45
1084         PLAY AUDIO (12)              a5
1085         PLAY AUDIO MSF               47
1086         PLAY TRACK RELATIVE (10)     49
1087         PLAY TRACK RELATIVE (12)     a9
1088         READ HEADER                  44
1089         READ SUB-CHANNEL             42
1090         READ TOC                     43
1091 
1092         p. 370: Commands for scanner devices (not previously listed)
1093         GET DATA BUFFER STATUS       34
1094         GET WINDOW                   25
1095         OBJECT POSITION              31
1096         SCAN                         1b
1097         SET WINDOW                   24 DATA OUT
1098 
1099         p. 391: Commands for optical memory devices (not listed)
1100         ERASE (10)                   2c
1101         ERASE (12)                   ac
1102         MEDIUM SCAN                  38 DATA OUT
1103         READ DEFECT DATA (12)        b7
1104         READ GENERATION              29
1105         READ UPDATED BLOCK           2d
1106         UPDATE BLOCK                 3d DATA OUT
1107 
1108         p. 419: Commands for medium changer devices (not listed)
1109         EXCHANGE MEDIUM              46
1110         INITIALIZE ELEMENT STATUS    07
1111         MOVE MEDIUM                  a5
1112         POSITION TO ELEMENT          2b
1113         READ ELEMENT STATUS          b8
1114         REQUEST VOL. ELEMENT ADDRESS b5
1115         SEND VOLUME TAG              b6 DATA OUT
1116 
1117         p. 454: Commands for communications devices (not listed previously)
1118         GET MESSAGE (6)              08
1119         GET MESSAGE (10)             28
1120         GET MESSAGE (12)             a8
1121       */
1122         
1123       switch (current_SC->cmnd[0]) {
1124       case CHANGE_DEFINITION: case COMPARE:         case COPY:
1125       case COPY_VERIFY:       case LOG_SELECT:      case MODE_SELECT:
1126       case MODE_SELECT_10:    case SEND_DIAGNOSTIC: case WRITE_BUFFER:
1127 
1128       case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
1129       case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
1130       case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
1131       case 0x3f:              case 0x41:
1132 
1133       case 0xb1:              case 0xb0:            case 0xb2:
1134       case 0xaa:              case 0xae:
1135 
1136       case 0x24:
1137 
1138       case 0x38:              case 0x3d:
1139 
1140       case 0xb6:
1141          
1142       case 0xea:                /* alternate number for WRITE LONG */
1143          
1144          current_SC->SCp.have_data_in = -1;
1145          outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1146          break;
1147 
1148       case 0x00:
1149       default:
1150          
1151          current_SC->SCp.have_data_in = 1;
1152          outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1153          break;
1154       }
1155    }
1156 
1157    if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
1158       while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
1159 #if EVERY_ACCESS
1160          printk( "DC=%d, ", data_count ) ;
1161 #endif
1162          if (data_count > current_SC->SCp.this_residual)
1163                data_count = current_SC->SCp.this_residual;
1164          if (data_count > 0) {
1165 #if EVERY_ACCESS
1166             printk( "%d OUT, ", data_count );
1167 #endif
1168             if (data_count == 1) {
1169                outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1170                --current_SC->SCp.this_residual;
1171             } else {
1172                data_count >>= 1;
1173                outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1174                current_SC->SCp.ptr += 2 * data_count;
1175                current_SC->SCp.this_residual -= 2 * data_count;
1176             }
1177          }
1178          if (!current_SC->SCp.this_residual) {
1179             if (current_SC->SCp.buffers_residual) {
1180                --current_SC->SCp.buffers_residual;
1181                ++current_SC->SCp.buffer;
1182                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1183                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1184             } else
1185                   break;
1186          }
1187       }
1188    }
1189    
1190    if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
1191       while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1192 #if EVERY_ACCESS
1193          printk( "DC=%d, ", data_count );
1194 #endif
1195          if (data_count > current_SC->SCp.this_residual)
1196                data_count = current_SC->SCp.this_residual;
1197          if (data_count) {
1198 #if EVERY_ACCESS
1199             printk( "%d IN, ", data_count );
1200 #endif
1201             if (data_count == 1) {
1202                *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1203                --current_SC->SCp.this_residual;
1204             } else {
1205                data_count >>= 1; /* Number of words */
1206                insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1207                current_SC->SCp.ptr += 2 * data_count;
1208                current_SC->SCp.this_residual -= 2 * data_count;
1209             }
1210          }
1211          if (!current_SC->SCp.this_residual
1212              && current_SC->SCp.buffers_residual) {
1213             --current_SC->SCp.buffers_residual;
1214             ++current_SC->SCp.buffer;
1215             current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1216             current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1217          }
1218       }
1219    }
1220    
1221    if (done) {
1222 #if EVERY_ACCESS
1223       printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1224 #endif
1225 
1226 #if ERRORS_ONLY
1227       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1228          if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1229             unsigned char key;
1230             unsigned char code;
1231             unsigned char qualifier;
1232 
1233             key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1234                   & 0x0f;
1235             code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1236             qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1237                                           + 13));
1238 
1239             if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1240                 && !(key == NOT_READY
1241                      && code == 0x04
1242                      && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1243                 && !(key == ILLEGAL_REQUEST && (code == 0x25
1244                                                 || code == 0x24
1245                                                 || !code)))
1246                   
1247                   printk( "Future Domain: REQUEST SENSE "
1248                           "Key = %x, Code = %x, Qualifier = %x\n",
1249                           key, code, qualifier );
1250          }
1251       }
1252 #endif
1253 #if EVERY_ACCESS
1254       printk( "BEFORE MY_DONE. . ." );
1255 #endif
1256       my_done( (current_SC->SCp.Status & 0xff)
1257                | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1258 #if EVERY_ACCESS
1259       printk( "RETURNING.\n" );
1260 #endif
1261       
1262    } else {
1263       if (current_SC->SCp.phase & disconnect) {
1264          outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1265          outb( 0x00, SCSI_Cntl_port );
1266       } else {
1267          outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1268       }
1269    }
1270 #if DEBUG_RACE
1271    in_interrupt_flag = 0;
1272 #endif
1273    return;
1274 }
1275 
1276 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
1277 {
1278    if (in_command) {
1279       panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1280    }
1281 #if EVERY_ACCESS
1282    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1283            SCpnt->target,
1284            *(unsigned char *)SCpnt->cmnd,
1285            SCpnt->use_sg,
1286            SCpnt->request_bufflen );
1287 #endif
1288 
1289    fdomain_make_bus_idle();
1290 
1291    current_SC            = SCpnt; /* Save this for the done function */
1292    current_SC->scsi_done = done;
1293 
1294    /* Initialize static data */
1295 
1296    if (current_SC->use_sg) {
1297       current_SC->SCp.buffer =
1298             (struct scatterlist *)current_SC->request_buffer;
1299       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
1300       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
1301       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1302    } else {
1303       current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
1304       current_SC->SCp.this_residual    = current_SC->request_bufflen;
1305       current_SC->SCp.buffer           = NULL;
1306       current_SC->SCp.buffers_residual = 0;
1307    }
1308          
1309    
1310    current_SC->SCp.Status              = 0;
1311    current_SC->SCp.Message             = 0;
1312    current_SC->SCp.have_data_in        = 0;
1313    current_SC->SCp.sent_command        = 0;
1314    current_SC->SCp.phase               = in_arbitration;
1315 
1316    /* Start arbitration */
1317    outb( 0x00, Interrupt_Cntl_port );
1318    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
1319    outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
1320    ++in_command;
1321    outb( 0x20, Interrupt_Cntl_port );
1322    outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1323 
1324    return 0;
1325 }
1326 
1327 /* The following code, which simulates the old-style command function, was
1328    taken from Tommy Thorn's aha1542.c file.  This code is Copyright (C)
1329    1992 Tommy Thorn. */
1330 
1331 static volatile int internal_done_flag    = 0;
1332 static volatile int internal_done_errcode = 0;
1333 
1334 static void internal_done( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1335 {
1336     internal_done_errcode = SCpnt->result;
1337     ++internal_done_flag;
1338 }
1339 
1340 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1341 {
1342     fdomain_16x0_queue( SCpnt, internal_done );
1343 
1344     while (!internal_done_flag)
1345           ;
1346     internal_done_flag = 0;
1347     return internal_done_errcode;
1348 }
1349 
1350 /* End of code derived from Tommy Thorn's work. */
1351 
1352 void print_info( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1353 {
1354    unsigned int imr;
1355    unsigned int irr;
1356    unsigned int isr;
1357    
1358    print_banner();
1359    switch (SCpnt->SCp.phase) {
1360    case in_arbitration: printk( "arbitration " ); break;
1361    case in_selection:   printk( "selection " );   break;
1362    case in_other:       printk( "other " );       break;
1363    default:             printk( "unknown " );     break;
1364    }
1365 
1366    printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1367            SCpnt->SCp.phase,
1368            SCpnt->target,
1369            *(unsigned char *)SCpnt->cmnd,
1370            SCpnt->use_sg,
1371            SCpnt->request_bufflen );
1372    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1373            SCpnt->SCp.sent_command,
1374            SCpnt->SCp.have_data_in,
1375            SCpnt->timeout );
1376 #if DEBUG_RACE
1377    printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1378 #endif
1379 
1380    imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1381    outb( 0x0a, 0xa0 );
1382    irr = inb( 0xa0 ) << 8;
1383    outb( 0x0a, 0x20 );
1384    irr += inb( 0x20 );
1385    outb( 0x0b, 0xa0 );
1386    isr = inb( 0xa0 ) << 8;
1387    outb( 0x0b, 0x20 );
1388    isr += inb( 0x20 );
1389 
1390                                 /* Print out interesting information */
1391    printk( "IMR = 0x%04x", imr );
1392    if (imr & (1 << interrupt_level))
1393          printk( " (masked)" );
1394    printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1395 
1396    printk( "SCSI Status      = 0x%02x\n", inb( SCSI_Status_port ) );
1397    printk( "TMC Status       = 0x%02x", inb( TMC_Status_port ) );
1398    if (inb( TMC_Status_port & 1))
1399          printk( " (interrupt)" );
1400    printk( "\n" );
1401    printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1402    if (inb( Interrupt_Status_port ) & 0x08)
1403          printk( " (enabled)" );
1404    printk( "\n" );
1405    if (chip == tmc18c50 || chip == tmc18c30) {
1406       printk( "FIFO Status      = 0x%02x\n", inb( port_base + FIFO_Status ) );
1407       printk( "Int. Condition   = 0x%02x\n",
1408               inb( port_base + Interrupt_Cond ) );
1409    }
1410    printk( "Configuration 1  = 0x%02x\n", inb( port_base + Configuration1 ) );
1411    if (chip == tmc18c50 || chip == tmc18c30)
1412          printk( "Configuration 2  = 0x%02x\n",
1413                  inb( port_base + Configuration2 ) );
1414 }
1415 
1416 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1417 {
1418 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1419    printk( "Future Domain: Abort " );
1420 #endif
1421 
1422    cli();
1423    if (!in_command) {
1424 #if EVERY_ACCESS || ERRORS_ONLY
1425       printk( " (not in command)\n" );
1426 #endif
1427       sti();
1428       return SCSI_ABORT_NOT_RUNNING;
1429    }
1430 
1431 #if DEBUG_ABORT
1432    print_info( SCpnt );
1433 #endif
1434 
1435    fdomain_make_bus_idle();
1436 
1437    current_SC->SCp.phase |= aborted;
1438 
1439    current_SC->result = DID_ABORT << 16;
1440 
1441    sti();
1442    
1443    /* Aborts are not done well. . . */
1444    my_done( DID_ABORT << 16 );
1445 
1446    return SCSI_ABORT_SUCCESS;
1447 }
1448 
1449 int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
1450 {
1451 #if DEBUG_RESET
1452    static int called_once = 0;
1453 #endif
1454 
1455 #if ERRORS_ONLY
1456    printk( "Future Domain: SCSI Bus Reset\n" );
1457 #endif
1458 
1459 #if DEBUG_RESET
1460    if (called_once) print_info( current_SC );
1461    called_once = 1;
1462 #endif
1463    
1464    outb( 1, SCSI_Cntl_port );
1465    do_pause( 2 );
1466    outb( 0, SCSI_Cntl_port );
1467    do_pause( 115 );
1468    outb( 0, SCSI_Mode_Cntl_port );
1469    outb( PARITY_MASK, TMC_Cntl_port );
1470 
1471    /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1472       is probably hosed at this point.  We will, however, try to keep
1473       things going by informing the high-level code that we need help. */
1474 
1475    return SCSI_RESET_WAKEUP;
1476 }
1477 
1478 #include "sd.h"
1479 #include "scsi_ioctl.h"
1480 
1481 int fdomain_16x0_biosparam( Scsi_Disk *disk, int dev, int *info_array )
     /* [previous][next][first][last][top][bottom][index][help] */
1482 {
1483    int              drive;
1484    unsigned char    buf[512 + sizeof( int ) * 2];
1485    int              size      = disk->capacity;
1486    int              *sizes    = (int *)buf;
1487    unsigned char    *data     = (unsigned char *)(sizes + 2);
1488    unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
1489    int              retcode;
1490    struct drive_info {
1491       unsigned short cylinders;
1492       unsigned char  heads;
1493       unsigned char  sectors;
1494    } *i;
1495    
1496    /* NOTES:
1497       The RAM area starts at 0x1f00 from the bios_base address.
1498 
1499       For BIOS Version 2.0:
1500       
1501       The drive parameter table seems to start at 0x1f30.
1502       The first byte's purpose is not known.
1503       Next is the cylinder, head, and sector information.
1504       The last 4 bytes appear to be the drive's size in sectors.
1505       The other bytes in the drive parameter table are unknown.
1506       If anyone figures them out, please send me mail, and I will
1507       update these notes.
1508 
1509       Tape drives do not get placed in this table.
1510 
1511       There is another table at 0x1fea:
1512       If the byte is 0x01, then the SCSI ID is not in use.
1513       If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1514       although tapes don't seem to be in this table.  I haven't
1515       seen any other numbers (in a limited sample).
1516 
1517       0x1f2d is a drive count (i.e., not including tapes)
1518 
1519       The table at 0x1fcc are I/O ports addresses for the various
1520       operations.  I calculate these by hand in this driver code.
1521 
1522       For BIOS Version 3.2:
1523 
1524       The drive parameter table starts at 0x1f70.  Each entry is
1525       0x0a bytes long.  Heads are one less than we need to report.
1526     */
1527 
1528    drive = MINOR(dev) / 16;
1529 
1530    if (bios_major == 2) {
1531       i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1532       info_array[0] = i->heads;
1533       info_array[1] = i->sectors;
1534       info_array[2] = i->cylinders;
1535    } else if (bios_major == 3 && bios_minor < 4) { /* 3.0 and 3.2 BIOS */
1536       i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1537       info_array[0] = i->heads + 1;
1538       info_array[1] = i->sectors;
1539       info_array[2] = i->cylinders;
1540    } else {                     /* 3.4 BIOS (and up?) */
1541       /* This algorithm was provided by Future Domain (much thanks!). */
1542 
1543       sizes[0] = 0;             /* zero bytes out */
1544       sizes[1] = 512;           /* one sector in */
1545       memcpy( data, do_read, sizeof( do_read ) );
1546       retcode = kernel_scsi_ioctl( disk->device,
1547                                    SCSI_IOCTL_SEND_COMMAND,
1548                                    (void *)buf );
1549       if (!retcode                                  /* SCSI command ok */
1550           && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
1551           && data[0x1c2]) {                         /* Partition type */
1552 
1553          /* The partition table layout is as follows:
1554 
1555             Start: 0x1b3h
1556             Offset: 0 = partition status
1557                     1 = starting head
1558                     2 = starting sector and cylinder (word, encoded)
1559                     4 = partition type
1560                     5 = ending head
1561                     6 = ending sector and cylinder (word, encoded)
1562                     8 = starting absolute sector (double word)
1563                     c = number of sectors (double word)
1564             Signature: 0x1fe = 0x55aa
1565 
1566             So, this algorithm assumes:
1567             1) the first partition table is in use,
1568             2) the data in the first entry is correct, and
1569             3) partitions never divide cylinders
1570 
1571             Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1572             as well as for Linux.  Note also, that Linux doesn't pay any
1573             attention to the fields that are used by this algorithm -- it
1574             only uses the absolute sector data.  Recent versions of Linux's
1575             fdisk(1) will fill this data in correctly, and forthcoming
1576             versions will check for consistency.
1577 
1578             Checking for a non-zero partition type is not part of the
1579             Future Domain algorithm, but it seemed to be a reasonable thing
1580             to do, especially in the Linux and BSD worlds. */
1581 
1582          info_array[0] = data[0x1c3] + 1;           /* heads */
1583          info_array[1] = data[0x1c4] & 0x3f;        /* sectors */
1584       } else {
1585 
1586          /* Note that this new method guarantees that there will always be
1587             less than 1024 cylinders on a platter.  This is good for drives
1588             up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1589 
1590          if ((unsigned int)size >= 0x7e0000U) {
1591             info_array[0] = 0xff; /* heads   = 255 */
1592             info_array[1] = 0x3f; /* sectors =  63 */
1593          } else if ((unsigned int)size >= 0x200000U) {
1594             info_array[0] = 0x80; /* heads   = 128 */
1595             info_array[1] = 0x3f; /* sectors =  63 */
1596          } else {
1597             info_array[0] = 0x40; /* heads   =  64 */
1598             info_array[1] = 0x20; /* sectors =  32 */
1599          }
1600       }
1601                                 /* For both methods, compute the cylinders */
1602       info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1603    }
1604    
1605    return 0;
1606 }

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