linux/drivers/scsi/aic94xx/aic94xx_sds.c
<<
>>
Prefs
   1/*
   2 * Aic94xx SAS/SATA driver access to shared data structures and memory
   3 * maps.
   4 *
   5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
   6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
   7 *
   8 * This file is licensed under GPLv2.
   9 *
  10 * This file is part of the aic94xx driver.
  11 *
  12 * The aic94xx driver is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation; version 2 of the
  15 * License.
  16 *
  17 * The aic94xx driver is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20 * General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with the aic94xx driver; if not, write to the Free Software
  24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  25 *
  26 */
  27
  28#include <linux/pci.h>
  29#include <linux/delay.h>
  30
  31#include "aic94xx.h"
  32#include "aic94xx_reg.h"
  33#include "aic94xx_sds.h"
  34
  35/* ---------- OCM stuff ---------- */
  36
  37struct asd_ocm_dir_ent {
  38        u8 type;
  39        u8 offs[3];
  40        u8 _r1;
  41        u8 size[3];
  42} __attribute__ ((packed));
  43
  44struct asd_ocm_dir {
  45        char sig[2];
  46        u8   _r1[2];
  47        u8   major;          /* 0 */
  48        u8   minor;          /* 0 */
  49        u8   _r2;
  50        u8   num_de;
  51        struct asd_ocm_dir_ent entry[15];
  52} __attribute__ ((packed));
  53
  54#define OCM_DE_OCM_DIR                  0x00
  55#define OCM_DE_WIN_DRVR                 0x01
  56#define OCM_DE_BIOS_CHIM                0x02
  57#define OCM_DE_RAID_ENGN                0x03
  58#define OCM_DE_BIOS_INTL                0x04
  59#define OCM_DE_BIOS_CHIM_OSM            0x05
  60#define OCM_DE_BIOS_CHIM_DYNAMIC        0x06
  61#define OCM_DE_ADDC2C_RES0              0x07
  62#define OCM_DE_ADDC2C_RES1              0x08
  63#define OCM_DE_ADDC2C_RES2              0x09
  64#define OCM_DE_ADDC2C_RES3              0x0A
  65
  66#define OCM_INIT_DIR_ENTRIES    5
  67/***************************************************************************
  68*  OCM directory default
  69***************************************************************************/
  70static struct asd_ocm_dir OCMDirInit =
  71{
  72        .sig = {0x4D, 0x4F},    /* signature */
  73        .num_de = OCM_INIT_DIR_ENTRIES, /* no. of directory entries */
  74};
  75
  76/***************************************************************************
  77*  OCM directory Entries default
  78***************************************************************************/
  79static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] =
  80{
  81        {
  82                .type = (OCM_DE_ADDC2C_RES0),   /* Entry type  */
  83                .offs = {128},                  /* Offset */
  84                .size = {0, 4},                 /* size */
  85        },
  86        {
  87                .type = (OCM_DE_ADDC2C_RES1),   /* Entry type  */
  88                .offs = {128, 4},               /* Offset */
  89                .size = {0, 4},                 /* size */
  90        },
  91        {
  92                .type = (OCM_DE_ADDC2C_RES2),   /* Entry type  */
  93                .offs = {128, 8},               /* Offset */
  94                .size = {0, 4},                 /* size */
  95        },
  96        {
  97                .type = (OCM_DE_ADDC2C_RES3),   /* Entry type  */
  98                .offs = {128, 12},              /* Offset */
  99                .size = {0, 4},                 /* size */
 100        },
 101        {
 102                .type = (OCM_DE_WIN_DRVR),      /* Entry type  */
 103                .offs = {128, 16},              /* Offset */
 104                .size = {128, 235, 1},          /* size */
 105        },
 106};
 107
 108struct asd_bios_chim_struct {
 109        char sig[4];
 110        u8   major;          /* 1 */
 111        u8   minor;          /* 0 */
 112        u8   bios_major;
 113        u8   bios_minor;
 114        __le32  bios_build;
 115        u8   flags;
 116        u8   pci_slot;
 117        __le16  ue_num;
 118        __le16  ue_size;
 119        u8  _r[14];
 120        /* The unit element array is right here.
 121         */
 122} __attribute__ ((packed));
 123
 124/**
 125 * asd_read_ocm_seg - read an on chip memory (OCM) segment
 126 * @asd_ha: pointer to the host adapter structure
 127 * @buffer: where to write the read data
 128 * @offs: offset into OCM where to read from
 129 * @size: how many bytes to read
 130 *
 131 * Return the number of bytes not read. Return 0 on success.
 132 */
 133static int asd_read_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer,
 134                            u32 offs, int size)
 135{
 136        u8 *p = buffer;
 137        if (unlikely(asd_ha->iospace))
 138                asd_read_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size);
 139        else {
 140                for ( ; size > 0; size--, offs++, p++)
 141                        *p = asd_read_ocm_byte(asd_ha, offs);
 142        }
 143        return size;
 144}
 145
 146static int asd_read_ocm_dir(struct asd_ha_struct *asd_ha,
 147                            struct asd_ocm_dir *dir, u32 offs)
 148{
 149        int err = asd_read_ocm_seg(asd_ha, dir, offs, sizeof(*dir));
 150        if (err) {
 151                ASD_DPRINTK("couldn't read ocm segment\n");
 152                return err;
 153        }
 154
 155        if (dir->sig[0] != 'M' || dir->sig[1] != 'O') {
 156                ASD_DPRINTK("no valid dir signature(%c%c) at start of OCM\n",
 157                            dir->sig[0], dir->sig[1]);
 158                return -ENOENT;
 159        }
 160        if (dir->major != 0) {
 161                asd_printk("unsupported major version of ocm dir:0x%x\n",
 162                           dir->major);
 163                return -ENOENT;
 164        }
 165        dir->num_de &= 0xf;
 166        return 0;
 167}
 168
 169/**
 170 * asd_write_ocm_seg - write an on chip memory (OCM) segment
 171 * @asd_ha: pointer to the host adapter structure
 172 * @buffer: where to read the write data
 173 * @offs: offset into OCM to write to
 174 * @size: how many bytes to write
 175 *
 176 * Return the number of bytes not written. Return 0 on success.
 177 */
 178static void asd_write_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer,
 179                            u32 offs, int size)
 180{
 181        u8 *p = buffer;
 182        if (unlikely(asd_ha->iospace))
 183                asd_write_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size);
 184        else {
 185                for ( ; size > 0; size--, offs++, p++)
 186                        asd_write_ocm_byte(asd_ha, offs, *p);
 187        }
 188        return;
 189}
 190
 191#define THREE_TO_NUM(X) ((X)[0] | ((X)[1] << 8) | ((X)[2] << 16))
 192
 193static int asd_find_dir_entry(struct asd_ocm_dir *dir, u8 type,
 194                              u32 *offs, u32 *size)
 195{
 196        int i;
 197        struct asd_ocm_dir_ent *ent;
 198
 199        for (i = 0; i < dir->num_de; i++) {
 200                if (dir->entry[i].type == type)
 201                        break;
 202        }
 203        if (i >= dir->num_de)
 204                return -ENOENT;
 205        ent = &dir->entry[i];
 206        *offs = (u32) THREE_TO_NUM(ent->offs);
 207        *size = (u32) THREE_TO_NUM(ent->size);
 208        return 0;
 209}
 210
 211#define OCM_BIOS_CHIM_DE  2
 212#define BC_BIOS_PRESENT   1
 213
 214static int asd_get_bios_chim(struct asd_ha_struct *asd_ha,
 215                             struct asd_ocm_dir *dir)
 216{
 217        int err;
 218        struct asd_bios_chim_struct *bc_struct;
 219        u32 offs, size;
 220
 221        err = asd_find_dir_entry(dir, OCM_BIOS_CHIM_DE, &offs, &size);
 222        if (err) {
 223                ASD_DPRINTK("couldn't find BIOS_CHIM dir ent\n");
 224                goto out;
 225        }
 226        err = -ENOMEM;
 227        bc_struct = kmalloc(sizeof(*bc_struct), GFP_KERNEL);
 228        if (!bc_struct) {
 229                asd_printk("no memory for bios_chim struct\n");
 230                goto out;
 231        }
 232        err = asd_read_ocm_seg(asd_ha, (void *)bc_struct, offs,
 233                               sizeof(*bc_struct));
 234        if (err) {
 235                ASD_DPRINTK("couldn't read ocm segment\n");
 236                goto out2;
 237        }
 238        if (strncmp(bc_struct->sig, "SOIB", 4)
 239            && strncmp(bc_struct->sig, "IPSA", 4)) {
 240                ASD_DPRINTK("BIOS_CHIM entry has no valid sig(%c%c%c%c)\n",
 241                            bc_struct->sig[0], bc_struct->sig[1],
 242                            bc_struct->sig[2], bc_struct->sig[3]);
 243                err = -ENOENT;
 244                goto out2;
 245        }
 246        if (bc_struct->major != 1) {
 247                asd_printk("BIOS_CHIM unsupported major version:0x%x\n",
 248                           bc_struct->major);
 249                err = -ENOENT;
 250                goto out2;
 251        }
 252        if (bc_struct->flags & BC_BIOS_PRESENT) {
 253                asd_ha->hw_prof.bios.present = 1;
 254                asd_ha->hw_prof.bios.maj = bc_struct->bios_major;
 255                asd_ha->hw_prof.bios.min = bc_struct->bios_minor;
 256                asd_ha->hw_prof.bios.bld = le32_to_cpu(bc_struct->bios_build);
 257                ASD_DPRINTK("BIOS present (%d,%d), %d\n",
 258                            asd_ha->hw_prof.bios.maj,
 259                            asd_ha->hw_prof.bios.min,
 260                            asd_ha->hw_prof.bios.bld);
 261        }
 262        asd_ha->hw_prof.ue.num = le16_to_cpu(bc_struct->ue_num);
 263        asd_ha->hw_prof.ue.size= le16_to_cpu(bc_struct->ue_size);
 264        ASD_DPRINTK("ue num:%d, ue size:%d\n", asd_ha->hw_prof.ue.num,
 265                    asd_ha->hw_prof.ue.size);
 266        size = asd_ha->hw_prof.ue.num * asd_ha->hw_prof.ue.size;
 267        if (size > 0) {
 268                err = -ENOMEM;
 269                asd_ha->hw_prof.ue.area = kmalloc(size, GFP_KERNEL);
 270                if (!asd_ha->hw_prof.ue.area)
 271                        goto out2;
 272                err = asd_read_ocm_seg(asd_ha, (void *)asd_ha->hw_prof.ue.area,
 273                                       offs + sizeof(*bc_struct), size);
 274                if (err) {
 275                        kfree(asd_ha->hw_prof.ue.area);
 276                        asd_ha->hw_prof.ue.area = NULL;
 277                        asd_ha->hw_prof.ue.num  = 0;
 278                        asd_ha->hw_prof.ue.size = 0;
 279                        ASD_DPRINTK("couldn't read ue entries(%d)\n", err);
 280                }
 281        }
 282out2:
 283        kfree(bc_struct);
 284out:
 285        return err;
 286}
 287
 288static void
 289asd_hwi_initialize_ocm_dir (struct asd_ha_struct *asd_ha)
 290{
 291        int i;
 292
 293        /* Zero OCM */
 294        for (i = 0; i < OCM_MAX_SIZE; i += 4)
 295                asd_write_ocm_dword(asd_ha, i, 0);
 296
 297        /* Write Dir */
 298        asd_write_ocm_seg(asd_ha, &OCMDirInit, 0,
 299                          sizeof(struct asd_ocm_dir));
 300
 301        /* Write Dir Entries */
 302        for (i = 0; i < OCM_INIT_DIR_ENTRIES; i++)
 303                asd_write_ocm_seg(asd_ha, &OCMDirEntriesInit[i],
 304                                  sizeof(struct asd_ocm_dir) +
 305                                  (i * sizeof(struct asd_ocm_dir_ent))
 306                                  , sizeof(struct asd_ocm_dir_ent));
 307
 308}
 309
 310static int
 311asd_hwi_check_ocm_access (struct asd_ha_struct *asd_ha)
 312{
 313        struct pci_dev *pcidev = asd_ha->pcidev;
 314        u32 reg;
 315        int err = 0;
 316        u32 v;
 317
 318        /* check if OCM has been initialized by BIOS */
 319        reg = asd_read_reg_dword(asd_ha, EXSICNFGR);
 320
 321        if (!(reg & OCMINITIALIZED)) {
 322                err = pci_read_config_dword(pcidev, PCIC_INTRPT_STAT, &v);
 323                if (err) {
 324                        asd_printk("couldn't access PCIC_INTRPT_STAT of %s\n",
 325                                        pci_name(pcidev));
 326                        goto out;
 327                }
 328
 329                printk(KERN_INFO "OCM is not initialized by BIOS,"
 330                       "reinitialize it and ignore it, current IntrptStatus"
 331                       "is 0x%x\n", v);
 332
 333                if (v)
 334                        err = pci_write_config_dword(pcidev,
 335                                                     PCIC_INTRPT_STAT, v);
 336                if (err) {
 337                        asd_printk("couldn't write PCIC_INTRPT_STAT of %s\n",
 338                                        pci_name(pcidev));
 339                        goto out;
 340                }
 341
 342                asd_hwi_initialize_ocm_dir(asd_ha);
 343
 344        }
 345out:
 346        return err;
 347}
 348
 349/**
 350 * asd_read_ocm - read on chip memory (OCM)
 351 * @asd_ha: pointer to the host adapter structure
 352 */
 353int asd_read_ocm(struct asd_ha_struct *asd_ha)
 354{
 355        int err;
 356        struct asd_ocm_dir *dir;
 357
 358        if (asd_hwi_check_ocm_access(asd_ha))
 359                return -1;
 360
 361        dir = kmalloc(sizeof(*dir), GFP_KERNEL);
 362        if (!dir) {
 363                asd_printk("no memory for ocm dir\n");
 364                return -ENOMEM;
 365        }
 366
 367        err = asd_read_ocm_dir(asd_ha, dir, 0);
 368        if (err)
 369                goto out;
 370
 371        err = asd_get_bios_chim(asd_ha, dir);
 372out:
 373        kfree(dir);
 374        return err;
 375}
 376
 377/* ---------- FLASH stuff ---------- */
 378
 379#define FLASH_RESET                     0xF0
 380
 381#define ASD_FLASH_SIZE                  0x200000
 382#define FLASH_DIR_COOKIE                "*** ADAPTEC FLASH DIRECTORY *** "
 383#define FLASH_NEXT_ENTRY_OFFS           0x2000
 384#define FLASH_MAX_DIR_ENTRIES           32
 385
 386#define FLASH_DE_TYPE_MASK              0x3FFFFFFF
 387#define FLASH_DE_MS                     0x120
 388#define FLASH_DE_CTRL_A_USER            0xE0
 389
 390struct asd_flash_de {
 391        __le32   type;
 392        __le32   offs;
 393        __le32   pad_size;
 394        __le32   image_size;
 395        __le32   chksum;
 396        u8       _r[12];
 397        u8       version[32];
 398} __attribute__ ((packed));
 399
 400struct asd_flash_dir {
 401        u8    cookie[32];
 402        __le32   rev;             /* 2 */
 403        __le32   chksum;
 404        __le32   chksum_antidote;
 405        __le32   bld;
 406        u8    bld_id[32];         /* build id data */
 407        u8    ver_data[32];       /* date and time of build */
 408        __le32   ae_mask;
 409        __le32   v_mask;
 410        __le32   oc_mask;
 411        u8    _r[20];
 412        struct asd_flash_de dir_entry[FLASH_MAX_DIR_ENTRIES];
 413} __attribute__ ((packed));
 414
 415struct asd_manuf_sec {
 416        char  sig[2];             /* 'S', 'M' */
 417        u16   offs_next;
 418        u8    maj;           /* 0 */
 419        u8    min;           /* 0 */
 420        u16   chksum;
 421        u16   size;
 422        u8    _r[6];
 423        u8    sas_addr[SAS_ADDR_SIZE];
 424        u8    pcba_sn[ASD_PCBA_SN_SIZE];
 425        /* Here start the other segments */
 426        u8    linked_list[0];
 427} __attribute__ ((packed));
 428
 429struct asd_manuf_phy_desc {
 430        u8    state;         /* low 4 bits */
 431#define MS_PHY_STATE_ENABLED    0
 432#define MS_PHY_STATE_REPORTED   1
 433#define MS_PHY_STATE_HIDDEN     2
 434        u8    phy_id;
 435        u16   _r;
 436        u8    phy_control_0; /* mode 5 reg 0x160 */
 437        u8    phy_control_1; /* mode 5 reg 0x161 */
 438        u8    phy_control_2; /* mode 5 reg 0x162 */
 439        u8    phy_control_3; /* mode 5 reg 0x163 */
 440} __attribute__ ((packed));
 441
 442struct asd_manuf_phy_param {
 443        char  sig[2];             /* 'P', 'M' */
 444        u16   next;
 445        u8    maj;           /* 0 */
 446        u8    min;           /* 2 */
 447        u8    num_phy_desc;  /* 8 */
 448        u8    phy_desc_size; /* 8 */
 449        u8    _r[3];
 450        u8    usage_model_id;
 451        u32   _r2;
 452        struct asd_manuf_phy_desc phy_desc[ASD_MAX_PHYS];
 453} __attribute__ ((packed));
 454
 455#if 0
 456static const char *asd_sb_type[] = {
 457        "unknown",
 458        "SGPIO",
 459        [2 ... 0x7F] = "unknown",
 460        [0x80] = "ADPT_I2C",
 461        [0x81 ... 0xFF] = "VENDOR_UNIQUExx"
 462};
 463#endif
 464
 465struct asd_ms_sb_desc {
 466        u8    type;
 467        u8    node_desc_index;
 468        u8    conn_desc_index;
 469        u8    _recvd[0];
 470} __attribute__ ((packed));
 471
 472#if 0
 473static const char *asd_conn_type[] = {
 474        [0 ... 7] = "unknown",
 475        "SFF8470",
 476        "SFF8482",
 477        "SFF8484",
 478        [0x80] = "PCIX_DAUGHTER0",
 479        [0x81] = "SAS_DAUGHTER0",
 480        [0x82 ... 0xFF] = "VENDOR_UNIQUExx"
 481};
 482
 483static const char *asd_conn_location[] = {
 484        "unknown",
 485        "internal",
 486        "external",
 487        "board_to_board",
 488};
 489#endif
 490
 491struct asd_ms_conn_desc {
 492        u8    type;
 493        u8    location;
 494        u8    num_sideband_desc;
 495        u8    size_sideband_desc;
 496        u32   _resvd;
 497        u8    name[16];
 498        struct asd_ms_sb_desc sb_desc[0];
 499} __attribute__ ((packed));
 500
 501struct asd_nd_phy_desc {
 502        u8    vp_attch_type;
 503        u8    attch_specific[0];
 504} __attribute__ ((packed));
 505
 506#if 0
 507static const char *asd_node_type[] = {
 508        "IOP",
 509        "IO_CONTROLLER",
 510        "EXPANDER",
 511        "PORT_MULTIPLIER",
 512        "PORT_MULTIPLEXER",
 513        "MULTI_DROP_I2C_BUS",
 514};
 515#endif
 516
 517struct asd_ms_node_desc {
 518        u8    type;
 519        u8    num_phy_desc;
 520        u8    size_phy_desc;
 521        u8    _resvd;
 522        u8    name[16];
 523        struct asd_nd_phy_desc phy_desc[0];
 524} __attribute__ ((packed));
 525
 526struct asd_ms_conn_map {
 527        char  sig[2];             /* 'M', 'C' */
 528        __le16 next;
 529        u8    maj;                /* 0 */
 530        u8    min;                /* 0 */
 531        __le16 cm_size;           /* size of this struct */
 532        u8    num_conn;
 533        u8    conn_size;
 534        u8    num_nodes;
 535        u8    usage_model_id;
 536        u32   _resvd;
 537        struct asd_ms_conn_desc conn_desc[0];
 538        struct asd_ms_node_desc node_desc[0];
 539} __attribute__ ((packed));
 540
 541struct asd_ctrla_phy_entry {
 542        u8    sas_addr[SAS_ADDR_SIZE];
 543        u8    sas_link_rates;  /* max in hi bits, min in low bits */
 544        u8    flags;
 545        u8    sata_link_rates;
 546        u8    _r[5];
 547} __attribute__ ((packed));
 548
 549struct asd_ctrla_phy_settings {
 550        u8    id0;                /* P'h'y */
 551        u8    _r;
 552        u16   next;
 553        u8    num_phys;       /* number of PHYs in the PCI function */
 554        u8    _r2[3];
 555        struct asd_ctrla_phy_entry phy_ent[ASD_MAX_PHYS];
 556} __attribute__ ((packed));
 557
 558struct asd_ll_el {
 559        u8   id0;
 560        u8   id1;
 561        __le16  next;
 562        u8   something_here[0];
 563} __attribute__ ((packed));
 564
 565static int asd_poll_flash(struct asd_ha_struct *asd_ha)
 566{
 567        int c;
 568        u8 d;
 569
 570        for (c = 5000; c > 0; c--) {
 571                d  = asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 572                d ^= asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 573                if (!d)
 574                        return 0;
 575                udelay(5);
 576        }
 577        return -ENOENT;
 578}
 579
 580static int asd_reset_flash(struct asd_ha_struct *asd_ha)
 581{
 582        int err;
 583
 584        err = asd_poll_flash(asd_ha);
 585        if (err)
 586                return err;
 587        asd_write_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar, FLASH_RESET);
 588        err = asd_poll_flash(asd_ha);
 589
 590        return err;
 591}
 592
 593static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
 594                              void *buffer, u32 offs, int size)
 595{
 596        asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
 597                            size);
 598        return 0;
 599}
 600
 601/**
 602 * asd_find_flash_dir - finds and reads the flash directory
 603 * @asd_ha: pointer to the host adapter structure
 604 * @flash_dir: pointer to flash directory structure
 605 *
 606 * If found, the flash directory segment will be copied to
 607 * @flash_dir.  Return 1 if found, 0 if not.
 608 */
 609static int asd_find_flash_dir(struct asd_ha_struct *asd_ha,
 610                              struct asd_flash_dir *flash_dir)
 611{
 612        u32 v;
 613        for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
 614                asd_read_flash_seg(asd_ha, flash_dir, v,
 615                                   sizeof(FLASH_DIR_COOKIE)-1);
 616                if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
 617                           sizeof(FLASH_DIR_COOKIE)-1) == 0) {
 618                        asd_ha->hw_prof.flash.dir_offs = v;
 619                        asd_read_flash_seg(asd_ha, flash_dir, v,
 620                                           sizeof(*flash_dir));
 621                        return 1;
 622                }
 623        }
 624        return 0;
 625}
 626
 627static int asd_flash_getid(struct asd_ha_struct *asd_ha)
 628{
 629        int err = 0;
 630        u32 reg;
 631
 632        reg = asd_read_reg_dword(asd_ha, EXSICNFGR);
 633
 634        if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR,
 635                                  &asd_ha->hw_prof.flash.bar)) {
 636                asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n",
 637                           pci_name(asd_ha->pcidev));
 638                return -ENOENT;
 639        }
 640        asd_ha->hw_prof.flash.present = 1;
 641        asd_ha->hw_prof.flash.wide = reg & FLASHW ? 1 : 0;
 642        err = asd_reset_flash(asd_ha);
 643        if (err) {
 644                ASD_DPRINTK("couldn't reset flash(%d)\n", err);
 645                return err;
 646        }
 647        return 0;
 648}
 649
 650static u16 asd_calc_flash_chksum(u16 *p, int size)
 651{
 652        u16 chksum = 0;
 653
 654        while (size-- > 0)
 655                chksum += *p++;
 656
 657        return chksum;
 658}
 659
 660
 661static int asd_find_flash_de(struct asd_flash_dir *flash_dir, u32 entry_type,
 662                             u32 *offs, u32 *size)
 663{
 664        int i;
 665        struct asd_flash_de *de;
 666
 667        for (i = 0; i < FLASH_MAX_DIR_ENTRIES; i++) {
 668                u32 type = le32_to_cpu(flash_dir->dir_entry[i].type);
 669
 670                type &= FLASH_DE_TYPE_MASK;
 671                if (type == entry_type)
 672                        break;
 673        }
 674        if (i >= FLASH_MAX_DIR_ENTRIES)
 675                return -ENOENT;
 676        de = &flash_dir->dir_entry[i];
 677        *offs = le32_to_cpu(de->offs);
 678        *size = le32_to_cpu(de->pad_size);
 679        return 0;
 680}
 681
 682static int asd_validate_ms(struct asd_manuf_sec *ms)
 683{
 684        if (ms->sig[0] != 'S' || ms->sig[1] != 'M') {
 685                ASD_DPRINTK("manuf sec: no valid sig(%c%c)\n",
 686                            ms->sig[0], ms->sig[1]);
 687                return -ENOENT;
 688        }
 689        if (ms->maj != 0) {
 690                asd_printk("unsupported manuf. sector. major version:%x\n",
 691                           ms->maj);
 692                return -ENOENT;
 693        }
 694        ms->offs_next = le16_to_cpu((__force __le16) ms->offs_next);
 695        ms->chksum = le16_to_cpu((__force __le16) ms->chksum);
 696        ms->size = le16_to_cpu((__force __le16) ms->size);
 697
 698        if (asd_calc_flash_chksum((u16 *)ms, ms->size/2)) {
 699                asd_printk("failed manuf sector checksum\n");
 700        }
 701
 702        return 0;
 703}
 704
 705static int asd_ms_get_sas_addr(struct asd_ha_struct *asd_ha,
 706                               struct asd_manuf_sec *ms)
 707{
 708        memcpy(asd_ha->hw_prof.sas_addr, ms->sas_addr, SAS_ADDR_SIZE);
 709        return 0;
 710}
 711
 712static int asd_ms_get_pcba_sn(struct asd_ha_struct *asd_ha,
 713                              struct asd_manuf_sec *ms)
 714{
 715        memcpy(asd_ha->hw_prof.pcba_sn, ms->pcba_sn, ASD_PCBA_SN_SIZE);
 716        asd_ha->hw_prof.pcba_sn[ASD_PCBA_SN_SIZE] = '\0';
 717        return 0;
 718}
 719
 720/**
 721 * asd_find_ll_by_id - find a linked list entry by its id
 722 * @start: void pointer to the first element in the linked list
 723 * @id0: the first byte of the id  (offs 0)
 724 * @id1: the second byte of the id (offs 1)
 725 *
 726 * @start has to be the _base_ element start, since the
 727 * linked list entries's offset is from this pointer.
 728 * Some linked list entries use only the first id, in which case
 729 * you can pass 0xFF for the second.
 730 */
 731static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1)
 732{
 733        struct asd_ll_el *el = start;
 734
 735        do {
 736                switch (id1) {
 737                default:
 738                        if (el->id1 == id1)
 739                case 0xFF:
 740                                if (el->id0 == id0)
 741                                        return el;
 742                }
 743                el = start + le16_to_cpu(el->next);
 744        } while (el != start);
 745
 746        return NULL;
 747}
 748
 749/**
 750 * asd_ms_get_phy_params - get phy parameters from the manufacturing sector
 751 * @asd_ha: pointer to the host adapter structure
 752 * @manuf_sec: pointer to the manufacturing sector
 753 *
 754 * The manufacturing sector contans also the linked list of sub-segments,
 755 * since when it was read, its size was taken from the flash directory,
 756 * not from the structure size.
 757 *
 758 * HIDDEN phys do not count in the total count.  REPORTED phys cannot
 759 * be enabled but are reported and counted towards the total.
 760 * ENABLED phys are enabled by default and count towards the total.
 761 * The absolute total phy number is ASD_MAX_PHYS.  hw_prof->num_phys
 762 * merely specifies the number of phys the host adapter decided to
 763 * report.  E.g., it is possible for phys 0, 1 and 2 to be HIDDEN,
 764 * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED.
 765 * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2
 766 * are actually enabled (enabled by default, max number of phys
 767 * enableable in this case).
 768 */
 769static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha,
 770                                 struct asd_manuf_sec *manuf_sec)
 771{
 772        int i;
 773        int en_phys = 0;
 774        int rep_phys = 0;
 775        struct asd_manuf_phy_param *phy_param;
 776        struct asd_manuf_phy_param dflt_phy_param;
 777
 778        phy_param = asd_find_ll_by_id(manuf_sec, 'P', 'M');
 779        if (!phy_param) {
 780                ASD_DPRINTK("ms: no phy parameters found\n");
 781                ASD_DPRINTK("ms: Creating default phy parameters\n");
 782                dflt_phy_param.sig[0] = 'P';
 783                dflt_phy_param.sig[1] = 'M';
 784                dflt_phy_param.maj = 0;
 785                dflt_phy_param.min = 2;
 786                dflt_phy_param.num_phy_desc = 8;
 787                dflt_phy_param.phy_desc_size = sizeof(struct asd_manuf_phy_desc);
 788                for (i =0; i < ASD_MAX_PHYS; i++) {
 789                        dflt_phy_param.phy_desc[i].state = 0;
 790                        dflt_phy_param.phy_desc[i].phy_id = i;
 791                        dflt_phy_param.phy_desc[i].phy_control_0 = 0xf6;
 792                        dflt_phy_param.phy_desc[i].phy_control_1 = 0x10;
 793                        dflt_phy_param.phy_desc[i].phy_control_2 = 0x43;
 794                        dflt_phy_param.phy_desc[i].phy_control_3 = 0xeb;
 795                }
 796
 797                phy_param = &dflt_phy_param;
 798
 799        }
 800
 801        if (phy_param->maj != 0) {
 802                asd_printk("unsupported manuf. phy param major version:0x%x\n",
 803                           phy_param->maj);
 804                return -ENOENT;
 805        }
 806
 807        ASD_DPRINTK("ms: num_phy_desc: %d\n", phy_param->num_phy_desc);
 808        asd_ha->hw_prof.enabled_phys = 0;
 809        for (i = 0; i < phy_param->num_phy_desc; i++) {
 810                struct asd_manuf_phy_desc *pd = &phy_param->phy_desc[i];
 811                switch (pd->state & 0xF) {
 812                case MS_PHY_STATE_HIDDEN:
 813                        ASD_DPRINTK("ms: phy%d: HIDDEN\n", i);
 814                        continue;
 815                case MS_PHY_STATE_REPORTED:
 816                        ASD_DPRINTK("ms: phy%d: REPORTED\n", i);
 817                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 818                        rep_phys++;
 819                        continue;
 820                case MS_PHY_STATE_ENABLED:
 821                        ASD_DPRINTK("ms: phy%d: ENABLED\n", i);
 822                        asd_ha->hw_prof.enabled_phys |= (1 << i);
 823                        en_phys++;
 824                        break;
 825                }
 826                asd_ha->hw_prof.phy_desc[i].phy_control_0 = pd->phy_control_0;
 827                asd_ha->hw_prof.phy_desc[i].phy_control_1 = pd->phy_control_1;
 828                asd_ha->hw_prof.phy_desc[i].phy_control_2 = pd->phy_control_2;
 829                asd_ha->hw_prof.phy_desc[i].phy_control_3 = pd->phy_control_3;
 830        }
 831        asd_ha->hw_prof.max_phys = rep_phys + en_phys;
 832        asd_ha->hw_prof.num_phys = en_phys;
 833        ASD_DPRINTK("ms: max_phys:0x%x, num_phys:0x%x\n",
 834                    asd_ha->hw_prof.max_phys, asd_ha->hw_prof.num_phys);
 835        ASD_DPRINTK("ms: enabled_phys:0x%x\n", asd_ha->hw_prof.enabled_phys);
 836        return 0;
 837}
 838
 839static int asd_ms_get_connector_map(struct asd_ha_struct *asd_ha,
 840                                    struct asd_manuf_sec *manuf_sec)
 841{
 842        struct asd_ms_conn_map *cm;
 843
 844        cm = asd_find_ll_by_id(manuf_sec, 'M', 'C');
 845        if (!cm) {
 846                ASD_DPRINTK("ms: no connector map found\n");
 847                return 0;
 848        }
 849
 850        if (cm->maj != 0) {
 851                ASD_DPRINTK("ms: unsupported: connector map major version 0x%x"
 852                            "\n", cm->maj);
 853                return -ENOENT;
 854        }
 855
 856        /* XXX */
 857
 858        return 0;
 859}
 860
 861
 862/**
 863 * asd_process_ms - find and extract information from the manufacturing sector
 864 * @asd_ha: pointer to the host adapter structure
 865 * @flash_dir: pointer to the flash directory
 866 */
 867static int asd_process_ms(struct asd_ha_struct *asd_ha,
 868                          struct asd_flash_dir *flash_dir)
 869{
 870        int err;
 871        struct asd_manuf_sec *manuf_sec;
 872        u32 offs, size;
 873
 874        err = asd_find_flash_de(flash_dir, FLASH_DE_MS, &offs, &size);
 875        if (err) {
 876                ASD_DPRINTK("Couldn't find the manuf. sector\n");
 877                goto out;
 878        }
 879
 880        if (size == 0)
 881                goto out;
 882
 883        err = -ENOMEM;
 884        manuf_sec = kmalloc(size, GFP_KERNEL);
 885        if (!manuf_sec) {
 886                ASD_DPRINTK("no mem for manuf sector\n");
 887                goto out;
 888        }
 889
 890        err = asd_read_flash_seg(asd_ha, (void *)manuf_sec, offs, size);
 891        if (err) {
 892                ASD_DPRINTK("couldn't read manuf sector at 0x%x, size 0x%x\n",
 893                            offs, size);
 894                goto out2;
 895        }
 896
 897        err = asd_validate_ms(manuf_sec);
 898        if (err) {
 899                ASD_DPRINTK("couldn't validate manuf sector\n");
 900                goto out2;
 901        }
 902
 903        err = asd_ms_get_sas_addr(asd_ha, manuf_sec);
 904        if (err) {
 905                ASD_DPRINTK("couldn't read the SAS_ADDR\n");
 906                goto out2;
 907        }
 908        ASD_DPRINTK("manuf sect SAS_ADDR %llx\n",
 909                    SAS_ADDR(asd_ha->hw_prof.sas_addr));
 910
 911        err = asd_ms_get_pcba_sn(asd_ha, manuf_sec);
 912        if (err) {
 913                ASD_DPRINTK("couldn't read the PCBA SN\n");
 914                goto out2;
 915        }
 916        ASD_DPRINTK("manuf sect PCBA SN %s\n", asd_ha->hw_prof.pcba_sn);
 917
 918        err = asd_ms_get_phy_params(asd_ha, manuf_sec);
 919        if (err) {
 920                ASD_DPRINTK("ms: couldn't get phy parameters\n");
 921                goto out2;
 922        }
 923
 924        err = asd_ms_get_connector_map(asd_ha, manuf_sec);
 925        if (err) {
 926                ASD_DPRINTK("ms: couldn't get connector map\n");
 927                goto out2;
 928        }
 929
 930out2:
 931        kfree(manuf_sec);
 932out:
 933        return err;
 934}
 935
 936static int asd_process_ctrla_phy_settings(struct asd_ha_struct *asd_ha,
 937                                          struct asd_ctrla_phy_settings *ps)
 938{
 939        int i;
 940        for (i = 0; i < ps->num_phys; i++) {
 941                struct asd_ctrla_phy_entry *pe = &ps->phy_ent[i];
 942
 943                if (!PHY_ENABLED(asd_ha, i))
 944                        continue;
 945                if (*(u64 *)pe->sas_addr == 0) {
 946                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 947                        continue;
 948                }
 949                /* This is the SAS address which should be sent in IDENTIFY. */
 950                memcpy(asd_ha->hw_prof.phy_desc[i].sas_addr, pe->sas_addr,
 951                       SAS_ADDR_SIZE);
 952                asd_ha->hw_prof.phy_desc[i].max_sas_lrate =
 953                        (pe->sas_link_rates & 0xF0) >> 4;
 954                asd_ha->hw_prof.phy_desc[i].min_sas_lrate =
 955                        (pe->sas_link_rates & 0x0F);
 956                asd_ha->hw_prof.phy_desc[i].max_sata_lrate =
 957                        (pe->sata_link_rates & 0xF0) >> 4;
 958                asd_ha->hw_prof.phy_desc[i].min_sata_lrate =
 959                        (pe->sata_link_rates & 0x0F);
 960                asd_ha->hw_prof.phy_desc[i].flags = pe->flags;
 961                ASD_DPRINTK("ctrla: phy%d: sas_addr: %llx, sas rate:0x%x-0x%x,"
 962                            " sata rate:0x%x-0x%x, flags:0x%x\n",
 963                            i,
 964                            SAS_ADDR(asd_ha->hw_prof.phy_desc[i].sas_addr),
 965                            asd_ha->hw_prof.phy_desc[i].max_sas_lrate,
 966                            asd_ha->hw_prof.phy_desc[i].min_sas_lrate,
 967                            asd_ha->hw_prof.phy_desc[i].max_sata_lrate,
 968                            asd_ha->hw_prof.phy_desc[i].min_sata_lrate,
 969                            asd_ha->hw_prof.phy_desc[i].flags);
 970        }
 971
 972        return 0;
 973}
 974
 975/**
 976 * asd_process_ctrl_a_user - process CTRL-A user settings
 977 * @asd_ha: pointer to the host adapter structure
 978 * @flash_dir: pointer to the flash directory
 979 */
 980static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha,
 981                                   struct asd_flash_dir *flash_dir)
 982{
 983        int err, i;
 984        u32 offs, size;
 985        struct asd_ll_el *el;
 986        struct asd_ctrla_phy_settings *ps;
 987        struct asd_ctrla_phy_settings dflt_ps;
 988
 989        err = asd_find_flash_de(flash_dir, FLASH_DE_CTRL_A_USER, &offs, &size);
 990        if (err) {
 991                ASD_DPRINTK("couldn't find CTRL-A user settings section\n");
 992                ASD_DPRINTK("Creating default CTRL-A user settings section\n");
 993
 994                dflt_ps.id0 = 'h';
 995                dflt_ps.num_phys = 8;
 996                for (i =0; i < ASD_MAX_PHYS; i++) {
 997                        memcpy(dflt_ps.phy_ent[i].sas_addr,
 998                               asd_ha->hw_prof.sas_addr, SAS_ADDR_SIZE);
 999                        dflt_ps.phy_ent[i].sas_link_rates = 0x98;
1000                        dflt_ps.phy_ent[i].flags = 0x0;
1001                        dflt_ps.phy_ent[i].sata_link_rates = 0x0;
1002                }
1003
1004                size = sizeof(struct asd_ctrla_phy_settings);
1005                ps = &dflt_ps;
1006        }
1007
1008        if (size == 0)
1009                goto out;
1010
1011        err = -ENOMEM;
1012        el = kmalloc(size, GFP_KERNEL);
1013        if (!el) {
1014                ASD_DPRINTK("no mem for ctrla user settings section\n");
1015                goto out;
1016        }
1017
1018        err = asd_read_flash_seg(asd_ha, (void *)el, offs, size);
1019        if (err) {
1020                ASD_DPRINTK("couldn't read ctrla phy settings section\n");
1021                goto out2;
1022        }
1023
1024        err = -ENOENT;
1025        ps = asd_find_ll_by_id(el, 'h', 0xFF);
1026        if (!ps) {
1027                ASD_DPRINTK("couldn't find ctrla phy settings struct\n");
1028                goto out2;
1029        }
1030
1031        err = asd_process_ctrla_phy_settings(asd_ha, ps);
1032        if (err) {
1033                ASD_DPRINTK("couldn't process ctrla phy settings\n");
1034                goto out2;
1035        }
1036out2:
1037        kfree(el);
1038out:
1039        return err;
1040}
1041
1042/**
1043 * asd_read_flash - read flash memory
1044 * @asd_ha: pointer to the host adapter structure
1045 */
1046int asd_read_flash(struct asd_ha_struct *asd_ha)
1047{
1048        int err;
1049        struct asd_flash_dir *flash_dir;
1050
1051        err = asd_flash_getid(asd_ha);
1052        if (err)
1053                return err;
1054
1055        flash_dir = kmalloc(sizeof(*flash_dir), GFP_KERNEL);
1056        if (!flash_dir)
1057                return -ENOMEM;
1058
1059        err = -ENOENT;
1060        if (!asd_find_flash_dir(asd_ha, flash_dir)) {
1061                ASD_DPRINTK("couldn't find flash directory\n");
1062                goto out;
1063        }
1064
1065        if (le32_to_cpu(flash_dir->rev) != 2) {
1066                asd_printk("unsupported flash dir version:0x%x\n",
1067                           le32_to_cpu(flash_dir->rev));
1068                goto out;
1069        }
1070
1071        err = asd_process_ms(asd_ha, flash_dir);
1072        if (err) {
1073                ASD_DPRINTK("couldn't process manuf sector settings\n");
1074                goto out;
1075        }
1076
1077        err = asd_process_ctrl_a_user(asd_ha, flash_dir);
1078        if (err) {
1079                ASD_DPRINTK("couldn't process CTRL-A user settings\n");
1080                goto out;
1081        }
1082
1083out:
1084        kfree(flash_dir);
1085        return err;
1086}
1087
1088/**
1089 * asd_verify_flash_seg - verify data with flash memory
1090 * @asd_ha: pointer to the host adapter structure
1091 * @src: pointer to the source data to be verified
1092 * @dest_offset: offset from flash memory
1093 * @bytes_to_verify: total bytes to verify
1094 */
1095int asd_verify_flash_seg(struct asd_ha_struct *asd_ha,
1096                         const void *src, u32 dest_offset, u32 bytes_to_verify)
1097{
1098        const u8 *src_buf;
1099        u8 flash_char;
1100        int err;
1101        u32 nv_offset, reg, i;
1102
1103        reg = asd_ha->hw_prof.flash.bar;
1104        src_buf = NULL;
1105
1106        err = FLASH_OK;
1107        nv_offset = dest_offset;
1108        src_buf = (const u8 *)src;
1109        for (i = 0; i < bytes_to_verify; i++) {
1110                flash_char = asd_read_reg_byte(asd_ha, reg + nv_offset + i);
1111                if (flash_char != src_buf[i]) {
1112                        err = FAIL_VERIFY;
1113                        break;
1114                }
1115        }
1116        return err;
1117}
1118
1119/**
1120 * asd_write_flash_seg - write data into flash memory
1121 * @asd_ha: pointer to the host adapter structure
1122 * @src: pointer to the source data to be written
1123 * @dest_offset: offset from flash memory
1124 * @bytes_to_write: total bytes to write
1125 */
1126int asd_write_flash_seg(struct asd_ha_struct *asd_ha,
1127                        const void *src, u32 dest_offset, u32 bytes_to_write)
1128{
1129        const u8 *src_buf;
1130        u32 nv_offset, reg, i;
1131        int err;
1132
1133        reg = asd_ha->hw_prof.flash.bar;
1134        src_buf = NULL;
1135
1136        err = asd_check_flash_type(asd_ha);
1137        if (err) {
1138                ASD_DPRINTK("couldn't find the type of flash. err=%d\n", err);
1139                return err;
1140        }
1141
1142        nv_offset = dest_offset;
1143        err = asd_erase_nv_sector(asd_ha, nv_offset, bytes_to_write);
1144        if (err) {
1145                ASD_DPRINTK("Erase failed at offset:0x%x\n",
1146                        nv_offset);
1147                return err;
1148        }
1149
1150        err = asd_reset_flash(asd_ha);
1151        if (err) {
1152                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1153                return err;
1154        }
1155
1156        src_buf = (const u8 *)src;
1157        for (i = 0; i < bytes_to_write; i++) {
1158                /* Setup program command sequence */
1159                switch (asd_ha->hw_prof.flash.method) {
1160                case FLASH_METHOD_A:
1161                {
1162                        asd_write_reg_byte(asd_ha,
1163                                        (reg + 0xAAA), 0xAA);
1164                        asd_write_reg_byte(asd_ha,
1165                                        (reg + 0x555), 0x55);
1166                        asd_write_reg_byte(asd_ha,
1167                                        (reg + 0xAAA), 0xA0);
1168                        asd_write_reg_byte(asd_ha,
1169                                        (reg + nv_offset + i),
1170                                        (*(src_buf + i)));
1171                        break;
1172                }
1173                case FLASH_METHOD_B:
1174                {
1175                        asd_write_reg_byte(asd_ha,
1176                                        (reg + 0x555), 0xAA);
1177                        asd_write_reg_byte(asd_ha,
1178                                        (reg + 0x2AA), 0x55);
1179                        asd_write_reg_byte(asd_ha,
1180                                        (reg + 0x555), 0xA0);
1181                        asd_write_reg_byte(asd_ha,
1182                                        (reg + nv_offset + i),
1183                                        (*(src_buf + i)));
1184                        break;
1185                }
1186                default:
1187                        break;
1188                }
1189                if (asd_chk_write_status(asd_ha,
1190                                (nv_offset + i), 0) != 0) {
1191                        ASD_DPRINTK("aicx: Write failed at offset:0x%x\n",
1192                                reg + nv_offset + i);
1193                        return FAIL_WRITE_FLASH;
1194                }
1195        }
1196
1197        err = asd_reset_flash(asd_ha);
1198        if (err) {
1199                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1200                return err;
1201        }
1202        return 0;
1203}
1204
1205int asd_chk_write_status(struct asd_ha_struct *asd_ha,
1206         u32 sector_addr, u8 erase_flag)
1207{
1208        u32 reg;
1209        u32 loop_cnt;
1210        u8  nv_data1, nv_data2;
1211        u8  toggle_bit1;
1212
1213        /*
1214         * Read from DQ2 requires sector address
1215         * while it's dont care for DQ6
1216         */
1217        reg = asd_ha->hw_prof.flash.bar;
1218
1219        for (loop_cnt = 0; loop_cnt < 50000; loop_cnt++) {
1220                nv_data1 = asd_read_reg_byte(asd_ha, reg);
1221                nv_data2 = asd_read_reg_byte(asd_ha, reg);
1222
1223                toggle_bit1 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1224                                 ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1225
1226                if (toggle_bit1 == 0) {
1227                        return 0;
1228                } else {
1229                        if (nv_data2 & FLASH_STATUS_BIT_MASK_DQ5) {
1230                                nv_data1 = asd_read_reg_byte(asd_ha,
1231                                                                reg);
1232                                nv_data2 = asd_read_reg_byte(asd_ha,
1233                                                                reg);
1234                                toggle_bit1 =
1235                                ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1236                                ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1237
1238                                if (toggle_bit1 == 0)
1239                                        return 0;
1240                        }
1241                }
1242
1243                /*
1244                 * ERASE is a sector-by-sector operation and requires
1245                 * more time to finish while WRITE is byte-byte-byte
1246                 * operation and takes lesser time to finish.
1247                 *
1248                 * For some strange reason a reduced ERASE delay gives different
1249                 * behaviour across different spirit boards. Hence we set
1250                 * a optimum balance of 50mus for ERASE which works well
1251                 * across all boards.
1252                 */
1253                if (erase_flag) {
1254                        udelay(FLASH_STATUS_ERASE_DELAY_COUNT);
1255                } else {
1256                        udelay(FLASH_STATUS_WRITE_DELAY_COUNT);
1257                }
1258        }
1259        return -1;
1260}
1261
1262/**
1263 * asd_hwi_erase_nv_sector - Erase the flash memory sectors.
1264 * @asd_ha: pointer to the host adapter structure
1265 * @flash_addr: pointer to offset from flash memory
1266 * @size: total bytes to erase.
1267 */
1268int asd_erase_nv_sector(struct asd_ha_struct *asd_ha, u32 flash_addr, u32 size)
1269{
1270        u32 reg;
1271        u32 sector_addr;
1272
1273        reg = asd_ha->hw_prof.flash.bar;
1274
1275        /* sector staring address */
1276        sector_addr = flash_addr & FLASH_SECTOR_SIZE_MASK;
1277
1278        /*
1279         * Erasing an flash sector needs to be done in six consecutive
1280         * write cyles.
1281         */
1282        while (sector_addr < flash_addr+size) {
1283                switch (asd_ha->hw_prof.flash.method) {
1284                case FLASH_METHOD_A:
1285                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1286                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1287                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0x80);
1288                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1289                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1290                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1291                        break;
1292                case FLASH_METHOD_B:
1293                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1294                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1295                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x80);
1296                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1297                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1298                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1299                        break;
1300                default:
1301                        break;
1302                }
1303
1304                if (asd_chk_write_status(asd_ha, sector_addr, 1) != 0)
1305                        return FAIL_ERASE_FLASH;
1306
1307                sector_addr += FLASH_SECTOR_SIZE;
1308        }
1309
1310        return 0;
1311}
1312
1313int asd_check_flash_type(struct asd_ha_struct *asd_ha)
1314{
1315        u8 manuf_id;
1316        u8 dev_id;
1317        u8 sec_prot;
1318        u32 inc;
1319        u32 reg;
1320        int err;
1321
1322        /* get Flash memory base address */
1323        reg = asd_ha->hw_prof.flash.bar;
1324
1325        /* Determine flash info */
1326        err = asd_reset_flash(asd_ha);
1327        if (err) {
1328                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1329                return err;
1330        }
1331
1332        asd_ha->hw_prof.flash.method = FLASH_METHOD_UNKNOWN;
1333        asd_ha->hw_prof.flash.manuf = FLASH_MANUF_ID_UNKNOWN;
1334        asd_ha->hw_prof.flash.dev_id = FLASH_DEV_ID_UNKNOWN;
1335
1336        /* Get flash info. This would most likely be AMD Am29LV family flash.
1337         * First try the sequence for word mode.  It is the same as for
1338         * 008B (byte mode only), 160B (word mode) and 800D (word mode).
1339         */
1340        inc = asd_ha->hw_prof.flash.wide ? 2 : 1;
1341        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0xAA);
1342        asd_write_reg_byte(asd_ha, reg + 0x555, 0x55);
1343        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0x90);
1344        manuf_id = asd_read_reg_byte(asd_ha, reg);
1345        dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1346        sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1347        /* Get out of autoselect mode. */
1348        err = asd_reset_flash(asd_ha);
1349        if (err) {
1350                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1351                return err;
1352        }
1353        ASD_DPRINTK("Flash MethodA manuf_id(0x%x) dev_id(0x%x) "
1354                "sec_prot(0x%x)\n", manuf_id, dev_id, sec_prot);
1355        err = asd_reset_flash(asd_ha);
1356        if (err != 0)
1357                return err;
1358
1359        switch (manuf_id) {
1360        case FLASH_MANUF_ID_AMD:
1361                switch (sec_prot) {
1362                case FLASH_DEV_ID_AM29LV800DT:
1363                case FLASH_DEV_ID_AM29LV640MT:
1364                case FLASH_DEV_ID_AM29F800B:
1365                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1366                        break;
1367                default:
1368                        break;
1369                }
1370                break;
1371        case FLASH_MANUF_ID_ST:
1372                switch (sec_prot) {
1373                case FLASH_DEV_ID_STM29W800DT:
1374                case FLASH_DEV_ID_STM29LV640:
1375                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1376                        break;
1377                default:
1378                        break;
1379                }
1380                break;
1381        case FLASH_MANUF_ID_FUJITSU:
1382                switch (sec_prot) {
1383                case FLASH_DEV_ID_MBM29LV800TE:
1384                case FLASH_DEV_ID_MBM29DL800TA:
1385                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1386                        break;
1387                }
1388                break;
1389        case FLASH_MANUF_ID_MACRONIX:
1390                switch (sec_prot) {
1391                case FLASH_DEV_ID_MX29LV800BT:
1392                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1393                        break;
1394                }
1395                break;
1396        }
1397
1398        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN) {
1399                err = asd_reset_flash(asd_ha);
1400                if (err) {
1401                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1402                        return err;
1403                }
1404
1405                /* Issue Unlock sequence for AM29LV008BT */
1406                asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1407                asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1408                asd_write_reg_byte(asd_ha, (reg + 0x555), 0x90);
1409                manuf_id = asd_read_reg_byte(asd_ha, reg);
1410                dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1411                sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1412
1413                ASD_DPRINTK("Flash MethodB manuf_id(0x%x) dev_id(0x%x) sec_prot"
1414                        "(0x%x)\n", manuf_id, dev_id, sec_prot);
1415
1416                err = asd_reset_flash(asd_ha);
1417                if (err != 0) {
1418                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1419                        return err;
1420                }
1421
1422                switch (manuf_id) {
1423                case FLASH_MANUF_ID_AMD:
1424                        switch (dev_id) {
1425                        case FLASH_DEV_ID_AM29LV008BT:
1426                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1427                                break;
1428                        default:
1429                                break;
1430                        }
1431                        break;
1432                case FLASH_MANUF_ID_ST:
1433                        switch (dev_id) {
1434                        case FLASH_DEV_ID_STM29008:
1435                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1436                                break;
1437                        default:
1438                                break;
1439                        }
1440                        break;
1441                case FLASH_MANUF_ID_FUJITSU:
1442                        switch (dev_id) {
1443                        case FLASH_DEV_ID_MBM29LV008TA:
1444                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1445                                break;
1446                        }
1447                        break;
1448                case FLASH_MANUF_ID_INTEL:
1449                        switch (dev_id) {
1450                        case FLASH_DEV_ID_I28LV00TAT:
1451                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1452                                break;
1453                        }
1454                        break;
1455                case FLASH_MANUF_ID_MACRONIX:
1456                        switch (dev_id) {
1457                        case FLASH_DEV_ID_I28LV00TAT:
1458                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1459                                break;
1460                        }
1461                        break;
1462                default:
1463                        return FAIL_FIND_FLASH_ID;
1464                }
1465        }
1466
1467        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN)
1468              return FAIL_FIND_FLASH_ID;
1469
1470        asd_ha->hw_prof.flash.manuf = manuf_id;
1471        asd_ha->hw_prof.flash.dev_id = dev_id;
1472        asd_ha->hw_prof.flash.sec_prot = sec_prot;
1473        return 0;
1474}
1475