linux/drivers/staging/ath6kl/bmi/src/bmi.c
<<
>>
Prefs
   1//------------------------------------------------------------------------------
   2// <copyright file="bmi.c" company="Atheros">
   3//    Copyright (c) 2004-2010 Atheros Corporation.  All rights reserved.
   4// 
   5//
   6// Permission to use, copy, modify, and/or distribute this software for any
   7// purpose with or without fee is hereby granted, provided that the above
   8// copyright notice and this permission notice appear in all copies.
   9//
  10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17//
  18//
  19//------------------------------------------------------------------------------
  20//==============================================================================
  21//
  22// Author(s): ="Atheros"
  23//==============================================================================
  24
  25
  26#ifdef THREAD_X
  27#include <string.h>
  28#endif
  29
  30#include "hif.h"
  31#include "bmi.h"
  32#include "htc_api.h"
  33#include "bmi_internal.h"
  34
  35#ifdef ATH_DEBUG_MODULE
  36static struct ath_debug_mask_description bmi_debug_desc[] = {
  37    { ATH_DEBUG_BMI , "BMI Tracing"},
  38};
  39
  40ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
  41                                 "bmi",
  42                                 "Boot Manager Interface",
  43                                 ATH_DEBUG_MASK_DEFAULTS,
  44                                 ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
  45                                 bmi_debug_desc);
  46                                 
  47#endif
  48
  49/*
  50Although we had envisioned BMI to run on top of HTC, this is not how the
  51final implementation ended up. On the Target side, BMI is a part of the BSP
  52and does not use the HTC protocol nor even DMA -- it is intentionally kept
  53very simple.
  54*/
  55
  56static bool pendingEventsFuncCheck = false;
  57static u32 *pBMICmdCredits;
  58static u8 *pBMICmdBuf;
  59#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
  60                       sizeof(u32) /* cmd */ + \
  61                       sizeof(u32) /* addr */ + \
  62                       sizeof(u32))/* length */
  63#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
  64    
  65/* APIs visible to the driver */
  66void
  67BMIInit(void)
  68{
  69    bmiDone = false;
  70    pendingEventsFuncCheck = false;
  71
  72    /*
  73     * On some platforms, it's not possible to DMA to a static variable
  74     * in a device driver (e.g. Linux loadable driver module).
  75     * So we need to A_MALLOC space for "command credits" and for commands.
  76     *
  77     * Note: implicitly relies on A_MALLOC to provide a buffer that is
  78     * suitable for DMA (or PIO).  This buffer will be passed down the
  79     * bus stack.
  80     */
  81    if (!pBMICmdCredits) {
  82        pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
  83        A_ASSERT(pBMICmdCredits);
  84    }
  85
  86    if (!pBMICmdBuf) {
  87        pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
  88        A_ASSERT(pBMICmdBuf);
  89    }
  90    
  91    A_REGISTER_MODULE_DEBUG_INFO(bmi);
  92}
  93
  94void
  95BMICleanup(void)
  96{
  97    if (pBMICmdCredits) {
  98        A_FREE(pBMICmdCredits);
  99        pBMICmdCredits = NULL;
 100    }
 101
 102    if (pBMICmdBuf) {
 103        A_FREE(pBMICmdBuf);
 104        pBMICmdBuf = NULL;
 105    }
 106}
 107
 108int
 109BMIDone(struct hif_device *device)
 110{
 111    int status;
 112    u32 cid;
 113
 114    if (bmiDone) {
 115        AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
 116        return 0;
 117    }
 118
 119    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
 120    bmiDone = true;
 121    cid = BMI_DONE;
 122
 123    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
 124    if (status) {
 125        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 126        return A_ERROR;
 127    }
 128
 129    if (pBMICmdCredits) {
 130        A_FREE(pBMICmdCredits);
 131        pBMICmdCredits = NULL;
 132    }
 133
 134    if (pBMICmdBuf) {
 135        A_FREE(pBMICmdBuf);
 136        pBMICmdBuf = NULL;
 137    }
 138
 139    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
 140
 141    return 0;
 142}
 143
 144int
 145BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
 146{
 147    int status;
 148    u32 cid;
 149
 150    if (bmiDone) {
 151        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 152        return A_ERROR;
 153    }
 154
 155    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
 156    cid = BMI_GET_TARGET_INFO;
 157
 158    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
 159    if (status) {
 160        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 161        return A_ERROR;
 162    }
 163
 164    status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
 165                                                sizeof(targ_info->target_ver), true);
 166    if (status) {
 167        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
 168        return A_ERROR;
 169    }
 170
 171    if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
 172        /* Determine how many bytes are in the Target's targ_info */
 173        status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
 174                                            sizeof(targ_info->target_info_byte_count), true);
 175        if (status) {
 176            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
 177            return A_ERROR;
 178        }
 179
 180        /*
 181         * The Target's targ_info doesn't match the Host's targ_info.
 182         * We need to do some backwards compatibility work to make this OK.
 183         */
 184        A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
 185
 186        /* Read the remainder of the targ_info */
 187        status = bmiBufferReceive(device,
 188                        ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
 189                        sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
 190        if (status) {
 191            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
 192                                                                targ_info->target_info_byte_count));
 193            return A_ERROR;
 194        }
 195    }
 196
 197    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
 198                                                                targ_info->target_ver, targ_info->target_type));
 199
 200    return 0;
 201}
 202
 203int
 204BMIReadMemory(struct hif_device *device,
 205              u32 address,
 206              u8 *buffer,
 207              u32 length)
 208{
 209    u32 cid;
 210    int status;
 211    u32 offset;
 212    u32 remaining, rxlen;
 213
 214    A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
 215    memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
 216
 217    if (bmiDone) {
 218        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 219        return A_ERROR;
 220    }
 221
 222    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 223                        ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
 224                                device, address, length));
 225
 226    cid = BMI_READ_MEMORY;
 227
 228    remaining = length;
 229
 230    while (remaining)
 231    {
 232        rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
 233        offset = 0;
 234        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 235        offset += sizeof(cid);
 236        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 237        offset += sizeof(address);
 238        memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
 239        offset += sizeof(length);
 240
 241        status = bmiBufferSend(device, pBMICmdBuf, offset);
 242        if (status) {
 243            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 244            return A_ERROR;
 245        }
 246        status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
 247        if (status) {
 248            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
 249            return A_ERROR;
 250        }
 251        memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
 252        remaining -= rxlen; address += rxlen;
 253    }
 254
 255    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
 256    return 0;
 257}
 258
 259int
 260BMIWriteMemory(struct hif_device *device,
 261               u32 address,
 262               u8 *buffer,
 263               u32 length)
 264{
 265    u32 cid;
 266    int status;
 267    u32 offset;
 268    u32 remaining, txlen;
 269    const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
 270    u8 alignedBuffer[BMI_DATASZ_MAX];
 271    u8 *src;
 272
 273    A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
 274    memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
 275
 276    if (bmiDone) {
 277        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 278        return A_ERROR;
 279    }
 280
 281    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 282         ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
 283         device, address, length));
 284
 285    cid = BMI_WRITE_MEMORY;
 286
 287    remaining = length;
 288    while (remaining)
 289    {
 290        src = &buffer[length - remaining];
 291        if (remaining < (BMI_DATASZ_MAX - header)) {
 292            if (remaining & 3) {
 293                /* align it with 4 bytes */
 294                remaining = remaining + (4 - (remaining & 3));
 295                memcpy(alignedBuffer, src, remaining);
 296                src = alignedBuffer;
 297            } 
 298            txlen = remaining;
 299        } else {
 300            txlen = (BMI_DATASZ_MAX - header);
 301        }
 302        offset = 0;
 303        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 304        offset += sizeof(cid);
 305        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 306        offset += sizeof(address);
 307        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
 308        offset += sizeof(txlen);
 309        memcpy(&(pBMICmdBuf[offset]), src, txlen);
 310        offset += txlen;
 311        status = bmiBufferSend(device, pBMICmdBuf, offset);
 312        if (status) {
 313            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 314            return A_ERROR;
 315        }
 316        remaining -= txlen; address += txlen;
 317    }
 318
 319    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
 320
 321    return 0;
 322}
 323
 324int
 325BMIExecute(struct hif_device *device,
 326           u32 address,
 327           u32 *param)
 328{
 329    u32 cid;
 330    int status;
 331    u32 offset;
 332
 333    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
 334    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
 335
 336    if (bmiDone) {
 337        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 338        return A_ERROR;
 339    }
 340
 341    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 342       ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
 343        device, address, *param));
 344
 345    cid = BMI_EXECUTE;
 346
 347    offset = 0;
 348    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 349    offset += sizeof(cid);
 350    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 351    offset += sizeof(address);
 352    memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
 353    offset += sizeof(*param);
 354    status = bmiBufferSend(device, pBMICmdBuf, offset);
 355    if (status) {
 356        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 357        return A_ERROR;
 358    }
 359
 360    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
 361    if (status) {
 362        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
 363        return A_ERROR;
 364    }
 365
 366    memcpy(param, pBMICmdBuf, sizeof(*param));
 367
 368    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
 369    return 0;
 370}
 371
 372int
 373BMISetAppStart(struct hif_device *device,
 374               u32 address)
 375{
 376    u32 cid;
 377    int status;
 378    u32 offset;
 379
 380    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
 381    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
 382
 383    if (bmiDone) {
 384        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 385        return A_ERROR;
 386    }
 387
 388    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 389       ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
 390        device, address));
 391
 392    cid = BMI_SET_APP_START;
 393
 394    offset = 0;
 395    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 396    offset += sizeof(cid);
 397    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 398    offset += sizeof(address);
 399    status = bmiBufferSend(device, pBMICmdBuf, offset);
 400    if (status) {
 401        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 402        return A_ERROR;
 403    }
 404
 405    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
 406    return 0;
 407}
 408
 409int
 410BMIReadSOCRegister(struct hif_device *device,
 411                   u32 address,
 412                   u32 *param)
 413{
 414    u32 cid;
 415    int status;
 416    u32 offset;
 417
 418    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
 419    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
 420
 421    if (bmiDone) {
 422        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 423        return A_ERROR;
 424    }
 425
 426    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 427       ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
 428       device, address));
 429
 430    cid = BMI_READ_SOC_REGISTER;
 431
 432    offset = 0;
 433    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 434    offset += sizeof(cid);
 435    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 436    offset += sizeof(address);
 437
 438    status = bmiBufferSend(device, pBMICmdBuf, offset);
 439    if (status) {
 440        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 441        return A_ERROR;
 442    }
 443
 444    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
 445    if (status) {
 446        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
 447        return A_ERROR;
 448    }
 449    memcpy(param, pBMICmdBuf, sizeof(*param));
 450
 451    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
 452    return 0;
 453}
 454
 455int
 456BMIWriteSOCRegister(struct hif_device *device,
 457                    u32 address,
 458                    u32 param)
 459{
 460    u32 cid;
 461    int status;
 462    u32 offset;
 463
 464    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
 465    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
 466
 467    if (bmiDone) {
 468        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 469        return A_ERROR;
 470    }
 471
 472    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 473     ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
 474     device, address, param));
 475
 476    cid = BMI_WRITE_SOC_REGISTER;
 477
 478    offset = 0;
 479    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 480    offset += sizeof(cid);
 481    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 482    offset += sizeof(address);
 483    memcpy(&(pBMICmdBuf[offset]), &param, sizeof(param));
 484    offset += sizeof(param);
 485    status = bmiBufferSend(device, pBMICmdBuf, offset);
 486    if (status) {
 487        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 488        return A_ERROR;
 489    }
 490
 491    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
 492    return 0;
 493}
 494
 495int
 496BMIrompatchInstall(struct hif_device *device,
 497                   u32 ROM_addr,
 498                   u32 RAM_addr,
 499                   u32 nbytes,
 500                   u32 do_activate,
 501                   u32 *rompatch_id)
 502{
 503    u32 cid;
 504    int status;
 505    u32 offset;
 506
 507    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
 508                                sizeof(nbytes) + sizeof(do_activate)));
 509    memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
 510                        sizeof(nbytes) + sizeof(do_activate));
 511
 512    if (bmiDone) {
 513        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 514        return A_ERROR;
 515    }
 516
 517    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 518         ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
 519         device, ROM_addr, RAM_addr, nbytes, do_activate));
 520
 521    cid = BMI_ROMPATCH_INSTALL;
 522
 523    offset = 0;
 524    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 525    offset += sizeof(cid);
 526    memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
 527    offset += sizeof(ROM_addr);
 528    memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
 529    offset += sizeof(RAM_addr);
 530    memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
 531    offset += sizeof(nbytes);
 532    memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
 533    offset += sizeof(do_activate);
 534    status = bmiBufferSend(device, pBMICmdBuf, offset);
 535    if (status) {
 536        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 537        return A_ERROR;
 538    }
 539
 540    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
 541    if (status) {
 542        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
 543        return A_ERROR;
 544    }
 545    memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
 546
 547    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
 548    return 0;
 549}
 550
 551int
 552BMIrompatchUninstall(struct hif_device *device,
 553                     u32 rompatch_id)
 554{
 555    u32 cid;
 556    int status;
 557    u32 offset;
 558
 559    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
 560    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
 561
 562    if (bmiDone) {
 563        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 564        return A_ERROR;
 565    }
 566
 567    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 568         ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
 569                                                                         device, rompatch_id));
 570
 571    cid = BMI_ROMPATCH_UNINSTALL;
 572
 573    offset = 0;
 574    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 575    offset += sizeof(cid);
 576    memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
 577    offset += sizeof(rompatch_id);
 578    status = bmiBufferSend(device, pBMICmdBuf, offset);
 579    if (status) {
 580        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 581        return A_ERROR;
 582    }
 583
 584    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
 585    return 0;
 586}
 587
 588static int
 589_BMIrompatchChangeActivation(struct hif_device *device,
 590                             u32 rompatch_count,
 591                             u32 *rompatch_list,
 592                             u32 do_activate)
 593{
 594    u32 cid;
 595    int status;
 596    u32 offset;
 597    u32 length;
 598
 599    A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
 600    memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
 601
 602    if (bmiDone) {
 603        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 604        return A_ERROR;
 605    }
 606
 607    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 608         ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
 609           device, rompatch_count));
 610
 611    cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
 612
 613    offset = 0;
 614    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 615    offset += sizeof(cid);
 616    memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
 617    offset += sizeof(rompatch_count);
 618    length = rompatch_count * sizeof(*rompatch_list);
 619    memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
 620    offset += length;
 621    status = bmiBufferSend(device, pBMICmdBuf, offset);
 622    if (status) {
 623        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 624        return A_ERROR;
 625    }
 626
 627    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
 628
 629    return 0;
 630}
 631
 632int
 633BMIrompatchActivate(struct hif_device *device,
 634                    u32 rompatch_count,
 635                    u32 *rompatch_list)
 636{
 637    return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
 638}
 639
 640int
 641BMIrompatchDeactivate(struct hif_device *device,
 642                      u32 rompatch_count,
 643                      u32 *rompatch_list)
 644{
 645    return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
 646}
 647
 648int
 649BMILZData(struct hif_device *device,
 650          u8 *buffer,
 651          u32 length)
 652{
 653    u32 cid;
 654    int status;
 655    u32 offset;
 656    u32 remaining, txlen;
 657    const u32 header = sizeof(cid) + sizeof(length);
 658
 659    A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
 660    memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
 661
 662    if (bmiDone) {
 663        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 664        return A_ERROR;
 665    }
 666
 667    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 668         ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
 669         device, length));
 670
 671    cid = BMI_LZ_DATA;
 672
 673    remaining = length;
 674    while (remaining)
 675    {
 676        txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
 677                                       remaining : (BMI_DATASZ_MAX - header);
 678        offset = 0;
 679        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 680        offset += sizeof(cid);
 681        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
 682        offset += sizeof(txlen);
 683        memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
 684        offset += txlen;
 685        status = bmiBufferSend(device, pBMICmdBuf, offset);
 686        if (status) {
 687            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
 688            return A_ERROR;
 689        }
 690        remaining -= txlen;
 691    }
 692
 693    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
 694
 695    return 0;
 696}
 697
 698int
 699BMILZStreamStart(struct hif_device *device,
 700                 u32 address)
 701{
 702    u32 cid;
 703    int status;
 704    u32 offset;
 705
 706    A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
 707    memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
 708
 709    if (bmiDone) {
 710        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
 711        return A_ERROR;
 712    }
 713
 714    AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
 715         ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
 716         device, address));
 717
 718    cid = BMI_LZ_STREAM_START;
 719    offset = 0;
 720    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
 721    offset += sizeof(cid);
 722    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
 723    offset += sizeof(address);
 724    status = bmiBufferSend(device, pBMICmdBuf, offset);
 725    if (status) {
 726        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
 727        return A_ERROR;
 728    }
 729
 730    AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
 731
 732    return 0;
 733}
 734
 735/* BMI Access routines */
 736int
 737bmiBufferSend(struct hif_device *device,
 738              u8 *buffer,
 739              u32 length)
 740{
 741    int status;
 742    u32 timeout;
 743    u32 address;
 744    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
 745
 746    HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
 747                       &mboxAddress[0], sizeof(mboxAddress));
 748
 749    *pBMICmdCredits = 0;
 750    timeout = BMI_COMMUNICATION_TIMEOUT;
 751
 752    while(timeout-- && !(*pBMICmdCredits)) {
 753        /* Read the counter register to get the command credits */
 754        address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
 755        /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
 756         * a decrement, while the remaining 3 bytes has no effect.  The rationale behind this is to
 757         * make all HIF accesses 4-byte aligned */
 758        status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
 759            HIF_RD_SYNC_BYTE_INC, NULL);
 760        if (status) {
 761            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
 762            return A_ERROR;
 763        }
 764        /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
 765        (*pBMICmdCredits) &= 0xFF;
 766    }
 767
 768    if (*pBMICmdCredits) {
 769        address = mboxAddress[ENDPOINT1];
 770        status = HIFReadWrite(device, address, buffer, length,
 771            HIF_WR_SYNC_BYTE_INC, NULL);
 772        if (status) {
 773            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
 774            return A_ERROR;
 775        }
 776    } else {
 777        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
 778        return A_ERROR;
 779    }
 780
 781    return status;
 782}
 783
 784int
 785bmiBufferReceive(struct hif_device *device,
 786                 u8 *buffer,
 787                 u32 length,
 788                 bool want_timeout)
 789{
 790    int status;
 791    u32 address;
 792    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
 793    struct hif_pending_events_info     hifPendingEvents;
 794    static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
 795    
 796    if (!pendingEventsFuncCheck) {
 797            /* see if the HIF layer implements an alternative function to get pending events
 798             * do this only once! */
 799        HIFConfigureDevice(device,
 800                           HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
 801                           &getPendingEventsFunc,
 802                           sizeof(getPendingEventsFunc));
 803        pendingEventsFuncCheck = true;
 804    }
 805                       
 806    HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
 807                       &mboxAddress[0], sizeof(mboxAddress));
 808
 809    /*
 810     * During normal bootup, small reads may be required.
 811     * Rather than issue an HIF Read and then wait as the Target
 812     * adds successive bytes to the FIFO, we wait here until
 813     * we know that response data is available.
 814     *
 815     * This allows us to cleanly timeout on an unexpected
 816     * Target failure rather than risk problems at the HIF level.  In
 817     * particular, this avoids SDIO timeouts and possibly garbage
 818     * data on some host controllers.  And on an interconnect
 819     * such as Compact Flash (as well as some SDIO masters) which
 820     * does not provide any indication on data timeout, it avoids
 821     * a potential hang or garbage response.
 822     *
 823     * Synchronization is more difficult for reads larger than the
 824     * size of the MBOX FIFO (128B), because the Target is unable
 825     * to push the 129th byte of data until AFTER the Host posts an
 826     * HIF Read and removes some FIFO data.  So for large reads the
 827     * Host proceeds to post an HIF Read BEFORE all the data is
 828     * actually available to read.  Fortunately, large BMI reads do
 829     * not occur in practice -- they're supported for debug/development.
 830     *
 831     * So Host/Target BMI synchronization is divided into these cases:
 832     *  CASE 1: length < 4
 833     *        Should not happen
 834     *
 835     *  CASE 2: 4 <= length <= 128
 836     *        Wait for first 4 bytes to be in FIFO
 837     *        If CONSERVATIVE_BMI_READ is enabled, also wait for
 838     *        a BMI command credit, which indicates that the ENTIRE
 839     *        response is available in the the FIFO
 840     *
 841     *  CASE 3: length > 128
 842     *        Wait for the first 4 bytes to be in FIFO
 843     *
 844     * For most uses, a small timeout should be sufficient and we will
 845     * usually see a response quickly; but there may be some unusual
 846     * (debug) cases of BMI_EXECUTE where we want an larger timeout.
 847     * For now, we use an unbounded busy loop while waiting for
 848     * BMI_EXECUTE.
 849     *
 850     * If BMI_EXECUTE ever needs to support longer-latency execution,
 851     * especially in production, this code needs to be enhanced to sleep
 852     * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
 853     * a function of Host processor speed.
 854     */
 855    if (length >= 4) { /* NB: Currently, always true */
 856        /*
 857         * NB: word_available is declared static for esoteric reasons
 858         * having to do with protection on some OSes.
 859         */
 860        static u32 word_available;
 861        u32 timeout;
 862
 863        word_available = 0;
 864        timeout = BMI_COMMUNICATION_TIMEOUT;
 865        while((!want_timeout || timeout--) && !word_available) {
 866            
 867            if (getPendingEventsFunc != NULL) {
 868                status = getPendingEventsFunc(device,
 869                                              &hifPendingEvents,
 870                                              NULL);
 871                if (status) {
 872                    AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
 873                    break;
 874                }
 875  
 876                if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
 877                    word_available = 1;    
 878                }
 879                continue;    
 880            }
 881            
 882            status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
 883                sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
 884            if (status) {
 885                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
 886                return A_ERROR;
 887            }
 888            /* We did a 4-byte read to the same register; all we really want is one bit */ 
 889            word_available &= (1 << ENDPOINT1);
 890        }
 891
 892        if (!word_available) {
 893            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
 894            return A_ERROR;
 895        }
 896    }
 897
 898#define CONSERVATIVE_BMI_READ 0
 899#if CONSERVATIVE_BMI_READ
 900    /*
 901     * This is an extra-conservative CREDIT check.  It guarantees
 902     * that ALL data is available in the FIFO before we start to
 903     * read from the interconnect.
 904     *
 905     * This credit check is useless when firmware chooses to
 906     * allow multiple outstanding BMI Command Credits, since the next
 907     * credit will already be present.  To restrict the Target to one
 908     * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
 909     *
 910     * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
 911     * we cannot wait for the next credit because the Target's FIFO
 912     * will not hold the entire response.  So we need the Host to
 913     * start to empty the FIFO sooner.  (And again, large reads are
 914     * not used in practice; they are for debug/development only.)
 915     *
 916     * For a more conservative Host implementation (which would be
 917     * safer for a Compact Flash interconnect):
 918     *   Set CONSERVATIVE_BMI_READ (above) to 1
 919     *   Set HI_OPTION_BMI_CRED_LIMIT and
 920     *   reduce BMI_DATASZ_MAX to 32 or 64
 921     */
 922    if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
 923        u32 timeout;
 924
 925        *pBMICmdCredits = 0;
 926        timeout = BMI_COMMUNICATION_TIMEOUT;
 927        while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
 928            /* Read the counter register to get the command credits */
 929            address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
 930            /* read the counter using a 4-byte read.  Since the counter is NOT auto-decrementing,
 931             * we can read this counter multiple times using a non-incrementing address mode.
 932             * The rationale here is to make all HIF accesses a multiple of 4 bytes */
 933            status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
 934                HIF_RD_SYNC_BYTE_FIX, NULL);
 935            if (status) {
 936                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
 937                return A_ERROR;
 938            }
 939                /* we did a 4-byte read to the same count register so mask off upper bytes */
 940            (*pBMICmdCredits) &= 0xFF;
 941        }
 942
 943        if (!(*pBMICmdCredits)) {
 944            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
 945            return A_ERROR;
 946        }
 947    }
 948#endif
 949
 950    address = mboxAddress[ENDPOINT1];
 951    status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
 952    if (status) {
 953        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
 954        return A_ERROR;
 955    }
 956
 957    return 0;
 958}
 959
 960int
 961BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
 962{
 963    int status = A_ERROR;
 964    u32 lastWord = 0;
 965    u32 lastWordOffset = length & ~0x3;
 966    u32 unalignedBytes = length & 0x3;
 967
 968    status = BMILZStreamStart (device, address);
 969    if (status) {
 970            return A_ERROR;
 971    }
 972
 973    if (unalignedBytes) {
 974            /* copy the last word into a zero padded buffer */
 975        memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
 976    }
 977
 978    status = BMILZData(device, buffer, lastWordOffset);
 979
 980    if (status) {
 981        return A_ERROR;
 982    }
 983
 984    if (unalignedBytes) {
 985        status = BMILZData(device, (u8 *)&lastWord, 4);
 986    }
 987
 988    if (!status) {
 989        //
 990        // Close compressed stream and open a new (fake) one.  This serves mainly to flush Target caches.
 991        //
 992        status = BMILZStreamStart (device, 0x00);
 993        if (status) {
 994           return A_ERROR;
 995        }
 996    }
 997        return status;
 998}
 999
1000int
1001BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
1002{
1003    return bmiBufferSend(device, buffer, length);
1004}
1005
1006int
1007BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
1008{
1009    return bmiBufferReceive(device, buffer, length, want_timeout);
1010}
1011