www.pudn.com > CEWifiDriverAR6000-21374.zip > htc_recv.c


//------------------------------------------------------------------------------ 
//  
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved. 
//    Copyright (c) 2006 Atheros Corporation.  All rights reserved. 
// 
//    The use and distribution terms for this software are covered by the 
//    Microsoft Limited Permissive License (Ms-LPL)  
//    http://www.microsoft.com/resources/sharedsource/licensingbasics/limitedpermissivelicense.mspx  
//    which can be found in the file MS-LPL.txt at the root of this distribution. 
//    By using this software in any fashion, you are agreeing to be bound by 
//    the terms of this license. 
// 
//    The software is licensed “as-is.”  
//    You must not remove this notice, or any other, from this software. 
//  
//  
//  
//    Windows CE Wifi Driver for AR-6000 
//  
//------------------------------------------------------------------------------ 
//============================================================================== 
// This file contains the routines handling the receive path. 
// 
// Author(s): ="Atheros" 
//============================================================================== 
 
 
#include "htc_internal.h" 
 
/* ------ Global Variable Declarations ------- */ 
#ifdef DEBUG 
extern A_UINT32 debughtc; 
#endif 
 
/* ------ Static Variables ------ */ 
 
 
/* ------ Functions ------ */ 
/* Makes a buffer available to the HTC module */ 
A_STATUS  
HTCBufferReceive(HTC_TARGET *target,  
                 HTC_ENDPOINT_ID endPointId, 
                 A_UCHAR *buffer,  
                 A_UINT32 length, 
                 void *cookie) 
{ 
    A_STATUS status; 
    HTC_ENDPOINT *endPoint; 
    HTC_DATA_REQUEST_QUEUE *recvQueue; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "HTCBufferReceive: Enter (endPointId: %d, buffer: 0x%p, length: %d, cookie: 0x%p)\n", endPointId, buffer, length, cookie); 
 
    AR_DEBUG_ASSERT((endPointId >= ENDPOINT1) && (endPointId <= ENDPOINT4)); 
 
    /* Extract the end point instance */ 
    endPoint = &target->endPoint[endPointId]; 
    AR_DEBUG_ASSERT(endPoint != NULL); 
 
    recvQueue = &endPoint->recvQueue; 
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV, "recvQueue: %p\n",  
                    recvQueue); 
 
    /* Add this posted buffer to the pending receive queue */ 
    status = addToMboxQueue(recvQueue, buffer, length, 0, cookie); 
    if (status != A_OK) { 
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_RECV, 
                        "Mailbox (%d) Send queue full. Unable to add buffer\n",  
                        GET_ENDPOINT_ID(endPoint)); 
        return A_ERROR; 
    } 
 
    /*  
     * If this API was called as a result of a HTC_DATA_AVAILABLE event to 
     * the upper layer, indicating that HTC is out of buffers, then we should 
     * receive the frame in the buffer supplied otherwise we simply add the  
     * buffer to the Pending Receive Queue  
     */ 
    if (endPoint->rxLengthPending) { 
        htcReceiveFrame(endPoint); 
    } 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "HTCBufferReceive: Exit\n"); 
    return A_OK; 
} 
 
