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

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