OLD | NEW |
(Empty) | |
| 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="ar6k.h" company="Atheros"> |
| 3 // Copyright (c) 2007-2008 Atheros Corporation. All rights reserved. |
| 4 // |
| 5 // This program is free software; you can redistribute it and/or modify |
| 6 // it under the terms of the GNU General Public License version 2 as |
| 7 // published by the Free Software Foundation; |
| 8 // |
| 9 // Software distributed under the License is distributed on an "AS |
| 10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| 11 // implied. See the License for the specific language governing |
| 12 // rights and limitations under the License. |
| 13 // |
| 14 // |
| 15 //------------------------------------------------------------------------------ |
| 16 //============================================================================== |
| 17 // AR6K device layer that handles register level I/O |
| 18 // |
| 19 // Author(s): ="Atheros" |
| 20 //============================================================================== |
| 21 #ifndef AR6K_H_ |
| 22 #define AR6K_H_ |
| 23 |
| 24 #include "hci_transport_api.h" |
| 25 #include "../htc_debug.h" |
| 26 |
| 27 #define AR6K_MAILBOXES 4 |
| 28 |
| 29 /* HTC runs over mailbox 0 */ |
| 30 #define HTC_MAILBOX 0 |
| 31 |
| 32 #define AR6K_TARGET_DEBUG_INTR_MASK 0x01 |
| 33 |
| 34 #define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ |
| 35 INT_STATUS_ENABLE_CPU_MASK | \ |
| 36 INT_STATUS_ENABLE_COUNTER_MASK) |
| 37 |
| 38 |
| 39 //#define MBOXHW_UNIT_TEST 1 |
| 40 |
| 41 #include "athstartpack.h" |
| 42 typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS { |
| 43 A_UINT8 host_int_status; |
| 44 A_UINT8 cpu_int_status; |
| 45 A_UINT8 error_int_status; |
| 46 A_UINT8 counter_int_status; |
| 47 A_UINT8 mbox_frame; |
| 48 A_UINT8 rx_lookahead_valid; |
| 49 A_UINT8 host_int_status2; |
| 50 A_UINT8 gmbox_rx_avail; |
| 51 A_UINT32 rx_lookahead[2]; |
| 52 A_UINT32 rx_gmbox_lookahead_alias[2]; |
| 53 } POSTPACK AR6K_IRQ_PROC_REGISTERS; |
| 54 |
| 55 #define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS) |
| 56 |
| 57 typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS { |
| 58 A_UINT8 int_status_enable; |
| 59 A_UINT8 cpu_int_status_enable; |
| 60 A_UINT8 error_status_enable; |
| 61 A_UINT8 counter_int_status_enable; |
| 62 } POSTPACK AR6K_IRQ_ENABLE_REGISTERS; |
| 63 |
| 64 typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS { |
| 65 A_UINT8 int_status_enable; |
| 66 } POSTPACK AR6K_GMBOX_CTRL_REGISTERS; |
| 67 |
| 68 #include "athendpack.h" |
| 69 |
| 70 #define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS) |
| 71 |
| 72 #define AR6K_REG_IO_BUFFER_SIZE 32 |
| 73 #define AR6K_MAX_REG_IO_BUFFERS 8 |
| 74 #define FROM_DMA_BUFFER TRUE |
| 75 #define TO_DMA_BUFFER FALSE |
| 76 #define AR6K_SCATTER_ENTRIES_PER_REQ 16 |
| 77 #define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024 |
| 78 #define AR6K_SCATTER_REQS 2 |
| 79 #define AR6K_LEGACY_MAX_WRITE_LENGTH 2048 |
| 80 |
| 81 /* buffers for ASYNC I/O */ |
| 82 typedef struct AR6K_ASYNC_REG_IO_BUFFER { |
| 83 HTC_PACKET HtcPacket; /* we use an HTC packet as a wrapper for our asyn
c register-based I/O */ |
| 84 A_UINT8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; |
| 85 } AR6K_ASYNC_REG_IO_BUFFER; |
| 86 |
| 87 typedef struct _AR6K_GMBOX_INFO { |
| 88 void *pProtocolContext; |
| 89 A_STATUS (*pMessagePendingCallBack)(void *pContext, A_UINT8 LookAheadByte
s[], int ValidBytes); |
| 90 A_STATUS (*pCreditsPendingCallback)(void *pContext, int NumCredits, A_BO
OL CreditIRQEnabled); |
| 91 void (*pTargetFailureCallback)(void *pContext, A_STATUS Status); |
| 92 void (*pStateDumpCallback)(void *pContext); |
| 93 A_BOOL CreditCountIRQEnabled; |
| 94 } AR6K_GMBOX_INFO; |
| 95 |
| 96 typedef struct _AR6K_DEVICE { |
| 97 A_MUTEX_T Lock; |
| 98 AR6K_IRQ_PROC_REGISTERS IrqProcRegisters; |
| 99 AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters; |
| 100 void *HIFDevice; |
| 101 A_UINT32 BlockSize; |
| 102 A_UINT32 BlockMask; |
| 103 HIF_DEVICE_MBOX_INFO MailBoxInfo; |
| 104 HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc; |
| 105 void *HTCContext; |
| 106 HTC_PACKET_QUEUE RegisterIOList; |
| 107 AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS]; |
| 108 void (*TargetFailureCallback)(void *Context); |
| 109 A_STATUS (*MessagePendingCallback)(void *Context, |
| 110 A_UINT32 LookAheads[],
|
| 111 int NumLookAheads, |
| 112 A_BOOL *pAsyncProc, |
| 113 int *pNumPktsFetched); |
| 114 HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; |
| 115 HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; |
| 116 A_BOOL HifAttached; |
| 117 HIF_DEVICE_IRQ_YIELD_PARAMS HifIRQYieldParams; |
| 118 A_BOOL DSRCanYield; |
| 119 int CurrentDSRRecvCount; |
| 120 HIF_DEVICE_SCATTER_SUPPORT_INFO HifScatterInfo; |
| 121 DL_LIST ScatterReqHead; |
| 122 A_BOOL ScatterIsVirtual; |
| 123 int MaxRecvBundleSize; |
| 124 int MaxSendBundleSize; |
| 125 AR6K_GMBOX_INFO GMboxInfo; |
| 126 A_BOOL GMboxEnabled; |
| 127 AR6K_GMBOX_CTRL_REGISTERS GMboxControlRegisters; |
| 128 int RecheckIRQStatusCnt; |
| 129 } AR6K_DEVICE; |
| 130 |
| 131 #define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock); |
| 132 #define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock); |
| 133 #define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need
to lock this, it only gets set */ |
| 134 |
| 135 A_STATUS DevSetup(AR6K_DEVICE *pDev); |
| 136 void DevCleanup(AR6K_DEVICE *pDev); |
| 137 A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev); |
| 138 A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev); |
| 139 A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, |
| 140 A_UINT32 *pLookAhead, |
| 141 int TimeoutMS); |
| 142 A_STATUS DevRWCompletionHandler(void *context, A_STATUS status); |
| 143 A_STATUS DevDsrHandler(void *context); |
| 144 A_STATUS DevCheckPendingRecvMsgsAsync(void *context); |
| 145 void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev); |
| 146 void DevDumpRegisters(AR6K_DEVICE *pDev, |
| 147 AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs, |
| 148 AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs); |
| 149 |
| 150 #define DEV_STOP_RECV_ASYNC TRUE |
| 151 #define DEV_STOP_RECV_SYNC FALSE |
| 152 #define DEV_ENABLE_RECV_ASYNC TRUE |
| 153 #define DEV_ENABLE_RECV_SYNC FALSE |
| 154 A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); |
| 155 A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); |
| 156 A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev); |
| 157 A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev); |
| 158 |
| 159 |
| 160 #define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) &
(~((pDev)->BlockMask))) |
| 161 #define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,len
gth) |
| 162 #define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) =
= 0) |
| 163 |
| 164 static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_U
INT32 SendLength) { |
| 165 A_UINT32 paddedLength; |
| 166 A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; |
| 167 A_STATUS status; |
| 168 |
| 169 /* adjust the length to be a multiple of block size if appropriate */ |
| 170 paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength); |
| 171 |
| 172 #if 0 |
| 173 if (paddedLength > pPacket->BufferLength) { |
| 174 A_ASSERT(FALSE); |
| 175 if (pPacket->Completion != NULL) { |
| 176 COMPLETE_HTC_PACKET(pPacket,A_EINVAL); |
| 177 return A_OK; |
| 178 } |
| 179 return A_EINVAL; |
| 180 } |
| 181 #endif |
| 182 |
| 183 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, |
| 184 ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", |
| 185 paddedLength, |
| 186 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], |
| 187 sync ? "SYNC" : "ASYNC")); |
| 188 |
| 189 status = HIFReadWrite(pDev->HIFDevice, |
| 190 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], |
| 191 pPacket->pBuffer, |
| 192 paddedLength, /* the padded length */ |
| 193 sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, |
| 194 sync ? NULL : pPacket); /* pass the packet as the con
text to the HIF request */ |
| 195 |
| 196 if (sync) { |
| 197 pPacket->Status = status; |
| 198 } else { |
| 199 if (status == A_PENDING) { |
| 200 status = A_OK; |
| 201 } |
| 202 } |
| 203 |
| 204 return status; |
| 205 } |
| 206 |
| 207 static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_U
INT32 RecvLength) { |
| 208 A_UINT32 paddedLength; |
| 209 A_STATUS status; |
| 210 A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; |
| 211 |
| 212 /* adjust the length to be a multiple of block size if appropriate */ |
| 213 paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength); |
| 214 |
| 215 if (paddedLength > pPacket->BufferLength) { |
| 216 A_ASSERT(FALSE); |
| 217 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, |
| 218 ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d buffe
rlen:%d \n", |
| 219 paddedLength,RecvLength,pPacket->BufferLength)); |
| 220 if (pPacket->Completion != NULL) { |
| 221 COMPLETE_HTC_PACKET(pPacket,A_EINVAL); |
| 222 return A_OK; |
| 223 } |
| 224 return A_EINVAL; |
| 225 } |
| 226 |
| 227 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, |
| 228 ("DevRecvPacket (0x%X : hdr:0x%X) Padded Length: %d Mbox:0x%X (m
ode:%s)\n", |
| 229 (A_UINT32)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, |
| 230 paddedLength, |
| 231 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], |
| 232 sync ? "SYNC" : "ASYNC")); |
| 233 |
| 234 status = HIFReadWrite(pDev->HIFDevice, |
| 235 pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], |
| 236 pPacket->pBuffer, |
| 237 paddedLength, |
| 238 sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX, |
| 239 sync ? NULL : pPacket); /* pass the packet as the con
text to the HIF request */ |
| 240 |
| 241 if (sync) { |
| 242 pPacket->Status = status; |
| 243 } |
| 244 |
| 245 return status; |
| 246 } |
| 247 |
| 248 #define DEV_CHECK_RECV_YIELD(pDev) \ |
| 249 ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacket
YieldCount) |
| 250 |
| 251 #define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->Hif
IRQProcessingMode) |
| 252 #define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode
!= HIF_DEVICE_IRQ_SYNC_ONLY) |
| 253 |
| 254 /**************************************************/ |
| 255 /****** Scatter Function and Definitions |
| 256 * |
| 257 * |
| 258 */ |
| 259 |
| 260 A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA
); |
| 261 |
| 262 /* copy any READ data back into scatter list */ |
| 263 #define DEV_FINISH_SCATTER_OPERATION(pR) \ |
| 264 if (A_SUCCESS((pR)->CompletionStatus) && \ |
| 265 !((pR)->Request & HIF_WRITE) && \ |
| 266 ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \ |
| 267 (pR)->CompletionStatus = DevCopyScatterListToFromDMABuffer((pR),FROM_DM
A_BUFFER); \ |
| 268 } |
| 269 |
| 270 /* copy any WRITE data to bounce buffer */ |
| 271 static INLINE A_STATUS DEV_PREPARE_SCATTER_OPERATION(HIF_SCATTER_REQ *pReq) { |
| 272 if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_B
OUNCE)) { |
| 273 return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER); |
| 274 } else { |
| 275 return A_OK; |
| 276 } |
| 277 } |
| 278 |
| 279 |
| 280 A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer); |
| 281 |
| 282 #define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatte
rEntries |
| 283 #define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransf
erSizePerScatterReq |
| 284 #define DEV_ALLOC_SCATTER_REQ(pDev) \ |
| 285 (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) :
(pDev)->HIFDevice) |
| 286 |
| 287 #define DEV_FREE_SCATTER_REQ(pDev,pR) \ |
| 288 (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDe
v)->HIFDevice,(pR)) |
| 289 |
| 290 #define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize |
| 291 #define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize |
| 292 |
| 293 #define DEV_SCATTER_READ TRUE |
| 294 #define DEV_SCATTER_WRITE FALSE |
| 295 #define DEV_SCATTER_ASYNC TRUE |
| 296 #define DEV_SCATTER_SYNC FALSE |
| 297 A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq
, A_BOOL Read, A_BOOL Async); |
| 298 |
| 299 #ifdef MBOXHW_UNIT_TEST |
| 300 A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev); |
| 301 #endif |
| 302 |
| 303 /* completely virtual */ |
| 304 typedef struct _DEV_SCATTER_DMA_VIRTUAL_INFO { |
| 305 A_UINT8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible
address */ |
| 306 A_UINT8 DataArea[1]; /* start of data area */ |
| 307 } DEV_SCATTER_DMA_VIRTUAL_INFO; |
| 308 |
| 309 |
| 310 |
| 311 void DumpAR6KDevState(AR6K_DEVICE *pDev); |
| 312 |
| 313 /**************************************************/ |
| 314 /****** GMBOX functions and definitions |
| 315 * |
| 316 * |
| 317 */ |
| 318 |
| 319 #ifdef ATH_AR6K_ENABLE_GMBOX |
| 320 |
| 321 void DevCleanupGMbox(AR6K_DEVICE *pDev); |
| 322 A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev); |
| 323 A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev); |
| 324 void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev); |
| 325 |
| 326 #else |
| 327 |
| 328 /* compiled out */ |
| 329 #define DevCleanupGMbox(p) |
| 330 #define DevCheckGMboxInterrupts(p) A_OK |
| 331 #define DevNotifyGMboxTargetFailure(p) |
| 332 |
| 333 static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) { |
| 334 pDev->GMboxEnabled = FALSE; |
| 335 return A_OK; |
| 336 } |
| 337 |
| 338 #endif |
| 339 |
| 340 #ifdef ATH_AR6K_ENABLE_GMBOX |
| 341 |
| 342 /* GMBOX protocol modules must expose each of these internal APIs */ |
| 343 HCI_TRANSPORT_HANDLE GMboxAttachProtocol(AR6K_DEVICE *pDev, HCI_TRANSPORT_CONFIG
_INFO *pInfo); |
| 344 A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev); |
| 345 void GMboxProtocolUninstall(AR6K_DEVICE *pDev); |
| 346 |
| 347 /* API used by GMBOX protocol modules */ |
| 348 AR6K_DEVICE *HTCGetAR6KDevice(void *HTCHandle); |
| 349 #define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,stated
ump,context) \ |
| 350 { \ |
| 351 (pDev)->GMboxInfo.pProtocolContext = (context); \ |
| 352 (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \ |
| 353 (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \ |
| 354 (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \ |
| 355 (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \ |
| 356 } |
| 357 |
| 358 #define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext |
| 359 |
| 360 A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLen
gth); |
| 361 A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLengt
h); |
| 362 |
| 363 #define PROC_IO_ASYNC TRUE |
| 364 #define PROC_IO_SYNC FALSE |
| 365 typedef enum GMBOX_IRQ_ACTION_TYPE { |
| 366 GMBOX_ACTION_NONE = 0, |
| 367 GMBOX_DISABLE_ALL, |
| 368 GMBOX_ERRORS_IRQ_ENABLE, |
| 369 GMBOX_RECV_IRQ_ENABLE, |
| 370 GMBOX_RECV_IRQ_DISABLE, |
| 371 GMBOX_CREDIT_IRQ_ENABLE, |
| 372 GMBOX_CREDIT_IRQ_DISABLE, |
| 373 } GMBOX_IRQ_ACTION_TYPE; |
| 374 |
| 375 A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE, A_BOOL Asyn
cMode); |
| 376 A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCr
edits); |
| 377 A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize); |
| 378 A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer,
int *pLookAheadBytes); |
| 379 A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int SignalNumber, int Ack
TimeoutMS); |
| 380 |
| 381 #endif |
| 382 |
| 383 #endif /*AR6K_H_*/ |
OLD | NEW |