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. do_pause
  3. fdomain_make_bus_idle
  4. fdomain_is_valid_port
  5. fdomain_test_loopback
  6. fdomain_16x0_detect
  7. fdomain_16x0_info
  8. fdomain_arbitrate
  9. fdomain_select
  10. my_done
  11. fdomain_16x0_intr
  12. fdomain_16x0_queue
  13. fdomain_16x0_command
  14. fdomain_16x0_abort
  15. fdomain_16x0_reset
  16. fdomain_16x0_biosparam

   1 /* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
   2  * Created: Sun May  3 18:53:19 1992 by faith
   3  * Revised: Wed Dec  9 21:34:53 1992 by root
   4  * Author: Rickard E. Faith, faith@cs.unc.edu
   5  * Copyright 1992 Rickard E. Faith
   6  *
   7  * $Log$
   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  * WARNING: THIS IS A BETA VERSION!
  20  *          USE AT YOUR OWN RISK!
  21  *          BACKUP YOUR SYSTEM BEFORE USING!
  22 
  23  * I would like to thank Maxtor, whose *free* 206 page manual on the LXT
  24  * drives was very helpful: "LXT SCSI Products: Specifications and OEM
  25  * Technical Manual (Revision B/September 1991)"
  26 
  27  * I wish that I could thank Future Domain for the necessary documentation,
  28  * but I can't.  I used the $25 "TMC-1800 SCSI Chip Specification" document
  29  * (FDC-1800T), which documents the *chip* and not the board.  Without it,
  30  * I would have been totally lost, but it would have been nice to have some
  31  * example source.  (The DOS BIOS source cost $250 and the UN*X driver
  32  * source was $750 [both required a non-disclosure agreement].  Ever wonder
  33  * why there are no freely available Future Domain drivers?)
  34 
  35  * Thanks to: Todd Carrico (todd@wutc.wustl.edu), Dan Poirier
  36  * (poirier@cs.unc.edu ), Ken Corey (kenc@sol.acs.unt.edu), C. de Bruin
  37  * (bruin@dutiba.tudelft.nl) and Sakari Aaltonen (sakaria@vipunen.hit.fi)
  38  * for alpha testing.  Also thanks to Drew Eckhardt (drew@cs.colorado.edu)
  39  * and Eric Youngdale (eric@tantalus.nrl.navy.mil) for answering questions,
  40  * and to Doug Hoffman (hoffman@cs.unc.edu) for lending me SCSI devices to
  41  * make the driver more robust. */
  42 
  43 #include <linux/sched.h>
  44 #include <asm/io.h>
  45 #include "../blk.h"
  46 #include "scsi.h"
  47 #include "hosts.h"
  48 #include "fdomain.h"
  49 #include <asm/system.h>
  50 #include <linux/errno.h>
  51 
  52 #define VERSION          "3.2"  /* Change with each revision */
  53 
  54 /* START OF USER DEFINABLE OPTIONS */
  55 
  56 #define DEBUG            1      /* Enable debugging output */
  57 #define ENABLE_PARITY    1      /* Enable SCSI Parity */
  58 #define QUEUE            1      /* Enable command queueing */
  59 #define FIFO_COUNT       2      /* Number of 512 byte blocks before INTR */
  60 #define DO_DETECT        0      /* Do device detection here (see scsi.c) */
  61 #define RESELECTION      0      /* Support RESELECTION PHASE (NOT stable) */
  62 
  63 /* END OF USER DEFINABLE OPTIONS */
  64 
  65 #if DEBUG
  66 #define EVERY_ACCESS     0      /* Write a line on every scsi access */
  67 #define ERRORS_ONLY      1      /* Only write a line if there is an error */
  68 #define DEBUG_DETECT     0      /* Debug fdomain_16x0_detect() */
  69 #define DEBUG_MESSAGES   0      /* Debug MESSAGE IN PHASE */
  70 #define DEBUG_ABORT      1    /* Debug abort() routine */
  71 #else
  72 #define EVERY_ACCESS     0      /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
  73 #define ERRORS_ONLY      0
  74 #define DEBUG_DETECT     0
  75 #define DEBUG_MESSAGES   0
  76 #define DEBUG_ABORT      0
  77 #endif
  78 
  79 /* Errors are reported on the line, so we don't need to report them again */
  80 #if EVERY_ACCESS
  81 #undef ERRORS_ONLY
  82 #define ERRORS_ONLY      0
  83 #endif
  84 
  85 #if ENABLE_PARITY
  86 #define PARITY_MASK      0x08
  87 #else
  88 #define PARITY_MASK      0x00
  89 #endif
  90 
  91 static int               port_base = 0;
  92 static void              *bios_base = NULL;
  93 static int               interrupt_level = 0;
  94 
  95 static int               Data_Mode_Cntl_port;
  96 static int               FIFO_Data_Count_port;
  97 static int               Interrupt_Cntl_port;
  98 static int               Interrupt_Mask_port;
  99 static int               Read_FIFO_port;
 100 static int               Read_SCSI_Data_port;
 101 static int               SCSI_Cntl_port;
 102 static int               SCSI_Data_NoACK_port;
 103 static int               SCSI_Status_port;
 104 static int               TMC_Cntl_port;
 105 static int               TMC_Status_port;
 106 static int               Write_FIFO_port;
 107 static int               Write_SCSI_Data_port;
 108 
 109 static int               this_host = 0;
 110 static int               can_queue = QUEUE;
 111 
 112 static volatile int      in_command = 0;
 113 static volatile int      in_interrupt_code = 0;
 114 static Scsi_Cmnd         *current_SC = NULL;
 115 
 116 enum { non_queueing   = 0x01,
 117        in_arbitration = 0x02,
 118        in_selection   = 0x04,
 119        in_other       = 0x08,
 120        disconnect     = 0x10,
 121        aborted        = 0x20,
 122        sent_ident     = 0x40,
 123      };
 124 
 125 extern void              fdomain_16x0_intr( int unused );
 126 
 127 enum in_port_type { Read_SCSI_Data = 0, SCSI_Status = 1, TMC_Status = 2,
 128                           LSB_ID_Code = 5, MSB_ID_Code = 6, Read_Loopback = 7,
 129                           SCSI_Data_NoACK = 8, Interrupt_Mask = 9,
 130                           Option_Select = 10, Read_FIFO = 12,
 131                           FIFO_Data_Count = 14 };
 132 
 133 enum out_port_type { Write_SCSI_Data = 0, SCSI_Cntl = 1, Interrupt_Cntl = 2,
 134                            Data_Mode_Cntl = 3, TMC_Cntl = 4, Write_Loopback = 7,
 135                            Write_FIFO = 12 };
 136 
 137 static void *addresses[] = {
 138    (void *)0xc8000,
 139    (void *)0xca000,
 140    (void *)0xce000,
 141    (void *)0xde000 };
 142 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
 143                        
 144 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
 145 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
 146 
 147 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 148 
 149 /*
 150 
 151   READ THIS BEFORE YOU ADD A SIGNATURE!
 152 
 153   READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
 154 
 155   READ EVERY WORD, ESPECIALLY THE WORD *NOT*
 156 
 157   This driver works *ONLY* for Future Domain cards using the
 158   TMC-1800 chip.  This includes models TMC-1660 and TMC-1680
 159   *ONLY*.
 160 
 161   The following BIOS signatures have been tried with this driver.  These
 162   signatures are for boards which do *NOT* work with this driver (but the
 163   first one should work with the Seagate driver):
 164 
 165   FUTURE DOMAIN COPR. (C) 1986-1989 V6.0A7/28/90
 166 
 167   FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
 168 
 169   FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
 170 
 171   */
 172 
 173 struct signature {
 174    char *signature;
 175    int  sig_offset;
 176    int  sig_length;
 177 } signatures[] = {
 178    { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0 7/28/89", 5, 50 },
 179    { "FUTURE DOMAIN CORP. (C) 1986-1990 1800", 5, 37 },
 180    /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE */
 181 };
 182 
 183 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
 184 
 185 
 186 /* These functions are based on include/asm/io.h */
 187 
 188 inline static unsigned short inw( unsigned short port )
 189 {
 190    unsigned short _v;
 191    
 192    __asm__ volatile ("inw %1,%0"
 193                      :"=a" (_v):"d" ((unsigned short) port));
 194    return _v;
 195 }
 196 
 197 inline static void outw( unsigned short value, unsigned short port )
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199    __asm__ volatile ("outw %0,%1"
 200                      ::"a" ((unsigned short) value),
 201                      "d" ((unsigned short) port));
 202 }
 203 
 204 
 205 /* These defines are copied from kernel/blk_drv/hd.c */
 206 
 207 #define insw( buf, count, port ) \
 208       __asm__ volatile \
 209       ( "cld;rep;insw"::"d" (port),"D" (buf),"c" (count):"cx","di" )
 210 
 211 #define outsw( buf, count, port ) \
 212       __asm__ volatile \
 213       ("cld;rep;outsw"::"d" (port),"S" (buf),"c" (count):"cx","si")
 214 
 215 
 216 static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
     /* [previous][next][first][last][top][bottom][index][help] */
 217 {
 218    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 219 
 220    while (jiffies < the_time);
 221 }
 222 
 223 inline static void fdomain_make_bus_idle( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225    outb( 0, SCSI_Cntl_port );
 226    outb( 0, Data_Mode_Cntl_port );
 227    outb( 1 | PARITY_MASK, TMC_Cntl_port );
 228 }
 229 
 230 static int fdomain_is_valid_port( int port )
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232    int options;
 233 
 234 #if DEBUG_DETECT 
 235    printk( " (%x%x),",
 236           inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
 237 #endif
 238 
 239    /* The MCA ID is a unique id for each MCA compatible board.  We
 240       are using ISA boards, but Future Domain provides the MCA ID
 241       anyway.  We can use this ID to ensure that this is a Future
 242       Domain TMC-1660/TMC-1680.
 243     */
 244 
 245    if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
 246       if (inb( port + LSB_ID_Code ) != 0x27) return 0;
 247       if (inb( port + MSB_ID_Code ) != 0x61) return 0;
 248    } else {                                 /* test for 0xe960 id */
 249       if (inb( port + MSB_ID_Code ) != 0x60) return 0;
 250    }
 251 
 252    /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
 253       Now, check to be sure the bios_base matches these ports.
 254       If someone was unlucky enough to have purchased more than one
 255       Future Domain board, then they will have to modify this code, as
 256       we only detect one board here.  [The one with the lowest bios_base.]
 257     */
 258 
 259    options = inb( port + Option_Select );
 260 
 261 #if DEBUG_DETECT
 262    printk( " Options = %x,", options );
 263 #endif
 264 
 265    if (addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
 266    interrupt_level = ints[ (options & 0x0e) >> 1 ];
 267 
 268    return 1;
 269 }
 270 
 271 static int fdomain_test_loopback( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273    int i;
 274    int result;
 275 
 276    for (i = 0; i < 255; i++) {
 277       outb( i, port_base + Write_Loopback );
 278       result = inb( port_base + Read_Loopback );
 279       if (i != result) return 1;
 280    }
 281    return 0;
 282 }
 283 
 284 int fdomain_16x0_detect( int hostnum )
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286    int              i, j;
 287    int              flag;
 288    struct sigaction sa;
 289    int              retcode;
 290 #if DO_DETECT
 291    const int        buflen = 255;
 292    Scsi_Cmnd        SCinit;
 293    unsigned char    do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
 294    unsigned char    do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
 295    unsigned char    do_read_capacity[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 296    unsigned char    buf[buflen];
 297 #endif
 298 
 299 #if DEBUG_DETECT
 300    printk( "SCSI: fdomain_16x0_detect()," );
 301 #endif
 302 
 303    for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
 304 #if DEBUG_DETECT
 305       printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
 306 #endif
 307       for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
 308          if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
 309                     signatures[j].signature, signatures[j].sig_length )) {
 310             bios_base = addresses[i];
 311          }
 312       }
 313    }
 314 
 315    if (!bios_base) {
 316 #if DEBUG_DETECT
 317       printk( " FAILED: NO BIOS\n" );
 318 #endif
 319       return 0;
 320    }
 321 
 322    /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 323       Assuming the ROM is enabled (otherwise we wouldn't have been
 324       able to read the ROM signature :-), then the ROM sets up the
 325       RAM area with some magic numbers, such as a list of port
 326       base addresses and a list of the disk "geometry" reported to
 327       DOS (this geometry has nothing to do with physical geometry).
 328     */
 329 
 330    port_base = *((char *)bios_base + 0x1fcc)
 331          + (*((char *)bios_base + 0x1fcd) << 8);
 332    
 333 #if DEBUG_DETECT
 334    printk( " %x,", port_base );
 335 #endif
 336 
 337    for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 338       if (port_base == ports[i]) ++flag;
 339    }
 340 
 341    if (flag) flag = fdomain_is_valid_port( port_base );
 342 
 343    if (!flag) {                 /* Cannot get port base from BIOS RAM */
 344       
 345       /* This is a bad sign.  It usually means that someone patched the
 346          BIOS signature list (the signatures variable) to contain a BIOS
 347          signature for a board *OTHER THAN* the TMC-1660/TMC-1680.
 348        */
 349       
 350 #if DEBUG_DETECT
 351       printk( " RAM FAILED, " );
 352 #endif
 353 
 354       /* Anyway, the alternative to finding the address in the RAM is
 355          to just search through every possible port address for one
 356          that is attached to the Future Domain card.  Don't panic,
 357          though, about reading all these random port addresses--there
 358          are rumors that the Future Domain BIOS does something very
 359          similar.
 360        */
 361 
 362       for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
 363          port_base = ports[i];
 364 #if DEBUG_DETECT
 365          printk( " %x,", port_base );
 366 #endif
 367          flag = fdomain_is_valid_port( port_base );
 368       }
 369    }
 370 
 371    if (!flag) {
 372 #if DEBUG_DETECT
 373       printk( " FAILED: NO PORT\n" );
 374 #endif
 375       return 0;         /* Cannot find valid set of ports */
 376    }
 377 
 378 #if DEBUG_DETECT
 379    printk( "\n" );
 380    printk( "SCSI: bios_base = %x, port_base = %x, interrupt_level = %d\n",
 381           (unsigned)bios_base, port_base, interrupt_level );
 382 #endif
 383 
 384    if (interrupt_level) {
 385       printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
 386              (unsigned)bios_base, port_base, interrupt_level );
 387    } else {
 388       printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
 389              (unsigned)bios_base, port_base );
 390    }
 391    
 392    Data_Mode_Cntl_port  = port_base + Data_Mode_Cntl;
 393    FIFO_Data_Count_port = port_base + FIFO_Data_Count;
 394    Interrupt_Cntl_port  = port_base + Interrupt_Cntl;
 395    Interrupt_Mask_port  = port_base + Interrupt_Mask;
 396    Read_FIFO_port       = port_base + Read_FIFO;
 397    Read_SCSI_Data_port  = port_base + Read_SCSI_Data;
 398    SCSI_Cntl_port       = port_base + SCSI_Cntl;
 399    SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
 400    SCSI_Status_port     = port_base + SCSI_Status;
 401    TMC_Cntl_port        = port_base + TMC_Cntl;
 402    TMC_Status_port      = port_base + TMC_Status;
 403    Write_FIFO_port      = port_base + Write_FIFO;
 404    Write_SCSI_Data_port = port_base + Write_SCSI_Data;
 405 
 406     fdomain_16x0_reset();
 407 
 408    if (fdomain_test_loopback()) {
 409 #if DEBUG_DETECT
 410       printk( "SCSI: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
 411 #endif
 412       return 0;
 413    }
 414 
 415 #if DO_DETECT
 416 
 417    /* These routines are here because of the way the SCSI bus behaves after
 418       a reset.  This appropriate behavior was not handled correctly by the
 419       higher level SCSI routines when I first wrote this driver.  Now,
 420       however, correct scan routines are part of scsi.c and these routines
 421       are no longer needed.  However, this code is still good for
 422       debugging.
 423     */
 424 
 425    SCinit.request_buffer = SCinit.buffer = buf;
 426    SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
 427    SCinit.use_sg = 0;
 428    SCinit.lun = 0;
 429 
 430    printk( "Future Domain detection routine scanning for devices:\n" );
 431    for (i = 0; i < 8; i++) {
 432       SCinit.target = i;
 433       if (i == 6) continue;     /* The host adapter is at SCSI ID 6 */
 434       memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 435       retcode = fdomain_16x0_command(&SCinit);
 436       if (!retcode) {
 437          memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
 438          retcode = fdomain_16x0_command(&SCinit);
 439          if (!retcode) {
 440             printk( "     SCSI ID %d: ", i );
 441             for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
 442                   printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
 443             memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
 444             retcode = fdomain_16x0_command(&SCinit);
 445             if (!retcode) {
 446                unsigned long blocks, size, capacity;
 447                
 448                blocks = (buf[0] << 24) | (buf[1] << 16)
 449                      | (buf[2] << 8) | buf[3];
 450                size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
 451                capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
 452 
 453                printk( "%lu MB (%lu byte blocks)",
 454                       ((capacity + 5L) / 10L), size );
 455             } else {
 456                memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 457                retcode = fdomain_16x0_command(&SCinit);
 458             }
 459             printk ("\n" );
 460          } else {
 461             memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
 462             retcode = fdomain_16x0_command(&SCinit);
 463          }
 464       }
 465    }
 466 #endif
 467 
 468    this_host      = hostnum;
 469    
 470    if (!QUEUE || !interrupt_level) {
 471       printk( "Future Domain: *NO* interrupt level selected!\n" );
 472       printk( "               COMMAND QUEUEING DISABLED!\n" );
 473       can_queue = scsi_hosts[this_host].can_queue = 0;
 474       scsi_hosts[this_host].sg_tablesize = SG_NONE;
 475    } else {
 476       /* Register the IRQ with the kernel */
 477 
 478       sa.sa_handler  = fdomain_16x0_intr;
 479       sa.sa_flags    = SA_INTERRUPT;
 480       sa.sa_mask     = 0;
 481       sa.sa_restorer = NULL;
 482       
 483       retcode = irqaction( interrupt_level, &sa );
 484 
 485       if (retcode < 0) {
 486          if (retcode == -EINVAL) {
 487             printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
 488             printk( "               This shouldn't happen: REPORT TO RIK!\n" );
 489          } else if (retcode == -EBUSY) {
 490             printk( "Future Domain: IRQ %d is already in use!\n",
 491                    interrupt_level );
 492             printk( "               Please use another IRQ for the FD card!\n" );
 493          } else {
 494             printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
 495             printk( "               This shouldn't happen: REPORT TO RIK!\n" );
 496          }
 497          printk( "               COMMAND QUEUEING DISABLED!\n" );
 498       
 499          can_queue = scsi_hosts[this_host].can_queue = 0;
 500          scsi_hosts[this_host].sg_tablesize = SG_NONE;
 501       } else {
 502          printk( "Future Domain: IRQ %d requested from kernel\n",
 503                 interrupt_level );
 504       }
 505    }
 506    
 507    return 1;
 508 }
 509 
 510 const char *fdomain_16x0_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 511 {
 512    static char buffer[] =
 513          "Future Domain TMC-1660/TMC-1680 SCSI driver version "
 514                VERSION
 515                      "\n";
 516    return buffer;
 517 }
 518 
 519 static int fdomain_arbitrate( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 520 {
 521    int           status = 0;
 522    unsigned long timeout;
 523 
 524 #if EVERY_ACCESS
 525    printk( "SCSI: fdomain_arbitrate()\n" );
 526 #endif
 527    
 528    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
 529    outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
 530    outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
 531 
 532    timeout = jiffies + 50;                    /* 500 mS */
 533    while (jiffies < timeout) {
 534       status = inb( TMC_Status_port );        /* Read adapter status */
 535       if (status & 0x02) return 0;            /* Arbitration complete */
 536    }
 537 
 538    /* Make bus idle */
 539    fdomain_make_bus_idle();
 540 
 541 #if EVERY_ACCESS
 542    printk( "Arbitration failed, status = %x\n", status );
 543 #endif
 544 #if ERRORS_ONLY
 545    printk( "SCSI (Future Domain): Arbitration failed, status = %x",
 546           status );
 547 #endif
 548    return 1;
 549 }
 550 
 551 static int fdomain_select( int target )
     /* [previous][next][first][last][top][bottom][index][help] */
 552 {
 553    int           status;
 554    unsigned long timeout;
 555 
 556    /* Send our address OR'd with target address */
 557    outb( 0x40 | (1 << target), SCSI_Data_NoACK_port );
 558 
 559    if (RESELECTION && can_queue)
 560          outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
 561    else
 562          outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 563 
 564    /* Stop arbitration (also set FIFO for output and enable parity) */
 565    outb( 0xc0 | PARITY_MASK, TMC_Cntl_port ); 
 566 
 567    timeout = jiffies + 25;              /* 250mS */
 568    while (jiffies < timeout) {
 569       status = inb( SCSI_Status_port ); /* Read adapter status */
 570       if (status & 1) {                 /* Busy asserted */
 571          /* Enable SCSI Bus (on error, should make bus idle with 0) */
 572          outb( 0x80, SCSI_Cntl_port );
 573          return 0;
 574       }
 575    }
 576    /* Make bus idle */
 577    fdomain_make_bus_idle();
 578 #if EVERY_ACCESS
 579    if (!target) printk( "Selection failed\n" );
 580 #endif
 581 #if ERRORS_ONLY
 582    if (!target) printk( "SCSI (Future Domain): Selection failed" );
 583 #endif
 584    return 1;
 585 }
 586 
 587 void my_done( int error )
     /* [previous][next][first][last][top][bottom][index][help] */
 588 {
 589    if (in_command) {
 590       in_command = 0;
 591       in_interrupt_code = 0;
 592       outb( 0x00, Interrupt_Cntl_port );
 593       fdomain_make_bus_idle();
 594       current_SC->result = error;
 595       if (current_SC->scsi_done) current_SC->scsi_done( current_SC );
 596       else panic( "SCSI (Future Domain): current_SC->scsi_done() == NULL" );
 597    } else {
 598       panic( "SCSI (Future Domain): my_done() called outside of command\n" );
 599    }
 600 }
 601 
 602 void fdomain_16x0_intr( int unused )
     /* [previous][next][first][last][top][bottom][index][help] */
 603 {
 604    int      status;
 605    int      done = 0;
 606    unsigned data_count;
 607 
 608    sti();
 609 
 610    if (in_interrupt_code)
 611          panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
 612    else
 613          ++in_interrupt_code;
 614    
 615    outb( 0x00, Interrupt_Cntl_port );
 616 
 617    if (current_SC->SCp.phase & aborted) {
 618 #if EVERY_ACCESS
 619       if (current_SC->SCp.phase & (in_other || disconnect))
 620             printk( "aborted (%s) = %d, ",
 621                    current_SC->SCp.phase & in_other
 622                    ? "in_other" : "disconnect",
 623                    current_SC->result );
 624       else
 625             printk( "aborted = %d, ",
 626                    current_SC->result );
 627 #endif
 628       /* Force retry for timeouts after selection complete */
 629       if (current_SC->SCp.phase & (in_other || disconnect)) {
 630          fdomain_16x0_reset();
 631          my_done( DID_RESET << 16 );
 632       } else {
 633          my_done( current_SC->result << 16 );
 634       }
 635       return;
 636    }
 637 
 638    /* We usually have one spurious interrupt after each command.  Ignore it. */
 639    if (!in_command) {           /* Spurious interrupt */
 640       in_interrupt_code = 0;
 641       return;
 642    }
 643 
 644 #if RESELECTION
 645    if (current_SC->SCp.phase & disconnect) {
 646       printk( " RECON %x ", inb( SCSI_Data_NoACK_port ) );
 647       current_SC->SCp.phase = in_other;
 648       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 649       outb( 0x84, SCSI_Cntl_port );
 650       while ( (status = inb( SCSI_Status_port )) & 0x20 ) {
 651          printk( "s = %x, ", status );
 652       }
 653       outb( 0x80, SCSI_Cntl_port );
 654    } else
 655 #endif
 656          if (current_SC->SCp.phase & in_arbitration) {
 657       status = inb( TMC_Status_port );        /* Read adapter status */
 658       if (!(status & 0x02)) {
 659 #if EVERY_ACCESS
 660          printk( " AFAIL " );
 661 #endif
 662          my_done( DID_BUS_BUSY << 16 );
 663          return;
 664       }
 665       current_SC->SCp.phase = in_selection;
 666 
 667       outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
 668 
 669       outb( 0x40 | (1 << current_SC->target), SCSI_Data_NoACK_port );
 670 
 671 #if RESELECTION
 672       outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */
 673 #else
 674       outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
 675 #endif
 676 
 677       /* Stop arbitration (also set FIFO for output and enable parity) */
 678       outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 679 
 680       in_interrupt_code = 0;
 681       return;
 682    } else if (current_SC->SCp.phase & in_selection) {
 683       status = inb( SCSI_Status_port );
 684       if (!(status & 0x01)) {
 685          /* Try again, for slow devices */
 686          if (fdomain_select( current_SC->target )) {
 687 #if EVERY_ACCESS
 688             printk( " SFAIL " );
 689 #endif
 690             my_done( DID_NO_CONNECT << 16 );
 691             return;
 692          } else {
 693 #if EVERY_ACCESS
 694          printk( " AltSel " );
 695 #endif
 696          /* Stop arbitration (also set FIFO for output and enable parity) */
 697          outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
 698        }
 699       }
 700       current_SC->SCp.phase = in_other;
 701       in_interrupt_code = 0;
 702       outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 703 #if RESELECTION
 704       outb( 0x88, SCSI_Cntl_port );
 705 #else
 706       outb( 0x80, SCSI_Cntl_port );
 707 #endif
 708       return;
 709    }
 710 
 711    /* current_SC->SCp.phase == in_other: this is the body of the routine */
 712 
 713    switch (current_SC->cmnd[0]) {
 714    case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
 715    case 0x2e: case 0x3b: case 0xea: case 0x3f:
 716       while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
 717 #if EVERY_ACCESS
 718          printk( "DC=%d, ", data_count );
 719 #endif
 720          if (data_count > current_SC->SCp.this_residual)
 721                data_count = current_SC->SCp.this_residual;
 722          if (data_count > 0) {
 723 #if EVERY_ACCESS
 724             printk( "%d OUT, ", data_count );
 725 #endif
 726             if (data_count == 1) {
 727                outb( *current_SC->SCp.ptr++, Write_FIFO_port );
 728                --current_SC->SCp.this_residual;
 729             } else {
 730                data_count >>= 1;
 731                outsw( current_SC->SCp.ptr, data_count, Write_FIFO_port );
 732                current_SC->SCp.ptr += 2 * data_count;
 733                current_SC->SCp.this_residual -= 2 * data_count;
 734             }
 735          }
 736          if (!current_SC->SCp.this_residual) {
 737             if (current_SC->SCp.buffers_residual) {
 738                --current_SC->SCp.buffers_residual;
 739                ++current_SC->SCp.buffer;
 740                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 741                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 742             } else
 743                   break;
 744          }
 745       }
 746       break;
 747    default:
 748       if (!current_SC->SCp.have_data_in) {
 749          outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
 750          ++current_SC->SCp.have_data_in;
 751       } else {
 752          while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
 753 #if EVERY_ACCESS
 754             printk( "DC=%d, ", data_count );
 755 #endif
 756             if (data_count > current_SC->SCp.this_residual)
 757                   data_count = current_SC->SCp.this_residual;
 758             if (data_count) {
 759 #if EVERY_ACCESS
 760                printk( "%d IN, ", data_count );
 761 #endif
 762                if (data_count == 1) {
 763                   *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
 764                   --current_SC->SCp.this_residual;
 765                } else {
 766                   data_count >>= 1; /* Number of words */
 767                   insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
 768                   current_SC->SCp.ptr += 2 * data_count;
 769                   current_SC->SCp.this_residual -= 2 * data_count;
 770                }
 771             }
 772             if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
 773                --current_SC->SCp.buffers_residual;
 774                ++current_SC->SCp.buffer;
 775                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 776                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 777             }
 778          }
 779       }
 780       break;
 781    }
 782 
 783    status = inb( SCSI_Status_port );
 784 
 785    if (status & 0x10) { /* REQ */
 786       
 787       switch (status & 0x0e) {
 788       case 0x08:                /* COMMAND OUT */
 789 #if 0
 790          if (!current_SC->SCp.sent_command) {
 791             int i;
 792             
 793             ++current_SC->SCp.sent_command;
 794             
 795             for (i = 0; i < COMMAND_SIZE( current_SC->cmnd[0] ); i++) {
 796                outb( current_SC->cmnd[i], Write_SCSI_Data_port );
 797 #if EVERY_ACCESS
 798                printk( "CMD = %x,", current_SC->cmnd[i] );
 799 #endif
 800             }
 801          }
 802 #else
 803          outb( current_SC->cmnd[current_SC->SCp.sent_command++],
 804                Write_SCSI_Data_port );
 805 #if EVERY_ACCESS
 806          printk( "CMD = %x,",
 807                  current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
 808 #endif
 809             
 810 #endif
 811          break;
 812       case 0x0c:                /* STATUS IN */
 813          current_SC->SCp.Status = inb( Read_SCSI_Data_port );
 814 #if EVERY_ACCESS
 815          printk( "Status = %x, ", current_SC->SCp.Status );
 816 #endif
 817 #if ERRORS_ONLY
 818          if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
 819             printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
 820                    current_SC->target, current_SC->cmnd[0], current_SC->SCp.Status );
 821          }
 822 #endif
 823          break;
 824       case 0x0a:                /* MESSAGE OUT */
 825 #if RESELECTION
 826          if (!(current_SC->SCp.phase & sent_ident)) {
 827 #if EVERY_ACCESS
 828             printk( " IDENT " );
 829 #endif
 830             outb( 0x80, SCSI_Cntl_port );
 831             outb( IDENTIFY( 1, 0 ), Write_SCSI_Data_port );
 832             current_SC->SCp.phase |= sent_ident;
 833          } else
 834 #else
 835                outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
 836 #endif
 837          break;
 838       case 0x0e:                /* MESSAGE IN */
 839          current_SC->SCp.Message = inb( Read_SCSI_Data_port );
 840 #if EVERY_ACCESS
 841          printk( "Message = %x, ", current_SC->SCp.Message );
 842 #endif
 843          if (!current_SC->SCp.Message) ++done;
 844 #if RESELECTION
 845          if (current_SC->SCp.Message == DISCONNECT) {
 846             printk( " DISCON " );
 847             current_SC->SCp.phase = disconnect;
 848          }
 849 #endif
 850 #if DEBUG_MESSAGES || EVERY_ACCESS
 851          if (current_SC->SCp.Message) {
 852             printk( "SCSI (Future Domain): Message = %x\n",
 853                    current_SC->SCp.Message );
 854          }
 855 #endif
 856          break;
 857       }
 858    }
 859 
 860    if (done) {
 861 #if EVERY_ACCESS
 862       printk( " ** IN DONE ** " );
 863 #endif
 864 
 865       if (current_SC->SCp.have_data_in) {
 866          while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
 867             if (data_count > current_SC->SCp.this_residual)
 868                   data_count = current_SC->SCp.this_residual;
 869 
 870             if (data_count) {
 871 #if EVERY_ACCESS
 872                printk( "%d IN, ", data_count );
 873 #endif
 874                if (data_count == 1) {
 875                   *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
 876                   --current_SC->SCp.this_residual;
 877                } else {
 878                   data_count >>= 1; /* Number of words */
 879                   insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
 880                   current_SC->SCp.this_residual -= 2 * data_count;
 881                }
 882             }
 883 
 884             if (!current_SC->SCp.this_residual
 885                 && current_SC->SCp.buffers_residual) {
 886                
 887                --current_SC->SCp.buffers_residual;
 888                ++current_SC->SCp.buffer;
 889                current_SC->SCp.ptr = current_SC->SCp.buffer->address;
 890                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 891             }
 892          }
 893       }
 894 #if EVERY_ACCESS
 895       printk( "AFTER DATA GET\n" );
 896 #endif
 897       
 898 #if ERRORS_ONLY
 899       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
 900          if ((unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f) {
 901             unsigned char key;
 902             unsigned char code;
 903 
 904             key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f;
 905             code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
 906 
 907             if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
 908                 && !(key == ILLEGAL_REQUEST && (code == 0x25 || !code)))
 909                 
 910                 printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
 911                        key, code );
 912          }
 913       }
 914 #endif
 915 #if EVERY_ACCESS
 916       printk( "BEFORE MY_DONE. . ." );
 917 #endif
 918       my_done( (current_SC->SCp.Status & 0xff) | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
 919 #if EVERY_ACCESS
 920       printk( "RETURNING.\n" );
 921 #endif
 922       
 923    } else {
 924       in_interrupt_code = 0;
 925       if (current_SC->SCp.phase & disconnect) {
 926          outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
 927          outb( 0x00, SCSI_Cntl_port );
 928       } else {
 929          outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
 930       }
 931    }
 932 
 933    return;
 934 }
 935 
 936 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 937 {
 938    if (in_command) {
 939       panic( "SCSI (Future Domain): fdomain_16x0_queue() NOT REENTRANT!\n" );
 940    }
 941 #if EVERY_ACCESS
 942    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
 943            SCpnt->target,
 944            *(unsigned char *)SCpnt->cmnd,
 945            SCpnt->use_sg,
 946            SCpnt->request_bufflen );
 947 #endif
 948 
 949    fdomain_make_bus_idle();
 950 
 951    current_SC            = SCpnt; /* Save this for the done function */
 952    current_SC->scsi_done = done;
 953 
 954    /* Initialize static data */
 955 
 956    if (current_SC->use_sg) {
 957       current_SC->SCp.buffer =
 958             (struct scatterlist *)current_SC->request_buffer;
 959       current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
 960       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
 961       current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
 962    } else {
 963       current_SC->SCp.ptr              = current_SC->request_buffer;
 964       current_SC->SCp.this_residual    = current_SC->request_bufflen;
 965       current_SC->SCp.buffer           = NULL;
 966       current_SC->SCp.buffers_residual = 0;
 967    }
 968          
 969    
 970    current_SC->SCp.Status              = 0;
 971    current_SC->SCp.Message             = 0;
 972    current_SC->SCp.have_data_in        = 0;
 973    current_SC->SCp.sent_command        = 0;
 974    current_SC->SCp.phase               = in_arbitration;
 975 
 976    /* Start arbitration */
 977    outb( 0x00, Interrupt_Cntl_port );
 978    outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
 979    outb( 0x40, SCSI_Data_NoACK_port );        /* Set our id bit */
 980    ++in_command;
 981    outb( 0x20, Interrupt_Cntl_port );
 982    outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
 983 
 984    return 0;
 985 }
 986 
 987 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
     /* [previous][next][first][last][top][bottom][index][help] */
 988 {
 989    const char     *cmd_pt = SCpnt->cmnd;
 990    const char     *the_command = SCpnt->cmnd;
 991    unsigned char  *out_buf_pt = SCpnt->request_buffer;
 992    unsigned char  *in_buf_pt = SCpnt->request_buffer;
 993    unsigned char  target = SCpnt->target;
 994    void           *buff = SCpnt->request_buffer;
 995    int            bufflen = SCpnt->request_bufflen;
 996    int            Status = 0;
 997    int            Message = 0;
 998    int            status;
 999    int            done = 0;
1000    unsigned long  timeout;
1001    unsigned       data_sent = 0;
1002    unsigned       data_count;
1003    int            have_data_in = 0;
1004 
1005    current_SC = SCpnt;
1006 
1007 #if EVERY_ACCESS
1008    printk( "fdomain_command(%d, %x): ", target, (unsigned char)*the_command );
1009 #endif
1010 
1011    if (fdomain_arbitrate()) {
1012 #if ERRORS_ONLY
1013       printk( ", target = %d, command = %x\n",
1014              target, (unsigned char)*the_command );
1015 #endif
1016       return DID_TIME_OUT << 16;
1017    }
1018 
1019    if (fdomain_select( target )) {
1020 #if ERRORS_ONLY
1021       if (!target) printk( ", target = %d, command = %x\n",
1022                          target, (unsigned char)*the_command );
1023 #endif
1024       return DID_NO_CONNECT << 16;
1025    }
1026 
1027    timeout = jiffies + 500;     /* 5000 mS -- For Maxtor after a RST */
1028    current_SC->SCp.phase = non_queueing;
1029 
1030    switch ((unsigned char)*the_command) {
1031    case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
1032    case 0x2e: case 0x3b: case 0xea: case 0x3f:
1033       data_count = 0x2000 - inw( FIFO_Data_Count_port );
1034       if (bufflen - data_sent < data_count)
1035             data_count = bufflen - data_sent;
1036       if (data_count == 1) {
1037          outb( *out_buf_pt++, Write_FIFO_port );
1038          ++data_sent;
1039       } else {
1040          data_count >>= 1;
1041          outsw( out_buf_pt, data_count, Write_FIFO_port );
1042          out_buf_pt += 2 * data_count;
1043          data_sent += 2 * data_count;
1044       }
1045       break;
1046    default:
1047       outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
1048       ++have_data_in;
1049       break;
1050    }
1051    
1052    while (((status = inb( SCSI_Status_port )) & 1)
1053           && !done && !(current_SC->SCp.phase & aborted)
1054           && jiffies < timeout) {
1055       
1056       if (status & 0x10) {      /* REQ */
1057 
1058          switch (status & 0x0e) {
1059          case 0x00:             /* DATA OUT */
1060             data_count = 0x2000 - inw( FIFO_Data_Count_port );
1061             if (bufflen - data_sent < data_count)
1062                   data_count = bufflen - data_sent;
1063             if (data_count == 1) {
1064                outb( *out_buf_pt++, Write_FIFO_port );
1065                ++data_sent;
1066             } else {
1067                data_count >>= 1;
1068                outsw( out_buf_pt, data_count, Write_FIFO_port );
1069                out_buf_pt += 2 * data_count;
1070                data_sent += 2 * data_count;
1071             }
1072             break;
1073          case 0x04:             /* DATA IN */
1074             if (!have_data_in) {
1075                outb( 0x80 | PARITY_MASK, TMC_Cntl_port );
1076                ++have_data_in;
1077             }
1078             data_count = inw( FIFO_Data_Count_port );
1079             if (data_count == 1) {
1080                *in_buf_pt++ = inb( Read_FIFO_port );
1081             } else {
1082                data_count >>= 1; /* Number of words */
1083                insw( in_buf_pt, data_count, Read_FIFO_port );
1084                in_buf_pt += 2 * data_count;
1085             }
1086             break;
1087          case 0x08:             /* COMMAND OUT */
1088             outb( *cmd_pt++, Write_SCSI_Data_port );
1089 #if EVERY_ACCESS
1090             printk( "%x,", (unsigned char)cmd_pt[-1] );
1091 #endif
1092             break;
1093          case 0x0c:             /* STATUS IN */
1094             Status = inb( Read_SCSI_Data_port );
1095 #if EVERY_ACCESS
1096             printk( "Status = %x, ", Status );
1097 #endif
1098 #if ERRORS_ONLY
1099             if (Status) {
1100                printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",
1101                       target, (unsigned char)*the_command, Status );
1102             }
1103 #endif
1104             break;
1105          case 0x0a:             /* MESSAGE OUT */
1106             outb( 0x07, Write_SCSI_Data_port ); /* Reject */
1107             break;
1108          case 0x0e:             /* MESSAGE IN */
1109             Message = inb( Read_SCSI_Data_port );
1110 #if EVERY_ACCESS
1111             printk( "Message = %x, ", Message );
1112 #endif
1113             if (!Message) ++done;
1114             if (Message == DISCONNECT) printk( "DISCONNECT\n" );
1115             break;
1116          }
1117       }
1118    }
1119 
1120    if (jiffies >= timeout) {
1121 #if EVERY_ACCESS
1122       printk( "Time out, status = %x\n", status );
1123 #endif
1124 #if ERRORS_ONLY
1125       printk( "SCSI (Future Domain): "
1126              "Time out, status = %x (target = %d, command = %x)\n",
1127              status, target, (unsigned char)*the_command );
1128 #endif
1129       fdomain_make_bus_idle();
1130       return DID_BUS_BUSY << 16;
1131    }
1132 
1133    if (current_SC->SCp.phase & aborted) {
1134 #if EVERY_ACCESS
1135       printk( "Aborted\n" );
1136 #endif
1137 #if ERRORS_ONLY
1138       printk( "SCSI (Future Domain): Aborted (command = %x)\n",
1139              (unsigned char)*the_command );
1140 #endif
1141       fdomain_16x0_reset();
1142       return DID_RESET << 16;
1143    }
1144    
1145    if (have_data_in) {
1146       while ((data_count = inw( FIFO_Data_Count_port )) != 0) {
1147          if (data_count == 1) {
1148             *in_buf_pt++ = inb( Read_FIFO_port );
1149          } else {
1150             data_count >>= 1; /* Number of words */
1151             insw( in_buf_pt, data_count, Read_FIFO_port );
1152             in_buf_pt += 2 * data_count;
1153          }
1154       }
1155    }
1156 
1157    fdomain_make_bus_idle();
1158 
1159 #if EVERY_ACCESS
1160    printk( "Retcode = %x\n",
1161           (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );
1162 #endif
1163 #if ERRORS_ONLY
1164    if (*the_command == REQUEST_SENSE && !Status) {
1165       if ((unsigned char)(*((char *)buff + 2)) & 0x0f) {
1166          printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
1167                 (unsigned char)(*((char *)buff + 2)) & 0x0f,
1168                 (unsigned char)(*((char *)buff + 12)) );
1169       }
1170    }
1171 #endif
1172 
1173    return (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16);
1174 }
1175 
1176 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
     /* [previous][next][first][last][top][bottom][index][help] */
