root/kernel/blk_drv/scsi/fdomain.c

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

DEFINITIONS

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

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