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 PREPACK struct ar6k_irq_proc_registers {
49 u8 counter_int_status;
51 u8 rx_lookahead_valid;
55 u32 rx_gmbox_lookahead_alias[2];
58 #define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers)
60 PREPACK struct ar6k_irq_enable_registers {
62 u8 cpu_int_status_enable;
63 u8 error_status_enable;
64 u8 counter_int_status_enable;
67 PREPACK struct ar6k_gmbox_ctrl_registers {
71 #define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers)
73 #define AR6K_REG_IO_BUFFER_SIZE 32
74 #define AR6K_MAX_REG_IO_BUFFERS 8
75 #define FROM_DMA_BUFFER true
76 #define TO_DMA_BUFFER false
77 #define AR6K_SCATTER_ENTRIES_PER_REQ 16
78 #define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024
79 #define AR6K_SCATTER_REQS 4
80 #define AR6K_LEGACY_MAX_WRITE_LENGTH 2048
82 #ifndef A_CACHE_LINE_PAD
83 #define A_CACHE_LINE_PAD 128
85 #define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2
86 #define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024
88 /* buffers for ASYNC I/O */
89 struct ar6k_async_reg_io_buffer {
90 struct htc_packet HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */
91 u8 _Pad1[A_CACHE_LINE_PAD];
92 u8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; /* cache-line safe with pads around */
93 u8 _Pad2[A_CACHE_LINE_PAD];
96 struct ar6k_gmbox_info {
97 void *pProtocolContext;
98 int (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes);
99 int (*pCreditsPendingCallback)(void *pContext, int NumCredits, bool CreditIRQEnabled);
100 void (*pTargetFailureCallback)(void *pContext, int Status);
101 void (*pStateDumpCallback)(void *pContext);
102 bool CreditCountIRQEnabled;
107 u8 _Pad1[A_CACHE_LINE_PAD];
108 struct ar6k_irq_proc_registers IrqProcRegisters; /* cache-line safe with pads around */
109 u8 _Pad2[A_CACHE_LINE_PAD];
110 struct ar6k_irq_enable_registers IrqEnableRegisters; /* cache-line safe with pads around */
111 u8 _Pad3[A_CACHE_LINE_PAD];
115 struct hif_device_mbox_info MailBoxInfo;
116 HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc;
118 struct htc_packet_queue RegisterIOList;
119 struct ar6k_async_reg_io_buffer RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
120 void (*TargetFailureCallback)(void *Context);
121 int (*MessagePendingCallback)(void *Context,
125 int *pNumPktsFetched);
126 HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode;
127 HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent;
129 struct hif_device_irq_yield_params HifIRQYieldParams;
131 int CurrentDSRRecvCount;
132 struct hif_device_scatter_support_info HifScatterInfo;
133 struct dl_list ScatterReqHead;
134 bool ScatterIsVirtual;
135 int MaxRecvBundleSize;
136 int MaxSendBundleSize;
137 struct ar6k_gmbox_info GMboxInfo;
139 struct ar6k_gmbox_ctrl_registers GMboxControlRegisters;
140 int RecheckIRQStatusCnt;
143 #define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock);
144 #define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock);
145 #define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need to lock this, it only gets set */
147 int DevSetup(struct ar6k_device *pDev);
148 void DevCleanup(struct ar6k_device *pDev);
149 int DevUnmaskInterrupts(struct ar6k_device *pDev);
150 int DevMaskInterrupts(struct ar6k_device *pDev);
151 int DevPollMboxMsgRecv(struct ar6k_device *pDev,
154 int DevRWCompletionHandler(void *context, int status);
155 int DevDsrHandler(void *context);
156 int DevCheckPendingRecvMsgsAsync(void *context);
157 void DevAsyncIrqProcessComplete(struct ar6k_device *pDev);
158 void DevDumpRegisters(struct ar6k_device *pDev,
159 struct ar6k_irq_proc_registers *pIrqProcRegs,
160 struct ar6k_irq_enable_registers *pIrqEnableRegs);
162 #define DEV_STOP_RECV_ASYNC true
163 #define DEV_STOP_RECV_SYNC false
164 #define DEV_ENABLE_RECV_ASYNC true
165 #define DEV_ENABLE_RECV_SYNC false
166 int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode);
167 int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode);
168 int DevEnableInterrupts(struct ar6k_device *pDev);
169 int DevDisableInterrupts(struct ar6k_device *pDev);
170 int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending);
172 #define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
173 #define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
174 #define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
176 static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) {
178 bool sync = (pPacket->Completion == NULL) ? true : false;
181 /* adjust the length to be a multiple of block size if appropriate */
182 paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
185 if (paddedLength > pPacket->BufferLength) {
187 if (pPacket->Completion != NULL) {
188 COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
195 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
196 ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
198 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
199 sync ? "SYNC" : "ASYNC"));
201 status = HIFReadWrite(pDev->HIFDevice,
202 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
204 paddedLength, /* the padded length */
205 sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
206 sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
209 pPacket->Status = status;
211 if (status == A_PENDING) {
219 static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) {
222 bool sync = (pPacket->Completion == NULL) ? true : false;
224 /* adjust the length to be a multiple of block size if appropriate */
225 paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
227 if (paddedLength > pPacket->BufferLength) {
229 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
230 ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
231 paddedLength,RecvLength,pPacket->BufferLength));
232 if (pPacket->Completion != NULL) {
233 COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
239 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
240 ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
241 (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
243 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
244 sync ? "SYNC" : "ASYNC"));
246 status = HIFReadWrite(pDev->HIFDevice,
247 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
250 sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
251 sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
254 pPacket->Status = status;
260 #define DEV_CHECK_RECV_YIELD(pDev) \
261 ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount)
263 #define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode)
264 #define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
266 /**************************************************/
267 /****** Scatter Function and Definitions
272 int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA);
274 /* copy any READ data back into scatter list */
275 #define DEV_FINISH_SCATTER_OPERATION(pR) \
277 if (!((pR)->CompletionStatus) && \
278 !((pR)->Request & HIF_WRITE) && \
279 ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \
280 (pR)->CompletionStatus = \
281 DevCopyScatterListToFromDMABuffer((pR), \
286 /* copy any WRITE data to bounce buffer */
287 static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq) {
288 if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
289 return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);
296 int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer);
298 int DevCleanupMsgBundling(struct ar6k_device *pDev);
300 #define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatterEntries
301 #define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
302 #define DEV_ALLOC_SCATTER_REQ(pDev) \
303 (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice)
305 #define DEV_FREE_SCATTER_REQ(pDev,pR) \
306 (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
308 #define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize
309 #define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize
311 #define DEV_SCATTER_READ true
312 #define DEV_SCATTER_WRITE false
313 #define DEV_SCATTER_ASYNC true
314 #define DEV_SCATTER_SYNC false
315 int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async);
317 #ifdef MBOXHW_UNIT_TEST
318 int DoMboxHWTest(struct ar6k_device *pDev);
321 /* completely virtual */
322 struct dev_scatter_dma_virtual_info {
323 u8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible address */
324 u8 DataArea[1]; /* start of data area */
329 void DumpAR6KDevState(struct ar6k_device *pDev);
331 /**************************************************/
332 /****** GMBOX functions and definitions
337 #ifdef ATH_AR6K_ENABLE_GMBOX
339 void DevCleanupGMbox(struct ar6k_device *pDev);
340 int DevSetupGMbox(struct ar6k_device *pDev);
341 int DevCheckGMboxInterrupts(struct ar6k_device *pDev);
342 void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev);
347 #define DevCleanupGMbox(p)
348 #define DevCheckGMboxInterrupts(p) 0
349 #define DevNotifyGMboxTargetFailure(p)
351 static INLINE int DevSetupGMbox(struct ar6k_device *pDev) {
352 pDev->GMboxEnabled = false;
358 #ifdef ATH_AR6K_ENABLE_GMBOX
360 /* GMBOX protocol modules must expose each of these internal APIs */
361 HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo);
362 int GMboxProtocolInstall(struct ar6k_device *pDev);
363 void GMboxProtocolUninstall(struct ar6k_device *pDev);
365 /* API used by GMBOX protocol modules */
366 struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle);
367 #define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
369 (pDev)->GMboxInfo.pProtocolContext = (context); \
370 (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \
371 (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \
372 (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \
373 (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \
376 #define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext
378 int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength);
379 int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength);
381 #define PROC_IO_ASYNC true
382 #define PROC_IO_SYNC false
383 typedef enum GMBOX_IRQ_ACTION_TYPE {
384 GMBOX_ACTION_NONE = 0,
386 GMBOX_ERRORS_IRQ_ENABLE,
387 GMBOX_RECV_IRQ_ENABLE,
388 GMBOX_RECV_IRQ_DISABLE,
389 GMBOX_CREDIT_IRQ_ENABLE,
390 GMBOX_CREDIT_IRQ_DISABLE,
391 } GMBOX_IRQ_ACTION_TYPE;
393 int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode);
394 int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits);
395 int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize);
396 int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes);
397 int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS);