root/drivers/scsi/wd7000.c

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

DEFINITIONS

This source file includes following definitions.
  1. any2scsi
  2. scsi2int
  3. wd7000_enable_intr
  4. wd7000_enable_dma
  5. delay
  6. command_out
  7. alloc_scbs
  8. free_scb
  9. init_scbs
  10. mail_out
  11. make_code
  12. wd7000_scsi_done
  13. wd7000_intr_handle
  14. wd7000_queuecommand
  15. wd7000_command
  16. wd7000_diagnostics
  17. wd7000_init
  18. wd7000_revision
  19. wd7000_detect
  20. wd7000_abort
  21. wd7000_reset
  22. wd7000_biosparam

   1 /* $Id: $
   2  *  linux/drivers/scsi/wd7000.c
   3  *
   4  *  Copyright (C) 1992  Thomas Wuensche
   5  *      closely related to the aha1542 driver from Tommy Thorn
   6  *      ( as close as different hardware allows on a lowlevel-driver :-) )
   7  *
   8  *  Revised (and renamed) by John Boyd <boyd@cis.ohio-state.edu> to
   9  *  accommodate Eric Youngdale's modifications to scsi.c.  Nov 1992.
  10  *
  11  *  Additional changes to support scatter/gather.  Dec. 1992.  tw/jb
  12  *
  13  *  No longer tries to reset SCSI bus at boot (it wasn't working anyway).
  14  *  Rewritten to support multiple host adapters.
  15  *  Miscellaneous cleanup.
  16  *  So far, still doesn't do reset or abort correctly, since I have no idea
  17  *  how to do them with this board (8^(.                      Jan 1994 jb
  18  *
  19  * This driver now supports both of the two standard configurations (per
  20  * the 3.36 Owner's Manual, my latest reference) by the same method as
  21  * before; namely, by looking for a BIOS signature.  Thus, the location of
  22  * the BIOS signature determines the board configuration.  Until I have
  23  * time to do something more flexible, users should stick to one of the
  24  * following:
  25  *
  26  * Standard configuration for single-adapter systems:
  27  *    - BIOS at CE00h
  28  *    - I/O base address 350h
  29  *    - IRQ level 15
  30  *    - DMA channel 6
  31  * Standard configuration for a second adapter in a system:
  32  *    - BIOS at C800h
  33  *    - I/O base address 330h
  34  *    - IRQ level 11
  35  *    - DMA channel 5
  36  *
  37  * Anyone who can recompile the kernel is welcome to add others as need
  38  * arises, but unpredictable results may occur if there are conflicts.
  39  * In any event, if there are multiple adapters in a system, they MUST
  40  * use different I/O bases, IRQ levels, and DMA channels, since they will be
  41  * indistinguishable (and in direct conflict) otherwise.
  42  *
  43  *   As a point of information, the NO_OP command toggles the CMD_RDY bit
  44  * of the status port, and this fact could be used as a test for the I/O
  45  * base address (or more generally, board detection).  There is an interrupt
  46  * status port, so IRQ probing could also be done.  I suppose the full
  47  * DMA diagnostic could be used to detect the DMA channel being used.  I
  48  * haven't done any of this, though, because I think there's too much of
  49  * a chance that such explorations could be destructive, if some other
  50  * board's resources are used inadvertently.  So, call me a wimp, but I
  51  * don't want to try it.  The only kind of exploration I trust is memory
  52  * exploration, since it's more certain that reading memory won't be
  53  * destructive.
  54  *
  55  * More to my liking would be a LILO boot command line specification, such
  56  * as is used by the aha152x driver (and possibly others).  I'll look into
  57  * it, as I have time...
  58  *
  59  *   I get mail occasionally from people who either are using or are
  60  * considering using a WD7000 with Linux.  There is a variety of
  61  * nomenclature describing WD7000's.  To the best of my knowledge, the
  62  * following is a brief summary (from an old WD doc - I don't work for
  63  * them or anything like that):
  64  *
  65  * WD7000-FASST2: This is a WD7000 board with the real-mode SST ROM BIOS
  66  *        installed.  Last I heard, the BIOS was actually done by Columbia
  67  *        Data Products.  The BIOS is only used by this driver (and thus
  68  *        by Linux) to identify the board; none of it can be executed under
  69  *        Linux.
  70  *
  71  * WD7000-ASC: This is the original adapter board, with or without BIOS.
  72  *        The board uses a WD33C93 or WD33C93A SBIC, which in turn is
  73  *        controlled by an onboard Z80 processor.  The board interface
  74  *        visible to the host CPU is defined effectively by the Z80's
  75  *        firmware, and it is this firmware's revision level that is
  76  *        determined and reported by this driver.  (The version of the
  77  *        on-board BIOS is of no interest whatsoever.)  The host CPU has
  78  *        no access to the SBIC; hence the fact that it is a WD33C93 is
  79  *        also of no interest to this driver.
  80  *
  81  * WD7000-AX:
  82  * WD7000-MX:
  83  * WD7000-EX: These are newer versions of the WD7000-ASC.  The -ASC is
  84  *        largely built from discrete components; these boards use more
  85  *        integration.  The -AX is an ISA bus board (like the -ASC),
  86  *        the -MX is an MCA (i.e., PS/2) bus board), and the -EX is an
  87  *        EISA bus board.
  88  *
  89  *  At the time of my documentation, the -?X boards were "future" products,
  90  *  and were not yet available.  However, I vaguely recall that Thomas
  91  *  Wuensche had an -AX, so I believe at least it is supported by this
  92  *  driver.  I have no personal knowledge of either -MX or -EX boards.
  93  *
  94  *  P.S. Just recently, I've discovered (directly from WD and Future
  95  *  Domain) that all but the WD7000-EX have been out of production for
  96  *  two years now.  FD has production rights to the 7000-EX, and are
  97  *  producing it under a new name, and with a new BIOS.  If anyone has
  98  *  one of the FD boards, it would be nice to come up with a signature
  99  *  for it.
 100  *                                                           J.B. Jan 1994.
 101  */
 102 
 103 #ifdef MODULE
 104 #include <linux/module.h>
 105 #endif
 106 
 107 #include <stdarg.h>
 108 #include <linux/kernel.h>
 109 #include <linux/head.h>
 110 #include <linux/types.h>
 111 #include <linux/string.h>
 112 #include <linux/sched.h>
 113 #include <linux/malloc.h>
 114 #include <asm/system.h>
 115 #include <asm/dma.h>
 116 #include <asm/io.h>
 117 #include <linux/ioport.h>
 118 #include <linux/proc_fs.h>
 119 #include <linux/blk.h>
 120 #include "scsi.h"
 121 #include "hosts.h"
 122 #include "sd.h"
 123 
 124 #define ANY2SCSI_INLINE    /* undef this to use old macros */
 125 #undef DEBUG
 126 
 127 #include "wd7000.h"
 128 
 129 #include<linux/stat.h>
 130 
 131 struct proc_dir_entry proc_scsi_wd7000 = {
 132     PROC_SCSI_7000FASST, 6, "wd7000",
 133     S_IFDIR | S_IRUGO | S_IXUGO, 2
 134 };
 135 
 136 
 137 /*
 138  *  Mailbox structure sizes.
 139  *  I prefer to keep the number of ICMBs much larger than the number of
 140  *  OGMBs.  OGMBs are used very quickly by the driver to start one or
 141  *  more commands, while ICMBs are used by the host adapter per command.
 142  */
 143 #define OGMB_CNT        16
 144 #define ICMB_CNT        32
 145 
 146 /*
 147  *  Scb's are shared by all active adapters.  So, if they all become busy,
 148  *  callers may be made to wait in alloc_scbs for them to free.  That can
 149  *  be avoided by setting MAX_SCBS to NUM_CONFIG * WD7000_Q.  If you'd
 150  *  rather conserve memory, use a smaller number (> 0, of course) - things
 151  *  will should still work OK.
 152  */
 153 #define MAX_SCBS        32
 154 
 155 /*
 156  *  WD7000-specific mailbox structure
 157  *
 158  */
 159 typedef volatile struct mailbox{
 160   unchar status;
 161   unchar scbptr[3];             /* SCSI-style - MSB first (big endian) */
 162 } Mailbox;
 163 
 164 /*
 165  *  This structure should contain all per-adapter global data.  I.e., any
 166  *  new global per-adapter data should put in here.
 167  *
 168  */
 169 typedef struct adapter {
 170   struct Scsi_Host *sh;             /* Pointer to Scsi_Host structure */
 171   int iobase;                       /* This adapter's I/O base address */
 172   int irq;                          /* This adapter's IRQ level */
 173   int dma;                          /* This adapter's DMA channel */
 174   struct {                          /* This adapter's mailboxes */
 175     Mailbox ogmb[OGMB_CNT];             /* Outgoing mailboxes */
 176     Mailbox icmb[ICMB_CNT];             /* Incoming mailboxes */
 177   } mb;
 178   int next_ogmb;                    /* to reduce contention at mailboxes */
 179   unchar control;                   /* shadows CONTROL port value */
 180   unchar rev1, rev2;                /* filled in by wd7000_revision */
 181 } Adapter;
 182 
 183 /*
 184  * The following is set up by wd7000_detect, and used thereafter by
 185  * wd7000_intr_handle to map the irq level to the corresponding Adapter.
 186  * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be
 187  * changed to pick up the IRQ level correctly.
 188  */
 189 Adapter *irq2host[16] = {NULL};  /* Possible IRQs are 0-15 */
 190 
 191 /*
 192  *  Standard Adapter Configurations - used by wd7000_detect
 193  */
 194 typedef struct {
 195   const void *bios;             /* (linear) base address for ROM BIOS */
 196   int iobase;                   /* I/O ports base address */
 197   int irq;                      /* IRQ level */
 198   int dma;                      /* DMA channel */
 199 } Config;
 200 
 201 static const Config configs[] = {
 202   {(void *) 0xce000, 0x350, 15, 6},  /* defaults for single adapter */
 203   {(void *) 0xc8000, 0x330, 11, 5},  /* defaults for second adapter */
 204   {(void *) 0xd8000, 0x350, 15, 6},  /* Arghhh.... who added this ? */
 205 };
 206 #define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
 207 
 208 /*
 209  *  The following list defines strings to look for in the BIOS that identify
 210  *  it as the WD7000-FASST2 SST BIOS.  I suspect that something should be
 211  *  added for the Future Domain version.
 212  */
 213 typedef struct signature {
 214     const void *sig;           /* String to look for */
 215     unsigned    ofs;           /* offset from BIOS base address */
 216     unsigned    len;           /* length of string */
 217 } Signature;
 218 
 219 static const Signature signatures[] = {
 220   {"SSTBIOS",0x0000d,7}                  /* "SSTBIOS" @ offset 0x0000d */
 221 };
 222 #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
 223 
 224 
 225 /*
 226  *  I/O Port Offsets and Bit Definitions
 227  *  4 addresses are used.  Those not defined here are reserved.
 228  */
 229 #define ASC_STAT        0       /* Status,  Read */
 230 #define ASC_COMMAND     0       /* Command, Write */
 231 #define ASC_INTR_STAT   1       /* Interrupt Status, Read */
 232 #define ASC_INTR_ACK    1       /* Acknowledge, Write */
 233 #define ASC_CONTROL     2       /* Control, Write */
 234 
 235 /* ASC Status Port
 236  */
 237 #define INT_IM          0x80            /* Interrupt Image Flag */
 238 #define CMD_RDY         0x40            /* Command Port Ready */
 239 #define CMD_REJ         0x20            /* Command Port Byte Rejected */
 240 #define ASC_INIT        0x10            /* ASC Initialized Flag */
 241 #define ASC_STATMASK    0xf0            /* The lower 4 Bytes are reserved */
 242 
 243 /* COMMAND opcodes
 244  *
 245  *  Unfortunately, I have no idea how to properly use some of these commands,
 246  *  as the OEM manual does not make it clear.  I have not been able to use
 247  *  enable/disable unsolicited interrupts or the reset commands with any
 248  *  discernible effect whatsoever.  I think they may be related to certain
 249  *  ICB commands, but again, the OEM manual doesn't make that clear.
 250  */
 251 #define NO_OP             0     /* NO-OP toggles CMD_RDY bit in ASC_STAT */
 252 #define INITIALIZATION    1     /* initialization (10 bytes) */
 253 #define DISABLE_UNS_INTR  2     /* disable unsolicited interrupts */
 254 #define ENABLE_UNS_INTR   3     /* enable unsolicited interrupts */
 255 #define INTR_ON_FREE_OGMB 4     /* interrupt on free OGMB */
 256 #define SOFT_RESET        5     /* SCSI bus soft reset */
 257 #define HARD_RESET_ACK    6     /* SCSI bus hard reset acknowledge */
 258 #define START_OGMB        0x80  /* start command in OGMB (n) */
 259 #define SCAN_OGMBS        0xc0  /* start multiple commands, signature (n) */
 260                                 /*    where (n) = lower 6 bits */
 261 /* For INITIALIZATION:
 262  */
 263 typedef struct initCmd {
 264   unchar op;                   /* command opcode (= 1) */
 265   unchar ID;                   /* Adapter's SCSI ID */
 266   unchar bus_on;               /* Bus on time, x 125ns (see below) */
 267   unchar bus_off;              /* Bus off time, ""         ""      */
 268   unchar rsvd;                 /* Reserved */
 269   unchar mailboxes[3];         /* Address of Mailboxes, MSB first  */
 270   unchar ogmbs;                /* Number of outgoing MBs, max 64, 0,1 = 1 */
 271   unchar icmbs;                /* Number of incoming MBs,   ""       ""   */
 272 } InitCmd;
 273 
 274 #define BUS_ON            64    /* x 125ns = 8000ns (BIOS default) */
 275 #define BUS_OFF           15    /* x 125ns = 1875ns (BIOS default) */
 276  
 277 /* Interrupt Status Port - also returns diagnostic codes at ASC reset
 278  *
 279  * if msb is zero, the lower bits are diagnostic status
 280  * Diagnostics:
 281  * 01   No diagnostic error occurred
 282  * 02   RAM failure
 283  * 03   FIFO R/W failed
 284  * 04   SBIC register read/write failed
 285  * 05   Initialization D-FF failed
 286  * 06   Host IRQ D-FF failed
 287  * 07   ROM checksum error
 288  * Interrupt status (bitwise):
 289  * 10NNNNNN   outgoing mailbox NNNNNN is free
 290  * 11NNNNNN   incoming mailbox NNNNNN needs service
 291  */
 292 #define MB_INTR  0xC0           /* Mailbox Service possible/required */
 293 #define IMB_INTR 0x40           /* 1 Incoming / 0 Outgoing */
 294 #define MB_MASK  0x3f           /* mask for mailbox number */
 295 
 296 /* CONTROL port bits
 297  */
 298 #define INT_EN          0x08    /* Interrupt Enable     */
 299 #define DMA_EN          0x04    /* DMA Enable           */
 300 #define SCSI_RES        0x02    /* SCSI Reset           */
 301 #define ASC_RES         0x01    /* ASC Reset            */
 302 
 303 /*
 304    Driver data structures:
 305    - mb and scbs are required for interfacing with the host adapter.
 306      An SCB has extra fields not visible to the adapter; mb's
 307      _cannot_ do this, since the adapter assumes they are contiguous in
 308      memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
 309      to access them.
 310    - An icb is for host-only (non-SCSI) commands.  ICBs are 16 bytes each;
 311      the additional bytes are used only by the driver.
 312    - For now, a pool of SCBs are kept in global storage by this driver,
 313      and are allocated and freed as needed.
 314 
 315   The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
 316   not when it has finished.  Since the SCB must be around for completion,
 317   problems arise when SCBs correspond to OGMBs, which may be reallocated
 318   earlier (or delayed unnecessarily until a command completes).
 319   Mailboxes are used as transient data structures, simply for
 320   carrying SCB addresses to/from the 7000-FASST2.
 321 
 322   Note also since SCBs are not "permanently" associated with mailboxes,
 323   there is no need to keep a global list of Scsi_Cmnd pointers indexed
 324   by OGMB.   Again, SCBs reference their Scsi_Cmnds directly, so mailbox
 325   indices need not be involved.
 326 */
 327 
 328 /*
 329  *  WD7000-specific scatter/gather element structure
 330  */
 331 typedef struct sgb {
 332     unchar len[3];
 333     unchar ptr[3];              /* Also SCSI-style - MSB first */
 334 } Sgb;
 335 
 336 typedef struct scb {            /* Command Control Block 5.4.1 */
 337   unchar op;                    /* Command Control Block Operation Code */
 338   unchar idlun;                 /* op=0,2:Target Id, op=1:Initiator Id */
 339                                 /* Outbound data transfer, length is checked*/
 340                                 /* Inbound data transfer, length is checked */
 341                                 /* Logical Unit Number */
 342   unchar cdb[12];               /* SCSI Command Block */
 343   volatile unchar status;       /* SCSI Return Status */
 344   volatile unchar vue;          /* Vendor Unique Error Code */
 345   unchar maxlen[3];             /* Maximum Data Transfer Length */
 346   unchar dataptr[3];            /* SCSI Data Block Pointer */
 347   unchar linkptr[3];            /* Next Command Link Pointer */
 348   unchar direc;                 /* Transfer Direction */
 349   unchar reserved2[6];          /* SCSI Command Descriptor Block */
 350                                 /* end of hardware SCB */
 351   Scsi_Cmnd *SCpnt;             /* Scsi_Cmnd using this SCB */
 352   Sgb sgb[WD7000_SG];           /* Scatter/gather list for this SCB */
 353   Adapter *host;                /* host adapter */
 354   struct scb *next;             /* for lists of scbs */
 355 } Scb;
 356 
 357 /*
 358  *  This driver is written to allow host-only commands to be executed.
 359  *  These use a 16-byte block called an ICB.  The format is extended by the
 360  *  driver to 18 bytes, to support the status returned in the ICMB and
 361  *  an execution phase code.
 362  *
 363  *  There are other formats besides these; these are the ones I've tried
 364  *  to use.  Formats for some of the defined ICB opcodes are not defined
 365  *  (notably, get/set unsolicited interrupt status) in my copy of the OEM
 366  *  manual, and others are ambiguous/hard to follow.
 367  */
 368 #define ICB_OP_MASK             0x80  /* distinguishes scbs from icbs */
 369 #define ICB_OP_OPEN_RBUF        0x80  /* open receive buffer */
 370 #define ICB_OP_RECV_CMD         0x81  /* receive command from initiator */
 371 #define ICB_OP_RECV_DATA        0x82  /* receive data from initiator */
 372 #define ICB_OP_RECV_SDATA       0x83  /* receive data with status from init. */
 373 #define ICB_OP_SEND_DATA        0x84  /* send data with status to initiator */
 374 #define ICB_OP_SEND_STAT        0x86  /* send command status to initiator */
 375                              /* 0x87 is reserved */
 376 #define ICB_OP_READ_INIT        0x88  /* read initialization bytes */
 377 #define ICB_OP_READ_ID          0x89  /* read adapter's SCSI ID */
 378 #define ICB_OP_SET_UMASK        0x8A  /* set unsolicited interrupt mask */
 379 #define ICB_OP_GET_UMASK        0x8B  /* read unsolicited interrupt mask */
 380 #define ICB_OP_GET_REVISION     0x8C  /* read firmware revision level */
 381 #define ICB_OP_DIAGNOSTICS      0x8D  /* execute diagnostics */
 382 #define ICB_OP_SET_EPARMS       0x8E  /* set execution parameters */
 383 #define ICB_OP_GET_EPARMS       0x8F  /* read execution parameters */
 384 
 385 typedef struct icbRecvCmd {
 386   unchar op;
 387   unchar IDlun;                 /* Initiator SCSI ID/lun */
 388   unchar len[3];                /* command buffer length */
 389   unchar ptr[3];                /* command buffer address */
 390   unchar rsvd[7];               /* reserved */
 391   volatile unchar vue;          /* vendor-unique error code */
 392   volatile unchar status;       /* returned (icmb) status */
 393   volatile unchar phase;        /* used by interrupt handler */
 394 } IcbRecvCmd;
 395 
 396 typedef struct icbSendStat {
 397   unchar op;
 398   unchar IDlun;                 /* Target SCSI ID/lun */
 399   unchar stat;                  /* (outgoing) completion status byte 1 */
 400   unchar rsvd[12];              /* reserved */
 401   volatile unchar vue;          /* vendor-unique error code */
 402   volatile unchar status;       /* returned (icmb) status */
 403   volatile unchar phase;        /* used by interrupt handler */
 404 } IcbSendStat;
 405 
 406 typedef struct icbRevLvl {
 407   unchar op;
 408   volatile unchar primary;      /* primary revision level (returned) */
 409   volatile unchar secondary;    /* secondary revision level (returned) */
 410   unchar rsvd[12];              /* reserved */
 411   volatile unchar vue;          /* vendor-unique error code */
 412   volatile unchar status;       /* returned (icmb) status */
 413   volatile unchar phase;        /* used by interrupt handler */
 414 } IcbRevLvl;
 415 
 416 typedef struct icbUnsMask {     /* I'm totally guessing here */
 417   unchar op;
 418   volatile unchar mask[14];     /* mask bits */
 419 #ifdef 0
 420   unchar rsvd[12];              /* reserved */
 421 #endif
 422   volatile unchar vue;          /* vendor-unique error code */
 423   volatile unchar status;       /* returned (icmb) status */
 424   volatile unchar phase;        /* used by interrupt handler */
 425 } IcbUnsMask;
 426 
 427 typedef struct icbDiag {
 428   unchar op;
 429   unchar type;                  /* diagnostics type code (0-3) */
 430   unchar len[3];                /* buffer length */
 431   unchar ptr[3];                /* buffer address */
 432   unchar rsvd[7];               /* reserved */
 433   volatile unchar vue;          /* vendor-unique error code */
 434   volatile unchar status;       /* returned (icmb) status */
 435   volatile unchar phase;        /* used by interrupt handler */
 436 } IcbDiag;
 437 
 438 #define ICB_DIAG_POWERUP        0     /* Power-up diags only */
 439 #define ICB_DIAG_WALKING        1     /* walking 1's pattern */
 440 #define ICB_DIAG_DMA            2     /* DMA - system memory diags */
 441 #define ICB_DIAG_FULL           3     /* do both 1 & 2 */
 442 
 443 typedef struct icbParms {
 444   unchar op;
 445   unchar rsvd1;                 /* reserved */
 446   unchar len[3];                /* parms buffer length */
 447   unchar ptr[3];                /* parms buffer address */
 448   unchar idx[2];                /* index (MSB-LSB) */
 449   unchar rsvd2[5];              /* reserved */
 450   volatile unchar vue;          /* vendor-unique error code */
 451   volatile unchar status;       /* returned (icmb) status */
 452   volatile unchar phase;        /* used by interrupt handler */
 453 } IcbParms;
 454 
 455 typedef struct icbAny {
 456   unchar op;
 457   unchar data[14];              /* format-specific data */
 458   volatile unchar vue;          /* vendor-unique error code */
 459   volatile unchar status;       /* returned (icmb) status */
 460   volatile unchar phase;        /* used by interrupt handler */
 461 } IcbAny;
 462 
 463 typedef union icb {
 464   unchar op;                    /* ICB opcode */
 465   IcbRecvCmd recv_cmd;          /* format for receive command */
 466   IcbSendStat send_stat;        /* format for send status */
 467   IcbRevLvl rev_lvl;            /* format for get revision level */
 468   IcbDiag diag;                 /* format for execute diagnostics */
 469   IcbParms eparms;              /* format for get/set exec parms */
 470   IcbAny icb;                   /* generic format */
 471   unchar data[18];
 472 } Icb;
 473 
 474 
 475 /*
 476  *  Driver SCB structure pool.
 477  *
 478  *  The SCBs declared here are shared by all host adapters; hence, this
 479  *  structure is not part of the Adapter structure.
 480  */
 481 static Scb scbs[MAX_SCBS];
 482 static Scb *scbfree = NULL;      /* free list */
 483 static int freescbs = MAX_SCBS;  /* free list counter */
 484 
 485 /*
 486  *  END of data/declarations - code follows.
 487  */
 488 
 489 
 490 #ifdef ANY2SCSI_INLINE
 491 /*
 492    Since they're used a lot, I've redone the following from the macros
 493    formerly in wd7000.h, hopefully to speed them up by getting rid of
 494    all the shifting (it may not matter; GCC might have done as well anyway).
 495 
 496    xany2scsi and xscsi2int were not being used, and are no longer defined.
 497    (They were simply 4-byte versions of these routines).
 498 */
 499 
 500 typedef union {  /* let's cheat... */
 501   int i;
 502   unchar u[sizeof(int)];  /* the sizeof(int) makes it more portable */
 503 } i_u;
 504 
 505 
 506 static inline void any2scsi( unchar *scsi, int any )
     /* [previous][next][first][last][top][bottom][index][help] */
 507 {
 508     *scsi++ = ((i_u) any).u[2];
 509     *scsi++ = ((i_u) any).u[1];
 510     *scsi++ = ((i_u) any).u[0];
 511 }
 512 
 513 
 514 static inline int scsi2int( unchar *scsi )
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516     i_u result;
 517 
 518     result.i = 0;  /* clears unused bytes */
 519     *(result.u+2) = *scsi++;
 520     *(result.u+1) = *scsi++;
 521       *(result.u) = *scsi++;
 522     return result.i;
 523 }
 524 #else
 525 /*
 526    These are the old ones - I've just moved them here...
 527 */
 528 #undef any2scsi
 529 #define any2scsi(up, p)                 \
 530 (up)[0] = (((unsigned long)(p)) >> 16);         \
 531 (up)[1] = ((unsigned long)(p)) >> 8;            \
 532 (up)[2] = ((unsigned long)(p));
 533 
 534 #undef scsi2int
 535 #define scsi2int(up) ( (((unsigned long)*(up)) << 16) + \
 536  (((unsigned long)(up)[1]) << 8) + ((unsigned long)(up)[2]) )
 537 #endif
 538 
 539     
 540 static inline void wd7000_enable_intr(Adapter *host)
     /* [previous][next][first][last][top][bottom][index][help] */
 541 {
 542     host->control |= INT_EN;
 543     outb(host->control, host->iobase+ASC_CONTROL);
 544 }
 545 
 546 
 547 static inline void wd7000_enable_dma(Adapter *host)
     /* [previous][next][first][last][top][bottom][index][help] */
 548 {
 549     host->control |= DMA_EN;
 550     outb(host->control,host->iobase+ASC_CONTROL);
 551     set_dma_mode(host->dma, DMA_MODE_CASCADE);
 552     enable_dma(host->dma);
 553 }
 554 
 555 
 556 #define WAITnexttimeout 200  /* 2 seconds */
 557 
 558 #define WAIT(port, mask, allof, noneof)                                 \
 559  { register volatile unsigned WAITbits;                                 \
 560    register unsigned long WAITtimeout = jiffies + WAITnexttimeout;      \
 561    while (1) {                                                          \
 562      WAITbits = inb(port) & (mask);                                     \
 563      if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
 564        break;                                                           \
 565      if (jiffies > WAITtimeout) goto fail;                              \
 566    }                                                                    \
 567  }
 568 
 569 
 570 static inline void delay( unsigned how_long )
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572      register unsigned long time = jiffies + how_long;
 573 
 574      while (jiffies < time);
 575 }
 576 
 577 
 578 static inline int command_out(Adapter *host, unchar *cmd, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 579 {
 580     WAIT(host->iobase+ASC_STAT,ASC_STATMASK,CMD_RDY,0);
 581     while (len--)  {
 582         do  {
 583             outb(*cmd, host->iobase+ASC_COMMAND);
 584             WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0);
 585         }  while (inb(host->iobase+ASC_STAT) & CMD_REJ);
 586         cmd++;
 587     }
 588     return 1;
 589 
 590 fail:
 591     printk("wd7000 command_out: WAIT failed(%d)\n", len+1);
 592     return 0;
 593 }
 594 
 595 
 596 /*
 597  *  This version of alloc_scbs is in preparation for supporting multiple
 598  *  commands per lun and command chaining, by queueing pending commands.
 599  *  We will need to allocate Scbs in blocks since they will wait to be
 600  *  executed so there is the possibility of deadlock otherwise.
 601  *  Also, to keep larger requests from being starved by smaller requests,
 602  *  we limit access to this routine with an internal busy flag, so that
 603  *  the satisfiability of a request is not dependent on the size of the
 604  *  request.
 605  */
 606 static inline Scb *alloc_scbs(int needed)
     /* [previous][next][first][last][top][bottom][index][help] */
 607 {
 608     register Scb *scb, *p;
 609     register unsigned long flags;
 610     register unsigned long timeout = jiffies + WAITnexttimeout;
 611     register unsigned long now;
 612     static int busy = 0;
 613     int i;
 614 
 615     if (needed <= 0)  return NULL;  /* sanity check */
 616 
 617     save_flags(flags);
 618     cli();
 619     while (busy)  { /* someone else is allocating */
 620         sti();  /* Yes this is really needed here */
 621         now = jiffies;  while (jiffies == now)  /* wait a jiffy */;
 622         cli();
 623     }
 624     busy = 1;          /* not busy now; it's our turn */
 625 
 626     while (freescbs < needed)  {
 627         timeout = jiffies + WAITnexttimeout;
 628         do {
 629             sti();      /* Yes this is really needed here */
 630             now = jiffies;   while (jiffies == now) /* wait a jiffy */;
 631             cli();
 632         }  while (freescbs < needed && jiffies <= timeout);
 633         /*
 634          *  If we get here with enough free Scbs, we can take them.
 635          *  Otherwise, we timed out and didn't get enough.
 636          */
 637         if (freescbs < needed)  {
 638             busy = 0;
 639             panic("wd7000: can't get enough free SCBs.\n");
 640             restore_flags(flags);
 641             return NULL;
 642         }
 643     }
 644     scb = scbfree;  freescbs -= needed;
 645     for (i = 0; i < needed; i++)  { p = scbfree;  scbfree = p->next; }
 646     p->next = NULL;
 647     
 648     busy = 0;   /* we're done */
 649 
 650     restore_flags(flags);
 651 
 652     return scb;
 653 }
 654 
 655 
 656 static inline void free_scb( Scb *scb )
     /* [previous][next][first][last][top][bottom][index][help] */
 657 {
 658     register unsigned long flags;
 659 
 660     save_flags(flags);
 661     cli();
 662 
 663     memset(scb, 0, sizeof(Scb));
 664     scb->next = scbfree;  scbfree = scb;
 665     freescbs++;
 666 
 667     restore_flags(flags);
 668 }
 669 
 670 
 671 static inline void init_scbs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673     int i;
 674     unsigned long flags;
 675 
 676     save_flags(flags);
 677     cli();
 678 
 679     scbfree = &(scbs[0]);
 680     memset(scbs, 0, sizeof(scbs));
 681     for (i = 0;  i < MAX_SCBS-1;  i++)  {
 682       scbs[i].next = &(scbs[i+1]);  scbs[i].SCpnt = NULL;
 683     }
 684     scbs[MAX_SCBS-1].next = NULL;
 685     scbs[MAX_SCBS-1].SCpnt = NULL;
 686 
 687     restore_flags(flags);
 688 }    
 689     
 690 
 691 static int mail_out( Adapter *host, Scb *scbptr )
     /* [previous][next][first][last][top][bottom][index][help] */
 692 /*
 693  *  Note: this can also be used for ICBs; just cast to the parm type.
 694  */
 695 {
 696     register int i, ogmb;
 697     register unsigned long flags;
 698     unchar start_ogmb;
 699     Mailbox *ogmbs = host->mb.ogmb;
 700     int *next_ogmb = &(host->next_ogmb);
 701 #ifdef DEBUG
 702     printk("wd7000 mail_out: %06x",(unsigned int) scbptr);
 703 #endif
 704     /* We first look for a free outgoing mailbox */
 705     save_flags(flags);
 706     cli();
 707     ogmb = *next_ogmb;
 708     for (i = 0; i < OGMB_CNT; i++) {
 709         if (ogmbs[ogmb].status == 0)  {
 710 #ifdef DEBUG
 711             printk(" using OGMB %x",ogmb);
 712 #endif
 713             ogmbs[ogmb].status = 1;
 714             any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
 715 
 716             *next_ogmb = (ogmb+1) % OGMB_CNT;
 717             break;
 718         }  else
 719             ogmb = (++ogmb) % OGMB_CNT;
 720     }
 721     restore_flags(flags);
 722 #ifdef DEBUG
 723     printk(", scb is %x",(unsigned int) scbptr);
 724 #endif
 725     if (i >= OGMB_CNT) {
 726         /*
 727          *  Alternatively, we might issue the "interrupt on free OGMB",
 728          *  and sleep, but it must be ensured that it isn't the init
 729          *  task running.  Instead, this version assumes that the caller
 730          *  will be persistent, and try again.  Since it's the adapter
 731          *  that marks OGMB's free, waiting even with interrupts off
 732          *  should work, since they are freed very quickly in most cases.
 733          */
 734         #ifdef DEBUG
 735         printk(", no free OGMBs.\n");
 736 #endif
 737         return 0;
 738     }
 739 
 740     wd7000_enable_intr(host); 
 741 
 742     start_ogmb = START_OGMB | ogmb;
 743     command_out( host, &start_ogmb, 1 );
 744 #ifdef DEBUG
 745     printk(", awaiting interrupt.\n");
 746 #endif
 747     return 1;
 748 }
 749 
 750 
 751 int make_code(unsigned hosterr, unsigned scsierr)
     /* [previous][next][first][last][top][bottom][index][help] */
 752 {   
 753 #ifdef DEBUG
 754     int in_error = hosterr;
 755 #endif
 756 
 757     switch ((hosterr>>8)&0xff){
 758         case 0: /* Reserved */
 759                 hosterr = DID_ERROR;
 760                 break;
 761         case 1: /* Command Complete, no errors */
 762                 hosterr = DID_OK;
 763                 break;
 764         case 2: /* Command complete, error logged in scb status (scsierr) */ 
 765                 hosterr = DID_OK;
 766                 break;
 767         case 4: /* Command failed to complete - timeout */
 768                 hosterr = DID_TIME_OUT;
 769                 break;
 770         case 5: /* Command terminated; Bus reset by external device */
 771                 hosterr = DID_RESET;
 772                 break;
 773         case 6: /* Unexpected Command Received w/ host as target */
 774                 hosterr = DID_BAD_TARGET;
 775                 break;
 776         case 80: /* Unexpected Reselection */
 777         case 81: /* Unexpected Selection */
 778                 hosterr = DID_BAD_INTR;
 779                 break;
 780         case 82: /* Abort Command Message  */
 781                 hosterr = DID_ABORT;
 782                 break;
 783         case 83: /* SCSI Bus Software Reset */
 784         case 84: /* SCSI Bus Hardware Reset */
 785                 hosterr = DID_RESET;
 786                 break;
 787         default: /* Reserved */
 788                 hosterr = DID_ERROR;
 789                 break;
 790         }
 791 #ifdef DEBUG
 792     if (scsierr||hosterr)
 793         printk("\nSCSI command error: SCSI %02x host %04x return %d",
 794                scsierr,in_error,hosterr);
 795 #endif
 796     return scsierr | (hosterr << 16);
 797 }
 798 
 799 
 800 static void wd7000_scsi_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 801 {
 802 #ifdef DEBUG
 803     printk("wd7000_scsi_done: %06x\n",(unsigned int) SCpnt);
 804 #endif
 805     SCpnt->SCp.phase = 0;
 806 }
 807 
 808 
 809 #define wd7000_intr_ack(host)  outb(0,host->iobase+ASC_INTR_ACK)
 810 
 811 void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 812 {
 813     register int flag, icmb, errstatus, icmb_status;
 814     register int host_error, scsi_error;
 815     register Scb *scb;             /* for SCSI commands */
 816     register IcbAny *icb;          /* for host commands */
 817     register Scsi_Cmnd *SCpnt;
 818     Adapter *host = irq2host[irq];  /* This MUST be set!!! */
 819     Mailbox *icmbs = host->mb.icmb;
 820 
 821 #ifdef DEBUG
 822     printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host);
 823 #endif
 824 
 825     flag = inb(host->iobase+ASC_INTR_STAT);
 826 #ifdef DEBUG
 827     printk("wd7000_intr_handle: intr stat = %02x\n",flag);
 828 #endif
 829 
 830     if (!(inb(host->iobase+ASC_STAT) & INT_IM))  {
 831         /* NB: these are _very_ possible if IRQ 15 is being used, since
 832            it's the "garbage collector" on the 2nd 8259 PIC.  Specifically,
 833            any interrupt signal into the 8259 which can't be identified
 834            comes out as 7 from the 8259, which is 15 to the host.  Thus, it
 835            is a good thing the WD7000 has an interrupt status port, so we
 836            can sort these out.  Otherwise, electrical noise and other such
 837            problems would be indistinguishable from valid interrupts...
 838         */
 839 #ifdef DEBUG 
 840         printk("wd7000_intr_handle: phantom interrupt...\n");
 841 #endif
 842         wd7000_intr_ack(host);
 843         return; 
 844     }
 845 
 846     if (flag & MB_INTR)  {
 847         /* The interrupt is for a mailbox */
 848         if (!(flag & IMB_INTR)) {
 849 #ifdef DEBUG
 850             printk("wd7000_intr_handle: free outgoing mailbox");
 851 #endif
 852             /*
 853              * If sleep_on() and the "interrupt on free OGMB" command are
 854              * used in mail_out(), wake_up() should correspondingly be called
 855              * here.  For now, we don't need to do anything special.
 856              */
 857             wd7000_intr_ack(host);
 858             return;
 859         }  else  {
 860             /* The interrupt is for an incoming mailbox */
 861             icmb = flag & MB_MASK;
 862             icmb_status = icmbs[icmb].status;
 863             if (icmb_status & 0x80)  {  /* unsolicited - result in ICMB */
 864 #ifdef DEBUG
 865                 printk("wd7000_intr_handle: unsolicited interrupt %02xh\n",
 866                        icmb_status);
 867 #endif
 868                 wd7000_intr_ack(host);
 869                 return;
 870             }
 871             scb = (struct scb *) scsi2int((unchar *)icmbs[icmb].scbptr);
 872             icmbs[icmb].status = 0;
 873             if (!(scb->op & ICB_OP_MASK))  {   /* an SCB is done */
 874                 SCpnt = scb->SCpnt;
 875                 if (--(SCpnt->SCp.phase) <= 0)  {  /* all scbs are done */
 876                     host_error = scb->vue | (icmb_status << 8);
 877                     scsi_error = scb->status;
 878                     errstatus = make_code(host_error,scsi_error);    
 879                     SCpnt->result = errstatus;
 880 
 881                     free_scb(scb);
 882 
 883                     SCpnt->scsi_done(SCpnt);
 884                 }
 885             }  else  {    /* an ICB is done */
 886                 icb = (IcbAny *) scb;
 887                 icb->status = icmb_status;
 888                 icb->phase  = 0;
 889             }
 890         }  /* incoming mailbox */
 891     }
 892 
 893     wd7000_intr_ack(host);
 894     return;
 895 }
 896 
 897 
 898 int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 899 {
 900     register Scb *scb;
 901     register Sgb *sgb;
 902     register unchar *cdb = (unchar *) SCpnt->cmnd;
 903     register unchar idlun;
 904     register short cdblen;
 905     Adapter *host = (Adapter *) SCpnt->host->hostdata;
 906 
 907     cdblen = SCpnt->cmd_len;
 908     idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7);
 909     SCpnt->scsi_done = done;
 910     SCpnt->SCp.phase = 1;
 911     scb = alloc_scbs(1);
 912     scb->idlun = idlun;
 913     memcpy(scb->cdb, cdb, cdblen);
 914     scb->direc = 0x40;          /* Disable direction check */
 915 
 916     scb->SCpnt = SCpnt;         /* so we can find stuff later */
 917     SCpnt->host_scribble = (unchar *) scb;
 918     scb->host = host;
 919 
 920     if (SCpnt->use_sg)  {
 921         struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
 922         unsigned i;
 923 
 924         if (SCpnt->host->sg_tablesize == SG_NONE)  {
 925             panic("wd7000_queuecommand: scatter/gather not supported.\n");
 926         }
 927 #ifdef DEBUG
 928         printk("Using scatter/gather with %d elements.\n",SCpnt->use_sg);
 929 #endif
 930 
 931         sgb = scb->sgb;
 932         scb->op = 1;
 933         any2scsi(scb->dataptr, (int) sgb);
 934         any2scsi(scb->maxlen, SCpnt->use_sg * sizeof (Sgb) );
 935 
 936         for (i = 0;  i < SCpnt->use_sg;  i++)  {
 937             any2scsi(sgb[i].ptr, (int) sg[i].address);
 938             any2scsi(sgb[i].len, sg[i].length);
 939         }
 940     }  else  {
 941         scb->op = 0;
 942         any2scsi(scb->dataptr, (int) SCpnt->request_buffer);
 943         any2scsi(scb->maxlen, SCpnt->request_bufflen);
 944     }
 945     while (!mail_out(host, scb)) /* keep trying */;
 946 
 947     return 1;
 948 }
 949 
 950 
 951 int wd7000_command(Scsi_Cmnd *SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 952 {
 953     wd7000_queuecommand(SCpnt, wd7000_scsi_done);
 954 
 955     while (SCpnt->SCp.phase > 0) barrier();  /* phase counts scbs down to 0 */
 956 
 957     return SCpnt->result;
 958 }
 959 
 960 
 961 int wd7000_diagnostics( Adapter *host, int code )
     /* [previous][next][first][last][top][bottom][index][help] */
 962 {
 963     static IcbDiag icb = {ICB_OP_DIAGNOSTICS};
 964     static unchar buf[256];
 965     unsigned long timeout;
 966 
 967     icb.type = code;
 968     any2scsi(icb.len, sizeof(buf));
 969     any2scsi(icb.ptr, (int) &buf);
 970     icb.phase = 1;
 971     /*
 972      * This routine is only called at init, so there should be OGMBs
 973      * available.  I'm assuming so here.  If this is going to
 974      * fail, I can just let the timeout catch the failure.
 975      */
 976     mail_out(host, (struct scb *) &icb);
 977     timeout = jiffies + WAITnexttimeout;  /* wait up to 2 seconds */
 978     while (icb.phase && jiffies < timeout)
 979         barrier(); /* wait for completion */
 980 
 981     if (icb.phase)  {
 982         printk("wd7000_diagnostics: timed out.\n");
 983         return 0;
 984     }
 985     if (make_code(icb.vue|(icb.status << 8),0))  {
 986         printk("wd7000_diagnostics: failed (%02x,%02x)\n",
 987                icb.vue, icb.status);
 988         return 0;
 989     }
 990 
 991     return 1;
 992 }
 993 
 994 
 995 int wd7000_init( Adapter *host )
     /* [previous][next][first][last][top][bottom][index][help] */
 996 {
 997     InitCmd init_cmd = {
 998         INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, {0,0,0}, OGMB_CNT, ICMB_CNT
 999     };
1000     int diag;
1001 
1002     /*
1003        Reset the adapter - only.  The SCSI bus was initialized at power-up,
1004        and we need to do this just so we control the mailboxes, etc.
1005     */
1006     outb(ASC_RES, host->iobase+ASC_CONTROL);
1007     delay(1);  /* reset pulse: this is 10ms, only need 25us */
1008     outb(0,host->iobase+ASC_CONTROL);
1009     host->control = 0;   /* this must always shadow ASC_CONTROL */
1010     WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0);
1011 
1012     if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1)  {
1013         printk("wd7000_init: ");
1014         switch (diag)  {
1015         case 2:
1016           printk("RAM failure.\n");
1017           break;
1018         case 3:
1019           printk("FIFO R/W failed\n");
1020           break;
1021         case 4:
1022           printk("SBIC register R/W failed\n");
1023           break;
1024         case 5:
1025           printk("Initialization D-FF failed.\n");
1026           break;
1027         case 6:
1028           printk("Host IRQ D-FF failed.\n");
1029           break;
1030         case 7:
1031           printk("ROM checksum error.\n");
1032           break;
1033         default:
1034           printk("diagnostic code %02Xh received.\n", diag);
1035           break;
1036         }
1037         return 0;
1038     }
1039     
1040     /* Clear mailboxes */
1041     memset(&(host->mb), 0, sizeof(host->mb));
1042 
1043     /* Execute init command */
1044     any2scsi((unchar *) &(init_cmd.mailboxes), (int) &(host->mb));
1045     if (!command_out(host, (unchar *) &init_cmd, sizeof(init_cmd)))  {
1046         printk("wd7000_init: adapter initialization failed.\n"); 
1047         return 0;
1048     }
1049     WAIT(host->iobase+ASC_STAT, ASC_STATMASK, ASC_INIT, 0);
1050 
1051     if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000", NULL)) {
1052         printk("wd7000_init: can't get IRQ %d.\n", host->irq);
1053         return 0;
1054     }
1055     if (request_dma(host->dma,"wd7000"))  {
1056         printk("wd7000_init: can't get DMA channel %d.\n", host->dma);
1057         free_irq(host->irq, NULL);
1058         return 0;
1059     }
1060     wd7000_enable_dma(host);
1061     wd7000_enable_intr(host);
1062 
1063     if (!wd7000_diagnostics(host,ICB_DIAG_FULL))  {
1064         free_dma(host->dma);
1065         free_irq(host->irq, NULL);
1066         return 0;
1067     }
1068 
1069     return 1;
1070 
1071   fail:
1072     printk("wd7000_init: WAIT timed out.\n"); 
1073     return 0;                                   /* 0 = not ok */
1074 }
1075 
1076 
1077 void wd7000_revision(Adapter *host)
     /* [previous][next][first][last][top][bottom][index][help] */
