?? htc_events.c
字號:
/* * Copyright (c) 2004-2006 Atheros Communications Inc. * * Wireless Network driver for Atheros AR6001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * * This file contains the routines handling the different events and callbacks * from the hardware interface layer. */#include "htc_internal.h"/* ------ Global Variable Declarations ------- */extern A_MUTEX_T instanceCS, counterCS, creditCS;extern A_WAITQUEUE_HEAD htcEvent;#ifdef DEBUGextern 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];#endifextern A_UINT32 tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete *//* ------ Static Variables ------ *//* ------ Functions ------ */#ifdef CFA_STATUS htcInterruptEnabler(HIF_DEVICE *device) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; HTC_TARGET *target; target = getTargetInstance(device); AR_DEBUG_ASSERT(target != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_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 */ HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, &target->table.int_status_enable, 1, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("htcInterruptEnabler Exit\n")); return A_OK;}#endif /* CF */A_STATUShtcRWCompletionHandler(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_STATUShtcTxCompletionCB(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; AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_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); AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_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) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_SEND, ("Frame transmission failed\n")); AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_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); AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, ("htcTxCompletionCB - Exit\n")); } return A_OK; } AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_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); AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, ("htcTxCompletionCB - Exit\n")); return A_OK;}A_STATUShtcBlkSzNegCompletionCB(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, 1, INT_WLAN_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, &target->table.int_wlan, 1, &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_STATUShtcRxCompletionCB(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; AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, ("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); AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_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) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_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); AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV, ("htcRxCompletionCB - Exit\n")); } return A_OK; } AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_RECV, ("Frame reception complete\n")); AR_DEBUG_PRINTBUF(mboxBuffer->buffer, 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); AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV, ("htcRxCompletion - Exit\n")); return A_OK;}A_STATUShtcRegCompletionCB(HTC_REG_REQUEST_ELEMENT *element, A_STATUS status){ A_STATUS ret; HTC_TARGET *target; HTC_ENDPOINT *endPoint; HTC_REG_BUFFER *regBuffer; A_UINT8 txCreditsConsumed; A_UINT8 txCreditsAvailable; HTC_ENDPOINT_ID endPointId; AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV | ATH_DEBUG_SEND, ("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: AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("TX_CREDIT_COUNTER_DECREMENT_REG\n")); endPointId = regBuffer->offset; endPoint = &target->endPoint[endPointId]; AR_DEBUG_PRINTF(ATH_DEBUG_SYNC, ("Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__)); A_MUTEX_LOCK(&creditCS); /* Calculate the number of credits available */ AR_DEBUG_ASSERT(GET_TX_CREDITS_CONSUMED(endPoint) == regBuffer->length); 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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -