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
++)
281 mgt_le_to_cpu(int type
, void *data
)
285 *(u32
*) data
= le32_to_cpu(*(u32
*) data
);
287 case OID_TYPE_BUFFER
:{
288 struct obj_buffer
*buff
= data
;
289 buff
->size
= le32_to_cpu(buff
->size
);
290 buff
->addr
= le32_to_cpu(buff
->addr
);
294 struct obj_bss
*bss
= data
;
295 bss
->age
= le16_to_cpu(bss
->age
);
296 bss
->channel
= le16_to_cpu(bss
->channel
);
297 bss
->capinfo
= le16_to_cpu(bss
->capinfo
);
298 bss
->rates
= le16_to_cpu(bss
->rates
);
299 bss
->basic_rates
= le16_to_cpu(bss
->basic_rates
);
302 case OID_TYPE_BSSLIST
:{
303 struct obj_bsslist
*list
= data
;
305 list
->nr
= le32_to_cpu(list
->nr
);
306 for (i
= 0; i
< list
->nr
; i
++)
307 mgt_le_to_cpu(OID_TYPE_BSS
, &list
->bsslist
[i
]);
310 case OID_TYPE_FREQUENCIES
:{
311 struct obj_frequencies
*freq
= data
;
313 freq
->nr
= le16_to_cpu(freq
->nr
);
314 for (i
= 0; i
< freq
->nr
; i
++)
315 freq
->mhz
[i
] = le16_to_cpu(freq
->mhz
[i
]);
319 struct obj_mlme
*mlme
= data
;
320 mlme
->id
= le16_to_cpu(mlme
->id
);
321 mlme
->state
= le16_to_cpu(mlme
->state
);
322 mlme
->code
= le16_to_cpu(mlme
->code
);
325 case OID_TYPE_MLMEEX
:{
326 struct obj_mlmeex
*mlme
= data
;
327 mlme
->id
= le16_to_cpu(mlme
->id
);
328 mlme
->state
= le16_to_cpu(mlme
->state
);
329 mlme
->code
= le16_to_cpu(mlme
->code
);
330 mlme
->size
= le16_to_cpu(mlme
->size
);
333 case OID_TYPE_ATTACH
:{
334 struct obj_attachment
*attach
= data
;
335 attach
->id
= le16_to_cpu(attach
->id
);
336 attach
->size
= le16_to_cpu(attach
->size
);;
350 mgt_cpu_to_le(int type
, void *data
)
354 *(u32
*) data
= cpu_to_le32(*(u32
*) data
);
356 case OID_TYPE_BUFFER
:{
357 struct obj_buffer
*buff
= data
;
358 buff
->size
= cpu_to_le32(buff
->size
);
359 buff
->addr
= cpu_to_le32(buff
->addr
);
363 struct obj_bss
*bss
= data
;
364 bss
->age
= cpu_to_le16(bss
->age
);
365 bss
->channel
= cpu_to_le16(bss
->channel
);
366 bss
->capinfo
= cpu_to_le16(bss
->capinfo
);
367 bss
->rates
= cpu_to_le16(bss
->rates
);
368 bss
->basic_rates
= cpu_to_le16(bss
->basic_rates
);
371 case OID_TYPE_BSSLIST
:{
372 struct obj_bsslist
*list
= data
;
374 list
->nr
= cpu_to_le32(list
->nr
);
375 for (i
= 0; i
< list
->nr
; i
++)
376 mgt_cpu_to_le(OID_TYPE_BSS
, &list
->bsslist
[i
]);
379 case OID_TYPE_FREQUENCIES
:{
380 struct obj_frequencies
*freq
= data
;
382 freq
->nr
= cpu_to_le16(freq
->nr
);
383 for (i
= 0; i
< freq
->nr
; i
++)
384 freq
->mhz
[i
] = cpu_to_le16(freq
->mhz
[i
]);
388 struct obj_mlme
*mlme
= data
;
389 mlme
->id
= cpu_to_le16(mlme
->id
);
390 mlme
->state
= cpu_to_le16(mlme
->state
);
391 mlme
->code
= cpu_to_le16(mlme
->code
);
394 case OID_TYPE_MLMEEX
:{
395 struct obj_mlmeex
*mlme
= data
;
396 mlme
->id
= cpu_to_le16(mlme
->id
);
397 mlme
->state
= cpu_to_le16(mlme
->state
);
398 mlme
->code
= cpu_to_le16(mlme
->code
);
399 mlme
->size
= cpu_to_le16(mlme
->size
);
402 case OID_TYPE_ATTACH
:{
403 struct obj_attachment
*attach
= data
;
404 attach
->id
= cpu_to_le16(attach
->id
);
405 attach
->size
= cpu_to_le16(attach
->size
);;
418 /* Note : data is modified during this function */
421 mgt_set_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
)
424 struct islpci_mgmtframe
*response
= NULL
;
425 int response_op
= PIMFOR_OP_ERROR
;
427 void *cache
, *_data
= data
;
430 BUG_ON(OID_NUM_LAST
<= n
);
431 BUG_ON(extra
> isl_oid
[n
].range
);
434 /* memory has been freed */
437 dlen
= isl_oid
[n
].size
;
438 cache
= priv
->mib
[n
];
439 cache
+= (cache
? extra
* dlen
: 0);
440 oid
= isl_oid
[n
].oid
+ extra
;
443 /* we are requested to re-set a cached value */
446 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, _data
);
447 /* If we are going to write to the cache, we don't want anyone to read
448 * it -> acquire write lock.
449 * Else we could acquire a read lock to be sure we don't bother the
450 * commit process (which takes a write lock). But I'm not sure if it's
454 down_write(&priv
->mib_sem
);
456 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
457 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
458 _data
, dlen
, &response
);
460 response_op
= response
->header
->operation
;
461 islpci_mgt_release(response
);
463 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
470 memcpy(cache
, _data
, dlen
);
471 up_write(&priv
->mib_sem
);
474 /* re-set given data to what it was */
476 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
481 /* None of these are cached */
483 mgt_set_varlen(islpci_private
*priv
, enum oid_num_t n
, void *data
, int extra_len
)
486 struct islpci_mgmtframe
*response
;
487 int response_op
= PIMFOR_OP_ERROR
;
491 BUG_ON(OID_NUM_LAST
<= n
);
493 dlen
= isl_oid
[n
].size
;
494 oid
= isl_oid
[n
].oid
;
496 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
498 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
499 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
, oid
,
500 data
, dlen
+ extra_len
, &response
);
502 response_op
= response
->header
->operation
;
503 islpci_mgt_release(response
);
505 if (ret
|| response_op
== PIMFOR_OP_ERROR
)
510 /* re-set given data to what it was */
512 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, data
);
518 mgt_get_request(islpci_private
*priv
, enum oid_num_t n
, int extra
, void *data
,
519 union oid_res_t
*res
)
524 struct islpci_mgmtframe
*response
= NULL
;
527 void *cache
, *_res
= NULL
;
530 BUG_ON(OID_NUM_LAST
<= n
);
531 BUG_ON(extra
> isl_oid
[n
].range
);
536 /* memory has been freed */
539 dlen
= isl_oid
[n
].size
;
540 cache
= priv
->mib
[n
];
541 cache
+= cache
? extra
* dlen
: 0;
542 oid
= isl_oid
[n
].oid
+ extra
;
546 down_read(&priv
->mib_sem
);
548 if (islpci_get_state(priv
) >= PRV_STATE_READY
) {
549 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
550 oid
, data
, dlen
, &response
);
551 if (ret
|| !response
||
552 response
->header
->operation
== PIMFOR_OP_ERROR
) {
554 islpci_mgt_release(response
);
558 _res
= response
->data
;
559 reslen
= response
->header
->length
;
565 if ((isl_oid
[n
].flags
& OID_FLAG_TYPE
) == OID_TYPE_U32
)
566 res
->u
= ret
? 0 : le32_to_cpu(*(u32
*) _res
);
568 res
->ptr
= kmalloc(reslen
, GFP_KERNEL
);
569 BUG_ON(res
->ptr
== NULL
);
571 memset(res
->ptr
, 0, reslen
);
573 memcpy(res
->ptr
, _res
, reslen
);
574 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
,
579 up_read(&priv
->mib_sem
);
581 if (response
&& !ret
)
582 islpci_mgt_release(response
);
584 if (reslen
> isl_oid
[n
].size
)
586 "mgt_get_request(0x%x): received data length was bigger "
587 "than expected (%d > %d). Memory is probably corrupted...",
588 oid
, reslen
, isl_oid
[n
].size
);
595 mgt_commit_list(islpci_private
*priv
, enum oid_num_t
*l
, int n
)
598 struct islpci_mgmtframe
*response
;
600 for (i
= 0; i
< n
; i
++) {
601 struct oid_t
*t
= &(isl_oid
[l
[i
]]);
602 void *data
= priv
->mib
[l
[i
]];
605 BUG_ON(data
== NULL
);
606 while (j
<= t
->range
) {
607 int r
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_SET
,
611 r
|= (response
->header
->operation
== PIMFOR_OP_ERROR
);
612 islpci_mgt_release(response
);
615 printk(KERN_ERR
"%s: mgt_commit_list: failure. "
617 priv
->ndev
->name
, oid
, r
);
630 mgt_set(islpci_private
*priv
, enum oid_num_t n
, void *data
)
632 BUG_ON(OID_NUM_LAST
<= n
);
633 BUG_ON(priv
->mib
[n
] == NULL
);
635 memcpy(priv
->mib
[n
], data
, isl_oid
[n
].size
);
636 mgt_cpu_to_le(isl_oid
[n
].flags
& OID_FLAG_TYPE
, priv
->mib
[n
]);
640 mgt_get(islpci_private
*priv
, enum oid_num_t n
, void *res
)
642 BUG_ON(OID_NUM_LAST
<= n
);
643 BUG_ON(priv
->mib
[n
] == NULL
);
646 memcpy(res
, priv
->mib
[n
], isl_oid
[n
].size
);
647 mgt_le_to_cpu(isl_oid
[n
].flags
& OID_FLAG_TYPE
, res
);
650 /* Commits the cache. Lock outside. */
652 static enum oid_num_t commit_part1
[] = {
657 DOT11_OID_MLMEAUTOLEVEL
660 static enum oid_num_t commit_part2
[] = {
663 DOT11_OID_AUTHENABLE
,
664 DOT11_OID_PRIVACYINVOKED
,
665 DOT11_OID_EXUNENCRYPTED
,
666 DOT11_OID_DEFKEYX
, /* MULTIPLE */
668 DOT11_OID_DOT1XENABLE
,
669 OID_INL_DOT11D_CONFORMANCE
,
670 /* Do not initialize this - fw < 1.0.4.3 rejects it
675 /* update the MAC addr. */
677 mgt_update_addr(islpci_private
*priv
)
679 struct islpci_mgmtframe
*res
;
682 ret
= islpci_mgt_transaction(priv
->ndev
, PIMFOR_OP_GET
,
683 isl_oid
[GEN_OID_MACADDRESS
].oid
, NULL
,
684 isl_oid
[GEN_OID_MACADDRESS
].size
, &res
);
686 if ((ret
== 0) && res
&& (res
->header
->operation
!= PIMFOR_OP_ERROR
))
687 memcpy(priv
->ndev
->dev_addr
, res
->data
, 6);
691 islpci_mgt_release(res
);
694 printk(KERN_ERR
"%s: mgt_update_addr: failure\n", priv
->ndev
->name
);
698 #define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
701 mgt_commit(islpci_private
*priv
)
706 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
709 rvalue
= mgt_commit_list(priv
, commit_part1
, VEC_SIZE(commit_part1
));
711 if (priv
->iw_mode
!= IW_MODE_MONITOR
)
712 rvalue
|= mgt_commit_list(priv
, commit_part2
, VEC_SIZE(commit_part2
));
715 rvalue
|= mgt_commit_list(priv
, &u
, 1);
716 rvalue
|= mgt_update_addr(priv
);
719 /* some request have failed. The device might be in an
720 incoherent state. We should reset it ! */
721 printk(KERN_DEBUG
"%s: mgt_commit: failure\n", priv
->ndev
->name
);
726 /* The following OIDs need to be "unlatched":
728 * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
729 * FREQUENCY,EXTENDEDRATES.
731 * The way to do this is to set ESSID. Note though that they may get
732 * unlatch before though by setting another OID. */
735 mgt_unlatch_all(islpci_private
*priv
)
740 if (islpci_get_state(priv
) < PRV_STATE_INIT
)
744 rvalue
= mgt_commit_list(priv
, &u
, 1);
745 /* Necessary if in MANUAL RUN mode? */
748 rvalue
|= mgt_commit_list(priv
, &u
, 1);
750 u
= DOT11_OID_MLMEAUTOLEVEL
;
751 rvalue
|= mgt_commit_list(priv
, &u
, 1);
754 rvalue
|= mgt_commit_list(priv
, &u
, 1);
758 printk(KERN_DEBUG
"%s: Unlatching OIDs failed\n", priv
->ndev
->name
);
762 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
765 mgt_mlme_answer(islpci_private
*priv
)
768 /* Acquire a read lock because if we are in a mode change, it's
769 * possible to answer true, while the card is leaving master to managed
770 * mode. Answering to a mlme in this situation could hang the card.
772 down_read(&priv
->mib_sem
);
774 le32_to_cpu(*(u32
*) priv
->mib
[DOT11_OID_MLMEAUTOLEVEL
]);
775 up_read(&priv
->mib_sem
);
777 return ((priv
->iw_mode
== IW_MODE_MASTER
) &&
778 (mlmeautolevel
>= DOT11_MLME_INTERMEDIATE
));
782 mgt_oidtonum(u32 oid
)
786 for (i
= 0; i
< OID_NUM_LAST
; i
++)
787 if (isl_oid
[i
].oid
== oid
)
790 printk(KERN_DEBUG
"looking for an unknown oid 0x%x", oid
);
796 mgt_response_to_str(enum oid_num_t n
, union oid_res_t
*r
, char *str
)
798 switch (isl_oid
[n
].flags
& OID_FLAG_TYPE
) {
800 return snprintf(str
, PRIV_STR_SIZE
, "%u\n", r
->u
);
802 case OID_TYPE_BUFFER
:{
803 struct obj_buffer
*buff
= r
->ptr
;
804 return snprintf(str
, PRIV_STR_SIZE
,
805 "size=%u\naddr=0x%X\n", buff
->size
,
810 struct obj_bss
*bss
= r
->ptr
;
811 return snprintf(str
, PRIV_STR_SIZE
,
812 "age=%u\nchannel=%u\n"
813 "capinfo=0x%X\nrates=0x%X\n"
814 "basic_rates=0x%X\n", bss
->age
,
815 bss
->channel
, bss
->capinfo
,
816 bss
->rates
, bss
->basic_rates
);
819 case OID_TYPE_BSSLIST
:{
820 struct obj_bsslist
*list
= r
->ptr
;
822 k
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", list
->nr
);
823 for (i
= 0; i
< list
->nr
; i
++)
824 k
+= snprintf(str
+ k
, PRIV_STR_SIZE
- k
,
825 "bss[%u] : \nage=%u\nchannel=%u\n"
826 "capinfo=0x%X\nrates=0x%X\n"
827 "basic_rates=0x%X\n",
828 i
, list
->bsslist
[i
].age
,
829 list
->bsslist
[i
].channel
,
830 list
->bsslist
[i
].capinfo
,
831 list
->bsslist
[i
].rates
,
832 list
->bsslist
[i
].basic_rates
);
836 case OID_TYPE_FREQUENCIES
:{
837 struct obj_frequencies
*freq
= r
->ptr
;
839 printk("nr : %u\n", freq
->nr
);
840 t
= snprintf(str
, PRIV_STR_SIZE
, "nr=%u\n", freq
->nr
);
841 for (i
= 0; i
< freq
->nr
; i
++)
842 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
843 "mhz[%u]=%u\n", i
, freq
->mhz
[i
]);
848 struct obj_mlme
*mlme
= r
->ptr
;
849 return snprintf(str
, PRIV_STR_SIZE
,
850 "id=0x%X\nstate=0x%X\ncode=0x%X\n",
851 mlme
->id
, mlme
->state
, mlme
->code
);
854 case OID_TYPE_MLMEEX
:{
855 struct obj_mlmeex
*mlme
= r
->ptr
;
856 return snprintf(str
, PRIV_STR_SIZE
,
857 "id=0x%X\nstate=0x%X\n"
858 "code=0x%X\nsize=0x%X\n", mlme
->id
,
859 mlme
->state
, mlme
->code
, mlme
->size
);
862 case OID_TYPE_ATTACH
:{
863 struct obj_attachment
*attach
= r
->ptr
;
864 return snprintf(str
, PRIV_STR_SIZE
,
871 struct obj_ssid
*ssid
= r
->ptr
;
872 return snprintf(str
, PRIV_STR_SIZE
,
873 "length=%u\noctets=%.*s\n",
874 ssid
->length
, ssid
->length
,
879 struct obj_key
*key
= r
->ptr
;
881 t
= snprintf(str
, PRIV_STR_SIZE
,
882 "type=0x%X\nlength=0x%X\nkey=0x",
883 key
->type
, key
->length
);
884 for (i
= 0; i
< key
->length
; i
++)
885 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
886 "%02X:", key
->key
[i
]);
887 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");
893 unsigned char *buff
= r
->ptr
;
895 t
= snprintf(str
, PRIV_STR_SIZE
, "hex data=");
896 for (i
= 0; i
< isl_oid
[n
].size
; i
++)
897 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
,
899 t
+= snprintf(str
+ t
, PRIV_STR_SIZE
- t
, "\n");