1 //------------------------------------------------------------------------------
2 // <copyright file="ar6k.h" company="Atheros">
3 // Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
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.
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.
19 //------------------------------------------------------------------------------
20 //==============================================================================
21 // AR6K device layer that handles register level I/O
23 // Author(s): ="Atheros"
24 //==============================================================================
28 #include "hci_transport_api.h"
29 #include "../htc_debug.h"
31 #define AR6K_MAILBOXES 4
33 /* HTC runs over mailbox 0 */
36 #define AR6K_TARGET_DEBUG_INTR_MASK 0x01
38 #define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
39 INT_STATUS_ENABLE_CPU_MASK | \
40 INT_STATUS_ENABLE_COUNTER_MASK)
43 //#define MBOXHW_UNIT_TEST 1
45 #include "athstartpack.h"
46 typedef 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
;
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
;
59 #define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
61 typedef 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
;
68 typedef PREPACK
struct _AR6K_GMBOX_CTRL_REGISTERS
{
69 A_UINT8 int_status_enable
;
70 } POSTPACK AR6K_GMBOX_CTRL_REGISTERS
;
72 #include "athendpack.h"
74 #define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
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
85 #ifndef A_CACHE_LINE_PAD
86 #define A_CACHE_LINE_PAD 128
88 #define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2
89 #define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024
91 /* buffers for ASYNC I/O */
92 typedef 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
;
99 typedef struct _AR6K_GMBOX_INFO
{
100 void *pProtocolContext
;
101 int (*pMessagePendingCallBack
)(void *pContext
, A_UINT8 LookAheadBytes
[], int ValidBytes
);
102 int (*pCreditsPendingCallback
)(void *pContext
, int NumCredits
, A_BOOL CreditIRQEnabled
);
103 void (*pTargetFailureCallback
)(void *pContext
, int Status
);
104 void (*pStateDumpCallback
)(void *pContext
);
105 A_BOOL CreditCountIRQEnabled
;
108 typedef struct _AR6K_DEVICE
{
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
];
118 HIF_DEVICE_MBOX_INFO MailBoxInfo
;
119 HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc
;
121 HTC_PACKET_QUEUE RegisterIOList
;
122 AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers
[AR6K_MAX_REG_IO_BUFFERS
];
123 void (*TargetFailureCallback
)(void *Context
);
124 int (*MessagePendingCallback
)(void *Context
,
125 A_UINT32 LookAheads
[],
128 int *pNumPktsFetched
);
129 HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode
;
130 HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent
;
132 HIF_DEVICE_IRQ_YIELD_PARAMS HifIRQYieldParams
;
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
;
142 AR6K_GMBOX_CTRL_REGISTERS GMboxControlRegisters
;
143 int RecheckIRQStatusCnt
;
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 */
150 int DevSetup(AR6K_DEVICE
*pDev
);
151 void DevCleanup(AR6K_DEVICE
*pDev
);
152 int DevUnmaskInterrupts(AR6K_DEVICE
*pDev
);
153 int DevMaskInterrupts(AR6K_DEVICE
*pDev
);
154 int DevPollMboxMsgRecv(AR6K_DEVICE
*pDev
,
155 A_UINT32
*pLookAhead
,
157 int DevRWCompletionHandler(void *context
, int status
);
158 int DevDsrHandler(void *context
);
159 int DevCheckPendingRecvMsgsAsync(void *context
);
160 void DevAsyncIrqProcessComplete(AR6K_DEVICE
*pDev
);
161 void DevDumpRegisters(AR6K_DEVICE
*pDev
,
162 AR6K_IRQ_PROC_REGISTERS
*pIrqProcRegs
,
163 AR6K_IRQ_ENABLE_REGISTERS
*pIrqEnableRegs
);
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
169 int DevStopRecv(AR6K_DEVICE
*pDev
, A_BOOL ASyncMode
);
170 int DevEnableRecv(AR6K_DEVICE
*pDev
, A_BOOL ASyncMode
);
171 int DevEnableInterrupts(AR6K_DEVICE
*pDev
);
172 int DevDisableInterrupts(AR6K_DEVICE
*pDev
);
173 int DevWaitForPendingRecv(AR6K_DEVICE
*pDev
,A_UINT32 TimeoutInMs
,A_BOOL
*pbIsRecvPending
);
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)
179 static INLINE
int DevSendPacket(AR6K_DEVICE
*pDev
, HTC_PACKET
*pPacket
, A_UINT32 SendLength
) {
180 A_UINT32 paddedLength
;
181 A_BOOL sync
= (pPacket
->Completion
== NULL
) ? TRUE
: FALSE
;
184 /* adjust the length to be a multiple of block size if appropriate */
185 paddedLength
= DEV_CALC_SEND_PADDED_LEN(pDev
, SendLength
);
188 if (paddedLength
> pPacket
->BufferLength
) {
190 if (pPacket
->Completion
!= NULL
) {
191 COMPLETE_HTC_PACKET(pPacket
,A_EINVAL
);
198 AR_DEBUG_PRINTF(ATH_DEBUG_SEND
,
199 ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
201 pDev
->MailBoxInfo
.MboxAddresses
[HTC_MAILBOX
],
202 sync
? "SYNC" : "ASYNC"));
204 status
= HIFReadWrite(pDev
->HIFDevice
,
205 pDev
->MailBoxInfo
.MboxAddresses
[HTC_MAILBOX
],
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 */
212 pPacket
->Status
= status
;
214 if (status
== A_PENDING
) {
222 static INLINE
int DevRecvPacket(AR6K_DEVICE
*pDev
, HTC_PACKET
*pPacket
, A_UINT32 RecvLength
) {
223 A_UINT32 paddedLength
;
225 A_BOOL sync
= (pPacket
->Completion
== NULL
) ? TRUE
: FALSE
;
227 /* adjust the length to be a multiple of block size if appropriate */
228 paddedLength
= DEV_CALC_RECV_PADDED_LEN(pDev
, RecvLength
);
230 if (paddedLength
> pPacket
->BufferLength
) {
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
);
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
,
246 pDev
->MailBoxInfo
.MboxAddresses
[HTC_MAILBOX
],
247 sync
? "SYNC" : "ASYNC"));
249 status
= HIFReadWrite(pDev
->HIFDevice
,
250 pDev
->MailBoxInfo
.MboxAddresses
[HTC_MAILBOX
],
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 */
257 pPacket
->Status
= status
;
263 #define DEV_CHECK_RECV_YIELD(pDev) \
264 ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount)
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)
269 /**************************************************/
270 /****** Scatter Function and Definitions
275 int DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ
*pReq
, A_BOOL FromDMA
);
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); \
285 /* copy any WRITE data to bounce buffer */
286 static INLINE
int 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
);
295 int DevSetupMsgBundling(AR6K_DEVICE
*pDev
, int MaxMsgsPerTransfer
);
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)
302 #define DEV_FREE_SCATTER_REQ(pDev,pR) \
303 (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
305 #define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize
306 #define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize
308 #define DEV_SCATTER_READ TRUE
309 #define DEV_SCATTER_WRITE FALSE
310 #define DEV_SCATTER_ASYNC TRUE
311 #define DEV_SCATTER_SYNC FALSE
312 int DevSubmitScatterRequest(AR6K_DEVICE
*pDev
, HIF_SCATTER_REQ
*pScatterReq
, A_BOOL Read
, A_BOOL Async
);
314 #ifdef MBOXHW_UNIT_TEST
315 int DoMboxHWTest(AR6K_DEVICE
*pDev
);
318 /* completely virtual */
319 typedef 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
;
326 void DumpAR6KDevState(AR6K_DEVICE
*pDev
);
328 /**************************************************/
329 /****** GMBOX functions and definitions
334 #ifdef ATH_AR6K_ENABLE_GMBOX
336 void DevCleanupGMbox(AR6K_DEVICE
*pDev
);
337 int DevSetupGMbox(AR6K_DEVICE
*pDev
);
338 int DevCheckGMboxInterrupts(AR6K_DEVICE
*pDev
);
339 void DevNotifyGMboxTargetFailure(AR6K_DEVICE
*pDev
);
344 #define DevCleanupGMbox(p)
345 #define DevCheckGMboxInterrupts(p) A_OK
346 #define DevNotifyGMboxTargetFailure(p)
348 static INLINE
int DevSetupGMbox(AR6K_DEVICE
*pDev
) {
349 pDev
->GMboxEnabled
= FALSE
;
355 #ifdef ATH_AR6K_ENABLE_GMBOX
357 /* GMBOX protocol modules must expose each of these internal APIs */
358 HCI_TRANSPORT_HANDLE
GMboxAttachProtocol(AR6K_DEVICE
*pDev
, HCI_TRANSPORT_CONFIG_INFO
*pInfo
);
359 int GMboxProtocolInstall(AR6K_DEVICE
*pDev
);
360 void GMboxProtocolUninstall(AR6K_DEVICE
*pDev
);
362 /* API used by GMBOX protocol modules */
363 AR6K_DEVICE
*HTCGetAR6KDevice(void *HTCHandle
);
364 #define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
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); \
373 #define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext
375 int DevGMboxWrite(AR6K_DEVICE
*pDev
, HTC_PACKET
*pPacket
, A_UINT32 WriteLength
);
376 int DevGMboxRead(AR6K_DEVICE
*pDev
, HTC_PACKET
*pPacket
, A_UINT32 ReadLength
);
378 #define PROC_IO_ASYNC TRUE
379 #define PROC_IO_SYNC FALSE
380 typedef enum GMBOX_IRQ_ACTION_TYPE
{
381 GMBOX_ACTION_NONE
= 0,
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
;
390 int DevGMboxIRQAction(AR6K_DEVICE
*pDev
, GMBOX_IRQ_ACTION_TYPE
, A_BOOL AsyncMode
);
391 int DevGMboxReadCreditCounter(AR6K_DEVICE
*pDev
, A_BOOL AsyncMode
, int *pCredits
);
392 int DevGMboxReadCreditSize(AR6K_DEVICE
*pDev
, int *pCreditSize
);
393 int DevGMboxRecvLookAheadPeek(AR6K_DEVICE
*pDev
, A_UINT8
*pLookAheadBuffer
, int *pLookAheadBytes
);
394 int DevGMboxSetTargetInterrupt(AR6K_DEVICE
*pDev
, int SignalNumber
, int AckTimeoutMS
);