⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htc_send.c

📁 Atheros Communications AR6001 WLAN Driver for SDIO installation Read Me March 26,2007 (based on
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
// <copyright file="htc_send.c" company="Atheros">
//    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.
//
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
//    Windows CE Wifi Driver for AR-6000
// </summary>
//------------------------------------------------------------------------------
//==============================================================================
// This file contains the routines handling the transmit path.
//
// Author(s): ="Atheros"
//==============================================================================


#include "htc_internal.h"

/* ------ Global Variable Declarations ------- */
extern A_MUTEX_T creditCS,txCS;

#ifdef DEBUG
extern A_UINT32 debughtc;
extern A_UINT32 txcreditsavailable[HTC_MAILBOX_NUM_MAX];
extern A_UINT32 txcreditsconsumed[HTC_MAILBOX_NUM_MAX];
#ifdef HTC_SYNC
extern A_UINT32 txcreditintrenable[HTC_MAILBOX_NUM_MAX];
extern A_UINT32 txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX];
#endif
#endif

extern A_UINT32 tx_attempt[HTC_MAILBOX_NUM_MAX];  /* Num of attempts to add */
extern A_UINT32 tx_post[HTC_MAILBOX_NUM_MAX];     /* Num of attemps succeded */
extern A_UINT32 tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete */

void htcSendFrameLocked(HTC_ENDPOINT *endPoint);

/* ------ Functions ------ */
A_STATUS 
HTCBufferSend(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 *sendQueue;

    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND, 
                    "HTCBufferSend: Enter (endPointId: %d, buffer: 0x%p, length: %d, cookie: 0x%p)\n", endPointId, buffer, length, cookie);

    AR_DEBUG_ASSERT((endPointId >= ENDPOINT1) && (endPointId <= ENDPOINT4));
    AR_DEBUG_ASSERT(length);

    /* Extract the end point instance */
    endPoint = &target->endPoint[endPointId];
    AR_DEBUG_ASSERT(endPoint != NULL);
    sendQueue = &endPoint->sendQueue;
    AR_DEBUG_ASSERT(sendQueue != NULL);
    HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND, 
                    "mboxQueue: %p\n", sendQueue);

    /* 
     * Add this posted buffer to the pending send queue. We need to allocate 
     * a bufferElement to store the packet information and we borrow that 
     * buffer from the pending send queue. If circumstances allow us to 
     * transmit it right away then we dequeue it otherwise we let it remain 
     * to be picked in the interrupt handler context.
     */
    tx_attempt[endPointId] += 1;

    if (!endPoint->enabled) {
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND, "Endpoint not enabled: %d\n", 
                                        GET_ENDPOINT_ID(endPoint));
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND, 
                        "tx_attempt[%d] = %d, tx_post[%d] = %d, tx_complete[%d] = %d\n", endPointId, tx_attempt[endPointId], endPointId, tx_post[endPointId], endPointId, tx_complete[endPointId]);
        return A_ERROR;
    }

    status = addToMboxQueue(sendQueue, buffer, length, 0, cookie);
    if (status != A_OK) {
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND,
                        "Mailbox (%d) PSQ full. Unable to add buffer\n", 
                         endPointId);
        HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND, 
                        "tx_attempt[%d] = %d, tx_post[%d] = %d, tx_complete[%d] = %d\n", endPointId, tx_attempt[endPointId], endPointId, tx_post[endPointId], endPointId, tx_complete[endPointId]);
        return A_ERROR;
    }

    tx_post[endPointId] += 1;

    /* 
     * The frame shall be dequeued and sent if there are any credits 
     * available. 
     */
    htcSendFrame(endPoint);

    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND, "HTCBufferSend: Exit\n");
    return A_OK;
}

void
htcSendFrame(HTC_ENDPOINT *endPoint) 
{
	A_MUTEX_LOCK(&txCS);	
	htcSendFrameLocked(endPoint);
	A_MUTEX_UNLOCK(&txCS);
}

