static void _WMI_SendEvent(wmi_handle_t handle, adf_nbuf_t pEvt, A_UINT16 EventId, A_UINT16 SeqNo, int Length) { WMI_SVC_CONTEXT *pWMI = (WMI_SVC_CONTEXT *)handle; A_UINT8 *pBuffer; pBuffer = adf_nbuf_push_head(pEvt, sizeof(WMI_CMD_HDR)); A_SET_UINT16_FIELD(pBuffer, WMI_CMD_HDR, commandId, adf_os_htons(EventId)); A_SET_UINT16_FIELD(pBuffer, WMI_CMD_HDR, seqNo, adf_os_htons(SeqNo)); HTC_SendMsg(pWMI->HtcHandle, pWMI->ControlEp, pEvt); }
LOCAL void HTCProcessConfigPipeMsg(HTC_CONTEXT *pHTC, HTC_CONFIG_PIPE_MSG *pMsg) { adf_nbuf_t pBuffer; HTC_CONFIG_PIPE_RESPONSE_MSG *pRspMsg; pBuffer = HTCAllocMsgBuffer(pHTC); /* 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 */ HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); }
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); /* 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); pReady->CreditCount = adf_os_htons((A_UINT16)pHTC->TotalCredits); pReady->MaxEndpoints = ENDPOINT_MAX; /* send out the message */ HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); /* now we need to wait for service connection requests */ }
/* 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); }
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); }