Linux 2.6.31-rc6
[linux-2.6] / drivers / staging / vt6655 / wctl.c
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * File: wctl.c
20  *
21  * Purpose: handle WMAC duplicate filter & defragment
22  *
23  * Author: Jerry Chen
24  *
25  * Date: Jun. 27, 2002
26  *
27  * Functions:
28  *      WCTLbIsDuplicate - Test if duplicate packet
29  *      WCTLuSearchDFCB - Search DeFragment Control Database
30  *      WCTLuInsertDFCB - Insert DeFragment Control Database
31  *      WCTLbHandleFragment - Handle received fragment packet
32  *
33  * Revision History:
34  *
35  */
36
37
38 #if !defined(__WCTL_H__)
39 #include "wctl.h"
40 #endif
41 #if !defined(__DEVICE_H__)
42 #include "device.h"
43 #endif
44 #if !defined(__CARD_H__)
45 #include "card.h"
46 #endif
47
48 /*---------------------  Static Definitions -------------------------*/
49
50 /*---------------------  Static Classes  ----------------------------*/
51
52 /*---------------------  Static Variables  --------------------------*/
53 // static int          msglevel                =MSG_LEVEL_INFO;
54 /*---------------------  Static Functions  --------------------------*/
55
56 /*---------------------  Export Variables  --------------------------*/
57
58
59
60 /*
61  * Description:
62  *      Scan Rx cache.  Return TRUE if packet is duplicate, else
63  *      inserts in receive cache and returns FALSE.
64  *
65  * Parameters:
66  *  In:
67  *      pCache      - Receive packets history
68  *      pMACHeader  - 802.11 MAC Header of received packet
69  *  Out:
70  *      none
71  *
72  * Return Value: TRUE if packet duplicate; otherwise FALSE
73  *
74  */
75
76 BOOL WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
77 {
78     UINT            uIndex;
79     UINT            ii;
80     PSCacheEntry    pCacheEntry;
81
82     if (IS_FC_RETRY(pMACHeader)) {
83
84         uIndex = pCache->uInPtr;
85         for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
86             pCacheEntry = &(pCache->asCacheEntry[uIndex]);
87             if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
88                 (IS_ETH_ADDRESS_EQUAL (&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
89                 ) {
90                 /* Duplicate match */
91                 return TRUE;
92             }
93             ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
94         }
95     }
96     /* Not fount in cache - insert */
97     pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
98     pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
99     memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), U_ETHER_ADDR_LEN);
100     ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
101     return FALSE;
102 }
103
104 /*
105  * Description:
106  *      Found if sequence number of received fragment packet in Defragment Database
107  *
108  * Parameters:
109  *  In:
110  *      pDevice     - Pointer to adapter
111  *      pMACHeader  - 802.11 MAC Header of received packet
112  *  Out:
113  *      none
114  *
115  * Return Value: index number in Defragment Database
116  *
117  */
118 UINT WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader)
119 {
120 UINT ii;
121
122     for(ii=0;ii<pDevice->cbDFCB;ii++) {
123         if ((pDevice->sRxDFCB[ii].bInUse == TRUE) &&
124             (IS_ETH_ADDRESS_EQUAL (&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
125             ) {
126             //
127             return(ii);
128         }
129     }
130     return(pDevice->cbDFCB);
131 }
132
133
134 /*
135  * Description:
136  *      Insert received fragment packet in Defragment Database
137  *
138  * Parameters:
139  *  In:
140  *      pDevice     - Pointer to adapter
141  *      pMACHeader  - 802.11 MAC Header of received packet
142  *  Out:
143  *      none
144  *
145  * Return Value: index number in Defragment Database
146  *
147  */
148 UINT WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader)
149 {
150 UINT ii;
151
152     if (pDevice->cbFreeDFCB == 0)
153         return(pDevice->cbDFCB);
154     for(ii=0;ii<pDevice->cbDFCB;ii++) {
155         if (pDevice->sRxDFCB[ii].bInUse == FALSE) {
156             pDevice->cbFreeDFCB--;
157             pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
158             pDevice->sRxDFCB[ii].bInUse = TRUE;
159             pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
160             pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
161             memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]), U_ETHER_ADDR_LEN);
162             return(ii);
163         }
164     }
165     return(pDevice->cbDFCB);
166 }
167
168
169 /*
170  * Description:
171  *      Handle received fragment packet
172  *
173  * Parameters:
174  *  In:
175  *      pDevice         - Pointer to adapter
176  *      pMACHeader      - 802.11 MAC Header of received packet
177  *      cbFrameLength   - Frame length
178  *      bWEP            - is WEP packet
179  *  Out:
180  *      none
181  *
182  * Return Value: TRUE if it is valid fragment packet and we have resource to defragment; otherwise FALSE
183  *
184  */
185 BOOL WCTLbHandleFragment (PSDevice pDevice, PS802_11Header pMACHeader, UINT cbFrameLength, BOOL bWEP, BOOL bExtIV)
186 {
187 UINT            uHeaderSize;
188
189
190     if (bWEP == TRUE) {
191         uHeaderSize = 28;
192         if (bExtIV)
193         // ExtIV
194             uHeaderSize +=4;
195     }
196     else {
197         uHeaderSize = 24;
198     }
199
200     if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
201         pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
202         if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
203             // duplicate, we must flush previous DCB
204             pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
205             pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
206             pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
207         }
208         else {
209             pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
210             if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
211                 return(FALSE);
212             }
213         }
214         // reserve 4 byte to match MAC RX Buffer
215 #ifdef PRIVATE_OBJ
216         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].ref_skb.data + 4);
217 #else
218         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
219 #endif
220         memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
221         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
222         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
223         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
224         //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
225         return(FALSE);
226     }
227     else {
228         pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
229         if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
230             if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
231                 (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
232                 ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
233
234                 memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
235                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
236                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
237                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
238                 //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
239             }
240             else {
241                 // seq error or frag # error flush DFCB
242                 pDevice->cbFreeDFCB++;
243                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
244                 return(FALSE);
245             }
246         }
247         else {
248             return(FALSE);
249         }
250         if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
251             //enq defragcontrolblock
252             pDevice->cbFreeDFCB++;
253             pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = FALSE;
254             //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
255             return(TRUE);
256         }
257         return(FALSE);
258     }
259 }
260
261