void 
htcSendFrameLocked(HTC_ENDPOINT *endPoint) 
{
    A_STATUS status;
    A_UINT32 address;
    HIF_DATAMODE dmode;
    HTC_TARGET *target;
    HIF_REQUEST request;
    A_UINT32 frameLength;
    A_UINT32 paddedLength;
    HTC_EVENT_INFO eventInfo;
#ifdef ONLY_16BIT
    A_UINT16 txCreditsConsumed;
    A_UINT16 txCreditsAvailable;
#else
    A_UINT8 txCreditsConsumed;
    A_UINT8 txCreditsAvailable;
#endif
    HTC_ENDPOINT_ID endPointId;
    HTC_QUEUE_ELEMENT *element;
    HTC_MBOX_BUFFER *mboxBuffer;
    HTC_REG_REQUEST_LIST *regList;
    HTC_DATA_REQUEST_QUEUE *sendQueue;
#ifdef HTC_SYNC
    HTC_REG_BUFFER *regBuffer;
#endif

    HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND, "htcSendFrame - Enter\n");

    /* Get the context */
    AR_DEBUG_ASSERT(endPoint != NULL);
    endPointId = GET_ENDPOINT_ID(endPoint);
    target = endPoint->target;
    AR_DEBUG_ASSERT(target != NULL);
    sendQueue = &endPoint->sendQueue;
    AR_DEBUG_ASSERT(sendQueue != NULL);
    regList = &target->regList;
    AR_DEBUG_ASSERT(regList != NULL);

    /* 
     * Transmit the frames as long as we have the credits available and
     * the queue is not out of them 
     */
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,
                    "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__);
    A_MUTEX_LOCK(&creditCS);
    txCreditsAvailable = GET_TX_CREDITS_AVAILABLE(endPoint);
    txCreditsConsumed = GET_TX_CREDITS_CONSUMED(endPoint);
    SET_TX_CREDITS_AVAILABLE(endPoint, 0);
    SET_TX_CREDITS_CONSUMED(endPoint, txCreditsConsumed + txCreditsAvailable);
    HTC_DEBUG_PRINTF(ATH_LOG_SYNC,
                    "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__);
    A_MUTEX_UNLOCK(&creditCS);

    if (!txCreditsAvailable) {
        return;
    }

    /* 
     * Send the packet only when there are packets to be sent and there
     * are positive number of credits available.
     */
    while((!IS_DATA_QUEUE_EMPTY(sendQueue)) && txCreditsAvailable)
    {
        /* Get the request buffer from the Pending Send Queue */
        element = removeFromMboxQueue(sendQueue);
        mboxBuffer = GET_MBOX_BUFFER(element);

        /* 
         * Prepend the actual length in the first 2 bytes of the outgoing 
         * packet.
         */
        mboxBuffer->buffer -= HTC_HEADER_LEN;
        A_MEMCPY(mboxBuffer->buffer, &mboxBuffer->bufferLength, HTC_HEADER_LEN);

        /* 
         * Adjust the length in the block mode only when its not an integral 
         * multiple of the block size. Assumption is that the block size is
         * a power of 2.
         */
        frameLength = mboxBuffer->bufferLength + HTC_HEADER_LEN;
        paddedLength = (frameLength + (endPoint->blockSize - 1)) & 
                       (~(endPoint->blockSize - 1));
        mboxBuffer->actualLength = paddedLength;
        HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,  
                        "Original frame length: %d, Padded frame length: %d\n", frameLength, paddedLength);

        HTC_DEBUG_PRINTBUF(mboxBuffer->buffer, (A_UINT16)mboxBuffer->actualLength);
        HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,  
                        "Available Tx credits: %d\n", txCreditsAvailable);

        /* Frame the interface request */
        dmode = (endPoint->blockSize > 1) ? HIF_BLOCK_BASIS : HIF_BYTE_BASIS;
        HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, 
                          HIF_ASYNCHRONOUS, dmode, HIF_INCREMENTAL_ADDRESS);
        address = HIF_MBOX_START_ADDR(endPointId);

        /* Send the data to the bus driver */
        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) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -