linux/drivers/block/cciss.h
<<
>>
Prefs
   1#ifndef CCISS_H
   2#define CCISS_H
   3
   4#include <linux/genhd.h>
   5#include <linux/mutex.h>
   6
   7#include "cciss_cmd.h"
   8
   9
  10#define NWD_SHIFT       4
  11#define MAX_PART        (1 << NWD_SHIFT)
  12
  13#define IO_OK           0
  14#define IO_ERROR        1
  15#define IO_NEEDS_RETRY  3
  16
  17#define VENDOR_LEN      8
  18#define MODEL_LEN       16
  19#define REV_LEN         4
  20
  21struct ctlr_info;
  22typedef struct ctlr_info ctlr_info_t;
  23
  24struct access_method {
  25        void (*submit_command)(ctlr_info_t *h, CommandList_struct *c);
  26        void (*set_intr_mask)(ctlr_info_t *h, unsigned long val);
  27        unsigned long (*fifo_full)(ctlr_info_t *h);
  28        bool (*intr_pending)(ctlr_info_t *h);
  29        unsigned long (*command_completed)(ctlr_info_t *h);
  30};
  31typedef struct _drive_info_struct
  32{
  33        unsigned char LunID[8];
  34        int     usage_count;
  35        struct request_queue *queue;
  36        sector_t nr_blocks;
  37        int     block_size;
  38        int     heads;
  39        int     sectors;
  40        int     cylinders;
  41        int     raid_level; /* set to -1 to indicate that
  42                             * the drive is not in use/configured
  43                             */
  44        int     busy_configuring; /* This is set when a drive is being removed
  45                                   * to prevent it from being opened or it's
  46                                   * queue from being started.
  47                                   */
  48        struct  device dev;
  49        __u8 serial_no[16]; /* from inquiry page 0x83,
  50                             * not necc. null terminated.
  51                             */
  52        char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */
  53        char model[MODEL_LEN + 1];   /* SCSI model string */
  54        char rev[REV_LEN + 1];       /* SCSI revision string */
  55        char device_initialized;     /* indicates whether dev is initialized */
  56} drive_info_struct;
  57
  58struct ctlr_info
  59{
  60        int     ctlr;
  61        char    devname[8];
  62        char    *product_name;
  63        char    firm_ver[4]; /* Firmware version */
  64        struct pci_dev *pdev;
  65        __u32   board_id;
  66        void __iomem *vaddr;
  67        unsigned long paddr;
  68        int     nr_cmds; /* Number of commands allowed on this controller */
  69        CfgTable_struct __iomem *cfgtable;
  70        int     interrupts_enabled;
  71        int     major;
  72        int     max_commands;
  73        int     commands_outstanding;
  74        int     max_outstanding; /* Debug */ 
  75        int     num_luns;
  76        int     highest_lun;
  77        int     usage_count;  /* number of opens all all minor devices */
  78        /* Need space for temp sg list
  79         * number of scatter/gathers supported
  80         * number of scatter/gathers in chained block
  81         */
  82        struct  scatterlist **scatter_list;
  83        int     maxsgentries;
  84        int     chainsize;
  85        int     max_cmd_sgentries;
  86        SGDescriptor_struct **cmd_sg_list;
  87
  88#       define PERF_MODE_INT    0
  89#       define DOORBELL_INT     1
  90#       define SIMPLE_MODE_INT  2
  91#       define MEMQ_MODE_INT    3
  92        unsigned int intr[4];
  93        unsigned int msix_vector;
  94        unsigned int msi_vector;
  95        int     intr_mode;
  96        int     cciss_max_sectors;
  97        BYTE    cciss_read;
  98        BYTE    cciss_write;
  99        BYTE    cciss_read_capacity;
 100
 101        /* information about each logical volume */
 102        drive_info_struct *drv[CISS_MAX_LUN];
 103
 104        struct access_method access;
 105
 106        /* queue and queue Info */ 
 107        struct list_head reqQ;
 108        struct list_head cmpQ;
 109        unsigned int Qdepth;
 110        unsigned int maxQsinceinit;
 111        unsigned int maxSG;
 112        spinlock_t lock;
 113
 114        /* pointers to command and error info pool */
 115        CommandList_struct      *cmd_pool;
 116        dma_addr_t              cmd_pool_dhandle; 
 117        ErrorInfo_struct        *errinfo_pool;
 118        dma_addr_t              errinfo_pool_dhandle; 
 119        unsigned long           *cmd_pool_bits;
 120        int                     nr_allocs;
 121        int                     nr_frees; 
 122        int                     busy_configuring;
 123        int                     busy_initializing;
 124        int                     busy_scanning;
 125        struct mutex            busy_shutting_down;
 126
 127        /* This element holds the zero based queue number of the last
 128         * queue to be started.  It is used for fairness.
 129        */
 130        int                     next_to_run;
 131
 132        /* Disk structures we need to pass back */
 133        struct gendisk   *gendisk[CISS_MAX_LUN];
 134#ifdef CONFIG_CISS_SCSI_TAPE
 135        struct cciss_scsi_adapter_data_t *scsi_ctlr;
 136#endif
 137        unsigned char alive;
 138        struct list_head scan_list;
 139        struct completion scan_wait;
 140        struct device dev;
 141        /*
 142         * Performant mode tables.
 143         */
 144        u32 trans_support;
 145        u32 trans_offset;
 146        struct TransTable_struct *transtable;
 147        unsigned long transMethod;
 148
 149        /*
 150         * Performant mode completion buffer
 151         */
 152        u64 *reply_pool;
 153        dma_addr_t reply_pool_dhandle;
 154        u64 *reply_pool_head;
 155        size_t reply_pool_size;
 156        unsigned char reply_pool_wraparound;
 157        u32 *blockFetchTable;
 158};
 159
 160/*  Defining the diffent access_methods
 161 *
 162 * Memory mapped FIFO interface (SMART 53xx cards)
 163 */
 164#define SA5_DOORBELL    0x20
 165#define SA5_REQUEST_PORT_OFFSET 0x40
 166#define SA5_REPLY_INTR_MASK_OFFSET      0x34
 167#define SA5_REPLY_PORT_OFFSET           0x44
 168#define SA5_INTR_STATUS         0x30
 169#define SA5_SCRATCHPAD_OFFSET   0xB0
 170
 171#define SA5_CTCFG_OFFSET        0xB4
 172#define SA5_CTMEM_OFFSET        0xB8
 173
 174#define SA5_INTR_OFF            0x08
 175#define SA5B_INTR_OFF           0x04
 176#define SA5_INTR_PENDING        0x08
 177#define SA5B_INTR_PENDING       0x04
 178#define FIFO_EMPTY              0xffffffff      
 179#define CCISS_FIRMWARE_READY    0xffff0000 /* value in scratchpad register */
 180/* Perf. mode flags */
 181#define SA5_PERF_INTR_PENDING   0x04
 182#define SA5_PERF_INTR_OFF       0x05
 183#define SA5_OUTDB_STATUS_PERF_BIT       0x01
 184#define SA5_OUTDB_CLEAR_PERF_BIT        0x01
 185#define SA5_OUTDB_CLEAR         0xA0
 186#define SA5_OUTDB_CLEAR_PERF_BIT        0x01
 187#define SA5_OUTDB_STATUS        0x9C
 188
 189
 190#define  CISS_ERROR_BIT         0x02
 191
 192#define CCISS_INTR_ON   1 
 193#define CCISS_INTR_OFF  0
 194
 195
 196/* CCISS_BOARD_READY_WAIT_SECS is how long to wait for a board
 197 * to become ready, in seconds, before giving up on it.
 198 * CCISS_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait
 199 * between polling the board to see if it is ready, in
 200 * milliseconds.  CCISS_BOARD_READY_ITERATIONS is derived
 201 * the above.
 202 */
 203#define CCISS_BOARD_READY_WAIT_SECS (120)
 204#define CCISS_BOARD_NOT_READY_WAIT_SECS (100)
 205#define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100)
 206#define CCISS_BOARD_READY_ITERATIONS \
 207        ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \
 208                CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
 209#define CCISS_BOARD_NOT_READY_ITERATIONS \
 210        ((CCISS_BOARD_NOT_READY_WAIT_SECS * 1000) / \
 211                CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
 212#define CCISS_POST_RESET_PAUSE_MSECS (3000)
 213#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (4000)
 214#define CCISS_POST_RESET_NOOP_RETRIES (12)
 215#define CCISS_POST_RESET_NOOP_TIMEOUT_MSECS (10000)
 216
 217/* 
 218        Send the command to the hardware 
 219*/
 220static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) 
 221{
 222#ifdef CCISS_DEBUG
 223        printk(KERN_WARNING "cciss%d: Sending %08x - down to controller\n",
 224                        h->ctlr, c->busaddr);
 225#endif /* CCISS_DEBUG */
 226         writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
 227        readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
 228         h->commands_outstanding++;
 229         if ( h->commands_outstanding > h->max_outstanding)
 230                h->max_outstanding = h->commands_outstanding;
 231}
 232
 233/*  
 234 *  This card is the opposite of the other cards.  
 235 *   0 turns interrupts on... 
 236 *   0x08 turns them off... 
 237 */
 238static void SA5_intr_mask(ctlr_info_t *h, unsigned long val)
 239{
 240        if (val) 
 241        { /* Turn interrupts on */
 242                h->interrupts_enabled = 1;
 243                writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 244                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 245        } else /* Turn them off */
 246        {
 247                h->interrupts_enabled = 0;
 248                writel( SA5_INTR_OFF, 
 249                        h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 250                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 251        }
 252}
 253/*
 254 *  This card is the opposite of the other cards.
 255 *   0 turns interrupts on...
 256 *   0x04 turns them off...
 257 */
 258static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val)
 259{
 260        if (val)
 261        { /* Turn interrupts on */
 262                h->interrupts_enabled = 1;
 263                writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 264                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 265        } else /* Turn them off */
 266        {
 267                h->interrupts_enabled = 0;
 268                writel( SA5B_INTR_OFF,
 269                        h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 270                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 271        }
 272}
 273
 274/* Performant mode intr_mask */
 275static void SA5_performant_intr_mask(ctlr_info_t *h, unsigned long val)
 276{
 277        if (val) { /* turn on interrupts */
 278                h->interrupts_enabled = 1;
 279                writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 280                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 281        } else {
 282                h->interrupts_enabled = 0;
 283                writel(SA5_PERF_INTR_OFF,
 284                                h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 285                (void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
 286        }
 287}
 288
 289/*
 290 *  Returns true if fifo is full.  
 291 * 
 292 */ 
 293static unsigned long SA5_fifo_full(ctlr_info_t *h)
 294{
 295        if( h->commands_outstanding >= h->max_commands)
 296                return(1);
 297        else 
 298                return(0);
 299
 300}
 301/* 
 302 *   returns value read from hardware. 
 303 *     returns FIFO_EMPTY if there is nothing to read 
 304 */ 
 305static unsigned long SA5_completed(ctlr_info_t *h)
 306{
 307        unsigned long register_value 
 308                = readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
 309        if(register_value != FIFO_EMPTY)
 310        {
 311                h->commands_outstanding--;
 312#ifdef CCISS_DEBUG
 313                printk("cciss:  Read %lx back from board\n", register_value);
 314#endif /* CCISS_DEBUG */ 
 315        } 
 316#ifdef CCISS_DEBUG
 317        else
 318        {
 319                printk("cciss:  FIFO Empty read\n");
 320        }
 321#endif 
 322        return ( register_value); 
 323
 324}
 325
 326/* Performant mode command completed */
 327static unsigned long SA5_performant_completed(ctlr_info_t *h)
 328{
 329        unsigned long register_value = FIFO_EMPTY;
 330
 331        /* flush the controller write of the reply queue by reading
 332         * outbound doorbell status register.
 333         */
 334        register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
 335        /* msi auto clears the interrupt pending bit. */
 336        if (!(h->msi_vector || h->msix_vector)) {
 337                writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
 338                /* Do a read in order to flush the write to the controller
 339                 * (as per spec.)
 340                 */
 341                register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
 342        }
 343
 344        if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
 345                register_value = *(h->reply_pool_head);
 346                (h->reply_pool_head)++;
 347                h->commands_outstanding--;
 348        } else {
 349                register_value = FIFO_EMPTY;
 350        }
 351        /* Check for wraparound */
 352        if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
 353                h->reply_pool_head = h->reply_pool;
 354                h->reply_pool_wraparound ^= 1;
 355        }
 356
 357        return register_value;
 358}
 359/*
 360 *      Returns true if an interrupt is pending.. 
 361 */
 362static bool SA5_intr_pending(ctlr_info_t *h)
 363{
 364        unsigned long register_value  = 
 365                readl(h->vaddr + SA5_INTR_STATUS);
 366#ifdef CCISS_DEBUG
 367        printk("cciss: intr_pending %lx\n", register_value);
 368#endif  /* CCISS_DEBUG */
 369        if( register_value &  SA5_INTR_PENDING) 
 370                return  1;      
 371        return 0 ;
 372}
 373
 374/*
 375 *      Returns true if an interrupt is pending..
 376 */
 377static bool SA5B_intr_pending(ctlr_info_t *h)
 378{
 379        unsigned long register_value  =
 380                readl(h->vaddr + SA5_INTR_STATUS);
 381#ifdef CCISS_DEBUG
 382        printk("cciss: intr_pending %lx\n", register_value);
 383#endif  /* CCISS_DEBUG */
 384        if( register_value &  SA5B_INTR_PENDING)
 385                return  1;
 386        return 0 ;
 387}
 388
 389static bool SA5_performant_intr_pending(ctlr_info_t *h)
 390{
 391        unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS);
 392
 393        if (!register_value)
 394                return false;
 395
 396        if (h->msi_vector || h->msix_vector)
 397                return true;
 398
 399        /* Read outbound doorbell to flush */
 400        register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
 401        return register_value & SA5_OUTDB_STATUS_PERF_BIT;
 402}
 403
 404static struct access_method SA5_access = {
 405        SA5_submit_command,
 406        SA5_intr_mask,
 407        SA5_fifo_full,
 408        SA5_intr_pending,
 409        SA5_completed,
 410};
 411
 412static struct access_method SA5B_access = {
 413        SA5_submit_command,
 414        SA5B_intr_mask,
 415        SA5_fifo_full,
 416        SA5B_intr_pending,
 417        SA5_completed,
 418};
 419
 420static struct access_method SA5_performant_access = {
 421        SA5_submit_command,
 422        SA5_performant_intr_mask,
 423        SA5_fifo_full,
 424        SA5_performant_intr_pending,
 425        SA5_performant_completed,
 426};
 427
 428struct board_type {
 429        __u32   board_id;
 430        char    *product_name;
 431        struct access_method *access;
 432        int nr_cmds; /* Max cmds this kind of ctlr can handle. */
 433};
 434
 435#endif /* CCISS_H */
 436