2 * Copyright (C) 2003,2004 Aurelien Alleaume <slts@free.fr>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/kernel.h>
20 #include <linux/slab.h>
22 #include "prismcompat.h"
23 #include "islpci_dev.h"
24 #include "islpci_mgt.h"
27 #include "isl_ioctl.h"
29 /* to convert between channel and freq */
30 static const int frequency_list_bg
[] = { 2412, 2417, 2422, 2427, 2432,
31 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484
35 channel_of_freq(int f
)
39 if ((f
>= 2412) && (f
<= 2484)) {
40 while ((c
< 14) && (f
!= frequency_list_bg
[c
]))
42 return (c
>= 14) ? 0 : ++c
;
43 } else if ((f
>= (int) 5000) && (f
<= (int) 6000)) {
44 return ( (f
- 5000) / 5 );
49 #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
50 #define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED)
51 #define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32)
52 #define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32)
53 #define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME)
54 #define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX)
56 #define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0)
58 struct oid_t isl_oid
[] = {
59 OID_STRUCT(GEN_OID_MACADDRESS
, 0x00000000, u8
[6], OID_TYPE_ADDR
),
60 OID_U32(GEN_OID_LINKSTATE
, 0x00000001),
61 OID_UNKNOWN(GEN_OID_WATCHDOG
, 0x00000002),
62 OID_UNKNOWN(GEN_OID_MIBOP
, 0x00000003),
63 OID_UNKNOWN(GEN_OID_OPTIONS
, 0x00000004),
64 OID_UNKNOWN(GEN_OID_LEDCONFIG
, 0x00000005),
67 OID_U32_C(DOT11_OID_BSSTYPE
, 0x10000000),
68 OID_STRUCT_C(DOT11_OID_BSSID
, 0x10000001, u8
[6], OID_TYPE_RAW
),
69 OID_STRUCT_C(DOT11_OID_SSID
, 0x10000002, struct obj_ssid
,
71 OID_U32(DOT11_OID_STATE
, 0x10000003),
72 OID_U32(DOT11_OID_AID
, 0x10000004),
73 OID_STRUCT(DOT11_OID_COUNTRYSTRING
, 0x10000005, u8
[4], OID_TYPE_RAW
),
74 OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE
, 0x10000006, struct obj_ssid
,
77 OID_U32(DOT11_OID_MEDIUMLIMIT
, 0x11000000),
78 OID_U32_C(DOT11_OID_BEACONPERIOD
, 0x11000001),
79 OID_U32(DOT11_OID_DTIMPERIOD
, 0x11000002),
80 OID_U32(DOT11_OID_ATIMWINDOW
, 0x11000003),
81 OID_U32(DOT11_OID_LISTENINTERVAL
, 0x11000004),
82 OID_U32(DOT11_OID_CFPPERIOD
, 0x11000005),
83 OID_U32(DOT11_OID_CFPDURATION
, 0x11000006),
85 OID_U32_C(DOT11_OID_AUTHENABLE
, 0x12000000),
86 OID_U32_C(DOT11_OID_PRIVACYINVOKED
, 0x12000001),
87 OID_U32_C(DOT11_OID_EXUNENCRYPTED
, 0x12000002),
88 OID_U32_C(DOT11_OID_DEFKEYID
, 0x12000003),
89 [DOT11_OID_DEFKEYX
] = {0x12000004, 3, sizeof (struct obj_key
),
90 OID_FLAG_CACHED
| OID_TYPE_KEY
}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */
91 OID_UNKNOWN(DOT11_OID_STAKEY
, 0x12000008),
92 OID_U32(DOT11_OID_REKEYTHRESHOLD
, 0x12000009),
93 OID_UNKNOWN(DOT11_OID_STASC
, 0x1200000a),
95 OID_U32(DOT11_OID_PRIVTXREJECTED
, 0x1a000000),
96 OID_U32(DOT11_OID_PRIVRXPLAIN
, 0x1a000001),
97 OID_U32(DOT11_OID_PRIVRXFAILED
, 0x1a000002),
98 OID_U32(DOT11_OID_PRIVRXNOKEY
, 0x1a000003),
100 OID_U32_C(DOT11_OID_RTSTHRESH
, 0x13000000),
101 OID_U32_C(DOT11_OID_FRAGTHRESH
, 0x13000001),
102 OID_U32_C(DOT11_OID_SHORTRETRIES
, 0x13000002),
103 OID_U32_C(DOT11_OID_LONGRETRIES
, 0x13000003),
104 OID_U32_C(DOT11_OID_MAXTXLIFETIME
, 0x13000004),
105 OID_U32(DOT11_OID_MAXRXLIFETIME
, 0x13000005),
106 OID_U32(DOT11_OID_AUTHRESPTIMEOUT
, 0x13000006),
107 OID_U32(DOT11_OID_ASSOCRESPTIMEOUT
, 0x13000007),
109 OID_UNKNOWN(DOT11_OID_ALOFT_TABLE
, 0x1d000000),
110 OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE
, 0x1d000001),
111 OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT
, 0x1d000002),
112 OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS
, 0x1d000003),
113 OID_U32(DOT11_OID_ALOFT_FIXEDRATE
, 0x1d000004),
114 OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH
, 0x1d000005),
115 OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG
, 0x1d000006),
117 [DOT11_OID_VDCFX
] = {0x1b000000, 7, 0, 0},
118 OID_U32(DOT11_OID_MAXFRAMEBURST
, 0x1b000008),
120 OID_U32(DOT11_OID_PSM
, 0x14000000),
121 OID_U32(DOT11_OID_CAMTIMEOUT
, 0x14000001),
122 OID_U32(DOT11_OID_RECEIVEDTIMS
, 0x14000002),
123 OID_U32(DOT11_OID_ROAMPREFERENCE
, 0x14000003),
125 OID_U32(DOT11_OID_BRIDGELOCAL
, 0x15000000),
126 OID_U32(DOT11_OID_CLIENTS
, 0x15000001),
127 OID_U32(DOT11_OID_CLIENTSASSOCIATED
, 0x15000002),
128 [DOT11_OID_CLIENTX
] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */
130 OID_STRUCT(DOT11_OID_CLIENTFIND
, 0x150007DB, u8
[6], OID_TYPE_ADDR
),
131 OID_STRUCT(DOT11_OID_WDSLINKADD
, 0x150007DC, u8
[6], OID_TYPE_ADDR
),
132 OID_STRUCT(DOT11_OID_WDSLINKREMOVE
, 0x150007DD, u8
[6], OID_TYPE_ADDR
),
133 OID_STRUCT(DOT11_OID_EAPAUTHSTA
, 0x150007DE, u8
[6], OID_TYPE_ADDR
),
134 OID_STRUCT(DOT11_OID_EAPUNAUTHSTA
, 0x150007DF, u8
[6], OID_TYPE_ADDR
),
135 OID_U32_C(DOT11_OID_DOT1XENABLE
, 0x150007E0),
136 OID_UNKNOWN(DOT11_OID_MICFAILURE
, 0x150007E1),
137 OID_UNKNOWN(DOT11_OID_REKEYINDICATE
, 0x150007E2),
139 OID_U32(DOT11_OID_MPDUTXSUCCESSFUL
, 0x16000000),
140 OID_U32(DOT11_OID_MPDUTXONERETRY
, 0x16000001),
141 OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES
, 0x16000002),
142 OID_U32(DOT11_OID_MPDUTXFAILED
, 0x16000003),
143 OID_U32(DOT11_OID_MPDURXSUCCESSFUL
, 0x16000004),
144 OID_U32(DOT11_OID_MPDURXDUPS
, 0x16000005),
145 OID_U32(DOT11_OID_RTSSUCCESSFUL
, 0x16000006),
146 OID_U32(DOT11_OID_RTSFAILED
, 0x16000007),
147 OID_U32(DOT11_OID_ACKFAILED
, 0x16000008),
148 OID_U32(DOT11_OID_FRAMERECEIVES
, 0x16000009),
149 OID_U32(DOT11_OID_FRAMEERRORS
, 0x1600000A),
150 OID_U32(DOT11_OID_FRAMEABORTS
, 0x1600000B),
151 OID_U32(DOT11_OID_FRAMEABORTSPHY
, 0x1600000C),
153 OID_U32(DOT11_OID_SLOTTIME
, 0x17000000),
154 OID_U32(DOT11_OID_CWMIN
, 0x17000001),
155 OID_U32(DOT11_OID_CWMAX
, 0x17000002),
156 OID_U32(DOT11_OID_ACKWINDOW
, 0x17000003),
157 OID_U32(DOT11_OID_ANTENNARX
, 0x17000004),
158 OID_U32(DOT11_OID_ANTENNATX
, 0x17000005),
159 OID_U32(DOT11_OID_ANTENNADIVERSITY
, 0x17000006),
160 OID_U32_C(DOT11_OID_CHANNEL
, 0x17000007),
161 OID_U32_C(DOT11_OID_EDTHRESHOLD
, 0x17000008),
162 OID_U32(DOT11_OID_PREAMBLESETTINGS
, 0x17000009),
163 OID_STRUCT(DOT11_OID_RATES
, 0x1700000A, u8
[IWMAX_BITRATES
+ 1],
165 OID_U32(DOT11_OID_CCAMODESUPPORTED
, 0x1700000B),
166 OID_U32(DOT11_OID_CCAMODE
, 0x1700000C),
167 OID_UNKNOWN(DOT11_OID_RSSIVECTOR
, 0x1700000D),
168 OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE
, 0x1700000E),
169 OID_U32(DOT11_OID_OUTPUTPOWER
, 0x1700000F),
170 OID_STRUCT(DOT11_OID_SUPPORTEDRATES
, 0x17000010,
171 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
172 OID_U32_C(DOT11_OID_FREQUENCY
, 0x17000011),
173 [DOT11_OID_SUPPORTEDFREQUENCIES
] =
174 {0x17000012, 0, sizeof (struct obj_frequencies
)
175 + sizeof (u16
) * IWMAX_FREQ
, OID_TYPE_FREQUENCIES
},
177 OID_U32(DOT11_OID_NOISEFLOOR
, 0x17000013),
178 OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY
, 0x17000014, u8
[IWMAX_FREQ
+ 1],
180 OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE
, 0x17000015),
181 OID_U32(DOT11_OID_NONERPPROTECTION
, 0x17000016),
182 OID_U32(DOT11_OID_SLOTSETTINGS
, 0x17000017),
183 OID_U32(DOT11_OID_NONERPTIMEOUT
, 0x17000018),
184 OID_U32(DOT11_OID_PROFILES
, 0x17000019),
185 OID_STRUCT(DOT11_OID_EXTENDEDRATES
, 0x17000020,
186 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
188 OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE
, 0x18000000),
189 OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE
, 0x18000001),
190 OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE
, 0x18000002),
191 OID_STRUCT_MLME(DOT11_OID_ASSOCIATE
, 0x18000003),
192 OID_UNKNOWN(DOT11_OID_SCAN
, 0x18000004),
193 OID_STRUCT_MLMEEX(DOT11_OID_BEACON
, 0x18000005),
194 OID_STRUCT_MLMEEX(DOT11_OID_PROBE
, 0x18000006),
195 OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX
, 0x18000007),
196 OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX
, 0x18000008),
197 OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX
, 0x18000009),
198 OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX
, 0x1800000A),
199 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE
, 0x1800000B),
200 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX
, 0x1800000C),
202 OID_U32(DOT11_OID_NONERPSTATUS
, 0x1E000000),
204 OID_U32(DOT11_OID_STATIMEOUT
, 0x19000000),
205 OID_U32_C(DOT11_OID_MLMEAUTOLEVEL
, 0x19000001),
206 OID_U32(DOT11_OID_BSSTIMEOUT
, 0x19000002),
207 [DOT11_OID_ATTACHMENT
] = {0x19000003, 0,
208 sizeof(struct obj_attachment
), OID_TYPE_ATTACH
},
209 OID_STRUCT_C(DOT11_OID_PSMBUFFER
, 0x19000004, struct obj_buffer
,
212 OID_U32(DOT11_OID_BSSS
, 0x1C000000),
213 [DOT11_OID_BSSX
] = {0x1C000001, 63, sizeof (struct obj_bss
),
214 OID_TYPE_BSS
}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */
215 OID_STRUCT(DOT11_OID_BSSFIND
, 0x1C000042, struct obj_bss
, OID_TYPE_BSS
),
216 [DOT11_OID_BSSLIST
] = {0x1C000043, 0, sizeof (struct
218 sizeof (struct obj_bss
[IWMAX_BSS
]),
221 OID_UNKNOWN(OID_INL_TUNNEL
, 0xFF020000),
222 OID_UNKNOWN(OID_INL_MEMADDR
, 0xFF020001),
223 OID_UNKNOWN(OID_INL_MEMORY
, 0xFF020002),
224 OID_U32_C(OID_INL_MODE
, 0xFF020003),
225 OID_UNKNOWN(OID_INL_COMPONENT_NR
, 0xFF020004),
226 OID_STRUCT(OID_INL_VERSION
, 0xFF020005, u8
[8], OID_TYPE_RAW
),
227 OID_UNKNOWN(OID_INL_INTERFACE_ID
, 0xFF020006),
228 OID_UNKNOWN(OID_INL_COMPONENT_ID
, 0xFF020007),
229 OID_U32_C(OID_INL_CONFIG
, 0xFF020008),
230 OID_U32_C(OID_INL_DOT11D_CONFORMANCE
, 0xFF02000C),
231 OID_U32(OID_INL_PHYCAPABILITIES
, 0xFF02000D),
232 OID_U32_C(OID_INL_OUTPUTPOWER
, 0xFF02000F),
237 mgt_init(islpci_private
*priv
)
241 priv
->mib
= kcalloc(OID_NUM_LAST
, sizeof (void *), GFP_KERNEL
);
245 /* Alloc the cache */
246 for (i
= 0; i
< OID_NUM_LAST
; i
++) {
247 if (isl_oid
[i
].flags
& OID_FLAG_CACHED
) {
248 priv
->mib
[i
] = kzalloc(isl_oid
[i
].size
*
249 (isl_oid
[i
].range
+ 1),
257 init_rwsem(&priv
->mib_sem
);
258 prism54_mib_init(priv
);
264 mgt_clean(islpci_private
*priv
)
270 for (i
= 0; i
< OID_NUM_LAST
; i
++) {
279 mgt_le_to_cpu(int type
, void *data
)
283 *(u32
*) data
= le32_to_cpu(*(u32
*) data
);
285 case OID_TYPE_BUFFER
:{
286 struct obj_buffer
*buff
= data
;
287 buff
->size
= le32_to_cpu(buff
->size
);
288 buff
->addr
= le32_to_cpu(buff
->addr
);
292 struct obj_bss
*bss
= data
;
293 bss
->age
= le16_to_cpu(bss
->age
);
294 bss
->channel
= le16_to_cpu(bss
->channel
);
295 bss
->capinfo
= le16_to_cpu(bss
->capinfo
);
296 bss
->rates
= le16_to_cpu(bss
->rates
);
297 bss
->basic_rates
= le16_to_cpu(bss
->basic_rates
);
300 case OID_TYPE_BSSLIST
:{
301 struct obj_bsslist
*list
= data
;
303 list
->nr
= le32_to_cpu(list
->nr
);
304 for (i
= 0; i
< list
->nr
; i
++)
305 mgt_le_to_cpu(OID_TYPE_BSS
, &list
->bsslist
[i
]);
308 case OID_TYPE_FREQUENCIES
:{
309 struct obj_frequencies
*freq
= data
;
311 freq
->nr
= le16_to_cpu(freq
->nr
);
312 for (i
= 0; i
< freq
->nr
; i
++)
313 freq
->mhz
[i
] = le16_to_cpu(freq
->mhz
[i
]);
317 struct obj_mlme
*mlme
= data
;
318 mlme
->id
= le16_to_cpu(mlme
->id
);
319 mlme
->state
= le16_to_cpu(mlme
->state
);
320 mlme
->code
= le16_to_cpu(mlme
->code
);
323 case OID_TYPE_MLMEEX
:{
324 struct obj_mlmeex
*mlme
= data
;
325 mlme
->id
= le16_to_cpu(mlme
->id
);
326 mlme
->state
= le16_to_cpu(mlme
->state
);
327 mlme
->code
= le16_to_cpu(mlme
->code
);
328 mlme
->size
= le16_to_cpu(mlme
->size
);
331 case OID_TYPE_ATTACH
:{
332 struct obj_attachment
*attach
= data
;
333 attach
->id
= le16_to_cpu(attach
->id
);
334 attach
->size
= le16_to_cpu(attach
->size
);
348 mgt_cpu_to_le(int type
, void *data
)
352 *(u32
*) data
= cpu_to_le32(*(u32
*) data
);
354 case OID_TYPE_BUFFER
:{
355 struct obj_buffer
*buff
= data
;
356 buff
->size
= cpu_to_le32(buff
->size
);
357 buff
->addr
= cpu_to_le32(buff
->addr
);
361 struct obj_bss
*bss
= data
;
362 bss
->age
= cpu_to_le16(bss
->age
);
363 bss
->channel
= cpu_to_le16(bss
->channel
);
364 bss
->capinfo
= cpu_to_le16(bss
->capinfo
);
365 bss
->rates
= cpu_to_le16(bss
->rates
);
366 bss
->basic_rates
= cpu_to_le16(bss
->basic_rates
);
369 case OID_TYPE_BSSLIST
:{
370 struct obj_bsslist
*list
= data
;
372 list
->nr
= cpu_to_le32(list
->nr
);
373 for (i
= 0; i
< list
->nr
; i
++)
374 mgt_cpu_to_le(OID_TYPE_BSS
, &list
->bsslist
[i
]);
377 case OID_TYPE_FREQUENCIES
:{
378 struct obj_frequencies
*freq
= data
;
380 freq
->nr
= cpu_to_le16(freq
->nr
);
381 for (i
= 0; i
< freq
->nr
; i
++)
382 freq
->mhz
[i
] = cpu_to_le16(freq
->mhz
[i
]);
386 struct obj_mlme
*mlme
= data
;
387 mlme
->id
= cpu_to_le16(mlme
->id
);
388 mlme
->state
= cpu_to_le16(mlme
->state
);
389 mlme
->code
= cpu_to_le16(mlme
->code
);
392 case OID_TYPE_MLMEEX
:{
393 struct obj_mlmeex
*mlme
= data
;
394 mlme
->id
= cpu_to_le16(mlme
->id
);
395 mlme
->state
= cpu_to_le16(mlme
->state
);
396 mlme
->code
= cpu_to_le16(mlme
->code
);
397 mlme
->size
= cpu_to_le16(mlme
->size
);
400 case OID_TYPE_ATTACH
:{
401 struct obj_attachment
*attach
= data
;
402 attach
->id
= cpu_to_le16(attach
->id
);
403 attach
->size
= cpu_to_le16(attach
->size
);
416 /* Note : data is modified during this function */
419 mgt_set_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
)
422 struct islpci_mgmtframe
*response
= NULL
;
423 int response_op
= PIMFOR_OP_ERROR
;
425 void *cache
, *_data
= data
;
428 BUG_ON(OID_NUM_LAST
<= n
);
429 BUG_ON(extra
> isl_oid
[n
].range
);
432 /* memory has been freed */
435 dlen
= isl_oid
[n
].size
;
436 cache
= priv
->mib
[n
];
437 cache
+= (cache
? extra
* dlen
: 0);
438 oid
= isl_oid
[n
].oid
+ extra
;
441 /* we are requested to re-set a cached value */
444 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, _data
);
445 /* If we are going to write to the cache, we don't want anyone to read
446 * it -> acquire write lock.
447 * Else we could acquire a read lock to be sure we don't bother the
448 * commit process (which takes a write lock). But I'm not sure if it's
452 down_write(&priv
->mib_sem
);
454 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
455 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
456 _data
, dlen
, &response
);
458 response_op
= response
->header
->operation
;
459 islpci_mgt_release(response
);
461 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
468 memcpy(cache
, _data
, dlen
);
469 up_write(&priv
->mib_sem
);
472 /* re-set given data to what it was */
474 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
479 /* None of these are cached */
481 mgt_set_varlen(islpci_private
*priv
, enum oid_num_t n
, void *data
, int extra_len
)
484 struct islpci_mgmtframe
*response
;
485 int response_op
= PIMFOR_OP_ERROR
;
489 BUG_ON(OID_NUM_LAST
<= n
);
491 dlen
= isl_oid
[n
].size
;
492 oid
= isl_oid
[n
].oid
;
494 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
496 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
497 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
498 data
, dlen
+ extra_len
, &response
);
500 response_op
= response
->header
->operation
;
501 islpci_mgt_release(response
);
503 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
508 /* re-set given data to what it was */
510 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
516 mgt_get_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
,
517 union oid_res_t
*res
)
522 struct islpci_mgmtframe
*response
= NULL
;
525 void *cache
, *_res
= NULL
;
528 BUG_ON(OID_NUM_LAST
<= n
);
529 BUG_ON(extra
> isl_oid
[n
].range
);
534 /* memory has been freed */
537 dlen
= isl_oid
[n
].size
;
538 cache
= priv
->mib
[n
];
539 cache
+= cache
? extra
* dlen
: 0;
540 oid
= isl_oid
[n
].oid
+ extra
;
544 down_read(&priv
->mib_sem
);
546 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
547 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
548 oid
, data
, dlen
, &response
);
549 if (ret
|| !response
||
550 response
->header
->operation
== PIMFOR_OP_ERROR
) {
552 islpci_mgt_release(response
);
556 _res
= response
->data
;
557 reslen
= response
->header
->length
;
563 if ((isl_oid
[n
].flags
& OID_FLAG_TYPE
) == OID_TYPE_U32
)
564 res
->u
= ret
? 0 : le32_to_cpu(*(u32
*) _res
);
566 res
->ptr
= kmalloc(reslen
, GFP_KERNEL
);
567 BUG_ON(res
->ptr
== NULL
);
569 memset(res
->ptr
, 0, reslen
);
571 memcpy(res
->ptr
, _res
, reslen
);
572 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
,
577 up_read(&priv
->mib_sem
);
579 if (response
&& !ret
)
580 islpci_mgt_release(response
);
582 if (reslen
> isl_oid
[n
].size
)
584 "mgt_get_request(0x%x): received data length was bigger "
585 "than expected (%d > %d). Memory is probably corrupted...",
586 oid
, reslen
, isl_oid
[n
].size
);
593 mgt_commit_list(islpci_private
*priv
, enum oid_num_t
*l
, int n
)
596 struct islpci_mgmtframe
*response
;
598 for (i
= 0; i
< n
; i
++) {
599 struct oid_t
*t
= &(isl_oid
[l
[i
]]);
600 void *data
= priv
->mib
[l
[i
]];
603 BUG_ON(data
== NULL
);
604 while (j
<= t
->range
) {
605 int r
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
,
609 r
|= (response
->header
->operation
== PIMFOR_OP_ERROR
);
610 islpci_mgt_release(response
);
613 printk(KERN_ERR
"%s: mgt_commit_list: failure. "
615 priv
->ndev
->name
, oid
, r
);
628 mgt_set(islpci_private
*priv
, enum oid_num_t n
, void *data
)
630 BUG_ON(OID_NUM_LAST
<= n
);
631 BUG_ON(priv
->mib
[n
] == NULL
);
633 memcpy(priv
->mib
[n
], data
, isl_oid
[n
].size
);
634 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, priv
->mib
[n
]);
638 mgt_get(islpci_private
*priv
, enum oid_num_t n
, void *res
)
640 BUG_ON(OID_NUM_LAST
<= n
);
641 BUG_ON(priv
->mib
[n
] == NULL
);
644 memcpy(res
, priv
->mib
[n
], isl_oid
[n
].size
);
645 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, res
);
648 /* Commits the cache. Lock outside. */
650 static enum oid_num_t commit_part1
[] = {
655 DOT11_OID_MLMEAUTOLEVEL
658 static enum oid_num_t commit_part2
[] = {
661 DOT11_OID_AUTHENABLE
,
662 DOT11_OID_PRIVACYINVOKED
,
663 DOT11_OID_EXUNENCRYPTED
,
664 DOT11_OID_DEFKEYX
, /* MULTIPLE */
666 DOT11_OID_DOT1XENABLE
,
667 OID_INL_DOT11D_CONFORMANCE
,
668 /* Do not initialize this - fw < 1.0.4.3 rejects it
673 /* update the MAC addr. */
675 mgt_update_addr(islpci_private
*priv
)
677 struct islpci_mgmtframe
*res
;
680 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
681 isl_oid
[GEN_OID_MACADDRESS
].oid
, NULL
,
682 isl_oid
[GEN_OID_MACADDRESS
].size
, &res
);
684 if ((ret
== 0) && res
&& (res
->header
->operation
!= PIMFOR_OP_ERROR
))
685 memcpy(priv
->ndev
->dev_addr
, res
->data
, 6);
689 islpci_mgt_release(res
);
692 printk(KERN_ERR
"%s: mgt_update_addr: failure\n", priv
->ndev
->name
);
696 #define VEC_SIZE(a) ARRAY_SIZE(a)
699 mgt_commit(islpci_private
*priv
)
704 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
707 rvalue
= mgt_commit_list(priv
, commit_part1
, VEC_SIZE(commit_part1
));
709 if (priv
->iw_mode
!= IW_MODE_MONITOR
)
710 rvalue
|= mgt_commit_list(priv
, commit_part2
, VEC_SIZE(commit_part2
));
713 rvalue
|= mgt_commit_list(priv
, &u
, 1);
714 rvalue
|= mgt_update_addr(priv
);
717 /* some request have failed. The device might be in an
718 incoherent state. We should reset it ! */
719 printk(KERN_DEBUG
"%s: mgt_commit: failure\n", priv
->ndev
->name
);
724 /* The following OIDs need to be "unlatched":
726 * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
727 * FREQUENCY,EXTENDEDRATES.
729 * The way to do this is to set ESSID. Note though that they may get
730 * unlatch before though by setting another OID. */
733 mgt_unlatch_all(islpci_private
*priv
)
738 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
742 rvalue
= mgt_commit_list(priv
, &u
, 1);
743 /* Necessary if in MANUAL RUN mode? */
746 rvalue
|= mgt_commit_list(priv
, &u
, 1);
748 u
= DOT11_OID_MLMEAUTOLEVEL
;
749 rvalue
|= mgt_commit_list(priv
, &u
, 1);
752 rvalue
|= mgt_commit_list(priv
, &u
, 1);
756 printk(KERN_DEBUG
"%s: Unlatching OIDs failed\n", priv
->ndev
->name
);
760 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
763 mgt_mlme_answer(islpci_private
*priv
)
766 /* Acquire a read lock because if we are in a mode change, it's
767 * possible to answer true, while the card is leaving master to managed
768 * mode. Answering to a mlme in this situation could hang the card.
770 down_read(&priv
->mib_sem
);
772 le32_to_cpu(*(u32
*) priv
->mib
[DOT11_OID_MLMEAUTOLEVEL
]);
773 up_read(&priv
->mib_sem
);
775 return ((priv
->iw_mode
== IW_MODE_MASTER
) &&
776 (mlmeautolevel
>= DOT11_MLME_INTERMEDIATE
));
780 mgt_oidtonum(u32 oid
)
784 for (i
= 0; i
< OID_NUM_LAST
; i
++)
785 if (isl_oid
[i
].oid
== oid
)
788 printk(KERN_DEBUG
"looking for an unknown oid 0x%x", oid
);
794 mgt_response_to_str(enum oid_num_t n
, union oid_res_t
*r
, char *str
)
796 switch (isl_oid
[n
].flags
& OID_FLAG_TYPE
) {
798 return snprintf(str
, PRIV_STR_SIZE
, "%u\n", r
->u
);
800 case OID_TYPE_BUFFER
:{
801 struct obj_buffer
*buff
= r
->ptr
;
802 return snprintf(str
, PRIV_STR_SIZE
,
803 "size=%u\naddr=0x%X\n", buff
->size
,
808 struct obj_bss
*bss
= r
->ptr
;
809 return snprintf(str
, PRIV_STR_SIZE
,
810 "age=%u\nchannel=%u\n"
811 "capinfo=0x%X\nrates=0x%X\n"
812 "basic_rates=0x%X\n", bss
->age
,
813 bss
->channel
, bss
->capinfo
,
814 bss
->rates
, bss
->basic_rates
);
817 case OID_TYPE_BSSLIST
:{
818 struct obj_bsslist
*list
= r
->ptr
;
820 k
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", list
->nr
);
821 for (i
= 0; i
< list
->nr
; i
++)
822 k
+= snprintf(str
+ k
, PRIV_STR_SIZE
- k
,
823 "bss[%u] :\nage=%u\nchannel=%u\n"
824 "capinfo=0x%X\nrates=0x%X\n"
825 "basic_rates=0x%X\n",
826 i
, list
->bsslist
[i
].age
,
827 list
->bsslist
[i
].channel
,
828 list
->bsslist
[i
].capinfo
,
829 list
->bsslist
[i
].rates
,
830 list
->bsslist
[i
].basic_rates
);
834 case OID_TYPE_FREQUENCIES
:{
835 struct obj_frequencies
*freq
= r
->ptr
;
837 printk("nr : %u\n", freq
->nr
);
838 t
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", freq
->nr
);
839 for (i
= 0; i
< freq
->nr
; i
++)
840 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
841 "mhz[%u]=%u\n", i
, freq
->mhz
[i
]);
846 struct obj_mlme
*mlme
= r
->ptr
;
847 return snprintf(str
, PRIV_STR_SIZE
,
848 "id=0x%X\nstate=0x%X\ncode=0x%X\n",
849 mlme
->id
, mlme
->state
, mlme
->code
);
852 case OID_TYPE_MLMEEX
:{
853 struct obj_mlmeex
*mlme
= r
->ptr
;
854 return snprintf(str
, PRIV_STR_SIZE
,
855 "id=0x%X\nstate=0x%X\n"
856 "code=0x%X\nsize=0x%X\n", mlme
->id
,
857 mlme
->state
, mlme
->code
, mlme
->size
);
860 case OID_TYPE_ATTACH
:{
861 struct obj_attachment
*attach
= r
->ptr
;
862 return snprintf(str
, PRIV_STR_SIZE
,
869 struct obj_ssid
*ssid
= r
->ptr
;
870 return snprintf(str
, PRIV_STR_SIZE
,
871 "length=%u\noctets=%.*s\n",
872 ssid
->length
, ssid
->length
,
877 struct obj_key
*key
= r
->ptr
;
879 t
= snprintf(str
, PRIV_STR_SIZE
,
880 "type=0x%X\nlength=0x%X\nkey=0x",
881 key
->type
, key
->length
);
882 for (i
= 0; i
< key
->length
; i
++)
883 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
884 "%02X:", key
->key
[i
]);
885 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");
891 unsigned char *buff
= r
->ptr
;
893 t
= snprintf(str
, PRIV_STR_SIZE
, "hex data=");
894 for (i
= 0; i
< isl_oid
[n
].size
; i
++)
895 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
897 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");