void HTCDestroy(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%p \n",target)); HTCCleanup(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n")); }
void htc_dump_credit_states(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint; int i; for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->EndPoint[i]; if (0 == pEndpoint->ServiceID) { continue; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", pEndpoint->Id, pEndpoint->ServiceID)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEndpoint->TxCredits)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEndpoint->TxCreditSize)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEndpoint->TxCreditsPerMaxMsg)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); } }
/*flush all queued buffers for surpriseremove case*/ void htc_flush_surprise_remove(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; HTC_ENDPOINT *pEndpoint; #ifdef RX_SG_SUPPORT cdf_nbuf_t netbuf; cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; #endif AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove \n")); /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->EndPoint[i]; htc_flush_rx_hold_queue(target, pEndpoint); htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); } hif_flush_surprise_remove(target->hif_dev); #ifdef RX_SG_SUPPORT LOCK_HTC_RX(target); while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) { cdf_nbuf_free(netbuf); } RESET_RX_SG_CONFIG(target); UNLOCK_HTC_RX(target); #endif reset_endpoint_states(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove \n")); }
int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue); }
A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_MSG *SetupComp; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(HTCHandle); #ifdef HTC_HOST_CREDIT_DIST adf_os_assert(target->InitCredits != NULL); adf_os_assert(target->EpCreditDistributionListHead != NULL); adf_os_assert(target->EpCreditDistributionListHead->pNext != NULL); /* call init credits callback to do the distribution , * NOTE: the first entry in the distribution list is ENDPOINT_0, so * we pass the start of the list after this one. */ target->InitCredits(target->pCredDistContext, target->EpCreditDistributionListHead->pNext, target->TargetCredits); #if 1 adf_os_timer_init(target->os_handle, &target->host_htc_credit_debug_timer, host_htc_credit_show, target); adf_os_timer_start(&target->host_htc_credit_debug_timer, 10000); #endif #endif /* allocate a buffer to send */ //netbuf = adf_nbuf_alloc(anet, sizeof(HTC_SETUP_COMPLETE_MSG), HTC_HDR_LENGTH, 0); netbuf = adf_nbuf_alloc(50, HTC_HDR_LENGTH, 0); if (netbuf == ADF_NBUF_NULL) { status = A_NO_MEMORY; break; } /* assemble setup complete message */ SetupComp = (HTC_SETUP_COMPLETE_MSG *)adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_MSG)); SetupComp->MessageID = adf_os_htons(HTC_MSG_SETUP_COMPLETE_ID); /* assemble the HTC header and send to HIF layer */ status = HTCIssueSend(target, ADF_NBUF_NULL, netbuf, 0, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT0); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
A_BOOL HTC_busy(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Ep, a_uint32_t nPkts) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_BOOL busy_flag; HTC_ENDPOINT *pEndpoint; if (Ep >= ENDPOINT_MAX) { adf_os_print("Ep %u is invalid!\n", Ep); adf_os_assert(0); } pEndpoint = &target->EndPoint[Ep]; LOCK_HTC_TX(target); if (pEndpoint->TxBufCnt >= nPkts) { busy_flag = TRUE; } else { busy_flag = FALSE; } UNLOCK_HTC_TX(target); return busy_flag; }
A_STATUS HTCTrySendAll(HTC_HANDLE hHTC) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(hHTC); HTCTrySend(target, NULL, ADF_NBUF_NULL, ADF_NBUF_NULL); return A_OK; }
void HTCDisableRecv(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); if (!HTC_STOPPING(target)) { /* disable */ DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC); } }
A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; HTC_PACKET *pSendPacket; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(target); /* allocate a buffer to send */ pSendPacket = HTCAllocControlTxPacket(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); adf_os_print("%s: allocControlTxPacket failed\n",__func__); status = A_NO_MEMORY; break; } netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); /* assemble setup complete message */ adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupComp = (HTC_SETUP_COMPLETE_EX_MSG *) adf_nbuf_data(netbuf); A_MEMZERO(pSetupComp,sizeof(HTC_SETUP_COMPLETE_EX_MSG)); HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); //if (!htc_credit_flow) { if (0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC will not use TX credit flow control\n")); pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC using TX credit flow control\n")); } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
void HTCDumpCreditStates(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); LOCK_HTC_TX(target); DumpCreditDistStates(target); UNLOCK_HTC_TX(target); }
void htc_destroy(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_destroy .. Destroying :0x%p\n", target)); hif_stop(htc_get_hif_device(HTCHandle)); if (target) htc_cleanup(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n")); }
A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint; HTC_PACKET *pFirstPacket; A_STATUS status = A_OK; HTC_PACKET *pPacket; pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); if (NULL == pFirstPacket) { A_ASSERT(FALSE); return A_EINVAL; } AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n", pFirstPacket->Endpoint, HTC_PACKET_QUEUE_DEPTH(pPktQueue), pFirstPacket->BufferLength)); pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; LOCK_HTC_RX(target); do { if (HTC_STOPPING(target)) { status = A_ERROR; break; } /* store receive packets */ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,pPktQueue); } while (FALSE); UNLOCK_HTC_RX(target); if (A_FAILED(status)) { /* walk through queue and mark each one canceled */ HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { pPacket->Status = A_ECANCELED; } HTC_PACKET_QUEUE_ITERATE_END; DoRecvCompletion(pEndpoint,pPktQueue); } return status; }
A_BOOL htc_get_endpoint_statistics(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_ENDPOINT_STAT_ACTION Action, HTC_ENDPOINT_STATS *pStats) { #ifdef HTC_EP_STAT_PROFILING HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_BOOL clearStats = false; A_BOOL sample = false; switch (Action) { case HTC_EP_STAT_SAMPLE: sample = true; break; case HTC_EP_STAT_SAMPLE_AND_CLEAR: sample = true; clearStats = true; break; case HTC_EP_STAT_CLEAR: clearStats = true; break; default: break; } A_ASSERT(Endpoint < ENDPOINT_MAX); /* lock out TX and RX while we sample and/or clear */ LOCK_HTC_TX(target); LOCK_HTC_RX(target); if (sample) { A_ASSERT(pStats != NULL); /* return the stats to the caller */ A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); } if (clearStats) { /* reset stats */ A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); } UNLOCK_HTC_RX(target); UNLOCK_HTC_TX(target); return true; #else return false; #endif }
/** * htc_ipa_get_ce_resource() - get uc resource on lower layer * @htc_handle: htc context * @ce_sr_base_paddr: copyengine source ring base physical address * @ce_sr_ring_size: copyengine source ring size * @ce_reg_paddr: copyengine register physical address * * Return: None */ void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); if (target->hif_dev != NULL) { hif_ipa_get_ce_resource(target->hif_dev, ce_sr_base_paddr, ce_sr_ring_size, ce_reg_paddr); } }
/* Makes a buffer available to the HTC module */ A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint; A_BOOL unblockRecv = FALSE; A_STATUS status = A_OK; AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+- HTCAddReceivePkt: endPointId: %d, buffer: 0x%X, length: %d\n", pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->BufferLength)); do { AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); pEndpoint = &target->EndPoint[pPacket->Endpoint]; LOCK_HTC_RX(target); if (HTC_STOPPING(target)) { pPacket->Status = A_ECANCELED; status = A_ECANCELED; UNLOCK_HTC_RX(target); pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); break; } /* store receive packet */ HTC_PACKET_ENQUEUE(&pEndpoint->RxBuffers, pPacket); /* check if we are blocked waiting for a new buffer */ if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) { if (target->EpWaitingForBuffers == pPacket->Endpoint) { AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n", target->EpWaitingForBuffers)); target->HTCStateFlags &= ~HTC_STATE_WAIT_BUFFERS; target->EpWaitingForBuffers = ENDPOINT_MAX; unblockRecv = TRUE; } } UNLOCK_HTC_RX(target); if (unblockRecv && !HTC_STOPPING(target)) { /* TODO : implement a buffer threshold count? */ DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); } } while (FALSE); return status; }
A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) { A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A_UINT32)HTCHandle)); A_STATUS status = A_OK; /* a_status_t wait_status;*/ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HIFStart(target->hif_dev); adf_os_print("[%s %d] Starting mutex waiting...\n",adf_os_function, __LINE__); adf_os_mutex_acquire(&target->htc_rdy_mutex); adf_os_print("[%s %d] Finish mutex waiting...\n",adf_os_function, __LINE__); return status; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); return status; }
void HTCTxComp(HTC_HANDLE hHTC, adf_nbuf_t buf, HTC_ENDPOINT_ID ep) { #ifdef __linux__ HTC_ENDPOINT *pEndpoint; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(hHTC); pEndpoint = &target->EndPoint[ep]; if (pEndpoint->EpCallBacks.EpTxComplete != NULL) { pEndpoint->EpCallBacks.EpTxComplete( pEndpoint->EpCallBacks.pContext, buf, ep); } #endif }
void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, void *pCreditDistContext, HTC_CREDIT_DIST_CALLBACK CreditDistFunc, HTC_CREDIT_INIT_CALLBACK CreditInitFunc, HTC_SERVICE_ID ServicePriorityOrder[], int ListLength) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; int ep; if (CreditInitFunc != NULL) { /* caller has supplied their own distribution functions */ target->InitCredits = CreditInitFunc; AR_DEBUG_ASSERT(CreditDistFunc != NULL); target->DistributeCredits = CreditDistFunc; target->pCredDistContext = pCreditDistContext; } else { /* caller wants HTC to do distribution */ /* if caller wants service to handle distributions then * it must set both of these to NULL! */ AR_DEBUG_ASSERT(CreditDistFunc == NULL); target->InitCredits = HTCDefaultCreditInit; target->DistributeCredits = HTCDefaultCreditDist; target->pCredDistContext = target; } /* always add HTC control endpoint first, we only expose the list after the * first one, this is added for TX queue checking */ AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist); /* build the list of credit distribution structures in priority order * supplied by the caller, these will follow endpoint 0 */ for (i = 0; i < ListLength; i++) { /* match services with endpoints and add the endpoints to the distribution list * in FIFO order */ for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) { /* queue this one to the list */ AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist); break; } } AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); } }
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ void htc_stop(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; HTC_ENDPOINT *pEndpoint; #ifdef RX_SG_SUPPORT cdf_nbuf_t netbuf; cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; #endif AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop \n")); /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->EndPoint[i]; htc_flush_rx_hold_queue(target, pEndpoint); htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); if (pEndpoint->ul_is_polled) { cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer); cdf_softirq_timer_free(&pEndpoint->ul_poll_timer); } } /* Note: htc_flush_endpoint_tx for all endpoints should be called before * hif_stop - otherwise htc_tx_completion_handler called from * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer, * might queue the packet again to HIF Layer - which could cause tx * buffer leak */ hif_stop(target->hif_dev); #ifdef RX_SG_SUPPORT LOCK_HTC_RX(target); while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) { cdf_nbuf_free(netbuf); } RESET_RX_SG_CONFIG(target); UNLOCK_HTC_RX(target); #endif reset_endpoint_states(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n")); }
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ void HTCStop(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; HTC_ENDPOINT *pEndpoint; #ifdef RX_SG_SUPPORT adf_nbuf_t netbuf; adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; #endif AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->EndPoint[i]; HTCFlushRxHoldQueue(target,pEndpoint); HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); } /* Note: HTCFlushEndpointTX for all endpoints should be called before * HIFStop - otherwise HTCTxCompletionHandler called from * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer, * might queue the packet again to HIF Layer - which could cause tx * buffer leak */ HIFStop(target->hif_dev); #ifdef RX_SG_SUPPORT LOCK_HTC_RX(target); while ((netbuf = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) { adf_nbuf_free(netbuf); } RESET_RX_SG_CONFIG(target); UNLOCK_HTC_RX(target); #endif ResetEndpointStates(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); }
/* cleanup the HTC instance */ static void HTCCleanup(HTC_TARGET *target) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HIF_Cleanup(target->hif_dev); /*Todo HIF should cleanup if any buffers are there*/ #ifdef HTC_HOST_CREDIT_DIST adf_os_timer_cancel(&target->host_htc_credit_debug_timer); #endif /* release htc_rdy_mutex */ adf_os_mutex_release(&target->htc_rdy_mutex); /* free our instance */ adf_os_mem_free(target); /* TODO : other cleanup */ /* free our instance */ A_FREE(target); }
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ void HTCStop(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); /* mark that we are shutting down .. */ target->HTCStateFlags |= HTC_STATE_STOPPING; /* Masking interrupts is a synchronous operation, when this function returns * all pending HIF I/O has completed, we can safely flush the queues */ DevMaskInterrupts(&target->Device); /* flush all send packets */ HTCFlushSendPkts(target); /* flush all recv buffers */ HTCFlushRecvBuffers(target); ResetEndpointStates(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); }
void HTCUnblockRecv(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_BOOL unblockRecv = FALSE; LOCK_HTC_RX(target); /* check if we are blocked waiting for a new buffer */ if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) { AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n", target->EpWaitingForBuffers)); target->HTCStateFlags &= ~HTC_STATE_WAIT_BUFFERS; target->EpWaitingForBuffers = ENDPOINT_MAX; unblockRecv = TRUE; } UNLOCK_HTC_RX(target); if (unblockRecv && !HTC_STOPPING(target)) { /* re-enable */ DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC); } }
A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pConnectReq, HTC_SERVICE_CONNECT_RESP *pConnectResp) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_STATUS status = A_OK; HTC_PACKET *pRecvPacket = NULL; HTC_PACKET *pSendPacket = NULL; HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; HTC_CONNECT_SERVICE_MSG *pConnectMsg; HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; HTC_ENDPOINT *pEndpoint; unsigned int maxMsgSize = 0; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n", (A_UINT32)target, pConnectReq->ServiceID)); do { AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { /* special case for pseudo control service */ assignedEndpoint = ENDPOINT_0; maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; } else { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); status = A_NO_MEMORY; break; } /* assemble connect service message */ pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; AR_DEBUG_ASSERT(pConnectMsg != NULL); A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; pConnectMsg->ServiceID = pConnectReq->ServiceID; pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; /* check caller if it wants to transfer meta data */ if ((pConnectReq->pMetaData != NULL) && (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* copy meta data into message buffer (after header ) */ A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), pConnectReq->pMetaData, pConnectReq->MetaDataLength); pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pConnectMsg, sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); /* we want synchronous operation */ pSendPacket->Completion = NULL; HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); status = HTCIssueSend(target,pSendPacket); if (A_FAILED(status)) { break; } /* wait for response */ status = HTCWaitforControlMessage(target, &pRecvPacket); if (A_FAILED(status)) { break; } /* we controlled the buffer creation so it has to be properly aligned */ pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } pConnectResp->ConnectRespCode = pResponseMsg->Status; /* check response status */ if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target failed service 0x%X connect request (status:%d)\n", pResponseMsg->ServiceID, pResponseMsg->Status)); status = A_EPROTO; break; } assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID; maxMsgSize = pResponseMsg->MaxMsgSize; if ((pConnectResp->pMetaData != NULL) && (pResponseMsg->ServiceMetaLength > 0) && (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* caller supplied a buffer and the target responded with data */ int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); /* copy the meta data */ A_MEMCPY(pConnectResp->pMetaData, ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), copyLength); pConnectResp->ActualLength = copyLength; } } /* the rest of these are parameter checks so set the error status */ status = A_EPROTO; if (assignedEndpoint >= ENDPOINT_MAX) { AR_DEBUG_ASSERT(FALSE); break; } if (0 == maxMsgSize) { AR_DEBUG_ASSERT(FALSE); break; } pEndpoint = &target->EndPoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; if (pEndpoint->ServiceID != 0) { /* endpoint already in use! */ AR_DEBUG_ASSERT(FALSE); break; } /* return assigned endpoint to caller */ pConnectResp->Endpoint = assignedEndpoint; pConnectResp->MaxMsgLength = maxMsgSize; /* setup the endpoint */ pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; pEndpoint->MaxMsgLength = maxMsgSize; /* copy all the callbacks */ pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; /* set the credit distribution info for this endpoint, this information is * passed back to the credit distribution callback function */ pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; pEndpoint->CreditDist.pHTCReserved = pEndpoint; pEndpoint->CreditDist.Endpoint = assignedEndpoint; pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; if (pConnectReq->MaxSendMsgSize != 0) { /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications * since the host will actually issue smaller messages in the Send path */ if (pConnectReq->MaxSendMsgSize > maxMsgSize) { /* can't be larger than the maximum the target can support */ AR_DEBUG_ASSERT(FALSE); break; } pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize; } else { pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; } if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; } /* save local connection flags */ pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags; status = A_OK; } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } if (pRecvPacket != NULL) { HTC_FREE_CONTROL_RX(target,pRecvPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); return status; }
A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) { A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_READY_EX_MSG *pReadyMsg; HTC_SERVICE_CONNECT_REQ connect; HTC_SERVICE_CONNECT_RESP resp; HTC_READY_MSG *rdy_msg; A_UINT16 htc_rdy_msg_id; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%p) \n", HTCHandle)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n")); do { status = HIFStart(target->hif_dev); if (A_FAILED(status)) { break; } status = HTCWaitRecvCtrlMessage(target); if (A_FAILED(status)) { break; } if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid HTC Ready Msg Len:%d! \n",target->CtrlResponseLength)); status = A_ECOMM; break; } pReadyMsg = (HTC_READY_EX_MSG *)target->CtrlResponseBuffer; rdy_msg = &pReadyMsg->Version2_0_Info; htc_rdy_msg_id = HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID); if (htc_rdy_msg_id != HTC_MSG_READY_ID) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid HTC Ready Msg : 0x%X ! \n",htc_rdy_msg_id)); status = A_ECOMM; break; } target->TotalTransmitCredits = HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT); target->TargetCreditSize = (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE); AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("Target Ready! : transmit resources : %d size:%d\n", target->TotalTransmitCredits, target->TargetCreditSize)); if ((0 == target->TotalTransmitCredits) || (0 == target->TargetCreditSize)) { status = A_ECOMM; break; } /* done processing */ target->CtrlResponseProcessing = FALSE; HTCSetupTargetBufferAssignments(target); /* setup our pseudo HTC control endpoint connection */ A_MEMZERO(&connect,sizeof(connect)); A_MEMZERO(&resp,sizeof(resp)); connect.EpCallbacks.pContext = target; connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; connect.EpCallbacks.EpRecv = HTCControlRxComplete; connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS; connect.ServiceID = HTC_CTRL_RSVD_SVC; /* connect fake service */ status = HTCConnectService((HTC_HANDLE)target, &connect, &resp); } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit (%d)\n",status)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("-HWT\n")); return status; }
/* get the low level HIF device for the caller , the caller may wish to do low level * HIF requests */ void *HTCGetHifDevice(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); return target->hif_dev; }
/* Start HTC, enable interrupts and let the target know host has finished setup */ A_STATUS HTCStart(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_PACKET *pPacket; A_STATUS status; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); printk("HTCStart Enter\n"); /* make sure interrupts are disabled at the chip level, * this function can be called again from a reboot of the target without shutting down HTC */ DevDisableInterrupts(&target->Device); /* make sure state is cleared again */ target->HTCStateFlags = 0; /* now that we are starting, push control receive buffers into the * HTC control endpoint */ while (1) { pPacket = HTC_ALLOC_CONTROL_RX(target); if (NULL == pPacket) { break; } HTCAddReceivePkt((HTC_HANDLE)target,pPacket); } do { AR_DEBUG_ASSERT(target->InitCredits != NULL); AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL); AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL); /* call init credits callback to do the distribution , * NOTE: the first entry in the distribution list is ENDPOINT_0, so * we pass the start of the list after this one. */ target->InitCredits(target->pCredDistContext, target->EpCreditDistributionListHead->pNext, target->TargetCredits); if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { DumpCreditDistStates(target); } /* the caller is done connecting to services, so we can indicate to the * target that the setup phase is complete */ status = HTCSendSetupComplete(target); if (A_FAILED(status)) { break; } /* unmask interrupts */ status = DevUnmaskInterrupts(&target->Device); if (A_FAILED(status)) { HTCStop(target); } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); printk("HTCStart Exit\n"); return status; }
/* wait for the target to arrive (sends HTC Ready message) * this operation is fully synchronous and the message is polled for */ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_STATUS status; HTC_PACKET *pPacket = NULL; HTC_READY_MSG *pRdyMsg; HTC_SERVICE_CONNECT_REQ connect; HTC_SERVICE_CONNECT_RESP resp; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A_UINT32)target)); do { #ifdef MBOXHW_UNIT_TEST status = DoMboxHWTest(&target->Device); if (status != A_OK) { break; } #endif /* we should be getting 1 control message that the target is ready */ status = HTCWaitforControlMessage(target, &pPacket); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n")); break; } /* we controlled the buffer creation so it has to be properly aligned */ pRdyMsg = (HTC_READY_MSG *)pPacket->pBuffer; if ((pRdyMsg->MessageID != HTC_MSG_READY_ID) || (pPacket->ActualLength < sizeof(HTC_READY_MSG))) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } if (pRdyMsg->CreditCount == 0 || pRdyMsg->CreditSize == 0) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } target->TargetCredits = pRdyMsg->CreditCount; target->TargetCreditSize = pRdyMsg->CreditSize; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Target Ready: credits: %d credit size: %d\n", target->TargetCredits, target->TargetCreditSize)); printk(" Target Ready: credits: %d credit size: %d\n",target->TargetCredits, target->TargetCreditSize); /* setup our pseudo HTC control endpoint connection */ A_MEMZERO(&connect,sizeof(connect)); A_MEMZERO(&resp,sizeof(resp)); connect.EpCallbacks.pContext = target; connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; connect.EpCallbacks.EpRecv = HTCControlRecv; connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */ connect.EpCallbacks.EpSendFull = NULL; /* not nedded */ connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS; connect.ServiceID = HTC_CTRL_RSVD_SVC; /* connect fake service */ status = HTCConnectService((HTC_HANDLE)target, &connect, &resp); if (!A_FAILED(status)) { break; } } while (FALSE); if (pPacket != NULL) { HTC_FREE_CONTROL_RX(target,pPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); return status; }
/* set the instance block for this HTC handle, so that on removal, the blob can be * returned to the caller */ void HTCSetInstance(HTC_HANDLE HTCHandle, void *Instance) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); target->pInstanceContext = Instance; }
void *htc_get_targetdef(HTC_HANDLE htc_handle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); return hif_get_targetdef(target->hif_dev); }