| /* |
| * txXfer.c |
| * |
| * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Texas Instruments nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| /**************************************************************************** |
| * |
| * MODULE: txXfer.c |
| * |
| * PURPOSE: Handle Tx frame transfer to the firmware. |
| * |
| * DESCRIPTION: |
| * ============ |
| * This module gets the upper driver's Tx packets after FW resources were |
| * allocated for it, and handles its transfer to the FW via the |
| * host slave (indirect) interface, using the TwIf Transaction API. |
| * |
| ****************************************************************************/ |
| |
| #define __FILE_ID__ FILE_ID_108 |
| #include "tidef.h" |
| #include "osApi.h" |
| #include "report.h" |
| #include "TwIf.h" |
| #include "TWDriver.h" |
| #include "FwEvent_api.h" |
| #include "txXfer_api.h" |
| |
| |
| /* remove workaround when WL6-PG1.0 becomes obsolete */ |
| typedef struct |
| { |
| TTxnStruct tTxnStruct; |
| TI_UINT32 uPktsCntr; |
| } TPktsCntrTxn; |
| |
| |
| /* The TxXfer module object. */ |
| typedef struct |
| { |
| TI_HANDLE hOs; |
| TI_HANDLE hReport; |
| TI_HANDLE hTwIf; |
| |
| TSendPacketTranferCb fSendPacketTransferCb; /* Upper layer Xfer-Complete callback */ |
| TI_HANDLE hSendPacketTransferHndl; /* Upper layer Xfer-Complete callback handle */ |
| |
| /* remove workaround when WL6-PG1.0 becomes obsolete */ |
| TI_BOOL bChipIs1273Pg10; |
| TI_UINT32 uPktsCntr; |
| TPktsCntrTxn aPktsCntrTxn[CTRL_BLK_ENTRIES_NUM]; |
| |
| } TTxXferObj; |
| |
| static void txXfer_TransferDoneCb (TI_HANDLE hTxXfer, TTxnStruct *pTxn); |
| |
| |
| |
| /**************************************************************************** |
| * txXfer_Create() |
| **************************************************************************** |
| * DESCRIPTION: Create the Xfer module object |
| * |
| * INPUTS: None |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: The Created object |
| ****************************************************************************/ |
| TI_HANDLE txXfer_Create(TI_HANDLE hOs) |
| { |
| TTxXferObj *pTxXfer; |
| |
| pTxXfer = os_memoryAlloc (hOs, sizeof(TTxXferObj)); |
| if (pTxXfer == NULL) |
| { |
| return NULL; |
| } |
| |
| os_memoryZero (hOs, pTxXfer, sizeof(TTxXferObj)); |
| |
| pTxXfer->hOs = hOs; |
| |
| return (TI_HANDLE)pTxXfer; |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_Destroy() |
| **************************************************************************** |
| * DESCRIPTION: Destroy the Xfer module object |
| * |
| * INPUTS: hTxXfer - The object to free |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: TI_OK or TI_NOK |
| ****************************************************************************/ |
| TI_STATUS txXfer_Destroy(TI_HANDLE hTxXfer) |
| { |
| TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
| |
| if (pTxXfer) |
| { |
| os_memoryFree (pTxXfer->hOs, pTxXfer, sizeof(TTxXferObj)); |
| } |
| |
| return TI_OK; |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_init() |
| **************************************************************************** |
| DESCRIPTION: |
| ============ |
| Initialize the Xfer module. |
| ****************************************************************************/ |
| TI_STATUS txXfer_Init (TI_HANDLE hTxXfer, TI_HANDLE hReport, TI_HANDLE hTwIf) |
| { |
| TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
| TTxnStruct *pTxn; |
| TI_UINT8 i; |
| |
| pTxXfer->hReport = hReport; |
| pTxXfer->hTwIf = hTwIf; |
| pTxXfer->fSendPacketTransferCb = NULL; |
| |
| /* remove workaround when WL6-PG1.0 becomes obsolete */ |
| pTxXfer->uPktsCntr = 0; |
| for (i = 0; i < CTRL_BLK_ENTRIES_NUM; i++) |
| { |
| pTxn = &(pTxXfer->aPktsCntrTxn[i].tTxnStruct); |
| TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) |
| BUILD_TTxnStruct(pTxn, HOST_WR_ACCESS_REG, &pTxXfer->aPktsCntrTxn[i].uPktsCntr, REGISTER_SIZE, NULL, NULL) |
| } |
| |
| return txXfer_Restart(hTxXfer, TI_TRUE); |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_Restart() |
| **************************************************************************** |
| DESCRIPTION: |
| ============ |
| Restart the Xfer module. |
| ****************************************************************************/ |
| TI_STATUS txXfer_Restart (TI_HANDLE hTxXfer, TI_BOOL bChipIs1273Pg10) |
| { |
| TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
| |
| /* remove the counter transactions workaround when WL6-PG1.0 becomes obsolete */ |
| pTxXfer->bChipIs1273Pg10 = bChipIs1273Pg10; |
| pTxXfer->uPktsCntr = 0; |
| |
| return TI_OK; |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_sendPacket() |
| **************************************************************************** |
| * DESCRIPTION: |
| ============ |
| Send packet to the transaction queue. |
| Return the transfer status: |
| TXN_STATUS_COMPLETE - if completed, i.e. Synchronous mode. |
| TXN_STATUS_PENDING - if pending, i.e. Asynchronous mode. |
| Note that in case of PENDING, a callback function will be called |
| only if registered (needed for WHA). |
| ****************************************************************************/ |
| ETxnStatus txXfer_SendPacket (TI_HANDLE hTxXfer, TTxCtrlBlk *pPktCtrlBlk) |
| { |
| TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
| TTxnStruct *pTxn = (TTxnStruct *)pPktCtrlBlk; |
| ETxnStatus eStatus; |
| TPktsCntrTxn *pPktsCntrTxn; |
| |
| /* Prepare the Txn fields to the host-slave register (fixed address) */ |
| TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_FIXED_ADDR) |
| pTxn->uHwAddr = SLV_MEM_DATA; |
| |
| /* Fill the TxnDone CB only if registered by the upper layers */ |
| if (pTxXfer->fSendPacketTransferCb == NULL) |
| { |
| pTxn->fTxnDoneCb = NULL; |
| } |
| else |
| { |
| pTxn->fTxnDoneCb = (TTxnDoneCb)txXfer_TransferDoneCb; |
| pTxn->hCbHandle = hTxXfer; |
| } |
| |
| /* Send the transaction */ |
| eStatus = twIf_Transact (pTxXfer->hTwIf, pTxn); |
| |
| #ifdef TI_DBG |
| |
| TRACE11(pTxXfer->hReport, REPORT_SEVERITY_INFORMATION, ": Status=%d, PktType=%d, Len0=%d, Len1=%d, Length=%d, ExtraBlks=%d, TotalBlks=%d, TxAttr=0x%x, TID=%d, DescID=%d, StartTime=%d\n", eStatus, pPktCtrlBlk->tTxPktParams.uPktType, pPktCtrlBlk->tTxnStruct.aLen[0], pPktCtrlBlk->tTxnStruct.aLen[1], pPktCtrlBlk->tTxDescriptor.length, pPktCtrlBlk->tTxDescriptor.extraMemBlks, pPktCtrlBlk->tTxDescriptor.totalMemBlks, pPktCtrlBlk->tTxDescriptor.txAttr, pPktCtrlBlk->tTxDescriptor.tid, pPktCtrlBlk->tTxDescriptor.descID, pPktCtrlBlk->tTxDescriptor.startTime); |
| |
| if (eStatus == TXN_STATUS_ERROR) |
| { |
| TI_UINT32 i; |
| for (i = 0; i < MAX_XFER_BUFS; i++) |
| { |
| if (pPktCtrlBlk->tTxnStruct.aLen[i] == 0) |
| { |
| break; |
| } |
| TRACE1(pTxXfer->hReport, REPORT_SEVERITY_CONSOLE, "txXfer_SendPacket(): Tx Buffer %d:\n", i); |
| WLAN_OS_REPORT (("txXfer_SendPacket(): Tx Buffer %d:\n", i)); |
| report_PrintDump(pPktCtrlBlk->tTxnStruct.aBuf[i], pPktCtrlBlk->tTxnStruct.aLen[i]); |
| return eStatus; |
| } |
| } |
| |
| #endif /* TI_DBG */ |
| |
| /* remove workaround when WL6-PG1.0 becomes obsolete */ |
| if (1) /* restore -> if (pTxXfer->bChipIs1273Pg10) */ |
| { |
| pTxXfer->uPktsCntr++; |
| pPktsCntrTxn = &(pTxXfer->aPktsCntrTxn[pTxXfer->uPktsCntr % CTRL_BLK_ENTRIES_NUM]); |
| pPktsCntrTxn->uPktsCntr = ENDIAN_HANDLE_LONG(pTxXfer->uPktsCntr); |
| pPktsCntrTxn->tTxnStruct.uHwAddr = HOST_WR_ACCESS_REG; |
| twIf_Transact(pTxXfer->hTwIf, &pPktsCntrTxn->tTxnStruct); |
| } |
| |
| /* Return the Txn result - COMPLETE or PENDING. */ |
| /* Note: For PENDING, a callback function will be called only if registered (needed for WHA) */ |
| return eStatus; |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_TransferDoneCb() |
| **************************************************************************** |
| * DESCRIPTION: Call the upper layers TranferDone callback, providing the TxCtrlBlk |
| ****************************************************************************/ |
| static void txXfer_TransferDoneCb (TI_HANDLE hTxXfer, TTxnStruct *pTxn) |
| { |
| TTxXferObj *pTxXfer = (TTxXferObj*)hTxXfer; |
| |
| TRACE1(pTxXfer->hReport, REPORT_SEVERITY_INFORMATION, ": pTxn=0x%x\n", pTxn); |
| |
| /* Call the upper layers TranferDone callback, providing the TxCtrlBlk. */ |
| /* Note: If this CB was called it means that the upper CB exists (see in txXfer_SendPacket) */ |
| pTxXfer->fSendPacketTransferCb (pTxXfer->hSendPacketTransferHndl, (TTxCtrlBlk *)pTxn); |
| } |
| |
| |
| /**************************************************************************** |
| * txXfer_RegisterCb() |
| **************************************************************************** |
| * DESCRIPTION: Register the upper driver Xfer callback functions. |
| ****************************************************************************/ |
| void txXfer_RegisterCb (TI_HANDLE hTxXfer, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj) |
| { |
| TTxXferObj* pTxXfer = (TTxXferObj*)hTxXfer; |
| |
| TRACE3(pTxXfer->hReport, REPORT_SEVERITY_INFORMATION, ": CallBackID=%d, CBFunc=0x%x, CBObj=0x%x\n", CallBackID, CBFunc, CBObj); |
| |
| switch(CallBackID) |
| { |
| /* Save upper layers Transfer-Done callback */ |
| case TWD_INT_SEND_PACKET_TRANSFER: |
| pTxXfer->fSendPacketTransferCb = (TSendPacketTranferCb)CBFunc; |
| pTxXfer->hSendPacketTransferHndl = CBObj; |
| break; |
| |
| default: |
| TRACE0(pTxXfer->hReport, REPORT_SEVERITY_ERROR, " - Illegal value\n"); |
| break; |
| } |
| } |
| |
| |
| |
| |
| |