void 
htcReceiveFrame(HTC_ENDPOINT *endPoint) 
{ 
    A_STATUS status; 
    A_UINT32 address; 
    A_UINT32 paddedLength; 
    A_UINT32 frameLength; 
    HIF_REQUEST request; 
    HTC_ENDPOINT_ID endPointId; 
    HTC_QUEUE_ELEMENT *element; 
    HTC_MBOX_BUFFER *mboxBuffer; 
    HTC_DATA_REQUEST_QUEUE *recvQueue; 
    HTC_TARGET *target; 
    HTC_EVENT_INFO eventInfo; 
    HIF_DATAMODE dmode; 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "htcReceiveFrame - Enter\n"); 
 
    /* Get the context */ 
    AR_DEBUG_ASSERT(endPoint != NULL); 
    endPointId = GET_ENDPOINT_ID(endPoint); 
    target = endPoint->target; 
    AR_DEBUG_ASSERT(target != NULL); 
    recvQueue = &endPoint->recvQueue; 
    AR_DEBUG_ASSERT(recvQueue != NULL); 
 
    /*  
     * Receive the frame if we have any pending frames and a buffer to 
     * receive it into. 
     */ 
     if (IS_DATA_QUEUE_EMPTY(recvQueue)) { 
         HTC_DEBUG_PRINTF(ATH_LOG_WARN | ATH_LOG_RECV, 
                         "Mailbox (%d) recv queue empty. Unable to remove buffer\n", endPointId); 
 
         /*  
          * Communicate this situation to the host via the HTC_DATA_AVAILABLE 
          * event to request some buffers in the queue. 
          */ 
         endPoint->rxLengthPending = htcGetFrameLength(endPoint); 
         AR_DEBUG_ASSERT(endPoint->rxLengthPending); 
         FRAME_EVENT(eventInfo, NULL, endPoint->rxLengthPending,  
                     0, A_OK, NULL); 
         dispatchEvent(target, endPointId, HTC_DATA_AVAILABLE, &eventInfo); 
         return; 
     } 
 
     /*  
      * Get the length from the lookahead register if there is nothing  
      * pending. 
      */ 
     if (endPoint->rxLengthPending) { 
         frameLength = endPoint->rxLengthPending; 
         endPoint->rxLengthPending = 0; 
     } else { 
         frameLength = htcGetFrameLength(endPoint); 
     } 
      
     if (frameLength > HTC_MESSAGE_SIZE_MAX) { 
             return; 
     } 
  
     HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV, "Frame Length: %d\n",  
                     frameLength); 
 
     /* Adjust the length to be a multiple of block size if appropriate */ 
     paddedLength = (frameLength + (endPoint->blockSize - 1)) & 
                    (~(endPoint->blockSize - 1)); 
 
     /*  
      * Receive the frame(s). Pull an empty buffer from the head of the  
      * Pending Receive Queue. 
      */ 
     element = removeFromMboxQueue(recvQueue); 
     mboxBuffer = GET_MBOX_BUFFER(element); 
     mboxBuffer->actualLength = paddedLength; 
     dmode = (endPoint->blockSize > 1) ? HIF_BLOCK_BASIS : HIF_BYTE_BASIS; 
     HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO,  
                       HIF_ASYNCHRONOUS, dmode, HIF_FIXED_ADDRESS); 
     address = HIF_MBOX_END_ADDR(endPointId); 
     status = HIFReadWrite(target->device, address, mboxBuffer->buffer,  
                           mboxBuffer->actualLength, &request, element); 
#ifndef HTC_SYNC 
     if (status != A_OK) { 
#else 
     if (status != A_OK && status != A_PENDING) { 
#endif 
         HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_RECV,  
                         "Frame reception failed\n"); 
         if (!IS_ELEMENT_FREE(element)) { 
             mboxBuffer->actualLength = 0; 
             FRAME_EVENT(eventInfo, mboxBuffer->buffer,  
                         mboxBuffer->bufferLength, mboxBuffer->actualLength,  
                         A_ERROR, mboxBuffer->cookie); 
             RECYCLE_DATA_REQUEST_ELEMENT(element); 
             dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED,  
                           &eventInfo); 
             HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                             "htcReceiveFrame - Exit\n"); 
             return; 
         } 
     } 
#ifdef HTC_SYNC 
	else if (status == A_OK) { 
		element->completionCB(element, status); 
	} 
#endif 
 
    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,  
                    "htcReceiveFrame - Exit\n"); 
} 
 
A_UINT32 
htcGetFrameLength(HTC_ENDPOINT *endPoint) 
{ 
    HTC_TARGET *target; 
    A_UINT32 frameLength; 
    HTC_ENDPOINT_ID endPointId; 
 
    /* Get the context */ 
    AR_DEBUG_ASSERT(endPoint != NULL); 
    target = endPoint->target; 
    AR_DEBUG_ASSERT(target != NULL); 
    endPointId = GET_ENDPOINT_ID(endPoint); 
 
    AR_DEBUG_ASSERT(target->table.rx_lookahead_valid & (1 << endPointId)); 
 
    /* The length is contained in the first two bytes - HTC_HEADER_LEN */ 
    frameLength = (target->table.rx_lookahead[endPointId] & 0xFFFF) + 
                  HTC_HEADER_LEN; 
    AR_DEBUG_ASSERT(frameLength); 
 
    return frameLength; 
}