1177 {
1178 
1179 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1180    printk( "SCSI (Future Domain): Abort " );
1181 #endif
1182 
1183 #if DEBUG_ABORT
1184    printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1185     current_SC->SCp.phase,
1186     in_interrupt_code,
1187     current_SC->target,
1188     *(unsigned char *)current_SC->cmnd,
1189     current_SC->use_sg,
1190     current_SC->request_bufflen );
1191    printk( "IMR = 0x%02x%02x\n", inb( 0x0a1 ), inb( 0x21 ) );
1192    outb( 0x0a, 0xa0 );
1193    printk( "IRR = 0x%02x", inb( 0xa0 ) );
1194    outb( 0x0a, 0x20 );
1195    printk( "%02x\n", inb( 0x20 ) );
1196    outb( 0x0b, 0xa0 );
1197    printk( "ISR = 0x%02x", inb( 0xa0 ) );
1198    outb( 0x0b, 0x20 );
1199    printk( "%02x\n", inb( 0x20 ) );
1200    printk( "SCSI Status    = %x\n", inb( SCSI_Status_port ) );
1201    printk( "TMC Status     = %x\n", inb( TMC_Status_port ) );
1202    printk( "Interrupt Mask = %x\n", inb( Interrupt_Mask_port ) );
1203 #else
1204    cli();
1205    if (!in_command) {
1206 #if EVERY_ACCESS || ERRORS_ONLY
1207       printk( " (not in command)\n" );
1208 #endif
1209       sti();
1210       return 0;
1211    } else {
1212 #if EVERY_ACCESS || ERRORS_ONLY
1213       printk( " code = %d\n", code );
1214 #endif
1215    }
1216 
1217    current_SC->SCp.phase |= aborted;
1218 
1219    current_SC->result = code ? code : DID_ABORT;
1220 
1221    sti();
1222    
1223    /* Aborts are not done well. . . */
1224    my_done( code << 16 );
1225 #endif
1226    return 0;
1227 }
1228 
1229 int fdomain_16x0_reset( void )
     /* [previous][next][first][last][top][bottom][index][help] */
