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 "prismcompat.h"
20 #include "islpci_dev.h"
21 #include "islpci_mgt.h"
24 #include "isl_ioctl.h"
26 /* to convert between channel and freq */
27 static const int frequency_list_bg
[] = { 2412, 2417, 2422, 2427, 2432,
28 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484
32 channel_of_freq(int f
)
36 if ((f
>= 2412) && (f
<= 2484)) {
37 while ((c
< 14) && (f
!= frequency_list_bg
[c
]))
39 return (c
>= 14) ? 0 : ++c
;
40 } else if ((f
>= (int) 5000) && (f
<= (int) 6000)) {
41 return ( (f
- 5000) / 5 );
46 #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
47 #define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED)
48 #define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32)
49 #define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32)
50 #define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME)
51 #define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX)
53 #define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0)
55 struct oid_t isl_oid
[] = {
56 OID_STRUCT(GEN_OID_MACADDRESS
, 0x00000000, u8
[6], OID_TYPE_ADDR
),
57 OID_U32(GEN_OID_LINKSTATE
, 0x00000001),
58 OID_UNKNOWN(GEN_OID_WATCHDOG
, 0x00000002),
59 OID_UNKNOWN(GEN_OID_MIBOP
, 0x00000003),
60 OID_UNKNOWN(GEN_OID_OPTIONS
, 0x00000004),
61 OID_UNKNOWN(GEN_OID_LEDCONFIG
, 0x00000005),
64 OID_U32_C(DOT11_OID_BSSTYPE
, 0x10000000),
65 OID_STRUCT_C(DOT11_OID_BSSID
, 0x10000001, u8
[6], OID_TYPE_RAW
),
66 OID_STRUCT_C(DOT11_OID_SSID
, 0x10000002, struct obj_ssid
,
68 OID_U32(DOT11_OID_STATE
, 0x10000003),
69 OID_U32(DOT11_OID_AID
, 0x10000004),
70 OID_STRUCT(DOT11_OID_COUNTRYSTRING
, 0x10000005, u8
[4], OID_TYPE_RAW
),
71 OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE
, 0x10000006, struct obj_ssid
,
74 OID_U32(DOT11_OID_MEDIUMLIMIT
, 0x11000000),
75 OID_U32_C(DOT11_OID_BEACONPERIOD
, 0x11000001),
76 OID_U32(DOT11_OID_DTIMPERIOD
, 0x11000002),
77 OID_U32(DOT11_OID_ATIMWINDOW
, 0x11000003),
78 OID_U32(DOT11_OID_LISTENINTERVAL
, 0x11000004),
79 OID_U32(DOT11_OID_CFPPERIOD
, 0x11000005),
80 OID_U32(DOT11_OID_CFPDURATION
, 0x11000006),
82 OID_U32_C(DOT11_OID_AUTHENABLE
, 0x12000000),
83 OID_U32_C(DOT11_OID_PRIVACYINVOKED
, 0x12000001),
84 OID_U32_C(DOT11_OID_EXUNENCRYPTED
, 0x12000002),
85 OID_U32_C(DOT11_OID_DEFKEYID
, 0x12000003),
86 [DOT11_OID_DEFKEYX
] = {0x12000004, 3, sizeof (struct obj_key
),
87 OID_FLAG_CACHED
| OID_TYPE_KEY
}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */
88 OID_UNKNOWN(DOT11_OID_STAKEY
, 0x12000008),
89 OID_U32(DOT11_OID_REKEYTHRESHOLD
, 0x12000009),
90 OID_UNKNOWN(DOT11_OID_STASC
, 0x1200000a),
92 OID_U32(DOT11_OID_PRIVTXREJECTED
, 0x1a000000),
93 OID_U32(DOT11_OID_PRIVRXPLAIN
, 0x1a000001),
94 OID_U32(DOT11_OID_PRIVRXFAILED
, 0x1a000002),
95 OID_U32(DOT11_OID_PRIVRXNOKEY
, 0x1a000003),
97 OID_U32_C(DOT11_OID_RTSTHRESH
, 0x13000000),
98 OID_U32_C(DOT11_OID_FRAGTHRESH
, 0x13000001),
99 OID_U32_C(DOT11_OID_SHORTRETRIES
, 0x13000002),
100 OID_U32_C(DOT11_OID_LONGRETRIES
, 0x13000003),
101 OID_U32_C(DOT11_OID_MAXTXLIFETIME
, 0x13000004),
102 OID_U32(DOT11_OID_MAXRXLIFETIME
, 0x13000005),
103 OID_U32(DOT11_OID_AUTHRESPTIMEOUT
, 0x13000006),
104 OID_U32(DOT11_OID_ASSOCRESPTIMEOUT
, 0x13000007),
106 OID_UNKNOWN(DOT11_OID_ALOFT_TABLE
, 0x1d000000),
107 OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE
, 0x1d000001),
108 OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT
, 0x1d000002),
109 OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS
, 0x1d000003),
110 OID_U32(DOT11_OID_ALOFT_FIXEDRATE
, 0x1d000004),
111 OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH
, 0x1d000005),
112 OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG
, 0x1d000006),
114 [DOT11_OID_VDCFX
] = {0x1b000000, 7, 0, 0},
115 OID_U32(DOT11_OID_MAXFRAMEBURST
, 0x1b000008),
117 OID_U32(DOT11_OID_PSM
, 0x14000000),
118 OID_U32(DOT11_OID_CAMTIMEOUT
, 0x14000001),
119 OID_U32(DOT11_OID_RECEIVEDTIMS
, 0x14000002),
120 OID_U32(DOT11_OID_ROAMPREFERENCE
, 0x14000003),
122 OID_U32(DOT11_OID_BRIDGELOCAL
, 0x15000000),
123 OID_U32(DOT11_OID_CLIENTS
, 0x15000001),
124 OID_U32(DOT11_OID_CLIENTSASSOCIATED
, 0x15000002),
125 [DOT11_OID_CLIENTX
] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */
127 OID_STRUCT(DOT11_OID_CLIENTFIND
, 0x150007DB, u8
[6], OID_TYPE_ADDR
),
128 OID_STRUCT(DOT11_OID_WDSLINKADD
, 0x150007DC, u8
[6], OID_TYPE_ADDR
),
129 OID_STRUCT(DOT11_OID_WDSLINKREMOVE
, 0x150007DD, u8
[6], OID_TYPE_ADDR
),
130 OID_STRUCT(DOT11_OID_EAPAUTHSTA
, 0x150007DE, u8
[6], OID_TYPE_ADDR
),
131 OID_STRUCT(DOT11_OID_EAPUNAUTHSTA
, 0x150007DF, u8
[6], OID_TYPE_ADDR
),
132 OID_U32_C(DOT11_OID_DOT1XENABLE
, 0x150007E0),
133 OID_UNKNOWN(DOT11_OID_MICFAILURE
, 0x150007E1),
134 OID_UNKNOWN(DOT11_OID_REKEYINDICATE
, 0x150007E2),
136 OID_U32(DOT11_OID_MPDUTXSUCCESSFUL
, 0x16000000),
137 OID_U32(DOT11_OID_MPDUTXONERETRY
, 0x16000001),
138 OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES
, 0x16000002),
139 OID_U32(DOT11_OID_MPDUTXFAILED
, 0x16000003),
140 OID_U32(DOT11_OID_MPDURXSUCCESSFUL
, 0x16000004),
141 OID_U32(DOT11_OID_MPDURXDUPS
, 0x16000005),
142 OID_U32(DOT11_OID_RTSSUCCESSFUL
, 0x16000006),
143 OID_U32(DOT11_OID_RTSFAILED
, 0x16000007),
144 OID_U32(DOT11_OID_ACKFAILED
, 0x16000008),
145 OID_U32(DOT11_OID_FRAMERECEIVES
, 0x16000009),
146 OID_U32(DOT11_OID_FRAMEERRORS
, 0x1600000A),
147 OID_U32(DOT11_OID_FRAMEABORTS
, 0x1600000B),
148 OID_U32(DOT11_OID_FRAMEABORTSPHY
, 0x1600000C),
150 OID_U32(DOT11_OID_SLOTTIME
, 0x17000000),
151 OID_U32(DOT11_OID_CWMIN
, 0x17000001),
152 OID_U32(DOT11_OID_CWMAX
, 0x17000002),
153 OID_U32(DOT11_OID_ACKWINDOW
, 0x17000003),
154 OID_U32(DOT11_OID_ANTENNARX
, 0x17000004),
155 OID_U32(DOT11_OID_ANTENNATX
, 0x17000005),
156 OID_U32(DOT11_OID_ANTENNADIVERSITY
, 0x17000006),
157 OID_U32_C(DOT11_OID_CHANNEL
, 0x17000007),
158 OID_U32_C(DOT11_OID_EDTHRESHOLD
, 0x17000008),
159 OID_U32(DOT11_OID_PREAMBLESETTINGS
, 0x17000009),
160 OID_STRUCT(DOT11_OID_RATES
, 0x1700000A, u8
[IWMAX_BITRATES
+ 1],
162 OID_U32(DOT11_OID_CCAMODESUPPORTED
, 0x1700000B),
163 OID_U32(DOT11_OID_CCAMODE
, 0x1700000C),
164 OID_UNKNOWN(DOT11_OID_RSSIVECTOR
, 0x1700000D),
165 OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE
, 0x1700000E),
166 OID_U32(DOT11_OID_OUTPUTPOWER
, 0x1700000F),
167 OID_STRUCT(DOT11_OID_SUPPORTEDRATES
, 0x17000010,
168 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
169 OID_U32_C(DOT11_OID_FREQUENCY
, 0x17000011),
170 [DOT11_OID_SUPPORTEDFREQUENCIES
] =
171 {0x17000012, 0, sizeof (struct obj_frequencies
)
172 + sizeof (u16
) * IWMAX_FREQ
, OID_TYPE_FREQUENCIES
},
174 OID_U32(DOT11_OID_NOISEFLOOR
, 0x17000013),
175 OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY
, 0x17000014, u8
[IWMAX_FREQ
+ 1],
177 OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE
, 0x17000015),
178 OID_U32(DOT11_OID_NONERPPROTECTION
, 0x17000016),
179 OID_U32(DOT11_OID_SLOTSETTINGS
, 0x17000017),
180 OID_U32(DOT11_OID_NONERPTIMEOUT
, 0x17000018),
181 OID_U32(DOT11_OID_PROFILES
, 0x17000019),
182 OID_STRUCT(DOT11_OID_EXTENDEDRATES
, 0x17000020,
183 u8
[IWMAX_BITRATES
+ 1], OID_TYPE_RAW
),
185 OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE
, 0x18000000),
186 OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE
, 0x18000001),
187 OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE
, 0x18000002),
188 OID_STRUCT_MLME(DOT11_OID_ASSOCIATE
, 0x18000003),
189 OID_UNKNOWN(DOT11_OID_SCAN
, 0x18000004),
190 OID_STRUCT_MLMEEX(DOT11_OID_BEACON
, 0x18000005),
191 OID_STRUCT_MLMEEX(DOT11_OID_PROBE
, 0x18000006),
192 OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX
, 0x18000007),
193 OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX
, 0x18000008),
194 OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX
, 0x18000009),
195 OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX
, 0x1800000A),
196 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE
, 0x1800000B),
197 OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX
, 0x1800000C),
199 OID_U32(DOT11_OID_NONERPSTATUS
, 0x1E000000),
201 OID_U32(DOT11_OID_STATIMEOUT
, 0x19000000),
202 OID_U32_C(DOT11_OID_MLMEAUTOLEVEL
, 0x19000001),
203 OID_U32(DOT11_OID_BSSTIMEOUT
, 0x19000002),
204 [DOT11_OID_ATTACHMENT
] = {0x19000003, 0,
205 sizeof(struct obj_attachment
), OID_TYPE_ATTACH
},
206 OID_STRUCT_C(DOT11_OID_PSMBUFFER
, 0x19000004, struct obj_buffer
,
209 OID_U32(DOT11_OID_BSSS
, 0x1C000000),
210 [DOT11_OID_BSSX
] = {0x1C000001, 63, sizeof (struct obj_bss
),
211 OID_TYPE_BSS
}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */
212 OID_STRUCT(DOT11_OID_BSSFIND
, 0x1C000042, struct obj_bss
, OID_TYPE_BSS
),
213 [DOT11_OID_BSSLIST
] = {0x1C000043, 0, sizeof (struct
215 sizeof (struct obj_bss
[IWMAX_BSS
]),
218 OID_UNKNOWN(OID_INL_TUNNEL
, 0xFF020000),
219 OID_UNKNOWN(OID_INL_MEMADDR
, 0xFF020001),
220 OID_UNKNOWN(OID_INL_MEMORY
, 0xFF020002),
221 OID_U32_C(OID_INL_MODE
, 0xFF020003),
222 OID_UNKNOWN(OID_INL_COMPONENT_NR
, 0xFF020004),
223 OID_STRUCT(OID_INL_VERSION
, 0xFF020005, u8
[8], OID_TYPE_RAW
),
224 OID_UNKNOWN(OID_INL_INTERFACE_ID
, 0xFF020006),
225 OID_UNKNOWN(OID_INL_COMPONENT_ID
, 0xFF020007),
226 OID_U32_C(OID_INL_CONFIG
, 0xFF020008),
227 OID_U32_C(OID_INL_DOT11D_CONFORMANCE
, 0xFF02000C),
228 OID_U32(OID_INL_PHYCAPABILITIES
, 0xFF02000D),
229 OID_U32_C(OID_INL_OUTPUTPOWER
, 0xFF02000F),
234 mgt_init(islpci_private
*priv
)
238 priv
->mib
= kmalloc(OID_NUM_LAST
* sizeof (void *), GFP_KERNEL
);
242 memset(priv
->mib
, 0, OID_NUM_LAST
* sizeof (void *));
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
] = kmalloc(isl_oid
[i
].size
*
248 (isl_oid
[i
].range
+ 1),
252 memset(priv
->mib
[i
], 0,
253 isl_oid
[i
].size
* (isl_oid
[i
].range
+ 1));
258 init_rwsem(&priv
->mib_sem
);
259 prism54_mib_init(priv
);
265 mgt_clean(islpci_private
*priv
)
271 for (i
= 0; i
< OID_NUM_LAST
; i
++) {
280 mgt_le_to_cpu(int type
, void *data
)
284 *(u32
*) data
= le32_to_cpu(*(u32
*) data
);
286 case OID_TYPE_BUFFER
:{
287 struct obj_buffer
*buff
= data
;
288 buff
->size
= le32_to_cpu(buff
->size
);
289 buff
->addr
= le32_to_cpu(buff
->addr
);
293 struct obj_bss
*bss
= data
;
294 bss
->age
= le16_to_cpu(bss
->age
);
295 bss
->channel
= le16_to_cpu(bss
->channel
);
296 bss
->capinfo
= le16_to_cpu(bss
->capinfo
);
297 bss
->rates
= le16_to_cpu(bss
->rates
);
298 bss
->basic_rates
= le16_to_cpu(bss
->basic_rates
);
301 case OID_TYPE_BSSLIST
:{
302 struct obj_bsslist
*list
= data
;
304 list
->nr
= le32_to_cpu(list
->nr
);
305 for (i
= 0; i
< list
->nr
; i
++)
306 mgt_le_to_cpu(OID_TYPE_BSS
, &list
->bsslist
[i
]);
309 case OID_TYPE_FREQUENCIES
:{
310 struct obj_frequencies
*freq
= data
;
312 freq
->nr
= le16_to_cpu(freq
->nr
);
313 for (i
= 0; i
< freq
->nr
; i
++)
314 freq
->mhz
[i
] = le16_to_cpu(freq
->mhz
[i
]);
318 struct obj_mlme
*mlme
= data
;
319 mlme
->id
= le16_to_cpu(mlme
->id
);
320 mlme
->state
= le16_to_cpu(mlme
->state
);
321 mlme
->code
= le16_to_cpu(mlme
->code
);
324 case OID_TYPE_MLMEEX
:{
325 struct obj_mlmeex
*mlme
= data
;
326 mlme
->id
= le16_to_cpu(mlme
->id
);
327 mlme
->state
= le16_to_cpu(mlme
->state
);
328 mlme
->code
= le16_to_cpu(mlme
->code
);
329 mlme
->size
= le16_to_cpu(mlme
->size
);
332 case OID_TYPE_ATTACH
:{
333 struct obj_attachment
*attach
= data
;
334 attach
->id
= le16_to_cpu(attach
->id
);
335 attach
->size
= le16_to_cpu(attach
->size
);
349 mgt_cpu_to_le(int type
, void *data
)
353 *(u32
*) data
= cpu_to_le32(*(u32
*) data
);
355 case OID_TYPE_BUFFER
:{
356 struct obj_buffer
*buff
= data
;
357 buff
->size
= cpu_to_le32(buff
->size
);
358 buff
->addr
= cpu_to_le32(buff
->addr
);
362 struct obj_bss
*bss
= data
;
363 bss
->age
= cpu_to_le16(bss
->age
);
364 bss
->channel
= cpu_to_le16(bss
->channel
);
365 bss
->capinfo
= cpu_to_le16(bss
->capinfo
);
366 bss
->rates
= cpu_to_le16(bss
->rates
);
367 bss
->basic_rates
= cpu_to_le16(bss
->basic_rates
);
370 case OID_TYPE_BSSLIST
:{
371 struct obj_bsslist
*list
= data
;
373 list
->nr
= cpu_to_le32(list
->nr
);
374 for (i
= 0; i
< list
->nr
; i
++)
375 mgt_cpu_to_le(OID_TYPE_BSS
, &list
->bsslist
[i
]);
378 case OID_TYPE_FREQUENCIES
:{
379 struct obj_frequencies
*freq
= data
;
381 freq
->nr
= cpu_to_le16(freq
->nr
);
382 for (i
= 0; i
< freq
->nr
; i
++)
383 freq
->mhz
[i
] = cpu_to_le16(freq
->mhz
[i
]);
387 struct obj_mlme
*mlme
= data
;
388 mlme
->id
= cpu_to_le16(mlme
->id
);
389 mlme
->state
= cpu_to_le16(mlme
->state
);
390 mlme
->code
= cpu_to_le16(mlme
->code
);
393 case OID_TYPE_MLMEEX
:{
394 struct obj_mlmeex
*mlme
= data
;
395 mlme
->id
= cpu_to_le16(mlme
->id
);
396 mlme
->state
= cpu_to_le16(mlme
->state
);
397 mlme
->code
= cpu_to_le16(mlme
->code
);
398 mlme
->size
= cpu_to_le16(mlme
->size
);
401 case OID_TYPE_ATTACH
:{
402 struct obj_attachment
*attach
= data
;
403 attach
->id
= cpu_to_le16(attach
->id
);
404 attach
->size
= cpu_to_le16(attach
->size
);
417 /* Note : data is modified during this function */
420 mgt_set_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
)
423 struct islpci_mgmtframe
*response
= NULL
;
424 int response_op
= PIMFOR_OP_ERROR
;
426 void *cache
, *_data
= data
;
429 BUG_ON(OID_NUM_LAST
<= n
);
430 BUG_ON(extra
> isl_oid
[n
].range
);
433 /* memory has been freed */
436 dlen
= isl_oid
[n
].size
;
437 cache
= priv
->mib
[n
];
438 cache
+= (cache
? extra
* dlen
: 0);
439 oid
= isl_oid
[n
].oid
+ extra
;
442 /* we are requested to re-set a cached value */
445 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, _data
);
446 /* If we are going to write to the cache, we don't want anyone to read
447 * it -> acquire write lock.
448 * Else we could acquire a read lock to be sure we don't bother the
449 * commit process (which takes a write lock). But I'm not sure if it's
453 down_write(&priv
->mib_sem
);
455 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
456 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
457 _data
, dlen
, &response
);
459 response_op
= response
->header
->operation
;
460 islpci_mgt_release(response
);
462 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
469 memcpy(cache
, _data
, dlen
);
470 up_write(&priv
->mib_sem
);
473 /* re-set given data to what it was */
475 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
480 /* None of these are cached */
482 mgt_set_varlen(islpci_private
*priv
, enum oid_num_t n
, void *data
, int extra_len
)
485 struct islpci_mgmtframe
*response
;
486 int response_op
= PIMFOR_OP_ERROR
;
490 BUG_ON(OID_NUM_LAST
<= n
);
492 dlen
= isl_oid
[n
].size
;
493 oid
= isl_oid
[n
].oid
;
495 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
497 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
498 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
499 data
, dlen
+ extra_len
, &response
);
501 response_op
= response
->header
->operation
;
502 islpci_mgt_release(response
);
504 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
509 /* re-set given data to what it was */
511 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
517 mgt_get_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
,
518 union oid_res_t
*res
)
523 struct islpci_mgmtframe
*response
= NULL
;
526 void *cache
, *_res
= NULL
;
529 BUG_ON(OID_NUM_LAST
<= n
);
530 BUG_ON(extra
> isl_oid
[n
].range
);
535 /* memory has been freed */
538 dlen
= isl_oid
[n
].size
;
539 cache
= priv
->mib
[n
];
540 cache
+= cache
? extra
* dlen
: 0;
541 oid
= isl_oid
[n
].oid
+ extra
;
545 down_read(&priv
->mib_sem
);
547 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
548 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
549 oid
, data
, dlen
, &response
);
550 if (ret
|| !response
||
551 response
->header
->operation
== PIMFOR_OP_ERROR
) {
553 islpci_mgt_release(response
);
557 _res
= response
->data
;
558 reslen
= response
->header
->length
;
564 if ((isl_oid
[n
].flags
& OID_FLAG_TYPE
) == OID_TYPE_U32
)
565 res
->u
= ret
? 0 : le32_to_cpu(*(u32
*) _res
);
567 res
->ptr
= kmalloc(reslen
, GFP_KERNEL
);
568 BUG_ON(res
->ptr
== NULL
);
570 memset(res
->ptr
, 0, reslen
);
572 memcpy(res
->ptr
, _res
, reslen
);
573 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
,
578 up_read(&priv
->mib_sem
);
580 if (response
&& !ret
)
581 islpci_mgt_release(response
);
583 if (reslen
> isl_oid
[n
].size
)
585 "mgt_get_request(0x%x): received data length was bigger "
586 "than expected (%d > %d). Memory is probably corrupted...",
587 oid
, reslen
, isl_oid
[n
].size
);
594 mgt_commit_list(islpci_private
*priv
, enum oid_num_t
*l
, int n
)
597 struct islpci_mgmtframe
*response
;
599 for (i
= 0; i
< n
; i
++) {
600 struct oid_t
*t
= &(isl_oid
[l
[i
]]);
601 void *data
= priv
->mib
[l
[i
]];
604 BUG_ON(data
== NULL
);
605 while (j
<= t
->range
) {
606 int r
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
,
610 r
|= (response
->header
->operation
== PIMFOR_OP_ERROR
);
611 islpci_mgt_release(response
);
614 printk(KERN_ERR
"%s: mgt_commit_list: failure. "
616 priv
->ndev
->name
, oid
, r
);
629 mgt_set(islpci_private
*priv
, enum oid_num_t n
, void *data
)
631 BUG_ON(OID_NUM_LAST
<= n
);
632 BUG_ON(priv
->mib
[n
] == NULL
);
634 memcpy(priv
->mib
[n
], data
, isl_oid
[n
].size
);
635 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, priv
->mib
[n
]);
639 mgt_get(islpci_private
*priv
, enum oid_num_t n
, void *res
)
641 BUG_ON(OID_NUM_LAST
<= n
);
642 BUG_ON(priv
->mib
[n
] == NULL
);
645 memcpy(res
, priv
->mib
[n
], isl_oid
[n
].size
);
646 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, res
);
649 /* Commits the cache. Lock outside. */
651 static enum oid_num_t commit_part1
[] = {
656 DOT11_OID_MLMEAUTOLEVEL
659 static enum oid_num_t commit_part2
[] = {
662 DOT11_OID_AUTHENABLE
,
663 DOT11_OID_PRIVACYINVOKED
,
664 DOT11_OID_EXUNENCRYPTED
,
665 DOT11_OID_DEFKEYX
, /* MULTIPLE */
667 DOT11_OID_DOT1XENABLE
,
668 OID_INL_DOT11D_CONFORMANCE
,
669 /* Do not initialize this - fw < 1.0.4.3 rejects it
674 /* update the MAC addr. */
676 mgt_update_addr(islpci_private
*priv
)
678 struct islpci_mgmtframe
*res
;
681 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
682 isl_oid
[GEN_OID_MACADDRESS
].oid
, NULL
,
683 isl_oid
[GEN_OID_MACADDRESS
].size
, &res
);
685 if ((ret
== 0) && res
&& (res
->header
->operation
!= PIMFOR_OP_ERROR
))
686 memcpy(priv
->ndev
->dev_addr
, res
->data
, 6);
690 islpci_mgt_release(res
);
693 printk(KERN_ERR
"%s: mgt_update_addr: failure\n", priv
->ndev
->name
);
697 #define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
700 mgt_commit(islpci_private
*priv
)
705 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
708 rvalue
= mgt_commit_list(priv
, commit_part1
, VEC_SIZE(commit_part1
));
710 if (priv
->iw_mode
!= IW_MODE_MONITOR
)
711 rvalue
|= mgt_commit_list(priv
, commit_part2
, VEC_SIZE(commit_part2
));
714 rvalue
|= mgt_commit_list(priv
, &u
, 1);
715 rvalue
|= mgt_update_addr(priv
);
718 /* some request have failed. The device might be in an
719 incoherent state. We should reset it ! */
720 printk(KERN_DEBUG
"%s: mgt_commit: failure\n", priv
->ndev
->name
);
725 /* The following OIDs need to be "unlatched":
727 * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
728 * FREQUENCY,EXTENDEDRATES.
730 * The way to do this is to set ESSID. Note though that they may get
731 * unlatch before though by setting another OID. */
734 mgt_unlatch_all(islpci_private
*priv
)
739 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
743 rvalue
= mgt_commit_list(priv
, &u
, 1);
744 /* Necessary if in MANUAL RUN mode? */
747 rvalue
|= mgt_commit_list(priv
, &u
, 1);
749 u
= DOT11_OID_MLMEAUTOLEVEL
;
750 rvalue
|= mgt_commit_list(priv
, &u
, 1);
753 rvalue
|= mgt_commit_list(priv
, &u
, 1);
757 printk(KERN_DEBUG
"%s: Unlatching OIDs failed\n", priv
->ndev
->name
);
761 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
764 mgt_mlme_answer(islpci_private
*priv
)
767 /* Acquire a read lock because if we are in a mode change, it's
768 * possible to answer true, while the card is leaving master to managed
769 * mode. Answering to a mlme in this situation could hang the card.
771 down_read(&priv
->mib_sem
);
773 le32_to_cpu(*(u32
*) priv
->mib
[DOT11_OID_MLMEAUTOLEVEL
]);
774 up_read(&priv
->mib_sem
);
776 return ((priv
->iw_mode
== IW_MODE_MASTER
) &&
777 (mlmeautolevel
>= DOT11_MLME_INTERMEDIATE
));
781 mgt_oidtonum(u32 oid
)
785 for (i
= 0; i
< OID_NUM_LAST
; i
++)
786 if (isl_oid
[i
].oid
== oid
)
789 printk(KERN_DEBUG
"looking for an unknown oid 0x%x", oid
);
795 mgt_response_to_str(enum oid_num_t n
, union oid_res_t
*r
, char *str
)
797 switch (isl_oid
[n
].flags
& OID_FLAG_TYPE
) {
799 return snprintf(str
, PRIV_STR_SIZE
, "%u\n", r
->u
);
801 case OID_TYPE_BUFFER
:{
802 struct obj_buffer
*buff
= r
->ptr
;
803 return snprintf(str
, PRIV_STR_SIZE
,
804 "size=%u\naddr=0x%X\n", buff
->size
,
809 struct obj_bss
*bss
= r
->ptr
;
810 return snprintf(str
, PRIV_STR_SIZE
,
811 "age=%u\nchannel=%u\n"
812 "capinfo=0x%X\nrates=0x%X\n"
813 "basic_rates=0x%X\n", bss
->age
,
814 bss
->channel
, bss
->capinfo
,
815 bss
->rates
, bss
->basic_rates
);
818 case OID_TYPE_BSSLIST
:{
819 struct obj_bsslist
*list
= r
->ptr
;
821 k
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", list
->nr
);
822 for (i
= 0; i
< list
->nr
; i
++)
823 k
+= snprintf(str
+ k
, PRIV_STR_SIZE
- k
,
824 "bss[%u] : \nage=%u\nchannel=%u\n"
825 "capinfo=0x%X\nrates=0x%X\n"
826 "basic_rates=0x%X\n",
827 i
, list
->bsslist
[i
].age
,
828 list
->bsslist
[i
].channel
,
829 list
->bsslist
[i
].capinfo
,
830 list
->bsslist
[i
].rates
,
831 list
->bsslist
[i
].basic_rates
);
835 case OID_TYPE_FREQUENCIES
:{
836 struct obj_frequencies
*freq
= r
->ptr
;
838 printk("nr : %u\n", freq
->nr
);
839 t
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", freq
->nr
);
840 for (i
= 0; i
< freq
->nr
; i
++)
841 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
842 "mhz[%u]=%u\n", i
, freq
->mhz
[i
]);
847 struct obj_mlme
*mlme
= r
->ptr
;
848 return snprintf(str
, PRIV_STR_SIZE
,
849 "id=0x%X\nstate=0x%X\ncode=0x%X\n",
850 mlme
->id
, mlme
->state
, mlme
->code
);
853 case OID_TYPE_MLMEEX
:{
854 struct obj_mlmeex
*mlme
= r
->ptr
;
855 return snprintf(str
, PRIV_STR_SIZE
,
856 "id=0x%X\nstate=0x%X\n"
857 "code=0x%X\nsize=0x%X\n", mlme
->id
,
858 mlme
->state
, mlme
->code
, mlme
->size
);
861 case OID_TYPE_ATTACH
:{
862 struct obj_attachment
*attach
= r
->ptr
;
863 return snprintf(str
, PRIV_STR_SIZE
,
870 struct obj_ssid
*ssid
= r
->ptr
;
871 return snprintf(str
, PRIV_STR_SIZE
,
872 "length=%u\noctets=%.*s\n",
873 ssid
->length
, ssid
->length
,
878 struct obj_key
*key
= r
->ptr
;
880 t
= snprintf(str
, PRIV_STR_SIZE
,
881 "type=0x%X\nlength=0x%X\nkey=0x",
882 key
->type
, key
->length
);
883 for (i
= 0; i
< key
->length
; i
++)
884 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
885 "%02X:", key
->key
[i
]);
886 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");
892 unsigned char *buff
= r
->ptr
;
894 t
= snprintf(str
, PRIV_STR_SIZE
, "hex data=");
895 for (i
= 0; i
< isl_oid
[n
].size
; i
++)
896 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
898 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");