linux/drivers/scsi/aic94xx/aic94xx_hwi.h
<<
>>
Prefs
   1/*
   2 * Aic94xx SAS/SATA driver hardware interface header file.
   3 *
   4 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
   5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
   6 *
   7 * This file is licensed under GPLv2.
   8 *
   9 * This file is part of the aic94xx driver.
  10 *
  11 * The aic94xx driver is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; version 2 of the
  14 * License.
  15 *
  16 * The aic94xx driver is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 * General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with the aic94xx driver; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  24 *
  25 */
  26
  27#ifndef _AIC94XX_HWI_H_
  28#define _AIC94XX_HWI_H_
  29
  30#include <linux/interrupt.h>
  31#include <linux/pci.h>
  32#include <linux/dma-mapping.h>
  33
  34#include <scsi/libsas.h>
  35
  36#include "aic94xx.h"
  37#include "aic94xx_sas.h"
  38
  39/* Define ASD_MAX_PHYS to the maximum phys ever. Currently 8. */
  40#define ASD_MAX_PHYS       8
  41#define ASD_PCBA_SN_SIZE   12
  42
  43struct asd_ha_addrspace {
  44        void __iomem  *addr;
  45        unsigned long  start;       /* pci resource start */
  46        unsigned long  len;         /* pci resource len */
  47        unsigned long  flags;       /* pci resource flags */
  48
  49        /* addresses internal to the host adapter */
  50        u32 swa_base; /* mmspace 1 (MBAR1) uses this only */
  51        u32 swb_base;
  52        u32 swc_base;
  53};
  54
  55struct bios_struct {
  56        int    present;
  57        u8     maj;
  58        u8     min;
  59        u32    bld;
  60};
  61
  62struct unit_element_struct {
  63        u16    num;
  64        u16    size;
  65        void   *area;
  66};
  67
  68struct flash_struct {
  69        u32    bar;
  70        int    present;
  71        int    wide;
  72        u8     manuf;
  73        u8     dev_id;
  74        u8     sec_prot;
  75        u8     method;
  76
  77        u32    dir_offs;
  78};
  79
  80struct asd_phy_desc {
  81        /* From CTRL-A settings, then set to what is appropriate */
  82        u8     sas_addr[SAS_ADDR_SIZE];
  83        u8     max_sas_lrate;
  84        u8     min_sas_lrate;
  85        u8     max_sata_lrate;
  86        u8     min_sata_lrate;
  87        u8     flags;
  88#define ASD_CRC_DIS  1
  89#define ASD_SATA_SPINUP_HOLD 2
  90
  91        u8     phy_control_0; /* mode 5 reg 0x160 */
  92        u8     phy_control_1; /* mode 5 reg 0x161 */
  93        u8     phy_control_2; /* mode 5 reg 0x162 */
  94        u8     phy_control_3; /* mode 5 reg 0x163 */
  95};
  96
  97struct asd_dma_tok {
  98        void *vaddr;
  99        dma_addr_t dma_handle;
 100        size_t size;
 101};
 102
 103struct hw_profile {
 104        struct bios_struct bios;
 105        struct unit_element_struct ue;
 106        struct flash_struct flash;
 107
 108        u8     sas_addr[SAS_ADDR_SIZE];
 109        char   pcba_sn[ASD_PCBA_SN_SIZE+1];
 110
 111        u8     enabled_phys;      /* mask of enabled phys */
 112        struct asd_phy_desc phy_desc[ASD_MAX_PHYS];
 113        u32    max_scbs;          /* absolute sequencer scb queue size */
 114        struct asd_dma_tok *scb_ext;
 115        u32    max_ddbs;
 116        struct asd_dma_tok *ddb_ext;
 117
 118        spinlock_t ddb_lock;
 119        void  *ddb_bitmap;
 120
 121        int    num_phys;          /* ENABLEABLE */
 122        int    max_phys;          /* REPORTED + ENABLEABLE */
 123
 124        unsigned addr_range;      /* max # of addrs; max # of possible ports */
 125        unsigned port_name_base;
 126        unsigned dev_name_base;
 127        unsigned sata_name_base;
 128};
 129
 130struct asd_ascb {
 131        struct list_head list;
 132        struct asd_ha_struct *ha;
 133
 134        struct scb *scb;          /* equals dma_scb->vaddr */
 135        struct asd_dma_tok dma_scb;
 136        struct asd_dma_tok *sg_arr;
 137
 138        void (*tasklet_complete)(struct asd_ascb *, struct done_list_struct *);
 139        u8     uldd_timer:1;
 140
 141        /* internally generated command */
 142        struct timer_list timer;
 143        struct completion *completion;
 144        u8        tag_valid:1;
 145        __be16    tag;            /* error recovery only */
 146
 147        /* If this is an Empty SCB, index of first edb in seq->edb_arr. */
 148        int    edb_index;
 149
 150        /* Used by the timer timeout function. */
 151        int    tc_index;
 152
 153        void   *uldd_task;
 154};
 155
 156#define ASD_DL_SIZE_BITS   0x8
 157#define ASD_DL_SIZE        (1<<(2+ASD_DL_SIZE_BITS))
 158#define ASD_DEF_DL_TOGGLE  0x01
 159
 160struct asd_seq_data {
 161        spinlock_t pend_q_lock;
 162        u16    scbpro;
 163        int    pending;
 164        struct list_head pend_q;
 165        int    can_queue;         /* per adapter */
 166        struct asd_dma_tok next_scb; /* next scb to be delivered to CSEQ */
 167
 168        spinlock_t tc_index_lock;
 169        void **tc_index_array;
 170        void *tc_index_bitmap;
 171        int   tc_index_bitmap_bits;
 172
 173        struct tasklet_struct dl_tasklet;
 174        struct done_list_struct *dl; /* array of done list entries, equals */
 175        struct asd_dma_tok *actual_dl; /* actual_dl->vaddr */
 176        int    dl_toggle;
 177        int    dl_next;
 178
 179        int    num_edbs;
 180        struct asd_dma_tok **edb_arr;
 181        int    num_escbs;
 182        struct asd_ascb **escb_arr; /* array of pointers to escbs */
 183};
 184
 185/* This is an internal port structure. These are used to get accurate
 186 * phy_mask for updating DDB 0.
 187 */
 188struct asd_port {
 189        u8  sas_addr[SAS_ADDR_SIZE];
 190        u8  attached_sas_addr[SAS_ADDR_SIZE];
 191        u32 phy_mask;
 192        int num_phys;
 193};
 194
 195/* This is the Host Adapter structure.  It describes the hardware
 196 * SAS adapter.
 197 */
 198struct asd_ha_struct {
 199        struct pci_dev   *pcidev;
 200        const char       *name;
 201
 202        struct sas_ha_struct sas_ha;
 203
 204        u8                revision_id;
 205
 206        int               iospace;
 207        spinlock_t        iolock;
 208        struct asd_ha_addrspace io_handle[2];
 209
 210        struct hw_profile hw_prof;
 211
 212        struct asd_phy    phys[ASD_MAX_PHYS];
 213        spinlock_t        asd_ports_lock;
 214        struct asd_port   asd_ports[ASD_MAX_PHYS];
 215        struct asd_sas_port   ports[ASD_MAX_PHYS];
 216
 217        struct dma_pool  *scb_pool;
 218
 219        struct asd_seq_data  seq; /* sequencer related */
 220        u32    bios_status;
 221        const struct firmware *bios_image;
 222};
 223
 224/* ---------- Common macros ---------- */
 225
 226#define ASD_BUSADDR_LO(__dma_handle) ((u32)(__dma_handle))
 227#define ASD_BUSADDR_HI(__dma_handle) (((sizeof(dma_addr_t))==8)     \
 228                                    ? ((u32)((__dma_handle) >> 32)) \
 229                                    : ((u32)0))
 230
 231#define dev_to_asd_ha(__dev)  pci_get_drvdata(to_pci_dev(__dev))
 232#define SCB_SITE_VALID(__site_no) (((__site_no) & 0xF0FF) != 0x00FF   \
 233                                 && ((__site_no) & 0xF0FF) > 0x001F)
 234/* For each bit set in __lseq_mask, set __lseq to equal the bit
 235 * position of the set bit and execute the statement following.
 236 * __mc is the temporary mask, used as a mask "counter".
 237 */
 238#define for_each_sequencer(__lseq_mask, __mc, __lseq)                        \
 239        for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
 240                if (((__mc) & 1))
 241#define for_each_phy(__lseq_mask, __mc, __lseq)                              \
 242        for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
 243                if (((__mc) & 1))
 244
 245#define PHY_ENABLED(_HA, _I) ((_HA)->hw_prof.enabled_phys & (1<<(_I)))
 246
 247/* ---------- DMA allocs ---------- */
 248
 249static inline struct asd_dma_tok *asd_dmatok_alloc(gfp_t flags)
 250{
 251        return kmem_cache_alloc(asd_dma_token_cache, flags);
 252}
 253
 254static inline void asd_dmatok_free(struct asd_dma_tok *token)
 255{
 256        kmem_cache_free(asd_dma_token_cache, token);
 257}
 258
 259static inline struct asd_dma_tok *asd_alloc_coherent(struct asd_ha_struct *
 260                                                     asd_ha, size_t size,
 261                                                     gfp_t flags)
 262{
 263        struct asd_dma_tok *token = asd_dmatok_alloc(flags);
 264        if (token) {
 265                token->size = size;
 266                token->vaddr = dma_alloc_coherent(&asd_ha->pcidev->dev,
 267                                                  token->size,
 268                                                  &token->dma_handle,
 269                                                  flags);
 270                if (!token->vaddr) {
 271                        asd_dmatok_free(token);
 272                        token = NULL;
 273                }
 274        }
 275        return token;
 276}
 277
 278static inline void asd_free_coherent(struct asd_ha_struct *asd_ha,
 279                                     struct asd_dma_tok *token)
 280{
 281        if (token) {
 282                dma_free_coherent(&asd_ha->pcidev->dev, token->size,
 283                                  token->vaddr, token->dma_handle);
 284                asd_dmatok_free(token);
 285        }
 286}
 287
 288static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
 289                                 struct asd_ascb *ascb)
 290{
 291        INIT_LIST_HEAD(&ascb->list);
 292        ascb->scb = ascb->dma_scb.vaddr;
 293        ascb->ha = asd_ha;
 294        ascb->timer.function = NULL;
 295        init_timer(&ascb->timer);
 296        ascb->tc_index = -1;
 297}
 298
 299/* Must be called with the tc_index_lock held!
 300 */
 301static inline void asd_tc_index_release(struct asd_seq_data *seq, int index)
 302{
 303        seq->tc_index_array[index] = NULL;
 304        clear_bit(index, seq->tc_index_bitmap);
 305}
 306
 307/* Must be called with the tc_index_lock held!
 308 */
 309static inline int asd_tc_index_get(struct asd_seq_data *seq, void *ptr)
 310{
 311        int index;
 312
 313        index = find_first_zero_bit(seq->tc_index_bitmap,
 314                                    seq->tc_index_bitmap_bits);
 315        if (index == seq->tc_index_bitmap_bits)
 316                return -1;
 317
 318        seq->tc_index_array[index] = ptr;
 319        set_bit(index, seq->tc_index_bitmap);
 320
 321        return index;
 322}
 323
 324/* Must be called with the tc_index_lock held!
 325 */
 326static inline void *asd_tc_index_find(struct asd_seq_data *seq, int index)
 327{
 328        return seq->tc_index_array[index];
 329}
 330
 331/**
 332 * asd_ascb_free -- free a single aSCB after is has completed
 333 * @ascb: pointer to the aSCB of interest
 334 *
 335 * This frees an aSCB after it has been executed/completed by
 336 * the sequencer.
 337 */
 338static inline void asd_ascb_free(struct asd_ascb *ascb)
 339{
 340        if (ascb) {
 341                struct asd_ha_struct *asd_ha = ascb->ha;
 342                unsigned long flags;
 343
 344                BUG_ON(!list_empty(&ascb->list));
 345                spin_lock_irqsave(&ascb->ha->seq.tc_index_lock, flags);
 346                asd_tc_index_release(&ascb->ha->seq, ascb->tc_index);
 347                spin_unlock_irqrestore(&ascb->ha->seq.tc_index_lock, flags);
 348                dma_pool_free(asd_ha->scb_pool, ascb->dma_scb.vaddr,
 349                              ascb->dma_scb.dma_handle);
 350                kmem_cache_free(asd_ascb_cache, ascb);
 351        }
 352}
 353
 354/**
 355 * asd_ascb_list_free -- free a list of ascbs
 356 * @ascb_list: a list of ascbs
 357 *
 358 * This function will free a list of ascbs allocated by asd_ascb_alloc_list.
 359 * It is used when say the scb queueing function returned QUEUE_FULL,
 360 * and we do not need the ascbs any more.
 361 */
 362static inline void asd_ascb_free_list(struct asd_ascb *ascb_list)
 363{
 364        LIST_HEAD(list);
 365        struct list_head *n, *pos;
 366
 367        __list_add(&list, ascb_list->list.prev, &ascb_list->list);
 368        list_for_each_safe(pos, n, &list) {
 369                list_del_init(pos);
 370                asd_ascb_free(list_entry(pos, struct asd_ascb, list));
 371        }
 372}
 373
 374/* ---------- Function declarations ---------- */
 375
 376int  asd_init_hw(struct asd_ha_struct *asd_ha);
 377irqreturn_t asd_hw_isr(int irq, void *dev_id);
 378
 379
 380struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
 381                                     *asd_ha, int *num,
 382                                     gfp_t gfp_mask);
 383
 384int  asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
 385                        int num);
 386int  asd_post_escb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
 387                        int num);
 388
 389int  asd_init_post_escbs(struct asd_ha_struct *asd_ha);
 390void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
 391void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
 392void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
 393int  asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
 394
 395void asd_ascb_timedout(unsigned long data);
 396int  asd_chip_hardrst(struct asd_ha_struct *asd_ha);
 397
 398#endif
 399