OLD | NEW |
(Empty) | |
| 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="htc.c" 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 // Author(s): ="Atheros" |
| 18 //============================================================================== |
| 19 #include "htc_internal.h" |
| 20 |
| 21 #ifdef DEBUG |
| 22 static ATH_DEBUG_MASK_DESCRIPTION g_HTCDebugDescription[] = { |
| 23 { ATH_DEBUG_SEND , "Send"}, |
| 24 { ATH_DEBUG_RECV , "Recv"}, |
| 25 { ATH_DEBUG_SYNC , "Sync"}, |
| 26 { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"}, |
| 27 { ATH_DEBUG_IRQ , "Interrupt Processing"} |
| 28 }; |
| 29 |
| 30 ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, |
| 31 "htc", |
| 32 "Host Target Communications", |
| 33 ATH_DEBUG_MASK_DEFAULTS, |
| 34 ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescripti
on), |
| 35 g_HTCDebugDescription); |
| 36 |
| 37 #endif |
| 38 |
| 39 static void HTCReportFailure(void *Context); |
| 40 static void ResetEndpointStates(HTC_TARGET *target); |
| 41 |
| 42 void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QU
EUE *pList) |
| 43 { |
| 44 LOCK_HTC(target); |
| 45 HTC_PACKET_ENQUEUE(pList,pPacket); |
| 46 UNLOCK_HTC(target); |
| 47 } |
| 48 |
| 49 HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList) |
| 50 { |
| 51 HTC_PACKET *pPacket; |
| 52 |
| 53 LOCK_HTC(target); |
| 54 pPacket = HTC_PACKET_DEQUEUE(pList); |
| 55 UNLOCK_HTC(target); |
| 56 |
| 57 return pPacket; |
| 58 } |
| 59 |
| 60 /* cleanup the HTC instance */ |
| 61 static void HTCCleanup(HTC_TARGET *target) |
| 62 { |
| 63 A_INT32 i; |
| 64 |
| 65 DevCleanup(&target->Device); |
| 66 |
| 67 for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { |
| 68 if (target->HTCControlBuffers[i].Buffer) { |
| 69 A_FREE(target->HTCControlBuffers[i].Buffer); |
| 70 } |
| 71 } |
| 72 |
| 73 if (A_IS_MUTEX_VALID(&target->HTCLock)) { |
| 74 A_MUTEX_DELETE(&target->HTCLock); |
| 75 } |
| 76 |
| 77 if (A_IS_MUTEX_VALID(&target->HTCRxLock)) { |
| 78 A_MUTEX_DELETE(&target->HTCRxLock); |
| 79 } |
| 80 |
| 81 if (A_IS_MUTEX_VALID(&target->HTCTxLock)) { |
| 82 A_MUTEX_DELETE(&target->HTCTxLock); |
| 83 } |
| 84 /* free our instance */ |
| 85 A_FREE(target); |
| 86 } |
| 87 |
| 88 /* registered target arrival callback from the HIF layer */ |
| 89 HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo) |
| 90 { |
| 91 HTC_TARGET *target = NULL; |
| 92 A_STATUS status = A_OK; |
| 93 int i; |
| 94 A_UINT32 ctrl_bufsz; |
| 95 A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; |
| 96 |
| 97 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n")); |
| 98 |
| 99 A_REGISTER_MODULE_DEBUG_INFO(htc); |
| 100 |
| 101 do { |
| 102 |
| 103 /* allocate target memory */ |
| 104 if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { |
| 105 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); |
| 106 status = A_ERROR; |
| 107 break; |
| 108 } |
| 109 |
| 110 A_MEMZERO(target, sizeof(HTC_TARGET)); |
| 111 A_MUTEX_INIT(&target->HTCLock); |
| 112 A_MUTEX_INIT(&target->HTCRxLock); |
| 113 A_MUTEX_INIT(&target->HTCTxLock); |
| 114 INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); |
| 115 INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList); |
| 116 |
| 117 /* give device layer the hif device handle */ |
| 118 target->Device.HIFDevice = hif_handle; |
| 119 /* give the device layer our context (for event processing) |
| 120 * the device layer will register it's own context with HIF |
| 121 * so we need to set this so we can fetch it in the target remove ha
ndler */ |
| 122 target->Device.HTCContext = target; |
| 123 /* set device layer target failure callback */ |
| 124 target->Device.TargetFailureCallback = HTCReportFailure; |
| 125 /* set device layer recv message pending callback */ |
| 126 target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler; |
| 127 target->EpWaitingForBuffers = ENDPOINT_MAX; |
| 128 |
| 129 A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO)); |
| 130 |
| 131 ResetEndpointStates(target); |
| 132 |
| 133 /* setup device layer */ |
| 134 status = DevSetup(&target->Device); |
| 135 |
| 136 if (A_FAILED(status)) { |
| 137 break; |
| 138 } |
| 139 |
| 140 |
| 141 /* get the block sizes */ |
| 142 status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, |
| 143 blocksizes, sizeof(blocksizes)); |
| 144 if (A_FAILED(status)) { |
| 145 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from H
IF layer...\n")); |
| 146 break; |
| 147 } |
| 148 |
| 149 /* Set the control buffer size based on the block size */ |
| 150 if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) { |
| 151 ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH; |
| 152 } else { |
| 153 ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH; |
| 154 } |
| 155 for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { |
| 156 target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz); |
| 157 if (target->HTCControlBuffers[i].Buffer == NULL) { |
| 158 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); |
| 159 status = A_ERROR; |
| 160 break; |
| 161 } |
| 162 } |
| 163 |
| 164 if (A_FAILED(status)) { |
| 165 break; |
| 166 } |
| 167 |
| 168 /* carve up buffers/packets for control messages */ |
| 169 for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) { |
| 170 HTC_PACKET *pControlPacket; |
| 171 pControlPacket = &target->HTCControlBuffers[i].HtcPacket; |
| 172 SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket, |
| 173 target, |
| 174 target->HTCControlBuffers[i].Buffer, |
| 175 ctrl_bufsz, |
| 176 ENDPOINT_0); |
| 177 HTC_FREE_CONTROL_RX(target,pControlPacket); |
| 178 } |
| 179 |
| 180 for (;i < NUM_CONTROL_BUFFERS;i++) { |
| 181 HTC_PACKET *pControlPacket; |
| 182 pControlPacket = &target->HTCControlBuffers[i].HtcPacket; |
| 183 INIT_HTC_PACKET_INFO(pControlPacket, |
| 184 target->HTCControlBuffers[i].Buffer, |
| 185 ctrl_bufsz); |
| 186 HTC_FREE_CONTROL_TX(target,pControlPacket); |
| 187 } |
| 188 |
| 189 } while (FALSE); |
| 190 |
| 191 if (A_FAILED(status)) { |
| 192 if (target != NULL) { |
| 193 HTCCleanup(target); |
| 194 target = NULL; |
| 195 } |
| 196 } |
| 197 |
| 198 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n")); |
| 199 |
| 200 return target; |
| 201 } |
| 202 |
| 203 void HTCDestroy(HTC_HANDLE HTCHandle) |
| 204 { |
| 205 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 206 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%X \n",(A_UIN
T32)target)); |
| 207 HTCCleanup(target); |
| 208 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n")); |
| 209 } |
| 210 |
| 211 /* get the low level HIF device for the caller , the caller may wish to do low l
evel |
| 212 * HIF requests */ |
| 213 void *HTCGetHifDevice(HTC_HANDLE HTCHandle) |
| 214 { |
| 215 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 216 return target->Device.HIFDevice; |
| 217 } |
| 218 |
| 219 /* wait for the target to arrive (sends HTC Ready message) |
| 220 * this operation is fully synchronous and the message is polled for */ |
| 221 A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) |
| 222 { |
| 223 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 224 A_STATUS status; |
| 225 HTC_PACKET *pPacket = NULL; |
| 226 HTC_READY_EX_MSG *pRdyMsg; |
| 227 HTC_SERVICE_CONNECT_REQ connect; |
| 228 HTC_SERVICE_CONNECT_RESP resp; |
| 229 |
| 230 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A
_UINT32)target)); |
| 231 |
| 232 do { |
| 233 |
| 234 #ifdef MBOXHW_UNIT_TEST |
| 235 |
| 236 status = DoMboxHWTest(&target->Device); |
| 237 |
| 238 if (status != A_OK) { |
| 239 break; |
| 240 } |
| 241 |
| 242 #endif |
| 243 |
| 244 /* we should be getting 1 control message that the target is ready *
/ |
| 245 status = HTCWaitforControlMessage(target, &pPacket); |
| 246 |
| 247 if (A_FAILED(status)) { |
| 248 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n")); |
| 249 break; |
| 250 } |
| 251 |
| 252 /* we controlled the buffer creation so it has to be properly aligne
d */ |
| 253 pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer; |
| 254 |
| 255 if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) || |
| 256 (pPacket->ActualLength < sizeof(HTC_READY_MSG))) { |
| 257 /* this message is not valid */ |
| 258 AR_DEBUG_ASSERT(FALSE); |
| 259 status = A_EPROTO; |
| 260 break; |
| 261 } |
| 262 |
| 263 |
| 264 if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Inf
o.CreditSize == 0) { |
| 265 /* this message is not valid */ |
| 266 AR_DEBUG_ASSERT(FALSE); |
| 267 status = A_EPROTO; |
| 268 break; |
| 269 } |
| 270 |
| 271 target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount; |
| 272 target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize; |
| 273 |
| 274 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size
: %d\n", |
| 275 target->TargetCredits, target->TargetCreditSize)); |
| 276 |
| 277 /* check if this is an extended ready message */ |
| 278 if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) { |
| 279 /* this is an extended message */ |
| 280 target->HTCTargetVersion = pRdyMsg->HTCVersion; |
| 281 target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle; |
| 282 } else { |
| 283 /* legacy */ |
| 284 target->HTCTargetVersion = HTC_VERSION_2P0; |
| 285 target->MaxMsgPerBundle = 0; |
| 286 } |
| 287 |
| 288 #ifdef HTC_FORCE_LEGACY_2P0 |
| 289 /* for testing and comparison...*/ |
| 290 target->HTCTargetVersion = HTC_VERSION_2P0; |
| 291 target->MaxMsgPerBundle = 0; |
| 292 #endif |
| 293 |
| 294 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, |
| 295 ("Using HTC Protocol Version : %s (%d)\n ", |
| 296 (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">=
2.1", |
| 297 target->HTCTargetVersion)); |
| 298 |
| 299 if (target->MaxMsgPerBundle > 0) { |
| 300 /* limit what HTC can handle */ |
| 301 target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->M
axMsgPerBundle); |
| 302 /* target supports message bundling, setup device layer */ |
| 303 if (A_FAILED(DevSetupMsgBundling(&target->Device,target->MaxMsgPerBu
ndle))) { |
| 304 /* device layer can't handle bundling */ |
| 305 target->MaxMsgPerBundle = 0; |
| 306 } else { |
| 307 /* limit bundle what the device layer can handle */ |
| 308 target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target
->Device), |
| 309 target->MaxMsgPerBundle); |
| 310 } |
| 311 } |
| 312 |
| 313 if (target->MaxMsgPerBundle > 0) { |
| 314 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, |
| 315 (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", targ
et->MaxMsgPerBundle)); |
| 316 target->SendBundlingEnabled = TRUE; |
| 317 target->RecvBundlingEnabled = TRUE; |
| 318 if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSi
ze)) { |
| 319 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not blo
ck aligned! Disabling send bundling \n", |
| 320 target->TargetCreditSize)); |
| 321 /* disallow send bundling since the credit size is not align
ed to a block size |
| 322 * the I/O block padding will spill into the next credit buf
fer which is fatal */ |
| 323 target->SendBundlingEnabled = FALSE; |
| 324 } |
| 325 } |
| 326 |
| 327 /* setup our pseudo HTC control endpoint connection */ |
| 328 A_MEMZERO(&connect,sizeof(connect)); |
| 329 A_MEMZERO(&resp,sizeof(resp)); |
| 330 connect.EpCallbacks.pContext = target; |
| 331 connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; |
| 332 connect.EpCallbacks.EpRecv = HTCControlRecv; |
| 333 connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */ |
| 334 connect.EpCallbacks.EpSendFull = NULL; /* not nedded */ |
| 335 connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS; |
| 336 connect.ServiceID = HTC_CTRL_RSVD_SVC; |
| 337 |
| 338 /* connect fake service */ |
| 339 status = HTCConnectService((HTC_HANDLE)target, |
| 340 &connect, |
| 341 &resp); |
| 342 |
| 343 if (!A_FAILED(status)) { |
| 344 break; |
| 345 } |
| 346 |
| 347 } while (FALSE); |
| 348 |
| 349 if (pPacket != NULL) { |
| 350 HTC_FREE_CONTROL_RX(target,pPacket); |
| 351 } |
| 352 |
| 353 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); |
| 354 |
| 355 return status; |
| 356 } |
| 357 |
| 358 |
| 359 |
| 360 /* Start HTC, enable interrupts and let the target know host has finished setup
*/ |
| 361 A_STATUS HTCStart(HTC_HANDLE HTCHandle) |
| 362 { |
| 363 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 364 HTC_PACKET *pPacket; |
| 365 A_STATUS status; |
| 366 |
| 367 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); |
| 368 |
| 369 /* make sure interrupts are disabled at the chip level, |
| 370 * this function can be called again from a reboot of the target without
shutting down HTC */ |
| 371 DevDisableInterrupts(&target->Device); |
| 372 /* make sure state is cleared again */ |
| 373 target->OpStateFlags = 0; |
| 374 target->RecvStateFlags = 0; |
| 375 |
| 376 /* now that we are starting, push control receive buffers into the |
| 377 * HTC control endpoint */ |
| 378 |
| 379 while (1) { |
| 380 pPacket = HTC_ALLOC_CONTROL_RX(target); |
| 381 if (NULL == pPacket) { |
| 382 break; |
| 383 } |
| 384 HTCAddReceivePkt((HTC_HANDLE)target,pPacket); |
| 385 } |
| 386 |
| 387 do { |
| 388 |
| 389 AR_DEBUG_ASSERT(target->InitCredits != NULL); |
| 390 AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL); |
| 391 AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL); |
| 392 |
| 393 /* call init credits callback to do the distribution , |
| 394 * NOTE: the first entry in the distribution list is ENDPOINT_0, so |
| 395 * we pass the start of the list after this one. */ |
| 396 target->InitCredits(target->pCredDistContext, |
| 397 target->EpCreditDistributionListHead->pNext, |
| 398 target->TargetCredits); |
| 399 |
| 400 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { |
| 401 DumpCreditDistStates(target); |
| 402 } |
| 403 |
| 404 /* the caller is done connecting to services, so we can indicate to
the |
| 405 * target that the setup phase is complete */ |
| 406 status = HTCSendSetupComplete(target); |
| 407 |
| 408 if (A_FAILED(status)) { |
| 409 break; |
| 410 } |
| 411 |
| 412 /* unmask interrupts */ |
| 413 status = DevUnmaskInterrupts(&target->Device); |
| 414 |
| 415 if (A_FAILED(status)) { |
| 416 HTCStop(target); |
| 417 } |
| 418 |
| 419 } while (FALSE); |
| 420 |
| 421 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); |
| 422 return status; |
| 423 } |
| 424 |
| 425 static void ResetEndpointStates(HTC_TARGET *target) |
| 426 { |
| 427 HTC_ENDPOINT *pEndpoint; |
| 428 int i; |
| 429 |
| 430 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { |
| 431 pEndpoint = &target->EndPoint[i]; |
| 432 |
| 433 A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist)); |
| 434 pEndpoint->ServiceID = 0; |
| 435 pEndpoint->MaxMsgLength = 0; |
| 436 pEndpoint->MaxTxQueueDepth = 0; |
| 437 #ifdef HTC_EP_STAT_PROFILING |
| 438 A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats)); |
| 439 #endif |
| 440 INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers); |
| 441 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); |
| 442 INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue); |
| 443 pEndpoint->target = target; |
| 444 } |
| 445 /* reset distribution list */ |
| 446 target->EpCreditDistributionListHead = NULL; |
| 447 } |
| 448 |
| 449 /* stop HTC communications, i.e. stop interrupt reception, and flush all queued
buffers */ |
| 450 void HTCStop(HTC_HANDLE HTCHandle) |
| 451 { |
| 452 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 453 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); |
| 454 |
| 455 LOCK_HTC(target); |
| 456 /* mark that we are shutting down .. */ |
| 457 target->OpStateFlags |= HTC_OP_STATE_STOPPING; |
| 458 UNLOCK_HTC(target); |
| 459 |
| 460 /* Masking interrupts is a synchronous operation, when this function ret
urns |
| 461 * all pending HIF I/O has completed, we can safely flush the queues */ |
| 462 DevMaskInterrupts(&target->Device); |
| 463 |
| 464 /* flush all send packets */ |
| 465 HTCFlushSendPkts(target); |
| 466 /* flush all recv buffers */ |
| 467 HTCFlushRecvBuffers(target); |
| 468 |
| 469 ResetEndpointStates(target); |
| 470 |
| 471 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); |
| 472 } |
| 473 |
| 474 void HTCDumpCreditStates(HTC_HANDLE HTCHandle) |
| 475 { |
| 476 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 477 |
| 478 LOCK_HTC_TX(target); |
| 479 |
| 480 DumpCreditDistStates(target); |
| 481 |
| 482 UNLOCK_HTC_TX(target); |
| 483 |
| 484 DumpAR6KDevState(&target->Device); |
| 485 } |
| 486 |
| 487 /* report a target failure from the device, this is a callback from the device l
ayer |
| 488 * which uses a mechanism to report errors from the target (i.e. special interru
pts) */ |
| 489 static void HTCReportFailure(void *Context) |
| 490 { |
| 491 HTC_TARGET *target = (HTC_TARGET *)Context; |
| 492 |
| 493 target->TargetFailure = TRUE; |
| 494 |
| 495 if (target->HTCInitInfo.TargetFailure != NULL) { |
| 496 /* let upper layer know, it needs to call HTCStop() */ |
| 497 target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR)
; |
| 498 } |
| 499 } |
| 500 |
| 501 A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, |
| 502 HTC_ENDPOINT_ID Endpoint, |
| 503 HTC_ENDPOINT_STAT_ACTION Action, |
| 504 HTC_ENDPOINT_STATS *pStats) |
| 505 { |
| 506 |
| 507 #ifdef HTC_EP_STAT_PROFILING |
| 508 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 509 A_BOOL clearStats = FALSE; |
| 510 A_BOOL sample = FALSE; |
| 511 |
| 512 switch (Action) { |
| 513 case HTC_EP_STAT_SAMPLE : |
| 514 sample = TRUE; |
| 515 break; |
| 516 case HTC_EP_STAT_SAMPLE_AND_CLEAR : |
| 517 sample = TRUE; |
| 518 clearStats = TRUE; |
| 519 break; |
| 520 case HTC_EP_STAT_CLEAR : |
| 521 clearStats = TRUE; |
| 522 break; |
| 523 default: |
| 524 break; |
| 525 } |
| 526 |
| 527 A_ASSERT(Endpoint < ENDPOINT_MAX); |
| 528 |
| 529 /* lock out TX and RX while we sample and/or clear */ |
| 530 LOCK_HTC_TX(target); |
| 531 LOCK_HTC_RX(target); |
| 532 |
| 533 if (sample) { |
| 534 A_ASSERT(pStats != NULL); |
| 535 /* return the stats to the caller */ |
| 536 A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_E
NDPOINT_STATS)); |
| 537 } |
| 538 |
| 539 if (clearStats) { |
| 540 /* reset stats */ |
| 541 A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT
_STATS)); |
| 542 } |
| 543 |
| 544 UNLOCK_HTC_RX(target); |
| 545 UNLOCK_HTC_TX(target); |
| 546 |
| 547 return TRUE; |
| 548 #else |
| 549 return FALSE; |
| 550 #endif |
| 551 } |
| 552 |
| 553 AR6K_DEVICE *HTCGetAR6KDevice(void *HTCHandle) |
| 554 { |
| 555 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); |
| 556 return &target->Device; |
| 557 } |
| 558 |
OLD | NEW |