linux/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
<<
>>
Prefs
   1//------------------------------------------------------------------------------
   2// <copyright file="ar6k.h" 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// AR6K device layer that handles register level I/O
  22//
  23// Author(s): ="Atheros"
  24//==============================================================================
  25#ifndef AR6K_H_
  26#define AR6K_H_
  27
  28#include "hci_transport_api.h"
  29#include "../htc_debug.h"
  30
  31#define AR6K_MAILBOXES 4
  32
  33/* HTC runs over mailbox 0 */
  34#define HTC_MAILBOX          0
  35
  36#define AR6K_TARGET_DEBUG_INTR_MASK     0x01
  37
  38#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK |   \
  39                            INT_STATUS_ENABLE_CPU_MASK   |   \
  40                            INT_STATUS_ENABLE_COUNTER_MASK)
  41
  42
  43//#define MBOXHW_UNIT_TEST 1
  44
  45#include "athstartpack.h"
  46PREPACK struct ar6k_irq_proc_registers {
  47    u8 host_int_status;
  48    u8 cpu_int_status;
  49    u8 error_int_status;
  50    u8 counter_int_status;
  51    u8 mbox_frame;
  52    u8 rx_lookahead_valid;
  53    u8 host_int_status2;
  54    u8 gmbox_rx_avail;
  55    u32 rx_lookahead[2];
  56    u32 rx_gmbox_lookahead_alias[2];
  57} POSTPACK;
  58
  59#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers)
  60
  61PREPACK struct ar6k_irq_enable_registers {
  62    u8 int_status_enable;
  63    u8 cpu_int_status_enable;
  64    u8 error_status_enable;
  65    u8 counter_int_status_enable;
  66} POSTPACK;
  67
  68PREPACK struct ar6k_gmbox_ctrl_registers {
  69    u8 int_status_enable;
  70} POSTPACK;
  71
  72#include "athendpack.h"
  73
  74#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers)
  75
  76#define AR6K_REG_IO_BUFFER_SIZE     32
  77#define AR6K_MAX_REG_IO_BUFFERS     8
  78#define FROM_DMA_BUFFER true
  79#define TO_DMA_BUFFER   false
  80#define AR6K_SCATTER_ENTRIES_PER_REQ            16
  81#define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER      16*1024
  82#define AR6K_SCATTER_REQS                       4
  83#define AR6K_LEGACY_MAX_WRITE_LENGTH            2048
  84
  85#ifndef A_CACHE_LINE_PAD
  86#define A_CACHE_LINE_PAD                        128
  87#endif
  88#define AR6K_MIN_SCATTER_ENTRIES_PER_REQ        2
  89#define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER      4*1024
  90
  91/* buffers for ASYNC I/O */
  92struct ar6k_async_reg_io_buffer {
  93    struct htc_packet    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
  94    u8 _Pad1[A_CACHE_LINE_PAD];
  95    u8 Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
  96    u8 _Pad2[A_CACHE_LINE_PAD];
  97};
  98
  99struct ar6k_gmbox_info { 
 100    void        *pProtocolContext;
 101    int    (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes);
 102    int    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  bool CreditIRQEnabled);
 103    void        (*pTargetFailureCallback)(void *pContext, int Status);
 104    void        (*pStateDumpCallback)(void *pContext);
 105    bool      CreditCountIRQEnabled;
 106}; 
 107
 108struct ar6k_device {
 109    A_MUTEX_T                   Lock;
 110    u8 _Pad1[A_CACHE_LINE_PAD];
 111    struct ar6k_irq_proc_registers     IrqProcRegisters;   /* cache-line safe with pads around */
 112    u8 _Pad2[A_CACHE_LINE_PAD];
 113    struct ar6k_irq_enable_registers   IrqEnableRegisters; /* cache-line safe with pads around */
 114    u8 _Pad3[A_CACHE_LINE_PAD];
 115    void                        *HIFDevice;
 116    u32 BlockSize;
 117    u32 BlockMask;
 118    struct hif_device_mbox_info        MailBoxInfo;
 119    HIF_PENDING_EVENTS_FUNC     GetPendingEventsFunc;
 120    void                        *HTCContext;
 121    struct htc_packet_queue            RegisterIOList;
 122    struct ar6k_async_reg_io_buffer    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
 123    void                        (*TargetFailureCallback)(void *Context);
 124    int                    (*MessagePendingCallback)(void *Context,
 125                                                          u32 LookAheads[],
 126                                                          int NumLookAheads, 
 127                                                          bool *pAsyncProc,
 128                                                          int *pNumPktsFetched);
 129    HIF_DEVICE_IRQ_PROCESSING_MODE  HifIRQProcessingMode;
 130    HIF_MASK_UNMASK_RECV_EVENT      HifMaskUmaskRecvEvent;
 131    bool                          HifAttached;
 132    struct hif_device_irq_yield_params     HifIRQYieldParams;
 133    bool                          DSRCanYield;
 134    int                             CurrentDSRRecvCount;
 135    struct hif_device_scatter_support_info HifScatterInfo;
 136    struct dl_list                         ScatterReqHead; 
 137    bool                          ScatterIsVirtual;
 138    int                             MaxRecvBundleSize;
 139    int                             MaxSendBundleSize;
 140    struct ar6k_gmbox_info                 GMboxInfo;
 141    bool                          GMboxEnabled;
 142    struct ar6k_gmbox_ctrl_registers       GMboxControlRegisters;
 143    int                             RecheckIRQStatusCnt;
 144};
 145
 146#define LOCK_AR6K(p)      A_MUTEX_LOCK(&(p)->Lock);
 147#define UNLOCK_AR6K(p)    A_MUTEX_UNLOCK(&(p)->Lock);
 148#define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1  /* note: no need to lock this, it only gets set */
 149
 150int DevSetup(struct ar6k_device *pDev);
 151void     DevCleanup(struct ar6k_device *pDev);
 152int DevUnmaskInterrupts(struct ar6k_device *pDev);
 153int DevMaskInterrupts(struct ar6k_device *pDev);
 154int DevPollMboxMsgRecv(struct ar6k_device *pDev,
 155                            u32 *pLookAhead,
 156                            int          TimeoutMS);
 157int DevRWCompletionHandler(void *context, int status);
 158int DevDsrHandler(void *context);
 159int DevCheckPendingRecvMsgsAsync(void *context);
 160void     DevAsyncIrqProcessComplete(struct ar6k_device *pDev);
 161void     DevDumpRegisters(struct ar6k_device               *pDev,
 162                          struct ar6k_irq_proc_registers   *pIrqProcRegs,
 163                          struct ar6k_irq_enable_registers *pIrqEnableRegs);
 164
 165#define DEV_STOP_RECV_ASYNC true
 166#define DEV_STOP_RECV_SYNC  false
 167#define DEV_ENABLE_RECV_ASYNC true
 168#define DEV_ENABLE_RECV_SYNC  false
 169int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode);
 170int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode);
 171int DevEnableInterrupts(struct ar6k_device *pDev);
 172int DevDisableInterrupts(struct ar6k_device *pDev);
 173int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending);
 174
 175#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
 176#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
 177#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
 178
 179static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) {
 180    u32 paddedLength;
 181    bool   sync = (pPacket->Completion == NULL) ? true : false;
 182    int status;
 183
 184       /* adjust the length to be a multiple of block size if appropriate */
 185    paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
 186
 187#if 0                    
 188    if (paddedLength > pPacket->BufferLength) {
 189        A_ASSERT(false);
 190        if (pPacket->Completion != NULL) {
 191            COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
 192            return 0;
 193        }
 194        return A_EINVAL;
 195    }
 196#endif
 197    
 198    AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
 199                ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
 200                paddedLength,
 201                pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
 202                sync ? "SYNC" : "ASYNC"));
 203
 204    status = HIFReadWrite(pDev->HIFDevice,
 205                          pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
 206                          pPacket->pBuffer,
 207                          paddedLength,     /* the padded length */
 208                          sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
 209                          sync ? NULL : pPacket);  /* pass the packet as the context to the HIF request */
 210
 211    if (sync) {
 212        pPacket->Status = status;
 213    } else {
 214        if (status == A_PENDING) {
 215            status = 0;
 216        }    
 217    }
 218
 219    return status;
 220}
 221                    
 222static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) {
 223    u32 paddedLength;
 224    int status;
 225    bool   sync = (pPacket->Completion == NULL) ? true : false;
 226
 227        /* adjust the length to be a multiple of block size if appropriate */
 228    paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
 229                    
 230    if (paddedLength > pPacket->BufferLength) {
 231        A_ASSERT(false);
 232        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
 233                ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
 234                    paddedLength,RecvLength,pPacket->BufferLength));
 235        if (pPacket->Completion != NULL) {
 236            COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
 237            return 0;
 238        }
 239        return A_EINVAL;
 240    }
 241
 242    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
 243                ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
 244                (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
 245                paddedLength,
 246                pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
 247                sync ? "SYNC" : "ASYNC"));
 248
 249    status = HIFReadWrite(pDev->HIFDevice,
 250                          pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
 251                          pPacket->pBuffer,
 252                          paddedLength,
 253                          sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
 254                          sync ? NULL : pPacket);  /* pass the packet as the context to the HIF request */
 255
 256    if (sync) {
 257        pPacket->Status = status;
 258    }
 259
 260    return status;
 261}
 262
 263#define DEV_CHECK_RECV_YIELD(pDev) \
 264            ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount)
 265            
 266#define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode)
 267#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
 268
 269/**************************************************/
 270/****** Scatter Function and Definitions
 271 * 
 272 *  
 273 */
 274  
 275int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA);
 276    
 277    /* copy any READ data back into scatter list */        
 278#define DEV_FINISH_SCATTER_OPERATION(pR)                                \
 279do {                                                                    \
 280        if (!((pR)->CompletionStatus) &&                                \
 281            !((pR)->Request & HIF_WRITE) &&                             \
 282            ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {          \
 283                (pR)->CompletionStatus =                                \
 284                        DevCopyScatterListToFromDMABuffer((pR),         \
 285                                                          FROM_DMA_BUFFER); \
 286        }                                                               \
 287} while (0)
 288    
 289    /* copy any WRITE data to bounce buffer */
 290static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq)  {
 291    if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
 292        return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);    
 293    } else {
 294        return 0;
 295    }
 296}
 297        
 298    
 299int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer);
 300
 301int DevCleanupMsgBundling(struct ar6k_device *pDev);
 302                                  
 303#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev)        (pDev)->HifScatterInfo.MaxScatterEntries
 304#define DEV_GET_MAX_BUNDLE_LENGTH(pDev)         (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
 305#define DEV_ALLOC_SCATTER_REQ(pDev)             \
 306    (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice)
 307    
 308#define DEV_FREE_SCATTER_REQ(pDev,pR)           \
 309    (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
 310
 311#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)   (pDev)->MaxRecvBundleSize
 312#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)   (pDev)->MaxSendBundleSize
 313
 314#define DEV_SCATTER_READ  true
 315#define DEV_SCATTER_WRITE false
 316#define DEV_SCATTER_ASYNC true
 317#define DEV_SCATTER_SYNC  false
 318int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async);
 319
 320#ifdef MBOXHW_UNIT_TEST
 321int DoMboxHWTest(struct ar6k_device *pDev);
 322#endif
 323
 324    /* completely virtual */
 325struct dev_scatter_dma_virtual_info {
 326    u8 *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
 327    u8 DataArea[1];      /* start of data area */
 328};
 329
 330
 331
 332void     DumpAR6KDevState(struct ar6k_device *pDev);
 333
 334/**************************************************/
 335/****** GMBOX functions and definitions
 336 * 
 337 *  
 338 */
 339
 340#ifdef ATH_AR6K_ENABLE_GMBOX
 341
 342void     DevCleanupGMbox(struct ar6k_device *pDev);
 343int DevSetupGMbox(struct ar6k_device *pDev);
 344int DevCheckGMboxInterrupts(struct ar6k_device *pDev);
 345void     DevNotifyGMboxTargetFailure(struct ar6k_device *pDev);
 346
 347#else
 348
 349    /* compiled out */
 350#define DevCleanupGMbox(p)
 351#define DevCheckGMboxInterrupts(p) 0
 352#define DevNotifyGMboxTargetFailure(p)
 353
 354static INLINE int DevSetupGMbox(struct ar6k_device *pDev) {
 355    pDev->GMboxEnabled = false;
 356    return 0;
 357}
 358
 359#endif
 360
 361#ifdef ATH_AR6K_ENABLE_GMBOX
 362
 363    /* GMBOX protocol modules must expose each of these internal APIs */
 364HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo);
 365int             GMboxProtocolInstall(struct ar6k_device *pDev);
 366void                 GMboxProtocolUninstall(struct ar6k_device *pDev);
 367
 368    /* API used by GMBOX protocol modules */
 369struct ar6k_device  *HTCGetAR6KDevice(void *HTCHandle);
 370#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
 371{                                                                  \
 372    (pDev)->GMboxInfo.pProtocolContext = (context);                \
 373    (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback);   \
 374    (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \
 375    (pDev)->GMboxInfo.pTargetFailureCallback = (failure);          \
 376    (pDev)->GMboxInfo.pStateDumpCallback = (statedump);            \
 377}
 378
 379#define DEV_GMBOX_GET_PROTOCOL(pDev)  (pDev)->GMboxInfo.pProtocolContext
 380
 381int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength);
 382int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength);
 383
 384#define PROC_IO_ASYNC true
 385#define PROC_IO_SYNC  false
 386typedef enum GMBOX_IRQ_ACTION_TYPE {
 387    GMBOX_ACTION_NONE = 0,
 388    GMBOX_DISABLE_ALL,
 389    GMBOX_ERRORS_IRQ_ENABLE,
 390    GMBOX_RECV_IRQ_ENABLE,
 391    GMBOX_RECV_IRQ_DISABLE,
 392    GMBOX_CREDIT_IRQ_ENABLE,
 393    GMBOX_CREDIT_IRQ_DISABLE,
 394} GMBOX_IRQ_ACTION_TYPE;
 395
 396int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode);
 397int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits);
 398int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize);
 399int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes);
 400int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS);
 401
 402#endif
 403
 404#endif /*AR6K_H_*/
 405