linux/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
<<
>>
Prefs
   1//------------------------------------------------------------------------------
   2// <copyright file="ar6k_gmbox.c" company="Atheros">
   3//    Copyright (c) 2007-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// Generic MBOX API implementation
  22// 
  23// Author(s): ="Atheros"
  24//==============================================================================
  25#include "a_config.h"
  26#include "athdefs.h"
  27#include "a_types.h"
  28#include "a_osapi.h"
  29#include "../htc_debug.h"
  30#include "hif.h"
  31#include "htc_packet.h"
  32#include "ar6k.h"
  33#include "hw/mbox_host_reg.h"
  34#include "gmboxif.h"
  35
  36/* 
  37 * This file provides management functions and a toolbox for GMBOX protocol modules.  
  38 * Only one protocol module can be installed at a time. The determination of which protocol
  39 * module is installed is determined at compile time.  
  40 * 
  41 */
  42#ifdef ATH_AR6K_ENABLE_GMBOX
  43     /* GMBOX definitions */
  44#define GMBOX_INT_STATUS_ENABLE_REG     0x488
  45#define GMBOX_INT_STATUS_RX_DATA        (1 << 0)
  46#define GMBOX_INT_STATUS_TX_OVERFLOW    (1 << 1)
  47#define GMBOX_INT_STATUS_RX_OVERFLOW    (1 << 2)
  48
  49#define GMBOX_LOOKAHEAD_MUX_REG         0x498
  50#define GMBOX_LA_MUX_OVERRIDE_2_3       (1 << 0)
  51
  52#define AR6K_GMBOX_CREDIT_DEC_ADDRESS   (COUNT_DEC_ADDRESS + 4 * AR6K_GMBOX_CREDIT_COUNTER)
  53#define AR6K_GMBOX_CREDIT_SIZE_ADDRESS  (COUNT_ADDRESS     + AR6K_GMBOX_CREDIT_SIZE_COUNTER)
  54
  55
  56    /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */ 
  57extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
  58extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
  59
  60
  61/* callback when our fetch to enable/disable completes */
  62static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket)
  63{
  64    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
  65
  66    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
  67
  68    if (A_FAILED(pPacket->Status)) {
  69        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  70                ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status));
  71    }
  72        /* free this IO packet */
  73    AR6KFreeIOPacket(pDev,pPacket);
  74    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n"));
  75}
  76
  77static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
  78{
  79    A_STATUS                  status = A_OK;
  80    AR6K_IRQ_ENABLE_REGISTERS regs;
  81    HTC_PACKET                *pIOPacket = NULL;  
  82    
  83    LOCK_AR6K(pDev);
  84    
  85    if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
  86        pDev->GMboxInfo.CreditCountIRQEnabled = TRUE;
  87        pDev->IrqEnableRegisters.counter_int_status_enable |=
  88            COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER);
  89        pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01);
  90    } else {
  91        pDev->GMboxInfo.CreditCountIRQEnabled = FALSE;
  92        pDev->IrqEnableRegisters.counter_int_status_enable &=
  93            ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER));    
  94    }
  95        /* copy into our temp area */
  96    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
  97
  98    UNLOCK_AR6K(pDev);
  99
 100    do {
 101
 102        if (AsyncMode) {
 103
 104            pIOPacket = AR6KAllocIOPacket(pDev);
 105
 106            if (NULL == pIOPacket) {
 107                status = A_NO_MEMORY;
 108                A_ASSERT(FALSE);
 109                break;
 110            }
 111
 112                /* copy values to write to our async I/O buffer */
 113            A_MEMCPY(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 114
 115                /* stick in our completion routine when the I/O operation completes */
 116            pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
 117            pIOPacket->pContext = pDev;
 118            pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
 119                /* write it out asynchronously */
 120            HIFReadWrite(pDev->HIFDevice,
 121                         INT_STATUS_ENABLE_ADDRESS,
 122                         pIOPacket->pBuffer,
 123                         AR6K_IRQ_ENABLE_REGS_SIZE,
 124                         HIF_WR_ASYNC_BYTE_INC,
 125                         pIOPacket);
 126                         
 127            pIOPacket = NULL; 
 128            break;
 129        } 
 130
 131            /* if we get here we are doing it synchronously */
 132        status = HIFReadWrite(pDev->HIFDevice,
 133                              INT_STATUS_ENABLE_ADDRESS,
 134                              &regs.int_status_enable,
 135                              AR6K_IRQ_ENABLE_REGS_SIZE,
 136                              HIF_WR_SYNC_BYTE_INC,
 137                              NULL);    
 138    } while (FALSE);
 139    
 140    if (A_FAILED(status)) {
 141        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 142                (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
 143    } else {
 144        if (!AsyncMode) {
 145            AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
 146                    (" IRQAction Operation (%d) success \n", IrqAction)); 
 147        }       
 148    }
 149    
 150    if (pIOPacket != NULL) {
 151        AR6KFreeIOPacket(pDev,pIOPacket);
 152    }
 153        
 154    return status;
 155}
 156
 157
 158A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
 159{
 160    A_STATUS      status = A_OK;
 161    HTC_PACKET    *pIOPacket = NULL;   
 162    A_UINT8       GMboxIntControl[4];
 163
 164    if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
 165        return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode);
 166    } else if(GMBOX_CREDIT_IRQ_DISABLE == IrqAction) {
 167        return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);
 168    }
 169    
 170    if (GMBOX_DISABLE_ALL == IrqAction) {
 171            /* disable credit IRQ, those are on a different set of registers */
 172        DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);    
 173    }
 174            
 175        /* take the lock to protect interrupt enable shadows */
 176    LOCK_AR6K(pDev);
 177
 178    switch (IrqAction) {
 179        
 180        case GMBOX_DISABLE_ALL:
 181            pDev->GMboxControlRegisters.int_status_enable = 0;
 182            break;
 183        case GMBOX_ERRORS_IRQ_ENABLE:
 184            pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_TX_OVERFLOW |
 185                                                             GMBOX_INT_STATUS_RX_OVERFLOW;
 186            break;
 187        case GMBOX_RECV_IRQ_ENABLE:
 188            pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_RX_DATA;
 189            break;
 190        case GMBOX_RECV_IRQ_DISABLE:
 191            pDev->GMboxControlRegisters.int_status_enable &= ~GMBOX_INT_STATUS_RX_DATA;
 192            break;
 193        case GMBOX_ACTION_NONE:
 194        default:
 195            A_ASSERT(FALSE);    
 196            break;
 197    }
 198    
 199    GMboxIntControl[0] = pDev->GMboxControlRegisters.int_status_enable;
 200    GMboxIntControl[1] = GMboxIntControl[0];
 201    GMboxIntControl[2] = GMboxIntControl[0];
 202    GMboxIntControl[3] = GMboxIntControl[0];
 203    
 204    UNLOCK_AR6K(pDev);
 205
 206    do {
 207
 208        if (AsyncMode) {
 209
 210            pIOPacket = AR6KAllocIOPacket(pDev);
 211
 212            if (NULL == pIOPacket) {
 213                status = A_NO_MEMORY;
 214                A_ASSERT(FALSE);
 215                break;
 216            }
 217
 218                /* copy values to write to our async I/O buffer */
 219            A_MEMCPY(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
 220
 221                /* stick in our completion routine when the I/O operation completes */
 222            pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
 223            pIOPacket->pContext = pDev;
 224            pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
 225                /* write it out asynchronously */
 226            HIFReadWrite(pDev->HIFDevice,
 227                         GMBOX_INT_STATUS_ENABLE_REG,
 228                         pIOPacket->pBuffer,
 229                         sizeof(GMboxIntControl),
 230                         HIF_WR_ASYNC_BYTE_FIX,
 231                         pIOPacket);
 232            pIOPacket = NULL;
 233            break;
 234        }
 235
 236        /* if we get here we are doing it synchronously */
 237
 238        status = HIFReadWrite(pDev->HIFDevice,
 239                              GMBOX_INT_STATUS_ENABLE_REG,
 240                              GMboxIntControl,
 241                              sizeof(GMboxIntControl),
 242                              HIF_WR_SYNC_BYTE_FIX,
 243                              NULL);
 244
 245    } while (FALSE);
 246
 247    if (A_FAILED(status)) {
 248        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 249                (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
 250    } else {
 251        if (!AsyncMode) {
 252            AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
 253                    (" IRQAction Operation (%d) success \n", IrqAction)); 
 254        }      
 255    }
 256    
 257    if (pIOPacket != NULL) {
 258        AR6KFreeIOPacket(pDev,pIOPacket);
 259    }
 260
 261    return status;
 262}
 263
 264void DevCleanupGMbox(AR6K_DEVICE *pDev)
 265{
 266    if (pDev->GMboxEnabled) {
 267        pDev->GMboxEnabled = FALSE;
 268        GMboxProtocolUninstall(pDev);        
 269    }
 270}
 271
 272A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
 273{
 274    A_STATUS    status = A_OK;
 275    A_UINT8     muxControl[4];
 276    
 277    do {
 278        
 279        if (0 == pDev->MailBoxInfo.GMboxAddress) {
 280            break;    
 281        }
 282    
 283        AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n",
 284                    pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize));
 285                    
 286        status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
 287        
 288        if (A_FAILED(status)) {
 289            break;    
 290        }
 291       
 292            /* write to mailbox look ahead mux control register, we want the
 293             * GMBOX lookaheads to appear on lookaheads 2 and 3 
 294             * the register is 1-byte wide so we need to hit it 4 times to align the operation 
 295             * to 4-bytes */            
 296        muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3;
 297        muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3;
 298        muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3;
 299        muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3;
 300                
 301        status = HIFReadWrite(pDev->HIFDevice,
 302                              GMBOX_LOOKAHEAD_MUX_REG,
 303                              muxControl,
 304                              sizeof(muxControl),
 305                              HIF_WR_SYNC_BYTE_FIX,  /* hit this register 4 times */
 306                              NULL);
 307        
 308        if (A_FAILED(status)) {
 309            break;    
 310        }
 311        
 312        status = GMboxProtocolInstall(pDev);
 313        
 314        if (A_FAILED(status)) {
 315            break;    
 316        }
 317        
 318        pDev->GMboxEnabled = TRUE;
 319        
 320    } while (FALSE);
 321    
 322    return status;
 323}
 324
 325A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
 326{
 327    A_STATUS status = A_OK;
 328    A_UINT8  counter_int_status;
 329    int      credits;
 330    A_UINT8  host_int_status2;
 331    
 332    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n"));
 333     
 334    /* the caller guarantees that this is a context that allows for blocking I/O */
 335    
 336    do {
 337        
 338        host_int_status2 = pDev->IrqProcRegisters.host_int_status2 &
 339                           pDev->GMboxControlRegisters.int_status_enable; 
 340                
 341        if (host_int_status2 & GMBOX_INT_STATUS_TX_OVERFLOW) {
 342            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : TX Overflow \n"));  
 343            status = A_ECOMM;   
 344        }
 345        
 346        if (host_int_status2 & GMBOX_INT_STATUS_RX_OVERFLOW) {
 347            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : RX Overflow \n"));  
 348            status = A_ECOMM;    
 349        }
 350        
 351        if (A_FAILED(status)) {
 352            if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
 353                pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status);        
 354            }
 355            break;
 356        }
 357    
 358        if (host_int_status2 & GMBOX_INT_STATUS_RX_DATA) {
 359            if (pDev->IrqProcRegisters.gmbox_rx_avail > 0) {
 360                A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL);
 361                status = pDev->GMboxInfo.pMessagePendingCallBack(
 362                                pDev->GMboxInfo.pProtocolContext,
 363                                (A_UINT8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
 364                                pDev->IrqProcRegisters.gmbox_rx_avail);
 365            }
 366        } 
 367        
 368        if (A_FAILED(status)) {
 369           break;                
 370        }
 371        
 372        counter_int_status = pDev->IrqProcRegisters.counter_int_status &
 373                             pDev->IrqEnableRegisters.counter_int_status_enable;
 374    
 375            /* check if credit interrupt is pending */
 376        if (counter_int_status & (COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER))) {
 377            
 378                /* do synchronous read */
 379            status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits);
 380            
 381            if (A_FAILED(status)) {
 382                break;    
 383            }
 384            
 385            A_ASSERT(pDev->GMboxInfo.pCreditsPendingCallback != NULL);
 386            status = pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
 387                                                             credits,
 388                                                             pDev->GMboxInfo.CreditCountIRQEnabled);
 389        }
 390        
 391    } while (FALSE);
 392    
 393    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status));
 394    
 395    return status;
 396}
 397
 398
 399A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength) 
 400{
 401    A_UINT32 paddedLength;
 402    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
 403    A_STATUS status;
 404    A_UINT32 address;
 405    
 406       /* adjust the length to be a multiple of block size if appropriate */
 407    paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength);
 408    
 409    AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
 410                ("DevGMboxWrite, Padded Length: %d Mbox:0x%X (mode:%s)\n",
 411                WriteLength,
 412                pDev->MailBoxInfo.GMboxAddress,
 413                sync ? "SYNC" : "ASYNC"));
 414                
 415        /* last byte of packet has to hit the EOM marker */
 416    address = pDev->MailBoxInfo.GMboxAddress + pDev->MailBoxInfo.GMboxSize - paddedLength;
 417    
 418    status = HIFReadWrite(pDev->HIFDevice,
 419                          address,
 420                          pPacket->pBuffer,
 421                          paddedLength,     /* the padded length */
 422                          sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
 423                          sync ? NULL : pPacket);  /* pass the packet as the context to the HIF request */
 424
 425    if (sync) {
 426        pPacket->Status = status;
 427    } else {
 428        if (status == A_PENDING) {
 429            status = A_OK;    
 430        }    
 431    }
 432
 433    return status;
 434}
 435
 436A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength) 
 437{
 438    
 439    A_UINT32 paddedLength;
 440    A_STATUS status;
 441    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
 442
 443        /* adjust the length to be a multiple of block size if appropriate */
 444    paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength);
 445                    
 446    if (paddedLength > pPacket->BufferLength) {
 447        A_ASSERT(FALSE);
 448        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 449                ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
 450                    paddedLength,ReadLength,pPacket->BufferLength));
 451        if (pPacket->Completion != NULL) {
 452            COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
 453            return A_OK;
 454        }
 455        return A_EINVAL;
 456    }
 457
 458    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
 459                ("DevGMboxRead (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
 460                (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
 461                paddedLength,
 462                pDev->MailBoxInfo.GMboxAddress,
 463                sync ? "SYNC" : "ASYNC"));
 464
 465    status = HIFReadWrite(pDev->HIFDevice,
 466                          pDev->MailBoxInfo.GMboxAddress,
 467                          pPacket->pBuffer,
 468                          paddedLength,
 469                          sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
 470                          sync ? NULL : pPacket);  /* pass the packet as the context to the HIF request */
 471
 472    if (sync) {
 473        pPacket->Status = status;
 474    }
 475
 476    return status;
 477}
 478
 479
 480static int ProcessCreditCounterReadBuffer(A_UINT8 *pBuffer, int Length)
 481{
 482    int     credits = 0;
 483    
 484    /* theory of how this works:
 485     * We read the credit decrement register multiple times on a byte-wide basis. 
 486     * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a 
 487     * reasonable chance to acquire "all" pending credits in a single I/O operation. 
 488     * 
 489     * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions.
 490     * Each non-zero byte represents a single credit decrement (which is a credit given back to the host)
 491     * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following
 492     * pattern "could" appear:
 493     * 
 494     *    0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros
 495     *    <--------->                     <----------------------------->
 496     *         \_ credits aleady there              \_ target adding 4 more credits
 497     * 
 498     *    The total available credits would be 7, since there are 7 non-zero bytes in the buffer.
 499     * 
 500     * */
 501    
 502    if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
 503        DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer");
 504    } 
 505        
 506    while (Length) {
 507        if (*pBuffer != 0) {
 508            credits++;    
 509        }
 510        Length--;
 511        pBuffer++;   
 512    }  
 513    
 514    return credits;
 515}
 516   
 517
 518/* callback when our fetch to enable/disable completes */
 519static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket)
 520{
 521    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
 522
 523    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 524
 525    if (A_FAILED(pPacket->Status)) {
 526        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 527                ("Read Credit Operation failed! status:%d \n", pPacket->Status));
 528    } else {
 529        int credits = 0;
 530        credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);
 531        pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
 532                                                credits,
 533                                                pDev->GMboxInfo.CreditCountIRQEnabled);
 534        
 535        
 536    }
 537        /* free this IO packet */
 538    AR6KFreeIOPacket(pDev,pPacket);
 539    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n"));
 540}
 541
 542A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits)
 543{
 544    A_STATUS    status = A_OK;
 545    HTC_PACKET  *pIOPacket = NULL;  
 546    
 547    AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC"));
 548                                            
 549    do {
 550        
 551        pIOPacket = AR6KAllocIOPacket(pDev);
 552
 553        if (NULL == pIOPacket) {
 554            status = A_NO_MEMORY;
 555            A_ASSERT(FALSE);
 556            break;
 557        }
 558        
 559        A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE);
 560      
 561        if (AsyncMode) {   
 562                /* stick in our completion routine when the I/O operation completes */
 563            pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler;
 564            pIOPacket->pContext = pDev;
 565                /* read registers asynchronously */
 566            HIFReadWrite(pDev->HIFDevice,
 567                         AR6K_GMBOX_CREDIT_DEC_ADDRESS,
 568                         pIOPacket->pBuffer,
 569                         AR6K_REG_IO_BUFFER_SIZE,  /* hit the register multiple times */
 570                         HIF_RD_ASYNC_BYTE_FIX,
 571                         pIOPacket);
 572            pIOPacket = NULL;
 573            break;
 574        } 
 575
 576        pIOPacket->Completion = NULL;
 577            /* if we get here we are doing it synchronously */
 578        status = HIFReadWrite(pDev->HIFDevice,
 579                              AR6K_GMBOX_CREDIT_DEC_ADDRESS,
 580                              pIOPacket->pBuffer,
 581                              AR6K_REG_IO_BUFFER_SIZE,
 582                              HIF_RD_SYNC_BYTE_FIX,
 583                              NULL);    
 584    } while (FALSE);
 585    
 586    if (A_FAILED(status)) {
 587        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 588                (" DevGMboxReadCreditCounter failed! status:%d \n", status));          
 589    }
 590    
 591    if (pIOPacket != NULL) {
 592        if (A_SUCCESS(status)) {
 593                /* sync mode processing */
 594            *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);     
 595        }
 596        AR6KFreeIOPacket(pDev,pIOPacket);
 597    }
 598    
 599    AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n", 
 600            AsyncMode ? "ASYNC" : "SYNC", status));
 601    
 602    return status;
 603}
 604
 605A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
 606{
 607    A_STATUS    status;
 608    A_UINT8     buffer[4];
 609       
 610    status = HIFReadWrite(pDev->HIFDevice,
 611                          AR6K_GMBOX_CREDIT_SIZE_ADDRESS,
 612                          buffer,
 613                          sizeof(buffer),
 614                          HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
 615                          NULL);    
 616    
 617    if (A_SUCCESS(status)) {
 618        if (buffer[0] == 0) {
 619            *pCreditSize = 256;    
 620        } else {   
 621            *pCreditSize = buffer[0];
 622        } 
 623           
 624    } 
 625    
 626    return status;
 627}
 628
 629void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev)
 630{
 631        /* Target ASSERTED!!! */
 632    if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
 633        pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, A_HARDWARE);        
 634    }
 635}
 636
 637A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes)
 638{
 639
 640    A_STATUS                    status = A_OK;
 641    AR6K_IRQ_PROC_REGISTERS     procRegs;
 642    int                         maxCopy;
 643  
 644    do {
 645            /* on entry the caller provides the length of the lookahead buffer */
 646        if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) {
 647            A_ASSERT(FALSE);
 648            status = A_EINVAL;
 649            break;    
 650        }
 651        
 652        maxCopy = *pLookAheadBytes;
 653        *pLookAheadBytes = 0;
 654            /* load the register table from the device */
 655        status = HIFReadWrite(pDev->HIFDevice,
 656                              HOST_INT_STATUS_ADDRESS,
 657                              (A_UINT8 *)&procRegs,
 658                              AR6K_IRQ_PROC_REGS_SIZE,
 659                              HIF_RD_SYNC_BYTE_INC,
 660                              NULL);
 661
 662        if (A_FAILED(status)) {
 663            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 664                ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status));
 665            break;
 666        }
 667        
 668        if (procRegs.gmbox_rx_avail > 0) {
 669            int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail;
 670            A_MEMCPY(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
 671            *pLookAheadBytes = bytes;
 672        }
 673        
 674    } while (FALSE);
 675       
 676    return status; 
 677}
 678
 679A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeoutMS)
 680{
 681    A_STATUS status = A_OK;
 682    int      i;
 683    A_UINT8  buffer[4];
 684    
 685    A_MEMZERO(buffer, sizeof(buffer));
 686    
 687    do {
 688        
 689        if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) {
 690            status = A_EINVAL;
 691            break;    
 692        }
 693        
 694            /* set the last buffer to do the actual signal trigger */
 695        buffer[3] = (1 << Signal);
 696        
 697        status = HIFReadWrite(pDev->HIFDevice,
 698                              INT_WLAN_ADDRESS,
 699                              buffer,
 700                              sizeof(buffer),
 701                              HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
 702                              NULL);    
 703                          
 704        if (A_FAILED(status)) {
 705            break;    
 706        }
 707        
 708    } while (FALSE);
 709    
 710    
 711    if (A_SUCCESS(status)) {        
 712            /* now read back the register to see if the bit cleared */
 713        while (AckTimeoutMS) {        
 714            status = HIFReadWrite(pDev->HIFDevice,
 715                                  INT_WLAN_ADDRESS,
 716                                  buffer,
 717                                  sizeof(buffer),
 718                                  HIF_RD_SYNC_BYTE_FIX,
 719                                  NULL);    
 720                          
 721            if (A_FAILED(status)) {
 722                break;    
 723            }
 724                            
 725            for (i = 0; i < sizeof(buffer); i++) {
 726                if (buffer[i] & (1 << Signal)) {
 727                    /* bit is still set */
 728                    break;    
 729                }   
 730            }
 731            
 732            if (i >= sizeof(buffer)) {
 733                /* done */
 734                break;    
 735            }
 736            
 737            AckTimeoutMS--;
 738            A_MDELAY(1);  
 739        }
 740        
 741        if (0 == AckTimeoutMS) {
 742            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 743                ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal));
 744            status = A_ERROR;    
 745        }        
 746    }
 747    
 748    return status;
 749    
 750}
 751
 752#endif  //ATH_AR6K_ENABLE_GMBOX
 753
 754
 755
 756
 757