linux/drivers/block/smart1,2.h
<<
>>
Prefs
   1/*
   2 *    Disk Array driver for Compaq SMART2 Controllers
   3 *    Copyright 1998 Compaq Computer Corporation
   4 *
   5 *    This program is free software; you can redistribute it and/or modify
   6 *    it under the terms of the GNU General Public License as published by
   7 *    the Free Software Foundation; either version 2 of the License, or
   8 *    (at your option) any later version.
   9 *
  10 *    This program is distributed in the hope that it will be useful,
  11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  13 *    NON INFRINGEMENT.  See the GNU General Public License for more details.
  14 *
  15 *    You should have received a copy of the GNU General Public License
  16 *    along with this program; if not, write to the Free Software
  17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 *
  19 *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
  20 *
  21 *    If you want to make changes, improve or add functionality to this
  22 *    driver, you'll probably need the Compaq Array Controller Interface
  23 *    Specificiation (Document number ECG086/1198)
  24 */
  25
  26/*
  27 * This file contains the controller communication implementation for
  28 * Compaq SMART-1 and SMART-2 controllers.  To the best of my knowledge,
  29 * this should support:
  30 *
  31 *  PCI:
  32 *  SMART-2/P, SMART-2DH, SMART-2SL, SMART-221, SMART-3100ES, SMART-3200
  33 *  Integerated SMART Array Controller, SMART-4200, SMART-4250ES
  34 *
  35 *  EISA:
  36 *  SMART-2/E, SMART, IAES, IDA-2, IDA
  37 */
  38
  39/*
  40 * Memory mapped FIFO interface (SMART 42xx cards)
  41 */
  42static void smart4_submit_command(ctlr_info_t *h, cmdlist_t *c)
  43{
  44        writel(c->busaddr, h->vaddr + S42XX_REQUEST_PORT_OFFSET);
  45}
  46
  47/*  
  48 *  This card is the opposite of the other cards.  
  49 *   0 turns interrupts on... 
  50 *   0x08 turns them off... 
  51 */
  52static void smart4_intr_mask(ctlr_info_t *h, unsigned long val)
  53{
  54        if (val) 
  55        { /* Turn interrupts on */
  56                writel(0, h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
  57        } else /* Turn them off */
  58        {
  59                writel( S42XX_INTR_OFF, 
  60                        h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
  61        }
  62}
  63
  64/*
  65 *  For older cards FIFO Full = 0. 
  66 *  On this card 0 means there is room, anything else FIFO Full. 
  67 * 
  68 */ 
  69static unsigned long smart4_fifo_full(ctlr_info_t *h)
  70{
  71        
  72        return (!readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
  73}
  74
  75/* This type of controller returns -1 if the fifo is empty, 
  76 *    Not 0 like the others.
  77 *    And we need to let it know we read a value out 
  78 */ 
  79static unsigned long smart4_completed(ctlr_info_t *h)
  80{
  81        long register_value 
  82                = readl(h->vaddr + S42XX_REPLY_PORT_OFFSET);
  83
  84        /* Fifo is empty */
  85        if( register_value == 0xffffffff)
  86                return 0;       
  87
  88        /* Need to let it know we got the reply */
  89        /* We do this by writing a 0 to the port we just read from */
  90        writel(0, h->vaddr + S42XX_REPLY_PORT_OFFSET);
  91
  92        return ((unsigned long) register_value); 
  93}
  94
  95 /*
  96 *  This hardware returns interrupt pending at a different place and 
  97 *  it does not tell us if the fifo is empty, we will have check  
  98 *  that by getting a 0 back from the comamnd_completed call. 
  99 */
 100static unsigned long smart4_intr_pending(ctlr_info_t *h)
 101{
 102        unsigned long register_value  = 
 103                readl(h->vaddr + S42XX_INTR_STATUS);
 104
 105        if( register_value &  S42XX_INTR_PENDING) 
 106                return  FIFO_NOT_EMPTY; 
 107        return 0 ;
 108}
 109
 110static struct access_method smart4_access = {
 111        smart4_submit_command,
 112        smart4_intr_mask,
 113        smart4_fifo_full,
 114        smart4_intr_pending,
 115        smart4_completed,
 116};
 117
 118/*
 119 * Memory mapped FIFO interface (PCI SMART2 and SMART 3xxx cards)
 120 */
 121static void smart2_submit_command(ctlr_info_t *h, cmdlist_t *c)
 122{
 123        writel(c->busaddr, h->vaddr + COMMAND_FIFO);
 124}
 125
 126static void smart2_intr_mask(ctlr_info_t *h, unsigned long val)
 127{
 128        writel(val, h->vaddr + INTR_MASK);
 129}
 130
 131static unsigned long smart2_fifo_full(ctlr_info_t *h)
 132{
 133        return readl(h->vaddr + COMMAND_FIFO);
 134}
 135
 136static unsigned long smart2_completed(ctlr_info_t *h)
 137{
 138        return readl(h->vaddr + COMMAND_COMPLETE_FIFO);
 139}
 140
 141static unsigned long smart2_intr_pending(ctlr_info_t *h)
 142{
 143        return readl(h->vaddr + INTR_PENDING);
 144}
 145
 146static struct access_method smart2_access = {
 147        smart2_submit_command,
 148        smart2_intr_mask,
 149        smart2_fifo_full,
 150        smart2_intr_pending,
 151        smart2_completed,
 152};
 153
 154/*
 155 *  IO access for SMART-2/E cards
 156 */
 157static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c)
 158{
 159        outl(c->busaddr, h->io_mem_addr + COMMAND_FIFO);
 160}
 161
 162static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
 163{
 164        outl(val, h->io_mem_addr + INTR_MASK);
 165}
 166
 167static unsigned long smart2e_fifo_full(ctlr_info_t *h)
 168{
 169        return inl(h->io_mem_addr + COMMAND_FIFO);
 170}
 171
 172static unsigned long smart2e_completed(ctlr_info_t *h)
 173{
 174        return inl(h->io_mem_addr + COMMAND_COMPLETE_FIFO);
 175}
 176
 177static unsigned long smart2e_intr_pending(ctlr_info_t *h)
 178{
 179        return inl(h->io_mem_addr + INTR_PENDING);
 180}
 181
 182static struct access_method smart2e_access = {
 183        smart2e_submit_command,
 184        smart2e_intr_mask,
 185        smart2e_fifo_full,
 186        smart2e_intr_pending,
 187        smart2e_completed,
 188};
 189
 190/*
 191 *  IO access for older SMART-1 type cards
 192 */
 193#define SMART1_SYSTEM_MASK              0xC8E
 194#define SMART1_SYSTEM_DOORBELL          0xC8F
 195#define SMART1_LOCAL_MASK               0xC8C
 196#define SMART1_LOCAL_DOORBELL           0xC8D
 197#define SMART1_INTR_MASK                0xC89
 198#define SMART1_LISTADDR                 0xC90
 199#define SMART1_LISTLEN                  0xC94
 200#define SMART1_TAG                      0xC97
 201#define SMART1_COMPLETE_ADDR            0xC98
 202#define SMART1_LISTSTATUS               0xC9E
 203
 204#define CHANNEL_BUSY                    0x01
 205#define CHANNEL_CLEAR                   0x02
 206
 207static void smart1_submit_command(ctlr_info_t *h, cmdlist_t *c)
 208{
 209        /*
 210         * This __u16 is actually a bunch of control flags on SMART
 211         * and below.  We want them all to be zero.
 212         */
 213        c->hdr.size = 0;
 214
 215        outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
 216
 217        outl(c->busaddr, h->io_mem_addr + SMART1_LISTADDR);
 218        outw(c->size, h->io_mem_addr + SMART1_LISTLEN);
 219
 220        outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
 221}
 222
 223static void smart1_intr_mask(ctlr_info_t *h, unsigned long val)
 224{
 225        if (val == 1) {
 226                outb(0xFD, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
 227                outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
 228                outb(0x01, h->io_mem_addr + SMART1_INTR_MASK);
 229                outb(0x01, h->io_mem_addr + SMART1_SYSTEM_MASK);
 230        } else {
 231                outb(0, h->io_mem_addr + 0xC8E);
 232        }
 233}
 234
 235static unsigned long smart1_fifo_full(ctlr_info_t *h)
 236{
 237        unsigned char chan;
 238        chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
 239        return chan;
 240}
 241
 242static unsigned long smart1_completed(ctlr_info_t *h)
 243{
 244        unsigned char status;
 245        unsigned long cmd;
 246
 247        if (inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
 248                outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
 249
 250                cmd = inl(h->io_mem_addr + SMART1_COMPLETE_ADDR);
 251                status = inb(h->io_mem_addr + SMART1_LISTSTATUS);
 252
 253                outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
 254
 255                /*
 256                 * this is x86 (actually compaq x86) only, so it's ok
 257                 */
 258                if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
 259        } else {
 260                cmd = 0;
 261        }
 262        return cmd;
 263}
 264
 265static unsigned long smart1_intr_pending(ctlr_info_t *h)
 266{
 267        unsigned char chan;
 268        chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
 269        return chan;
 270}
 271
 272static struct access_method smart1_access = {
 273        smart1_submit_command,
 274        smart1_intr_mask,
 275        smart1_fifo_full,
 276        smart1_intr_pending,
 277        smart1_completed,
 278};
 279