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