tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / ixp / npe / IxEthDBWiFi.c
1 /**
2  * @file IxEthDBAPI.c
3  *
4  * @brief Implementation of the public API
5  * 
6  * @par
7  * IXP400 SW Release version 2.0
8  * 
9  * -- Copyright Notice --
10  * 
11  * @par
12  * Copyright 2001-2005, Intel Corporation.
13  * All rights reserved.
14  * 
15  * @par
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. Neither the name of the Intel Corporation nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  * 
28  * @par
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
30  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  * 
41  * @par
42  * -- End of Copyright Notice --
43  */
44
45 #include "IxEthDB_p.h"
46
47 /* forward prototypes */
48 IX_ETH_DB_PUBLIC
49 MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations);
50
51 /**
52  * @brief sets the BBSID value for the WiFi header conversion feature
53  *
54  * @param portID ID of the port
55  * @param bbsid pointer to the 6-byte BBSID value
56  *
57  * Note that this function is documented in the main component
58  * header file, IxEthDB.h.
59  *
60  * @return IX_ETH_DB_SUCCESS if the operation completed successfully
61  * or an appropriate error message otherwise
62  */
63 IX_ETH_DB_PUBLIC
64 IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid)
65 {
66     IxNpeMhMessage message;
67     IX_STATUS result;
68     
69     IX_ETH_DB_CHECK_PORT(portID);
70     
71     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
72     
73     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
74  
75     IX_ETH_DB_CHECK_REFERENCE(bbsid);
76     
77     memcpy(ixEthDBPortInfo[portID].bbsid, bbsid, sizeof (IxEthDBMacAddr));
78
79     FILL_SETBBSID_MSG(message, portID, bbsid);
80
81     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
82     
83     return result;
84 }
85
86 /**
87  * @brief updates the Frame Control and Duration/ID WiFi header
88  * conversion parameters in an NPE
89  *
90  * @param portID ID of the port
91  *
92  * This function will send a message to the NPE updating the 
93  * frame conversion parameters for 802.3 => 802.11 header conversion.
94  *
95  * @return IX_ETH_DB_SUCCESS if the operation completed successfully
96  * or IX_ETH_DB_FAIL otherwise
97  *
98  * @internal
99  */
100 IX_ETH_DB_PRIVATE
101 IxEthDBStatus ixEthDBWiFiFrameControlDurationIDUpdate(IxEthDBPortId portID)
102 {
103     IxNpeMhMessage message;
104     IX_STATUS result;
105
106     FILL_SETFRAMECONTROLDURATIONID(message, portID, ixEthDBPortInfo[portID].frameControlDurationID);
107     
108     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
109     
110     return result;
111 }
112
113 /**
114  * @brief sets the Duration/ID WiFi frame header conversion parameter
115  *
116  * @param portID ID of the port
117  * @param durationID 16-bit value containing the new Duration/ID parameter
118  *
119  * Note that this function is documented in the main component
120  * header file, IxEthDB.h.
121  *
122  * @return IX_ETH_DB_SUCCESS if the operation completed successfully
123  * or an appropriate error message otherwise
124  */
125 IX_ETH_DB_PUBLIC
126 IxEthDBStatus ixEthDBWiFiDurationIDSet(IxEthDBPortId portID, UINT16 durationID)
127 {
128     IX_ETH_DB_CHECK_PORT(portID);
129     
130     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
131     
132     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
133
134     ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF0000) | durationID;
135     
136     return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
137 }
138
139 /**
140  * @brief sets the Frame Control WiFi frame header conversion parameter
141  *
142  * @param portID ID of the port
143  * @param durationID 16-bit value containing the new Frame Control parameter
144  *
145  * Note that this function is documented in the main component
146  * header file, IxEthDB.h.
147  *
148  * @return IX_ETH_DB_SUCCESS if the operation completed successfully
149  * or an appropriate error message otherwise
150  */
151 IX_ETH_DB_PUBLIC
152 IxEthDBStatus ixEthDBWiFiFrameControlSet(IxEthDBPortId portID, UINT16 frameControl)
153 {
154     IX_ETH_DB_CHECK_PORT(portID);
155     
156     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
157     
158     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
159
160     ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF) | (frameControl << 16); 
161     
162     return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
163 }
164
165 /**
166  * @brief removes a WiFi header conversion record
167  *
168  * @param portID ID of the port
169  * @param macAddr MAC address of the record to remove
170  *
171  * Note that this function is documented in the main
172  * component header file, IxEthDB.h.
173  *
174  * @return IX_ETH_DB_SUCCESS if the operation completed
175  * successfully or an appropriate error message otherwise
176  */
177 IX_ETH_DB_PUBLIC
178 IxEthDBStatus ixEthDBWiFiEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
179 {
180     MacDescriptor recordTemplate;
181     
182     IX_ETH_DB_CHECK_PORT(portID);
183     
184     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
185     
186     IX_ETH_DB_CHECK_REFERENCE(macAddr);
187     
188     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
189     
190     memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
191     
192     recordTemplate.type   = IX_ETH_DB_WIFI_RECORD;
193     recordTemplate.portID = portID;
194     
195     return ixEthDBRemove(&recordTemplate, NULL);
196 }
197
198 /**
199  * @brief adds a WiFi header conversion record
200  *
201  * @param portID ID of the port
202  * @param macAddr MAC address of the record to add
203  * @param gatewayMacAddr address of the gateway (or
204  * NULL if this is a station record)
205  *
206  * This function adds a record of type AP_TO_AP (gateway is not NULL)
207  * or AP_TO_STA (gateway is NULL) in the main database as a 
208  * WiFi header conversion record.
209  *
210  * @return IX_ETH_DB_SUCCESS if the operation completed
211  * successfully or an appropriate error message otherwise
212  *
213  * @internal
214  */
215 IX_ETH_DB_PRIVATE
216 IxEthDBStatus ixEthDBWiFiEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
217 {
218     MacDescriptor recordTemplate;
219
220     IX_ETH_DB_CHECK_PORT(portID);
221
222     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
223
224     IX_ETH_DB_CHECK_REFERENCE(macAddr);
225     
226     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
227
228     memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
229     
230     recordTemplate.type   = IX_ETH_DB_WIFI_RECORD;
231     recordTemplate.portID = portID;
232     
233     if (gatewayMacAddr != NULL)
234     {
235         memcpy(recordTemplate.recordData.wifiData.gwMacAddress, gatewayMacAddr, sizeof (IxEthDBMacAddr));
236         
237         recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_AP;
238     }
239     else
240     {
241         memset(recordTemplate.recordData.wifiData.gwMacAddress, 0, sizeof (IxEthDBMacAddr));
242
243         recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_STA;
244     }
245     
246     return ixEthDBAdd(&recordTemplate, NULL);
247 }
248
249 /**
250  * @brief adds a WiFi header conversion record
251  *
252  * @param portID ID of the port
253  * @param macAddr MAC address of the record to add
254  * @param gatewayMacAddr address of the gateway 
255  *
256  * This function adds a record of type AP_TO_AP
257  * in the main database as a WiFi header conversion record.
258  *
259  * This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
260  *
261  * Note that this function is documented in the main
262  * component header file, IxEthDB.h.
263  *
264  * @return IX_ETH_DB_SUCCESS if the operation completed
265  * successfully or an appropriate error message otherwise
266  */
267 IX_ETH_DB_PUBLIC
268 IxEthDBStatus ixEthDBWiFiAccessPointEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
269 {
270     IX_ETH_DB_CHECK_REFERENCE(gatewayMacAddr);
271
272     return ixEthDBWiFiEntryAdd(portID, macAddr, gatewayMacAddr);
273 }
274
275 /**
276  * @brief adds a WiFi header conversion record
277  *
278  * @param portID ID of the port
279  * @param macAddr MAC address of the record to add
280  *
281  * This function adds a record of type AP_TO_STA
282  * in the main database as a WiFi header conversion record.
283  *
284  * This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
285  *
286  * Note that this function is documented in the main
287  * component header file, IxEthDB.h.
288  *
289  * @return IX_ETH_DB_SUCCESS if the operation completed
290  * successfully or an appropriate error message otherwise
291  */
292 IX_ETH_DB_PUBLIC
293 IxEthDBStatus ixEthDBWiFiStationEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
294 {
295     return ixEthDBWiFiEntryAdd(portID, macAddr, NULL);
296 }
297
298 /**
299  * @brief selects a set of gateways from a tree of 
300  * WiFi header conversion records
301  *
302  * @param stations binary tree containing pointers to WiFi header
303  * conversion records
304  *
305  * This function browses through the input binary tree, identifies
306  * records of type AP_TO_AP, clones these records and appends them
307  * to a vine (a single right-branch binary tree) which is returned
308  * as result. A maximum of MAX_GW_SIZE entries containing gateways
309  * will be cloned from the original tree.
310  *
311  * @return vine (linear binary tree) containing record
312  * clones of AP_TO_AP type, which have a gateway field
313  *
314  * @internal
315  */
316 IX_ETH_DB_PUBLIC
317 MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations)
318 {
319     MacTreeNodeStack *stack;
320     MacTreeNode *gateways, *insertionPlace;
321     UINT32 gwIndex = 1; /* skip the empty root */
322     
323     if (stations == NULL)
324     {
325         return NULL;
326     }
327
328     stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack));
329
330     if (stack == NULL)
331     {
332         ERROR_LOG("DB: (WiFi) failed to allocate the node stack for gateway tree linearization, out of memory?\n");
333         return NULL;
334     }
335     
336     /* initialize root node */
337     gateways = insertionPlace = NULL;
338         
339     /* start browsing the station tree */
340     NODE_STACK_INIT(stack);
341     
342     /* initialize stack by pushing the tree root at offset 0 */
343     NODE_STACK_PUSH(stack, stations, 0);
344     
345     while (NODE_STACK_NONEMPTY(stack))
346     {
347         MacTreeNode *node;
348         UINT32 offset;
349        
350         NODE_STACK_POP(stack, node, offset);
351
352         /* we can store maximum 31 (32 total, 1 empty root) entries in the gateway tree */
353         if (offset > (MAX_GW_SIZE - 1)) break;
354         
355         /* check if this record has a gateway address */
356         if (node->descriptor != NULL && node->descriptor->recordData.wifiData.type == IX_ETH_DB_WIFI_AP_TO_AP)
357         {
358             /* found a record, create an insertion place */
359             if (insertionPlace != NULL)
360             {
361                 insertionPlace->right = ixEthDBAllocMacTreeNode();
362                 insertionPlace        = insertionPlace->right;
363             }
364             else
365             {
366                 gateways       = ixEthDBAllocMacTreeNode();
367                 insertionPlace = gateways;
368             }
369
370             if (insertionPlace == NULL)
371             {
372                 /* no nodes left, bail out with what we have */
373                 ixOsalCacheDmaFree(stack);
374                 return gateways;
375             }
376             
377             /* clone the original record for the gateway tree */
378             insertionPlace->descriptor = ixEthDBCloneMacDescriptor(node->descriptor);
379             
380             /* insert and update the offset in the original record */
381             node->descriptor->recordData.wifiData.gwAddressIndex = gwIndex++;
382         }
383         
384         /* browse the tree */
385         if (node->left != NULL)
386         {
387             NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset));
388         }
389
390         if (node->right != NULL)
391         {
392             NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset));
393         }
394     }
395     
396     ixOsalCacheDmaFree(stack);
397     return gateways;    
398 }
399
400 /**
401  * @brief downloads the WiFi header conversion table to an NPE
402  *
403  * @param portID ID of the port
404  *
405  * This function prepares the WiFi header conversion tables and
406  * downloads them to the specified NPE port.
407  *
408  * The header conversion tables consist in the main table of
409  * addresses and the secondary table of gateways. AP_TO_AP records
410  * from the first table contain index fields into the second table
411  * for gateway selection.
412  *
413  * Note that this function is documented in the main component
414  * header file, IxEthDB.h.
415  *
416  * @return IX_ETH_DB_SUCCESS if the operation completed successfully
417  * or an appropriate error message otherwise
418  */
419 IX_ETH_DB_PUBLIC
420 IxEthDBStatus ixEthDBWiFiConversionTableDownload(IxEthDBPortId portID)
421 {
422     IxEthDBPortMap query;
423     MacTreeNode *stations = NULL, *gateways = NULL, *gateway = NULL;
424     IxNpeMhMessage message;
425     PortInfo *portInfo;
426     IX_STATUS result;
427
428     IX_ETH_DB_CHECK_PORT(portID);
429
430     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
431     
432     IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
433
434     portInfo = &ixEthDBPortInfo[portID];
435    
436     SET_DEPENDENCY_MAP(query, portID);
437     
438     ixEthDBUpdateLock();
439
440     stations = ixEthDBQuery(NULL, query, IX_ETH_DB_WIFI_RECORD, MAX_ELT_SIZE);
441     gateways = ixEthDBGatewaySelect(stations);
442     
443     /* clean up gw area */
444     memset((void *) portInfo->updateMethod.npeGwUpdateZone, FULL_GW_BYTE_SIZE, 0);
445
446     /* write all gateways */
447     gateway = gateways;
448
449     while (gateway != NULL)
450     {
451         ixEthDBNPEGatewayNodeWrite((void *) (((UINT32) portInfo->updateMethod.npeGwUpdateZone) 
452             + gateway->descriptor->recordData.wifiData.gwAddressIndex * ELT_ENTRY_SIZE), 
453             gateway);
454
455         gateway = gateway->right;
456     }
457
458     /* free the gateway tree */
459     if (gateways != NULL)
460     {
461         ixEthDBFreeMacTreeNode(gateways);
462     }
463
464     FILL_SETAPMACTABLE_MSG(message, 
465         IX_OSAL_MMU_VIRT_TO_PHYS(portInfo->updateMethod.npeGwUpdateZone));
466
467     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
468
469     if (result == IX_SUCCESS)
470     {
471         /* update the main tree (the stations tree) */
472         portInfo->updateMethod.searchTree = stations;
473         
474         result = ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_WIFI_RECORD);
475     }
476
477     ixEthDBUpdateUnlock();
478
479     return result;
480 }