root/drivers/scsi/fdomain.c

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

DEFINITIONS

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

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

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