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"
  46typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS {
  47    A_UINT8                      host_int_status;
  48    A_UINT8                      cpu_int_status;
  49    A_UINT8                      error_int_status;
  50    A_UINT8                      counter_int_status;
  51    A_UINT8                      mbox_frame;
  52    A_UINT8                      rx_lookahead_valid;
  53    A_UINT8                      host_int_status2;
  54    A_UINT8                      gmbox_rx_avail;
  55    A_UINT32                     rx_lookahead[2];
  56    A_UINT32                     rx_gmbox_lookahead_alias[2];
  57} POSTPACK AR6K_IRQ_PROC_REGISTERS;
  58
  59#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
  60
  61typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS {
  62    A_UINT8                      int_status_enable;
  63    A_UINT8                      cpu_int_status_enable;
  64    A_UINT8                      error_status_enable;
  65    A_UINT8                      counter_int_status_enable;
  66} POSTPACK AR6K_IRQ_ENABLE_REGISTERS;
  67
  68typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS {
  69    A_UINT8                      int_status_enable;
  70} POSTPACK AR6K_GMBOX_CTRL_REGISTERS;
  71
  72#include "athendpack.h"
  73
  74#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(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 */
  92typedef struct AR6K_ASYNC_REG_IO_BUFFER {
  93    HTC_PACKET    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
  94    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
  95    A_UINT8       Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
  96    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
  97} AR6K_ASYNC_REG_IO_BUFFER;
  98
  99typedef struct _AR6K_GMBOX_INFO { 
 100    void        *pProtocolContext;
 101    A_STATUS    (*pMessagePendingCallBack)(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes);
 102    A_STATUS    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  A_BOOL CreditIRQEnabled);
 103    void        (*pTargetFailureCallback)(void *pContext, A_STATUS Status);
 104    void        (*pStateDumpCallback)(void *pContext);
 105    A_BOOL      CreditCountIRQEnabled;    
 106} AR6K_GMBOX_INFO; 
 107
 108typedef struct _AR6K_DEVICE {
 109    A_MUTEX_T                   Lock;
 110    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
 111    AR6K_IRQ_PROC_REGISTERS     IrqProcRegisters;   /* cache-line safe with pads around */
 112    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
 113    AR6K_IRQ_ENABLE_REGISTERS   IrqEnableRegisters; /* cache-line safe with pads around */
 114    A_UINT8       _Pad3[A_CACHE_LINE_PAD];
 115    void                        *HIFDevice;
 116    A_UINT32                    BlockSize;
 117    A_UINT32                    BlockMask;
 118    HIF_DEVICE_MBOX_INFO        MailBoxInfo;
 119    HIF_PENDING_EVENTS_FUNC     GetPendingEventsFunc;
 120    void                        *HTCContext;
 121    HTC_PACKET_QUEUE            RegisterIOList;
 122    AR6K_ASYNC_REG_IO_BUFFER    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
 123    void                        (*TargetFailureCallback)(void *Context);
 124    A_STATUS                    (*MessagePendingCallback)(void *Context, 
 125                                                          A_UINT32 LookAheads[], 
 126                                                          int NumLookAheads, 
 127                                                          A_BOOL *pAsyncProc,
 128                                                          int *pNumPktsFetched);
 129    HIF_DEVICE_IRQ_PROCESSING_MODE  HifIRQProcessingMode;
 130    HIF_MASK_UNMASK_RECV_EVENT      HifMaskUmaskRecvEvent;
 131    A_BOOL                          HifAttached;
 132    HIF_DEVICE_IRQ_YIELD_PARAMS     HifIRQYieldParams;
 133    A_BOOL                          DSRCanYield;
 134    int                             CurrentDSRRecvCount;
 135    HIF_DEVICE_SCATTER_SUPPORT_INFO HifScatterInfo;
 136    DL_LIST                         ScatterReqHead; 
 137    A_BOOL                          ScatterIsVirtual;    
 138    int                             MaxRecvBundleSize;
 139    int                             MaxSendBundleSize;
 140    AR6K_GMBOX_INFO                 GMboxInfo;
 141    A_BOOL                          GMboxEnabled; 
 142    AR6K_GMBOX_CTRL_REGISTERS       GMboxControlRegisters;
 143    int                             RecheckIRQStatusCnt;
 144} AR6K_DEVICE;
 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
 150A_STATUS DevSetup(AR6K_DEVICE *pDev);
 151void     DevCleanup(AR6K_DEVICE *pDev);
 152A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev);
 153A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev);
 154A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
 155                            A_UINT32    *pLookAhead,
 156                            int          TimeoutMS);
 157A_STATUS DevRWCompletionHandler(void *context, A_STATUS status);
 158A_STATUS DevDsrHandler(void *context);
 159A_STATUS DevCheckPendingRecvMsgsAsync(void *context);
 160void     DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev);
 161void     DevDumpRegisters(AR6K_DEVICE               *pDev,
 162                          AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
 163                          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
 169A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
 170A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
 171A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
 172A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
 173A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_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 A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) {
 180    A_UINT32 paddedLength;
 181    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
 182    A_STATUS 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 A_OK;
 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 = A_OK;    
 216        }    
 217    }
 218
 219    return status;
 220}
 221                    
 222static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
 223    A_UINT32 paddedLength;
 224    A_STATUS status;
 225    A_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 A_OK;
 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  
 275A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA);
 276    
 277    /* copy any READ data back into scatter list */        
 278#define DEV_FINISH_SCATTER_OPERATION(pR)                      \
 279    if (A_SUCCESS((pR)->CompletionStatus) &&                  \
 280        !((pR)->Request & HIF_WRITE) &&                       \
 281         ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {   \
 282         (pR)->CompletionStatus = DevCopyScatterListToFromDMABuffer((pR),FROM_DMA_BUFFER); \
 283    }
 284    
 285    /* copy any WRITE data to bounce buffer */
 286static INLINE A_STATUS DEV_PREPARE_SCATTER_OPERATION(HIF_SCATTER_REQ *pReq)  { 
 287    if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
 288        return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);    
 289    } else {
 290        return A_OK;    
 291    }
 292}
 293        
 294    
 295A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer);
 296                                  
 297#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev)        (pDev)->HifScatterInfo.MaxScatterEntries
 298#define DEV_GET_MAX_BUNDLE_LENGTH(pDev)         (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
 299#define DEV_ALLOC_SCATTER_REQ(pDev)             \
 300    (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice)
 301    
 302#define DEV_FREE_SCATTER_REQ(pDev,pR)           \
 303    (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
 304
 305#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)   (pDev)->MaxRecvBundleSize
 306#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)   (pDev)->MaxSendBundleSize
 307
 308#define DEV_SCATTER_READ  TRUE
 309#define DEV_SCATTER_WRITE FALSE
 310#define DEV_SCATTER_ASYNC TRUE
 311#define DEV_SCATTER_SYNC  FALSE
 312A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async);
 313
 314#ifdef MBOXHW_UNIT_TEST
 315A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
 316#endif
 317
 318    /* completely virtual */
 319typedef struct _DEV_SCATTER_DMA_VIRTUAL_INFO {
 320    A_UINT8            *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
 321    A_UINT8            DataArea[1];      /* start of data area */
 322} DEV_SCATTER_DMA_VIRTUAL_INFO;
 323
 324
 325
 326void     DumpAR6KDevState(AR6K_DEVICE *pDev);
 327
 328/**************************************************/
 329/****** GMBOX functions and definitions
 330 * 
 331 *  
 332 */
 333
 334#ifdef ATH_AR6K_ENABLE_GMBOX
 335
 336void     DevCleanupGMbox(AR6K_DEVICE *pDev);
 337A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev);
 338A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev);
 339void     DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev);
 340
 341#else
 342
 343    /* compiled out */
 344#define DevCleanupGMbox(p)
 345#define DevCheckGMboxInterrupts(p) A_OK
 346#define DevNotifyGMboxTargetFailure(p)
 347
 348static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) {
 349    pDev->GMboxEnabled = FALSE;
 350    return A_OK;    
 351}
 352
 353#endif
 354
 355#ifdef ATH_AR6K_ENABLE_GMBOX
 356
 357    /* GMBOX protocol modules must expose each of these internal APIs */
 358HCI_TRANSPORT_HANDLE GMboxAttachProtocol(AR6K_DEVICE *pDev, HCI_TRANSPORT_CONFIG_INFO *pInfo);
 359A_STATUS             GMboxProtocolInstall(AR6K_DEVICE *pDev);
 360void                 GMboxProtocolUninstall(AR6K_DEVICE *pDev);
 361
 362    /* API used by GMBOX protocol modules */
 363AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle);
 364#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
 365{                                                                  \
 366    (pDev)->GMboxInfo.pProtocolContext = (context);                \
 367    (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback);   \
 368    (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \
 369    (pDev)->GMboxInfo.pTargetFailureCallback = (failure);          \
 370    (pDev)->GMboxInfo.pStateDumpCallback = (statedump);            \
 371}
 372
 373#define DEV_GMBOX_GET_PROTOCOL(pDev)  (pDev)->GMboxInfo.pProtocolContext
 374
 375A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength);
 376A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength);
 377
 378#define PROC_IO_ASYNC TRUE
 379#define PROC_IO_SYNC  FALSE
 380typedef enum GMBOX_IRQ_ACTION_TYPE {
 381    GMBOX_ACTION_NONE = 0,
 382    GMBOX_DISABLE_ALL,
 383    GMBOX_ERRORS_IRQ_ENABLE,
 384    GMBOX_RECV_IRQ_ENABLE,
 385    GMBOX_RECV_IRQ_DISABLE,
 386    GMBOX_CREDIT_IRQ_ENABLE,
 387    GMBOX_CREDIT_IRQ_DISABLE,
 388} GMBOX_IRQ_ACTION_TYPE;
 389
 390A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE, A_BOOL AsyncMode);
 391A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits);
 392A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize);
 393A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes);
 394A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int SignalNumber, int AckTimeoutMS);
 395
 396#endif
 397
 398#endif /*AR6K_H_*/
 399