madwifi: clean up scanning code, add support for changing scan lists
[openwrt.git] / package / madwifi / patches / 351-scanlist.patch
1 Index: madwifi-trunk-r3314/net80211/ieee80211_scan_sta.c
2 ===================================================================
3 --- madwifi-trunk-r3314.orig/net80211/ieee80211_scan_sta.c      2008-06-01 03:41:58.000000000 +0200
4 +++ madwifi-trunk-r3314/net80211/ieee80211_scan_sta.c   2008-06-01 03:42:18.000000000 +0200
5 @@ -317,147 +317,6 @@
6  #undef ISPROBE
7  }
8  
9 -static struct ieee80211_channel *
10 -find11gchannel(struct ieee80211com *ic, int i, int freq)
11 -{
12 -       struct ieee80211_channel *c;
13 -       int j;
14 -
15 -       /*
16 -        * The normal ordering in the channel list is b channel
17 -        * immediately followed by g so optimize the search for
18 -        * this.  We'll still do a full search just in case.
19 -        */
20 -       for (j = i+1; j < ic->ic_nchans; j++) {
21 -               c = &ic->ic_channels[j];
22 -               if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
23 -                       return c;
24 -       }
25 -       for (j = 0; j < i; j++) {
26 -               c = &ic->ic_channels[j];
27 -               if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
28 -                       return c;
29 -       }
30 -       return NULL;
31 -}
32 -static const u_int chanflags[] = {
33 -       IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */
34 -       IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
35 -       IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
36 -       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
37 -       IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
38 -       IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
39 -       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
40 -       IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
41 -};
42 -
43 -static void
44 -add_channels(struct ieee80211com *ic,
45 -       struct ieee80211_scan_state *ss,
46 -       enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
47 -{
48 -       struct ieee80211_channel *c, *cg;
49 -       u_int modeflags;
50 -       int i;
51 -
52 -       KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
53 -       modeflags = chanflags[mode];
54 -       for (i = 0; i < nfreq; i++) {
55 -               c = ieee80211_find_channel(ic, freq[i], modeflags);
56 -               if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
57 -                       continue;
58 -               if (mode == IEEE80211_MODE_AUTO) {
59 -                       /*
60 -                        * XXX special-case 11b/g channels so we select
61 -                        *     the g channel if both are present.
62 -                        */
63 -                       if (IEEE80211_IS_CHAN_B(c) &&
64 -                           (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
65 -                               c = cg;
66 -               }
67 -               if (ss->ss_last >= IEEE80211_SCAN_MAX)
68 -                       break;
69 -               ss->ss_chans[ss->ss_last++] = c;
70 -       }
71 -}
72 -
73 -static const u_int16_t rcl1[] =                /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */
74 -{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
75 -static const u_int16_t rcl2[] =                /* 4 MKK channels: 34, 38, 42, 46 */
76 -{ 5170, 5190, 5210, 5230 };
77 -static const u_int16_t rcl3[] =                /* 2.4Ghz ch: 1,6,11,7,13 */
78 -{ 2412, 2437, 2462, 2442, 2472 };
79 -static const u_int16_t rcl4[] =                /* 5 FCC channel: 149, 153, 161, 165 */
80 -{ 5745, 5765, 5785, 5805, 5825 };
81 -static const u_int16_t rcl7[] =                /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */
82 -{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
83 -static const u_int16_t rcl8[] =                /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
84 -{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
85 -static const u_int16_t rcl9[] =                /* 2.4Ghz ch: 14 */
86 -{ 2484 };
87 -static const u_int16_t rcl10[] =       /* Added Korean channels 2312-2372 */
88 -{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
89 -static const u_int16_t rcl11[] =       /* Added Japan channels in 4.9/5.0 spectrum */
90 -{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
91 -#ifdef ATH_TURBO_SCAN
92 -static const u_int16_t rcl5[] =                /* 3 static turbo channels */
93 -{ 5210, 5250, 5290 };
94 -static const u_int16_t rcl6[] =                /* 2 static turbo channels */
95 -{ 5760, 5800 };
96 -static const u_int16_t rcl6x[] =               /* 4 FCC3 turbo channels */
97 -{ 5540, 5580, 5620, 5660 };
98 -static const u_int16_t rcl12[] =               /* 2.4Ghz Turbo channel 6 */
99 -{ 2437 };
100 -static const u_int16_t rcl13[] =               /* dynamic Turbo channels */
101 -{ 5200, 5240, 5280, 5765, 5805 };
102 -#endif /* ATH_TURBO_SCAN */
103 -
104 -struct scanlist {
105 -       u_int16_t       mode;
106 -       u_int16_t       count;
107 -       const u_int16_t *list;
108 -};
109 -
110 -#define        IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
111 -#define        X(a)    .count = sizeof(a)/sizeof(a[0]), .list = a
112 -
113 -static const struct scanlist staScanTable[] = {
114 -       { IEEE80211_MODE_11B,                   X(rcl3) },
115 -       { IEEE80211_MODE_11A,                   X(rcl1) },
116 -       { IEEE80211_MODE_11A,                   X(rcl2) },
117 -       { IEEE80211_MODE_11B,                   X(rcl8) },
118 -       { IEEE80211_MODE_11B,                   X(rcl9) },
119 -       { IEEE80211_MODE_11A,                   X(rcl4) },
120 -#ifdef ATH_TURBO_SCAN
121 -       { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5) },
122 -       { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6) },
123 -       { IEEE80211_MODE_TURBO_A,               X(rcl6x) },
124 -       { IEEE80211_MODE_TURBO_A,               X(rcl13) },
125 -#endif /* ATH_TURBO_SCAN */
126 -       { IEEE80211_MODE_11A,                   X(rcl7) },
127 -       { IEEE80211_MODE_11B,                   X(rcl10) },
128 -       { IEEE80211_MODE_11A,                   X(rcl11) },
129 -#ifdef ATH_TURBO_SCAN
130 -       { IEEE80211_MODE_TURBO_G,               X(rcl12) },
131 -#endif /* ATH_TURBO_SCAN */
132 -       { .list = NULL }
133 -};
134 -
135 -#undef X
136 -
137 -static int
138 -checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
139 -{
140 -       int i;
141 -
142 -       for (; scan->list != NULL; scan++) {
143 -               for (i = 0; i < scan->count; i++)
144 -                       if (scan->list[i] == c->ic_freq)
145 -                               return 1;
146 -       }
147 -       return 0;
148 -}
149 -
150  /*
151   * Start a station-mode scan by populating the channel list.
152   */
153 @@ -466,81 +325,14 @@
154  {
155         struct ieee80211com *ic = vap->iv_ic;
156         struct sta_table *st = ss->ss_priv;
157 -       const struct scanlist *scan;
158         enum ieee80211_phymode mode;
159         struct ieee80211_channel *c;
160         int i;
161  
162         ss->ss_last = 0;
163 -       /*
164 -        * Use the table of ordered channels to construct the list
165 -        * of channels for scanning.  Any channels in the ordered
166 -        * list not in the master list will be discarded.
167 -        */
168 -       for (scan = staScanTable; scan->list != NULL; scan++) {
169 -               mode = scan->mode;
170 -               if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
171 -                       /*
172 -                        * If a desired mode was specified, scan only 
173 -                        * channels that satisfy that constraint.
174 -                        */
175 -                       if (vap->iv_des_mode != mode) {
176 -                               /*
177 -                                * The scan table marks 2.4Ghz channels as b
178 -                                * so if the desired mode is 11g, then use
179 -                                * the 11b channel list but upgrade the mode.
180 -                                */
181 -                               if (vap->iv_des_mode != IEEE80211_MODE_11G ||
182 -                                   mode != IEEE80211_MODE_11B)
183 -                                       continue;
184 -                               mode = IEEE80211_MODE_11G;      /* upgrade */
185 -                       }
186 -               } else {
187 -                       /*
188 -                        * This lets ieee80211_scan_add_channels
189 -                        * upgrade an 11b channel to 11g if available.
190 -                        */
191 -                       if (mode == IEEE80211_MODE_11B)
192 -                               mode = IEEE80211_MODE_AUTO;
193 -               }
194 -               /* XR does not operate on turbo channels */
195 -               if ((vap->iv_flags & IEEE80211_F_XR) &&
196 -                   (mode == IEEE80211_MODE_TURBO_A ||
197 -                    mode == IEEE80211_MODE_TURBO_G))
198 -                       continue;
199 -               /*
200 -                * Add the list of the channels; any that are not
201 -                * in the master channel list will be discarded.
202 -                */
203 -               add_channels(ic, ss, mode, scan->list, scan->count);
204 -       }
205 -
206 -       /*
207 -        * Add the channels from the ic (from HAL) that are not present
208 -        * in the staScanTable.
209 -        */
210 -       for (i = 0; i < ic->ic_nchans; i++) {
211 -               c = &ic->ic_channels[i];
212 -               /*
213 -                * scan dynamic turbo channels in normal mode.
214 -                */
215 -               if (IEEE80211_IS_CHAN_DTURBO(c))
216 -                       continue;
217 -               mode = ieee80211_chan2mode(c);
218 -               if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
219 -                       /*
220 -                        * If a desired mode was specified, scan only 
221 -                        * channels that satisfy that constraint.
222 -                        */
223 -                       if (vap->iv_des_mode != mode)
224 -                               continue;
225 -
226 -               }
227 -               if (!checktable(staScanTable, c))
228 -                       ss->ss_chans[ss->ss_last++] = c;
229 -       }
230 -
231 +       ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
232         ss->ss_next = 0;
233 +
234         /* XXX tunables */
235         /* 
236          * The scanner will stay on station for ss_maxdwell ms (using a 
237 @@ -749,17 +541,7 @@
238         fail = 0;
239         if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan)))
240                 fail |= 0x01;
241 -       /*
242 -        * NB: normally the desired mode is used to construct
243 -        * the channel list, but it's possible for the scan
244 -        * cache to include entries for stations outside this
245 -        * list so we check the desired mode here to weed them
246 -        * out.
247 -        */
248 -       if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
249 -           (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
250 -           chanflags[vap->iv_des_mode])
251 -               fail |= 0x01;
252 +
253         if (vap->iv_opmode == IEEE80211_M_IBSS) {
254                 if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
255                         fail |= 0x02;
256 @@ -1168,78 +950,6 @@
257         .scan_default           = ieee80211_sta_join,
258  };
259  
260 -/*
261 - * Start an adhoc-mode scan by populating the channel list.
262 - */
263 -static int
264 -adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
265 -{
266 -       struct ieee80211com *ic = vap->iv_ic;
267 -       struct sta_table *st = ss->ss_priv;
268 -       const struct scanlist *scan;
269 -       enum ieee80211_phymode mode;
270 -
271 -       ss->ss_last = 0;
272 -       /*
273 -        * Use the table of ordered channels to construct the list
274 -        * of channels for scanning.  Any channels in the ordered
275 -        * list not in the master list will be discarded.
276 -        */
277 -       for (scan = staScanTable; scan->list != NULL; scan++) {
278 -               mode = scan->mode;
279 -               if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
280 -                       /*
281 -                        * If a desired mode was specified, scan only 
282 -                        * channels that satisfy that constraint.
283 -                        */
284 -                       if (vap->iv_des_mode != mode) {
285 -                               /*
286 -                                * The scan table marks 2.4Ghz channels as b
287 -                                * so if the desired mode is 11g, then use
288 -                                * the 11b channel list but upgrade the mode.
289 -                                */
290 -                               if (vap->iv_des_mode != IEEE80211_MODE_11G ||
291 -                                   mode != IEEE80211_MODE_11B)
292 -                                       continue;
293 -                               mode = IEEE80211_MODE_11G;      /* upgrade */
294 -                       }
295 -               } else {
296 -                       /*
297 -                        * This lets ieee80211_scan_add_channels
298 -                        * upgrade an 11b channel to 11g if available.
299 -                        */
300 -                       if (mode == IEEE80211_MODE_11B)
301 -                               mode = IEEE80211_MODE_AUTO;
302 -               }
303 -               /* XR does not operate on turbo channels */
304 -               if ((vap->iv_flags & IEEE80211_F_XR) &&
305 -                   (mode == IEEE80211_MODE_TURBO_A ||
306 -                    mode == IEEE80211_MODE_TURBO_G))
307 -                       continue;
308 -               /*
309 -                * Add the list of the channels; any that are not
310 -                * in the master channel list will be discarded.
311 -                */
312 -               add_channels(ic, ss, mode, scan->list, scan->count);
313 -       }
314 -       ss->ss_next = 0;
315 -       /* XXX tunables */
316 -       ss->ss_mindwell = msecs_to_jiffies(200);        /* 200ms */
317 -       ss->ss_maxdwell = msecs_to_jiffies(200);        /* 200ms */
318 -
319 -#ifdef IEEE80211_DEBUG
320 -       if (ieee80211_msg_scan(vap)) {
321 -               printk("%s: scan set ", vap->iv_dev->name);
322 -               ieee80211_scan_dump_channels(ss);
323 -               printk(" dwell min %ld max %ld\n",
324 -                       ss->ss_mindwell, ss->ss_maxdwell);
325 -       }
326 -#endif /* IEEE80211_DEBUG */
327 -
328 -       st->st_newscan = 1;
329 -
330 -       return 0;
331 -}
332  
333  /*
334   * Select a channel to start an adhoc network on.
335 @@ -1405,7 +1115,7 @@
336         .scan_name              = "default",
337         .scan_attach            = sta_attach,
338         .scan_detach            = sta_detach,
339 -       .scan_start             = adhoc_start,
340 +       .scan_start             = sta_start,
341         .scan_restart           = sta_restart,
342         .scan_cancel            = sta_cancel,
343         .scan_end               = adhoc_pick_bss,
344 Index: madwifi-trunk-r3314/net80211/ieee80211.c
345 ===================================================================
346 --- madwifi-trunk-r3314.orig/net80211/ieee80211.c       2008-06-01 03:41:58.000000000 +0200
347 +++ madwifi-trunk-r3314/net80211/ieee80211.c    2008-06-01 03:42:18.000000000 +0200
348 @@ -278,6 +278,11 @@
349                         ("channel with bogus ieee number %u", c->ic_ieee));
350                 setbit(ic->ic_chan_avail, c->ic_ieee);
351  
352 +               if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
353 +                       c->ic_scanflags |= IEEE80211_NOSCAN_SET;
354 +               else
355 +                       c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
356 +
357                 /* Identify mode capabilities. */
358                 if (IEEE80211_IS_CHAN_A(c))
359                         ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
360 Index: madwifi-trunk-r3314/net80211/_ieee80211.h
361 ===================================================================
362 --- madwifi-trunk-r3314.orig/net80211/_ieee80211.h      2008-06-01 03:41:58.000000000 +0200
363 +++ madwifi-trunk-r3314/net80211/_ieee80211.h   2008-06-01 03:42:18.000000000 +0200
364 @@ -132,6 +132,11 @@
365         IEEE80211_SCAN_FIRST    = 2,    /* take first suitable candidate */
366  };
367  
368 +enum ieee80211_scanflags {
369 +       IEEE80211_NOSCAN_DEFAULT = (1 << 0),
370 +       IEEE80211_NOSCAN_SET     = (1 << 1),
371 +};
372 +
373  /*
374   * Channels are specified by frequency and attributes.
375   */
376 @@ -142,6 +147,7 @@
377         int8_t ic_maxregpower;  /* maximum regulatory tx power in dBm */
378         int8_t ic_maxpower;     /* maximum tx power in dBm */
379         int8_t ic_minpower;     /* minimum tx power in dBm */
380 +       u_int8_t ic_scanflags;
381  };
382  
383  #define        IEEE80211_CHAN_MAX      255
384 Index: madwifi-trunk-r3314/net80211/ieee80211_ioctl.h
385 ===================================================================
386 --- madwifi-trunk-r3314.orig/net80211/ieee80211_ioctl.h 2008-06-01 03:41:58.000000000 +0200
387 +++ madwifi-trunk-r3314/net80211/ieee80211_ioctl.h      2008-06-01 03:42:18.000000000 +0200
388 @@ -555,6 +555,7 @@
389  #define        IEEE80211_IOCTL_WDSADDMAC       (SIOCIWFIRSTPRIV+26)
390  #define        IEEE80211_IOCTL_WDSDELMAC       (SIOCIWFIRSTPRIV+28)
391  #define        IEEE80211_IOCTL_KICKMAC         (SIOCIWFIRSTPRIV+30)
392 +#define        IEEE80211_IOCTL_SETSCANLIST     (SIOCIWFIRSTPRIV+31)
393  
394  enum {
395         IEEE80211_WMMPARAMS_CWMIN       = 1,
396 Index: madwifi-trunk-r3314/net80211/ieee80211_scan_ap.c
397 ===================================================================
398 --- madwifi-trunk-r3314.orig/net80211/ieee80211_scan_ap.c       2008-06-01 03:41:58.000000000 +0200
399 +++ madwifi-trunk-r3314/net80211/ieee80211_scan_ap.c    2008-06-01 03:42:18.000000000 +0200
400 @@ -129,131 +129,7 @@
401  
402  static int ap_flush(struct ieee80211_scan_state *);
403  static void action_tasklet(IEEE80211_TQUEUE_ARG);
404 -static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, 
405 -               int i, int freq);
406  
407 -static const u_int chanflags[] = {
408 -       IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */
409 -       IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
410 -       IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
411 -       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
412 -       IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
413 -       IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode 
414 -                                                             * look for AP in 
415 -                                                             * normal channel 
416 -                                                             */
417 -       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
418 -       IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
419 -};
420 -
421 -static const u_int16_t rcl1[] =                /* 8 FCC channel: 52, 56, 60, 64, 
422 -                                        *                36, 40, 44, 48 */
423 -{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
424 -static const u_int16_t rcl2[] =                /* 4 MKK channels: 34, 38, 42, 46 */
425 -{ 5170, 5190, 5210, 5230 };
426 -static const u_int16_t rcl3[] =                /* 2.4Ghz ch: 1,6,11,7,13 */
427 -{ 2412, 2437, 2462, 2442, 2472 };
428 -static const u_int16_t rcl4[] =                /* 5 FCC channel: 149, 153, 161, 165 */
429 -{ 5745, 5765, 5785, 5805, 5825 };
430 -static const u_int16_t rcl7[] =                /* 11 ETSI channel: 100, 104, 108, 112,
431 -                                        *                  116, 120, 124, 128, 
432 -                                        *                  132, 136, 140 */
433 -{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
434 -static const u_int16_t rcl8[] =                /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
435 -{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
436 -static const u_int16_t rcl9[] =                /* 2.4Ghz ch: 14 */
437 -{ 2484 };
438 -static const u_int16_t rcl10[] =       /* Added Korean channels 2312-2372 */
439 -{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
440 -static const u_int16_t rcl11[] =       /* Added Japan channels in 4.9/5.0 spectrum */
441 -{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
442 -#ifdef ATH_TURBO_SCAN
443 -static const u_int16_t rcl5[] =                /* 3 static turbo channels */
444 -{ 5210, 5250, 5290 };
445 -static const u_int16_t rcl6[] =                /* 2 static turbo channels */
446 -{ 5760, 5800 };
447 -static const u_int16_t rcl6x[] =               /* 4 FCC3 turbo channels */
448 -{ 5540, 5580, 5620, 5660 };
449 -static const u_int16_t rcl12[] =               /* 2.4Ghz Turbo channel 6 */
450 -{ 2437 };
451 -static const u_int16_t rcl13[] =               /* dynamic Turbo channels */
452 -{ 5200, 5240, 5280, 5765, 5805 };
453 -#endif /* ATH_TURBO_SCAN */
454 -
455 -struct scanlist {
456 -       u_int16_t       mode;
457 -       u_int16_t       count;
458 -       const u_int16_t *list;
459 -};
460 -
461 -#define        IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
462 -#define        X(a)    .count = ARRAY_SIZE(a), .list = a
463 -
464 -static const struct scanlist staScanTable[] = {
465 -       { IEEE80211_MODE_11B,                   X(rcl3)  },
466 -       { IEEE80211_MODE_11A,                   X(rcl1)  },
467 -       { IEEE80211_MODE_11A,                   X(rcl2)  },
468 -       { IEEE80211_MODE_11B,                   X(rcl8)  },
469 -       { IEEE80211_MODE_11B,                   X(rcl9)  },
470 -       { IEEE80211_MODE_11A,                   X(rcl4)  },
471 -#ifdef ATH_TURBO_SCAN
472 -       { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5)  },
473 -       { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6)  },
474 -       { IEEE80211_MODE_TURBO_A,               X(rcl6x) },
475 -       { IEEE80211_MODE_TURBO_A,               X(rcl13) },
476 -#endif /* ATH_TURBO_SCAN */
477 -       { IEEE80211_MODE_11A,                   X(rcl7)  },
478 -       { IEEE80211_MODE_11B,                   X(rcl10) },
479 -       { IEEE80211_MODE_11A,                   X(rcl11) },
480 -#ifdef ATH_TURBO_SCAN
481 -       { IEEE80211_MODE_TURBO_G,               X(rcl12) },
482 -#endif /* ATH_TURBO_SCAN */
483 -       { .list = NULL }
484 -};
485 -
486 -#undef X
487 -/* This function must be invoked with locks acquired */
488 -static void
489 -add_channels(struct ieee80211com *ic,
490 -       struct ieee80211_scan_state *ss,
491 -       enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
492 -{
493 -       struct ieee80211_channel *c, *cg;
494 -       u_int modeflags;
495 -       int i;
496 -
497 -       KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
498 -       modeflags = chanflags[mode];
499 -       for (i = 0; i < nfreq; i++) {
500 -               c = ieee80211_find_channel(ic, freq[i], modeflags);
501 -               if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
502 -                       continue;
503 -               if (mode == IEEE80211_MODE_AUTO) {
504 -                       /* XXX special-case 11b/g channels so we select
505 -                        *     the g channel if both are present. */
506 -                       if (IEEE80211_IS_CHAN_B(c) &&
507 -                           (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
508 -                               c = cg;
509 -               }
510 -               if (ss->ss_last >= IEEE80211_SCAN_MAX)
511 -                       break;
512 -               ss->ss_chans[ss->ss_last++] = c;
513 -       }
514 -}
515 -
516 -/* This function must be invoked with locks acquired */
517 -static int
518 -checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
519 -{
520 -       int i;
521 -
522 -       for (; scan->list != NULL; scan++) {
523 -               for (i = 0; i < scan->count; i++)
524 -                       if (scan->list[i] == c->ic_freq)
525 -                               return 1;
526 -       }
527 -       return 0;
528 -}
529  
530  /*
531   * Attach prior to any scanning work.
532 @@ -327,29 +203,6 @@
533                 ieee80211_saveie(iep, ie);
534  }
535  
536 -/* This function must be invoked with locks acquired */
537 -static struct ieee80211_channel *
538 -find11gchannel(struct ieee80211com *ic, int i, int freq)
539 -{
540 -       struct ieee80211_channel *c;
541 -       int j;
542 -
543 -       /* The normal ordering in the channel list is b channel
544 -        * immediately followed by g so optimize the search for
545 -        * this.  We'll still do a full search just in case. */
546 -       for (j = i + 1; j < ic->ic_nchans; j++) {
547 -               c = &ic->ic_channels[j];
548 -               if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
549 -                       return c;
550 -       }
551 -       for (j = 0; j < i; j++) {
552 -               c = &ic->ic_channels[j];
553 -               if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
554 -                       return c;
555 -       }
556 -       return NULL;
557 -}
558 -
559  /*
560   * Start an ap scan by populating the channel list.
561   */
562 @@ -358,8 +211,6 @@
563  {
564         struct ap_state *as         = ss->ss_priv;
565         struct ieee80211com *ic     = NULL;
566 -       const struct scanlist *sl   = NULL;
567 -       struct ieee80211_channel *c = NULL;
568         int i;
569         unsigned int mode = 0;
570  
571 @@ -368,80 +219,8 @@
572         /* Determine mode flags to match, or leave zero for auto mode */
573         as->as_vap_desired_mode = vap->iv_des_mode;
574         as->as_required_mode    = 0;
575 -       if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) {
576 -               as->as_required_mode = chanflags[as->as_vap_desired_mode];
577 -               if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && 
578 -                   (as->as_required_mode != IEEE80211_CHAN_ST)) {
579 -                       /* Fixup for dynamic turbo flags */
580 -                       if (as->as_vap_desired_mode == IEEE80211_MODE_11G)
581 -                               as->as_required_mode = IEEE80211_CHAN_108G;
582 -                       else
583 -                               as->as_required_mode = IEEE80211_CHAN_108A;
584 -               }
585 -       }
586 -
587 -       ss->ss_last = 0;
588 -       /* Use the table of ordered channels to construct the list
589 -        * of channels for scanning.  Any channels in the ordered
590 -        * list not in the master list will be discarded. */
591 -       for (sl = staScanTable; sl->list != NULL; sl++) {
592 -               mode = sl->mode;
593 -
594 -               /* The scan table marks 2.4Ghz channels as b
595 -                * so if the desired mode is 11g, then use
596 -                * the 11b channel list but upgrade the mode. */
597 -               if (as->as_vap_desired_mode &&
598 -                   (as->as_vap_desired_mode != mode) && 
599 -                   (as->as_vap_desired_mode == IEEE80211_MODE_11G) && 
600 -                   (mode == IEEE80211_MODE_11B))
601 -                       mode = IEEE80211_MODE_11G;
602 -
603 -               /* If we are in "AUTO" mode, upgrade the mode to auto. 
604 -                * This lets add_channels upgrade an 11b channel to 
605 -                * 11g if available. */
606 -               if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B))
607 -                       mode = IEEE80211_MODE_AUTO;
608 -
609 -               /* Add the list of the channels; any that are not
610 -                * in the master channel list will be discarded. */
611 -               add_channels(ic, ss, mode, sl->list, sl->count);
612 -       }
613 -
614 -       /* Add the channels from the ic (from HAL) that are not present
615 -        * in the staScanTable, assuming they pass the sanity checks... */
616 -       for (i = 0; i < ic->ic_nchans; i++) {
617 -               c = &ic->ic_channels[i];
618 -
619 -               /* XR is not supported on turbo channels */
620 -               if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR)
621 -                       continue;
622 +       ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
623  
624 -               /* Dynamic channels are scanned in base mode */
625 -               if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c))
626 -                       continue;
627 -
628 -               /* Use any 11g channel instead of 11b one. */
629 -               if (vap->iv_des_mode == IEEE80211_MODE_AUTO && 
630 -                   IEEE80211_IS_CHAN_B(c) &&
631 -                   find11gchannel(ic, i, c->ic_freq))
632 -                       continue;
633 -
634 -               /* Do not add channels already put into the scan list by the
635 -                * scan table - these have already been filtered by mode
636 -                * and for whether they are in the active channel list. */
637 -               if (checktable(staScanTable, c))
638 -                       continue;
639 -
640 -               /* Make sure the channel is active */
641 -               if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
642 -                       continue;
643 -
644 -               /* Don't overrun */
645 -               if (ss->ss_last >= IEEE80211_SCAN_MAX)
646 -                       break;
647 -
648 -               ss->ss_chans[ss->ss_last++] = c;
649 -       }
650         ss->ss_next = 0;
651         /* XXX tunables */
652         ss->ss_mindwell = msecs_to_jiffies(200);        /* 200ms */
653 @@ -759,13 +538,6 @@
654                 if (IEEE80211_IS_CHAN_RADAR(c->chan))
655                         continue;
656  
657 -               /* Do not select 802.11a ST if mode is specified and is not 
658 -                * 802.11a ST */
659 -               if (as->as_required_mode &&
660 -                   IEEE80211_IS_CHAN_STURBO(c->chan) &&
661 -                   (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))
662 -                       continue;
663 -
664                 /* Verify mode matches any fixed mode specified */
665                 if((c->chan->ic_flags & as->as_required_mode) != 
666                                 as->as_required_mode)
667 Index: madwifi-trunk-r3314/net80211/ieee80211_scan.c
668 ===================================================================
669 --- madwifi-trunk-r3314.orig/net80211/ieee80211_scan.c  2008-06-01 03:41:58.000000000 +0200
670 +++ madwifi-trunk-r3314/net80211/ieee80211_scan.c       2008-06-01 03:42:18.000000000 +0200
671 @@ -958,6 +958,79 @@
672         }
673  }
674  
675 +static const u_int chanflags[] = {
676 +       0,      /* IEEE80211_MODE_AUTO */
677 +       IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
678 +       IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
679 +       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
680 +       IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
681 +       IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
682 +       IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
683 +       IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
684 +};
685 +
686 +static struct ieee80211_channel *
687 +find11gchannel(struct ieee80211com *ic, int i, int freq)
688 +{
689 +       struct ieee80211_channel *c;
690 +       int j;
691 +
692 +       /*
693 +        * The normal ordering in the channel list is b channel
694 +        * immediately followed by g so optimize the search for
695 +        * this.  We'll still do a full search just in case.
696 +        */
697 +       for (j = i+1; j < ic->ic_nchans; j++) {
698 +               c = &ic->ic_channels[j];
699 +               if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
700 +                       return c;
701 +       }
702 +       for (j = 0; j < i; j++) {
703 +               c = &ic->ic_channels[j];
704 +               if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
705 +                       return c;
706 +       }
707 +       return NULL;
708 +}
709 +
710 +
711 +void
712 +ieee80211_scan_add_channels(struct ieee80211com *ic,
713 +       struct ieee80211_scan_state *ss,
714 +       enum ieee80211_phymode mode)
715 +{
716 +       struct ieee80211_channel *c, *cg;
717 +       u_int modeflags;
718 +       int i;
719 +
720 +       KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
721 +       modeflags = chanflags[mode];
722 +       for (i = 0; i < ic->ic_nchans; i++) {
723 +               c = &ic->ic_channels[i];
724 +               if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
725 +                       continue;
726 +               if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
727 +                       continue;
728 +               if (modeflags &&
729 +                       ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
730 +                        (modeflags & IEEE80211_CHAN_ALLTURBO)))
731 +                       continue;
732 +               if (mode == IEEE80211_MODE_AUTO) {
733 +                       /*
734 +                        * XXX special-case 11b/g channels so we select
735 +                        *     the g channel if both are present.
736 +                        */
737 +                       if (IEEE80211_IS_CHAN_B(c) &&
738 +                           (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
739 +                               continue;
740 +               }
741 +               if (ss->ss_last >= IEEE80211_SCAN_MAX)
742 +                       break;
743 +               ss->ss_chans[ss->ss_last++] = c;
744 +       }
745 +}
746 +
747 +
748  /*
749   * Execute radar channel change. This is called when a radar/dfs
750   * signal is detected.  AP mode only.  Return 1 on success, 0 on
751 Index: madwifi-trunk-r3314/net80211/ieee80211_scan.h
752 ===================================================================
753 --- madwifi-trunk-r3314.orig/net80211/ieee80211_scan.h  2008-06-01 03:41:58.000000000 +0200
754 +++ madwifi-trunk-r3314/net80211/ieee80211_scan.h       2008-06-01 03:42:18.000000000 +0200
755 @@ -219,4 +219,7 @@
756  void ieee80211_scanner_unregister(enum ieee80211_opmode,
757         const struct ieee80211_scanner *);
758  void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
759 +void ieee80211_scan_add_channels(struct ieee80211com *ic,
760 +       struct ieee80211_scan_state *ss,
761 +       enum ieee80211_phymode mode);
762  #endif /* _NET80211_IEEE80211_SCAN_H_ */
763 Index: madwifi-trunk-r3314/net80211/ieee80211_wireless.c
764 ===================================================================
765 --- madwifi-trunk-r3314.orig/net80211/ieee80211_wireless.c      2008-06-01 03:41:58.000000000 +0200
766 +++ madwifi-trunk-r3314/net80211/ieee80211_wireless.c   2008-06-01 03:42:53.000000000 +0200
767 @@ -3873,6 +3873,106 @@
768         return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
769  }
770  
771 +static inline void setflag(struct ieee80211_channel *c, int flag)
772 +{
773 +       if (flag)
774 +               c->ic_scanflags |= IEEE80211_NOSCAN_SET;
775 +       else
776 +               c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
777 +}
778 +
779 +static void setscanflag(struct ieee80211com *ic, int min, int max, int set)
780 +{
781 +       int i;
782 +
783 +       for (i = 0; i < ic->ic_nchans; i++) {
784 +               struct ieee80211_channel *c = &ic->ic_channels[i];
785 +
786 +               if (min == -1) {
787 +                       if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT))
788 +                               setflag(c, set);
789 +               } else if ((c->ic_freq >= min) && (c->ic_freq <= max)) {
790 +                       setflag(c, set);
791 +               }
792 +       }
793 +}
794 +
795 +static int
796 +ieee80211_ioctl_setscanlist(struct net_device *dev,
797 +       struct iw_request_info *info,
798 +       struct iw_point *data, char *extra)
799 +{
800 +       struct ieee80211vap *vap = dev->priv;
801 +       struct ieee80211com *ic = vap->iv_ic;
802 +       char *s, *next;
803 +       int val = 1;
804 +
805 +       if (data->length <= 0)
806 +               return -EINVAL;
807 +
808 +       s = kmalloc(data->length + 1, GFP_KERNEL);
809 +       if (!s)
810 +               return -ENOMEM;
811 +
812 +       memset(s, 0, data->length + 1);
813 +       if (copy_from_user(s, data->pointer, data->length))
814 +               return -EFAULT;
815 +
816 +       s[data->length - 1] = '\0';             /* ensure null termination */
817 +
818 +       switch(*s) {
819 +               case '-':
820 +                       val = 1;
821 +                       break;
822 +               case '+':
823 +                       val = 0;
824 +                       break;
825 +               default:
826 +                       goto error;
827 +       }
828 +       s++;
829 +       next = s;
830 +       do {
831 +               next = strchr(s, ',');
832 +               if (next) {
833 +                       *next = 0;
834 +                       next++;
835 +               }
836 +               if (!strcmp(s, "ALL")) {
837 +                       setscanflag(ic, 0, 10000, val);
838 +               } else if (!strcmp(s, "REG")) {
839 +                       setscanflag(ic, -1, -1, val);
840 +               } else {
841 +                       int min, max;
842 +                       char *n, *end = NULL;
843 +
844 +                       n = strchr(s, '-');
845 +                       if (n) {
846 +                               *n = 0;
847 +                               n++;
848 +                       }
849 +                       min = simple_strtoul(s, &end, 10);
850 +                       if (end && *end)
851 +                               goto error;
852 +                       if (n) {
853 +                               max = simple_strtoul(n, &end, 10);
854 +                               if (end && *end)
855 +                                       goto error;
856 +                       } else {
857 +                               max = min;
858 +                       }
859 +                       setscanflag(ic, min, max, val);
860 +               }
861 +               s = next;
862 +       } while (next);
863 +       return 0;
864 +
865 +error:
866 +       if (s)
867 +               kfree(s);
868 +       return -EINVAL;
869 +}
870 +
871  static int
872  ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
873         void *w, char *extra)
874 @@ -5656,6 +5756,8 @@
875          IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
876         {IEEE80211_PARAM_MINRATE,
877          0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
878 +       { IEEE80211_IOCTL_SETSCANLIST,
879 +        IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
880  
881  #ifdef ATH_REVERSE_ENGINEERING
882         /*
883 @@ -5753,6 +5855,7 @@
884         set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
885         set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
886         set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
887 +       set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
888  #ifdef ATH_REVERSE_ENGINEERING
889         set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg),
890         set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),