Merge branch 'for-2.6.30' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux-2.6] / drivers / staging / rt2870 / common / dfs.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27     Module Name:
28     ap_dfs.c
29
30     Abstract:
31     Support DFS function.
32
33     Revision History:
34     Who       When            What
35     --------  ----------      ----------------------------------------------
36     Fonchi    03-12-2007      created
37 */
38
39 #include "../rt_config.h"
40
41 typedef struct _RADAR_DURATION_TABLE
42 {
43         ULONG RDDurRegion;
44         ULONG RadarSignalDuration;
45         ULONG Tolerance;
46 } RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE;
47
48
49 static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] =
50 {
51         {9, 250, 250, 250},             // CE
52         {4, 250, 250, 250},             // FCC
53         {4, 250, 250, 250},             // JAP
54         {15, 250, 250, 250},    // JAP_W53
55         {4, 250, 250, 250}              // JAP_W56
56 };
57
58 /*
59         ========================================================================
60
61         Routine Description:
62                 Bbp Radar detection routine
63
64         Arguments:
65                 pAd     Pointer to our adapter
66
67         Return Value:
68
69         ========================================================================
70 */
71 VOID BbpRadarDetectionStart(
72         IN PRTMP_ADAPTER pAd)
73 {
74         UINT8 RadarPeriod;
75
76         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02);
77         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20);
78         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00);
79         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/);
80         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28);
81         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff);
82
83 #if 0
84         // toggle Rx enable bit for radar detection.
85         // it's Andy's recommand.
86         {
87                 UINT32 Value;
88         RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
89         Value |= (0x1 << 3);
90         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
91         Value &= ~(0x1 << 3);
92         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
93         }
94 #endif
95         RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ?
96                         (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250;
97
98         RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
99         RTMP_IO_WRITE8(pAd, 0x7021, 0x40);
100
101         RadarDetectionStart(pAd, 0, RadarPeriod);
102         return;
103 }
104
105 /*
106         ========================================================================
107
108         Routine Description:
109                 Bbp Radar detection routine
110
111         Arguments:
112                 pAd     Pointer to our adapter
113
114         Return Value:
115
116         ========================================================================
117 */
118 VOID BbpRadarDetectionStop(
119         IN PRTMP_ADAPTER pAd)
120 {
121         RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
122         RTMP_IO_WRITE8(pAd, 0x7021, 0x60);
123
124         RadarDetectionStop(pAd);
125         return;
126 }
127
128 /*
129         ========================================================================
130
131         Routine Description:
132                 Radar detection routine
133
134         Arguments:
135                 pAd     Pointer to our adapter
136
137         Return Value:
138
139         ========================================================================
140 */
141 VOID RadarDetectionStart(
142         IN PRTMP_ADAPTER pAd,
143         IN BOOLEAN CTSProtect,
144         IN UINT8 CTSPeriod)
145 {
146         UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f);
147         UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect.
148
149         if (CTSProtect != 0)
150         {
151                 switch(pAd->CommonCfg.RadarDetect.RDDurRegion)
152                 {
153                 case FCC:
154                 case JAP_W56:
155                         CtsProtect = 0x03;
156                         break;
157
158                 case CE:
159                 case JAP_W53:
160                 default:
161                         CtsProtect = 0x02;
162                         break;
163                 }
164         }
165         else
166                 CtsProtect = 0x01;
167
168
169         // send start-RD with CTS protection command to MCU
170         // highbyte [7]         reserve
171         // highbyte [6:5]       0x: stop Carrier/Radar detection
172         // highbyte [10]:       Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection
173         // highbyte [4:0]       Radar/carrier detection duration. In 1ms.
174
175         // lowbyte [7:0]        Radar/carrier detection period, in 1ms.
176         AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5));
177         //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0);
178
179         return;
180 }
181
182 /*
183         ========================================================================
184
185         Routine Description:
186                 Radar detection routine
187
188         Arguments:
189                 pAd     Pointer to our adapter
190
191         Return Value:
192                 TRUE    Found radar signal
193                 FALSE   Not found radar signal
194
195         ========================================================================
196 */
197 VOID RadarDetectionStop(
198         IN PRTMP_ADAPTER        pAd)
199 {
200         DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n"));
201         AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00);      // send start-RD with CTS protection command to MCU
202
203         return;
204 }
205
206 /*
207         ========================================================================
208
209         Routine Description:
210                 Radar channel check routine
211
212         Arguments:
213                 pAd     Pointer to our adapter
214
215         Return Value:
216                 TRUE    need to do radar detect
217                 FALSE   need not to do radar detect
218
219         ========================================================================
220 */
221 BOOLEAN RadarChannelCheck(
222         IN PRTMP_ADAPTER        pAd,
223         IN UCHAR                        Ch)
224 {
225 #if 1
226         INT             i;
227         BOOLEAN result = FALSE;
228
229         for (i=0; i<pAd->ChannelListNum; i++)
230         {
231                 if (Ch == pAd->ChannelList[i].Channel)
232                 {
233                         result = pAd->ChannelList[i].DfsReq;
234                         break;
235                 }
236         }
237
238         return result;
239 #else
240         INT             i;
241         UCHAR   Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
242
243         for (i=0; i<15; i++)
244         {
245                 if (Ch == Channel[i])
246                 {
247                         break;
248                 }
249         }
250
251         if (i != 15)
252                 return TRUE;
253         else
254                 return FALSE;
255 #endif
256 }
257
258 ULONG JapRadarType(
259         IN PRTMP_ADAPTER pAd)
260 {
261         ULONG           i;
262         const UCHAR     Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
263
264         if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP)
265         {
266                 return pAd->CommonCfg.RadarDetect.RDDurRegion;
267         }
268
269         for (i=0; i<15; i++)
270         {
271                 if (pAd->CommonCfg.Channel == Channel[i])
272                 {
273                         break;
274                 }
275         }
276
277         if (i < 4)
278                 return JAP_W53;
279         else if (i < 15)
280                 return JAP_W56;
281         else
282                 return JAP; // W52
283
284 }
285
286 ULONG RTMPBbpReadRadarDuration(
287         IN PRTMP_ADAPTER        pAd)
288 {
289         UINT8 byteValue = 0;
290         ULONG result;
291
292         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue);
293
294         result = 0;
295         switch (byteValue)
296         {
297         case 1: // radar signal detected by pulse mode.
298         case 2: // radar signal detected by width mode.
299                 result = RTMPReadRadarDuration(pAd);
300                 break;
301
302         case 0: // No radar signal.
303         default:
304
305                 result = 0;
306                 break;
307         }
308
309         return result;
310 }
311
312 ULONG RTMPReadRadarDuration(
313         IN PRTMP_ADAPTER        pAd)
314 {
315         ULONG result = 0;
316
317 #ifdef DFS_SUPPORT
318         UINT8 duration1 = 0, duration2 = 0, duration3 = 0;
319
320         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1);
321         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2);
322         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3);
323         result = (duration1 << 16) + (duration2 << 8) + duration3;
324 #endif // DFS_SUPPORT //
325
326         return result;
327
328 }
329
330 VOID RTMPCleanRadarDuration(
331         IN PRTMP_ADAPTER        pAd)
332 {
333         return;
334 }
335
336 /*
337     ========================================================================
338     Routine Description:
339         Radar wave detection. The API should be invoke each second.
340
341     Arguments:
342         pAd         - Adapter pointer
343
344     Return Value:
345         None
346
347     ========================================================================
348 */
349 VOID ApRadarDetectPeriodic(
350         IN PRTMP_ADAPTER pAd)
351 {
352         INT     i;
353
354         pAd->CommonCfg.RadarDetect.InServiceMonitorCount++;
355
356         for (i=0; i<pAd->ChannelListNum; i++)
357         {
358                 if (pAd->ChannelList[i].RemainingTimeForUse > 0)
359                 {
360                         pAd->ChannelList[i].RemainingTimeForUse --;
361                         if ((pAd->Mlme.PeriodicRound%5) == 0)
362                         {
363                                 DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
364                         }
365                 }
366         }
367
368         //radar detect
369         if ((pAd->CommonCfg.Channel > 14)
370                 && (pAd->CommonCfg.bIEEE80211H == 1)
371                 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
372         {
373                 RadarDetectPeriodic(pAd);
374         }
375
376         return;
377 }
378
379 // Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()
380 // Before switch channel, driver needs doing channel switch announcement.
381 VOID RadarDetectPeriodic(
382         IN PRTMP_ADAPTER        pAd)
383 {
384         // need to check channel availability, after switch channel
385         if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE)
386                         return;
387
388         // channel availability check time is 60sec, use 65 for assurance
389         if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime)
390         {
391                 DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
392                         BbpRadarDetectionStop(pAd);
393                 AsicEnableBssSync(pAd);
394                 pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
395
396
397                 return;
398         }
399
400         return;
401 }
402
403
404 /*
405     ==========================================================================
406     Description:
407                 change channel moving time for DFS testing.
408
409         Arguments:
410             pAdapter                    Pointer to our adapter
411             wrq                         Pointer to the ioctl argument
412
413     Return Value:
414         None
415
416     Note:
417         Usage:
418                1.) iwpriv ra0 set ChMovTime=[value]
419     ==========================================================================
420 */
421 INT Set_ChMovingTime_Proc(
422         IN PRTMP_ADAPTER pAd,
423         IN PUCHAR arg)
424 {
425         UINT8 Value;
426
427         Value = simple_strtol(arg, 0, 10);
428
429         pAd->CommonCfg.RadarDetect.ChMovingTime = Value;
430
431         DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__,
432                 pAd->CommonCfg.RadarDetect.ChMovingTime));
433
434         return TRUE;
435 }
436
437 INT Set_LongPulseRadarTh_Proc(
438         IN PRTMP_ADAPTER pAd,
439         IN PUCHAR arg)
440 {
441         UINT8 Value;
442
443         Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10);
444
445         pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value;
446
447         DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__,
448                 pAd->CommonCfg.RadarDetect.LongPulseRadarTh));
449
450         return TRUE;
451 }
452
453