223d2691d38a25e6e6c3dbaedceb8b0e3a210690
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / htc / src / htc.c
1 /*
2  * @File: 
3  * 
4  * @Abstract: host target communications
5  * 
6  * @Notes: 
7  * 
8  * 
9  * Copyright (c) 2007 Atheros Communications Inc.
10  * All rights reserved.
11  *
12  */
13 #include <osapi.h>
14 #include <Magpie_api.h> 
15 #include <htc.h>
16 #include <htc_api.h>
17 #include <hif_api.h>
18 #include <adf_os_mem.h> 
19 #include <adf_os_io.h> 
20
21 #include "htc_internal.h" 
22
23 //#define A_ASSERT(m)
24 #define A_UNCACHED_ADDR(addr) addr
25 //#define A_MEMZERO(v, size)
26
27 /*** statics vars ****/ 
28 //HTC_CONTEXT g_htcCtx;
29 //HTC_CONTEXT *g_pHTC = NULL;
30  
31 /* prototypes */
32 LOCAL void HTCControlSvcProcessMsg(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t hdr_buf, adf_nbuf_t pBuffers, void *arg);
33 LOCAL void HTCControlSvcProcessSendComplete(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, void *arg);
34 LOCAL void HTCMsgRecvHandler(adf_nbuf_t hdr_buf, adf_nbuf_t buf, void *context);
35 LOCAL void HTCSendDoneHandler(adf_nbuf_t buf, void *context);
36 LOCAL void HTCFreeMsgBuffer(HTC_CONTEXT *pHTC, adf_nbuf_t pBuffer);
37 LOCAL adf_nbuf_t HTCAllocMsgBuffer(HTC_CONTEXT *pHTC);
38 //LOCAL void HTC_EnqueuePausedRecv(HTC_ENDPOINT *pEndpoint, 
39 //                                 VBUF   *pFirstBuf,
40 //                                 VBUF   *pLastBuf);
41 //LOCAL VBUF* HTC_DequeuePausedRecv(HTC_ENDPOINT *pEndpoint);
42 LOCAL void HTCCheckAndSendCreditReport(HTC_CONTEXT *pHTC, A_UINT32 EpMask, HTC_ENDPOINT *pEndpoint, HTC_ENDPOINT_ID Id);
43 LOCAL void AdjustCreditThreshold(HTC_ENDPOINT  *pEndpoint);
44 //LOCAL void _HTC_AddBufferResources(int buffers);
45 LOCAL void HTC_AssembleBuffers(HTC_CONTEXT *pHTC, int Count, int Size);
46 LOCAL htc_handle_t _HTC_Init(/*A_UINT32 dataAddr,*/
47         HTC_SETUP_COMPLETE_CB SetupComplete,
48                          HTC_CONFIG *pConfig);
49 LOCAL void _HTC_RegisterService(htc_handle_t handle, HTC_SERVICE *pService);
50 LOCAL void _HTC_Ready(htc_handle_t handle);
51 LOCAL void ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, A_BOOL sendCreditFlag);
52 LOCAL void _HTC_ReturnBuffers(htc_handle_t handle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers);
53 LOCAL void _HTC_ReturnBuffersList(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_queue_t bufHead);
54 LOCAL void _HTC_SendMsg(htc_handle_t handle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers);
55 void _HTC_PauseRecv(HTC_ENDPOINT_ID EndpointID);
56 void _HTC_ResumeRecv(HTC_ENDPOINT_ID EndpointID);
57 LOCAL void HTCProcessConnectMsg(HTC_CONTEXT *pHTC, HTC_CONNECT_SERVICE_MSG *pMsg);
58 LOCAL void HTCProcessConfigPipeMsg(HTC_CONTEXT *pHTC, HTC_CONFIG_PIPE_MSG *pMsg);
59 LOCAL void RedistributeCredit(adf_nbuf_t buf, int toPipeId);                         
60 LOCAL void _HTC_Shutdown(htc_handle_t htcHandle);
61
62      /* macro to check if the service wants to prevent credit dribbling by using 
63         a dynamic threshold */
64 #define CHECK_AND_ADJUST_CREDIT_THRESHOLD(pEndpoint)                                        \
65     if ((pEndpoint)->ConnectionFlags & HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE) { \
66         AdjustCreditThreshold((pEndpoint));                                       \
67     }    
68
69 /***********************************************************************************************/
70 /************************ MODULE API implementation *******************************************/
71 #if 0
72 LOCAL void _HTC_AddBufferResources(int buffers)
73 {
74     (void)buffers;
75     //MboxHW_AddDMAResources(buffers);   
76 }
77 #endif
78
79 LOCAL void HTC_AssembleBuffers(HTC_CONTEXT *pHTC, int Count, int Size)
80 {
81     BUF_Pool_create_pool(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, Count, Size);       
82 }
83
84
85 LOCAL htc_handle_t _HTC_Init(HTC_SETUP_COMPLETE_CB SetupComplete,
86                              HTC_CONFIG *pConfig)
87 {
88     HIF_CALLBACK       hifCBConfig;
89     HTC_CONTEXT        *pHTC;    
90     
91     //if (NULL == g_pHTC) 
92     {
93         pHTC = (HTC_CONTEXT *)adf_os_mem_alloc(sizeof(HTC_CONTEXT));
94         //g_pHTC = &g_htcCtx;
95     } 
96     
97     adf_os_mem_zero(pHTC, sizeof(HTC_CONTEXT));
98
99     pHTC->OSHandle = pConfig->OSHandle;
100     pHTC->PoolHandle = pConfig->PoolHandle;
101     pHTC->hifHandle = pConfig->HIFHandle;
102                         
103     //A_MEMZERO(&hwConfig,sizeof(hwConfig));  
104     hifCBConfig.send_buf_done = A_INDIR(htc._HTC_SendDoneHandler);
105     hifCBConfig.recv_buf = A_INDIR(htc._HTC_MsgRecvHandler);
106     hifCBConfig.context = pHTC;
107     
108     /* initialize hardware layer */
109     HIF_register_callback(pConfig->HIFHandle, &hifCBConfig);
110                              
111         /* see if the host wants us to override the number of ctrl buffers */
112     //g_pHTC->NumBuffersForCreditRpts = (HOST_INTEREST->hi_mbox_io_block_sz >> 16) & 0xF;
113     pHTC->NumBuffersForCreditRpts = 0;
114     
115     if (0 == pHTC->NumBuffersForCreditRpts) {
116         /* nothing to override, simply set default */
117         pHTC->NumBuffersForCreditRpts = HTC_DEFAULT_NUM_CTRL_BUFFERS; 
118     }    
119     
120     //g_pHTC->MaxEpPendingCreditRpts = (HOST_INTEREST->hi_mbox_io_block_sz >> 20) & 0xF;
121     pHTC->MaxEpPendingCreditRpts = 0;
122     
123     if (0 == pHTC->MaxEpPendingCreditRpts) {
124         pHTC->MaxEpPendingCreditRpts = HTC_DEFAULT_MAX_EP_PENDING_CREDIT_REPORTS;    
125     }
126     /* calculate the total allocation size based on the number of credit report buffers */
127     pHTC->CtrlBufferAllocSize = MIN_CREDIT_BUFFER_ALLOC_SIZE * pHTC->NumBuffersForCreditRpts;
128     /* we need at least enough buffer space for 1 ctrl message */
129     pHTC->CtrlBufferAllocSize = A_MAX(pHTC->CtrlBufferAllocSize,MAX_HTC_SETUP_MSG_SIZE);
130     
131     //A_PRINTF("%d, %d, (%d, %d) %s-%s \n",g_pHTC->NumBuffersForCreditRpts,g_pHTC->CtrlBufferAllocSize,
132     //                        MIN_BUF_SIZE_FOR_RPTS, MIN_CREDIT_BUFFER_ALLOC_SIZE,__DATE__, __TIME__);
133                                           
134     /* save the size of each buffer/credit we will receive */
135     pHTC->RecvBufferSize = pConfig->CreditSize; //RecvBufferSize;
136     pHTC->TotalCredits = pConfig->CreditNumber;
137     //g_pHTC->FreeCreditList = pConfig->CreditList;
138     pHTC->TotalCreditsAssigned = 0;
139      
140     /* setup the pseudo service that handles HTC control messages */
141     pHTC->HTCControlService.ProcessRecvMsg = A_INDIR(htc._HTC_ControlSvcProcessMsg);
142     pHTC->HTCControlService.ProcessSendBufferComplete = A_INDIR(htc._HTC_ControlSvcProcessSendComplete);
143     pHTC->HTCControlService.TrailerSpcCheckLimit = HTC_CTRL_BUFFER_CHECK_SIZE;
144     pHTC->HTCControlService.MaxSvcMsgSize = MAX_HTC_SETUP_MSG_SIZE;
145     pHTC->HTCControlService.ServiceCtx = pHTC;
146     
147     /* automatically register this pseudo service to endpoint 1 */
148     pHTC->Endpoints[ENDPOINT0].pService = &pHTC->HTCControlService;
149     HIF_get_default_pipe(pHTC->hifHandle, &pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, 
150                                           &pHTC->Endpoints[ENDPOINT0].DownLinkPipeID);
151     
152     /* Initialize control pipe so we could receive the HTC control packets */
153     // @TODO: msg size!
154     HIF_config_pipe(pHTC->hifHandle, pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, 1);    
155     
156     /* set the first free endpoint */
157     pHTC->CurrentEpIndex = ENDPOINT1;
158     pHTC->SetupCompleteCb = SetupComplete;
159     
160         /* setup buffers for just the setup phase, we only need 1 buffer to handle
161         * setup */
162     HTC_AssembleBuffers(pHTC, 4, MAX_HTC_SETUP_MSG_SIZE);
163    
164     /* start hardware layer so that we can queue buffers */
165     HIF_start(pHTC->hifHandle);
166     
167     return pHTC;
168 }
169
170 LOCAL void _HTC_Shutdown(htc_handle_t htcHandle)
171 {
172     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;
173     
174     adf_os_mem_free(pHTC);
175 }
176
177 LOCAL void _HTC_RegisterService(htc_handle_t htcHandle, HTC_SERVICE *pService)
178 {
179     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;
180     
181         /* add it to the list */
182     pService->pNext = pHTC->pServiceList;
183     pHTC->pServiceList = pService;
184 }
185
186 LOCAL void _HTC_Ready(htc_handle_t htcHandle)
187 {
188     adf_nbuf_t      pBuffer;
189     HTC_READY_MSG   *pReady;
190     a_uint8_t       *addr;
191     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;
192     
193     pBuffer = HTCAllocMsgBuffer(pHTC);
194     //A_ASSERT(pBuffer != NULL);
195        
196     /* an optimization... the header length is chosen to
197      * be aligned on a 16 bit bounday, the fields in the message are designed to
198      * be aligned */
199     addr = adf_nbuf_put_tail(pBuffer, sizeof(HTC_READY_MSG));       
200     pReady = (HTC_READY_MSG *)addr;     
201     A_MEMZERO(pReady,sizeof(HTC_READY_MSG));  
202     pReady->MessageID = adf_os_htons(HTC_MSG_READY_ID);
203     pReady->CreditSize = adf_os_htons((A_UINT16)pHTC->RecvBufferSize);
204     //A_ASSERT(g_pHTC->TotalCredits <= MAX_HTC_CREDITS);
205     pReady->CreditCount = adf_os_htons((A_UINT16)pHTC->TotalCredits);
206     pReady->MaxEndpoints = ENDPOINT_MAX;
207        
208     /* send out the message */
209     //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length);    
210     HTC_SendMsg(pHTC, ENDPOINT0, pBuffer);
211     /* now we need to wait for service connection requests */
212 }
213
214 LOCAL void ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, A_BOOL sendCreditFlag)
215 {   
216     int         nbufs = 1;
217     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;
218     
219     //A_ASSERT(EndpointID < ENDPOINT_MAX);
220  
221     /* supply some head-room again */
222     adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH);
223     //A_DATA_CACHE_INVAL(pBuffers->buffer, pBuffers->actual_length + HTC_HDR_SZ);
224               
225     /* enqueue all buffers to the single mailbox */
226     HIF_return_recv_buf(pHTC->hifHandle, pHTC->Endpoints[EndpointID].UpLinkPipeID, pBuffers);    
227     //A_ASSERT(nbufs != 0);
228      
229     if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) {       
230         A_UINT32    epCreditMask = (1 << EndpointID);
231         /* we are running normally */
232         /* update pending credit counts with the number of buffers that were added */
233         pHTC->Endpoints[EndpointID].CreditsToReturn += (A_INT16)nbufs;
234         pHTC->Endpoints[EndpointID].CreditsConsumed -= (A_INT16)nbufs;  
235         //A_ASSERT(g_pHTC->Endpoints[EndpointID].CreditsConsumed >= 0);          
236         /* update bit map that this endpoint has non-zero credits */
237         pHTC->EpCreditPendingMap |= epCreditMask; 
238
239         if (sendCreditFlag) {
240             HTCCheckAndSendCreditReport(pHTC, epCreditMask,&pHTC->Endpoints[EndpointID],EndpointID);
241         }
242
243     } else {
244         /* we have not started yet so all return operations are simply adding buffers
245          * to the interface at startup, so we can keep track of how many total 
246          * credits we get */
247         /* update global count that will be returned to the host */
248         pHTC->TotalCredits += nbufs;
249     }     
250 }
251
252 LOCAL void _HTC_ReturnBuffersList(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_queue_t bufHead)
253 {
254     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;
255     adf_nbuf_t netbuf, tmpNbuf;
256
257     /* retrieve each nbuf in the queue */
258     netbuf = adf_nbuf_queue_first(&bufHead);
259
260     while (netbuf) {
261
262         tmpNbuf = netbuf;
263         netbuf = adf_nbuf_queue_next(netbuf);
264
265         ReturnBuffers(htcHandle, EndpointID, tmpNbuf, FALSE);
266     }
267
268     HTCCheckAndSendCreditReport(pHTC, (1 << EndpointID),&pHTC->Endpoints[EndpointID],EndpointID);
269 }
270
271 LOCAL void _HTC_ReturnBuffers(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers)
272 {
273     ReturnBuffers(htcHandle, EndpointID, pBuffers, TRUE);
274 }
275  
276 LOCAL void _HTC_SendMsg(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers)
277 {
278     HTC_FRAME_HDR       *pHTCHdr;
279     int                 totsz;
280     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;  
281     HTC_BUF_CONTEXT *ctx;
282     
283     ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers);
284     
285     /* init total size (this does not include the space we will put in for the HTC header) */
286     totsz = adf_nbuf_len(pBuffers);
287     
288     /* the first buffer stores the header */
289         /* back up buffer by a header size when we pass it down, by agreed upon convention the caller
290     * points the buffer to it's payload and leaves head room for the HTC header  
291     * Note: in HTCSendDoneHandler(), we undo this so that the caller get's it's buffer
292         *       back untainted */   
293     pHTCHdr = (HTC_FRAME_HDR *)adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH);
294     
295     /* flag that this is the header buffer that was modified */
296     ctx->htc_flags |= HTC_FLAGS_BUF_HDR;   
297     /* mark where this buffer came from */
298     ctx->end_point = EndpointID;      
299     /* the header start is ALWAYS aligned since we DMA it directly */
300     //pHTCHdr = (HTC_FRAME_HDR *)A_UNCACHED_ADDR(VBUF_GET_DATA_ADDR(pBuffers));
301         /* set some fields, the rest of them will be filled below when we check for
302         * trailer space */
303     pHTCHdr->Flags = 0;
304     pHTCHdr->EndpointID = EndpointID;    
305        
306     //A_ASSERT(totsz <= g_pHTC->Endpoints[EndpointID].pService->MaxSvcMsgSize);  
307     /* check opportunistically if we can return any reports via a trailer */
308     do {
309         int               room,i,totalReportBytes;
310         A_UINT32          creditsPendingMap, compareMask;
311         HTC_CREDIT_REPORT *pCreditRpt;
312         HTC_RECORD_HDR    *pRecHdr;
313         int               pipeMaxLen;
314         A_UINT32          roomForPipeMaxLen;
315                           
316         /* figure out how much room the last buffer can spare */
317         pipeMaxLen = HIF_get_max_msg_len(pHTC->hifHandle, pHTC->Endpoints[EndpointID].DownLinkPipeID);
318         roomForPipeMaxLen = pipeMaxLen - adf_nbuf_headroom(pBuffers) - adf_nbuf_len(pBuffers);
319         if ( roomForPipeMaxLen < 0 ) {
320             roomForPipeMaxLen = 0;
321         }
322                         
323         room = adf_os_min( adf_nbuf_tailroom(pBuffers), roomForPipeMaxLen);
324         if (room < (int)(sizeof(HTC_CREDIT_REPORT) + sizeof(HTC_RECORD_HDR))) {
325             /* no room for any reports */
326             break;    
327         }   
328             /* note, a record header only has 8 bit fields, so this is safe.
329             * we need an uncached pointer here too */            
330         totalReportBytes = 0;
331         
332         /* get a copy */        
333         creditsPendingMap = pHTC->EpCreditPendingMap;   
334                            
335             /* test pending map to see if we can send a report , if any
336         * credits are available, we might as well send them on the 
337             * unused space in the buffer */
338         if (creditsPendingMap) { 
339             
340             pRecHdr = (HTC_RECORD_HDR *)adf_nbuf_put_tail(pBuffers, sizeof(HTC_RECORD_HDR));            
341             
342                 /* set the ID, the length will be updated with the number of credit reports we
343                 * can fit (see below) */
344             pRecHdr->RecordID = HTC_RECORD_CREDITS;
345             pRecHdr->Length = 0;
346             /* the credit report follows the record header */         
347             totalReportBytes += sizeof(HTC_RECORD_HDR);
348             room -= sizeof(HTC_RECORD_HDR);
349             
350             /* walkthrough pending credits map and build the records */
351             for (i = 0; 
352                  (creditsPendingMap != 0) && (room >= (int)sizeof(HTC_CREDIT_REPORT)); 
353                  i++) {                
354                      compareMask = (1 << i);
355                      if (compareMask & creditsPendingMap) {
356                         
357                          pCreditRpt = (HTC_CREDIT_REPORT *)adf_nbuf_put_tail(pBuffers, sizeof(HTC_CREDIT_REPORT));
358                                     
359                          /* clear pending mask, we are going to return all these credits */
360                          creditsPendingMap &= ~(compareMask);
361                          /* add this record */
362                          pCreditRpt->EndpointID = i;
363                          pCreditRpt->Credits = (A_UINT8)pHTC->Endpoints[i].CreditsToReturn;
364                          /* remove pending credits, we always send deltas */
365                          pHTC->Endpoints[i].CreditsToReturn = 0; 
366                          /* adjust new threshold for this endpoint if needed */
367                          CHECK_AND_ADJUST_CREDIT_THRESHOLD(&pHTC->Endpoints[i]);
368                          /* update this record length */
369                          pRecHdr->Length += sizeof(HTC_CREDIT_REPORT);
370                          room -= sizeof(HTC_CREDIT_REPORT);
371                          totalReportBytes += sizeof(HTC_CREDIT_REPORT);
372
373                          if ( room < sizeof(HTC_CREDIT_REPORT) ) {
374                              break;
375                          }
376                      }
377                  }
378             
379                  /* update new pending credits map */       
380                  pHTC->EpCreditPendingMap = creditsPendingMap;
381         }
382         
383         if (totalReportBytes <= 0) {
384             break;
385         }
386         
387             /* must fit into a byte, this should never actually happen since
388         * the maximum possible number of endpoints is 32. 
389         * The trailer can have at most 1 credit record with up to 32  reports in the record.
390         * The trailer can have at most 1 lookahead record with only 1 lookahead report in the record.
391         * 
392             * */
393         //A_ASSERT(totalReportBytes <= 255);
394         
395         /* set header option bytes */ 
396         pHTCHdr->ControlBytes[0] = totalReportBytes;
397         /* HTC frame contains a trailer */
398         pHTCHdr->Flags |= HTC_FLAGS_RECV_TRAILER;
399         /* increment total size by the reports we added */
400         totsz += totalReportBytes;
401         /* adjust the last buffer we used for adding on the trailer */                                 
402     } while (FALSE);
403           
404     if (totsz == 0) {
405         //A_ASSERT(FALSE);
406     }
407     
408     /* set length for message (this includes any reports that were added above) */
409     pHTCHdr->PayloadLen = adf_os_htons(totsz);  
410     HIF_send_buffer(pHTC->hifHandle, pHTC->Endpoints[EndpointID].DownLinkPipeID, pBuffers);       
411 }
412
413 void _HTC_PauseRecv(HTC_ENDPOINT_ID EndpointID)
414 {
415 #if 0  // Disable first. Ray
416 #ifdef HTC_PAUSE_RESUME_REF_COUNTING    
417     g_pHTC->Endpoints[EndpointID].PauseRefCount++;
418 #endif
419         /* we are now paused */
420     g_pHTC->EpRecvPausedMap |= (1 << EndpointID);
421 #endif    
422 }
423
424 void _HTC_ResumeRecv(HTC_ENDPOINT_ID EndpointID)
425 {
426 #if 0  // Disable first. Ray    
427     HTC_BUFFER      *buffer;
428     HTC_ENDPOINT    *pEndpoint;
429     
430     pEndpoint = &g_pHTC->Endpoints[EndpointID];
431
432 /* TODO: we can't quite use referencing counting yet until we clean up the WLAN
433  * app, there are some un-matched pause/resume cases that need to be fixed */
434 #ifdef HTC_PAUSE_RESUME_REF_COUNTING  
435     pEndpoint->PauseRefCount--;
436     //A_ASSERT(pEndpoint->PauseRefCount >= 0);
437     
438         /* check reference count and unpause if it is zero */
439     if (pEndpoint->PauseRefCount > 0) {
440         return;    
441     }   
442 #endif
443
444     g_pHTC->EpRecvPausedMap &= ~(1 << EndpointID);        
445         /* unload the paused receive queue */
446     while ((buffer = HTC_DequeuePausedRecv(pEndpoint)) != NULL) {          
447         /* note that the paused messages have already been processed at the HTC layer,
448          * we can simply indicate the buffers to the service */
449         pEndpoint->pService->ProcessRecvMsg(EndpointID,buffer);    
450     }
451 #endif    
452 }
453
454 int _HTC_GetReservedHeadroom(htc_handle_t htcHandle)
455 {
456     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;  
457     
458     return HTC_HDR_LENGTH + HIF_get_reserved_headroom(pHTC->hifHandle);
459 }
460     
461 void htc_module_install(struct htc_apis *pAPIs)
462 {   
463     pAPIs->_HTC_Init = _HTC_Init;
464     pAPIs->_HTC_ReturnBuffers = _HTC_ReturnBuffers;
465     pAPIs->_HTC_ReturnBuffersList = _HTC_ReturnBuffersList;
466     pAPIs->_HTC_Ready = _HTC_Ready;
467     pAPIs->_HTC_RegisterService = _HTC_RegisterService;
468     pAPIs->_HTC_SendMsg = _HTC_SendMsg;   
469     pAPIs->_HTC_Shutdown = _HTC_Shutdown;
470     pAPIs->_HTC_GetReservedHeadroom = _HTC_GetReservedHeadroom;
471     pAPIs->_HTC_MsgRecvHandler = HTCMsgRecvHandler;
472     pAPIs->_HTC_SendDoneHandler = HTCSendDoneHandler;
473     pAPIs->_HTC_ControlSvcProcessMsg = HTCControlSvcProcessMsg;
474     pAPIs->_HTC_ControlSvcProcessSendComplete = HTCControlSvcProcessSendComplete;
475     
476     //pAPIs->_HTC_PauseRecv = _HTC_PauseRecv;
477     //pAPIs->_HTC_ResumeRecv = _HTC_ResumeRecv; 
478     //pAPIs->_HTC_AddBufferResources = _HTC_AddBufferResources;
479         /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
480     //pAPIs->pReserved = &g_pHTC;
481 }
482
483 /*******************************************************************************************/
484 /****************   INTERNAL ROUTINES to this MODULE ***************************************/
485
486 /* free message to the free list */
487 //LOCAL void HTCFreeMsgBuffer(HTC_BUFFER *pBuffer)
488 LOCAL void HTCFreeMsgBuffer(HTC_CONTEXT *pHTC, adf_nbuf_t buf) 
489 {
490     BUF_Pool_free_buf(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, buf);      
491 }
492
493 /* HTC control message allocator (also used for empty frames to send trailer options) */
494 //LOCAL HTC_BUFFER *HTCAllocMsgBuffer(void)
495 LOCAL adf_nbuf_t HTCAllocMsgBuffer(HTC_CONTEXT *pHTC)
496 {
497     return BUF_Pool_alloc_buf(pHTC->PoolHandle, POOL_ID_HTC_CONTROL, HTC_GetReservedHeadroom(pHTC));   
498 }
499
500 LOCAL void HTCCheckAndSendCreditReport(HTC_CONTEXT *pHTC, A_UINT32 EpMask, HTC_ENDPOINT *pEndpoint, HTC_ENDPOINT_ID Eid)
501 {
502     adf_nbuf_t  pCredBuffer;
503     HTC_BUF_CONTEXT *ctx;    
504         
505     do {
506         /* check if host needs credits */
507         if (!(pHTC->EpHostNeedsCreditMap & EpMask)) {
508             /* host does not need any credits for this set */
509             break;    
510         }
511         /* check if any are pending */
512         if (!(pHTC->EpCreditPendingMap & EpMask)) {
513             /* nothing to send up */
514             break;    
515         }  
516         /* was an endpoint specified? */
517         if (pEndpoint != NULL) {
518             /* see if a threshold is in effect for this endpoint */
519             if (pEndpoint->CreditReturnThreshhold != 0) {
520                 if (pEndpoint->CreditsToReturn < pEndpoint->CreditReturnThreshhold) {
521                     /* this endpoint is using a threshold to prevent credits from dribbling
522                      * back to the host */
523                     break;
524                 }
525             }
526          
527             if (pEndpoint->PendingCreditReports >= pHTC->MaxEpPendingCreditRpts) {
528                 /* this endpoint already has some reports outstanding */
529                 /* flag that as soon as a buffer is reaped, we issue a credit update to
530                  * pick up this credit that is being held up because the endpoint has already
531                  * exceeded the max outstanding credit report limit */    
532                pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON;
533                 break;    
534             }                         
535         }
536         
537         /* if we get here we have some credits to send up */
538                         
539         /* allocate a message buffer for the trailer */
540         pCredBuffer = HTCAllocMsgBuffer(pHTC);
541         if (NULL == pCredBuffer) {
542             /* no buffers left to send an empty message with trailers, host will just
543             * have to wait until we get our endpoint 0 messages back.. */
544             /* mark that we need to send an update as soon as we can get a buffer back */
545             pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON;
546             break;    
547         }
548         
549         ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pCredBuffer);
550         if (pEndpoint != NULL) {
551             /* keep track of pending reports */
552             pEndpoint->PendingCreditReports++; 
553             /* save the endpoint in order to decrement the count when the send completes */
554             ctx->htc_flags = Eid | HTC_FLAGS_CREDIT_RPT;
555         }   
556             
557         /* this is an empty message, the HTC_SendMsg will tack on a trailer in the remaining
558          * space, NOTE: no need to flush the cache, the header and trailers are assembled
559          * using uncached addresses */
560         HTC_SendMsg(pHTC, ENDPOINT0, pCredBuffer);    
561     
562     } while (FALSE);      
563 }
564         
565 /* called in response to the arrival of a service connection message */
566 LOCAL void HTCProcessConnectMsg(HTC_CONTEXT *pHTC, HTC_CONNECT_SERVICE_MSG *pMsg)
567 {
568     HTC_SERVICE                         *pService = pHTC->pServiceList;
569     A_UINT8                             connectStatus = HTC_SERVICE_NOT_FOUND;
570     //HTC_BUFFER                          *pBuffer;
571     adf_nbuf_t                          pBuffer;
572     HTC_CONNECT_SERVICE_RESPONSE_MSG    *pRspMsg;
573     int                                 metaDataOutLen = 0;
574     A_UINT16                            serviceId = adf_os_ntohs(pMsg->ServiceID);
575     
576     pBuffer = HTCAllocMsgBuffer(pHTC);
577     //A_ASSERT(pBuffer != NULL);
578     /* note : this will be aligned */
579     pRspMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)
580                 adf_nbuf_put_tail(pBuffer, sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG));
581                                  
582     A_MEMZERO(pRspMsg,sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG));
583     pRspMsg->MessageID = adf_os_htons(HTC_MSG_CONNECT_SERVICE_RESPONSE_ID);
584     /* reflect the service ID for this connect attempt */
585     pRspMsg->ServiceID = adf_os_htons(serviceId);
586
587     while (pService) {
588         
589         if (pHTC->CurrentEpIndex >= ENDPOINT_MAX) {
590             /* no more endpoints */
591             connectStatus = HTC_SERVICE_NO_RESOURCES;
592             break;    
593         }
594
595         if (serviceId == pService->ServiceID) {
596             /* we found a match */             
597             A_UINT8     *pMetaDataIN = NULL; 
598             A_UINT8     *pMetaDataOut;
599             
600             /* outgoing meta data resides in the space after the response message */
601             pMetaDataOut = ((A_UINT8 *)pRspMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG);
602             
603             if (pMsg->ServiceMetaLength != 0) {
604                 //A_ASSERT(pMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH);
605                 /* the meta data follows the connect service message */
606                 pMetaDataIN = ((A_UINT8 *)pMsg) + sizeof(HTC_CONNECT_SERVICE_MSG);
607             }
608
609             //A_ASSERT(pService->ProcessConnect != NULL);
610             /* call the connect callback with the endpoint to use and pointers to meta data */
611             connectStatus = pService->ProcessConnect(pService,
612                     pHTC->CurrentEpIndex,
613                     pMetaDataIN,
614                     pMsg->ServiceMetaLength,
615                     pMetaDataOut,
616                     &metaDataOutLen);
617             
618             /* check if the service accepted this connection request */
619             if (HTC_SERVICE_SUCCESS == connectStatus) {
620                 //A_ASSERT(metaDataOutLen <= HTC_SERVICE_META_DATA_MAX_LENGTH);
621                 /* set the length of the response meta data going back to the host */
622                 pRspMsg->ServiceMetaLength = (A_UINT8)metaDataOutLen;
623                 /* set the endpoint ID the host will now communicate over */
624                 pRspMsg->EndpointID = pHTC->CurrentEpIndex;
625                 /* return the maximum message size for this service */
626                 pRspMsg->MaxMsgSize = adf_os_htons((A_UINT16)pService->MaxSvcMsgSize);
627                 /* assign this endpoint to this service, this will be used in routing messages */
628                 pHTC->Endpoints[pHTC->CurrentEpIndex].pService = pService;
629                 /* set connection flags */
630                 pHTC->Endpoints[pHTC->CurrentEpIndex].ConnectionFlags = pMsg->ConnectionFlags;
631                 
632                 pHTC->Endpoints[pHTC->CurrentEpIndex].DownLinkPipeID = pMsg->DownLinkPipeID;
633                 pHTC->Endpoints[pHTC->CurrentEpIndex].UpLinkPipeID = pMsg->UpLinkPipeID;
634                 
635                 /* mark that we are now connected */
636                 pService->ServiceFlags |= HTC_SERVICE_FLAGS_CONNECTED;
637                 /* bump up our index, this EP is now in use */
638                 pHTC->CurrentEpIndex++;   
639             }
640
641             break;
642         }       
643         
644         pService = pService->pNext;   
645     }
646                    
647     pRspMsg->Status = connectStatus;    
648     
649     /* send out the response message */
650     //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length);
651     HTC_SendMsg(pHTC, ENDPOINT0, pBuffer); 
652 }
653
654 LOCAL void HTCProcessConfigPipeMsg(HTC_CONTEXT *pHTC, HTC_CONFIG_PIPE_MSG *pMsg)
655 {
656     //HTC_SERVICE                         *pService = g_pHTC->pServiceList;
657     //A_UINT8                             connectStatus = HTC_SERVICE_NOT_FOUND;
658     adf_nbuf_t                          pBuffer;
659     HTC_CONFIG_PIPE_RESPONSE_MSG        *pRspMsg;
660         
661     pBuffer = HTCAllocMsgBuffer(pHTC);
662        
663     //A_ASSERT(pBuffer != NULL);
664     /* note : this will be aligned */
665     pRspMsg = (HTC_CONFIG_PIPE_RESPONSE_MSG *)
666                 adf_nbuf_put_tail(pBuffer, sizeof(HTC_CONFIG_PIPE_RESPONSE_MSG));    
667               
668     A_MEMZERO(pRspMsg,sizeof(HTC_CONFIG_PIPE_RESPONSE_MSG));
669     
670     pRspMsg->MessageID = adf_os_htons(HTC_MSG_CONFIG_PIPE_RESPONSE_ID);
671     /* reflect the service ID for this connect attempt */
672     pRspMsg->PipeID = pMsg->PipeID;
673
674     if ( HIF_is_pipe_supported(pHTC->hifHandle, pMsg->PipeID) ) {
675         pRspMsg->Status = 0;            
676     } else {
677         pRspMsg->Status = 1; 
678         goto config_done;
679     }
680
681     if ( (pHTC->TotalCreditsAssigned + pMsg->CreditCount) <= pHTC->TotalCredits ) {
682         pHTC->TotalCreditsAssigned += pMsg->CreditCount;
683     } else {
684         pRspMsg->Status = 2;
685         goto config_done;
686     }
687     
688     HIF_config_pipe(pHTC->hifHandle, pMsg->PipeID, pMsg->CreditCount);
689     
690 config_done:      
691     /* send out the response message */
692     //A_DATA_CACHE_FLUSH(pBuffer->buffer, pBuffer->actual_length);    
693     HTC_SendMsg(pHTC, ENDPOINT0, pBuffer);             
694 }
695
696 /* process an incomming control message from the host */
697 LOCAL void HTCControlSvcProcessMsg(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t hdr_buf, adf_nbuf_t pBuffers, void *arg)
698 {  
699     A_BOOL setupComplete = FALSE;
700     a_uint8_t *anbdata;
701     a_uint32_t anblen;
702     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)arg;
703     HTC_UNKNOWN_MSG  *pMsg;
704         
705     adf_os_assert(hdr_buf == ADF_NBUF_NULL);
706
707     /* we assume buffers are aligned such that we can access the message
708     * parameters directly*/
709     adf_nbuf_peek_header(pBuffers, &anbdata, &anblen);
710     pMsg = (HTC_UNKNOWN_MSG *)anbdata;
711     
712     /* we cannot handle fragmented messages across buffers */
713     //A_ASSERT(pBuffers->next == NULL);
714     
715     switch ( adf_os_ntohs(pMsg->MessageID) ) {        
716         case HTC_MSG_CONNECT_SERVICE_ID:
717             //A_ASSERT(pBuffers->actual_length >= sizeof(HTC_CONNECT_SERVICE_MSG));
718             HTCProcessConnectMsg(pHTC, (HTC_CONNECT_SERVICE_MSG *)pMsg); 
719             break;
720         case HTC_MSG_CONFIG_PIPE_ID:
721             HTCProcessConfigPipeMsg(pHTC, (HTC_CONFIG_PIPE_MSG *)pMsg); 
722             break;            
723         case HTC_MSG_SETUP_COMPLETE_ID:
724                 /* the host has indicated that it has completed all
725             setup tasks and we can now let the services take over to
726             run the rest of the application */
727             setupComplete = TRUE;  
728             /* can't get this more than once */
729             //A_ASSERT(!(g_pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE));            
730             break;
731         default:
732             ;
733             //A_ASSERT(FALSE);
734     }  
735         
736     if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) {
737         /* recycle buffer only if we are fully running */
738         HTC_ReturnBuffers(pHTC, ENDPOINT0,pBuffers);
739     } else {
740         /* supply some head-room again */
741         //A_DATA_CACHE_INVAL(pBuffers->buffer, pBuffers->actual_length + HTC_HDR_SZ);
742         adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH);
743             
744         /* otherwise return the packet back to mbox */
745         HIF_return_recv_buf(pHTC->hifHandle, pHTC->Endpoints[EndpointID].UpLinkPipeID, pBuffers);        
746     }
747
748     if (setupComplete) {        
749         /* mark that setup has completed */
750         pHTC->StateFlags |= HTC_STATE_SETUP_COMPLETE; 
751         if (pHTC->SetupCompleteCb != NULL) {
752             pHTC->SetupCompleteCb();
753         }
754     }
755 }
756
757 /* callback when endpoint 0 send buffers are completed */
758 LOCAL void HTCControlSvcProcessSendComplete(HTC_ENDPOINT_ID EndpointID, adf_nbuf_t pBuffers, void *arg)
759 {
760     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)arg;
761     HTC_BUF_CONTEXT *ctx;
762     HTC_ENDPOINT_ID  creditRptEndpoint;
763     
764     ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers);       
765     
766     //A_ASSERT(EndpointID == ENDPOINT0);
767     
768     /* put them back into the pool */
769 #if 0    
770     while (pBuffers != NULL) {
771         pNext = pBuffers->next_buf;
772         pBuffers->next_buf = NULL;       
773         /* note: HTC does not send fragmented control messages, so each buffer
774         * represents 1 full HTC control message */  
775         if (pBuffers->desc_list->control & HTC_FLAGS_CREDIT_RPT) {                      
776             /* extract the endpoint number that requested this credit report */     
777             creditRptEndpoint = pBuffers->desc_list->control & HTC_FLAGS_CRPT_EP_MASK;    
778             pBuffers->desc_list->control = 0;
779             g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports--;  
780             //A_ASSERT(g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports >= 0);           
781         }
782         /* free this one */
783         HTCFreeMsgBuffer(pBuffers);
784         pBuffers = pNext;
785     }
786 #else
787     if ( ctx->htc_flags & HTC_FLAGS_CREDIT_RPT ) {   
788         /* extract the endpoint number that requested this credit report */ 
789         creditRptEndpoint = ctx->htc_flags & HTC_FLAGS_CRPT_EP_MASK;    
790         pHTC->Endpoints[creditRptEndpoint].PendingCreditReports--;  
791         //A_ASSERT(g_pHTC->Endpoints[creditRptEndpoint].PendingCreditReports >= 0);             
792     }
793     
794     HTCFreeMsgBuffer(pHTC, pBuffers);
795 #endif  
796    
797     if (pHTC->StateFlags & HTC_SEND_CREDIT_UPDATE_SOON) {
798         /* this flag is set when the host could not send a credit report
799          * because we ran out of HTC control buffers */
800         pHTC->StateFlags &= ~HTC_SEND_CREDIT_UPDATE_SOON;
801         /* send out a report if anything is pending */
802         HTCCheckAndSendCreditReport(pHTC, HTC_ANY_ENDPOINT_MASK,NULL,ENDPOINT_MAX);
803     }  
804 }
805
806 LOCAL void HTCSendDoneHandler(adf_nbuf_t buf, void *context)
807 {
808     A_UINT8      current_eid;
809     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)context;
810     HTC_BUF_CONTEXT *ctx;
811       
812     ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(buf);
813     current_eid = ctx->end_point;
814         
815     /* Walk through the buffers and fixup the ones we used for HTC headers.
816      * The buffer list may contain more than one string of HTC buffers comprising of an
817     * HTC message so we need to check every buffer */            
818     adf_nbuf_pull_head(buf, HTC_HDR_LENGTH);
819                    
820     pHTC->Endpoints[current_eid].pService->
821         ProcessSendBufferComplete(current_eid, 
822                                   buf, 
823                                   pHTC->Endpoints[current_eid].pService->ServiceCtx); 
824 }
825
826 #if 0
827 LOCAL void HTC_EnqueuePausedRecv(HTC_ENDPOINT *pEndpoint, 
828                                  HTC_BUFFER *pFirstBuf,
829                                  HTC_BUFFER *pLastBuf)
830 {
831     //A_ASSERT(pLastBuf->next == NULL);
832     
833     if (NULL == pEndpoint->pRcvPausedQueueTail) {
834         pEndpoint->pRcvPausedQueueTail = pLastBuf;
835         pEndpoint->pRcvPausedQueueHead = pFirstBuf;        
836     } else {
837             /* queue to the tail */
838         pEndpoint->pRcvPausedQueueTail->next = pFirstBuf;
839         pEndpoint->pRcvPausedQueueTail = pLastBuf;        
840     }
841     
842 }
843 #endif
844
845 #if 0
846 LOCAL HTC_BUFFER *HTC_DequeuePausedRecv(HTC_ENDPOINT *pEndpoint)
847 {
848     HTC_BUFFER *pHead;
849     HTC_BUFFER *pCur;
850     
851     if (pEndpoint->pRcvPausedQueueHead != NULL) {
852             /* there is a message in the queue */ 
853         pHead = pEndpoint->pRcvPausedQueueHead;   
854         pCur = pHead;
855         
856         while (pCur != NULL) {
857                 /* check for end marker on this buffer */    
858             if (pCur->htc_flags & HTC_FLAGS_RECV_END_MSG) {
859                 pCur->htc_flags &= ~HTC_FLAGS_RECV_END_MSG;
860                     /* advance the head */
861                 pEndpoint->pRcvPausedQueueHead = pCur->next;
862                 
863                 if (NULL == pEndpoint->pRcvPausedQueueHead) {
864                         /* list is now empty */
865                     pEndpoint->pRcvPausedQueueTail = NULL;    
866                 }
867                     /* cut this message out */
868                 pCur->next = NULL;
869                 break;
870             }            
871             pCur = pCur->next;
872         }       
873             /* we should always find complete messages with the marker present */
874         //A_ASSERT(pCur != NULL);
875         return pHead;
876     } else {
877         //A_ASSERT(pEndpoint->pRcvPausedQueueTail == NULL);
878         return NULL;   
879     }
880 }
881 #endif
882     
883 LOCAL void AdjustCreditThreshold(HTC_ENDPOINT  *pEndpoint)
884 {
885
886     A_INT16 creditsOutstanding = pEndpoint->CreditsToReturn + pEndpoint->CreditsConsumed;
887         /* set the new threshold based on the number of credits that have been consumed
888          * and which have not been returned by the app.
889          * Note: it is okay for this threshold to be zero which indicates no threshold 
890          * is in use */    
891     switch (pEndpoint->ConnectionFlags & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK) {
892         case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH :
893             creditsOutstanding >>= 2;
894             break;                    
895         case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF :
896             creditsOutstanding >>= 1;
897             break;
898         case HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS :  
899             creditsOutstanding = (creditsOutstanding * 3) >> 2;                  
900             break;
901         /* default case is unity */    
902     }
903     
904     pEndpoint->CreditReturnThreshhold = creditsOutstanding;
905     
906 }
907
908 LOCAL void RedistributeCredit(adf_nbuf_t buf, int toPipeId)
909 {
910
911 }
912             
913 /* callback from the mailbox hardware layer when a full message arrives */
914 LOCAL void HTCMsgRecvHandler(adf_nbuf_t hdr_buf, adf_nbuf_t buffer, void *context)
915 {
916     A_UINT16       totsz;
917     HTC_ENDPOINT  *pEndpoint;
918     A_UINT32       eidMask;
919     int            eid;    
920     a_uint8_t      *anbdata;
921     a_uint32_t     anblen;
922     HTC_FRAME_HDR  *pHTCHdr;
923     HTC_CONTEXT *pHTC = (HTC_CONTEXT *)context;
924     adf_nbuf_t tmp_nbuf;
925                 
926     if (hdr_buf == ADF_NBUF_NULL) {
927         /* HTC hdr is not in the hdr_buf */
928         tmp_nbuf = buffer;
929     }
930     else {
931         tmp_nbuf = hdr_buf;
932     }
933                 
934     adf_nbuf_peek_header(tmp_nbuf, &anbdata, &anblen);        
935     pHTCHdr = (HTC_FRAME_HDR *)anbdata; 
936       
937     totsz = adf_os_ntohs(pHTCHdr->PayloadLen); 
938     
939     //A_ASSERT(pHTCHdr->EndpointID < ENDPOINT_MAX);   
940     eid = pHTCHdr->EndpointID; 
941     
942     pEndpoint = &pHTC->Endpoints[eid];
943     eidMask = 1 << eid;
944
945     if (pHTCHdr->Flags & HTC_FLAGS_CREDIT_REDISTRIBUTION) {
946         /* The pipe id where the credit is redistributed to is carried in Control
947         * Byte 0 */
948         RedistributeCredit(tmp_nbuf, pHTCHdr->ControlBytes[0]);
949         return;
950     }
951
952     if (pHTC->StateFlags & HTC_STATE_SETUP_COMPLETE) {
953         /* after setup we keep track of credit consumption to allow us to
954         * adjust thresholds to reduce credit dribbling */  
955         pEndpoint->CreditsConsumed ++;
956     }
957
958     /* from the design document, we put the endpoint into a "host-needs-credit" state
959     * when we receive a frame with the NEED_CREDIT_UPDATE flag set .
960     * if the host received credits through an opportunistic path, then it can
961     * issue a another frame with this bit cleared, this signals the target to clear
962     * the "host-needs-credit" state */    
963     if (pHTCHdr->Flags & HTC_FLAGS_NEED_CREDIT_UPDATE) {
964         /* the host is running low (or is out) of credits on this
965         * endpoint, update mask */
966         pHTC->EpHostNeedsCreditMap |= eidMask; 
967         /* check and set new threshold since host has reached a low credit situation */
968         CHECK_AND_ADJUST_CREDIT_THRESHOLD(pEndpoint);                          
969     } else {
970         /* clear the flag */
971         pHTC->EpHostNeedsCreditMap &= ~(eidMask);       
972         pEndpoint->CreditReturnThreshhold = 0; 
973     }
974
975     /* Adjust the first buffer to point to the start of the actual 
976        payload, the first buffer contains the header */
977     adf_nbuf_pull_head(tmp_nbuf, HTC_HDR_LENGTH);
978                     
979     /* NOTE : This callback could re-queue the recv buffers within this calling context.
980     *        The callback could also send a response message within the context of this callback
981     *        as the result of parsing this message.  In either case, if there are
982     *        pending credits and the host needs them, a credit report will be sent either through 
983     *        the response message trailer or a NULL message through HTC_ReturnBuffers().
984     */       
985         
986     //A_ASSERT(totsz <= pEndpoint->pService->MaxSvcMsgSize);       
987
988 #if 0    
989     /* is this endpoint paused? */ 
990     if (g_pHTC->EpRecvPausedMap & eidMask) {
991         /* note that curr_buf is the last buffer */  
992         /* mark the last buffer so that it indicates the end of this message */
993         //curr_buf->htc_flags |= HTC_FLAGS_RECV_END_MSG;
994         /* enqueue this message to our pause queues */
995         //HTC_EnqueuePausedRecv(pEndpoint,bufinfo,curr_buf);
996     } else {           
997         /* pass the message to the service */
998         pEndpoint->pService->ProcessRecvMsg(eid, buffer, pEndpoint->pService->ServiceCtx);
999     }                           
1000 #else
1001     pEndpoint->pService->ProcessRecvMsg(eid, hdr_buf, buffer, pEndpoint->pService->ServiceCtx);
1002 #endif
1003
1004     /* Calls to HTC_ReturnBuffers drives the endpoint credit reporting state machine. 
1005     * We do not want to delay credits for too long in the event that the application is 
1006     * holding onto buffers for excessive periods of time.  This gives us "some" better
1007     * opportunities to send up credits. */
1008     HTCCheckAndSendCreditReport(pHTC, eidMask, pEndpoint, eid); 
1009 }