📄 htc_send.c
字号:
//------------------------------------------------------------------------------
// <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 + -