コード例 #1
0
/* 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 */
    
	switch ( adf_os_ntohs(pMsg->MessageID) ) {        
        case HTC_MSG_CONNECT_SERVICE_ID:
		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 */
		break;
        default:
		;
	}  
        
	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 */
		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();
		}
	}
}
コード例 #2
0
/* 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); 
    
	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().
	 */       
        
	pEndpoint->pService->ProcessRecvMsg(eid, hdr_buf, buffer, pEndpoint->pService->ServiceCtx);

	/* 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); 
}
コード例 #3
0
static void WMIRecvMessageHandler(HTC_ENDPOINT_ID EndPt, adf_nbuf_t hdr_buf,
				  adf_nbuf_t pHTCBuf, void *arg)
{
	void *pContext;
	WMI_SVC_CONTEXT *pWMI = (WMI_SVC_CONTEXT *)arg;
	WMI_DISPATCH_TABLE *pCurrentTable;
	WMI_DISPATCH_ENTRY*pCurrentEntry;
	WMI_CMD_HANDLER pCmdHandler;
	A_UINT8* pCmdBuffer;
	int i;
	A_UINT16 cmd;
	A_UINT16 seq;
	int length;
	a_uint8_t *anbdata;
	a_uint32_t anblen;
	WMI_CMD_HDR *cmdHdr;

	adf_os_assert(hdr_buf == ADF_NBUF_NULL);

	do {
		length = adf_nbuf_len(pHTCBuf);
		if (length < sizeof(WMI_CMD_HDR)) {
			break;
		}

		adf_nbuf_peek_header(pHTCBuf, &anbdata, &anblen);

		pCurrentTable = pWMI->pDispatchHead;
		length = length - sizeof(WMI_CMD_HDR);

		cmdHdr = (WMI_CMD_HDR *)anbdata;
		cmd = adf_os_ntohs(cmdHdr->commandId);
		seq = adf_os_ntohs(cmdHdr->seqNo);

		pCmdBuffer = anbdata + sizeof(WMI_CMD_HDR);
		pCmdHandler = NULL;

		while (pCurrentTable != NULL) {

			pContext = pCurrentTable->pContext;
			pCurrentEntry = pCurrentTable->pTable;

			/* scan table entries */
			for (i = 0; i < pCurrentTable->NumberOfEntries; i++, pCurrentEntry++) {
				if (pCurrentEntry->CmdID == cmd) {
					/* found a match */
					pCmdHandler = pCurrentEntry->pCmdHandler;

					/* optionally check length */
					if ((pCurrentEntry->CheckLength != 0) &&
					    (length < pCurrentEntry->CheckLength)) {
						/* do not process command */
						pCmdHandler = NULL;
					}
					/* end search */
					break;
				}
			}

			if (pCmdHandler != NULL) {
				/* found a handler */
				break;
			}

			/* scan next table */
			pCurrentTable = pCurrentTable->pNext;
		}

		if (NULL == pCmdHandler) {
			break;
		}

		/* if we get here, we have a command handler to dispatch */

		/* call dispatch function */
		pCmdHandler(pContext, cmd, seq, pCmdBuffer, length);

	} while (FALSE);


        /* Invalidate the buffer (including HTC header). Note : we only need to invalidate up to the portion
	 * that was used (cache invalidate will also round up to the nearest cache line).
	 * The rest of the buffer should still be coherent.
	 * */

	HTC_ReturnBuffers(pWMI->HtcHandle, EndPt, pHTCBuf);
}
コード例 #4
0
/* 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;
	adf_nbuf_t pBuffer;
	HTC_CONNECT_SERVICE_RESPONSE_MSG *pRspMsg;
	int metaDataOutLen = 0;
	A_UINT16 serviceId = adf_os_ntohs(pMsg->ServiceID);
    
	pBuffer = HTCAllocMsgBuffer(pHTC);
	/* 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) {
				/* the meta data follows the connect service message */
				pMetaDataIN = ((A_UINT8 *)pMsg) + sizeof(HTC_CONNECT_SERVICE_MSG);
			}

			/* 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) {
				/* 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 */
	HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); 
}
コード例 #5
0
ファイル: htc_send.c プロジェクト: KHATEEBNSIT/AP
/* process credit reports and call distribution function */
void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt0, a_uint32_t RecLen, HTC_ENDPOINT_ID FromEndpoint)
{
    a_uint32_t i;
    a_uint32_t NumEntries;

#ifdef HTC_HOST_CREDIT_DIST
    a_uint32_t totalCredits = 0;
    a_uint8_t doDist = FALSE;
    HTC_ENDPOINT *pEndpoint;

    a_uint16_t seq_diff;
    a_uint16_t tgt_seq;
#endif
    HTC_CREDIT_REPORT_1_1 *pRpt = (HTC_CREDIT_REPORT_1_1 *)pRpt0 ;
    

    NumEntries = RecLen / (sizeof(HTC_CREDIT_REPORT_1_1)) ;
    /* lock out TX while we update credits */
    LOCK_HTC_TX(target);

    for (i = 0; i < NumEntries; i++, pRpt++) {

        if (pRpt->EndpointID >= ENDPOINT_MAX) {
            adf_os_assert(0);
            break;
        }
#ifdef HTC_HOST_CREDIT_DIST
        pEndpoint = &target->EndPoint[pRpt->EndpointID];

        tgt_seq =  adf_os_ntohs(pRpt->TgtCreditSeqNo);
        if (ENDPOINT0 == pRpt->EndpointID) {
            /* always give endpoint 0 credits back */
            seq_diff =  (tgt_seq - pEndpoint->LastCreditSeq)  & (HTC_SEQ_MAX -1);

            pEndpoint->CreditDist.TxCredits += seq_diff;
            pEndpoint->LastCreditSeq = tgt_seq;

        }
        else {
            /* for all other endpoints, update credits to distribute, the distribution function
             * will handle giving out credits back to the endpoints */

#ifdef MAGPIE_HIF_GMAC
            if ( pRpt->EndpointID == 6 ) 
                OS_SET_TIMER(&host_seek_credit_timer, 1000);
#endif            
            
            seq_diff =  (tgt_seq - pEndpoint->LastCreditSeq)  & (HTC_SEQ_MAX -1);

            pEndpoint->CreditDist.TxCreditsToDist += seq_diff;
            pEndpoint->LastCreditSeq = tgt_seq;
            /* flag that we have to do the distribution */
            doDist = TRUE;
        }

        totalCredits += seq_diff;
#endif
        
    }
#ifdef HTC_HOST_CREDIT_DIST
    if (doDist) {
        /* this was a credit return based on a completed send operations
         * note, this is done with the lock held */       
        DO_DISTRIBUTION(target,
                        HTC_CREDIT_DIST_SEND_COMPLETE,
                        "Send Complete",
                        target->EpCreditDistributionListHead->pNext);        
    }
#endif
    UNLOCK_HTC_TX(target);
    
}