|
1 /* |
|
2 * txXfer.c |
|
3 * |
|
4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. |
|
5 * All rights reserved. |
|
6 * |
|
7 * This program and the accompanying materials are made available under the |
|
8 * terms of the Eclipse Public License v1.0 or BSD License which accompanies |
|
9 * this distribution. The Eclipse Public License is available at |
|
10 * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below. |
|
11 * |
|
12 * Redistribution and use in source and binary forms, with or without |
|
13 * modification, are permitted provided that the following conditions |
|
14 * are met: |
|
15 * |
|
16 * * Redistributions of source code must retain the above copyright |
|
17 * notice, this list of conditions and the following disclaimer. |
|
18 * * Redistributions in binary form must reproduce the above copyright |
|
19 * notice, this list of conditions and the following disclaimer in |
|
20 * the documentation and/or other materials provided with the |
|
21 * distribution. |
|
22 * * Neither the name Texas Instruments nor the names of its |
|
23 * contributors may be used to endorse or promote products derived |
|
24 * from this software without specific prior written permission. |
|
25 * |
|
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
37 */ |
|
38 |
|
39 |
|
40 /**************************************************************************** |
|
41 * |
|
42 * MODULE: txXfer.c |
|
43 * |
|
44 * PURPOSE: Handle Tx frame transfer to the firmware. |
|
45 * |
|
46 * DESCRIPTION: |
|
47 * ============ |
|
48 * This module gets the upper driver's Tx packets after FW resources were |
|
49 * allocated for it, and handles its transfer to the FW via the |
|
50 * host slave (indirect) interface, using the TwIf Transaction API. |
|
51 * |
|
52 ****************************************************************************/ |
|
53 |
|
54 #define __FILE_ID__ FILE_ID_108 |
|
55 #include "tidef.h" |
|
56 #include "osApi.h" |
|
57 #include "report.h" |
|
58 #include "TwIf.h" |
|
59 #include "TWDriver.h" |
|
60 #include "FwEvent_api.h" |
|
61 #include "txXfer_api.h" |
|
62 |
|
63 |
|
64 |
|
65 typedef struct |
|
66 { |
|
67 TTxnStruct tTxnStruct; |
|
68 TI_UINT8 *pPktsCntr; |
|
69 } TPktsCntrTxn; |
|
70 |
|
71 |
|
72 /* The TxXfer module object. */ |
|
73 typedef struct |
|
74 { |
|
75 TI_HANDLE hOs; |
|
76 TI_HANDLE hReport; |
|
77 TI_HANDLE hTwIf; |
|
78 |
|
79 TSendPacketTranferCb fSendPacketTransferCb; /* Upper layer Xfer-Complete callback */ |
|
80 TI_HANDLE hSendPacketTransferHndl; /* Upper layer Xfer-Complete callback handle */ |
|
81 |
|
82 TI_UINT32 uPktsCntr; |
|
83 TPktsCntrTxn aPktsCntrTxn[CTRL_BLK_ENTRIES_NUM]; |
|
84 |
|
85 } TTxXferObj; |
|
86 |
|
87 static void txXfer_TransferDoneCb (TI_HANDLE hTxXfer, TTxnStruct *pTxn); |
|
88 |
|
89 |
|
90 |
|
91 /**************************************************************************** |
|
92 * txXfer_Create() |
|
93 **************************************************************************** |
|
94 * DESCRIPTION: Create the Xfer module object |
|
95 * |
|
96 * INPUTS: None |
|
97 * |
|
98 * OUTPUT: None |
|
99 * |
|
100 * RETURNS: The Created object |
|
101 ****************************************************************************/ |
|
102 TI_HANDLE txXfer_Create(TI_HANDLE hOs) |
|
103 { |
|
104 TTxXferObj *pTxXfer; |
|
105 int i; |
|
106 |
|
107 pTxXfer = os_memoryAlloc (hOs, sizeof(TTxXferObj), MemoryNormal); |
|
108 if (pTxXfer == NULL) |
|
109 { |
|
110 return NULL; |
|
111 } |
|
112 |
|
113 os_memoryZero (hOs, pTxXfer, sizeof(TTxXferObj)); |
|
114 |
|
115 for (i = 0; i < CTRL_BLK_ENTRIES_NUM; i++) |
|
116 { |
|
117 pTxXfer->aPktsCntrTxn[i].pPktsCntr = os_memoryAlloc (hOs, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ, MemoryDMA); |
|
118 if (pTxXfer->aPktsCntrTxn[i].pPktsCntr == NULL) |
|
119 { |
|
120 return NULL; |
|
121 } |
|
122 os_memoryZero (hOs, pTxXfer->aPktsCntrTxn[i].pPktsCntr, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ); |
|
123 pTxXfer->aPktsCntrTxn[i].pPktsCntr += WSPI_PAD_LEN_READ; |
|
124 } |
|
125 |
|
126 pTxXfer->hOs = hOs; |
|
127 |
|
128 return (TI_HANDLE)pTxXfer; |
|
129 } |
|
130 |
|
131 |
|
132 /**************************************************************************** |
|
133 * txXfer_Destroy() |
|
134 **************************************************************************** |
|
135 * DESCRIPTION: Destroy the Xfer module object |
|
136 * |
|
137 * INPUTS: hTxXfer - The object to free |
|
138 * |
|
139 * OUTPUT: None |
|
140 * |
|
141 * RETURNS: TI_OK or TI_NOK |
|
142 ****************************************************************************/ |
|
143 TI_STATUS txXfer_Destroy(TI_HANDLE hTxXfer) |
|
144 { |
|
145 TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
|
146 int i; |
|
147 |
|
148 if (pTxXfer) |
|
149 { |
|
150 for (i = 0; i < CTRL_BLK_ENTRIES_NUM; i++) |
|
151 { |
|
152 if (pTxXfer->aPktsCntrTxn[i].pPktsCntr) |
|
153 { |
|
154 os_memoryFree (pTxXfer->hOs, ((TI_UINT8*)pTxXfer->aPktsCntrTxn[i].pPktsCntr) - WSPI_PAD_LEN_READ, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ); |
|
155 } |
|
156 } |
|
157 |
|
158 os_memoryFree (pTxXfer->hOs, pTxXfer, sizeof(TTxXferObj)); |
|
159 } |
|
160 |
|
161 return TI_OK; |
|
162 } |
|
163 |
|
164 |
|
165 /**************************************************************************** |
|
166 * txXfer_init() |
|
167 **************************************************************************** |
|
168 DESCRIPTION: |
|
169 ============ |
|
170 Initialize the Xfer module. |
|
171 ****************************************************************************/ |
|
172 TI_STATUS txXfer_Init (TI_HANDLE hTxXfer, TI_HANDLE hReport, TI_HANDLE hTwIf) |
|
173 { |
|
174 TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
|
175 TTxnStruct *pTxn; |
|
176 TI_UINT8 i; |
|
177 |
|
178 pTxXfer->hReport = hReport; |
|
179 pTxXfer->hTwIf = hTwIf; |
|
180 pTxXfer->fSendPacketTransferCb = NULL; |
|
181 |
|
182 |
|
183 pTxXfer->uPktsCntr = 0; |
|
184 for (i = 0; i < CTRL_BLK_ENTRIES_NUM; i++) |
|
185 { |
|
186 pTxn = &(pTxXfer->aPktsCntrTxn[i].tTxnStruct); |
|
187 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) |
|
188 BUILD_TTxnStruct(pTxn, HOST_WR_ACCESS_REG, pTxXfer->aPktsCntrTxn[i].pPktsCntr, REGISTER_SIZE, NULL, NULL) |
|
189 } |
|
190 |
|
191 return txXfer_Restart(hTxXfer); |
|
192 } |
|
193 |
|
194 |
|
195 /**************************************************************************** |
|
196 * txXfer_Restart() |
|
197 **************************************************************************** |
|
198 DESCRIPTION: |
|
199 ============ |
|
200 Restart the Xfer module. |
|
201 ****************************************************************************/ |
|
202 TI_STATUS txXfer_Restart (TI_HANDLE hTxXfer) |
|
203 { |
|
204 TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
|
205 |
|
206 pTxXfer->uPktsCntr = 0; |
|
207 |
|
208 return TI_OK; |
|
209 } |
|
210 |
|
211 |
|
212 /**************************************************************************** |
|
213 * txXfer_sendPacket() |
|
214 **************************************************************************** |
|
215 * DESCRIPTION: |
|
216 ============ |
|
217 Send packet to the transaction queue. |
|
218 Return the transfer status: |
|
219 TXN_STATUS_COMPLETE - if completed, i.e. Synchronous mode. |
|
220 TXN_STATUS_PENDING - if pending, i.e. Asynchronous mode. |
|
221 Note that in case of PENDING, a callback function will be called |
|
222 only if registered (needed for WHA). |
|
223 ****************************************************************************/ |
|
224 ETxnStatus txXfer_SendPacket (TI_HANDLE hTxXfer, TTxCtrlBlk *pPktCtrlBlk) |
|
225 { |
|
226 TTxXferObj *pTxXfer = (TTxXferObj *)hTxXfer; |
|
227 TTxnStruct *pTxn = (TTxnStruct *)pPktCtrlBlk; |
|
228 ETxnStatus eStatus; |
|
229 TPktsCntrTxn *pPktsCntrTxn; |
|
230 |
|
231 /* Prepare the Txn fields to the host-slave register (fixed address) */ |
|
232 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_FIXED_ADDR) |
|
233 pTxn->uHwAddr = SLV_MEM_DATA; |
|
234 |
|
235 /* Fill the TxnDone CB only if registered by the upper layers */ |
|
236 if (pTxXfer->fSendPacketTransferCb == NULL) |
|
237 { |
|
238 pTxn->fTxnDoneCb = NULL; |
|
239 } |
|
240 else |
|
241 { |
|
242 pTxn->fTxnDoneCb = (TTxnDoneCb)txXfer_TransferDoneCb; |
|
243 pTxn->hCbHandle = hTxXfer; |
|
244 } |
|
245 |
|
246 /* Send the transaction */ |
|
247 eStatus = twIf_Transact (pTxXfer->hTwIf, pTxn); |
|
248 |
|
249 #ifdef TI_DBG |
|
250 |
|
251 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); |
|
252 |
|
253 if (eStatus == TXN_STATUS_ERROR) |
|
254 { |
|
255 TI_UINT32 i; |
|
256 for (i = 0; i < MAX_XFER_BUFS; i++) |
|
257 { |
|
258 if (pPktCtrlBlk->tTxnStruct.aLen[i] == 0) |
|
259 { |
|
260 break; |
|
261 } |
|
262 TRACE1(pTxXfer->hReport, REPORT_SEVERITY_CONSOLE, "txXfer_SendPacket(): Tx Buffer %d:\n", i); |
|
263 WLAN_OS_REPORT (("txXfer_SendPacket(): Tx Buffer %d:\n", i)); |
|
264 report_PrintDump(pPktCtrlBlk->tTxnStruct.aBuf[i], pPktCtrlBlk->tTxnStruct.aLen[i]); |
|
265 } |
|
266 } |
|
267 |
|
268 #endif /* TI_DBG */ |
|
269 |
|
270 |
|
271 pTxXfer->uPktsCntr++; |
|
272 pPktsCntrTxn = &(pTxXfer->aPktsCntrTxn[pTxXfer->uPktsCntr % CTRL_BLK_ENTRIES_NUM]); |
|
273 *((TI_UINT32*)(pPktsCntrTxn->pPktsCntr)) = ENDIAN_HANDLE_LONG(pTxXfer->uPktsCntr); |
|
274 pPktsCntrTxn->tTxnStruct.uHwAddr = HOST_WR_ACCESS_REG; |
|
275 twIf_Transact(pTxXfer->hTwIf, &pPktsCntrTxn->tTxnStruct); |
|
276 |
|
277 /* Return the Txn result - COMPLETE or PENDING. */ |
|
278 /* Note: For PENDING, a callback function will be called only if registered (needed for WHA) */ |
|
279 return eStatus; |
|
280 } |
|
281 |
|
282 |
|
283 /**************************************************************************** |
|
284 * txXfer_TransferDoneCb() |
|
285 **************************************************************************** |
|
286 * DESCRIPTION: Call the upper layers TranferDone callback, providing the TxCtrlBlk |
|
287 ****************************************************************************/ |
|
288 static void txXfer_TransferDoneCb (TI_HANDLE hTxXfer, TTxnStruct *pTxn) |
|
289 { |
|
290 TTxXferObj *pTxXfer = (TTxXferObj*)hTxXfer; |
|
291 |
|
292 TRACE1(pTxXfer->hReport, REPORT_SEVERITY_INFORMATION, ": pTxn=0x%x\n", pTxn); |
|
293 |
|
294 /* Call the upper layers TranferDone callback, providing the TxCtrlBlk. */ |
|
295 /* Note: If this CB was called it means that the upper CB exists (see in txXfer_SendPacket) */ |
|
296 pTxXfer->fSendPacketTransferCb (pTxXfer->hSendPacketTransferHndl, (TTxCtrlBlk *)pTxn); |
|
297 } |
|
298 |
|
299 |
|
300 /**************************************************************************** |
|
301 * txXfer_RegisterCb() |
|
302 **************************************************************************** |
|
303 * DESCRIPTION: Register the upper driver Xfer callback functions. |
|
304 ****************************************************************************/ |
|
305 void txXfer_RegisterCb (TI_HANDLE hTxXfer, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj) |
|
306 { |
|
307 TTxXferObj* pTxXfer = (TTxXferObj*)hTxXfer; |
|
308 |
|
309 TRACE3(pTxXfer->hReport, REPORT_SEVERITY_INFORMATION, ": CallBackID=%d, CBFunc=0x%x, CBObj=0x%x\n", CallBackID, CBFunc, CBObj); |
|
310 |
|
311 switch(CallBackID) |
|
312 { |
|
313 /* Save upper layers Transfer-Done callback */ |
|
314 case TWD_INT_SEND_PACKET_TRANSFER: |
|
315 pTxXfer->fSendPacketTransferCb = (TSendPacketTranferCb)CBFunc; |
|
316 pTxXfer->hSendPacketTransferHndl = CBObj; |
|
317 break; |
|
318 |
|
319 default: |
|
320 TRACE0(pTxXfer->hReport, REPORT_SEVERITY_ERROR, " - Illegal value\n"); |
|
321 break; |
|
322 } |
|
323 } |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |