X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=target_firmware%2Fmagpie_fw_dev%2Fbuild%2Fmagpie_1_1%2Fsboot%2Fhtc%2Fsrc%2Fhtc.c;fp=target_firmware%2Fmagpie_fw_dev%2Fbuild%2Fmagpie_1_1%2Fsboot%2Fhtc%2Fsrc%2Fhtc.c;h=0000000000000000000000000000000000000000;hb=ff66305a044be28464fa0969ea2d605bb268d478;hp=c3ebb33ef2610092562598093e663e2ee0bb2efb;hpb=60b496560eec004ded92ae4dad43b3d102c6658d;p=open-ath9k-htc-firmware.git diff --git a/target_firmware/magpie_fw_dev/build/magpie_1_1/sboot/htc/src/htc.c b/target_firmware/magpie_fw_dev/build/magpie_1_1/sboot/htc/src/htc.c deleted file mode 100755 index c3ebb33..0000000 --- a/target_firmware/magpie_fw_dev/build/magpie_1_1/sboot/htc/src/htc.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted (subject to the limitations in the - * disclaimer below) provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Qualcomm Atheros nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE - * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT - * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * @File: - * - * @Abstract: host target communications - * - * @Notes: - */ -#include -#include -#include -#include -#include -#include -#include - -#include "htc_internal.h" - -//#define A_ASSERT(m) -#define A_UNCACHED_ADDR(addr) addr -//#define A_MEMZERO(v, size) - -/*** statics vars ****/ -//HTC_CONTEXT g_htcCtx; -//HTC_CONTEXT *g_pHTC = NULL; - -/* prototypes */ -LOCAL void HTCControlSvcProcessMsg(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t hdr_buf, adf_nbuf_t pBuffers, void *arg); -LOCAL void HTCControlSvcProcessSendComplete(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, void *arg); -LOCAL void HTCMsgRecvHandler(adf_nbuf_t hdr_buf, adf_nbuf_t buf, void *context); -LOCAL void HTCSendDoneHandler(adf_nbuf_t buf, void *context); -LOCAL void HTCFreeMsgBuffer(HTC_CONTEXT *pHTC, adf_nbuf_t pBuffer); -LOCAL adf_nbuf_t HTCAllocMsgBuffer(HTC_CONTEXT *pHTC); -//LOCAL void HTC_EnqueuePausedRecv(HTC_ENDPOINT *pEndpoint, -// VBUF *pFirstBuf, -// VBUF *pLastBuf); -//LOCAL VBUF* HTC_DequeuePausedRecv(HTC_ENDPOINT *pEndpoint); -LOCAL void HTCCheckAndSendCreditReport(HTC_CONTEXT *pHTC, A_UINT32 EpMask, HTC_ENDPOINT *pEndpoint, HTC_ENDPOINT_ID Id); -LOCAL void AdjustCreditThreshold(HTC_ENDPOINT *pEndpoint); -//LOCAL void _HTC_AddBufferResources(int buffers); -LOCAL void HTC_AssembleBuffers(HTC_CONTEXT *pHTC, int Count, int Size); -LOCAL htc_handle_t _HTC_Init(/*A_UINT32 dataAddr,*/ - HTC_SETUP_COMPLETE_CB SetupComplete, - HTC_CONFIG *pConfig); -LOCAL void _HTC_RegisterService(htc_handle_t handle, HTC_SERVICE *pService); -LOCAL void _HTC_Ready(htc_handle_t handle); -LOCAL void ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, A_BOOL sendCreditFlag); -LOCAL void _HTC_ReturnBuffers(htc_handle_t handle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers); -LOCAL void _HTC_ReturnBuffersList(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_queue_t bufHead); -LOCAL void _HTC_SendMsg(htc_handle_t handle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers); -void _HTC_PauseRecv(HTC_ENDPOINT_ID EndpointID); -void _HTC_ResumeRecv(HTC_ENDPOINT_ID EndpointID); -LOCAL void HTCProcessConnectMsg(HTC_CONTEXT *pHTC, HTC_CONNECT_SERVICE_MSG *pMsg); -LOCAL void HTCProcessConfigPipeMsg(HTC_CONTEXT *pHTC, HTC_CONFIG_PIPE_MSG *pMsg); -LOCAL void RedistributeCredit(adf_nbuf_t buf, int toPipeId); -LOCAL void _HTC_Shutdown(htc_handle_t htcHandle); - - /* macro to check if the service wants to prevent credit dribbling by using - a dynamic threshold */ -#define CHECK_AND_ADJUST_CREDIT_THRESHOLD(pEndpoint) \ - if ((pEndpoint)->ConnectionFlags & HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE) { \ - AdjustCreditThreshold((pEndpoint)); \ - } - -/***********************************************************************************************/ -/************************ MODULE API implementation *******************************************/ -#if 0 -LOCAL void _HTC_AddBufferResources(int buffers) -{ - (void)buffers; - //MboxHW_AddDMAResources(buffers); -} -#endif - -LOCAL void HTC_AssembleBuffers(HTC_CONTEXT *pHTC, int Count, int Size) -{ - BUF_Pool_create_pool(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, Count, Size); -} - - -LOCAL htc_handle_t _HTC_Init(HTC_SETUP_COMPLETE_CB SetupComplete, - HTC_CONFIG *pConfig) -{ - HIF_CALLBACK hifCBConfig; - HTC_CONTEXT *pHTC; - - //if (NULL == g_pHTC) - { - pHTC = (HTC_CONTEXT *)adf_os_mem_alloc(sizeof(HTC_CONTEXT)); - //g_pHTC = &g_htcCtx; - } - - adf_os_mem_zero(pHTC, sizeof(HTC_CONTEXT)); - - pHTC->OSHandle = pConfig->OSHandle; - pHTC->PoolHandle = pConfig->PoolHandle; - pHTC->hifHandle = pConfig->HIFHandle; - - //A_MEMZERO(&hwConfig,sizeof(hwConfig)); - hifCBConfig.send_buf_done = A_INDIR(htc._HTC_SendDoneHandler); - hifCBConfig.recv_buf = A_INDIR(htc._HTC_MsgRecvHandler); - hifCBConfig.context = pHTC; - - /* initialize hardware layer */ - HIF_register_callback(pConfig->HIFHandle, &hifCBConfig); - - /* see if the host wants us to override the number of ctrl buffers */ - //g_pHTC->NumBuffersForCreditRpts = (HOST_INTEREST->hi_mbox_io_block_sz >> 16) & 0xF; - pHTC->NumBuffersForCreditRpts = 0; - - if (0 == pHTC->NumBuffersForCreditRpts) { - /* nothing to override, simply set default */ - pHTC->NumBuffersForCreditRpts = HTC_DEFAULT_NUM_CTRL_BUFFERS; - } - - //g_pHTC->MaxEpPendingCreditRpts = (HOST_INTEREST->hi_mbox_io_block_sz >> 20) & 0xF; - pHTC->MaxEpPendingCreditRpts = 0; - - if (0 == pHTC->MaxEpPendingCreditRpts) { - pHTC->MaxEpPendingCreditRpts = HTC_DEFAULT_MAX_EP_PENDING_CREDIT_REPORTS; - } - /* calculate the total allocation size based on the number of credit report buffers */ - pHTC->CtrlBufferAllocSize = MIN_CREDIT_BUFFER_ALLOC_SIZE * pHTC->NumBuffersForCreditRpts; - /* we need at least enough buffer space for 1 ctrl message */ - pHTC->CtrlBufferAllocSize = A_MAX(pHTC->CtrlBufferAllocSize,MAX_HTC_SETUP_MSG_SIZE); - - //A_PRINTF("%d, %d, (%d, %d) %s-%s \n",g_pHTC->NumBuffersForCreditRpts,g_pHTC->CtrlBufferAllocSize, - // MIN_BUF_SIZE_FOR_RPTS, MIN_CREDIT_BUFFER_ALLOC_SIZE,__DATE__, __TIME__); - - /* save the size of each buffer/credit we will receive */ - pHTC->RecvBufferSize = pConfig->CreditSize; //RecvBufferSize; - pHTC->TotalCredits = pConfig->CreditNumber; - //g_pHTC->FreeCreditList = pConfig->CreditList; - pHTC->TotalCreditsAssigned = 0; - - /* setup the pseudo service that handles HTC control messages */ - pHTC->HTCControlService.ProcessRecvMsg = A_INDIR(htc._HTC_ControlSvcProcessMsg); - pHTC->HTCControlService.ProcessSendBufferComplete = A_INDIR(htc._HTC_ControlSvcProcessSendComplete); - pHTC->HTCControlService.TrailerSpcCheckLimit = HTC_CTRL_BUFFER_CHECK_SIZE; - pHTC->HTCControlService.MaxSvcMsgSize = MAX_HTC_SETUP_MSG_SIZE; - pHTC->HTCControlService.ServiceCtx = pHTC; - - /* automatically register this pseudo service to endpoint 1 */ - pHTC->Endpoints[ENDPOINT0].pService = &pHTC->HTCControlService; - HIF_get_default_pipe(pHTC->hifHandle, &pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, - &pHTC->Endpoints[ENDPOINT0].DownLinkPipeID); - - /* Initialize control pipe so we could receive the HTC control packets */ - // @TODO: msg size! - HIF_config_pipe(pHTC->hifHandle, pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, 1); - - /* set the first free endpoint */ - pHTC->CurrentEpIndex = ENDPOINT1; - pHTC->SetupCompleteCb = SetupComplete; - - /* setup buffers for just the setup phase, we only need 1 buffer to handle - * setup */ - HTC_AssembleBuffers(pHTC, 4, MAX_HTC_SETUP_MSG_SIZE); - - /* start hardware layer so that we can queue buffers */ - HIF_start(pHTC->hifHandle); - - return pHTC; -} - -LOCAL void _HTC_Shutdown(htc_handle_t htcHandle) -{ - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - - adf_os_mem_free(pHTC); -} - -LOCAL void _HTC_RegisterService(htc_handle_t htcHandle, HTC_SERVICE *pService) -{ - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - - /* add it to the list */ - pService->pNext = pHTC->pServiceList; - pHTC->pServiceList = pService; -} - -LOCAL void _HTC_Ready(htc_handle_t htcHandle) -{ - adf_nbuf_t pBuffer; - HTC_READY_MSG *pReady; - a_uint8_t *addr; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - - pBuffer = HTCAllocMsgBuffer(pHTC); - //A_ASSERT(pBuffer != NULL); - - /* an optimization... the header length is chosen to - * be aligned on a 16 bit bounday, the fields in the message are designed to - * be aligned */ - addr = adf_nbuf_put_tail(pBuffer, sizeof(HTC_READY_MSG)); - pReady = (HTC_READY_MSG *)addr; - A_MEMZERO(pReady,sizeof(HTC_READY_MSG)); - pReady->MessageID = adf_os_htons(HTC_MSG_READY_ID); - pReady->CreditSize = adf_os_htons((A_UINT16)pHTC->RecvBufferSize); - //A_ASSERT(g_pHTC->TotalCredits <= MAX_HTC_CREDITS); - pReady->CreditCount = adf_os_htons((A_UINT16)pHTC->TotalCredits); - pReady->MaxEndpoints = ENDPOINT_MAX; - - /* send out the message */ - //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length); - HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); - /* now we need to wait for service connection requests */ -} - -LOCAL void ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, A_BOOL sendCreditFlag) -{ - int nbufs = 1; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - - //A_ASSERT(EndpointID < ENDPOINT_MAX); - - /* supply some head-room again */ - adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH); - //A_DATA_CACHE_INVAL(pBuffers->buffer, pBuffers->actual_length + HTC_HDR_SZ); - - /* enqueue all buffers to the single mailbox */ - HIF_return_recv_buf(pHTC->hifHandle, pHTC->Endpoints[EndpointID].UpLinkPipeID, pBuffers); - //A_ASSERT(nbufs != 0); - - if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) { - A_UINT32 epCreditMask = (1 << EndpointID); - /* we are running normally */ - /* update pending credit counts with the number of buffers that were added */ - pHTC->Endpoints[EndpointID].CreditsToReturn += (A_INT16)nbufs; - pHTC->Endpoints[EndpointID].CreditsConsumed -= (A_INT16)nbufs; - //A_ASSERT(g_pHTC->Endpoints[EndpointID].CreditsConsumed >= 0); - /* update bit map that this endpoint has non-zero credits */ - pHTC->EpCreditPendingMap |= epCreditMask; - - if (sendCreditFlag) { - HTCCheckAndSendCreditReport(pHTC, epCreditMask,&pHTC->Endpoints[EndpointID],EndpointID); - } - - } else { - /* we have not started yet so all return operations are simply adding buffers - * to the interface at startup, so we can keep track of how many total - * credits we get */ - /* update global count that will be returned to the host */ - pHTC->TotalCredits += nbufs; - } -} - -LOCAL void _HTC_ReturnBuffersList(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_queue_t bufHead) -{ - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - adf_nbuf_t netbuf, tmpNbuf; - - /* retrieve each nbuf in the queue */ - netbuf = adf_nbuf_queue_first(&bufHead); - - while (netbuf) { - - tmpNbuf = netbuf; - netbuf = adf_nbuf_queue_next(netbuf); - - ReturnBuffers(htcHandle, EndpointID, tmpNbuf, FALSE); - } - - HTCCheckAndSendCreditReport(pHTC, (1 << EndpointID),&pHTC->Endpoints[EndpointID],EndpointID); -} - -LOCAL void _HTC_ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers) -{ - ReturnBuffers(htcHandle, EndpointID, pBuffers, TRUE); -} - -LOCAL void _HTC_SendMsg(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers) -{ - HTC_FRAME_HDR *pHTCHdr; - int totsz; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - HTC_BUF_CONTEXT *ctx; - - ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers); - - /* init total size (this does not include the space we will put in for the HTC header) */ - totsz = adf_nbuf_len(pBuffers); - - /* the first buffer stores the header */ - /* back up buffer by a header size when we pass it down, by agreed upon convention the caller - * points the buffer to it's payload and leaves head room for the HTC header - * Note: in HTCSendDoneHandler(), we undo this so that the caller get's it's buffer - * back untainted */ - pHTCHdr = (HTC_FRAME_HDR *)adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH); - - /* flag that this is the header buffer that was modified */ - ctx->htc_flags |= HTC_FLAGS_BUF_HDR; - /* mark where this buffer came from */ - ctx->end_point = EndpointID; - /* the header start is ALWAYS aligned since we DMA it directly */ - //pHTCHdr = (HTC_FRAME_HDR *)A_UNCACHED_ADDR(VBUF_GET_DATA_ADDR(pBuffers)); - /* set some fields, the rest of them will be filled below when we check for - * trailer space */ - pHTCHdr->Flags = 0; - pHTCHdr->EndpointID = EndpointID; - - //A_ASSERT(totsz <= g_pHTC->Endpoints[EndpointID].pService->MaxSvcMsgSize); - /* check opportunistically if we can return any reports via a trailer */ - do { - int room,i,totalReportBytes; - A_UINT32 creditsPendingMap, compareMask; - HTC_CREDIT_REPORT *pCreditRpt; - HTC_RECORD_HDR *pRecHdr; - int pipeMaxLen; - A_UINT32 roomForPipeMaxLen; - - /* figure out how much room the last buffer can spare */ - pipeMaxLen = HIF_get_max_msg_len(pHTC->hifHandle, pHTC->Endpoints[EndpointID].DownLinkPipeID); - roomForPipeMaxLen = pipeMaxLen - adf_nbuf_headroom(pBuffers) - adf_nbuf_len(pBuffers); - if ( roomForPipeMaxLen < 0 ) { - roomForPipeMaxLen = 0; - } - - room = adf_os_min( adf_nbuf_tailroom(pBuffers), roomForPipeMaxLen); - if (room < (int)(sizeof(HTC_CREDIT_REPORT) + sizeof(HTC_RECORD_HDR))) { - /* no room for any reports */ - break; - } - /* note, a record header only has 8 bit fields, so this is safe. - * we need an uncached pointer here too */ - totalReportBytes = 0; - - /* get a copy */ - creditsPendingMap = pHTC->EpCreditPendingMap; - - /* test pending map to see if we can send a report , if any - * credits are available, we might as well send them on the - * unused space in the buffer */ - if (creditsPendingMap) { - - pRecHdr = (HTC_RECORD_HDR *)adf_nbuf_put_tail(pBuffers, sizeof(HTC_RECORD_HDR)); - - /* set the ID, the length will be updated with the number of credit reports we - * can fit (see below) */ - pRecHdr->RecordID = HTC_RECORD_CREDITS; - pRecHdr->Length = 0; - /* the credit report follows the record header */ - totalReportBytes += sizeof(HTC_RECORD_HDR); - room -= sizeof(HTC_RECORD_HDR); - - /* walkthrough pending credits map and build the records */ - for (i = 0; - (creditsPendingMap != 0) && (room >= (int)sizeof(HTC_CREDIT_REPORT)); - i++) { - compareMask = (1 << i); - if (compareMask & creditsPendingMap) { - - pCreditRpt = (HTC_CREDIT_REPORT *)adf_nbuf_put_tail(pBuffers, sizeof(HTC_CREDIT_REPORT)); - - /* clear pending mask, we are going to return all these credits */ - creditsPendingMap &= ~(compareMask); - /* add this record */ - pCreditRpt->EndpointID = i; - pCreditRpt->Credits = (A_UINT8)pHTC->Endpoints[i].CreditsToReturn; - /* remove pending credits, we always send deltas */ - pHTC->Endpoints[i].CreditsToReturn = 0; - /* adjust new threshold for this endpoint if needed */ - CHECK_AND_ADJUST_CREDIT_THRESHOLD(&pHTC->Endpoints[i]); - /* update this record length */ - pRecHdr->Length += sizeof(HTC_CREDIT_REPORT); - room -= sizeof(HTC_CREDIT_REPORT); - totalReportBytes += sizeof(HTC_CREDIT_REPORT); - - if ( room < sizeof(HTC_CREDIT_REPORT) ) { - break; - } - } - } - - /* update new pending credits map */ - pHTC->EpCreditPendingMap = creditsPendingMap; - } - - if (totalReportBytes <= 0) { - break; - } - - /* must fit into a byte, this should never actually happen since - * the maximum possible number of endpoints is 32. - * The trailer can have at most 1 credit record with up to 32 reports in the record. - * The trailer can have at most 1 lookahead record with only 1 lookahead report in the record. - * - * */ - //A_ASSERT(totalReportBytes <= 255); - - /* set header option bytes */ - pHTCHdr->ControlBytes[0] = totalReportBytes; - /* HTC frame contains a trailer */ - pHTCHdr->Flags |= HTC_FLAGS_RECV_TRAILER; - /* increment total size by the reports we added */ - totsz += totalReportBytes; - /* adjust the last buffer we used for adding on the trailer */ - } while (FALSE); - - if (totsz == 0) { - //A_ASSERT(FALSE); - } - - /* set length for message (this includes any reports that were added above) */ - pHTCHdr->PayloadLen = adf_os_htons(totsz); - HIF_send_buffer(pHTC->hifHandle, pHTC->Endpoints[EndpointID].DownLinkPipeID, pBuffers); -} - -void _HTC_PauseRecv(HTC_ENDPOINT_ID EndpointID) -{ -#if 0 // Disable first. Ray -#ifdef HTC_PAUSE_RESUME_REF_COUNTING - g_pHTC->Endpoints[EndpointID].PauseRefCount++; -#endif - /* we are now paused */ - g_pHTC->EpRecvPausedMap |= (1 << EndpointID); -#endif -} - -void _HTC_ResumeRecv(HTC_ENDPOINT_ID EndpointID) -{ -#if 0 // Disable first. Ray - HTC_BUFFER *buffer; - HTC_ENDPOINT *pEndpoint; - - pEndpoint = &g_pHTC->Endpoints[EndpointID]; - -/* TODO: we can't quite use referencing counting yet until we clean up the WLAN - * app, there are some un-matched pause/resume cases that need to be fixed */ -#ifdef HTC_PAUSE_RESUME_REF_COUNTING - pEndpoint->PauseRefCount--; - //A_ASSERT(pEndpoint->PauseRefCount >= 0); - - /* check reference count and unpause if it is zero */ - if (pEndpoint->PauseRefCount > 0) { - return; - } -#endif - - g_pHTC->EpRecvPausedMap &= ~(1 << EndpointID); - /* unload the paused receive queue */ - while ((buffer = HTC_DequeuePausedRecv(pEndpoint)) != NULL) { - /* note that the paused messages have already been processed at the HTC layer, - * we can simply indicate the buffers to the service */ - pEndpoint->pService->ProcessRecvMsg(EndpointID,buffer); - } -#endif -} - -int _HTC_GetReservedHeadroom(htc_handle_t htcHandle) -{ - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle; - - return HTC_HDR_LENGTH + HIF_get_reserved_headroom(pHTC->hifHandle); -} - -void htc_module_install(struct htc_apis *pAPIs) -{ - pAPIs->_HTC_Init = _HTC_Init; - pAPIs->_HTC_ReturnBuffers = _HTC_ReturnBuffers; - pAPIs->_HTC_ReturnBuffersList = _HTC_ReturnBuffersList; - pAPIs->_HTC_Ready = _HTC_Ready; - pAPIs->_HTC_RegisterService = _HTC_RegisterService; - pAPIs->_HTC_SendMsg = _HTC_SendMsg; - pAPIs->_HTC_Shutdown = _HTC_Shutdown; - pAPIs->_HTC_GetReservedHeadroom = _HTC_GetReservedHeadroom; - pAPIs->_HTC_MsgRecvHandler = HTCMsgRecvHandler; - pAPIs->_HTC_SendDoneHandler = HTCSendDoneHandler; - pAPIs->_HTC_ControlSvcProcessMsg = HTCControlSvcProcessMsg; - pAPIs->_HTC_ControlSvcProcessSendComplete = HTCControlSvcProcessSendComplete; - - //pAPIs->_HTC_PauseRecv = _HTC_PauseRecv; - //pAPIs->_HTC_ResumeRecv = _HTC_ResumeRecv; - //pAPIs->_HTC_AddBufferResources = _HTC_AddBufferResources; - /* save ptr to the ptr to the context for external code to inspect/modify internal module state */ - //pAPIs->pReserved = &g_pHTC; -} - -/*******************************************************************************************/ -/**************** INTERNAL ROUTINES to this MODULE ***************************************/ - -/* free message to the free list */ -//LOCAL void HTCFreeMsgBuffer(HTC_BUFFER *pBuffer) -LOCAL void HTCFreeMsgBuffer(HTC_CONTEXT *pHTC, adf_nbuf_t buf) -{ - BUF_Pool_free_buf(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, buf); -} - -/* HTC control message allocator (also used for empty frames to send trailer options) */ -//LOCAL HTC_BUFFER *HTCAllocMsgBuffer(void) -LOCAL adf_nbuf_t HTCAllocMsgBuffer(HTC_CONTEXT *pHTC) -{ - return BUF_Pool_alloc_buf(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, HTC_GetReservedHeadroom(pHTC)); -} - -LOCAL void HTCCheckAndSendCreditReport(HTC_CONTEXT *pHTC, A_UINT32 EpMask, HTC_ENDPOINT *pEndpoint, HTC_ENDPOINT_ID Eid) -{ - adf_nbuf_t pCredBuffer; - HTC_BUF_CONTEXT *ctx; - - do { - /* check if host needs credits */ - if (!(pHTC->EpHostNeedsCreditMap & EpMask)) { - /* host does not need any credits for this set */ - break; - } - /* check if any are pending */ - if (!(pHTC->EpCreditPendingMap & EpMask)) { - /* nothing to send up */ - break; - } - /* was an endpoint specified? */ - if (pEndpoint != NULL) { - /* see if a threshold is in effect for this endpoint */ - if (pEndpoint->CreditReturnThreshhold != 0) { - if (pEndpoint->CreditsToReturn < pEndpoint->CreditReturnThreshhold) { - /* this endpoint is using a threshold to prevent credits from dribbling - * back to the host */ - break; - } - } - - if (pEndpoint->PendingCreditReports >= pHTC->MaxEpPendingCreditRpts) { - /* this endpoint already has some reports outstanding */ - /* flag that as soon as a buffer is reaped, we issue a credit update to - * pick up this credit that is being held up because the endpoint has already - * exceeded the max outstanding credit report limit */ - pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON; - break; - } - } - - /* if we get here we have some credits to send up */ - - /* allocate a message buffer for the trailer */ - pCredBuffer = HTCAllocMsgBuffer(pHTC); - if (NULL == pCredBuffer) { - /* no buffers left to send an empty message with trailers, host will just - * have to wait until we get our endpoint 0 messages back.. */ - /* mark that we need to send an update as soon as we can get a buffer back */ - pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON; - break; - } - - ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pCredBuffer); - if (pEndpoint != NULL) { - /* keep track of pending reports */ - pEndpoint->PendingCreditReports++; - /* save the endpoint in order to decrement the count when the send completes */ - ctx->htc_flags = Eid | HTC_FLAGS_CREDIT_RPT; - } - - /* this is an empty message, the HTC_SendMsg will tack on a trailer in the remaining - * space, NOTE: no need to flush the cache, the header and trailers are assembled - * using uncached addresses */ - HTC_SendMsg(pHTC, ENDPOINT0, pCredBuffer); - - } while (FALSE); -} - -/* called in response to the arrival of a service connection message */ -LOCAL void HTCProcessConnectMsg(HTC_CONTEXT *pHTC, HTC_CONNECT_SERVICE_MSG *pMsg) -{ - HTC_SERVICE *pService = pHTC->pServiceList; - A_UINT8 connectStatus = HTC_SERVICE_NOT_FOUND; - //HTC_BUFFER *pBuffer; - adf_nbuf_t pBuffer; - HTC_CONNECT_SERVICE_RESPONSE_MSG *pRspMsg; - int metaDataOutLen = 0; - A_UINT16 serviceId = adf_os_ntohs(pMsg->ServiceID); - - pBuffer = HTCAllocMsgBuffer(pHTC); - //A_ASSERT(pBuffer != NULL); - /* note : this will be aligned */ - pRspMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *) - adf_nbuf_put_tail(pBuffer, sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG)); - - A_MEMZERO(pRspMsg,sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG)); - pRspMsg->MessageID = adf_os_htons(HTC_MSG_CONNECT_SERVICE_RESPONSE_ID); - /* reflect the service ID for this connect attempt */ - pRspMsg->ServiceID = adf_os_htons(serviceId); - - while (pService) { - - if (pHTC->CurrentEpIndex >= ENDPOINT_MAX) { - /* no more endpoints */ - connectStatus = HTC_SERVICE_NO_RESOURCES; - break; - } - - if (serviceId == pService->ServiceID) { - /* we found a match */ - A_UINT8 *pMetaDataIN = NULL; - A_UINT8 *pMetaDataOut; - - /* outgoing meta data resides in the space after the response message */ - pMetaDataOut = ((A_UINT8 *)pRspMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG); - - if (pMsg->ServiceMetaLength != 0) { - //A_ASSERT(pMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH); - /* the meta data follows the connect service message */ - pMetaDataIN = ((A_UINT8 *)pMsg) + sizeof(HTC_CONNECT_SERVICE_MSG); - } - - //A_ASSERT(pService->ProcessConnect != NULL); - /* call the connect callback with the endpoint to use and pointers to meta data */ - connectStatus = pService->ProcessConnect(pService, - pHTC->CurrentEpIndex, - pMetaDataIN, - pMsg->ServiceMetaLength, - pMetaDataOut, - &metaDataOutLen); - - /* check if the service accepted this connection request */ - if (HTC_SERVICE_SUCCESS == connectStatus) { - //A_ASSERT(metaDataOutLen <= HTC_SERVICE_META_DATA_MAX_LENGTH); - /* set the length of the response meta data going back to the host */ - pRspMsg->ServiceMetaLength = (A_UINT8)metaDataOutLen; - /* set the endpoint ID the host will now communicate over */ - pRspMsg->EndpointID = pHTC->CurrentEpIndex; - /* return the maximum message size for this service */ - pRspMsg->MaxMsgSize = adf_os_htons((A_UINT16)pService->MaxSvcMsgSize); - /* assign this endpoint to this service, this will be used in routing messages */ - pHTC->Endpoints[pHTC->CurrentEpIndex].pService = pService; - /* set connection flags */ - pHTC->Endpoints[pHTC->CurrentEpIndex].ConnectionFlags = pMsg->ConnectionFlags; - - pHTC->Endpoints[pHTC->CurrentEpIndex].DownLinkPipeID = pMsg->DownLinkPipeID; - pHTC->Endpoints[pHTC->CurrentEpIndex].UpLinkPipeID = pMsg->UpLinkPipeID; - - /* mark that we are now connected */ - pService->ServiceFlags |= HTC_SERVICE_FLAGS_CONNECTED; - /* bump up our index, this EP is now in use */ - pHTC->CurrentEpIndex++; - } - - break; - } - - pService = pService->pNext; - } - - pRspMsg->Status = connectStatus; - - /* send out the response message */ - //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length); - HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); -} - -LOCAL void HTCProcessConfigPipeMsg(HTC_CONTEXT *pHTC, HTC_CONFIG_PIPE_MSG *pMsg) -{ - //HTC_SERVICE *pService = g_pHTC->pServiceList; - //A_UINT8 connectStatus = HTC_SERVICE_NOT_FOUND; - adf_nbuf_t pBuffer; - HTC_CONFIG_PIPE_RESPONSE_MSG *pRspMsg; - - pBuffer = HTCAllocMsgBuffer(pHTC); - - //A_ASSERT(pBuffer != NULL); - /* note : this will be aligned */ - pRspMsg = (HTC_CONFIG_PIPE_RESPONSE_MSG *) - adf_nbuf_put_tail(pBuffer, sizeof(HTC_CONFIG_PIPE_RESPONSE_MSG)); - - A_MEMZERO(pRspMsg,sizeof(HTC_CONFIG_PIPE_RESPONSE_MSG)); - - pRspMsg->MessageID = adf_os_htons(HTC_MSG_CONFIG_PIPE_RESPONSE_ID); - /* reflect the service ID for this connect attempt */ - pRspMsg->PipeID = pMsg->PipeID; - - if ( HIF_is_pipe_supported(pHTC->hifHandle, pMsg->PipeID) ) { - pRspMsg->Status = 0; - } else { - pRspMsg->Status = 1; - goto config_done; - } - - if ( (pHTC->TotalCreditsAssigned + pMsg->CreditCount) <= pHTC->TotalCredits ) { - pHTC->TotalCreditsAssigned += pMsg->CreditCount; - } else { - pRspMsg->Status = 2; - goto config_done; - } - - HIF_config_pipe(pHTC->hifHandle, pMsg->PipeID, pMsg->CreditCount); - -config_done: - /* send out the response message */ - //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length); - HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); -} - -/* process an incomming control message from the host */ -LOCAL void HTCControlSvcProcessMsg(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t hdr_buf, adf_nbuf_t pBuffers, void *arg) -{ - A_BOOL setupComplete = FALSE; - a_uint8_t *anbdata; - a_uint32_t anblen; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)arg; - HTC_UNKNOWN_MSG *pMsg; - - adf_os_assert(hdr_buf == ADF_NBUF_NULL); - - /* we assume buffers are aligned such that we can access the message - * parameters directly*/ - adf_nbuf_peek_header(pBuffers, &anbdata, &anblen); - pMsg = (HTC_UNKNOWN_MSG *)anbdata; - - /* we cannot handle fragmented messages across buffers */ - //A_ASSERT(pBuffers->next == NULL); - - switch ( adf_os_ntohs(pMsg->MessageID) ) { - case HTC_MSG_CONNECT_SERVICE_ID: - //A_ASSERT(pBuffers->actual_length >= sizeof(HTC_CONNECT_SERVICE_MSG)); - HTCProcessConnectMsg(pHTC, (HTC_CONNECT_SERVICE_MSG *)pMsg); - break; - case HTC_MSG_CONFIG_PIPE_ID: - HTCProcessConfigPipeMsg(pHTC, (HTC_CONFIG_PIPE_MSG *)pMsg); - break; - case HTC_MSG_SETUP_COMPLETE_ID: - /* the host has indicated that it has completed all - setup tasks and we can now let the services take over to - run the rest of the application */ - setupComplete = TRUE; - /* can't get this more than once */ - //A_ASSERT(!(g_pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE)); - break; - default: - ; - //A_ASSERT(FALSE); - } - - if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) { - /* recycle buffer only if we are fully running */ - HTC_ReturnBuffers(pHTC, ENDPOINT0,pBuffers); - } else { - /* supply some head-room again */ - //A_DATA_CACHE_INVAL(pBuffers->buffer, pBuffers->actual_length + HTC_HDR_SZ); - adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH); - - /* otherwise return the packet back to mbox */ - HIF_return_recv_buf(pHTC->hifHandle, pHTC->Endpoints[EndpointID].UpLinkPipeID, pBuffers); - } - - if (setupComplete) { - /* mark that setup has completed */ - pHTC->StateFlags |= HTC_STATE_SETUP_COMPLETE; - if (pHTC->SetupCompleteCb != NULL) { - pHTC->SetupCompleteCb(); - } - } -} - -/* callback when endpoint 0 send buffers are completed */ -LOCAL void HTCControlSvcProcessSendComplete(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, void *arg) -{ - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)arg; - HTC_BUF_CONTEXT *ctx; - HTC_ENDPOINT_ID creditRptEndpoint; - - ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers); - - //A_ASSERT(EndpointID == ENDPOINT0); - - /* put them back into the pool */ -#if 0 - while (pBuffers != NULL) { - pNext = pBuffers->next_buf; - pBuffers->next_buf = NULL; - /* note: HTC does not send fragmented control messages, so each buffer - * represents 1 full HTC control message */ - if (pBuffers->desc_list->control & HTC_FLAGS_CREDIT_RPT) { - /* extract the endpoint number that requested this credit report */ - creditRptEndpoint = pBuffers->desc_list->control & HTC_FLAGS_CRPT_EP_MASK; - pBuffers->desc_list->control = 0; - g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports--; - //A_ASSERT(g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports >= 0); - } - /* free this one */ - HTCFreeMsgBuffer(pBuffers); - pBuffers = pNext; - } -#else - if ( ctx->htc_flags & HTC_FLAGS_CREDIT_RPT ) { - /* extract the endpoint number that requested this credit report */ - creditRptEndpoint = ctx->htc_flags & HTC_FLAGS_CRPT_EP_MASK; - pHTC->Endpoints[creditRptEndpoint].PendingCreditReports--; - //A_ASSERT(g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports >= 0); - } - - HTCFreeMsgBuffer(pHTC, pBuffers); -#endif - - if (pHTC->StateFlags & HTC_SEND_CREDIT_UPDATE_SOON) { - /* this flag is set when the host could not send a credit report - * because we ran out of HTC control buffers */ - pHTC->StateFlags &= ~HTC_SEND_CREDIT_UPDATE_SOON; - /* send out a report if anything is pending */ - HTCCheckAndSendCreditReport(pHTC, HTC_ANY_ENDPOINT_MASK,NULL,ENDPOINT_MAX); - } -} - -LOCAL void HTCSendDoneHandler(adf_nbuf_t buf, void *context) -{ - A_UINT8 current_eid; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)context; - HTC_BUF_CONTEXT *ctx; - - ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(buf); - current_eid = ctx->end_point; - - /* Walk through the buffers and fixup the ones we used for HTC headers. - * The buffer list may contain more than one string of HTC buffers comprising of an - * HTC message so we need to check every buffer */ - adf_nbuf_pull_head(buf, HTC_HDR_LENGTH); - - pHTC->Endpoints[current_eid].pService-> - ProcessSendBufferComplete(current_eid, - buf, - pHTC->Endpoints[current_eid].pService->ServiceCtx); -} - -#if 0 -LOCAL void HTC_EnqueuePausedRecv(HTC_ENDPOINT *pEndpoint, - HTC_BUFFER *pFirstBuf, - HTC_BUFFER *pLastBuf) -{ - //A_ASSERT(pLastBuf->next == NULL); - - if (NULL == pEndpoint->pRcvPausedQueueTail) { - pEndpoint->pRcvPausedQueueTail = pLastBuf; - pEndpoint->pRcvPausedQueueHead = pFirstBuf; - } else { - /* queue to the tail */ - pEndpoint->pRcvPausedQueueTail->next = pFirstBuf; - pEndpoint->pRcvPausedQueueTail = pLastBuf; - } - -} -#endif - -#if 0 -LOCAL HTC_BUFFER *HTC_DequeuePausedRecv(HTC_ENDPOINT *pEndpoint) -{ - HTC_BUFFER *pHead; - HTC_BUFFER *pCur; - - if (pEndpoint->pRcvPausedQueueHead != NULL) { - /* there is a message in the queue */ - pHead = pEndpoint->pRcvPausedQueueHead; - pCur = pHead; - - while (pCur != NULL) { - /* check for end marker on this buffer */ - if (pCur->htc_flags & HTC_FLAGS_RECV_END_MSG) { - pCur->htc_flags &= ~HTC_FLAGS_RECV_END_MSG; - /* advance the head */ - pEndpoint->pRcvPausedQueueHead = pCur->next; - - if (NULL == pEndpoint->pRcvPausedQueueHead) { - /* list is now empty */ - pEndpoint->pRcvPausedQueueTail = NULL; - } - /* cut this message out */ - pCur->next = NULL; - break; - } - pCur = pCur->next; - } - /* we should always find complete messages with the marker present */ - //A_ASSERT(pCur != NULL); - return pHead; - } else { - //A_ASSERT(pEndpoint->pRcvPausedQueueTail == NULL); - return NULL; - } -} -#endif - -LOCAL void AdjustCreditThreshold(HTC_ENDPOINT *pEndpoint) -{ - - A_INT16 creditsOutstanding = pEndpoint->CreditsToReturn + pEndpoint->CreditsConsumed; - /* set the new threshold based on the number of credits that have been consumed - * and which have not been returned by the app. - * Note: it is okay for this threshold to be zero which indicates no threshold - * is in use */ - switch (pEndpoint->ConnectionFlags & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK) { - case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH : - creditsOutstanding >>= 2; - break; - case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF : - creditsOutstanding >>= 1; - break; - case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS : - creditsOutstanding = (creditsOutstanding * 3) >> 2; - break; - /* default case is unity */ - } - - pEndpoint->CreditReturnThreshhold = creditsOutstanding; - -} - -LOCAL void RedistributeCredit(adf_nbuf_t buf, int toPipeId) -{ - -} - -/* callback from the mailbox hardware layer when a full message arrives */ -LOCAL void HTCMsgRecvHandler(adf_nbuf_t hdr_buf, adf_nbuf_t buffer, void *context) -{ - A_UINT16 totsz; - HTC_ENDPOINT *pEndpoint; - A_UINT32 eidMask; - int eid; - a_uint8_t *anbdata; - a_uint32_t anblen; - HTC_FRAME_HDR *pHTCHdr; - HTC_CONTEXT *pHTC = (HTC_CONTEXT *)context; - adf_nbuf_t tmp_nbuf; - - if (hdr_buf == ADF_NBUF_NULL) { - /* HTC hdr is not in the hdr_buf */ - tmp_nbuf = buffer; - } - else { - tmp_nbuf = hdr_buf; - } - - adf_nbuf_peek_header(tmp_nbuf, &anbdata, &anblen); - pHTCHdr = (HTC_FRAME_HDR *)anbdata; - - totsz = adf_os_ntohs(pHTCHdr->PayloadLen); - - //A_ASSERT(pHTCHdr->EndpointID < ENDPOINT_MAX); - eid = pHTCHdr->EndpointID; - - pEndpoint = &pHTC->Endpoints[eid]; - eidMask = 1 << eid; - - if (pHTCHdr->Flags & HTC_FLAGS_CREDIT_REDISTRIBUTION) { - /* The pipe id where the credit is redistributed to is carried in Control - * Byte 0 */ - RedistributeCredit(tmp_nbuf, pHTCHdr->ControlBytes[0]); - return; - } - - if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) { - /* after setup we keep track of credit consumption to allow us to - * adjust thresholds to reduce credit dribbling */ - pEndpoint->CreditsConsumed ++; - } - - /* from the design document, we put the endpoint into a "host-needs-credit" state - * when we receive a frame with the NEED_CREDIT_UPDATE flag set . - * if the host received credits through an opportunistic path, then it can - * issue a another frame with this bit cleared, this signals the target to clear - * the "host-needs-credit" state */ - if (pHTCHdr->Flags & HTC_FLAGS_NEED_CREDIT_UPDATE) { - /* the host is running low (or is out) of credits on this - * endpoint, update mask */ - pHTC->EpHostNeedsCreditMap |= eidMask; - /* check and set new threshold since host has reached a low credit situation */ - CHECK_AND_ADJUST_CREDIT_THRESHOLD(pEndpoint); - } else { - /* clear the flag */ - pHTC->EpHostNeedsCreditMap &= ~(eidMask); - pEndpoint->CreditReturnThreshhold = 0; - } - - /* Adjust the first buffer to point to the start of the actual - payload, the first buffer contains the header */ - adf_nbuf_pull_head(tmp_nbuf, HTC_HDR_LENGTH); - - /* NOTE : This callback could re-queue the recv buffers within this calling context. - * The callback could also send a response message within the context of this callback - * as the result of parsing this message. In either case, if there are - * pending credits and the host needs them, a credit report will be sent either through - * the response message trailer or a NULL message through HTC_ReturnBuffers(). - */ - - //A_ASSERT(totsz <= pEndpoint->pService->MaxSvcMsgSize); - -#if 0 - /* is this endpoint paused? */ - if (g_pHTC->EpRecvPausedMap & eidMask) { - /* note that curr_buf is the last buffer */ - /* mark the last buffer so that it indicates the end of this message */ - //curr_buf->htc_flags |= HTC_FLAGS_RECV_END_MSG; - /* enqueue this message to our pause queues */ - //HTC_EnqueuePausedRecv(pEndpoint,bufinfo,curr_buf); - } else { - /* pass the message to the service */ - pEndpoint->pService->ProcessRecvMsg(eid, buffer, pEndpoint->pService->ServiceCtx); - } -#else - pEndpoint->pService->ProcessRecvMsg(eid, hdr_buf, buffer, pEndpoint->pService->ServiceCtx); -#endif - - /* Calls to HTC_ReturnBuffers drives the endpoint credit reporting state machine. - * We do not want to delay credits for too long in the event that the application is - * holding onto buffers for excessive periods of time. This gives us "some" better - * opportunities to send up credits. */ - HTCCheckAndSendCreditReport(pHTC, eidMask, pEndpoint, eid); -}