📄 htc_events.c
字号:
//------------------------------------------------------------------------------
// <copyright file="htc_events.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 different events and callbacks
// from the hardware interface layer.
//
// Author(s): ="Atheros"
//==============================================================================
#include "htc_internal.h"
/* ------ Global Variable Declarations ------- */
extern A_MUTEX_T instanceCS, counterCS, creditCS,txCS;
extern A_WAITQUEUE_HEAD htcEvent;
#ifdef DEBUG
extern A_UINT32 debughtc;
extern A_UINT32 txcreditsavailable[HTC_MAILBOX_NUM_MAX];
extern A_UINT32 txcreditsconsumed[HTC_MAILBOX_NUM_MAX];
extern A_UINT32 txcreditintrenable[HTC_MAILBOX_NUM_MAX];
extern A_UINT32 txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX];
#endif
extern A_UINT32 tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete */
/* ------ Static Variables ------ */
/* ------ Functions ------ */
A_STATUS htcInterruptEnabler(HIF_DEVICE *device) {
A_STATUS status;
A_UINT32 address;
HIF_REQUEST request;
HTC_TARGET *target;
HTC_REG_REQUEST_ELEMENT *element;
target = getTargetInstance(device);
AR_DEBUG_ASSERT(target != NULL);
HTC_DEBUG_PRINTF(ATH_LOG_TRC,
"htcInterruptEnabler Enter target: 0x%p\n", target);
target->table.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) |
INT_STATUS_ENABLE_CPU_SET(0x01) |
INT_STATUS_ENABLE_COUNTER_SET(0x01) |
INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F);
/* Reenable Dragon Interrupts */
element = allocateRegRequestElement(target);
AR_DEBUG_ASSERT(element != NULL);
#ifdef ONLY_16BIT
FILL_REG_BUFFER(element, (A_UINT16 *)&target->table.int_status_enable, 2,
INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED);
#else
FILL_REG_BUFFER(element, &target->table.int_status_enable, 1,
INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED);
#endif
HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS,
HIF_BYTE_BASIS, HIF_FIXED_ADDRESS);
address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED);
#ifdef ONLY_16BIT
status = HIFReadWrite(target->device, address,
&target->table.int_status_enable, 2,
&request, element);
#else
status = HIFReadWrite(target->device, address,
&target->table.int_status_enable, 1,
&request, element);
#endif
#ifndef HTC_SYNC
AR_DEBUG_ASSERT(status == A_OK);
#else
AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING);
if ( status == A_OK ) {
element->completionCB(element, status);
}
#endif //HTC_SYNC
HTC_DEBUG_PRINTF(ATH_LOG_TRC,"htcInterruptEnabler Exit\n");
return A_OK;
}
A_STATUS
htcRWCompletionHandler(void *context,
A_STATUS status)
{
HTC_QUEUE_ELEMENT *element;
element = (HTC_QUEUE_ELEMENT *)context;
AR_DEBUG_ASSERT(element != NULL);
return(element->completionCB(element, status));
}
A_STATUS
htcTxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element,
A_STATUS status)
{
HTC_TARGET *target;
HTC_ENDPOINT_ID endPointId;
HTC_ENDPOINT *endPoint;
HTC_EVENT_INFO eventInfo;
HTC_MBOX_BUFFER *mboxBuffer;
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,
"htcTxCompletionCB - Enter\n");
/* Get the context */
mboxBuffer = GET_MBOX_BUFFER(element);
AR_DEBUG_ASSERT(mboxBuffer != NULL);
endPoint = mboxBuffer->endPoint;
AR_DEBUG_ASSERT(endPoint != NULL);
target = endPoint->target;
AR_DEBUG_ASSERT(target != NULL);
endPointId = GET_ENDPOINT_ID(endPoint);
HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,
"mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target);
/* Return the buffer to the user if the transmission was not successful */
if (status != A_OK) {
HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND,
"Frame transmission failed\n");
HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_SEND,
"EndPoint: %d, Tx credits available: %d\n",
endPointId, GET_TX_CREDITS_AVAILABLE(endPoint));
/*
* In the failure case it is possible that while queueing of the
* request itself it returned an error status in which case we
* would have dispatched an event and freed the element there
* itself. Ideally if it failed to queue the request then it
* should not generate a callback but we are being a little
* conservative.
*/
if (!(IS_ELEMENT_FREE(element))) {
mboxBuffer->buffer += HTC_HEADER_LEN;
FRAME_EVENT(eventInfo, mboxBuffer->buffer,
mboxBuffer->bufferLength, mboxBuffer->actualLength,
A_ECANCELED, mboxBuffer->cookie);
RECYCLE_DATA_REQUEST_ELEMENT(element);
dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo);
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,
"htcTxCompletionCB - Exit\n");
}
return A_OK;
}
HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,
"Frame transmission complete\n");
/*
* The user should see the actual length and buffer length
* to be the same. In case of block mode, we use the actual length
* parameter to reflect the total number of bytes transmitted after
* padding.
*/
mboxBuffer->actualLength = mboxBuffer->bufferLength;
mboxBuffer->buffer += HTC_HEADER_LEN;
/*
* Return the transmit buffer to the user through the HTC_BUFFER_SENT
* event indicating that the frame was transmitted successfully.
*/
FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength,
mboxBuffer->actualLength, A_OK, mboxBuffer->cookie);
RECYCLE_DATA_REQUEST_ELEMENT(element);
tx_complete[endPointId] += 1;
dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo);
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND,
"htcTxCompletionCB - Exit\n");
return A_OK;
}
A_STATUS
htcBlkSzNegCompletionCB(HTC_DATA_REQUEST_ELEMENT *element,
A_STATUS status)
{
HTC_TARGET *target;
HTC_ENDPOINT *endPoint;
HIF_REQUEST request;
HTC_MBOX_BUFFER *mboxBuffer;
HTC_REG_REQUEST_ELEMENT *regElement;
A_UINT32 address;
/* Get the context */
mboxBuffer = GET_MBOX_BUFFER(element);
AR_DEBUG_ASSERT(mboxBuffer != NULL);
endPoint = mboxBuffer->endPoint;
AR_DEBUG_ASSERT(endPoint != NULL);
target = endPoint->target;
AR_DEBUG_ASSERT(target != NULL);
/* Recycle the request element */
RECYCLE_DATA_REQUEST_ELEMENT(element);
element->completionCB = htcTxCompletionCB;
if (status == A_OK) {
/* Mark the state to be ready */
endPoint->enabled = TRUE;
/* Set the state of the target as ready */
if (target->endPoint[ENDPOINT1].enabled &&
target->endPoint[ENDPOINT2].enabled &&
target->endPoint[ENDPOINT3].enabled &&
target->endPoint[ENDPOINT4].enabled )
{
/* Send the INT_WLAN interrupt to the target */
target->table.int_wlan = 1;
HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO,
HIF_ASYNCHRONOUS, HIF_BYTE_BASIS,
HIF_FIXED_ADDRESS);
address = getRegAddr(INT_WLAN_REG, ENDPOINT_UNUSED);
regElement = allocateRegRequestElement(target);
AR_DEBUG_ASSERT(regElement != NULL);
FILL_REG_BUFFER(regElement, &target->table.int_wlan, sizeof(target->table.int_wlan),
INT_WLAN_REG, ENDPOINT_UNUSED);
status = HIFReadWrite(target->device, address,
(A_UCHAR *)&target->table.int_wlan,
sizeof(target->table.int_wlan), &request, regElement);
#ifndef HTC_SYNC
AR_DEBUG_ASSERT(status == A_OK);
#else
AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING);
if(status == A_OK) {
regElement->completionCB(regElement, status);
}
#endif
}
}
return A_OK;
}
A_STATUS
htcRxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element,
A_STATUS status)
{
HTC_TARGET *target;
HTC_ENDPOINT *endPoint;
HTC_EVENT_INFO eventInfo;
HTC_ENDPOINT_ID endPointId;
HTC_MBOX_BUFFER *mboxBuffer;
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,
"htcRxCompletionCB - Enter\n");
/* Get the context */
mboxBuffer = GET_MBOX_BUFFER(element);
AR_DEBUG_ASSERT(mboxBuffer != NULL);
endPoint = mboxBuffer->endPoint;
AR_DEBUG_ASSERT(endPoint != NULL);
target = endPoint->target;
AR_DEBUG_ASSERT(target != NULL);
endPointId = GET_ENDPOINT_ID(endPoint);
HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV,
"mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target);
/* Return the buffer to the user if the reception was not successful */
if (status != A_OK) {
HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_RECV,
"Frame reception failed\n");
/*
* In the failure case it is possible that while queueing of the
* request itself it returned an error status in which case we
* would have dispatched an event and freed the element there
* itself. Ideally if it failed to queue the request then it
* should not generate a callback but we are being a little
* conservative.
*/
if (!(IS_ELEMENT_FREE(element))) {
mboxBuffer->actualLength = 0;
mboxBuffer->buffer += HTC_HEADER_LEN;
FRAME_EVENT(eventInfo, mboxBuffer->buffer,
mboxBuffer->bufferLength, mboxBuffer->actualLength,
A_ECANCELED, mboxBuffer->cookie);
RECYCLE_DATA_REQUEST_ELEMENT(element);
dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo);
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,
"htcRxCompletionCB - Exit\n");
}
return A_OK;
}
HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV,
"Frame reception complete\n");
HTC_DEBUG_PRINTBUF(mboxBuffer->buffer, (A_UINT16)mboxBuffer->actualLength);
/*
* Advance the pointer by the size of HTC header and pass the payload
* pointer to the upper layer.
*/
mboxBuffer->actualLength = ((mboxBuffer->buffer[0] << 0) |
(mboxBuffer->buffer[1] << 8));
mboxBuffer->buffer += HTC_HEADER_LEN;
/*
* Frame the HTC_BUFFER_RECEIVED to the upper layer indicating that the
* packet has been succesfully received.
*/
FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength,
mboxBuffer->actualLength, A_OK, mboxBuffer->cookie);
/* Recycle the bufferElement structure */
RECYCLE_DATA_REQUEST_ELEMENT(element);
/* Dispatch the event */
dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo);
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV,
"htcRxCompletion - Exit\n");
return A_OK;
}
A_STATUS
htcRegCompletionCB(HTC_REG_REQUEST_ELEMENT *element,
A_STATUS status)
{
A_STATUS ret;
HTC_TARGET *target;
HTC_ENDPOINT *endPoint;
HTC_REG_BUFFER *regBuffer;
#ifdef ONLY_16BIT
A_UINT16 txCreditsConsumed;
A_UINT16 txCreditsAvailable;
#else
A_UINT8 txCreditsConsumed;
A_UINT8 txCreditsAvailable;
#endif
HTC_ENDPOINT_ID endPointId;
HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND | ATH_LOG_RECV,
"htcRegCompletion - Enter\n");
AR_DEBUG_ASSERT(status == A_OK);
/* Get the context */
AR_DEBUG_ASSERT(element != NULL);
regBuffer = GET_REG_BUFFER(element);
AR_DEBUG_ASSERT(regBuffer != NULL);
target = regBuffer->target;
AR_DEBUG_ASSERT(target != NULL);
/* Identify the register and the operation responsible for the callback */
ret = A_OK;
switch(regBuffer->base) {
case TX_CREDIT_COUNTER_DECREMENT_REG:
HTC_DEBUG_PRINTF(ATH_LOG_INF, "TX_CREDIT_COUNTER_DECREMENT_REG\n");
endPointId = regBuffer->offset;
endPoint = &target->endPoint[endPointId];
HTC_DEBUG_PRINTF(ATH_LOG_SYNC,
"Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__);
A_MUTEX_LOCK(&creditCS);
/* Calculate the number of credits available */
#ifdef ONLY_16BIT
AR_DEBUG_ASSERT((GET_TX_CREDITS_CONSUMED(endPoint)*2) == regBuffer->length);
#else
AR_DEBUG_ASSERT(GET_TX_CREDITS_CONSUMED(endPoint) == regBuffer->length);
#endif
AR_DEBUG_ASSERT(regBuffer->buffer[0] >=
GET_TX_CREDITS_CONSUMED(endPoint));
SET_TX_CREDITS_AVAILABLE(endPoint, regBuffer->buffer[0] -
GET_TX_CREDITS_CONSUMED(endPoint));
SET_TX_CREDITS_CONSUMED(endPoint, 0);
txCreditsAvailable = GET_TX_CREDITS_AVAILABLE(endPoint);
txCreditsConsumed = GET_TX_CREDITS_CONSUMED(endPoint);
HTC_DEBUG_PRINTF(ATH_LOG_SYNC,
"Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__);
A_MUTEX_UNLOCK(&creditCS);
HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -