Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/wd7000.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.