Staging: add rt3070 wireless driver
[safe/jmp/linux-2.6] / drivers / staging / rt3070 / 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         RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ?
84                         (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250;
85
86         RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
87         RTMP_IO_WRITE8(pAd, 0x7021, 0x40);
88
89         RadarDetectionStart(pAd, 0, RadarPeriod);
90         return;
91 }
92
93 /*
94         ========================================================================
95
96         Routine Description:
97                 Bbp Radar detection routine
98
99         Arguments:
100                 pAd     Pointer to our adapter
101
102         Return Value:
103
104         ========================================================================
105 */
106 VOID BbpRadarDetectionStop(
107         IN PRTMP_ADAPTER pAd)
108 {
109         RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
110         RTMP_IO_WRITE8(pAd, 0x7021, 0x60);
111
112         RadarDetectionStop(pAd);
113         return;
114 }
115
116 /*
117         ========================================================================
118
119         Routine Description:
120                 Radar detection routine
121
122         Arguments:
123                 pAd     Pointer to our adapter
124
125         Return Value:
126
127         ========================================================================
128 */
129 VOID RadarDetectionStart(
130         IN PRTMP_ADAPTER pAd,
131         IN BOOLEAN CTSProtect,
132         IN UINT8 CTSPeriod)
133 {
134         UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f);
135         UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect.
136
137         if (CTSProtect != 0)
138         {
139                 switch(pAd->CommonCfg.RadarDetect.RDDurRegion)
140                 {
141                 case FCC:
142                 case JAP_W56:
143                         CtsProtect = 0x03;
144                         break;
145
146                 case CE:
147                 case JAP_W53:
148                 default:
149                         CtsProtect = 0x02;
150                         break;
151                 }
152         }
153         else
154                 CtsProtect = 0x01;
155
156
157         // send start-RD with CTS protection command to MCU
158         // highbyte [7]         reserve
159         // highbyte [6:5]       0x: stop Carrier/Radar detection
160         // highbyte [10]:       Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection
161         // highbyte [4:0]       Radar/carrier detection duration. In 1ms.
162
163         // lowbyte [7:0]        Radar/carrier detection period, in 1ms.
164         AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5));
165         //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0);
166
167         return;
168 }
169
170 /*
171         ========================================================================
172
173         Routine Description:
174                 Radar detection routine
175
176         Arguments:
177                 pAd     Pointer to our adapter
178
179         Return Value:
180                 TRUE    Found radar signal
181                 FALSE   Not found radar signal
182
183         ========================================================================
184 */
185 VOID RadarDetectionStop(
186         IN PRTMP_ADAPTER        pAd)
187 {
188         DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n"));
189         AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00);      // send start-RD with CTS protection command to MCU
190
191         return;
192 }
193
194 /*
195         ========================================================================
196
197         Routine Description:
198                 Radar channel check routine
199
200         Arguments:
201                 pAd     Pointer to our adapter
202
203         Return Value:
204                 TRUE    need to do radar detect
205                 FALSE   need not to do radar detect
206
207         ========================================================================
208 */
209 BOOLEAN RadarChannelCheck(
210         IN PRTMP_ADAPTER        pAd,
211         IN UCHAR                        Ch)
212 {
213 #if 1
214         INT             i;
215         BOOLEAN result = FALSE;
216
217         for (i=0; i<pAd->ChannelListNum; i++)
218         {
219                 if (Ch == pAd->ChannelList[i].Channel)
220                 {
221                         result = pAd->ChannelList[i].DfsReq;
222                         break;
223                 }
224         }
225
226         return result;
227 #else
228         INT             i;
229         UCHAR   Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
230
231         for (i=0; i<15; i++)
232         {
233                 if (Ch == Channel[i])
234                 {
235                         break;
236                 }
237         }
238
239         if (i != 15)
240                 return TRUE;
241         else
242                 return FALSE;
243 #endif
244 }
245
246 ULONG JapRadarType(
247         IN PRTMP_ADAPTER pAd)
248 {
249         ULONG           i;
250         const UCHAR     Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
251
252         if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP)
253         {
254                 return pAd->CommonCfg.RadarDetect.RDDurRegion;
255         }
256
257         for (i=0; i<15; i++)
258         {
259                 if (pAd->CommonCfg.Channel == Channel[i])
260                 {
261                         break;
262                 }
263         }
264
265         if (i < 4)
266                 return JAP_W53;
267         else if (i < 15)
268                 return JAP_W56;
269         else
270                 return JAP; // W52
271
272 }
273
274 ULONG RTMPBbpReadRadarDuration(
275         IN PRTMP_ADAPTER        pAd)
276 {
277         UINT8 byteValue = 0;
278         ULONG result;
279
280         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue);
281
282         result = 0;
283         switch (byteValue)
284         {
285         case 1: // radar signal detected by pulse mode.
286         case 2: // radar signal detected by width mode.
287                 result = RTMPReadRadarDuration(pAd);
288                 break;
289
290         case 0: // No radar signal.
291         default:
292
293                 result = 0;
294                 break;
295         }
296
297         return result;
298 }
299
300 ULONG RTMPReadRadarDuration(
301         IN PRTMP_ADAPTER        pAd)
302 {
303         ULONG result = 0;
304
305 #ifdef DFS_SUPPORT
306         UINT8 duration1 = 0, duration2 = 0, duration3 = 0;
307
308         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1);
309         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2);
310         BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3);
311         result = (duration1 << 16) + (duration2 << 8) + duration3;
312 #endif // DFS_SUPPORT //
313
314         return result;
315
316 }
317
318 VOID RTMPCleanRadarDuration(
319         IN PRTMP_ADAPTER        pAd)
320 {
321         return;
322 }
323
324 /*
325     ========================================================================
326     Routine Description:
327         Radar wave detection. The API should be invoke each second.
328
329     Arguments:
330         pAd         - Adapter pointer
331
332     Return Value:
333         None
334
335     ========================================================================
336 */
337 VOID ApRadarDetectPeriodic(
338         IN PRTMP_ADAPTER pAd)
339 {
340         INT     i;
341
342         pAd->CommonCfg.RadarDetect.InServiceMonitorCount++;
343
344         for (i=0; i<pAd->ChannelListNum; i++)
345         {
346                 if (pAd->ChannelList[i].RemainingTimeForUse > 0)
347                 {
348                         pAd->ChannelList[i].RemainingTimeForUse --;
349                         if ((pAd->Mlme.PeriodicRound%5) == 0)
350                         {
351                                 DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
352                         }
353                 }
354         }
355
356         //radar detect
357         if ((pAd->CommonCfg.Channel > 14)
358                 && (pAd->CommonCfg.bIEEE80211H == 1)
359                 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
360         {
361                 RadarDetectPeriodic(pAd);
362         }
363
364         return;
365 }
366
367 // Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()
368 // Before switch channel, driver needs doing channel switch announcement.
369 VOID RadarDetectPeriodic(
370         IN PRTMP_ADAPTER        pAd)
371 {
372         // need to check channel availability, after switch channel
373         if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE)
374                         return;
375
376         // channel availability check time is 60sec, use 65 for assurance
377         if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime)
378         {
379                 DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
380                         BbpRadarDetectionStop(pAd);
381                 AsicEnableBssSync(pAd);
382                 pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
383
384
385                 return;
386         }
387
388         return;
389 }
390
391
392 /*
393     ==========================================================================
394     Description:
395                 change channel moving time for DFS testing.
396
397         Arguments:
398             pAdapter                    Pointer to our adapter
399             wrq                         Pointer to the ioctl argument
400
401     Return Value:
402         None
403
404     Note:
405         Usage:
406                1.) iwpriv ra0 set ChMovTime=[value]
407     ==========================================================================
408 */
409 INT Set_ChMovingTime_Proc(
410         IN PRTMP_ADAPTER pAd,
411         IN PUCHAR arg)
412 {
413         UINT8 Value;
414
415         Value = simple_strtol(arg, 0, 10);
416
417         pAd->CommonCfg.RadarDetect.ChMovingTime = Value;
418
419         DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__,
420                 pAd->CommonCfg.RadarDetect.ChMovingTime));
421
422         return TRUE;
423 }
424
425 INT Set_LongPulseRadarTh_Proc(
426         IN PRTMP_ADAPTER pAd,
427         IN PUCHAR arg)
428 {
429         UINT8 Value;
430
431         Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10);
432
433         pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value;
434
435         DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__,
436                 pAd->CommonCfg.RadarDetect.LongPulseRadarTh));
437
438         return TRUE;
439 }
440
441