1230 {
1231 #if ERRORS_ONLY
1232    printk( "Future Domain: SCSI Bus Reset\n" );
1233 #endif
1234    outb( 1, SCSI_Cntl_port );
1235    do_pause( 2 );
1236    outb( 0, SCSI_Cntl_port );
1237    do_pause( 115 );
1238    outb( 0, Data_Mode_Cntl_port );
1239    outb( PARITY_MASK, TMC_Cntl_port );
1240    return 0;
1241 }
1242 
1243 int fdomain_16x0_biosparam( int size, int dev, int *info )
     /* [previous][next][first][last][top][bottom][index][help] */
1244 {
1245    int    drive;
1246    struct drive_info {
1247       unsigned short cylinders;
1248       unsigned char  heads;
1249       unsigned char  sectors;
1250    } *i;
1251 
1252    /* NOTES:
1253       The RAM area starts at 0x1f00 from the bios_base address.
1254       The drive parameter table seems to start at 0x1f30.
1255       The first byte's purpose is not known.
1256       Next is the cylinder, head, and sector information.
1257       The last 4 bytes appear to be the drive's size in sectors.
1258       The other bytes in the drive parameter table are unknown.
1259       If anyone figures them out, please send me mail, and I will
1260       update these notes.
1261 
1262       Tape drives do not get placed in this table.
1263 
1264       There is another table at 0x1fea:
1265       If the byte is 0x01, then the SCSI ID is not in use.
1266       If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1267       although tapes don't seem to be in this table.  I haven't
1268       seen any other numbers (in a limited sample).
1269 
1270       0x1f2d is a drive count (i.e., not including tapes)
1271 
1272       The table at 0x1fcc are I/O ports addresses for the various
1273       operations.  I calculate these by hand in this driver code.
1274     */
1275 
1276    drive = MINOR(dev) / 16;
1277    i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1278    info[0] = i->heads;
1279    info[1] = i->sectors;
1280    info[2] = i->cylinders;
1281    return 0;
1282 }

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