1078 {
1079     static IcbRevLvl icb = {ICB_OP_GET_REVISION};
1080 
1081     icb.phase = 1;
1082     /*
1083      * Like diagnostics, this is only done at init time, in fact, from
1084      * wd7000_detect, so there should be OGMBs available.  If it fails,
1085      * the only damage will be that the revision will show up as 0.0,
1086      * which in turn means that scatter/gather will be disabled.
1087      */
1088     mail_out(host, (struct scb *) &icb);
1089     while (icb.phase)
1090         barrier(); /* wait for completion */
1091     host->rev1 = icb.primary;
1092     host->rev2 = icb.secondary;
1093 }
1094 
1095 
1096 int wd7000_detect(Scsi_Host_Template * tpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1097 /* 
1098  *  Returns the number of adapters this driver is supporting.
1099  *
1100  *  The source for hosts.c says to wait to call scsi_register until 100%
1101  *  sure about an adapter.  We need to do it a little sooner here; we
1102  *  need the storage set up by scsi_register before wd7000_init, and
1103  *  changing the location of an Adapter structure is more trouble than
1104  *  calling scsi_unregister.
1105  *
1106  */
1107 {
1108     int i,j, present = 0;
1109     const Config *cfg;
1110     const Signature *sig;
1111     Adapter *host = NULL;
1112     struct Scsi_Host *sh;
1113 
1114     tpnt->proc_dir = &proc_scsi_wd7000;
1115 
1116     /* Set up SCB free list, which is shared by all adapters */
1117     init_scbs();
1118 
1119     cfg = configs;
1120     for (i = 0; i < NUM_CONFIGS; i++)  {
1121         sig = signatures;
1122         for (j = 0; j < NUM_SIGNATURES; j++)  {
1123             if (!memcmp(cfg->bios+sig->ofs, sig->sig, sig->len))  {
1124                 /* matched this one */
1125 #ifdef DEBUG
1126                 printk("WD-7000 SST BIOS detected at %04X: checking...\n",
1127                        (int) cfg->bios);
1128 #endif
1129                 /*
1130                  *  We won't explicitly test the configuration (in this
1131                  *  version); instead, we'll just see if it works to
1132                  *  setup the adapter; if it does, we'll use it.
1133                  */
1134                 if (check_region(cfg->iobase, 4))  {  /* ports in use */
1135                     printk("IO %xh already in use.\n", host->iobase);
1136                     continue;
1137                 }
1138                 /*
1139                  *  We register here, to get a pointer to the extra space,
1140                  *  which we'll use as the Adapter structure (host) for
1141                  *  this adapter.  It is located just after the registered
1142                  *  Scsi_Host structure (sh), and is located by the empty
1143                  *  array hostdata.
1144                  */
1145                 sh = scsi_register(tpnt, sizeof(Adapter) );
1146                 host = (Adapter *) sh->hostdata;
1147 #ifdef DEBUG
1148                 printk("wd7000_detect: adapter allocated at %06x\n",
1149                        (int)host);
1150 #endif
1151                 memset( host, 0, sizeof(Adapter) );
1152                 host->sh = sh;
1153                 host->irq = cfg->irq;
1154                 host->iobase = cfg->iobase;
1155                 host->dma = cfg->dma;
1156                 irq2host[host->irq] = host;
1157 
1158                 if (!wd7000_init(host))  {  /* Initialization failed */
1159                     scsi_unregister (sh);
1160                     continue;
1161                 }
1162 
1163                 /*
1164                  *  OK from here - we'll use this adapter/configuration.
1165                  */
1166                 wd7000_revision(host);   /* important for scatter/gather */
1167 
1168                 printk("Western Digital WD-7000 (%d.%d) ",
1169                        host->rev1, host->rev2);
1170                 printk("using IO %xh IRQ %d DMA %d.\n",
1171                        host->iobase, host->irq, host->dma);
1172 
1173                 request_region(host->iobase, 4,"wd7000"); /* Register our ports */
1174                 /*
1175                  *  For boards before rev 6.0, scatter/gather isn't supported.
1176                  */
1177                 if (host->rev1 < 6)  sh->sg_tablesize = SG_NONE;
1178 
1179                 present++;                      /* count it */
1180                 break;                          /* don't try any more sigs */
1181             }
1182             sig++;  /* try next signature with this configuration */
1183         }
1184         cfg++;      /* try next configuration */
1185     }
1186 
1187     return present;
1188 }
1189 
1190 
1191 /*
1192  *  I have absolutely NO idea how to do an abort with the WD7000...
1193  */
1194 int wd7000_abort(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1195 {
1196     Adapter *host = (Adapter *) SCpnt->host->hostdata;
1197 
1198     if (inb(host->iobase+ASC_STAT) & INT_IM)  {
1199         printk("wd7000_abort: lost interrupt\n");
1200         wd7000_intr_handle(host->irq, NULL, NULL);
1201         return SCSI_ABORT_SUCCESS;
1202     }
1203 
1204     return SCSI_ABORT_SNOOZE;
1205 }
1206 
1207 
1208 /*
1209  *  I also have no idea how to do a reset...
1210  */
1211 int wd7000_reset(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
1212 {
1213     return SCSI_RESET_PUNT;
1214 }
1215 
1216 
1217 /*
1218  *  This was borrowed directly from aha1542.c, but my disks are organized
1219  *  this way, so I think it will work OK.  Someone who is ambitious can
1220  *  borrow a newer or more complete version from another driver.
1221  */
1222 int wd7000_biosparam(Disk * disk, kdev_t dev, int* ip)
     /* [previous][next][first][last][top][bottom][index][help] */
1223 {
1224   int size = disk->capacity;
1225   ip[0] = 64;
1226   ip[1] = 32;
1227   ip[2] = size >> 11;
1228 /*  if (ip[2] >= 1024) ip[2] = 1024; */
1229   return 0;
1230 }
1231 
1232 #ifdef MODULE
1233 /* Eventually this will go into an include file, but this will be later */
1234 Scsi_Host_Template driver_template = WD7000;
1235 
1236 #include "scsi_module.c"
1237 #endif

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