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

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