Annotation of Gnu-Mach/linux/src/drivers/scsi/wd7000.h, revision 1.1

1.1     ! root        1: /* $Id: wd7000.h,v 1.1 1999/04/26 05:55:19 tb Exp $
        !             2:  *
        !             3:  * Header file for the WD-7000 driver for Linux
        !             4:  *
        !             5:  * John Boyd <[email protected]>  Jan 1994:
        !             6:  * This file has been reduced to only the definitions needed for the
        !             7:  * WD7000 host structure.
        !             8:  *
        !             9:  * Revision by Miroslav Zagorac <[email protected]>  Jun 1997.
        !            10:  */
        !            11: #ifndef _WD7000_H
        !            12: 
        !            13: #include <linux/version.h>
        !            14: #include <linux/types.h>
        !            15: #include <linux/kdev_t.h>
        !            16: 
        !            17: #ifndef NULL
        !            18: #define NULL 0L
        !            19: #endif
        !            20: 
        !            21: /*
        !            22:  *  In this version, sg_tablesize now defaults to WD7000_SG, and will
        !            23:  *  be set to SG_NONE for older boards.  This is the reverse of the
        !            24:  *  previous default, and was changed so that the driver-level
        !            25:  *  Scsi_Host_Template would reflect the driver's support for scatter/
        !            26:  *  gather.
        !            27:  *
        !            28:  *  Also, it has been reported that boards at Revision 6 support scatter/
        !            29:  *  gather, so the new definition of an "older" board has been changed
        !            30:  *  accordingly.
        !            31:  */
        !            32: #define WD7000_Q    16
        !            33: #define WD7000_SG   16
        !            34: 
        !            35: #ifdef WD7000_DEFINES
        !            36: /*
        !            37:  *  Mailbox structure sizes.
        !            38:  *  I prefer to keep the number of ICMBs much larger than the number of
        !            39:  *  OGMBs.  OGMBs are used very quickly by the driver to start one or
        !            40:  *  more commands, while ICMBs are used by the host adapter per command.
        !            41:  */
        !            42: #define OGMB_CNT       16
        !            43: #define ICMB_CNT       32
        !            44: 
        !            45: /*
        !            46:  *  Scb's are shared by all active adapters.  If you'd rather conserve
        !            47:  *  memory, use a smaller number (> 0, of course) - things will should
        !            48:  *  still work OK.
        !            49:  */
        !            50: #define MAX_SCBS       (4 * WD7000_Q)
        !            51: 
        !            52: /*
        !            53:  *  WD7000-specific mailbox structure
        !            54:  */
        !            55: typedef volatile struct {
        !            56:     unchar status;
        !            57:     unchar scbptr[3];          /* SCSI-style - MSB first (big endian) */
        !            58: } Mailbox;
        !            59: 
        !            60: /*
        !            61:  *  This structure should contain all per-adapter global data.  I.e., any
        !            62:  *  new global per-adapter data should put in here.
        !            63:  */
        !            64: typedef struct {
        !            65:     struct Scsi_Host *sh;      /* Pointer to Scsi_Host structure    */
        !            66:     int iobase;                        /* This adapter's I/O base address   */
        !            67:     int irq;                   /* This adapter's IRQ level          */
        !            68:     int dma;                   /* This adapter's DMA channel        */
        !            69:     int int_counter;           /* This adapter's interrupt counter  */
        !            70:     int bus_on;                        /* This adapter's BUS_ON time        */
        !            71:     int bus_off;               /* This adapter's BUS_OFF time       */
        !            72:     struct {                   /* This adapter's mailboxes          */
        !            73:        Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes                */
        !            74:        Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes                */
        !            75:     } mb;
        !            76:     int next_ogmb;             /* to reduce contention at mailboxes */
        !            77:     unchar control;            /* shadows CONTROL port value        */
        !            78:     unchar rev1;               /* filled in by wd7000_revision      */
        !            79:     unchar rev2;
        !            80: } Adapter;
        !            81: 
        !            82: 
        !            83: /*
        !            84:  * possible irq range
        !            85:  */
        !            86: #define IRQ_MIN                3
        !            87: #define IRQ_MAX                15
        !            88: #define IRQS           (IRQ_MAX - IRQ_MIN + 1)
        !            89: 
        !            90: #define BUS_ON         64      /* x 125ns = 8000ns (BIOS default) */
        !            91: #define BUS_OFF                15      /* x 125ns = 1875ns (BIOS default) */
        !            92: 
        !            93: /*
        !            94:  *  Standard Adapter Configurations - used by wd7000_detect
        !            95:  */
        !            96: typedef struct {
        !            97:     short irq;         /* IRQ level                                  */
        !            98:     short dma;         /* DMA channel                                */
        !            99:     uint iobase;       /* I/O base address                           */
        !           100:     short bus_on;      /* Time that WD7000 spends on the AT-bus when */
        !           101:                        /* transferring data. BIOS default is 8000ns. */
        !           102:     short bus_off;     /* Time that WD7000 spends OFF THE BUS after  */
        !           103:                        /* while it is transferring data.             */
        !           104:                        /* BIOS default is 1875ns                     */
        !           105: } Config;
        !           106: 
        !           107: 
        !           108: /*
        !           109:  *  The following list defines strings to look for in the BIOS that identify
        !           110:  *  it as the WD7000-FASST2 SST BIOS.  I suspect that something should be
        !           111:  *  added for the Future Domain version.
        !           112:  */
        !           113: typedef struct {
        !           114:     const char *sig;           /* String to look for            */
        !           115:     ulong ofs;                 /* offset from BIOS base address */
        !           116:     uint len;                  /* length of string              */
        !           117: } Signature;
        !           118: 
        !           119: /*
        !           120:  *  I/O Port Offsets and Bit Definitions
        !           121:  *  4 addresses are used.  Those not defined here are reserved.
        !           122:  */
        !           123: #define ASC_STAT       0       /* Status,  Read          */
        !           124: #define ASC_COMMAND    0       /* Command, Write         */
        !           125: #define ASC_INTR_STAT  1       /* Interrupt Status, Read */
        !           126: #define ASC_INTR_ACK   1       /* Acknowledge, Write     */
        !           127: #define ASC_CONTROL    2       /* Control, Write         */
        !           128: 
        !           129: /*
        !           130:  * ASC Status Port
        !           131:  */
        !           132: #define INT_IM         0x80    /* Interrupt Image Flag           */
        !           133: #define CMD_RDY                0x40    /* Command Port Ready             */
        !           134: #define CMD_REJ                0x20    /* Command Port Byte Rejected     */
        !           135: #define ASC_INIT        0x10   /* ASC Initialized Flag           */
        !           136: #define ASC_STATMASK    0xf0   /* The lower 4 Bytes are reserved */
        !           137: 
        !           138: /*
        !           139:  * COMMAND opcodes
        !           140:  *
        !           141:  *  Unfortunately, I have no idea how to properly use some of these commands,
        !           142:  *  as the OEM manual does not make it clear.  I have not been able to use
        !           143:  *  enable/disable unsolicited interrupts or the reset commands with any
        !           144:  *  discernible effect whatsoever.  I think they may be related to certain
        !           145:  *  ICB commands, but again, the OEM manual doesn't make that clear.
        !           146:  */
        !           147: #define NO_OP                  0       /* NO-OP toggles CMD_RDY bit in ASC_STAT  */
        !           148: #define INITIALIZATION         1       /* initialization (10 bytes)              */
        !           149: #define DISABLE_UNS_INTR       2       /* disable unsolicited interrupts         */
        !           150: #define ENABLE_UNS_INTR                3       /* enable unsolicited interrupts          */
        !           151: #define INTR_ON_FREE_OGMB      4       /* interrupt on free OGMB                 */
        !           152: #define SOFT_RESET             5       /* SCSI bus soft reset                    */
        !           153: #define HARD_RESET_ACK         6       /* SCSI bus hard reset acknowledge        */
        !           154: #define START_OGMB             0x80    /* start command in OGMB (n)              */
        !           155: #define SCAN_OGMBS             0xc0    /* start multiple commands, signature (n) */
        !           156:                                        /*    where (n) = lower 6 bits            */
        !           157: /*
        !           158:  * For INITIALIZATION:
        !           159:  */
        !           160: typedef struct {
        !           161:     unchar op;                 /* command opcode (= 1)                    */
        !           162:     unchar ID;                 /* Adapter's SCSI ID                       */
        !           163:     unchar bus_on;             /* Bus on time, x 125ns (see below)        */
        !           164:     unchar bus_off;            /* Bus off time, ""         ""             */
        !           165:     unchar rsvd;               /* Reserved                                */
        !           166:     unchar mailboxes[3];       /* Address of Mailboxes, MSB first         */
        !           167:     unchar ogmbs;              /* Number of outgoing MBs, max 64, 0,1 = 1 */
        !           168:     unchar icmbs;              /* Number of incoming MBs,   ""       ""   */
        !           169: } InitCmd;
        !           170: 
        !           171: /*
        !           172:  * Interrupt Status Port - also returns diagnostic codes at ASC reset
        !           173:  *
        !           174:  * if msb is zero, the lower bits are diagnostic status
        !           175:  * Diagnostics:
        !           176:  * 01   No diagnostic error occurred
        !           177:  * 02   RAM failure
        !           178:  * 03   FIFO R/W failed
        !           179:  * 04   SBIC register read/write failed
        !           180:  * 05   Initialization D-FF failed
        !           181:  * 06   Host IRQ D-FF failed
        !           182:  * 07   ROM checksum error
        !           183:  * Interrupt status (bitwise):
        !           184:  * 10NNNNNN   outgoing mailbox NNNNNN is free
        !           185:  * 11NNNNNN   incoming mailbox NNNNNN needs service
        !           186:  */
        !           187: #define MB_INTR                0xC0    /* Mailbox Service possible/required */
        !           188: #define IMB_INTR       0x40    /* 1 Incoming / 0 Outgoing           */
        !           189: #define MB_MASK                0x3f    /* mask for mailbox number           */
        !           190: 
        !           191: /*
        !           192:  * CONTROL port bits
        !           193:  */
        !           194: #define INT_EN         0x08    /* Interrupt Enable */
        !           195: #define DMA_EN         0x04    /* DMA Enable       */
        !           196: #define SCSI_RES       0x02    /* SCSI Reset       */
        !           197: #define ASC_RES                0x01    /* ASC Reset        */
        !           198: 
        !           199: /*
        !           200:  * Driver data structures:
        !           201:  *   - mb and scbs are required for interfacing with the host adapter.
        !           202:  *     An SCB has extra fields not visible to the adapter; mb's
        !           203:  *     _cannot_ do this, since the adapter assumes they are contiguous in
        !           204:  *     memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
        !           205:  *     to access them.
        !           206:  *   - An icb is for host-only (non-SCSI) commands.  ICBs are 16 bytes each;
        !           207:  *     the additional bytes are used only by the driver.
        !           208:  *   - For now, a pool of SCBs are kept in global storage by this driver,
        !           209:  *     and are allocated and freed as needed.
        !           210:  *
        !           211:  *  The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
        !           212:  *  not when it has finished.  Since the SCB must be around for completion,
        !           213:  *  problems arise when SCBs correspond to OGMBs, which may be reallocated
        !           214:  *  earlier (or delayed unnecessarily until a command completes).
        !           215:  *  Mailboxes are used as transient data structures, simply for
        !           216:  *  carrying SCB addresses to/from the 7000-FASST2.
        !           217:  *
        !           218:  *  Note also since SCBs are not "permanently" associated with mailboxes,
        !           219:  *  there is no need to keep a global list of Scsi_Cmnd pointers indexed
        !           220:  *  by OGMB.   Again, SCBs reference their Scsi_Cmnds directly, so mailbox
        !           221:  *  indices need not be involved.
        !           222:  */
        !           223: 
        !           224: /*
        !           225:  *  WD7000-specific scatter/gather element structure
        !           226:  */
        !           227: typedef struct {
        !           228:     unchar len[3];
        !           229:     unchar ptr[3];             /* Also SCSI-style - MSB first */
        !           230: } Sgb;
        !           231: 
        !           232: typedef struct {               /* Command Control Block 5.4.1               */
        !           233:     unchar op;                 /* Command Control Block Operation Code      */
        !           234:     unchar idlun;              /* op=0,2:Target Id, op=1:Initiator Id       */
        !           235:                                /* Outbound data transfer, length is checked */
        !           236:                                /* Inbound data transfer, length is checked  */
        !           237:                                /* Logical Unit Number                       */
        !           238:     unchar cdb[12];            /* SCSI Command Block                        */
        !           239:     volatile unchar status;    /* SCSI Return Status                        */
        !           240:     volatile unchar vue;       /* Vendor Unique Error Code                  */
        !           241:     unchar maxlen[3];          /* Maximum Data Transfer Length              */
        !           242:     unchar dataptr[3];         /* SCSI Data Block Pointer                   */
        !           243:     unchar linkptr[3];         /* Next Command Link Pointer                 */
        !           244:     unchar direc;              /* Transfer Direction                        */
        !           245:     unchar reserved2[6];       /* SCSI Command Descriptor Block             */
        !           246:                                /* end of hardware SCB                       */
        !           247:     Scsi_Cmnd *SCpnt;          /* Scsi_Cmnd using this SCB                  */
        !           248:     Sgb sgb[WD7000_SG];                /* Scatter/gather list for this SCB          */
        !           249:     Adapter *host;             /* host adapter                              */
        !           250:     unchar used;               /* flag                                      */
        !           251: } Scb;
        !           252: 
        !           253: /*
        !           254:  *  This driver is written to allow host-only commands to be executed.
        !           255:  *  These use a 16-byte block called an ICB.  The format is extended by the
        !           256:  *  driver to 18 bytes, to support the status returned in the ICMB and
        !           257:  *  an execution phase code.
        !           258:  *
        !           259:  *  There are other formats besides these; these are the ones I've tried
        !           260:  *  to use.  Formats for some of the defined ICB opcodes are not defined
        !           261:  *  (notably, get/set unsolicited interrupt status) in my copy of the OEM
        !           262:  *  manual, and others are ambiguous/hard to follow.
        !           263:  */
        !           264: #define ICB_OP_MASK            0x80    /* distinguishes scbs from icbs        */
        !           265: #define ICB_OP_OPEN_RBUF       0x80    /* open receive buffer                 */
        !           266: #define ICB_OP_RECV_CMD                0x81    /* receive command from initiator      */
        !           267: #define ICB_OP_RECV_DATA       0x82    /* receive data from initiator         */
        !           268: #define ICB_OP_RECV_SDATA      0x83    /* receive data with status from init. */
        !           269: #define ICB_OP_SEND_DATA       0x84    /* send data with status to initiator  */
        !           270: #define ICB_OP_SEND_STAT       0x86    /* send command status to initiator    */
        !           271:                                        /* 0x87 is reserved                    */
        !           272: #define ICB_OP_READ_INIT       0x88    /* read initialization bytes           */
        !           273: #define ICB_OP_READ_ID         0x89    /* read adapter's SCSI ID              */
        !           274: #define ICB_OP_SET_UMASK       0x8A    /* set unsolicited interrupt mask      */
        !           275: #define ICB_OP_GET_UMASK       0x8B    /* read unsolicited interrupt mask     */
        !           276: #define ICB_OP_GET_REVISION    0x8C    /* read firmware revision level        */
        !           277: #define ICB_OP_DIAGNOSTICS     0x8D    /* execute diagnostics                 */
        !           278: #define ICB_OP_SET_EPARMS      0x8E    /* set execution parameters            */
        !           279: #define ICB_OP_GET_EPARMS      0x8F    /* read execution parameters           */
        !           280: 
        !           281: typedef struct {
        !           282:     unchar op;
        !           283:     unchar IDlun;              /* Initiator SCSI ID/lun     */
        !           284:     unchar len[3];             /* command buffer length     */
        !           285:     unchar ptr[3];             /* command buffer address    */
        !           286:     unchar rsvd[7];            /* reserved                  */
        !           287:     volatile unchar vue;       /* vendor-unique error code  */
        !           288:     volatile unchar status;    /* returned (icmb) status    */
        !           289:     volatile unchar phase;     /* used by interrupt handler */
        !           290: } IcbRecvCmd;
        !           291: 
        !           292: typedef struct {
        !           293:     unchar op;
        !           294:     unchar IDlun;              /* Target SCSI ID/lun                  */
        !           295:     unchar stat;               /* (outgoing) completion status byte 1 */
        !           296:     unchar rsvd[12];           /* reserved                            */
        !           297:     volatile unchar vue;       /* vendor-unique error code            */
        !           298:     volatile unchar status;    /* returned (icmb) status              */
        !           299:     volatile unchar phase;     /* used by interrupt handler           */
        !           300: } IcbSendStat;
        !           301: 
        !           302: typedef struct {
        !           303:     unchar op;
        !           304:     volatile unchar primary;   /* primary revision level (returned)   */
        !           305:     volatile unchar secondary; /* secondary revision level (returned) */
        !           306:     unchar rsvd[12];           /* reserved                            */
        !           307:     volatile unchar vue;       /* vendor-unique error code            */
        !           308:     volatile unchar status;    /* returned (icmb) status              */
        !           309:     volatile unchar phase;     /* used by interrupt handler           */
        !           310: } IcbRevLvl;
        !           311: 
        !           312: typedef struct {       /* I'm totally guessing here */
        !           313:     unchar op;
        !           314:     volatile unchar mask[14];  /* mask bits                 */
        !           315: #if 0
        !           316:     unchar rsvd[12];           /* reserved                  */
        !           317: #endif
        !           318:     volatile unchar vue;       /* vendor-unique error code  */
        !           319:     volatile unchar status;    /* returned (icmb) status    */
        !           320:     volatile unchar phase;     /* used by interrupt handler */
        !           321: } IcbUnsMask;
        !           322: 
        !           323: typedef struct {
        !           324:     unchar op;
        !           325:     unchar type;               /* diagnostics type code (0-3) */
        !           326:     unchar len[3];             /* buffer length               */
        !           327:     unchar ptr[3];             /* buffer address              */
        !           328:     unchar rsvd[7];            /* reserved                    */
        !           329:     volatile unchar vue;       /* vendor-unique error code    */
        !           330:     volatile unchar status;    /* returned (icmb) status      */
        !           331:     volatile unchar phase;     /* used by interrupt handler   */
        !           332: } IcbDiag;
        !           333: 
        !           334: #define ICB_DIAG_POWERUP       0       /* Power-up diags only       */
        !           335: #define ICB_DIAG_WALKING       1       /* walking 1's pattern       */
        !           336: #define ICB_DIAG_DMA           2       /* DMA - system memory diags */
        !           337: #define ICB_DIAG_FULL          3       /* do both 1 & 2             */
        !           338: 
        !           339: typedef struct {
        !           340:     unchar op;
        !           341:     unchar rsvd1;              /* reserved                  */
        !           342:     unchar len[3];             /* parms buffer length       */
        !           343:     unchar ptr[3];             /* parms buffer address      */
        !           344:     unchar idx[2];             /* index (MSB-LSB)           */
        !           345:     unchar rsvd2[5];           /* reserved                  */
        !           346:     volatile unchar vue;       /* vendor-unique error code  */
        !           347:     volatile unchar status;    /* returned (icmb) status    */
        !           348:     volatile unchar phase;     /* used by interrupt handler */
        !           349: } IcbParms;
        !           350: 
        !           351: typedef struct {
        !           352:     unchar op;
        !           353:     unchar data[14];           /* format-specific data      */
        !           354:     volatile unchar vue;       /* vendor-unique error code  */
        !           355:     volatile unchar status;    /* returned (icmb) status    */
        !           356:     volatile unchar phase;     /* used by interrupt handler */
        !           357: } IcbAny;
        !           358: 
        !           359: typedef union {
        !           360:     unchar op;                 /* ICB opcode                     */
        !           361:     IcbRecvCmd recv_cmd;       /* format for receive command     */
        !           362:     IcbSendStat send_stat;     /* format for send status         */
        !           363:     IcbRevLvl rev_lvl;         /* format for get revision level  */
        !           364:     IcbDiag diag;              /* format for execute diagnostics */
        !           365:     IcbParms eparms;           /* format for get/set exec parms  */
        !           366:     IcbAny icb;                        /* generic format                 */
        !           367:     unchar data[18];
        !           368: } Icb;
        !           369: 
        !           370: #define WAITnexttimeout                200     /* 2 seconds */
        !           371: 
        !           372: typedef union {                        /* let's cheat... */
        !           373:     int i;
        !           374:     unchar u[sizeof (int)];    /* the sizeof(int) makes it more portable */
        !           375: } i_u;
        !           376: 
        !           377: #endif /* WD7000_DEFINES */
        !           378: 
        !           379: 
        !           380: #if (LINUX_VERSION_CODE >= 0x020100)
        !           381: 
        !           382: #define WD7000 {                                       \
        !           383:     proc_dir:          &proc_scsi_wd7000,              \
        !           384:     proc_info:         wd7000_proc_info,               \
        !           385:     name:              "Western Digital WD-7000",      \
        !           386:     detect:            wd7000_detect,                  \
        !           387:     command:           wd7000_command,                 \
        !           388:     queuecommand:      wd7000_queuecommand,            \
        !           389:     abort:             wd7000_abort,                   \
        !           390:     reset:             wd7000_reset,                   \
        !           391:     bios_param:                wd7000_biosparam,               \
        !           392:     can_queue:         WD7000_Q,                       \
        !           393:     this_id:           7,                              \
        !           394:     sg_tablesize:      WD7000_SG,                      \
        !           395:     cmd_per_lun:       1,                              \
        !           396:     unchecked_isa_dma: 1,                              \
        !           397:     use_clustering:    ENABLE_CLUSTERING,              \
        !           398:     use_new_eh_code:   0                               \
        !           399: }
        !           400: 
        !           401: #else /* Use old scsi code */
        !           402: 
        !           403: #define WD7000 {                                       \
        !           404:     proc_dir:          &proc_scsi_wd7000,              \
        !           405:     proc_info:         wd7000_proc_info,               \
        !           406:     name:              "Western Digital WD-7000",      \
        !           407:     detect:            wd7000_detect,                  \
        !           408:     command:           wd7000_command,                 \
        !           409:     queuecommand:      wd7000_queuecommand,            \
        !           410:     abort:             wd7000_abort,                   \
        !           411:     reset:             wd7000_reset,                   \
        !           412:     bios_param:                wd7000_biosparam,               \
        !           413:     can_queue:         WD7000_Q,                       \
        !           414:     this_id:           7,                              \
        !           415:     sg_tablesize:      WD7000_SG,                      \
        !           416:     cmd_per_lun:       1,                              \
        !           417:     unchecked_isa_dma: 1,                              \
        !           418:     use_clustering:    ENABLE_CLUSTERING,              \
        !           419: }
        !           420: 
        !           421: #endif /* LINUX_VERSION_CODE */
        !           422: 
        !           423: 
        !           424: extern struct proc_dir_entry proc_scsi_wd7000;
        !           425: 
        !           426: 
        !           427: #ifdef WD7000_DEFINES
        !           428: int  wd7000_diagnostics    (Adapter *, int);
        !           429: int  wd7000_init           (Adapter *);
        !           430: void wd7000_revision       (Adapter *);
        !           431: #endif /* WD7000_DEFINES */
        !           432: 
        !           433: void wd7000_setup          (char *, int *);
        !           434: int  make_code             (uint, uint);
        !           435: void wd7000_intr_handle    (int, void *, struct pt_regs *);
        !           436: void do_wd7000_intr_handle (int, void *, struct pt_regs *);
        !           437: int  wd7000_queuecommand   (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
        !           438: int  wd7000_command        (Scsi_Cmnd *);
        !           439: int  wd7000_set_info       (char *, int, struct Scsi_Host *);
        !           440: int  wd7000_proc_info      (char *, char **, off_t, int, int, int);
        !           441: int  wd7000_detect         (Scsi_Host_Template *);
        !           442: int  wd7000_abort          (Scsi_Cmnd *);
        !           443: int  wd7000_reset          (Scsi_Cmnd *, uint);
        !           444: int  wd7000_biosparam      (Disk *, kdev_t, int *);
        !           445: 
        !           446: #endif /* _WD7000_H */

unix.superglobalmegacorp.com

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