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, see <http://www.gnu.org/licenses/>.
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
21 #include "prismcompat.h"
22 #include "islpci_dev.h"
23 #include "islpci_mgt.h"
26 #include "isl_ioctl.h"
28 /* to convert between channel and freq */
29 static const int frequency_list_bg
[] = { 2412, 2417, 2422, 2427, 2432,
30 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484
34 channel_of_freq(int f
)
38 if ((f
>= 2412) && (f
<= 2484)) {
39 while ((c
< 14) && (f
!= frequency_list_bg
[c
]))
41 return (c
>= 14) ? 0 : ++c
;
42 } else if ((f
>= (int) 5000) && (f
<= (int) 6000)) {
43 return ( (f
- 5000) / 5 );
48 #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
49 #define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED)
50 #define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32)
51 #define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32)
52 #define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME)
53 #define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX)
55 #define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0)
57 struct oid_t isl_oid
[] = {
58 OID_STRUCT(GEN_OID_MACADDRESS
, 0x00000000, u8
[6], OID_TYPE_ADDR
),
59 OID_U32(GEN_OID_LINKSTATE
, 0x00000001),
60 OID_UNKNOWN(GEN_OID_WATCHDOG
, 0x00000002),
61 OID_UNKNOWN(GEN_OID_MIBOP
, 0x00000003),
62 OID_UNKNOWN(GEN_OID_OPTIONS
, 0x00000004),
63 OID_UNKNOWN(GEN_OID_LEDCONFIG
, 0x00000005),
66 OID_U32_C(DOT11_OID_BSSTYPE
, 0x10000000),
67 OID_STRUCT_C(DOT11_OID_BSSID
, 0x10000001, u8
[6], OID_TYPE_RAW
),
68 OID_STRUCT_C(DOT11_OID_SSID
, 0x10000002, struct obj_ssid
,
70 OID_U32(DOT11_OID_STATE
, 0x10000003),
71 OID_U32(DOT11_OID_AID
, 0x10000004),
72 OID_STRUCT(DOT11_OID_COUNTRYSTRING
, 0x10000005, u8
[4], OID_TYPE_RAW
),
73 OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE
, 0x10000006, struct obj_ssid
,
76 OID_U32(DOT11_OID_MEDIUMLIMIT
, 0x11000000),
77 OID_U32_C(DOT11_OID_BEACONPERIOD
, 0x11000001),
78 OID_U32(DOT11_OID_DTIMPERIOD
, 0x11000002),
79 OID_U32(DOT11_OID_ATIMWINDOW
, 0x11000003),
80 OID_U32(DOT11_OID_LISTENINTERVAL
, 0x11000004),
81 OID_U32(DOT11_OID_CFPPERIOD
, 0x11000005),
82 OID_U32(DOT11_OID_CFPDURATION
, 0x11000006),
84 OID_U32_C(DOT11_OID_AUTHENABLE
, 0x12000000),
85 OID_U32_C(DOT11_OID_PRIVACYINVOKED
, 0x12000001),
86 OID_U32_C(DOT11_OID_EXUNENCRYPTED
, 0x12000002),
87 OID_U32_C(DOT11_OID_DEFKEYID
, 0x12000003),
88 [DOT11_OID_DEFKEYX
] = {0x12000004, 3, sizeof (struct obj_key
),
89 OID_FLAG_CACHED
| OID_TYPE_KEY
}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */
90 OID_UNKNOWN(DOT11_OID_STAKEY
, 0x12000008),
91 OID_U32(DOT11_OID_REKEYTHRESHOLD
, 0x12000009),
92 OID_UNKNOWN(DOT11_OID_STASC
, 0x1200000a),
94 OID_U32(DOT11_OID_PRIVTXREJECTED
, 0x1a000000),
95 OID_U32(DOT11_OID_PRIVRXPLAIN
, 0x1a000001),
96 OID_U32(DOT11_OID_PRIVRXFAILED
, 0x1a000002),
97 OID_U32(DOT11_OID_PRIVRXNOKEY
, 0x1a000003),
99 OID_U32_C(DOT11_OID_RTSTHRESH
, 0x13000000),
100 OID_U32_C(DOT11_OID_FRAGTHRESH
, 0x13000001),
101 OID_U32_C(DOT11_OID_SHORTRETRIES
, 0x13000002),
102 OID_U32_C(DOT11_OID_LONGRETRIES
, 0x13000003),
103 OID_U32_C(DOT11_OID_MAXTXLIFETIME
, 0x13000004),
104 OID_U32(DOT11_OID_MAXRXLIFETIME
, 0x13000005),
105 OID_U32(DOT11_OID_AUTHRESPTIMEOUT
, 0x13000006),
106 OID_U32(DOT11_OID_ASSOCRESPTIMEOUT
, 0x13000007),
108 OID_UNKNOWN(DOT11_OID_ALOFT_TABLE
, 0x1d000000),
109 OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE
, 0x1d000001),
110 OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT
, 0x1d000002),
111 OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS
, 0x1d000003),
112 OID_U32(DOT11_OID_ALOFT_FIXEDRATE
, 0x1d000004),
113 OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH
, 0x1d000005),
114 OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG
, 0x1d000006),
116 [DOT11_OID_VDCFX
] = {0x1b000000, 7, 0, 0},
117 OID_U32(DOT11_OID_MAXFRAMEBURST
, 0x1b000008),
119 OID_U32(DOT11_OID_PSM
, 0x14000000),
120 OID_U32(DOT11_OID_CAMTIMEOUT
, 0x14000001),
121 OID_U32(DOT11_OID_RECEIVEDTIMS
, 0x14000002),
122 OID_U32(DOT11_OID_ROAMPREFERENCE
, 0x14000003),
124 OID_U32(DOT11_OID_BRIDGELOCAL
, 0x15000000),
125 OID_U32(DOT11_OID_CLIENTS
, 0x15000001),
126 OID_U32(DOT11_OID_CLIENTSASSOCIATED
, 0x15000002),
127 [DOT11_OID_CLIENTX
] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */
129 OID_STRUCT(DOT11_OID_CLIENTFIND
, 0x150007DB, u8
[6], OID_TYPE_ADDR
),
130 OID_STRUCT(DOT11_OID_WDSLINKADD
, 0x150007DC, u8
[6], OID_TYPE_ADDR
),
131 OID_STRUCT(DOT11_OID_WDSLINKREMOVE
, 0x150007DD, u8
[6], OID_TYPE_ADDR
),
132 OID_STRUCT(DOT11_OID_EAPAUTHSTA
, 0x150007DE, u8
[6], OID_TYPE_ADDR
),
133 OID_STRUCT(DOT11_OID_EAPUNAUTHSTA
, 0x150007DF, u8
[6], OID_TYPE_ADDR
),
134 OID_U32_C(DOT11_OID_DOT1XENABLE
, 0x150007E0),
135 OID_UNKNOWN(DOT11_OID_MICFAILURE
, 0x150007E1),
136 OID_UNKNOWN(DOT11_OID_REKEYINDICATE
, 0x150007E2),
138 OID_U32(DOT11_OID_MPDUTXSUCCESSFUL
, 0x16000000),
139 OID_U32(DOT11_OID_MPDUTXONERETRY
, 0x16000001),
140 OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES
, 0x16000002),
141 OID_U32(DOT11_OID_MPDUTXFAILED
, 0x16000003),
142 OID_U32(DOT11_OID_MPDURXSUCCESSFUL
, 0x16000004),
143 OID_U32(DOT11_OID_MPDURXDUPS
, 0x16000005),
144 OID_U32(DOT11_OID_RTSSUCCESSFUL
, 0x16000006),
145 OID_U32(DOT11_OID_RTSFAILED
, 0x16000007),
146 OID_U32(DOT11_OID_ACKFAILED
, 0x16000008),
147 OID_U32(DOT11_OID_FRAMERECEIVES
, 0x16000009),
148 OID_U32(DOT11_OID_FRAMEERRORS
, 0x1600000A),
149 OID_U32(DOT11_OID_FRAMEABORTS
, 0x1600000B),
150 OID_U32(DOT11_OID_FRAMEABORTSPHY
, 0x1600000C),
152 OID_U32(DOT11_OID_SLOTTIME
, 0x17000000),
153 OID_U32(DOT11_OID_CWMIN
, 0x17000001),
154 OID_U32(DOT11_OID_CWMAX
, 0x17000002),
155 OID_U32(DOT11_OID_ACKWINDOW
, 0x17000003),
156 OID_U32(DOT11_OID_ANTENNARX
, 0x17000004),
157 OID_U32(DOT11_OID_ANTENNATX
, 0x17000005),
158 OID_U32(DOT11_OID_ANTENNADIVERSITY
, 0x17000006),
159 OID_U32_C(DOT11_OID_CHANNEL
, 0x17000007),
160 OID_U32_C(DOT11_OID_EDTHRESHOLD
, 0x17000008),
161 OID_U32(DOT11_OID_PREAMBLESETTINGS
, 0x17000009),
162 OID_STRUCT(DOT11_OID_RATES
, 0x1700000A, u8
[IWMAX_BITRATES
+ 1],
164 OID_U32(DOT11_OID_CCAMODESUPPORTED
, 0x1700000B),
165 OID_U32(DOT11_OID_CCAMODE
, 0x1700000C),
166 OID_UNKNOWN(DOT11_OID_RSSIVECTOR
, 0x1700000D),
167 OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE
, 0x1700000E),
168 OID_U32(DOT11_OID_OUTPUTPOWER
, 0x1700000F),
169 OID_STRUCT(DOT11_OID_SUPPORTEDRATES
, 0x17000010,
170 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
171 OID_U32_C(DOT11_OID_FREQUENCY
, 0x17000011),
172 [DOT11_OID_SUPPORTEDFREQUENCIES
] =
173 {0x17000012, 0, sizeof (struct obj_frequencies
)
174 + sizeof (u16
) * IWMAX_FREQ
, OID_TYPE_FREQUENCIES
},
176 OID_U32(DOT11_OID_NOISEFLOOR
, 0x17000013),
177 OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY
, 0x17000014, u8
[IWMAX_FREQ
+ 1],
179 OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE
, 0x17000015),
180 OID_U32(DOT11_OID_NONERPPROTECTION
, 0x17000016),
181 OID_U32(DOT11_OID_SLOTSETTINGS
, 0x17000017),
182 OID_U32(DOT11_OID_NONERPTIMEOUT
, 0x17000018),
183 OID_U32(DOT11_OID_PROFILES
, 0x17000019),
184 OID_STRUCT(DOT11_OID_EXTENDEDRATES
, 0x17000020,
185 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
187 OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE
, 0x18000000),
188 OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE
, 0x18000001),
189 OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE
, 0x18000002),
190 OID_STRUCT_MLME(DOT11_OID_ASSOCIATE
, 0x18000003),
191 OID_UNKNOWN(DOT11_OID_SCAN
, 0x18000004),
192 OID_STRUCT_MLMEEX(DOT11_OID_BEACON
, 0x18000005),
193 OID_STRUCT_MLMEEX(DOT11_OID_PROBE
, 0x18000006),
194 OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX
, 0x18000007),
195 OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX
, 0x18000008),
196 OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX
, 0x18000009),
197 OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX
, 0x1800000A),
198 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE
, 0x1800000B),
199 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX
, 0x1800000C),
201 OID_U32(DOT11_OID_NONERPSTATUS
, 0x1E000000),
203 OID_U32(DOT11_OID_STATIMEOUT
, 0x19000000),
204 OID_U32_C(DOT11_OID_MLMEAUTOLEVEL
, 0x19000001),
205 OID_U32(DOT11_OID_BSSTIMEOUT
, 0x19000002),
206 [DOT11_OID_ATTACHMENT
] = {0x19000003, 0,
207 sizeof(struct obj_attachment
), OID_TYPE_ATTACH
},
208 OID_STRUCT_C(DOT11_OID_PSMBUFFER
, 0x19000004, struct obj_buffer
,
211 OID_U32(DOT11_OID_BSSS
, 0x1C000000),
212 [DOT11_OID_BSSX
] = {0x1C000001, 63, sizeof (struct obj_bss
),
213 OID_TYPE_BSS
}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */
214 OID_STRUCT(DOT11_OID_BSSFIND
, 0x1C000042, struct obj_bss
, OID_TYPE_BSS
),
215 [DOT11_OID_BSSLIST
] = {0x1C000043, 0, sizeof (struct
217 sizeof (struct obj_bss
[IWMAX_BSS
]),
220 OID_UNKNOWN(OID_INL_TUNNEL
, 0xFF020000),
221 OID_UNKNOWN(OID_INL_MEMADDR
, 0xFF020001),
222 OID_UNKNOWN(OID_INL_MEMORY
, 0xFF020002),
223 OID_U32_C(OID_INL_MODE
, 0xFF020003),
224 OID_UNKNOWN(OID_INL_COMPONENT_NR
, 0xFF020004),
225 OID_STRUCT(OID_INL_VERSION
, 0xFF020005, u8
[8], OID_TYPE_RAW
),
226 OID_UNKNOWN(OID_INL_INTERFACE_ID
, 0xFF020006),
227 OID_UNKNOWN(OID_INL_COMPONENT_ID
, 0xFF020007),
228 OID_U32_C(OID_INL_CONFIG
, 0xFF020008),
229 OID_U32_C(OID_INL_DOT11D_CONFORMANCE
, 0xFF02000C),
230 OID_U32(OID_INL_PHYCAPABILITIES
, 0xFF02000D),
231 OID_U32_C(OID_INL_OUTPUTPOWER
, 0xFF02000F),
236 mgt_init(islpci_private
*priv
)
240 priv
->mib
= kcalloc(OID_NUM_LAST
, sizeof (void *), GFP_KERNEL
);
244 /* Alloc the cache */
245 for (i
= 0; i
< OID_NUM_LAST
; i
++) {
246 if (isl_oid
[i
].flags
& OID_FLAG_CACHED
) {
247 priv
->mib
[i
] = kzalloc(isl_oid
[i
].size
*
248 (isl_oid
[i
].range
+ 1),
256 init_rwsem(&priv
->mib_sem
);
257 prism54_mib_init(priv
);
263 mgt_clean(islpci_private
*priv
)
269 for (i
= 0; i
< OID_NUM_LAST
; i
++) {
278 mgt_le_to_cpu(int type
, void *data
)
282 *(u32
*) data
= le32_to_cpu(*(u32
*) data
);
284 case OID_TYPE_BUFFER
:{
285 struct obj_buffer
*buff
= data
;
286 buff
->size
= le32_to_cpu(buff
->size
);
287 buff
->addr
= le32_to_cpu(buff
->addr
);
291 struct obj_bss
*bss
= data
;
292 bss
->age
= le16_to_cpu(bss
->age
);
293 bss
->channel
= le16_to_cpu(bss
->channel
);
294 bss
->capinfo
= le16_to_cpu(bss
->capinfo
);
295 bss
->rates
= le16_to_cpu(bss
->rates
);
296 bss
->basic_rates
= le16_to_cpu(bss
->basic_rates
);
299 case OID_TYPE_BSSLIST
:{
300 struct obj_bsslist
*list
= data
;
302 list
->nr
= le32_to_cpu(list
->nr
);
303 for (i
= 0; i
< list
->nr
; i
++)
304 mgt_le_to_cpu(OID_TYPE_BSS
, &list
->bsslist
[i
]);
307 case OID_TYPE_FREQUENCIES
:{
308 struct obj_frequencies
*freq
= data
;
310 freq
->nr
= le16_to_cpu(freq
->nr
);
311 for (i
= 0; i
< freq
->nr
; i
++)
312 freq
->mhz
[i
] = le16_to_cpu(freq
->mhz
[i
]);
316 struct obj_mlme
*mlme
= data
;
317 mlme
->id
= le16_to_cpu(mlme
->id
);
318 mlme
->state
= le16_to_cpu(mlme
->state
);
319 mlme
->code
= le16_to_cpu(mlme
->code
);
322 case OID_TYPE_MLMEEX
:{
323 struct obj_mlmeex
*mlme
= data
;
324 mlme
->id
= le16_to_cpu(mlme
->id
);
325 mlme
->state
= le16_to_cpu(mlme
->state
);
326 mlme
->code
= le16_to_cpu(mlme
->code
);
327 mlme
->size
= le16_to_cpu(mlme
->size
);
330 case OID_TYPE_ATTACH
:{
331 struct obj_attachment
*attach
= data
;
332 attach
->id
= le16_to_cpu(attach
->id
);
333 attach
->size
= le16_to_cpu(attach
->size
);
347 mgt_cpu_to_le(int type
, void *data
)
351 *(u32
*) data
= cpu_to_le32(*(u32
*) data
);
353 case OID_TYPE_BUFFER
:{
354 struct obj_buffer
*buff
= data
;
355 buff
->size
= cpu_to_le32(buff
->size
);
356 buff
->addr
= cpu_to_le32(buff
->addr
);
360 struct obj_bss
*bss
= data
;
361 bss
->age
= cpu_to_le16(bss
->age
);
362 bss
->channel
= cpu_to_le16(bss
->channel
);
363 bss
->capinfo
= cpu_to_le16(bss
->capinfo
);
364 bss
->rates
= cpu_to_le16(bss
->rates
);
365 bss
->basic_rates
= cpu_to_le16(bss
->basic_rates
);
368 case OID_TYPE_BSSLIST
:{
369 struct obj_bsslist
*list
= data
;
371 list
->nr
= cpu_to_le32(list
->nr
);
372 for (i
= 0; i
< list
->nr
; i
++)
373 mgt_cpu_to_le(OID_TYPE_BSS
, &list
->bsslist
[i
]);
376 case OID_TYPE_FREQUENCIES
:{
377 struct obj_frequencies
*freq
= data
;
379 freq
->nr
= cpu_to_le16(freq
->nr
);
380 for (i
= 0; i
< freq
->nr
; i
++)
381 freq
->mhz
[i
] = cpu_to_le16(freq
->mhz
[i
]);
385 struct obj_mlme
*mlme
= data
;
386 mlme
->id
= cpu_to_le16(mlme
->id
);
387 mlme
->state
= cpu_to_le16(mlme
->state
);
388 mlme
->code
= cpu_to_le16(mlme
->code
);
391 case OID_TYPE_MLMEEX
:{
392 struct obj_mlmeex
*mlme
= data
;
393 mlme
->id
= cpu_to_le16(mlme
->id
);
394 mlme
->state
= cpu_to_le16(mlme
->state
);
395 mlme
->code
= cpu_to_le16(mlme
->code
);
396 mlme
->size
= cpu_to_le16(mlme
->size
);
399 case OID_TYPE_ATTACH
:{
400 struct obj_attachment
*attach
= data
;
401 attach
->id
= cpu_to_le16(attach
->id
);
402 attach
->size
= cpu_to_le16(attach
->size
);
415 /* Note : data is modified during this function */
418 mgt_set_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
)
421 struct islpci_mgmtframe
*response
= NULL
;
422 int response_op
= PIMFOR_OP_ERROR
;
424 void *cache
, *_data
= data
;
427 BUG_ON(OID_NUM_LAST
<= n
);
428 BUG_ON(extra
> isl_oid
[n
].range
);
431 /* memory has been freed */
434 dlen
= isl_oid
[n
].size
;
435 cache
= priv
->mib
[n
];
436 cache
+= (cache
? extra
* dlen
: 0);
437 oid
= isl_oid
[n
].oid
+ extra
;
440 /* we are requested to re-set a cached value */
443 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, _data
);
444 /* If we are going to write to the cache, we don't want anyone to read
445 * it -> acquire write lock.
446 * Else we could acquire a read lock to be sure we don't bother the
447 * commit process (which takes a write lock). But I'm not sure if it's
451 down_write(&priv
->mib_sem
);
453 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
454 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
455 _data
, dlen
, &response
);
457 response_op
= response
->header
->operation
;
458 islpci_mgt_release(response
);
460 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
467 memcpy(cache
, _data
, dlen
);
468 up_write(&priv
->mib_sem
);
471 /* re-set given data to what it was */
473 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
478 /* None of these are cached */
480 mgt_set_varlen(islpci_private
*priv
, enum oid_num_t n
, void *data
, int extra_len
)
483 struct islpci_mgmtframe
*response
;
484 int response_op
= PIMFOR_OP_ERROR
;
488 BUG_ON(OID_NUM_LAST
<= n
);
490 dlen
= isl_oid
[n
].size
;
491 oid
= isl_oid
[n
].oid
;
493 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
495 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
496 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
497 data
, dlen
+ extra_len
, &response
);
499 response_op
= response
->header
->operation
;
500 islpci_mgt_release(response
);
502 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
507 /* re-set given data to what it was */
509 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
515 mgt_get_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
,
516 union oid_res_t
*res
)
521 struct islpci_mgmtframe
*response
= NULL
;
524 void *cache
, *_res
= NULL
;
527 BUG_ON(OID_NUM_LAST
<= n
);
528 BUG_ON(extra
> isl_oid
[n
].range
);
533 /* memory has been freed */
536 dlen
= isl_oid
[n
].size
;
537 cache
= priv
->mib
[n
];
538 cache
+= cache
? extra
* dlen
: 0;
539 oid
= isl_oid
[n
].oid
+ extra
;
543 down_read(&priv
->mib_sem
);
545 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
546 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
547 oid
, data
, dlen
, &response
);
548 if (ret
|| !response
||
549 response
->header
->operation
== PIMFOR_OP_ERROR
) {
551 islpci_mgt_release(response
);
555 _res
= response
->data
;
556 reslen
= response
->header
->length
;
562 if ((isl_oid
[n
].flags
& OID_FLAG_TYPE
) == OID_TYPE_U32
)
563 res
->u
= ret
? 0 : le32_to_cpu(*(u32
*) _res
);
565 res
->ptr
= kmalloc(reslen
, GFP_KERNEL
);
566 BUG_ON(res
->ptr
== NULL
);
568 memset(res
->ptr
, 0, reslen
);
570 memcpy(res
->ptr
, _res
, reslen
);
571 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
,
576 up_read(&priv
->mib_sem
);
578 if (response
&& !ret
)
579 islpci_mgt_release(response
);
581 if (reslen
> isl_oid
[n
].size
)
583 "mgt_get_request(0x%x): received data length was bigger "
584 "than expected (%d > %d). Memory is probably corrupted...",
585 oid
, reslen
, isl_oid
[n
].size
);
592 mgt_commit_list(islpci_private
*priv
, enum oid_num_t
*l
, int n
)
595 struct islpci_mgmtframe
*response
;
597 for (i
= 0; i
< n
; i
++) {
598 struct oid_t
*t
= &(isl_oid
[l
[i
]]);
599 void *data
= priv
->mib
[l
[i
]];
602 BUG_ON(data
== NULL
);
603 while (j
<= t
->range
) {
604 int r
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
,
608 r
|= (response
->header
->operation
== PIMFOR_OP_ERROR
);
609 islpci_mgt_release(response
);
612 printk(KERN_ERR
"%s: mgt_commit_list: failure. "
614 priv
->ndev
->name
, oid
, r
);
627 mgt_set(islpci_private
*priv
, enum oid_num_t n
, void *data
)
629 BUG_ON(OID_NUM_LAST
<= n
);
630 BUG_ON(priv
->mib
[n
] == NULL
);
632 memcpy(priv
->mib
[n
], data
, isl_oid
[n
].size
);
633 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, priv
->mib
[n
]);
637 mgt_get(islpci_private
*priv
, enum oid_num_t n
, void *res
)
639 BUG_ON(OID_NUM_LAST
<= n
);
640 BUG_ON(priv
->mib
[n
] == NULL
);
643 memcpy(res
, priv
->mib
[n
], isl_oid
[n
].size
);
644 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, res
);
647 /* Commits the cache. Lock outside. */
649 static enum oid_num_t commit_part1
[] = {
654 DOT11_OID_MLMEAUTOLEVEL
657 static enum oid_num_t commit_part2
[] = {
660 DOT11_OID_AUTHENABLE
,
661 DOT11_OID_PRIVACYINVOKED
,
662 DOT11_OID_EXUNENCRYPTED
,
663 DOT11_OID_DEFKEYX
, /* MULTIPLE */
665 DOT11_OID_DOT1XENABLE
,
666 OID_INL_DOT11D_CONFORMANCE
,
667 /* Do not initialize this - fw < 1.0.4.3 rejects it
672 /* update the MAC addr. */
674 mgt_update_addr(islpci_private
*priv
)
676 struct islpci_mgmtframe
*res
;
679 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
680 isl_oid
[GEN_OID_MACADDRESS
].oid
, NULL
,
681 isl_oid
[GEN_OID_MACADDRESS
].size
, &res
);
683 if ((ret
== 0) && res
&& (res
->header
->operation
!= PIMFOR_OP_ERROR
))
684 memcpy(priv
->ndev
->dev_addr
, res
->data
, ETH_ALEN
);
688 islpci_mgt_release(res
);
691 printk(KERN_ERR
"%s: mgt_update_addr: failure\n", priv
->ndev
->name
);
696 mgt_commit(islpci_private
*priv
)
701 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
704 rvalue
= mgt_commit_list(priv
, commit_part1
, ARRAY_SIZE(commit_part1
));
706 if (priv
->iw_mode
!= IW_MODE_MONITOR
)
707 rvalue
|= mgt_commit_list(priv
, commit_part2
, ARRAY_SIZE(commit_part2
));
710 rvalue
|= mgt_commit_list(priv
, &u
, 1);
711 rvalue
|= mgt_update_addr(priv
);
714 /* some request have failed. The device might be in an
715 incoherent state. We should reset it ! */
716 printk(KERN_DEBUG
"%s: mgt_commit: failure\n", priv
->ndev
->name
);
721 /* The following OIDs need to be "unlatched":
723 * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
724 * FREQUENCY,EXTENDEDRATES.
726 * The way to do this is to set ESSID. Note though that they may get
727 * unlatch before though by setting another OID. */
730 mgt_unlatch_all(islpci_private
*priv
)
735 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
739 rvalue
= mgt_commit_list(priv
, &u
, 1);
740 /* Necessary if in MANUAL RUN mode? */
743 rvalue
|= mgt_commit_list(priv
, &u
, 1);
745 u
= DOT11_OID_MLMEAUTOLEVEL
;
746 rvalue
|= mgt_commit_list(priv
, &u
, 1);
749 rvalue
|= mgt_commit_list(priv
, &u
, 1);
753 printk(KERN_DEBUG
"%s: Unlatching OIDs failed\n", priv
->ndev
->name
);
757 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
760 mgt_mlme_answer(islpci_private
*priv
)
763 /* Acquire a read lock because if we are in a mode change, it's
764 * possible to answer true, while the card is leaving master to managed
765 * mode. Answering to a mlme in this situation could hang the card.
767 down_read(&priv
->mib_sem
);
769 le32_to_cpu(*(u32
*) priv
->mib
[DOT11_OID_MLMEAUTOLEVEL
]);
770 up_read(&priv
->mib_sem
);
772 return ((priv
->iw_mode
== IW_MODE_MASTER
) &&
773 (mlmeautolevel
>= DOT11_MLME_INTERMEDIATE
));
777 mgt_oidtonum(u32 oid
)
781 for (i
= 0; i
< OID_NUM_LAST
; i
++)
782 if (isl_oid
[i
].oid
== oid
)
785 printk(KERN_DEBUG
"looking for an unknown oid 0x%x", oid
);
791 mgt_response_to_str(enum oid_num_t n
, union oid_res_t
*r
, char *str
)
793 switch (isl_oid
[n
].flags
& OID_FLAG_TYPE
) {
795 return snprintf(str
, PRIV_STR_SIZE
, "%u\n", r
->u
);
797 case OID_TYPE_BUFFER
:{
798 struct obj_buffer
*buff
= r
->ptr
;
799 return snprintf(str
, PRIV_STR_SIZE
,
800 "size=%u\naddr=0x%X\n", buff
->size
,
805 struct obj_bss
*bss
= r
->ptr
;
806 return snprintf(str
, PRIV_STR_SIZE
,
807 "age=%u\nchannel=%u\n"
808 "capinfo=0x%X\nrates=0x%X\n"
809 "basic_rates=0x%X\n", bss
->age
,
810 bss
->channel
, bss
->capinfo
,
811 bss
->rates
, bss
->basic_rates
);
814 case OID_TYPE_BSSLIST
:{
815 struct obj_bsslist
*list
= r
->ptr
;
817 k
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", list
->nr
);
818 for (i
= 0; i
< list
->nr
; i
++)
819 k
+= snprintf(str
+ k
, PRIV_STR_SIZE
- k
,
820 "bss[%u] :\nage=%u\nchannel=%u\n"
821 "capinfo=0x%X\nrates=0x%X\n"
822 "basic_rates=0x%X\n",
823 i
, list
->bsslist
[i
].age
,
824 list
->bsslist
[i
].channel
,
825 list
->bsslist
[i
].capinfo
,
826 list
->bsslist
[i
].rates
,
827 list
->bsslist
[i
].basic_rates
);
831 case OID_TYPE_FREQUENCIES
:{
832 struct obj_frequencies
*freq
= r
->ptr
;
834 printk("nr : %u\n", freq
->nr
);
835 t
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", freq
->nr
);
836 for (i
= 0; i
< freq
->nr
; i
++)
837 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
838 "mhz[%u]=%u\n", i
, freq
->mhz
[i
]);
843 struct obj_mlme
*mlme
= r
->ptr
;
844 return snprintf(str
, PRIV_STR_SIZE
,
845 "id=0x%X\nstate=0x%X\ncode=0x%X\n",
846 mlme
->id
, mlme
->state
, mlme
->code
);
849 case OID_TYPE_MLMEEX
:{
850 struct obj_mlmeex
*mlme
= r
->ptr
;
851 return snprintf(str
, PRIV_STR_SIZE
,
852 "id=0x%X\nstate=0x%X\n"
853 "code=0x%X\nsize=0x%X\n", mlme
->id
,
854 mlme
->state
, mlme
->code
, mlme
->size
);
857 case OID_TYPE_ATTACH
:{
858 struct obj_attachment
*attach
= r
->ptr
;
859 return snprintf(str
, PRIV_STR_SIZE
,
866 struct obj_ssid
*ssid
= r
->ptr
;
867 return snprintf(str
, PRIV_STR_SIZE
,
868 "length=%u\noctets=%.*s\n",
869 ssid
->length
, ssid
->length
,
874 struct obj_key
*key
= r
->ptr
;
876 t
= snprintf(str
, PRIV_STR_SIZE
,
877 "type=0x%X\nlength=0x%X\nkey=0x",
878 key
->type
, key
->length
);
879 for (i
= 0; i
< key
->length
; i
++)
880 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
881 "%02X:", key
->key
[i
]);
882 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");
888 unsigned char *buff
= r
->ptr
;
890 t
= snprintf(str
, PRIV_STR_SIZE
, "hex data=");
891 for (i
= 0; i
< isl_oid
[n
].size
; i
++)
892 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
894 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");