]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/wireless/airo.c
airo: re-arrange WPA capability checks
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / wireless / airo.c
CommitLineData
1da177e4
LT
1/*======================================================================
2
3 Aironet driver for 4500 and 4800 series cards
4
5 This code is released under both the GPL version 2 and BSD licenses.
6 Either license may be used. The respective licenses are found at
7 the end of this file.
8
9 This code was developed by Benjamin Reed <breed@users.sourceforge.net>
10 including portions of which come from the Aironet PC4500
11 Developer's Reference Manual and used with permission. Copyright
12 (C) 1999 Benjamin Reed. All Rights Reserved. Permission to use
13 code in the Developer's manual was granted for this driver by
14 Aironet. Major code contributions were received from Javier Achirica
15 <achirica@users.sourceforge.net> and Jean Tourrilhes <jt@hpl.hp.com>.
16 Code was also integrated from the Cisco Aironet driver for Linux.
17 Support for MPI350 cards was added by Fabrice Bellet
18 <fabrice@bellet.info>.
19
20======================================================================*/
21
f12cc209 22#include <linux/err.h>
1da177e4
LT
23#include <linux/init.h>
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/proc_fs.h>
1da177e4
LT
28
29#include <linux/sched.h>
30#include <linux/ptrace.h>
31#include <linux/slab.h>
32#include <linux/string.h>
33#include <linux/timer.h>
34#include <linux/interrupt.h>
35#include <linux/in.h>
36#include <linux/bitops.h>
378f058c 37#include <linux/scatterlist.h>
a39d3e79 38#include <linux/crypto.h>
1da177e4
LT
39#include <asm/io.h>
40#include <asm/system.h>
593c2b9c 41#include <asm/unaligned.h>
1da177e4
LT
42
43#include <linux/netdevice.h>
44#include <linux/etherdevice.h>
45#include <linux/skbuff.h>
46#include <linux/if_arp.h>
47#include <linux/ioport.h>
48#include <linux/pci.h>
49#include <asm/uaccess.h>
3b4c7d64 50#include <linux/kthread.h>
7dfb7103 51#include <linux/freezer.h>
1da177e4 52
2c706002
JB
53#include <linux/ieee80211.h>
54
d3808760
AB
55#include "airo.h"
56
1138c37b
MS
57#define DRV_NAME "airo"
58
1da177e4
LT
59#ifdef CONFIG_PCI
60static struct pci_device_id card_ids[] = {
61 { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
62 { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
63 { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
64 { 0x14b9, 0x0340, PCI_ANY_ID, PCI_ANY_ID, },
65 { 0x14b9, 0x0350, PCI_ANY_ID, PCI_ANY_ID, },
66 { 0x14b9, 0x5000, PCI_ANY_ID, PCI_ANY_ID, },
67 { 0x14b9, 0xa504, PCI_ANY_ID, PCI_ANY_ID, },
68 { 0, }
69};
70MODULE_DEVICE_TABLE(pci, card_ids);
71
72static int airo_pci_probe(struct pci_dev *, const struct pci_device_id *);
73static void airo_pci_remove(struct pci_dev *);
05adc3b7 74static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state);
1da177e4
LT
75static int airo_pci_resume(struct pci_dev *pdev);
76
77static struct pci_driver airo_driver = {
1138c37b 78 .name = DRV_NAME,
1da177e4
LT
79 .id_table = card_ids,
80 .probe = airo_pci_probe,
81 .remove = __devexit_p(airo_pci_remove),
82 .suspend = airo_pci_suspend,
83 .resume = airo_pci_resume,
84};
85#endif /* CONFIG_PCI */
86
87/* Include Wireless Extension definition and check version - Jean II */
88#include <linux/wireless.h>
e292c737
PM
89#define WIRELESS_SPY /* enable iwspy support */
90#include <net/iw_handler.h> /* New driver API */
1da177e4 91
e292c737 92#define CISCO_EXT /* enable Cisco extensions */
1da177e4
LT
93#ifdef CISCO_EXT
94#include <linux/delay.h>
95#endif
96
1da177e4
LT
97/* Hack to do some power saving */
98#define POWER_ON_DOWN
99
100/* As you can see this list is HUGH!
101 I really don't know what a lot of these counts are about, but they
102 are all here for completeness. If the IGNLABEL macro is put in
103 infront of the label, that statistic will not be included in the list
104 of statistics in the /proc filesystem */
105
106#define IGNLABEL(comment) NULL
107static char *statsLabels[] = {
108 "RxOverrun",
109 IGNLABEL("RxPlcpCrcErr"),
110 IGNLABEL("RxPlcpFormatErr"),
111 IGNLABEL("RxPlcpLengthErr"),
112 "RxMacCrcErr",
113 "RxMacCrcOk",
114 "RxWepErr",
115 "RxWepOk",
116 "RetryLong",
117 "RetryShort",
118 "MaxRetries",
119 "NoAck",
120 "NoCts",
121 "RxAck",
122 "RxCts",
123 "TxAck",
124 "TxRts",
125 "TxCts",
126 "TxMc",
127 "TxBc",
128 "TxUcFrags",
129 "TxUcPackets",
130 "TxBeacon",
131 "RxBeacon",
132 "TxSinColl",
133 "TxMulColl",
134 "DefersNo",
135 "DefersProt",
136 "DefersEngy",
137 "DupFram",
138 "RxFragDisc",
139 "TxAged",
140 "RxAged",
141 "LostSync-MaxRetry",
142 "LostSync-MissedBeacons",
143 "LostSync-ArlExceeded",
144 "LostSync-Deauth",
145 "LostSync-Disassoced",
146 "LostSync-TsfTiming",
147 "HostTxMc",
148 "HostTxBc",
149 "HostTxUc",
150 "HostTxFail",
151 "HostRxMc",
152 "HostRxBc",
153 "HostRxUc",
154 "HostRxDiscard",
155 IGNLABEL("HmacTxMc"),
156 IGNLABEL("HmacTxBc"),
157 IGNLABEL("HmacTxUc"),
158 IGNLABEL("HmacTxFail"),
159 IGNLABEL("HmacRxMc"),
160 IGNLABEL("HmacRxBc"),
161 IGNLABEL("HmacRxUc"),
162 IGNLABEL("HmacRxDiscard"),
163 IGNLABEL("HmacRxAccepted"),
164 "SsidMismatch",
165 "ApMismatch",
166 "RatesMismatch",
167 "AuthReject",
168 "AuthTimeout",
169 "AssocReject",
170 "AssocTimeout",
171 IGNLABEL("ReasonOutsideTable"),
172 IGNLABEL("ReasonStatus1"),
173 IGNLABEL("ReasonStatus2"),
174 IGNLABEL("ReasonStatus3"),
175 IGNLABEL("ReasonStatus4"),
176 IGNLABEL("ReasonStatus5"),
177 IGNLABEL("ReasonStatus6"),
178 IGNLABEL("ReasonStatus7"),
179 IGNLABEL("ReasonStatus8"),
180 IGNLABEL("ReasonStatus9"),
181 IGNLABEL("ReasonStatus10"),
182 IGNLABEL("ReasonStatus11"),
183 IGNLABEL("ReasonStatus12"),
184 IGNLABEL("ReasonStatus13"),
185 IGNLABEL("ReasonStatus14"),
186 IGNLABEL("ReasonStatus15"),
187 IGNLABEL("ReasonStatus16"),
188 IGNLABEL("ReasonStatus17"),
189 IGNLABEL("ReasonStatus18"),
190 IGNLABEL("ReasonStatus19"),
191 "RxMan",
192 "TxMan",
193 "RxRefresh",
194 "TxRefresh",
195 "RxPoll",
196 "TxPoll",
197 "HostRetries",
198 "LostSync-HostReq",
199 "HostTxBytes",
200 "HostRxBytes",
201 "ElapsedUsec",
202 "ElapsedSec",
203 "LostSyncBetterAP",
204 "PrivacyMismatch",
205 "Jammed",
206 "DiscRxNotWepped",
207 "PhyEleMismatch",
208 (char*)-1 };
209#ifndef RUN_AT
210#define RUN_AT(x) (jiffies+(x))
211#endif
212
213
214/* These variables are for insmod, since it seems that the rates
215 can only be set in setup_card. Rates should be a comma separated
216 (no spaces) list of rates (up to 8). */
217
218static int rates[8];
219static int basic_rate;
220static char *ssids[3];
221
222static int io[4];
223static int irq[4];
224
225static
226int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at.
227 0 means no limit. For old cards this was 4 */
228
229static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */
230static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read
231 the bap, needed on some older cards and buses. */
232static int adhoc;
233
234static int probe = 1;
235
236static int proc_uid /* = 0 */;
237
238static int proc_gid /* = 0 */;
239
240static int airo_perm = 0555;
241
242static int proc_perm = 0644;
243
244MODULE_AUTHOR("Benjamin Reed");
245MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
d73ae55a
BN
246cards. Direct support for ISA/PCI/MPI cards and support \
247for PCMCIA when used with airo_cs.");
1da177e4
LT
248MODULE_LICENSE("Dual BSD/GPL");
249MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
250module_param_array(io, int, NULL, 0);
251module_param_array(irq, int, NULL, 0);
252module_param(basic_rate, int, 0);
253module_param_array(rates, int, NULL, 0);
254module_param_array(ssids, charp, NULL, 0);
255module_param(auto_wep, int, 0);
256MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \
257the authentication options until an association is made. The value of \
258auto_wep is number of the wep keys to check. A value of 2 will try using \
259the key at index 0 and index 1.");
260module_param(aux_bap, int, 0);
261MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \
262than seems to work better for older cards with some older buses. Before \
263switching it checks that the switch is needed.");
264module_param(maxencrypt, int, 0);
265MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \
266encryption. Units are in 512kbs. Zero (default) means there is no limit. \
267Older cards used to be limited to 2mbs (4).");
268module_param(adhoc, int, 0);
269MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode.");
270module_param(probe, int, 0);
271MODULE_PARM_DESC(probe, "If zero, the driver won't start the card.");
272
273module_param(proc_uid, int, 0);
274MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to.");
275module_param(proc_gid, int, 0);
276MODULE_PARM_DESC(proc_gid, "The gid that the /proc files will belong to.");
277module_param(airo_perm, int, 0);
278MODULE_PARM_DESC(airo_perm, "The permission bits of /proc/[driver/]aironet.");
279module_param(proc_perm, int, 0);
280MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc");
281
282/* This is a kind of sloppy hack to get this information to OUT4500 and
283 IN4500. I would be extremely interested in the situation where this
284 doesn't work though!!! */
e292c737 285static int do8bitIO /* = 0 */;
1da177e4
LT
286
287/* Return codes */
288#define SUCCESS 0
289#define ERROR -1
290#define NO_PACKET -2
291
292/* Commands */
293#define NOP2 0x0000
294#define MAC_ENABLE 0x0001
295#define MAC_DISABLE 0x0002
296#define CMD_LOSE_SYNC 0x0003 /* Not sure what this does... */
297#define CMD_SOFTRESET 0x0004
298#define HOSTSLEEP 0x0005
299#define CMD_MAGIC_PKT 0x0006
300#define CMD_SETWAKEMASK 0x0007
301#define CMD_READCFG 0x0008
302#define CMD_SETMODE 0x0009
303#define CMD_ALLOCATETX 0x000a
304#define CMD_TRANSMIT 0x000b
305#define CMD_DEALLOCATETX 0x000c
306#define NOP 0x0010
307#define CMD_WORKAROUND 0x0011
308#define CMD_ALLOCATEAUX 0x0020
309#define CMD_ACCESS 0x0021
310#define CMD_PCIBAP 0x0022
311#define CMD_PCIAUX 0x0023
312#define CMD_ALLOCBUF 0x0028
313#define CMD_GETTLV 0x0029
314#define CMD_PUTTLV 0x002a
315#define CMD_DELTLV 0x002b
316#define CMD_FINDNEXTTLV 0x002c
317#define CMD_PSPNODES 0x0030
318#define CMD_SETCW 0x0031
319#define CMD_SETPCF 0x0032
320#define CMD_SETPHYREG 0x003e
321#define CMD_TXTEST 0x003f
322#define MAC_ENABLETX 0x0101
323#define CMD_LISTBSS 0x0103
324#define CMD_SAVECFG 0x0108
325#define CMD_ENABLEAUX 0x0111
326#define CMD_WRITERID 0x0121
327#define CMD_USEPSPNODES 0x0130
328#define MAC_ENABLERX 0x0201
329
330/* Command errors */
331#define ERROR_QUALIF 0x00
332#define ERROR_ILLCMD 0x01
333#define ERROR_ILLFMT 0x02
334#define ERROR_INVFID 0x03
335#define ERROR_INVRID 0x04
336#define ERROR_LARGE 0x05
337#define ERROR_NDISABL 0x06
338#define ERROR_ALLOCBSY 0x07
339#define ERROR_NORD 0x0B
340#define ERROR_NOWR 0x0C
341#define ERROR_INVFIDTX 0x0D
342#define ERROR_TESTACT 0x0E
343#define ERROR_TAGNFND 0x12
344#define ERROR_DECODE 0x20
345#define ERROR_DESCUNAV 0x21
346#define ERROR_BADLEN 0x22
347#define ERROR_MODE 0x80
348#define ERROR_HOP 0x81
349#define ERROR_BINTER 0x82
350#define ERROR_RXMODE 0x83
351#define ERROR_MACADDR 0x84
352#define ERROR_RATES 0x85
353#define ERROR_ORDER 0x86
354#define ERROR_SCAN 0x87
355#define ERROR_AUTH 0x88
356#define ERROR_PSMODE 0x89
357#define ERROR_RTYPE 0x8A
358#define ERROR_DIVER 0x8B
359#define ERROR_SSID 0x8C
360#define ERROR_APLIST 0x8D
361#define ERROR_AUTOWAKE 0x8E
362#define ERROR_LEAP 0x8F
363
364/* Registers */
365#define COMMAND 0x00
366#define PARAM0 0x02
367#define PARAM1 0x04
368#define PARAM2 0x06
369#define STATUS 0x08
370#define RESP0 0x0a
371#define RESP1 0x0c
372#define RESP2 0x0e
373#define LINKSTAT 0x10
374#define SELECT0 0x18
375#define OFFSET0 0x1c
376#define RXFID 0x20
377#define TXALLOCFID 0x22
378#define TXCOMPLFID 0x24
379#define DATA0 0x36
380#define EVSTAT 0x30
381#define EVINTEN 0x32
382#define EVACK 0x34
383#define SWS0 0x28
384#define SWS1 0x2a
385#define SWS2 0x2c
386#define SWS3 0x2e
387#define AUXPAGE 0x3A
388#define AUXOFF 0x3C
389#define AUXDATA 0x3E
390
391#define FID_TX 1
392#define FID_RX 2
393/* Offset into aux memory for descriptors */
394#define AUX_OFFSET 0x800
395/* Size of allocated packets */
396#define PKTSIZE 1840
397#define RIDSIZE 2048
398/* Size of the transmit queue */
399#define MAXTXQ 64
400
401/* BAP selectors */
e292c737
PM
402#define BAP0 0 /* Used for receiving packets */
403#define BAP1 2 /* Used for xmiting packets and working with RIDS */
1da177e4
LT
404
405/* Flags */
406#define COMMAND_BUSY 0x8000
407
408#define BAP_BUSY 0x8000
409#define BAP_ERR 0x4000
410#define BAP_DONE 0x2000
411
412#define PROMISC 0xffff
413#define NOPROMISC 0x0000
414
415#define EV_CMD 0x10
416#define EV_CLEARCOMMANDBUSY 0x4000
417#define EV_RX 0x01
418#define EV_TX 0x02
419#define EV_TXEXC 0x04
420#define EV_ALLOC 0x08
421#define EV_LINK 0x80
422#define EV_AWAKE 0x100
423#define EV_TXCPY 0x400
424#define EV_UNKNOWN 0x800
425#define EV_MIC 0x1000 /* Message Integrity Check Interrupt */
426#define EV_AWAKEN 0x2000
427#define STATUS_INTS (EV_AWAKE|EV_LINK|EV_TXEXC|EV_TX|EV_TXCPY|EV_RX|EV_MIC)
428
429#ifdef CHECK_UNKNOWN_INTS
430#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
431#else
432#define IGNORE_INTS (~STATUS_INTS)
433#endif
434
435/* RID TYPES */
436#define RID_RW 0x20
437
438/* The RIDs */
439#define RID_CAPABILITIES 0xFF00
440#define RID_APINFO 0xFF01
441#define RID_RADIOINFO 0xFF02
442#define RID_UNKNOWN3 0xFF03
443#define RID_RSSI 0xFF04
444#define RID_CONFIG 0xFF10
445#define RID_SSID 0xFF11
446#define RID_APLIST 0xFF12
447#define RID_DRVNAME 0xFF13
448#define RID_ETHERENCAP 0xFF14
449#define RID_WEP_TEMP 0xFF15
450#define RID_WEP_PERM 0xFF16
451#define RID_MODULATION 0xFF17
452#define RID_OPTIONS 0xFF18
453#define RID_ACTUALCONFIG 0xFF20 /*readonly*/
454#define RID_FACTORYCONFIG 0xFF21
455#define RID_UNKNOWN22 0xFF22
456#define RID_LEAPUSERNAME 0xFF23
457#define RID_LEAPPASSWORD 0xFF24
458#define RID_STATUS 0xFF50
459#define RID_BEACON_HST 0xFF51
460#define RID_BUSY_HST 0xFF52
461#define RID_RETRIES_HST 0xFF53
462#define RID_UNKNOWN54 0xFF54
463#define RID_UNKNOWN55 0xFF55
464#define RID_UNKNOWN56 0xFF56
465#define RID_MIC 0xFF57
466#define RID_STATS16 0xFF60
467#define RID_STATS16DELTA 0xFF61
468#define RID_STATS16DELTACLEAR 0xFF62
469#define RID_STATS 0xFF68
470#define RID_STATSDELTA 0xFF69
471#define RID_STATSDELTACLEAR 0xFF6A
472#define RID_ECHOTEST_RID 0xFF70
473#define RID_ECHOTEST_RESULTS 0xFF71
474#define RID_BSSLISTFIRST 0xFF72
475#define RID_BSSLISTNEXT 0xFF73
3c304956
DW
476#define RID_WPA_BSSLISTFIRST 0xFF74
477#define RID_WPA_BSSLISTNEXT 0xFF75
1da177e4
LT
478
479typedef struct {
480 u16 cmd;
481 u16 parm0;
482 u16 parm1;
483 u16 parm2;
484} Cmd;
485
486typedef struct {
487 u16 status;
488 u16 rsp0;
489 u16 rsp1;
490 u16 rsp2;
491} Resp;
492
493/*
494 * Rids and endian-ness: The Rids will always be in cpu endian, since
495 * this all the patches from the big-endian guys end up doing that.
496 * so all rid access should use the read/writeXXXRid routines.
497 */
498
499/* This is redundant for x86 archs, but it seems necessary for ARM */
500#pragma pack(1)
501
502/* This structure came from an email sent to me from an engineer at
503 aironet for inclusion into this driver */
504typedef struct {
4293ea33
AV
505 __le16 len;
506 __le16 kindex;
1da177e4 507 u8 mac[ETH_ALEN];
4293ea33 508 __le16 klen;
1da177e4
LT
509 u8 key[16];
510} WepKeyRid;
511
512/* These structures are from the Aironet's PC4500 Developers Manual */
513typedef struct {
0dd2212f 514 __le16 len;
1da177e4
LT
515 u8 ssid[32];
516} Ssid;
517
518typedef struct {
0dd2212f 519 __le16 len;
1da177e4
LT
520 Ssid ssids[3];
521} SsidRid;
522
523typedef struct {
3eb9b41f
AV
524 __le16 len;
525 __le16 modulation;
526#define MOD_DEFAULT cpu_to_le16(0)
527#define MOD_CCK cpu_to_le16(1)
528#define MOD_MOK cpu_to_le16(2)
1da177e4
LT
529} ModulationRid;
530
531typedef struct {
3eb9b41f
AV
532 __le16 len; /* sizeof(ConfigRid) */
533 __le16 opmode; /* operating mode */
534#define MODE_STA_IBSS cpu_to_le16(0)
535#define MODE_STA_ESS cpu_to_le16(1)
536#define MODE_AP cpu_to_le16(2)
537#define MODE_AP_RPTR cpu_to_le16(3)
538#define MODE_CFG_MASK cpu_to_le16(0xff)
539#define MODE_ETHERNET_HOST cpu_to_le16(0<<8) /* rx payloads converted */
540#define MODE_LLC_HOST cpu_to_le16(1<<8) /* rx payloads left as is */
541#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extenstions */
542#define MODE_AP_INTERFACE cpu_to_le16(1<<10) /* enable ap interface extensions */
543#define MODE_ANTENNA_ALIGN cpu_to_le16(1<<11) /* enable antenna alignment */
544#define MODE_ETHER_LLC cpu_to_le16(1<<12) /* enable ethernet LLC */
545#define MODE_LEAF_NODE cpu_to_le16(1<<13) /* enable leaf node bridge */
546#define MODE_CF_POLLABLE cpu_to_le16(1<<14) /* enable CF pollable */
547#define MODE_MIC cpu_to_le16(1<<15) /* enable MIC */
548 __le16 rmode; /* receive mode */
549#define RXMODE_BC_MC_ADDR cpu_to_le16(0)
550#define RXMODE_BC_ADDR cpu_to_le16(1) /* ignore multicasts */
551#define RXMODE_ADDR cpu_to_le16(2) /* ignore multicast and broadcast */
552#define RXMODE_RFMON cpu_to_le16(3) /* wireless monitor mode */
553#define RXMODE_RFMON_ANYBSS cpu_to_le16(4)
554#define RXMODE_LANMON cpu_to_le16(5) /* lan style monitor -- data packets only */
555#define RXMODE_MASK cpu_to_le16(255)
556#define RXMODE_DISABLE_802_3_HEADER cpu_to_le16(1<<8) /* disables 802.3 header on rx */
557#define RXMODE_FULL_MASK (RXMODE_MASK | RXMODE_DISABLE_802_3_HEADER)
558#define RXMODE_NORMALIZED_RSSI cpu_to_le16(1<<9) /* return normalized RSSI */
559 __le16 fragThresh;
560 __le16 rtsThres;
1da177e4
LT
561 u8 macAddr[ETH_ALEN];
562 u8 rates[8];
3eb9b41f
AV
563 __le16 shortRetryLimit;
564 __le16 longRetryLimit;
565 __le16 txLifetime; /* in kusec */
566 __le16 rxLifetime; /* in kusec */
567 __le16 stationary;
568 __le16 ordering;
569 __le16 u16deviceType; /* for overriding device type */
570 __le16 cfpRate;
571 __le16 cfpDuration;
572 __le16 _reserved1[3];
1da177e4 573 /*---------- Scanning/Associating ----------*/
3eb9b41f
AV
574 __le16 scanMode;
575#define SCANMODE_ACTIVE cpu_to_le16(0)
576#define SCANMODE_PASSIVE cpu_to_le16(1)
577#define SCANMODE_AIROSCAN cpu_to_le16(2)
578 __le16 probeDelay; /* in kusec */
579 __le16 probeEnergyTimeout; /* in kusec */
580 __le16 probeResponseTimeout;
581 __le16 beaconListenTimeout;
582 __le16 joinNetTimeout;
583 __le16 authTimeout;
584 __le16 authType;
585#define AUTH_OPEN cpu_to_le16(0x1)
586#define AUTH_ENCRYPT cpu_to_le16(0x101)
587#define AUTH_SHAREDKEY cpu_to_le16(0x102)
588#define AUTH_ALLOW_UNENCRYPTED cpu_to_le16(0x200)
589 __le16 associationTimeout;
590 __le16 specifiedApTimeout;
591 __le16 offlineScanInterval;
592 __le16 offlineScanDuration;
593 __le16 linkLossDelay;
594 __le16 maxBeaconLostTime;
595 __le16 refreshInterval;
596#define DISABLE_REFRESH cpu_to_le16(0xFFFF)
597 __le16 _reserved1a[1];
1da177e4 598 /*---------- Power save operation ----------*/
3eb9b41f
AV
599 __le16 powerSaveMode;
600#define POWERSAVE_CAM cpu_to_le16(0)
601#define POWERSAVE_PSP cpu_to_le16(1)
602#define POWERSAVE_PSPCAM cpu_to_le16(2)
603 __le16 sleepForDtims;
604 __le16 listenInterval;
605 __le16 fastListenInterval;
606 __le16 listenDecay;
607 __le16 fastListenDelay;
608 __le16 _reserved2[2];
1da177e4 609 /*---------- Ap/Ibss config items ----------*/
3eb9b41f
AV
610 __le16 beaconPeriod;
611 __le16 atimDuration;
612 __le16 hopPeriod;
613 __le16 channelSet;
614 __le16 channel;
615 __le16 dtimPeriod;
616 __le16 bridgeDistance;
617 __le16 radioID;
1da177e4 618 /*---------- Radio configuration ----------*/
3eb9b41f
AV
619 __le16 radioType;
620#define RADIOTYPE_DEFAULT cpu_to_le16(0)
621#define RADIOTYPE_802_11 cpu_to_le16(1)
622#define RADIOTYPE_LEGACY cpu_to_le16(2)
1da177e4
LT
623 u8 rxDiversity;
624 u8 txDiversity;
3eb9b41f 625 __le16 txPower;
1da177e4 626#define TXPOWER_DEFAULT 0
3eb9b41f 627 __le16 rssiThreshold;
1da177e4 628#define RSSI_DEFAULT 0
3eb9b41f
AV
629 __le16 modulation;
630#define PREAMBLE_AUTO cpu_to_le16(0)
631#define PREAMBLE_LONG cpu_to_le16(1)
632#define PREAMBLE_SHORT cpu_to_le16(2)
633 __le16 preamble;
634 __le16 homeProduct;
635 __le16 radioSpecific;
1da177e4
LT
636 /*---------- Aironet Extensions ----------*/
637 u8 nodeName[16];
3eb9b41f
AV
638 __le16 arlThreshold;
639 __le16 arlDecay;
640 __le16 arlDelay;
641 __le16 _reserved4[1];
1da177e4
LT
642 /*---------- Aironet Extensions ----------*/
643 u8 magicAction;
644#define MAGIC_ACTION_STSCHG 1
645#define MAGIC_ACTION_RESUME 2
646#define MAGIC_IGNORE_MCAST (1<<8)
647#define MAGIC_IGNORE_BCAST (1<<9)
648#define MAGIC_SWITCH_TO_PSP (0<<10)
649#define MAGIC_STAY_IN_CAM (1<<10)
650 u8 magicControl;
3eb9b41f 651 __le16 autoWake;
1da177e4
LT
652} ConfigRid;
653
654typedef struct {
329e2c00 655 __le16 len;
1da177e4 656 u8 mac[ETH_ALEN];
329e2c00
AV
657 __le16 mode;
658 __le16 errorCode;
659 __le16 sigQuality;
660 __le16 SSIDlen;
1da177e4
LT
661 char SSID[32];
662 char apName[16];
663 u8 bssid[4][ETH_ALEN];
329e2c00
AV
664 __le16 beaconPeriod;
665 __le16 dimPeriod;
666 __le16 atimDuration;
667 __le16 hopPeriod;
668 __le16 channelSet;
669 __le16 channel;
670 __le16 hopsToBackbone;
671 __le16 apTotalLoad;
672 __le16 generatedLoad;
673 __le16 accumulatedArl;
674 __le16 signalQuality;
675 __le16 currentXmitRate;
676 __le16 apDevExtensions;
677 __le16 normalizedSignalStrength;
678 __le16 shortPreamble;
1da177e4
LT
679 u8 apIP[4];
680 u8 noisePercent; /* Noise percent in last second */
681 u8 noisedBm; /* Noise dBm in last second */
682 u8 noiseAvePercent; /* Noise percent in last minute */
683 u8 noiseAvedBm; /* Noise dBm in last minute */
684 u8 noiseMaxPercent; /* Highest noise percent in last minute */
685 u8 noiseMaxdBm; /* Highest noise dbm in last minute */
329e2c00 686 __le16 load;
1da177e4 687 u8 carrier[4];
329e2c00 688 __le16 assocStatus;
1da177e4
LT
689#define STAT_NOPACKETS 0
690#define STAT_NOCARRIERSET 10
691#define STAT_GOTCARRIERSET 11
692#define STAT_WRONGSSID 20
693#define STAT_BADCHANNEL 25
694#define STAT_BADBITRATES 30
695#define STAT_BADPRIVACY 35
696#define STAT_APFOUND 40
697#define STAT_APREJECTED 50
698#define STAT_AUTHENTICATING 60
699#define STAT_DEAUTHENTICATED 61
700#define STAT_AUTHTIMEOUT 62
701#define STAT_ASSOCIATING 70
702#define STAT_DEASSOCIATED 71
703#define STAT_ASSOCTIMEOUT 72
704#define STAT_NOTAIROAP 73
705#define STAT_ASSOCIATED 80
706#define STAT_LEAPING 90
707#define STAT_LEAPFAILED 91
708#define STAT_LEAPTIMEDOUT 92
709#define STAT_LEAPCOMPLETE 93
710} StatusRid;
711
712typedef struct {
a23ace5f
AV
713 __le16 len;
714 __le16 spacer;
715 __le32 vals[100];
1da177e4
LT
716} StatsRid;
717
718
719typedef struct {
a749716e 720 __le16 len;
1da177e4
LT
721 u8 ap[4][ETH_ALEN];
722} APListRid;
723
724typedef struct {
56d81bd3 725 __le16 len;
1da177e4
LT
726 char oui[3];
727 char zero;
56d81bd3 728 __le16 prodNum;
1da177e4
LT
729 char manName[32];
730 char prodName[16];
731 char prodVer[8];
732 char factoryAddr[ETH_ALEN];
733 char aironetAddr[ETH_ALEN];
56d81bd3
AV
734 __le16 radioType;
735 __le16 country;
1da177e4
LT
736 char callid[ETH_ALEN];
737 char supportedRates[8];
738 char rxDiversity;
739 char txDiversity;
56d81bd3
AV
740 __le16 txPowerLevels[8];
741 __le16 hardVer;
742 __le16 hardCap;
743 __le16 tempRange;
744 __le16 softVer;
745 __le16 softSubVer;
746 __le16 interfaceVer;
747 __le16 softCap;
748 __le16 bootBlockVer;
749 __le16 requiredHard;
750 __le16 extSoftCap;
1da177e4
LT
751} CapabilityRid;
752
3c304956
DW
753
754/* Only present on firmware >= 5.30.17 */
755typedef struct {
17e70491 756 __le16 unknown[4];
3c304956
DW
757 u8 fixed[12]; /* WLAN management frame */
758 u8 iep[624];
759} BSSListRidExtra;
760
1da177e4 761typedef struct {
17e70491
AV
762 __le16 len;
763 __le16 index; /* First is 0 and 0xffff means end of list */
1da177e4
LT
764#define RADIO_FH 1 /* Frequency hopping radio type */
765#define RADIO_DS 2 /* Direct sequence radio type */
766#define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */
17e70491 767 __le16 radioType;
1da177e4
LT
768 u8 bssid[ETH_ALEN]; /* Mac address of the BSS */
769 u8 zero;
770 u8 ssidLen;
771 u8 ssid[32];
17e70491
AV
772 __le16 dBm;
773#define CAP_ESS cpu_to_le16(1<<0)
774#define CAP_IBSS cpu_to_le16(1<<1)
775#define CAP_PRIVACY cpu_to_le16(1<<4)
776#define CAP_SHORTHDR cpu_to_le16(1<<5)
777 __le16 cap;
778 __le16 beaconInterval;
1da177e4
LT
779 u8 rates[8]; /* Same as rates for config rid */
780 struct { /* For frequency hopping only */
17e70491 781 __le16 dwell;
1da177e4
LT
782 u8 hopSet;
783 u8 hopPattern;
784 u8 hopIndex;
785 u8 fill;
786 } fh;
17e70491
AV
787 __le16 dsChannel;
788 __le16 atimWindow;
3c304956
DW
789
790 /* Only present on firmware >= 5.30.17 */
791 BSSListRidExtra extra;
1da177e4
LT
792} BSSListRid;
793
9e75af30
DW
794typedef struct {
795 BSSListRid bss;
796 struct list_head list;
797} BSSListElement;
798
1da177e4
LT
799typedef struct {
800 u8 rssipct;
801 u8 rssidBm;
802} tdsRssiEntry;
803
804typedef struct {
805 u16 len;
806 tdsRssiEntry x[256];
807} tdsRssiRid;
808
809typedef struct {
810 u16 len;
811 u16 state;
812 u16 multicastValid;
813 u8 multicast[16];
814 u16 unicastValid;
815 u8 unicast[16];
816} MICRid;
817
818typedef struct {
593c2b9c 819 __be16 typelen;
1da177e4
LT
820
821 union {
822 u8 snap[8];
823 struct {
824 u8 dsap;
825 u8 ssap;
826 u8 control;
827 u8 orgcode[3];
828 u8 fieldtype[2];
829 } llc;
830 } u;
593c2b9c
AV
831 __be32 mic;
832 __be32 seq;
1da177e4
LT
833} MICBuffer;
834
835typedef struct {
836 u8 da[ETH_ALEN];
837 u8 sa[ETH_ALEN];
838} etherHead;
839
840#pragma pack()
841
842#define TXCTL_TXOK (1<<1) /* report if tx is ok */
843#define TXCTL_TXEX (1<<2) /* report if tx fails */
844#define TXCTL_802_3 (0<<3) /* 802.3 packet */
845#define TXCTL_802_11 (1<<3) /* 802.11 mac packet */
846#define TXCTL_ETHERNET (0<<4) /* payload has ethertype */
847#define TXCTL_LLC (1<<4) /* payload is llc */
848#define TXCTL_RELEASE (0<<5) /* release after completion */
849#define TXCTL_NORELEASE (1<<5) /* on completion returns to host */
850
851#define BUSY_FID 0x10000
852
853#ifdef CISCO_EXT
854#define AIROMAGIC 0xa55a
855/* Warning : SIOCDEVPRIVATE may disapear during 2.5.X - Jean II */
856#ifdef SIOCIWFIRSTPRIV
857#ifdef SIOCDEVPRIVATE
858#define AIROOLDIOCTL SIOCDEVPRIVATE
859#define AIROOLDIDIFC AIROOLDIOCTL + 1
860#endif /* SIOCDEVPRIVATE */
861#else /* SIOCIWFIRSTPRIV */
862#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
863#endif /* SIOCIWFIRSTPRIV */
864/* This may be wrong. When using the new SIOCIWFIRSTPRIV range, we probably
865 * should use only "GET" ioctls (last bit set to 1). "SET" ioctls are root
866 * only and don't return the modified struct ifreq to the application which
867 * is usually a problem. - Jean II */
868#define AIROIOCTL SIOCIWFIRSTPRIV
869#define AIROIDIFC AIROIOCTL + 1
870
871/* Ioctl constants to be used in airo_ioctl.command */
872
873#define AIROGCAP 0 // Capability rid
874#define AIROGCFG 1 // USED A LOT
875#define AIROGSLIST 2 // System ID list
876#define AIROGVLIST 3 // List of specified AP's
877#define AIROGDRVNAM 4 // NOTUSED
878#define AIROGEHTENC 5 // NOTUSED
879#define AIROGWEPKTMP 6
880#define AIROGWEPKNV 7
881#define AIROGSTAT 8
882#define AIROGSTATSC32 9
883#define AIROGSTATSD32 10
884#define AIROGMICRID 11
885#define AIROGMICSTATS 12
886#define AIROGFLAGS 13
887#define AIROGID 14
888#define AIRORRID 15
889#define AIRORSWVERSION 17
890
891/* Leave gap of 40 commands after AIROGSTATSD32 for future */
892
893#define AIROPCAP AIROGSTATSD32 + 40
894#define AIROPVLIST AIROPCAP + 1
895#define AIROPSLIST AIROPVLIST + 1
896#define AIROPCFG AIROPSLIST + 1
897#define AIROPSIDS AIROPCFG + 1
898#define AIROPAPLIST AIROPSIDS + 1
899#define AIROPMACON AIROPAPLIST + 1 /* Enable mac */
900#define AIROPMACOFF AIROPMACON + 1 /* Disable mac */
901#define AIROPSTCLR AIROPMACOFF + 1
902#define AIROPWEPKEY AIROPSTCLR + 1
903#define AIROPWEPKEYNV AIROPWEPKEY + 1
904#define AIROPLEAPPWD AIROPWEPKEYNV + 1
905#define AIROPLEAPUSR AIROPLEAPPWD + 1
906
907/* Flash codes */
908
909#define AIROFLSHRST AIROPWEPKEYNV + 40
910#define AIROFLSHGCHR AIROFLSHRST + 1
911#define AIROFLSHSTFL AIROFLSHGCHR + 1
912#define AIROFLSHPCHR AIROFLSHSTFL + 1
913#define AIROFLPUTBUF AIROFLSHPCHR + 1
914#define AIRORESTART AIROFLPUTBUF + 1
915
916#define FLASHSIZE 32768
917#define AUXMEMSIZE (256 * 1024)
918
919typedef struct aironet_ioctl {
920 unsigned short command; // What to do
921 unsigned short len; // Len of data
922 unsigned short ridnum; // rid number
923 unsigned char __user *data; // d-data
924} aironet_ioctl;
925
62595eb9 926static char swversion[] = "2.1";
1da177e4
LT
927#endif /* CISCO_EXT */
928
929#define NUM_MODULES 2
930#define MIC_MSGLEN_MAX 2400
931#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
15db2763 932#define AIRO_DEF_MTU 2312
1da177e4
LT
933
934typedef struct {
935 u32 size; // size
936 u8 enabled; // MIC enabled or not
937 u32 rxSuccess; // successful packets received
938 u32 rxIncorrectMIC; // pkts dropped due to incorrect MIC comparison
939 u32 rxNotMICed; // pkts dropped due to not being MIC'd
940 u32 rxMICPlummed; // pkts dropped due to not having a MIC plummed
941 u32 rxWrongSequence; // pkts dropped due to sequence number violation
942 u32 reserve[32];
943} mic_statistics;
944
945typedef struct {
946 u32 coeff[((EMMH32_MSGLEN_MAX)+3)>>2];
947 u64 accum; // accumulated mic, reduced to u32 in final()
948 int position; // current position (byte offset) in message
949 union {
950 u8 d8[4];
593c2b9c 951 __be32 d32;
1da177e4
LT
952 } part; // saves partial message word across update() calls
953} emmh32_context;
954
955typedef struct {
956 emmh32_context seed; // Context - the seed
957 u32 rx; // Received sequence number
958 u32 tx; // Tx sequence number
959 u32 window; // Start of window
960 u8 valid; // Flag to say if context is valid or not
961 u8 key[16];
962} miccntx;
963
964typedef struct {
965 miccntx mCtx; // Multicast context
966 miccntx uCtx; // Unicast context
967} mic_module;
968
969typedef struct {
970 unsigned int rid: 16;
971 unsigned int len: 15;
972 unsigned int valid: 1;
973 dma_addr_t host_addr;
974} Rid;
975
976typedef struct {
977 unsigned int offset: 15;
978 unsigned int eoc: 1;
979 unsigned int len: 15;
980 unsigned int valid: 1;
981 dma_addr_t host_addr;
982} TxFid;
983
f55d4517
DW
984struct rx_hdr {
985 __le16 status, len;
986 u8 rssi[2];
987 u8 rate;
988 u8 freq;
989 __le16 tmp[4];
990} __attribute__ ((packed));
991
1da177e4
LT
992typedef struct {
993 unsigned int ctl: 15;
994 unsigned int rdy: 1;
995 unsigned int len: 15;
996 unsigned int valid: 1;
997 dma_addr_t host_addr;
998} RxFid;
999
1000/*
1001 * Host receive descriptor
1002 */
1003typedef struct {
1004 unsigned char __iomem *card_ram_off; /* offset into card memory of the
1005 desc */
1006 RxFid rx_desc; /* card receive descriptor */
1007 char *virtual_host_addr; /* virtual address of host receive
1008 buffer */
1009 int pending;
1010} HostRxDesc;
1011
1012/*
1013 * Host transmit descriptor
1014 */
1015typedef struct {
1016 unsigned char __iomem *card_ram_off; /* offset into card memory of the
1017 desc */
1018 TxFid tx_desc; /* card transmit descriptor */
1019 char *virtual_host_addr; /* virtual address of host receive
1020 buffer */
1021 int pending;
1022} HostTxDesc;
1023
1024/*
1025 * Host RID descriptor
1026 */
1027typedef struct {
1028 unsigned char __iomem *card_ram_off; /* offset into card memory of the
1029 descriptor */
1030 Rid rid_desc; /* card RID descriptor */
1031 char *virtual_host_addr; /* virtual address of host receive
1032 buffer */
1033} HostRidDesc;
1034
1035typedef struct {
1036 u16 sw0;
1037 u16 sw1;
1038 u16 status;
1039 u16 len;
1040#define HOST_SET (1 << 0)
1041#define HOST_INT_TX (1 << 1) /* Interrupt on successful TX */
1042#define HOST_INT_TXERR (1 << 2) /* Interrupt on unseccessful TX */
1043#define HOST_LCC_PAYLOAD (1 << 4) /* LLC payload, 0 = Ethertype */
1044#define HOST_DONT_RLSE (1 << 5) /* Don't release buffer when done */
1045#define HOST_DONT_RETRY (1 << 6) /* Don't retry trasmit */
1046#define HOST_CLR_AID (1 << 7) /* clear AID failure */
1047#define HOST_RTS (1 << 9) /* Force RTS use */
1048#define HOST_SHORT (1 << 10) /* Do short preamble */
1049 u16 ctl;
1050 u16 aid;
1051 u16 retries;
1052 u16 fill;
1053} TxCtlHdr;
1054
1055typedef struct {
1056 u16 ctl;
1057 u16 duration;
1058 char addr1[6];
1059 char addr2[6];
1060 char addr3[6];
1061 u16 seq;
1062 char addr4[6];
1063} WifiHdr;
1064
1065
1066typedef struct {
1067 TxCtlHdr ctlhdr;
1068 u16 fill1;
1069 u16 fill2;
1070 WifiHdr wifihdr;
1071 u16 gaplen;
1072 u16 status;
1073} WifiCtlHdr;
1074
ff1d2767 1075static WifiCtlHdr wifictlhdr8023 = {
1da177e4
LT
1076 .ctlhdr = {
1077 .ctl = HOST_DONT_RLSE,
1078 }
1079};
1080
1da177e4
LT
1081// A few details needed for WEP (Wireless Equivalent Privacy)
1082#define MAX_KEY_SIZE 13 // 128 (?) bits
1083#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP
1084typedef struct wep_key_t {
1085 u16 len;
1086 u8 key[16]; /* 40-bit and 104-bit keys */
1087} wep_key_t;
1088
1089/* Backward compatibility */
1090#ifndef IW_ENCODE_NOKEY
1091#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
1092#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
1093#endif /* IW_ENCODE_NOKEY */
1094
1095/* List of Wireless Handlers (new API) */
1096static const struct iw_handler_def airo_handler_def;
1da177e4
LT
1097
1098static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
1099
1100struct airo_info;
1101
1102static int get_dec_u16( char *buffer, int *start, int limit );
1103static void OUT4500( struct airo_info *, u16 register, u16 value );
1104static unsigned short IN4500( struct airo_info *, u16 register );
1105static u16 setup_card(struct airo_info*, u8 *mac, int lock);
175ec1a1 1106static int enable_MAC(struct airo_info *ai, int lock);
1da177e4
LT
1107static void disable_MAC(struct airo_info *ai, int lock);
1108static void enable_interrupts(struct airo_info*);
1109static void disable_interrupts(struct airo_info*);
1110static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
1111static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
b8c06bc1 1112static int aux_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen,
1da177e4 1113 int whichbap);
b8c06bc1 1114static int fast_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen,
1da177e4 1115 int whichbap);
b8c06bc1 1116static int bap_write(struct airo_info*, const __le16 *pu16Src, int bytelen,
1da177e4
LT
1117 int whichbap);
1118static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);
1119static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);
1120static int PC4500_writerid(struct airo_info*, u16 rid, const void
1121 *pBuf, int len, int lock);
1122static int do_writerid( struct airo_info*, u16 rid, const void *rid_data,
1123 int len, int dummy );
1124static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);
1125static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);
1126static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
1127
1128static int mpi_send_packet (struct net_device *dev);
1129static void mpi_unmap_card(struct pci_dev *pci);
1130static void mpi_receive_802_3(struct airo_info *ai);
1131static void mpi_receive_802_11(struct airo_info *ai);
1132static int waitbusy (struct airo_info *ai);
1133
7d12e780 1134static irqreturn_t airo_interrupt( int irq, void* dev_id);
1da177e4
LT
1135static int airo_thread(void *data);
1136static void timer_func( struct net_device *dev );
1137static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
ff1d2767 1138static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
1da177e4 1139static void airo_read_wireless_stats (struct airo_info *local);
1da177e4
LT
1140#ifdef CISCO_EXT
1141static int readrids(struct net_device *dev, aironet_ioctl *comp);
1142static int writerids(struct net_device *dev, aironet_ioctl *comp);
ff1d2767 1143static int flashcard(struct net_device *dev, aironet_ioctl *comp);
1da177e4 1144#endif /* CISCO_EXT */
1da177e4
LT
1145static void micinit(struct airo_info *ai);
1146static int micsetup(struct airo_info *ai);
1147static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
1148static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
1149
41480af2
DW
1150static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
1151static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
1152
9e75af30
DW
1153static void airo_networks_free(struct airo_info *ai);
1154
1da177e4 1155struct airo_info {
1da177e4 1156 struct net_device *dev;
af5b5c9a 1157 struct list_head dev_list;
1da177e4
LT
1158 /* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we
1159 use the high bit to mark whether it is in use. */
1160#define MAX_FIDS 6
1161#define MPI_MAX_FIDS 1
1162 int fids[MAX_FIDS];
1163 ConfigRid config;
1164 char keyindex; // Used with auto wep
1165 char defindex; // Used with auto wep
1166 struct proc_dir_entry *proc_entry;
1167 spinlock_t aux_lock;
1da177e4
LT
1168#define FLAG_RADIO_OFF 0 /* User disabling of MAC */
1169#define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */
1170#define FLAG_RADIO_MASK 0x03
1171#define FLAG_ENABLED 2
1172#define FLAG_ADHOC 3 /* Needed by MIC */
1173#define FLAG_MIC_CAPABLE 4
1174#define FLAG_UPDATE_MULTI 5
1175#define FLAG_UPDATE_UNI 6
1176#define FLAG_802_11 7
3c304956 1177#define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */
1da177e4
LT
1178#define FLAG_PENDING_XMIT 9
1179#define FLAG_PENDING_XMIT11 10
1180#define FLAG_MPI 11
1181#define FLAG_REGISTERED 12
1182#define FLAG_COMMIT 13
1183#define FLAG_RESET 14
1184#define FLAG_FLASHING 15
3c304956
DW
1185#define FLAG_WPA_CAPABLE 16
1186 unsigned long flags;
1187#define JOB_DIE 0
1188#define JOB_XMIT 1
1189#define JOB_XMIT11 2
1190#define JOB_STATS 3
1191#define JOB_PROMISC 4
1192#define JOB_MIC 5
1193#define JOB_EVENT 6
1194#define JOB_AUTOWEP 7
1195#define JOB_WSTATS 8
1196#define JOB_SCAN_RESULTS 9
1197 unsigned long jobs;
b8c06bc1 1198 int (*bap_read)(struct airo_info*, __le16 *pu16Dst, int bytelen,
1da177e4
LT
1199 int whichbap);
1200 unsigned short *flash;
1201 tdsRssiEntry *rssi;
3b4c7d64
SB
1202 struct task_struct *list_bss_task;
1203 struct task_struct *airo_thread_task;
1da177e4 1204 struct semaphore sem;
1da177e4 1205 wait_queue_head_t thr_wait;
1da177e4
LT
1206 unsigned long expires;
1207 struct {
1208 struct sk_buff *skb;
1209 int fid;
1210 } xmit, xmit11;
1211 struct net_device *wifidev;
1da177e4 1212 struct iw_statistics wstats; // wireless stats
9e75af30 1213 unsigned long scan_timeout; /* Time scan should be read */
1da177e4
LT
1214 struct iw_spy_data spy_data;
1215 struct iw_public_data wireless_data;
1da177e4 1216 /* MIC stuff */
f12cc209 1217 struct crypto_cipher *tfm;
1da177e4
LT
1218 mic_module mod[2];
1219 mic_statistics micstats;
1da177e4
LT
1220 HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
1221 HostTxDesc txfids[MPI_MAX_FIDS];
1222 HostRidDesc config_desc;
1223 unsigned long ridbus; // phys addr of config_desc
1224 struct sk_buff_head txq;// tx queue used by mpi350 code
1225 struct pci_dev *pci;
1226 unsigned char __iomem *pcimem;
1227 unsigned char __iomem *pciaux;
1228 unsigned char *shared;
1229 dma_addr_t shared_dma;
1cc68ae0 1230 pm_message_t power;
1da177e4
LT
1231 SsidRid *SSID;
1232 APListRid *APList;
1233#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
1234 char proc_name[IFNAMSIZ];
9e75af30 1235
3c304956
DW
1236 /* WPA-related stuff */
1237 unsigned int bssListFirst;
1238 unsigned int bssListNext;
1239 unsigned int bssListRidLen;
1240
9e75af30
DW
1241 struct list_head network_list;
1242 struct list_head network_free_list;
1243 BSSListElement *networks;
1da177e4
LT
1244};
1245
b8c06bc1
AV
1246static inline int bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen,
1247 int whichbap)
1248{
1da177e4
LT
1249 return ai->bap_read(ai, pu16Dst, bytelen, whichbap);
1250}
1251
1252static int setup_proc_entry( struct net_device *dev,
1253 struct airo_info *apriv );
1254static int takedown_proc_entry( struct net_device *dev,
1255 struct airo_info *apriv );
1256
ff1d2767
JM
1257static int cmdreset(struct airo_info *ai);
1258static int setflashmode (struct airo_info *ai);
1259static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
1260static int flashputbuf(struct airo_info *ai);
1261static int flashrestart(struct airo_info *ai,struct net_device *dev);
1262
934d8bf1 1263#define airo_print(type, name, fmt, args...) \
1138c37b 1264 printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
934d8bf1
DW
1265
1266#define airo_print_info(name, fmt, args...) \
1267 airo_print(KERN_INFO, name, fmt, ##args)
1268
1269#define airo_print_dbg(name, fmt, args...) \
1270 airo_print(KERN_DEBUG, name, fmt, ##args)
1271
1272#define airo_print_warn(name, fmt, args...) \
1273 airo_print(KERN_WARNING, name, fmt, ##args)
1274
1275#define airo_print_err(name, fmt, args...) \
1276 airo_print(KERN_ERR, name, fmt, ##args)
1277
faf3994a 1278#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash)
934d8bf1 1279
1da177e4
LT
1280/***********************************************************************
1281 * MIC ROUTINES *
1282 ***********************************************************************
1283 */
1284
1285static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
1286static void MoveWindow(miccntx *context, u32 micSeq);
f12cc209
HX
1287static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
1288 struct crypto_cipher *tfm);
ff1d2767
JM
1289static void emmh32_init(emmh32_context *context);
1290static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
1291static void emmh32_final(emmh32_context *context, u8 digest[4]);
1292static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
1da177e4
LT
1293
1294/* micinit - Initialize mic seed */
1295
1296static void micinit(struct airo_info *ai)
1297{
1298 MICRid mic_rid;
1299
3c304956 1300 clear_bit(JOB_MIC, &ai->jobs);
1da177e4
LT
1301 PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
1302 up(&ai->sem);
1303
1304 ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;
1305
1306 if (ai->micstats.enabled) {
1307 /* Key must be valid and different */
1308 if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||
1309 (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,
1310 sizeof(ai->mod[0].mCtx.key)) != 0))) {
1311 /* Age current mic Context */
1312 memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));
1313 /* Initialize new context */
1314 memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));
1315 ai->mod[0].mCtx.window = 33; //Window always points to the middle
1316 ai->mod[0].mCtx.rx = 0; //Rx Sequence numbers
1317 ai->mod[0].mCtx.tx = 0; //Tx sequence numbers
1318 ai->mod[0].mCtx.valid = 1; //Key is now valid
1319
1320 /* Give key to mic seed */
1321 emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);
1322 }
1323
1324 /* Key must be valid and different */
1325 if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid ||
1326 (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,
1327 sizeof(ai->mod[0].uCtx.key)) != 0))) {
1328 /* Age current mic Context */
1329 memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));
1330 /* Initialize new context */
1331 memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));
1332
1333 ai->mod[0].uCtx.window = 33; //Window always points to the middle
1334 ai->mod[0].uCtx.rx = 0; //Rx Sequence numbers
1335 ai->mod[0].uCtx.tx = 0; //Tx sequence numbers
1336 ai->mod[0].uCtx.valid = 1; //Key is now valid
1337
1338 //Give key to mic seed
1339 emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);
1340 }
1341 } else {
1342 /* So next time we have a valid key and mic is enabled, we will update
1343 * the sequence number if the key is the same as before.
1344 */
1345 ai->mod[0].uCtx.valid = 0;
1346 ai->mod[0].mCtx.valid = 0;
1347 }
1348}
1349
1350/* micsetup - Get ready for business */
1351
1352static int micsetup(struct airo_info *ai) {
1353 int i;
1354
1355 if (ai->tfm == NULL)
f12cc209 1356 ai->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
1da177e4 1357
f12cc209 1358 if (IS_ERR(ai->tfm)) {
934d8bf1 1359 airo_print_err(ai->dev->name, "failed to load transform for AES");
f12cc209 1360 ai->tfm = NULL;
1da177e4
LT
1361 return ERROR;
1362 }
1363
1364 for (i=0; i < NUM_MODULES; i++) {
1365 memset(&ai->mod[i].mCtx,0,sizeof(miccntx));
1366 memset(&ai->mod[i].uCtx,0,sizeof(miccntx));
1367 }
1368 return SUCCESS;
1369}
1370
ff1d2767 1371static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
1da177e4
LT
1372
1373/*===========================================================================
1374 * Description: Mic a packet
1375 *
1376 * Inputs: etherHead * pointer to an 802.3 frame
1377 *
1378 * Returns: BOOLEAN if successful, otherwise false.
1379 * PacketTxLen will be updated with the mic'd packets size.
1380 *
1381 * Caveats: It is assumed that the frame buffer will already
1382 * be big enough to hold the largets mic message possible.
1383 * (No memory allocation is done here).
1384 *
1385 * Author: sbraneky (10/15/01)
1386 * Merciless hacks by rwilcher (1/14/02)
1387 */
1388
1389static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, int payLen)
1390{
1391 miccntx *context;
1392
1393 // Determine correct context
1394 // If not adhoc, always use unicast key
1395
1396 if (test_bit(FLAG_ADHOC, &ai->flags) && (frame->da[0] & 0x1))
1397 context = &ai->mod[0].mCtx;
1398 else
1399 context = &ai->mod[0].uCtx;
1400
1401 if (!context->valid)
1402 return ERROR;
1403
1404 mic->typelen = htons(payLen + 16); //Length of Mic'd packet
1405
1406 memcpy(&mic->u.snap, micsnap, sizeof(micsnap)); // Add Snap
1407
1408 // Add Tx sequence
1409 mic->seq = htonl(context->tx);
1410 context->tx += 2;
1411
1412 emmh32_init(&context->seed); // Mic the packet
1413 emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA
1414 emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap
1415 emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ
1416 emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload
1417 emmh32_final(&context->seed, (u8*)&mic->mic);
1418
1419 /* New Type/length ?????????? */
1420 mic->typelen = 0; //Let NIC know it could be an oversized packet
1421 return SUCCESS;
1422}
1423
1424typedef enum {
1425 NONE,
1426 NOMIC,
1427 NOMICPLUMMED,
1428 SEQUENCE,
1429 INCORRECTMIC,
1430} mic_error;
1431
1432/*===========================================================================
1433 * Description: Decapsulates a MIC'd packet and returns the 802.3 packet
1434 * (removes the MIC stuff) if packet is a valid packet.
1435 *
1436 * Inputs: etherHead pointer to the 802.3 packet
1437 *
1438 * Returns: BOOLEAN - TRUE if packet should be dropped otherwise FALSE
1439 *
1440 * Author: sbraneky (10/15/01)
1441 * Merciless hacks by rwilcher (1/14/02)
1442 *---------------------------------------------------------------------------
1443 */
1444
1445static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *eth, u16 payLen)
1446{
1447 int i;
1448 u32 micSEQ;
1449 miccntx *context;
1450 u8 digest[4];
1451 mic_error micError = NONE;
1452
1453 // Check if the packet is a Mic'd packet
1454
1455 if (!ai->micstats.enabled) {
1456 //No Mic set or Mic OFF but we received a MIC'd packet.
1457 if (memcmp ((u8*)eth + 14, micsnap, sizeof(micsnap)) == 0) {
1458 ai->micstats.rxMICPlummed++;
1459 return ERROR;
1460 }
1461 return SUCCESS;
1462 }
1463
1464 if (ntohs(mic->typelen) == 0x888E)
1465 return SUCCESS;
1466
1467 if (memcmp (mic->u.snap, micsnap, sizeof(micsnap)) != 0) {
1468 // Mic enabled but packet isn't Mic'd
1469 ai->micstats.rxMICPlummed++;
1470 return ERROR;
1471 }
1472
1473 micSEQ = ntohl(mic->seq); //store SEQ as CPU order
1474
1475 //At this point we a have a mic'd packet and mic is enabled
1476 //Now do the mic error checking.
1477
1478 //Receive seq must be odd
1479 if ( (micSEQ & 1) == 0 ) {
1480 ai->micstats.rxWrongSequence++;
1481 return ERROR;
1482 }
1483
1484 for (i = 0; i < NUM_MODULES; i++) {
1485 int mcast = eth->da[0] & 1;
1486 //Determine proper context
1487 context = mcast ? &ai->mod[i].mCtx : &ai->mod[i].uCtx;
1488
1489 //Make sure context is valid
1490 if (!context->valid) {
1491 if (i == 0)
1492 micError = NOMICPLUMMED;
1493 continue;
1494 }
1495 //DeMic it
1496
1497 if (!mic->typelen)
1498 mic->typelen = htons(payLen + sizeof(MICBuffer) - 2);
1499
1500 emmh32_init(&context->seed);
1501 emmh32_update(&context->seed, eth->da, ETH_ALEN*2);
1502 emmh32_update(&context->seed, (u8 *)&mic->typelen, sizeof(mic->typelen)+sizeof(mic->u.snap));
1503 emmh32_update(&context->seed, (u8 *)&mic->seq,sizeof(mic->seq));
1504 emmh32_update(&context->seed, eth->da + ETH_ALEN*2,payLen);
1505 //Calculate MIC
1506 emmh32_final(&context->seed, digest);
1507
1508 if (memcmp(digest, &mic->mic, 4)) { //Make sure the mics match
1509 //Invalid Mic
1510 if (i == 0)
1511 micError = INCORRECTMIC;
1512 continue;
1513 }
1514
1515 //Check Sequence number if mics pass
1516 if (RxSeqValid(ai, context, mcast, micSEQ) == SUCCESS) {
1517 ai->micstats.rxSuccess++;
1518 return SUCCESS;
1519 }
1520 if (i == 0)
1521 micError = SEQUENCE;
1522 }
1523
1524 // Update statistics
1525 switch (micError) {
1526 case NOMICPLUMMED: ai->micstats.rxMICPlummed++; break;
1527 case SEQUENCE: ai->micstats.rxWrongSequence++; break;
1528 case INCORRECTMIC: ai->micstats.rxIncorrectMIC++; break;
1529 case NONE: break;
1530 case NOMIC: break;
1531 }
1532 return ERROR;
1533}
1534
1535/*===========================================================================
1536 * Description: Checks the Rx Seq number to make sure it is valid
1537 * and hasn't already been received
1538 *
1539 * Inputs: miccntx - mic context to check seq against
1540 * micSeq - the Mic seq number
1541 *
1542 * Returns: TRUE if valid otherwise FALSE.
1543 *
1544 * Author: sbraneky (10/15/01)
1545 * Merciless hacks by rwilcher (1/14/02)
1546 *---------------------------------------------------------------------------
1547 */
1548
1549static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq)
1550{
1551 u32 seq,index;
1552
1553 //Allow for the ap being rebooted - if it is then use the next
1554 //sequence number of the current sequence number - might go backwards
1555
1556 if (mcast) {
1557 if (test_bit(FLAG_UPDATE_MULTI, &ai->flags)) {
1558 clear_bit (FLAG_UPDATE_MULTI, &ai->flags);
1559 context->window = (micSeq > 33) ? micSeq : 33;
1560 context->rx = 0; // Reset rx
1561 }
1562 } else if (test_bit(FLAG_UPDATE_UNI, &ai->flags)) {
1563 clear_bit (FLAG_UPDATE_UNI, &ai->flags);
1564 context->window = (micSeq > 33) ? micSeq : 33; // Move window
1565 context->rx = 0; // Reset rx
1566 }
1567
1568 //Make sequence number relative to START of window
1569 seq = micSeq - (context->window - 33);
1570
1571 //Too old of a SEQ number to check.
1572 if ((s32)seq < 0)
1573 return ERROR;
1574
1575 if ( seq > 64 ) {
1576 //Window is infinite forward
1577 MoveWindow(context,micSeq);
1578 return SUCCESS;
1579 }
1580
1581 // We are in the window. Now check the context rx bit to see if it was already sent
1582 seq >>= 1; //divide by 2 because we only have odd numbers
1583 index = 1 << seq; //Get an index number
1584
1585 if (!(context->rx & index)) {
1586 //micSEQ falls inside the window.
1587 //Add seqence number to the list of received numbers.
1588 context->rx |= index;
1589
1590 MoveWindow(context,micSeq);
1591
1592 return SUCCESS;
1593 }
1594 return ERROR;
1595}
1596
1597static void MoveWindow(miccntx *context, u32 micSeq)
1598{
1599 u32 shift;
1600
1601 //Move window if seq greater than the middle of the window
1602 if (micSeq > context->window) {
1603 shift = (micSeq - context->window) >> 1;
1604
1605 //Shift out old
1606 if (shift < 32)
1607 context->rx >>= shift;
1608 else
1609 context->rx = 0;
1610
1611 context->window = micSeq; //Move window
1612 }
1613}
1614
1615/*==============================================*/
1616/*========== EMMH ROUTINES ====================*/
1617/*==============================================*/
1618
1619/* mic accumulate */
1620#define MIC_ACCUM(val) \
1621 context->accum += (u64)(val) * context->coeff[coeff_position++];
1622
1623static unsigned char aes_counter[16];
1624
1625/* expand the key to fill the MMH coefficient array */
f12cc209
HX
1626static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
1627 struct crypto_cipher *tfm)
1da177e4
LT
1628{
1629 /* take the keying material, expand if necessary, truncate at 16-bytes */
1630 /* run through AES counter mode to generate context->coeff[] */
1631
1632 int i,j;
1633 u32 counter;
1634 u8 *cipher, plain[16];
1da177e4
LT
1635
1636 crypto_cipher_setkey(tfm, pkey, 16);
1637 counter = 0;
e7c04fd3 1638 for (i = 0; i < ARRAY_SIZE(context->coeff); ) {
1da177e4
LT
1639 aes_counter[15] = (u8)(counter >> 0);
1640 aes_counter[14] = (u8)(counter >> 8);
1641 aes_counter[13] = (u8)(counter >> 16);
1642 aes_counter[12] = (u8)(counter >> 24);
1643 counter++;
1644 memcpy (plain, aes_counter, 16);
f12cc209
HX
1645 crypto_cipher_encrypt_one(tfm, plain, plain);
1646 cipher = plain;
e7c04fd3 1647 for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
593c2b9c 1648 context->coeff[i++] = ntohl(*(__be32 *)&cipher[j]);
1da177e4
LT
1649 j += 4;
1650 }
1651 }
1652}
1653
1654/* prepare for calculation of a new mic */
ff1d2767 1655static void emmh32_init(emmh32_context *context)
1da177e4
LT
1656{
1657 /* prepare for new mic calculation */
1658 context->accum = 0;
1659 context->position = 0;
1660}
1661
1662/* add some bytes to the mic calculation */
ff1d2767 1663static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
1da177e4
LT
1664{
1665 int coeff_position, byte_position;
1666
1667 if (len == 0) return;
1668
1669 coeff_position = context->position >> 2;
1670
1671 /* deal with partial 32-bit word left over from last update */
1672 byte_position = context->position & 3;
1673 if (byte_position) {
1674 /* have a partial word in part to deal with */
1675 do {
1676 if (len == 0) return;
1677 context->part.d8[byte_position++] = *pOctets++;
1678 context->position++;
1679 len--;
1680 } while (byte_position < 4);
593c2b9c 1681 MIC_ACCUM(ntohl(context->part.d32));
1da177e4
LT
1682 }
1683
1684 /* deal with full 32-bit words */
1685 while (len >= 4) {
593c2b9c 1686 MIC_ACCUM(ntohl(*(__be32 *)pOctets));
1da177e4
LT
1687 context->position += 4;
1688 pOctets += 4;
1689 len -= 4;
1690 }
1691
1692 /* deal with partial 32-bit word that will be left over from this update */
1693 byte_position = 0;
1694 while (len > 0) {
1695 context->part.d8[byte_position++] = *pOctets++;
1696 context->position++;
1697 len--;
1698 }
1699}
1700
1701/* mask used to zero empty bytes for final partial word */
1702static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
1703
1704/* calculate the mic */
ff1d2767 1705static void emmh32_final(emmh32_context *context, u8 digest[4])
1da177e4
LT
1706{
1707 int coeff_position, byte_position;
1708 u32 val;
1709
1710 u64 sum, utmp;
1711 s64 stmp;
1712
1713 coeff_position = context->position >> 2;
1714
1715 /* deal with partial 32-bit word left over from last update */
1716 byte_position = context->position & 3;
1717 if (byte_position) {
1718 /* have a partial word in part to deal with */
593c2b9c 1719 val = ntohl(context->part.d32);
1da177e4
LT
1720 MIC_ACCUM(val & mask32[byte_position]); /* zero empty bytes */
1721 }
1722
1723 /* reduce the accumulated u64 to a 32-bit MIC */
1724 sum = context->accum;
1725 stmp = (sum & 0xffffffffLL) - ((sum >> 32) * 15);
1726 utmp = (stmp & 0xffffffffLL) - ((stmp >> 32) * 15);
1727 sum = utmp & 0xffffffffLL;
1728 if (utmp > 0x10000000fLL)
1729 sum -= 15;
1730
1731 val = (u32)sum;
1732 digest[0] = (val>>24) & 0xFF;
1733 digest[1] = (val>>16) & 0xFF;
1734 digest[2] = (val>>8) & 0xFF;
1735 digest[3] = val & 0xFF;
1736}
1da177e4
LT
1737
1738static int readBSSListRid(struct airo_info *ai, int first,
17e70491
AV
1739 BSSListRid *list)
1740{
3c304956
DW
1741 Cmd cmd;
1742 Resp rsp;
1da177e4
LT
1743
1744 if (first == 1) {
3c304956
DW
1745 if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
1746 memset(&cmd, 0, sizeof(cmd));
1747 cmd.cmd=CMD_LISTBSS;
1748 if (down_interruptible(&ai->sem))
1749 return -ERESTARTSYS;
3b4c7d64 1750 ai->list_bss_task = current;
3c304956
DW
1751 issuecommand(ai, &cmd, &rsp);
1752 up(&ai->sem);
1753 /* Let the command take effect */
3b4c7d64
SB
1754 schedule_timeout_uninterruptible(3 * HZ);
1755 ai->list_bss_task = NULL;
3c304956 1756 }
17e70491 1757 return PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
3c304956 1758 list, ai->bssListRidLen, 1);
1da177e4
LT
1759}
1760
4293ea33
AV
1761static int readWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int temp, int lock)
1762{
1763 return PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,
1da177e4 1764 wkr, sizeof(*wkr), lock);
1da177e4 1765}
1da177e4 1766
4293ea33
AV
1767static int writeWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int perm, int lock)
1768{
1769 int rc;
1770 rc = PC4500_writerid(ai, RID_WEP_TEMP, wkr, sizeof(*wkr), lock);
1771 if (rc!=SUCCESS)
1772 airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
1da177e4 1773 if (perm) {
4293ea33
AV
1774 rc = PC4500_writerid(ai, RID_WEP_PERM, wkr, sizeof(*wkr), lock);
1775 if (rc!=SUCCESS)
934d8bf1 1776 airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
1da177e4
LT
1777 }
1778 return rc;
1779}
1780
0dd2212f
AV
1781static int readSsidRid(struct airo_info*ai, SsidRid *ssidr)
1782{
1783 return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
1da177e4 1784}
1da177e4 1785
0dd2212f
AV
1786static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock)
1787{
1788 return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock);
1da177e4 1789}
0dd2212f 1790
3eb9b41f
AV
1791static int readConfigRid(struct airo_info *ai, int lock)
1792{
1da177e4 1793 int rc;
1da177e4
LT
1794 ConfigRid cfg;
1795
1796 if (ai->config.len)
1797 return SUCCESS;
1798
1799 rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock);
1800 if (rc != SUCCESS)
1801 return rc;
1802
1da177e4
LT
1803 ai->config = cfg;
1804 return SUCCESS;
1805}
3eb9b41f
AV
1806
1807static inline void checkThrottle(struct airo_info *ai)
1808{
1da177e4
LT
1809 int i;
1810/* Old hardware had a limit on encryption speed */
1811 if (ai->config.authType != AUTH_OPEN && maxencrypt) {
1812 for(i=0; i<8; i++) {
1813 if (ai->config.rates[i] > maxencrypt) {
1814 ai->config.rates[i] = 0;
1815 }
1816 }
1817 }
1818}
3eb9b41f
AV
1819
1820static int writeConfigRid(struct airo_info *ai, int lock)
1821{
1da177e4
LT
1822 ConfigRid cfgr;
1823
1824 if (!test_bit (FLAG_COMMIT, &ai->flags))
1825 return SUCCESS;
1826
1827 clear_bit (FLAG_COMMIT, &ai->flags);
1828 clear_bit (FLAG_RESET, &ai->flags);
1829 checkThrottle(ai);
1830 cfgr = ai->config;
1831
3eb9b41f 1832 if ((cfgr.opmode & MODE_CFG_MASK) == MODE_STA_IBSS)
1da177e4
LT
1833 set_bit(FLAG_ADHOC, &ai->flags);
1834 else
1835 clear_bit(FLAG_ADHOC, &ai->flags);
1836
1da177e4
LT
1837 return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock);
1838}
1da177e4 1839
329e2c00
AV
1840static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock)
1841{
1842 return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
1da177e4 1843}
a749716e
AV
1844
1845static int readAPListRid(struct airo_info *ai, APListRid *aplr)
1846{
1847 return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
1da177e4 1848}
a749716e
AV
1849
1850static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock)
1851{
1852 return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
1da177e4 1853}
1da177e4 1854
56d81bd3
AV
1855static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock)
1856{
1857 return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
1da177e4 1858}
1da177e4 1859
a23ace5f
AV
1860static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
1861{
1862 return PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);
1da177e4
LT
1863}
1864
1c2b7db8
MS
1865static void try_auto_wep(struct airo_info *ai)
1866{
1867 if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
1868 ai->expires = RUN_AT(3*HZ);
1869 wake_up_interruptible(&ai->thr_wait);
1870 }
1871}
1872
1da177e4 1873static int airo_open(struct net_device *dev) {
faf3994a 1874 struct airo_info *ai = dev->ml_priv;
1c2b7db8 1875 int rc = 0;
1da177e4 1876
1c2b7db8 1877 if (test_bit(FLAG_FLASHING, &ai->flags))
1da177e4
LT
1878 return -EIO;
1879
1880 /* Make sure the card is configured.
1881 * Wireless Extensions may postpone config changes until the card
1882 * is open (to pipeline changes and speed-up card setup). If
1883 * those changes are not yet commited, do it now - Jean II */
1c2b7db8
MS
1884 if (test_bit(FLAG_COMMIT, &ai->flags)) {
1885 disable_MAC(ai, 1);
1886 writeConfigRid(ai, 1);
1da177e4
LT
1887 }
1888
1c2b7db8
MS
1889 if (ai->wifidev != dev) {
1890 clear_bit(JOB_DIE, &ai->jobs);
1891 ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
1892 if (IS_ERR(ai->airo_thread_task))
1893 return (int)PTR_ERR(ai->airo_thread_task);
1894
1895 rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
1896 dev->name, dev);
1897 if (rc) {
1898 airo_print_err(dev->name,
1899 "register interrupt %d failed, rc %d",
1900 dev->irq, rc);
1901 set_bit(JOB_DIE, &ai->jobs);
1902 kthread_stop(ai->airo_thread_task);
1903 return rc;
1904 }
1905
1da177e4 1906 /* Power on the MAC controller (which may have been disabled) */
1c2b7db8
MS
1907 clear_bit(FLAG_RADIO_DOWN, &ai->flags);
1908 enable_interrupts(ai);
1909
1910 try_auto_wep(ai);
1da177e4 1911 }
175ec1a1 1912 enable_MAC(ai, 1);
1da177e4
LT
1913
1914 netif_start_queue(dev);
1915 return 0;
1916}
1917
1918static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
1919 int npacks, pending;
1920 unsigned long flags;
faf3994a 1921 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
1922
1923 if (!skb) {
c94c93da 1924 airo_print_err(dev->name, "%s: skb == NULL!",__func__);
1da177e4
LT
1925 return 0;
1926 }
1927 npacks = skb_queue_len (&ai->txq);
1928
1929 if (npacks >= MAXTXQ - 1) {
1930 netif_stop_queue (dev);
1931 if (npacks > MAXTXQ) {
5d9276da 1932 dev->stats.tx_fifo_errors++;
1da177e4
LT
1933 return 1;
1934 }
1935 skb_queue_tail (&ai->txq, skb);
1936 return 0;
1937 }
1938
1939 spin_lock_irqsave(&ai->aux_lock, flags);
1940 skb_queue_tail (&ai->txq, skb);
1941 pending = test_bit(FLAG_PENDING_XMIT, &ai->flags);
1942 spin_unlock_irqrestore(&ai->aux_lock,flags);
1943 netif_wake_queue (dev);
1944
1945 if (pending == 0) {
1946 set_bit(FLAG_PENDING_XMIT, &ai->flags);
1947 mpi_send_packet (dev);
1948 }
1949 return 0;
1950}
1951
1952/*
1953 * @mpi_send_packet
1954 *
1955 * Attempt to transmit a packet. Can be called from interrupt
1956 * or transmit . return number of packets we tried to send
1957 */
1958
1959static int mpi_send_packet (struct net_device *dev)
1960{
1961 struct sk_buff *skb;
1962 unsigned char *buffer;
593c2b9c
AV
1963 s16 len;
1964 __le16 *payloadLen;
faf3994a 1965 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
1966 u8 *sendbuf;
1967
1968 /* get a packet to send */
1969
79ea13ce 1970 if ((skb = skb_dequeue(&ai->txq)) == NULL) {
934d8bf1
DW
1971 airo_print_err(dev->name,
1972 "%s: Dequeue'd zero in send_packet()",
c94c93da 1973 __func__);
1da177e4
LT
1974 return 0;
1975 }
1976
1977 /* check min length*/
1978 len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
1979 buffer = skb->data;
1980
1981 ai->txfids[0].tx_desc.offset = 0;
1982 ai->txfids[0].tx_desc.valid = 1;
1983 ai->txfids[0].tx_desc.eoc = 1;
1984 ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);
1985
1986/*
1987 * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
1988 * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
1989 * is immediatly after it. ------------------------------------------------
1990 * |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|
1991 * ------------------------------------------------
1992 */
1993
1994 memcpy((char *)ai->txfids[0].virtual_host_addr,
1995 (char *)&wifictlhdr8023, sizeof(wifictlhdr8023));
1996
593c2b9c 1997 payloadLen = (__le16 *)(ai->txfids[0].virtual_host_addr +
1da177e4
LT
1998 sizeof(wifictlhdr8023));
1999 sendbuf = ai->txfids[0].virtual_host_addr +
2000 sizeof(wifictlhdr8023) + 2 ;
2001
2002 /*
2003 * Firmware automaticly puts 802 header on so
2004 * we don't need to account for it in the length
2005 */
1da177e4 2006 if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
593c2b9c 2007 (ntohs(((__be16 *)buffer)[6]) != 0x888E)) {
1da177e4
LT
2008 MICBuffer pMic;
2009
2010 if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS)
2011 return ERROR;
2012
2013 *payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));
2014 ai->txfids[0].tx_desc.len += sizeof(pMic);
2015 /* copy data into airo dma buffer */
2016 memcpy (sendbuf, buffer, sizeof(etherHead));
2017 buffer += sizeof(etherHead);
2018 sendbuf += sizeof(etherHead);
2019 memcpy (sendbuf, &pMic, sizeof(pMic));
2020 sendbuf += sizeof(pMic);
2021 memcpy (sendbuf, buffer, len - sizeof(etherHead));
a39d3e79 2022 } else {
1da177e4
LT
2023 *payloadLen = cpu_to_le16(len - sizeof(etherHead));
2024
2025 dev->trans_start = jiffies;
2026
2027 /* copy data into airo dma buffer */
2028 memcpy(sendbuf, buffer, len);
2029 }
2030
2031 memcpy_toio(ai->txfids[0].card_ram_off,
2032 &ai->txfids[0].tx_desc, sizeof(TxFid));
2033
2034 OUT4500(ai, EVACK, 8);
2035
2036 dev_kfree_skb_any(skb);
2037 return 1;
2038}
2039
29b09fcc 2040static void get_tx_error(struct airo_info *ai, s32 fid)
1da177e4 2041{
593c2b9c 2042 __le16 status;
1da177e4
LT
2043
2044 if (fid < 0)
2045 status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status;
2046 else {
2047 if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) != SUCCESS)
2048 return;
2049 bap_read(ai, &status, 2, BAP0);
2050 }
2051 if (le16_to_cpu(status) & 2) /* Too many retries */
5d9276da 2052 ai->dev->stats.tx_aborted_errors++;
1da177e4 2053 if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */
5d9276da 2054 ai->dev->stats.tx_heartbeat_errors++;
1da177e4
LT
2055 if (le16_to_cpu(status) & 8) /* Aid fail */
2056 { }
2057 if (le16_to_cpu(status) & 0x10) /* MAC disabled */
5d9276da 2058 ai->dev->stats.tx_carrier_errors++;
1da177e4
LT
2059 if (le16_to_cpu(status) & 0x20) /* Association lost */
2060 { }
2061 /* We produce a TXDROP event only for retry or lifetime
2062 * exceeded, because that's the only status that really mean
2063 * that this particular node went away.
2064 * Other errors means that *we* screwed up. - Jean II */
2065 if ((le16_to_cpu(status) & 2) ||
2066 (le16_to_cpu(status) & 4)) {
2067 union iwreq_data wrqu;
2068 char junk[0x18];
2069
2070 /* Faster to skip over useless data than to do
2071 * another bap_setup(). We are at offset 0x6 and
2072 * need to go to 0x18 and read 6 bytes - Jean II */
b8c06bc1 2073 bap_read(ai, (__le16 *) junk, 0x18, BAP0);
1da177e4
LT
2074
2075 /* Copy 802.11 dest address.
2076 * We use the 802.11 header because the frame may
2077 * not be 802.3 or may be mangled...
2078 * In Ad-Hoc mode, it will be the node address.
2079 * In managed mode, it will be most likely the AP addr
2080 * User space will figure out how to convert it to
2081 * whatever it needs (IP address or else).
2082 * - Jean II */
2083 memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN);
2084 wrqu.addr.sa_family = ARPHRD_ETHER;
2085
2086 /* Send event to user space */
2087 wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL);
2088 }
2089}
2090
2091static void airo_end_xmit(struct net_device *dev) {
2092 u16 status;
2093 int i;
faf3994a 2094 struct airo_info *priv = dev->ml_priv;
1da177e4
LT
2095 struct sk_buff *skb = priv->xmit.skb;
2096 int fid = priv->xmit.fid;
2097 u32 *fids = priv->fids;
2098
3c304956 2099 clear_bit(JOB_XMIT, &priv->jobs);
1da177e4
LT
2100 clear_bit(FLAG_PENDING_XMIT, &priv->flags);
2101 status = transmit_802_3_packet (priv, fids[fid], skb->data);
2102 up(&priv->sem);
2103
2104 i = 0;
2105 if ( status == SUCCESS ) {
2106 dev->trans_start = jiffies;
2107 for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++);
2108 } else {
2109 priv->fids[fid] &= 0xffff;
5d9276da 2110 dev->stats.tx_window_errors++;
1da177e4
LT
2111 }
2112 if (i < MAX_FIDS / 2)
2113 netif_wake_queue(dev);
2114 dev_kfree_skb(skb);
2115}
2116
2117static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
2118 s16 len;
2119 int i, j;
faf3994a 2120 struct airo_info *priv = dev->ml_priv;
1da177e4
LT
2121 u32 *fids = priv->fids;
2122
2123 if ( skb == NULL ) {
c94c93da 2124 airo_print_err(dev->name, "%s: skb == NULL!", __func__);
1da177e4
LT
2125 return 0;
2126 }
2127
2128 /* Find a vacant FID */
2129 for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
2130 for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ );
2131
2132 if ( j >= MAX_FIDS / 2 ) {
2133 netif_stop_queue(dev);
2134
2135 if (i == MAX_FIDS / 2) {
5d9276da 2136 dev->stats.tx_fifo_errors++;
1da177e4
LT
2137 return 1;
2138 }
2139 }
2140 /* check min length*/
2141 len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
2142 /* Mark fid as used & save length for later */
2143 fids[i] |= (len << 16);
2144 priv->xmit.skb = skb;
2145 priv->xmit.fid = i;
2146 if (down_trylock(&priv->sem) != 0) {
2147 set_bit(FLAG_PENDING_XMIT, &priv->flags);
2148 netif_stop_queue(dev);
3c304956 2149 set_bit(JOB_XMIT, &priv->jobs);
1da177e4
LT
2150 wake_up_interruptible(&priv->thr_wait);
2151 } else
2152 airo_end_xmit(dev);
2153 return 0;
2154}
2155
2156static void airo_end_xmit11(struct net_device *dev) {
2157 u16 status;
2158 int i;
faf3994a 2159 struct airo_info *priv = dev->ml_priv;
1da177e4
LT
2160 struct sk_buff *skb = priv->xmit11.skb;
2161 int fid = priv->xmit11.fid;
2162 u32 *fids = priv->fids;
2163
3c304956 2164 clear_bit(JOB_XMIT11, &priv->jobs);
1da177e4
LT
2165 clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
2166 status = transmit_802_11_packet (priv, fids[fid], skb->data);
2167 up(&priv->sem);
2168
2169 i = MAX_FIDS / 2;
2170 if ( status == SUCCESS ) {
2171 dev->trans_start = jiffies;
2172 for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++);
2173 } else {
2174 priv->fids[fid] &= 0xffff;
5d9276da 2175 dev->stats.tx_window_errors++;
1da177e4
LT
2176 }
2177 if (i < MAX_FIDS)
2178 netif_wake_queue(dev);
2179 dev_kfree_skb(skb);
2180}
2181
2182static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
2183 s16 len;
2184 int i, j;
faf3994a 2185 struct airo_info *priv = dev->ml_priv;
1da177e4
LT
2186 u32 *fids = priv->fids;
2187
2188 if (test_bit(FLAG_MPI, &priv->flags)) {
2189 /* Not implemented yet for MPI350 */
2190 netif_stop_queue(dev);
2191 return -ENETDOWN;
2192 }
2193
2194 if ( skb == NULL ) {
c94c93da 2195 airo_print_err(dev->name, "%s: skb == NULL!", __func__);
1da177e4
LT
2196 return 0;
2197 }
2198
2199 /* Find a vacant FID */
2200 for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
2201 for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ );
2202
2203 if ( j >= MAX_FIDS ) {
2204 netif_stop_queue(dev);
2205
2206 if (i == MAX_FIDS) {
5d9276da 2207 dev->stats.tx_fifo_errors++;
1da177e4
LT
2208 return 1;
2209 }
2210 }
2211 /* check min length*/
2212 len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
2213 /* Mark fid as used & save length for later */
2214 fids[i] |= (len << 16);
2215 priv->xmit11.skb = skb;
2216 priv->xmit11.fid = i;
2217 if (down_trylock(&priv->sem) != 0) {
2218 set_bit(FLAG_PENDING_XMIT11, &priv->flags);
2219 netif_stop_queue(dev);
3c304956 2220 set_bit(JOB_XMIT11, &priv->jobs);
1da177e4
LT
2221 wake_up_interruptible(&priv->thr_wait);
2222 } else
2223 airo_end_xmit11(dev);
2224 return 0;
2225}
2226
5d9276da 2227static void airo_read_stats(struct net_device *dev)
a23ace5f 2228{
faf3994a 2229 struct airo_info *ai = dev->ml_priv;
1da177e4 2230 StatsRid stats_rid;
a23ace5f 2231 __le32 *vals = stats_rid.vals;
1da177e4 2232
3c304956 2233 clear_bit(JOB_STATS, &ai->jobs);
ca078bae 2234 if (ai->power.event) {
1da177e4
LT
2235 up(&ai->sem);
2236 return;
2237 }
2238 readStatsRid(ai, &stats_rid, RID_STATS, 0);
2239 up(&ai->sem);
2240
5d9276da 2241 dev->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
a23ace5f 2242 le32_to_cpu(vals[45]);
5d9276da 2243 dev->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
a23ace5f 2244 le32_to_cpu(vals[41]);
5d9276da
PZ
2245 dev->stats.rx_bytes = le32_to_cpu(vals[92]);
2246 dev->stats.tx_bytes = le32_to_cpu(vals[91]);
2247 dev->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
a23ace5f 2248 le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]);
5d9276da
PZ
2249 dev->stats.tx_errors = le32_to_cpu(vals[42]) +
2250 dev->stats.tx_fifo_errors;
2251 dev->stats.multicast = le32_to_cpu(vals[43]);
2252 dev->stats.collisions = le32_to_cpu(vals[89]);
1da177e4
LT
2253
2254 /* detailed rx_errors: */
5d9276da
PZ
2255 dev->stats.rx_length_errors = le32_to_cpu(vals[3]);
2256 dev->stats.rx_crc_errors = le32_to_cpu(vals[4]);
2257 dev->stats.rx_frame_errors = le32_to_cpu(vals[2]);
2258 dev->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
1da177e4
LT
2259}
2260
ff1d2767 2261static struct net_device_stats *airo_get_stats(struct net_device *dev)
1da177e4 2262{
faf3994a 2263 struct airo_info *local = dev->ml_priv;
1da177e4 2264
3c304956 2265 if (!test_bit(JOB_STATS, &local->jobs)) {
1da177e4
LT
2266 /* Get stats out of the card if available */
2267 if (down_trylock(&local->sem) != 0) {
3c304956 2268 set_bit(JOB_STATS, &local->jobs);
1da177e4
LT
2269 wake_up_interruptible(&local->thr_wait);
2270 } else
5d9276da 2271 airo_read_stats(dev);
1da177e4
LT
2272 }
2273
5d9276da 2274 return &dev->stats;
1da177e4
LT
2275}
2276
2277static void airo_set_promisc(struct airo_info *ai) {
2278 Cmd cmd;
2279 Resp rsp;
2280
2281 memset(&cmd, 0, sizeof(cmd));
2282 cmd.cmd=CMD_SETMODE;
3c304956 2283 clear_bit(JOB_PROMISC, &ai->jobs);
1da177e4
LT
2284 cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
2285 issuecommand(ai, &cmd, &rsp);
2286 up(&ai->sem);
2287}
2288
2289static void airo_set_multicast_list(struct net_device *dev) {
faf3994a 2290 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2291
2292 if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
2293 change_bit(FLAG_PROMISC, &ai->flags);
2294 if (down_trylock(&ai->sem) != 0) {
3c304956 2295 set_bit(JOB_PROMISC, &ai->jobs);
1da177e4
LT
2296 wake_up_interruptible(&ai->thr_wait);
2297 } else
2298 airo_set_promisc(ai);
2299 }
2300
2301 if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
2302 /* Turn on multicast. (Should be already setup...) */
2303 }
2304}
2305
2306static int airo_set_mac_address(struct net_device *dev, void *p)
2307{
faf3994a 2308 struct airo_info *ai = dev->ml_priv;
1da177e4 2309 struct sockaddr *addr = p;
1da177e4
LT
2310
2311 readConfigRid(ai, 1);
2312 memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
2313 set_bit (FLAG_COMMIT, &ai->flags);
2314 disable_MAC(ai, 1);
2315 writeConfigRid (ai, 1);
175ec1a1 2316 enable_MAC(ai, 1);
1da177e4
LT
2317 memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
2318 if (ai->wifidev)
2319 memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
2320 return 0;
2321}
2322
2323static int airo_change_mtu(struct net_device *dev, int new_mtu)
2324{
2325 if ((new_mtu < 68) || (new_mtu > 2400))
2326 return -EINVAL;
2327 dev->mtu = new_mtu;
2328 return 0;
2329}
2330
af5b5c9a
MS
2331static LIST_HEAD(airo_devices);
2332
2333static void add_airo_dev(struct airo_info *ai)
2334{
2335 /* Upper layers already keep track of PCI devices,
2336 * so we only need to remember our non-PCI cards. */
2337 if (!ai->pci)
2338 list_add_tail(&ai->dev_list, &airo_devices);
2339}
2340
2341static void del_airo_dev(struct airo_info *ai)
2342{
2343 if (!ai->pci)
2344 list_del(&ai->dev_list);
2345}
1da177e4
LT
2346
2347static int airo_close(struct net_device *dev) {
faf3994a 2348 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2349
2350 netif_stop_queue(dev);
2351
2352 if (ai->wifidev != dev) {
2353#ifdef POWER_ON_DOWN
2354 /* Shut power to the card. The idea is that the user can save
2355 * power when he doesn't need the card with "ifconfig down".
2356 * That's the method that is most friendly towards the network
2357 * stack (i.e. the network stack won't try to broadcast
2358 * anything on the interface and routes are gone. Jean II */
2359 set_bit(FLAG_RADIO_DOWN, &ai->flags);
2360 disable_MAC(ai, 1);
2361#endif
2362 disable_interrupts( ai );
1c2b7db8
MS
2363
2364 free_irq(dev->irq, dev);
2365
2366 set_bit(JOB_DIE, &ai->jobs);
2367 kthread_stop(ai->airo_thread_task);
1da177e4
LT
2368 }
2369 return 0;
2370}
2371
1da177e4
LT
2372void stop_airo_card( struct net_device *dev, int freeres )
2373{
faf3994a 2374 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2375
2376 set_bit(FLAG_RADIO_DOWN, &ai->flags);
2377 disable_MAC(ai, 1);
2378 disable_interrupts(ai);
1da177e4
LT
2379 takedown_proc_entry( dev, ai );
2380 if (test_bit(FLAG_REGISTERED, &ai->flags)) {
2381 unregister_netdev( dev );
2382 if (ai->wifidev) {
2383 unregister_netdev(ai->wifidev);
2384 free_netdev(ai->wifidev);
2385 ai->wifidev = NULL;
2386 }
2387 clear_bit(FLAG_REGISTERED, &ai->flags);
2388 }
1da177e4
LT
2389 /*
2390 * Clean out tx queue
2391 */
b03efcfb 2392 if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) {
1da177e4
LT
2393 struct sk_buff *skb = NULL;
2394 for (;(skb = skb_dequeue(&ai->txq));)
2395 dev_kfree_skb(skb);
2396 }
2397
9e75af30
DW
2398 airo_networks_free (ai);
2399
b4558ea9
JJ
2400 kfree(ai->flash);
2401 kfree(ai->rssi);
2402 kfree(ai->APList);
2403 kfree(ai->SSID);
1da177e4
LT
2404 if (freeres) {
2405 /* PCMCIA frees this stuff, so only for PCI and ISA */
2406 release_region( dev->base_addr, 64 );
2407 if (test_bit(FLAG_MPI, &ai->flags)) {
2408 if (ai->pci)
2409 mpi_unmap_card(ai->pci);
2410 if (ai->pcimem)
2411 iounmap(ai->pcimem);
2412 if (ai->pciaux)
2413 iounmap(ai->pciaux);
2414 pci_free_consistent(ai->pci, PCI_SHARED_LEN,
2415 ai->shared, ai->shared_dma);
2416 }
2417 }
f12cc209 2418 crypto_free_cipher(ai->tfm);
af5b5c9a 2419 del_airo_dev(ai);
1da177e4
LT
2420 free_netdev( dev );
2421}
2422
2423EXPORT_SYMBOL(stop_airo_card);
2424
b95cce35 2425static int wll_header_parse(const struct sk_buff *skb, unsigned char *haddr)
1da177e4 2426{
98e399f8 2427 memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN);
1da177e4
LT
2428 return ETH_ALEN;
2429}
2430
2431static void mpi_unmap_card(struct pci_dev *pci)
2432{
2433 unsigned long mem_start = pci_resource_start(pci, 1);
2434 unsigned long mem_len = pci_resource_len(pci, 1);
2435 unsigned long aux_start = pci_resource_start(pci, 2);
2436 unsigned long aux_len = AUXMEMSIZE;
2437
2438 release_mem_region(aux_start, aux_len);
2439 release_mem_region(mem_start, mem_len);
2440}
2441
2442/*************************************************************
2443 * This routine assumes that descriptors have been setup .
2444 * Run at insmod time or after reset when the decriptors
2445 * have been initialized . Returns 0 if all is well nz
2446 * otherwise . Does not allocate memory but sets up card
2447 * using previously allocated descriptors.
2448 */
2449static int mpi_init_descriptors (struct airo_info *ai)
2450{
2451 Cmd cmd;
2452 Resp rsp;
2453 int i;
2454 int rc = SUCCESS;
2455
2456 /* Alloc card RX descriptors */
2457 netif_stop_queue(ai->dev);
2458
2459 memset(&rsp,0,sizeof(rsp));
2460 memset(&cmd,0,sizeof(cmd));
2461
2462 cmd.cmd = CMD_ALLOCATEAUX;
2463 cmd.parm0 = FID_RX;
2464 cmd.parm1 = (ai->rxfids[0].card_ram_off - ai->pciaux);
2465 cmd.parm2 = MPI_MAX_FIDS;
2466 rc=issuecommand(ai, &cmd, &rsp);
2467 if (rc != SUCCESS) {
934d8bf1 2468 airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
1da177e4
LT
2469 return rc;
2470 }
2471
2472 for (i=0; i<MPI_MAX_FIDS; i++) {
2473 memcpy_toio(ai->rxfids[i].card_ram_off,
2474 &ai->rxfids[i].rx_desc, sizeof(RxFid));
2475 }
2476
2477 /* Alloc card TX descriptors */
2478
2479 memset(&rsp,0,sizeof(rsp));
2480 memset(&cmd,0,sizeof(cmd));
2481
2482 cmd.cmd = CMD_ALLOCATEAUX;
2483 cmd.parm0 = FID_TX;
2484 cmd.parm1 = (ai->txfids[0].card_ram_off - ai->pciaux);
2485 cmd.parm2 = MPI_MAX_FIDS;
2486
2487 for (i=0; i<MPI_MAX_FIDS; i++) {
2488 ai->txfids[i].tx_desc.valid = 1;
2489 memcpy_toio(ai->txfids[i].card_ram_off,
2490 &ai->txfids[i].tx_desc, sizeof(TxFid));
2491 }
2492 ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
2493
2494 rc=issuecommand(ai, &cmd, &rsp);
2495 if (rc != SUCCESS) {
934d8bf1 2496 airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
1da177e4
LT
2497 return rc;
2498 }
2499
2500 /* Alloc card Rid descriptor */
2501 memset(&rsp,0,sizeof(rsp));
2502 memset(&cmd,0,sizeof(cmd));
2503
2504 cmd.cmd = CMD_ALLOCATEAUX;
2505 cmd.parm0 = RID_RW;
2506 cmd.parm1 = (ai->config_desc.card_ram_off - ai->pciaux);
2507 cmd.parm2 = 1; /* Magic number... */
2508 rc=issuecommand(ai, &cmd, &rsp);
2509 if (rc != SUCCESS) {
934d8bf1 2510 airo_print_err(ai->dev->name, "Couldn't allocate RID");
1da177e4
LT
2511 return rc;
2512 }
2513
2514 memcpy_toio(ai->config_desc.card_ram_off,
2515 &ai->config_desc.rid_desc, sizeof(Rid));
2516
2517 return rc;
2518}
2519
2520/*
2521 * We are setting up three things here:
2522 * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid.
2523 * 2) Map PCI memory for issueing commands.
2524 * 3) Allocate memory (shared) to send and receive ethernet frames.
2525 */
1138c37b 2526static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
1da177e4
LT
2527{
2528 unsigned long mem_start, mem_len, aux_start, aux_len;
2529 int rc = -1;
2530 int i;
2759c8d5
JG
2531 dma_addr_t busaddroff;
2532 unsigned char *vpackoff;
1da177e4
LT
2533 unsigned char __iomem *pciaddroff;
2534
2535 mem_start = pci_resource_start(pci, 1);
2536 mem_len = pci_resource_len(pci, 1);
2537 aux_start = pci_resource_start(pci, 2);
2538 aux_len = AUXMEMSIZE;
2539
1138c37b
MS
2540 if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
2541 airo_print_err("", "Couldn't get region %x[%x]",
2542 (int)mem_start, (int)mem_len);
1da177e4
LT
2543 goto out;
2544 }
1138c37b
MS
2545 if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
2546 airo_print_err("", "Couldn't get region %x[%x]",
2547 (int)aux_start, (int)aux_len);
1da177e4
LT
2548 goto free_region1;
2549 }
2550
2551 ai->pcimem = ioremap(mem_start, mem_len);
2552 if (!ai->pcimem) {
1138c37b
MS
2553 airo_print_err("", "Couldn't map region %x[%x]",
2554 (int)mem_start, (int)mem_len);
1da177e4
LT
2555 goto free_region2;
2556 }
2557 ai->pciaux = ioremap(aux_start, aux_len);
2558 if (!ai->pciaux) {
1138c37b
MS
2559 airo_print_err("", "Couldn't map region %x[%x]",
2560 (int)aux_start, (int)aux_len);
1da177e4
LT
2561 goto free_memmap;
2562 }
2563
2564 /* Reserve PKTSIZE for each fid and 2K for the Rids */
2565 ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
2566 if (!ai->shared) {
1138c37b
MS
2567 airo_print_err("", "Couldn't alloc_consistent %d",
2568 PCI_SHARED_LEN);
1da177e4
LT
2569 goto free_auxmap;
2570 }
2571
2572 /*
2573 * Setup descriptor RX, TX, CONFIG
2574 */
2759c8d5 2575 busaddroff = ai->shared_dma;
1da177e4
LT
2576 pciaddroff = ai->pciaux + AUX_OFFSET;
2577 vpackoff = ai->shared;
2578
2579 /* RX descriptor setup */
2580 for(i = 0; i < MPI_MAX_FIDS; i++) {
2581 ai->rxfids[i].pending = 0;
2582 ai->rxfids[i].card_ram_off = pciaddroff;
2583 ai->rxfids[i].virtual_host_addr = vpackoff;
2759c8d5 2584 ai->rxfids[i].rx_desc.host_addr = busaddroff;
1da177e4
LT
2585 ai->rxfids[i].rx_desc.valid = 1;
2586 ai->rxfids[i].rx_desc.len = PKTSIZE;
2587 ai->rxfids[i].rx_desc.rdy = 0;
2588
2589 pciaddroff += sizeof(RxFid);
2590 busaddroff += PKTSIZE;
2591 vpackoff += PKTSIZE;
2592 }
2593
2594 /* TX descriptor setup */
2595 for(i = 0; i < MPI_MAX_FIDS; i++) {
2596 ai->txfids[i].card_ram_off = pciaddroff;
2597 ai->txfids[i].virtual_host_addr = vpackoff;
2598 ai->txfids[i].tx_desc.valid = 1;
2759c8d5 2599 ai->txfids[i].tx_desc.host_addr = busaddroff;
1da177e4
LT
2600 memcpy(ai->txfids[i].virtual_host_addr,
2601 &wifictlhdr8023, sizeof(wifictlhdr8023));
2602
2603 pciaddroff += sizeof(TxFid);
2604 busaddroff += PKTSIZE;
2605 vpackoff += PKTSIZE;
2606 }
2607 ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
2608
2609 /* Rid descriptor setup */
2610 ai->config_desc.card_ram_off = pciaddroff;
2611 ai->config_desc.virtual_host_addr = vpackoff;
2759c8d5
JG
2612 ai->config_desc.rid_desc.host_addr = busaddroff;
2613 ai->ridbus = busaddroff;
1da177e4
LT
2614 ai->config_desc.rid_desc.rid = 0;
2615 ai->config_desc.rid_desc.len = RIDSIZE;
2616 ai->config_desc.rid_desc.valid = 1;
2617 pciaddroff += sizeof(Rid);
2618 busaddroff += RIDSIZE;
2619 vpackoff += RIDSIZE;
2620
2621 /* Tell card about descriptors */
2622 if (mpi_init_descriptors (ai) != SUCCESS)
2623 goto free_shared;
2624
2625 return 0;
2626 free_shared:
2627 pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
2628 free_auxmap:
2629 iounmap(ai->pciaux);
2630 free_memmap:
2631 iounmap(ai->pcimem);
2632 free_region2:
2633 release_mem_region(aux_start, aux_len);
2634 free_region1:
2635 release_mem_region(mem_start, mem_len);
2636 out:
2637 return rc;
2638}
2639
3b04ddde
SH
2640static const struct header_ops airo_header_ops = {
2641 .parse = wll_header_parse,
2642};
2643
1da177e4
LT
2644static void wifi_setup(struct net_device *dev)
2645{
3b04ddde 2646 dev->header_ops = &airo_header_ops;
1da177e4
LT
2647 dev->hard_start_xmit = &airo_start_xmit11;
2648 dev->get_stats = &airo_get_stats;
2649 dev->set_mac_address = &airo_set_mac_address;
2650 dev->do_ioctl = &airo_ioctl;
1da177e4 2651 dev->wireless_handlers = &airo_handler_def;
1da177e4
LT
2652 dev->change_mtu = &airo_change_mtu;
2653 dev->open = &airo_open;
2654 dev->stop = &airo_close;
2655
2656 dev->type = ARPHRD_IEEE80211;
2657 dev->hard_header_len = ETH_HLEN;
15db2763 2658 dev->mtu = AIRO_DEF_MTU;
1da177e4
LT
2659 dev->addr_len = ETH_ALEN;
2660 dev->tx_queue_len = 100;
2661
2662 memset(dev->broadcast,0xFF, ETH_ALEN);
2663
2664 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
2665}
2666
2667static struct net_device *init_wifidev(struct airo_info *ai,
2668 struct net_device *ethdev)
2669{
2670 int err;
2671 struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
2672 if (!dev)
2673 return NULL;
faf3994a 2674 dev->ml_priv = ethdev->ml_priv;
1da177e4
LT
2675 dev->irq = ethdev->irq;
2676 dev->base_addr = ethdev->base_addr;
1da177e4 2677 dev->wireless_data = ethdev->wireless_data;
229ce3ab 2678 SET_NETDEV_DEV(dev, ethdev->dev.parent);
1da177e4
LT
2679 memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
2680 err = register_netdev(dev);
2681 if (err<0) {
2682 free_netdev(dev);
2683 return NULL;
2684 }
2685 return dev;
2686}
2687
ff1d2767 2688static int reset_card( struct net_device *dev , int lock) {
faf3994a 2689 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2690
2691 if (lock && down_interruptible(&ai->sem))
2692 return -1;
2693 waitbusy (ai);
2694 OUT4500(ai,COMMAND,CMD_SOFTRESET);
2695 msleep(200);
2696 waitbusy (ai);
2697 msleep(200);
2698 if (lock)
2699 up(&ai->sem);
2700 return 0;
2701}
2702
3c304956 2703#define AIRO_MAX_NETWORK_COUNT 64
9e75af30
DW
2704static int airo_networks_allocate(struct airo_info *ai)
2705{
2706 if (ai->networks)
2707 return 0;
2708
2709 ai->networks =
3c304956 2710 kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
9e75af30
DW
2711 GFP_KERNEL);
2712 if (!ai->networks) {
1138c37b 2713 airo_print_warn("", "Out of memory allocating beacons");
9e75af30
DW
2714 return -ENOMEM;
2715 }
2716
2717 return 0;
2718}
2719
2720static void airo_networks_free(struct airo_info *ai)
2721{
9e75af30
DW
2722 kfree(ai->networks);
2723 ai->networks = NULL;
2724}
2725
2726static void airo_networks_initialize(struct airo_info *ai)
2727{
2728 int i;
2729
2730 INIT_LIST_HEAD(&ai->network_free_list);
2731 INIT_LIST_HEAD(&ai->network_list);
3c304956 2732 for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++)
9e75af30
DW
2733 list_add_tail(&ai->networks[i].list,
2734 &ai->network_free_list);
2735}
2736
ff1d2767
JM
2737static struct net_device *_init_airo_card( unsigned short irq, int port,
2738 int is_pcmcia, struct pci_dev *pci,
2739 struct device *dmdev )
1da177e4
LT
2740{
2741 struct net_device *dev;
2742 struct airo_info *ai;
2743 int i, rc;
f65b56d6 2744 CapabilityRid cap_rid;
1da177e4
LT
2745
2746 /* Create the network device object. */
1138c37b
MS
2747 dev = alloc_netdev(sizeof(*ai), "", ether_setup);
2748 if (!dev) {
934d8bf1 2749 airo_print_err("", "Couldn't alloc_etherdev");
1da177e4 2750 return NULL;
1da177e4
LT
2751 }
2752
faf3994a 2753 ai = dev->ml_priv = netdev_priv(dev);
1da177e4 2754 ai->wifidev = NULL;
fb038c27 2755 ai->flags = 1 << FLAG_RADIO_DOWN;
3c304956 2756 ai->jobs = 0;
934d8bf1 2757 ai->dev = dev;
1da177e4 2758 if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
1138c37b 2759 airo_print_dbg("", "Found an MPI350 card");
1da177e4
LT
2760 set_bit(FLAG_MPI, &ai->flags);
2761 }
1da177e4
LT
2762 spin_lock_init(&ai->aux_lock);
2763 sema_init(&ai->sem, 1);
2764 ai->config.len = 0;
2765 ai->pci = pci;
2766 init_waitqueue_head (&ai->thr_wait);
1da177e4 2767 ai->tfm = NULL;
af5b5c9a 2768 add_airo_dev(ai);
1da177e4 2769
9e75af30 2770 if (airo_networks_allocate (ai))
1c2b7db8 2771 goto err_out_free;
9e75af30
DW
2772 airo_networks_initialize (ai);
2773
1da177e4
LT
2774 /* The Airo-specific entries in the device structure. */
2775 if (test_bit(FLAG_MPI,&ai->flags)) {
2776 skb_queue_head_init (&ai->txq);
2777 dev->hard_start_xmit = &mpi_start_xmit;
2778 } else
2779 dev->hard_start_xmit = &airo_start_xmit;
2780 dev->get_stats = &airo_get_stats;
2781 dev->set_multicast_list = &airo_set_multicast_list;
2782 dev->set_mac_address = &airo_set_mac_address;
2783 dev->do_ioctl = &airo_ioctl;
1da177e4
LT
2784 dev->wireless_handlers = &airo_handler_def;
2785 ai->wireless_data.spy_data = &ai->spy_data;
2786 dev->wireless_data = &ai->wireless_data;
1da177e4
LT
2787 dev->change_mtu = &airo_change_mtu;
2788 dev->open = &airo_open;
2789 dev->stop = &airo_close;
2790 dev->irq = irq;
2791 dev->base_addr = port;
2792
2793 SET_NETDEV_DEV(dev, dmdev);
2794
1d97f384
MC
2795 reset_card (dev, 1);
2796 msleep(400);
1da177e4 2797
1da177e4 2798 if (!is_pcmcia) {
1138c37b 2799 if (!request_region(dev->base_addr, 64, DRV_NAME)) {
1da177e4 2800 rc = -EBUSY;
934d8bf1 2801 airo_print_err(dev->name, "Couldn't request region");
1c2b7db8 2802 goto err_out_nets;
1da177e4
LT
2803 }
2804 }
2805
2806 if (test_bit(FLAG_MPI,&ai->flags)) {
1138c37b
MS
2807 if (mpi_map_card(ai, pci)) {
2808 airo_print_err("", "Could not map memory");
1da177e4
LT
2809 goto err_out_res;
2810 }
2811 }
2812
2813 if (probe) {
f65b56d6 2814 if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
934d8bf1 2815 airo_print_err(dev->name, "MAC could not be enabled" );
1da177e4
LT
2816 rc = -EIO;
2817 goto err_out_map;
2818 }
2819 } else if (!test_bit(FLAG_MPI,&ai->flags)) {
2820 ai->bap_read = fast_bap_read;
2821 set_bit(FLAG_FLASHING, &ai->flags);
2822 }
2823
f65b56d6
DW
2824 strcpy(dev->name, "eth%d");
2825 rc = register_netdev(dev);
2826 if (rc) {
2827 airo_print_err(dev->name, "Couldn't register_netdev");
2828 goto err_out_map;
2829 }
2830 ai->wifidev = init_wifidev(ai, dev);
2831 if (!ai->wifidev)
2832 goto err_out_reg;
2833
2834 rc = readCapabilityRid(ai, &cap_rid, 1);
2835 if (rc != SUCCESS) {
2836 rc = -EIO;
2837 goto err_out_wifi;
2838 }
2839
2840 airo_print_info(dev->name, "Firmware version %x.%x.%02x",
2841 ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF),
2842 (le16_to_cpu(cap_rid.softVer) & 0xFF),
2843 le16_to_cpu(cap_rid.softSubVer));
2844
3c304956 2845 /* Test for WPA support */
f65b56d6
DW
2846 /* Only firmware versions 5.30.17 or better can do WPA */
2847 if (le16_to_cpu(cap_rid.softVer) > 0x530
2848 || (le16_to_cpu(cap_rid.softVer) == 0x530
2849 && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
2850 airo_print_info(ai->dev->name, "WPA supported.");
2851
3c304956
DW
2852 set_bit(FLAG_WPA_CAPABLE, &ai->flags);
2853 ai->bssListFirst = RID_WPA_BSSLISTFIRST;
2854 ai->bssListNext = RID_WPA_BSSLISTNEXT;
2855 ai->bssListRidLen = sizeof(BSSListRid);
2856 } else {
f65b56d6
DW
2857 airo_print_info(ai->dev->name, "WPA unsupported with firmware "
2858 "versions older than 5.30.17.");
2859
3c304956
DW
2860 ai->bssListFirst = RID_BSSLISTFIRST;
2861 ai->bssListNext = RID_BSSLISTNEXT;
2862 ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
2863 }
2864
1da177e4 2865 set_bit(FLAG_REGISTERED,&ai->flags);
e174961c 2866 airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
1da177e4
LT
2867
2868 /* Allocate the transmit buffers */
2869 if (probe && !test_bit(FLAG_MPI,&ai->flags))
2870 for( i = 0; i < MAX_FIDS; i++ )
15db2763 2871 ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
1da177e4 2872
faf3994a 2873 if (setup_proc_entry(dev, dev->ml_priv) < 0)
431aca5a
FM
2874 goto err_out_wifi;
2875
1da177e4
LT
2876 return dev;
2877
431aca5a
FM
2878err_out_wifi:
2879 unregister_netdev(ai->wifidev);
2880 free_netdev(ai->wifidev);
2881err_out_reg:
2882 unregister_netdev(dev);
1da177e4
LT
2883err_out_map:
2884 if (test_bit(FLAG_MPI,&ai->flags) && pci) {
2885 pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
2886 iounmap(ai->pciaux);
2887 iounmap(ai->pcimem);
2888 mpi_unmap_card(ai->pci);
2889 }
2890err_out_res:
2891 if (!is_pcmcia)
2892 release_region( dev->base_addr, 64 );
4d881901
MS
2893err_out_nets:
2894 airo_networks_free(ai);
af5b5c9a 2895 del_airo_dev(ai);
1da177e4
LT
2896err_out_free:
2897 free_netdev(dev);
2898 return NULL;
2899}
2900
2901struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia,
2902 struct device *dmdev)
2903{
2904 return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev);
2905}
2906
2907EXPORT_SYMBOL(init_airo_card);
2908
2909static int waitbusy (struct airo_info *ai) {
2910 int delay = 0;
b212f337 2911 while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) {
1da177e4
LT
2912 udelay (10);
2913 if ((++delay % 20) == 0)
2914 OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
2915 }
2916 return delay < 10000;
2917}
2918
2919int reset_airo_card( struct net_device *dev )
2920{
2921 int i;
faf3994a 2922 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2923
2924 if (reset_card (dev, 1))
2925 return -1;
2926
2927 if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
934d8bf1 2928 airo_print_err(dev->name, "MAC could not be enabled");
1da177e4
LT
2929 return -1;
2930 }
e174961c 2931 airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
1da177e4
LT
2932 /* Allocate the transmit buffers if needed */
2933 if (!test_bit(FLAG_MPI,&ai->flags))
2934 for( i = 0; i < MAX_FIDS; i++ )
15db2763 2935 ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
1da177e4
LT
2936
2937 enable_interrupts( ai );
2938 netif_wake_queue(dev);
2939 return 0;
2940}
2941
2942EXPORT_SYMBOL(reset_airo_card);
2943
2944static void airo_send_event(struct net_device *dev) {
faf3994a 2945 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
2946 union iwreq_data wrqu;
2947 StatusRid status_rid;
2948
3c304956 2949 clear_bit(JOB_EVENT, &ai->jobs);
1da177e4
LT
2950 PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
2951 up(&ai->sem);
2952 wrqu.data.length = 0;
2953 wrqu.data.flags = 0;
2954 memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN);
2955 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2956
2957 /* Send event to user space */
2958 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
2959}
2960
9e75af30
DW
2961static void airo_process_scan_results (struct airo_info *ai) {
2962 union iwreq_data wrqu;
3c304956 2963 BSSListRid bss;
9e75af30
DW
2964 int rc;
2965 BSSListElement * loop_net;
2966 BSSListElement * tmp_net;
2967
2968 /* Blow away current list of scan results */
2969 list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
2970 list_move_tail (&loop_net->list, &ai->network_free_list);
2971 /* Don't blow away ->list, just BSS data */
2972 memset (loop_net, 0, sizeof (loop_net->bss));
2973 }
2974
2975 /* Try to read the first entry of the scan result */
3c304956 2976 rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0);
17e70491 2977 if((rc) || (bss.index == cpu_to_le16(0xffff))) {
9e75af30
DW
2978 /* No scan results */
2979 goto out;
2980 }
2981
2982 /* Read and parse all entries */
2983 tmp_net = NULL;
17e70491 2984 while((!rc) && (bss.index != cpu_to_le16(0xffff))) {
9e75af30
DW
2985 /* Grab a network off the free list */
2986 if (!list_empty(&ai->network_free_list)) {
2987 tmp_net = list_entry(ai->network_free_list.next,
2988 BSSListElement, list);
2989 list_del(ai->network_free_list.next);
2990 }
2991
2992 if (tmp_net != NULL) {
3c304956 2993 memcpy(tmp_net, &bss, sizeof(tmp_net->bss));
9e75af30
DW
2994 list_add_tail(&tmp_net->list, &ai->network_list);
2995 tmp_net = NULL;
2996 }
2997
2998 /* Read next entry */
3c304956
DW
2999 rc = PC4500_readrid(ai, ai->bssListNext,
3000 &bss, ai->bssListRidLen, 0);
9e75af30
DW
3001 }
3002
3003out:
3004 ai->scan_timeout = 0;
3c304956 3005 clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
9e75af30
DW
3006 up(&ai->sem);
3007
3008 /* Send an empty event to user space.
3009 * We don't send the received data on
3010 * the event because it would require
3011 * us to do complex transcoding, and
3012 * we want to minimise the work done in
3013 * the irq handler. Use a request to
3014 * extract the data - Jean II */
3015 wrqu.data.length = 0;
3016 wrqu.data.flags = 0;
3017 wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL);
3018}
3019
1da177e4
LT
3020static int airo_thread(void *data) {
3021 struct net_device *dev = data;
faf3994a 3022 struct airo_info *ai = dev->ml_priv;
1da177e4 3023 int locked;
83144186
RW
3024
3025 set_freezable();
1da177e4 3026 while(1) {
1da177e4 3027 /* make swsusp happy with our thread */
3e1d1d28 3028 try_to_freeze();
1da177e4 3029
3c304956 3030 if (test_bit(JOB_DIE, &ai->jobs))
1da177e4
LT
3031 break;
3032
3c304956 3033 if (ai->jobs) {
1da177e4
LT
3034 locked = down_interruptible(&ai->sem);
3035 } else {
3036 wait_queue_t wait;
3037
3038 init_waitqueue_entry(&wait, current);
3039 add_wait_queue(&ai->thr_wait, &wait);
3040 for (;;) {
3041 set_current_state(TASK_INTERRUPTIBLE);
3c304956 3042 if (ai->jobs)
1da177e4 3043 break;
9e75af30
DW
3044 if (ai->expires || ai->scan_timeout) {
3045 if (ai->scan_timeout &&
3046 time_after_eq(jiffies,ai->scan_timeout)){
3c304956 3047 set_bit(JOB_SCAN_RESULTS, &ai->jobs);
9e75af30
DW
3048 break;
3049 } else if (ai->expires &&
3050 time_after_eq(jiffies,ai->expires)){
3c304956 3051 set_bit(JOB_AUTOWEP, &ai->jobs);
1da177e4
LT
3052 break;
3053 }
5bb85f18
DK
3054 if (!kthread_should_stop() &&
3055 !freezing(current)) {
9e75af30
DW
3056 unsigned long wake_at;
3057 if (!ai->expires || !ai->scan_timeout) {
3058 wake_at = max(ai->expires,
3059 ai->scan_timeout);
3060 } else {
3061 wake_at = min(ai->expires,
3062 ai->scan_timeout);
3063 }
3064 schedule_timeout(wake_at - jiffies);
1da177e4
LT
3065 continue;
3066 }
5bb85f18
DK
3067 } else if (!kthread_should_stop() &&
3068 !freezing(current)) {
1da177e4
LT
3069 schedule();
3070 continue;
3071 }
3072 break;
3073 }
3074 current->state = TASK_RUNNING;
3075 remove_wait_queue(&ai->thr_wait, &wait);
3076 locked = 1;
3077 }
3078
3079 if (locked)
3080 continue;
3081
3c304956 3082 if (test_bit(JOB_DIE, &ai->jobs)) {
1da177e4
LT
3083 up(&ai->sem);
3084 break;
3085 }
3086
ca078bae 3087 if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
1da177e4
LT
3088 up(&ai->sem);
3089 continue;
3090 }
3091
3c304956 3092 if (test_bit(JOB_XMIT, &ai->jobs))
1da177e4 3093 airo_end_xmit(dev);
3c304956 3094 else if (test_bit(JOB_XMIT11, &ai->jobs))
1da177e4 3095 airo_end_xmit11(dev);
3c304956 3096 else if (test_bit(JOB_STATS, &ai->jobs))
5d9276da 3097 airo_read_stats(dev);
3c304956 3098 else if (test_bit(JOB_WSTATS, &ai->jobs))
1da177e4 3099 airo_read_wireless_stats(ai);
3c304956 3100 else if (test_bit(JOB_PROMISC, &ai->jobs))
1da177e4 3101 airo_set_promisc(ai);
3c304956 3102 else if (test_bit(JOB_MIC, &ai->jobs))
1da177e4 3103 micinit(ai);
3c304956 3104 else if (test_bit(JOB_EVENT, &ai->jobs))
1da177e4 3105 airo_send_event(dev);
3c304956 3106 else if (test_bit(JOB_AUTOWEP, &ai->jobs))
1da177e4 3107 timer_func(dev);
3c304956 3108 else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs))
9e75af30
DW
3109 airo_process_scan_results(ai);
3110 else /* Shouldn't get here, but we make sure to unlock */
3111 up(&ai->sem);
1da177e4 3112 }
3b4c7d64
SB
3113
3114 return 0;
1da177e4
LT
3115}
3116
0300b332
AV
3117static int header_len(__le16 ctl)
3118{
3119 u16 fc = le16_to_cpu(ctl);
3120 switch (fc & 0xc) {
3121 case 4:
3122 if ((fc & 0xe0) == 0xc0)
3123 return 10; /* one-address control packet */
3124 return 16; /* two-address control packet */
3125 case 8:
3126 if ((fc & 0x300) == 0x300)
3127 return 30; /* WDS packet */
3128 }
3129 return 24;
3130}
3131
f55d4517 3132static void airo_handle_cisco_mic(struct airo_info *ai)
28fc1f5a 3133{
f55d4517
DW
3134 if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) {
3135 set_bit(JOB_MIC, &ai->jobs);
3136 wake_up_interruptible(&ai->thr_wait);
3137 }
3138}
3139
3140/* Airo Status codes */
3141#define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */
3142#define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */
3143#define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
3144#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */
3145#define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
3146#define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */
3147#define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */
3148#define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */
3149#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */
3150#define STAT_ASSOC 0x0400 /* Associated */
3151#define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
3152
3153static void airo_print_status(const char *devname, u16 status)
3154{
3155 u8 reason = status & 0xFF;
3156
3157 switch (status) {
3158 case STAT_NOBEACON:
3159 airo_print_dbg(devname, "link lost (missed beacons)");
3160 break;
3161 case STAT_MAXRETRIES:
3162 case STAT_MAXARL:
3163 airo_print_dbg(devname, "link lost (max retries)");
3164 break;
3165 case STAT_FORCELOSS:
3166 airo_print_dbg(devname, "link lost (local choice)");
3167 break;
3168 case STAT_TSFSYNC:
3169 airo_print_dbg(devname, "link lost (TSF sync lost)");
3170 break;
3171 case STAT_DEAUTH:
3172 airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
3173 break;
3174 case STAT_DISASSOC:
3175 airo_print_dbg(devname, "disassociated (reason: %d)", reason);
3176 break;
3177 case STAT_ASSOC_FAIL:
3178 airo_print_dbg(devname, "association failed (reason: %d)",
3179 reason);
3180 break;
3181 case STAT_AUTH_FAIL:
3182 airo_print_dbg(devname, "authentication failed (reason: %d)",
3183 reason);
3184 break;
3185 default:
3186 break;
3187 }
3188}
3189
3190static void airo_handle_link(struct airo_info *ai)
3191{
3192 union iwreq_data wrqu;
3193 int scan_forceloss = 0;
1da177e4 3194 u16 status;
f55d4517
DW
3195
3196 /* Get new status and acknowledge the link change */
3197 status = le16_to_cpu(IN4500(ai, LINKSTAT));
3198 OUT4500(ai, EVACK, EV_LINK);
3199
3200 if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0))
3201 scan_forceloss = 1;
3202
3203 airo_print_status(ai->dev->name, status);
3204
3205 if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) {
3206 if (auto_wep)
3207 ai->expires = 0;
3208 if (ai->list_bss_task)
3209 wake_up_process(ai->list_bss_task);
3210 set_bit(FLAG_UPDATE_UNI, &ai->flags);
3211 set_bit(FLAG_UPDATE_MULTI, &ai->flags);
3212
3213 if (down_trylock(&ai->sem) != 0) {
3214 set_bit(JOB_EVENT, &ai->jobs);
3215 wake_up_interruptible(&ai->thr_wait);
3216 } else
3217 airo_send_event(ai->dev);
3218 } else if (!scan_forceloss) {
3219 if (auto_wep && !ai->expires) {
3220 ai->expires = RUN_AT(3*HZ);
3221 wake_up_interruptible(&ai->thr_wait);
3222 }
3223
3224 /* Send event to user space */
3225 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3226 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3227 wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL);
3228 }
3229}
3230
3231static void airo_handle_rx(struct airo_info *ai)
3232{
3233 struct sk_buff *skb = NULL;
3234 __le16 fc, v, *buffer, tmpbuf[4];
3235 u16 len, hdrlen = 0, gap, fid;
3236 struct rx_hdr hdr;
3237 int success = 0;
3238
3239 if (test_bit(FLAG_MPI, &ai->flags)) {
3240 if (test_bit(FLAG_802_11, &ai->flags))
3241 mpi_receive_802_11(ai);
3242 else
3243 mpi_receive_802_3(ai);
3244 OUT4500(ai, EVACK, EV_RX);
3245 return;
3246 }
3247
3248 fid = IN4500(ai, RXFID);
3249
3250 /* Get the packet length */
3251 if (test_bit(FLAG_802_11, &ai->flags)) {
3252 bap_setup (ai, fid, 4, BAP0);
3253 bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0);
3254 /* Bad CRC. Ignore packet */
3255 if (le16_to_cpu(hdr.status) & 2)
3256 hdr.len = 0;
3257 if (ai->wifidev == NULL)
3258 hdr.len = 0;
3259 } else {
3260 bap_setup(ai, fid, 0x36, BAP0);
3261 bap_read(ai, &hdr.len, 2, BAP0);
3262 }
3263 len = le16_to_cpu(hdr.len);
3264
3265 if (len > AIRO_DEF_MTU) {
3266 airo_print_err(ai->dev->name, "Bad size %d", len);
3267 goto done;
3268 }
3269 if (len == 0)
3270 goto done;
3271
3272 if (test_bit(FLAG_802_11, &ai->flags)) {
3273 bap_read(ai, &fc, sizeof (fc), BAP0);
3274 hdrlen = header_len(fc);
3275 } else
3276 hdrlen = ETH_ALEN * 2;
3277
3278 skb = dev_alloc_skb(len + hdrlen + 2 + 2);
3279 if (!skb) {
3280 ai->dev->stats.rx_dropped++;
3281 goto done;
3282 }
3283
3284 skb_reserve(skb, 2); /* This way the IP header is aligned */
3285 buffer = (__le16 *) skb_put(skb, len + hdrlen);
3286 if (test_bit(FLAG_802_11, &ai->flags)) {
3287 buffer[0] = fc;
3288 bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
3289 if (hdrlen == 24)
3290 bap_read(ai, tmpbuf, 6, BAP0);
3291
3292 bap_read(ai, &v, sizeof(v), BAP0);
3293 gap = le16_to_cpu(v);
3294 if (gap) {
3295 if (gap <= 8) {
3296 bap_read(ai, tmpbuf, gap, BAP0);
3297 } else {
3298 airo_print_err(ai->dev->name, "gaplen too "
3299 "big. Problems will follow...");
3300 }
3301 }
3302 bap_read(ai, buffer + hdrlen/2, len, BAP0);
3303 } else {
3304 MICBuffer micbuf;
3305
3306 bap_read(ai, buffer, ETH_ALEN * 2, BAP0);
3307 if (ai->micstats.enabled) {
3308 bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0);
3309 if (ntohs(micbuf.typelen) > 0x05DC)
3310 bap_setup(ai, fid, 0x44, BAP0);
3311 else {
3312 if (len <= sizeof (micbuf)) {
3313 dev_kfree_skb_irq(skb);
3314 goto done;
3315 }
3316
3317 len -= sizeof(micbuf);
3318 skb_trim(skb, len + hdrlen);
3319 }
3320 }
3321
3322 bap_read(ai, buffer + ETH_ALEN, len, BAP0);
3323 if (decapsulate(ai, &micbuf, (etherHead*) buffer, len))
3324 dev_kfree_skb_irq (skb);
3325 else
3326 success = 1;
3327 }
3328
3329#ifdef WIRELESS_SPY
3330 if (success && (ai->spy_data.spy_number > 0)) {
3331 char *sa;
3332 struct iw_quality wstats;
3333
3334 /* Prepare spy data : addr + qual */
3335 if (!test_bit(FLAG_802_11, &ai->flags)) {
3336 sa = (char *) buffer + 6;
3337 bap_setup(ai, fid, 8, BAP0);
3338 bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0);
3339 } else
3340 sa = (char *) buffer + 10;
3341 wstats.qual = hdr.rssi[0];
3342 if (ai->rssi)
3343 wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
3344 else
3345 wstats.level = (hdr.rssi[1] + 321) / 2;
3346 wstats.noise = ai->wstats.qual.noise;
3347 wstats.updated = IW_QUAL_LEVEL_UPDATED
3348 | IW_QUAL_QUAL_UPDATED
3349 | IW_QUAL_DBM;
3350 /* Update spy records */
3351 wireless_spy_update(ai->dev, sa, &wstats);
3352 }
3353#endif /* WIRELESS_SPY */
3354
3355done:
3356 OUT4500(ai, EVACK, EV_RX);
3357
3358 if (success) {
3359 if (test_bit(FLAG_802_11, &ai->flags)) {
3360 skb_reset_mac_header(skb);
3361 skb->pkt_type = PACKET_OTHERHOST;
3362 skb->dev = ai->wifidev;
3363 skb->protocol = htons(ETH_P_802_2);
3364 } else
3365 skb->protocol = eth_type_trans(skb, ai->dev);
3366 skb->ip_summed = CHECKSUM_NONE;
3367
3368 netif_rx(skb);
3369 }
3370}
3371
3372static void airo_handle_tx(struct airo_info *ai, u16 status)
3373{
3374 int i, len = 0, index = -1;
1da177e4 3375 u16 fid;
f55d4517
DW
3376
3377 if (test_bit(FLAG_MPI, &ai->flags)) {
3378 unsigned long flags;
3379
3380 if (status & EV_TXEXC)
3381 get_tx_error(ai, -1);
3382
3383 spin_lock_irqsave(&ai->aux_lock, flags);
3384 if (!skb_queue_empty(&ai->txq)) {
3385 spin_unlock_irqrestore(&ai->aux_lock,flags);
3386 mpi_send_packet(ai->dev);
3387 } else {
3388 clear_bit(FLAG_PENDING_XMIT, &ai->flags);
3389 spin_unlock_irqrestore(&ai->aux_lock,flags);
3390 netif_wake_queue(ai->dev);
3391 }
3392 OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3393 return;
3394 }
3395
3396 fid = IN4500(ai, TXCOMPLFID);
3397
3398 for(i = 0; i < MAX_FIDS; i++) {
3399 if ((ai->fids[i] & 0xffff) == fid) {
3400 len = ai->fids[i] >> 16;
3401 index = i;
3402 }
3403 }
3404
3405 if (index != -1) {
3406 if (status & EV_TXEXC)
3407 get_tx_error(ai, index);
3408
3409 OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC));
3410
3411 /* Set up to be used again */
3412 ai->fids[index] &= 0xffff;
3413 if (index < MAX_FIDS / 2) {
3414 if (!test_bit(FLAG_PENDING_XMIT, &ai->flags))
3415 netif_wake_queue(ai->dev);
3416 } else {
3417 if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags))
3418 netif_wake_queue(ai->wifidev);
3419 }
3420 } else {
3421 OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3422 airo_print_err(ai->dev->name, "Unallocated FID was used to xmit");
3423 }
3424}
3425
3426static irqreturn_t airo_interrupt(int irq, void *dev_id)
3427{
3428 struct net_device *dev = dev_id;
3429 u16 status, savedInterrupts = 0;
3430 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
3431 int handled = 0;
3432
3433 if (!netif_device_present(dev))
3434 return IRQ_NONE;
3435
3436 for (;;) {
f55d4517
DW
3437 status = IN4500(ai, EVSTAT);
3438 if (!(status & STATUS_INTS) || (status == 0xffff))
3439 break;
1da177e4
LT
3440
3441 handled = 1;
3442
f55d4517
DW
3443 if (status & EV_AWAKE) {
3444 OUT4500(ai, EVACK, EV_AWAKE);
3445 OUT4500(ai, EVACK, EV_AWAKE);
1da177e4
LT
3446 }
3447
3448 if (!savedInterrupts) {
f55d4517
DW
3449 savedInterrupts = IN4500(ai, EVINTEN);
3450 OUT4500(ai, EVINTEN, 0);
1da177e4
LT
3451 }
3452
f55d4517
DW
3453 if (status & EV_MIC) {
3454 OUT4500(ai, EVACK, EV_MIC);
3455 airo_handle_cisco_mic(ai);
1da177e4 3456 }
1da177e4 3457
f55d4517
DW
3458 if (status & EV_LINK) {
3459 /* Link status changed */
3460 airo_handle_link(ai);
1da177e4
LT
3461 }
3462
3463 /* Check to see if there is something to receive */
f55d4517
DW
3464 if (status & EV_RX)
3465 airo_handle_rx(ai);
1da177e4
LT
3466
3467 /* Check to see if a packet has been transmitted */
f55d4517
DW
3468 if (status & (EV_TX | EV_TXCPY | EV_TXEXC))
3469 airo_handle_tx(ai, status);
1da177e4 3470
f55d4517
DW
3471 if ( status & ~STATUS_INTS & ~IGNORE_INTS ) {
3472 airo_print_warn(ai->dev->name, "Got weird status %x",
1da177e4 3473 status & ~STATUS_INTS & ~IGNORE_INTS );
f55d4517 3474 }
1da177e4
LT
3475 }
3476
3477 if (savedInterrupts)
f55d4517 3478 OUT4500(ai, EVINTEN, savedInterrupts);
1da177e4 3479
1da177e4
LT
3480 return IRQ_RETVAL(handled);
3481}
3482
3483/*
3484 * Routines to talk to the card
3485 */
3486
3487/*
3488 * This was originally written for the 4500, hence the name
3489 * NOTE: If use with 8bit mode and SMP bad things will happen!
3490 * Why would some one do 8 bit IO in an SMP machine?!?
3491 */
3492static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) {
3493 if (test_bit(FLAG_MPI,&ai->flags))
3494 reg <<= 1;
3495 if ( !do8bitIO )
3496 outw( val, ai->dev->base_addr + reg );
3497 else {
3498 outb( val & 0xff, ai->dev->base_addr + reg );
3499 outb( val >> 8, ai->dev->base_addr + reg + 1 );
3500 }
3501}
3502
3503static u16 IN4500( struct airo_info *ai, u16 reg ) {
3504 unsigned short rc;
3505
3506 if (test_bit(FLAG_MPI,&ai->flags))
3507 reg <<= 1;
3508 if ( !do8bitIO )
3509 rc = inw( ai->dev->base_addr + reg );
3510 else {
3511 rc = inb( ai->dev->base_addr + reg );
3512 rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8;
3513 }
3514 return rc;
3515}
3516
175ec1a1
MS
3517static int enable_MAC(struct airo_info *ai, int lock)
3518{
1da177e4 3519 int rc;
175ec1a1
MS
3520 Cmd cmd;
3521 Resp rsp;
1da177e4
LT
3522
3523 /* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
3524 * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
3525 * Note : we could try to use !netif_running(dev) in enable_MAC()
3526 * instead of this flag, but I don't trust it *within* the
3527 * open/close functions, and testing both flags together is
3528 * "cheaper" - Jean II */
3529 if (ai->flags & FLAG_RADIO_MASK) return SUCCESS;
3530
3531 if (lock && down_interruptible(&ai->sem))
3532 return -ERESTARTSYS;
3533
3534 if (!test_bit(FLAG_ENABLED, &ai->flags)) {
3535 memset(&cmd, 0, sizeof(cmd));
3536 cmd.cmd = MAC_ENABLE;
175ec1a1 3537 rc = issuecommand(ai, &cmd, &rsp);
1da177e4
LT
3538 if (rc == SUCCESS)
3539 set_bit(FLAG_ENABLED, &ai->flags);
3540 } else
3541 rc = SUCCESS;
3542
3543 if (lock)
3544 up(&ai->sem);
3545
3546 if (rc)
175ec1a1
MS
3547 airo_print_err(ai->dev->name, "Cannot enable MAC");
3548 else if ((rsp.status & 0xFF00) != 0) {
3549 airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
3550 "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
3551 rc = ERROR;
3552 }
1da177e4
LT
3553 return rc;
3554}
3555
3556static void disable_MAC( struct airo_info *ai, int lock ) {
3557 Cmd cmd;
3558 Resp rsp;
3559
3560 if (lock && down_interruptible(&ai->sem))
3561 return;
3562
3563 if (test_bit(FLAG_ENABLED, &ai->flags)) {
3564 memset(&cmd, 0, sizeof(cmd));
3565 cmd.cmd = MAC_DISABLE; // disable in case already enabled
3566 issuecommand(ai, &cmd, &rsp);
3567 clear_bit(FLAG_ENABLED, &ai->flags);
3568 }
3569 if (lock)
3570 up(&ai->sem);
3571}
3572
3573static void enable_interrupts( struct airo_info *ai ) {
3574 /* Enable the interrupts */
3575 OUT4500( ai, EVINTEN, STATUS_INTS );
3576}
3577
3578static void disable_interrupts( struct airo_info *ai ) {
3579 OUT4500( ai, EVINTEN, 0 );
3580}
3581
3582static void mpi_receive_802_3(struct airo_info *ai)
3583{
3584 RxFid rxd;
3585 int len = 0;
3586 struct sk_buff *skb;
3587 char *buffer;
1da177e4
LT
3588 int off = 0;
3589 MICBuffer micbuf;
1da177e4
LT
3590
3591 memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
3592 /* Make sure we got something */
3593 if (rxd.rdy && rxd.valid == 0) {
3594 len = rxd.len + 12;
3595 if (len < 12 || len > 2048)
3596 goto badrx;
3597
3598 skb = dev_alloc_skb(len);
3599 if (!skb) {
5d9276da 3600 ai->dev->stats.rx_dropped++;
1da177e4
LT
3601 goto badrx;
3602 }
3603 buffer = skb_put(skb,len);
1da177e4
LT
3604 memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
3605 if (ai->micstats.enabled) {
3606 memcpy(&micbuf,
3607 ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2,
3608 sizeof(micbuf));
3609 if (ntohs(micbuf.typelen) <= 0x05DC) {
3610 if (len <= sizeof(micbuf) + ETH_ALEN * 2)
3611 goto badmic;
3612
3613 off = sizeof(micbuf);
3614 skb_trim (skb, len - off);
3615 }
3616 }
3617 memcpy(buffer + ETH_ALEN * 2,
3618 ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off,
3619 len - ETH_ALEN * 2 - off);
3620 if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) {
3621badmic:
3622 dev_kfree_skb_irq (skb);
3623 goto badrx;
3624 }
1da177e4
LT
3625#ifdef WIRELESS_SPY
3626 if (ai->spy_data.spy_number > 0) {
3627 char *sa;
3628 struct iw_quality wstats;
3629 /* Prepare spy data : addr + qual */
3630 sa = buffer + ETH_ALEN;
3631 wstats.qual = 0; /* XXX Where do I get that info from ??? */
3632 wstats.level = 0;
3633 wstats.updated = 0;
3634 /* Update spy records */
3635 wireless_spy_update(ai->dev, sa, &wstats);
3636 }
3637#endif /* WIRELESS_SPY */
3638
1da177e4
LT
3639 skb->ip_summed = CHECKSUM_NONE;
3640 skb->protocol = eth_type_trans(skb, ai->dev);
1da177e4
LT
3641 netif_rx(skb);
3642 }
3643badrx:
3644 if (rxd.valid == 0) {
3645 rxd.valid = 1;
3646 rxd.rdy = 0;
3647 rxd.len = PKTSIZE;
3648 memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd));
3649 }
3650}
3651
2ed5ba89 3652static void mpi_receive_802_11(struct airo_info *ai)
1da177e4
LT
3653{
3654 RxFid rxd;
3655 struct sk_buff *skb = NULL;
0300b332
AV
3656 u16 len, hdrlen = 0;
3657 __le16 fc;
f55d4517 3658 struct rx_hdr hdr;
1da177e4
LT
3659 u16 gap;
3660 u16 *buffer;
f55d4517 3661 char *ptr = ai->rxfids[0].virtual_host_addr + 4;
1da177e4
LT
3662
3663 memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
3664 memcpy ((char *)&hdr, ptr, sizeof(hdr));
3665 ptr += sizeof(hdr);
3666 /* Bad CRC. Ignore packet */
3667 if (le16_to_cpu(hdr.status) & 2)
3668 hdr.len = 0;
3669 if (ai->wifidev == NULL)
3670 hdr.len = 0;
3671 len = le16_to_cpu(hdr.len);
15db2763 3672 if (len > AIRO_DEF_MTU) {
934d8bf1 3673 airo_print_err(ai->dev->name, "Bad size %d", len);
1da177e4
LT
3674 goto badrx;
3675 }
3676 if (len == 0)
3677 goto badrx;
3678
0300b332
AV
3679 fc = get_unaligned((__le16 *)ptr);
3680 hdrlen = header_len(fc);
1da177e4
LT
3681
3682 skb = dev_alloc_skb( len + hdrlen + 2 );
3683 if ( !skb ) {
5d9276da 3684 ai->dev->stats.rx_dropped++;
1da177e4
LT
3685 goto badrx;
3686 }
3687 buffer = (u16*)skb_put (skb, len + hdrlen);
3688 memcpy ((char *)buffer, ptr, hdrlen);
3689 ptr += hdrlen;
3690 if (hdrlen == 24)
3691 ptr += 6;
533dd1b0 3692 gap = get_unaligned_le16(ptr);
593c2b9c 3693 ptr += sizeof(__le16);
1da177e4
LT
3694 if (gap) {
3695 if (gap <= 8)
3696 ptr += gap;
3697 else
934d8bf1
DW
3698 airo_print_err(ai->dev->name,
3699 "gaplen too big. Problems will follow...");
1da177e4
LT
3700 }
3701 memcpy ((char *)buffer + hdrlen, ptr, len);
3702 ptr += len;
3703#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
3704 if (ai->spy_data.spy_number > 0) {
3705 char *sa;
3706 struct iw_quality wstats;
3707 /* Prepare spy data : addr + qual */
3708 sa = (char*)buffer + 10;
3709 wstats.qual = hdr.rssi[0];
3710 if (ai->rssi)
3711 wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
3712 else
3713 wstats.level = (hdr.rssi[1] + 321) / 2;
41480af2
DW
3714 wstats.noise = ai->wstats.qual.noise;
3715 wstats.updated = IW_QUAL_QUAL_UPDATED
3716 | IW_QUAL_LEVEL_UPDATED
ce6623c3 3717 | IW_QUAL_DBM;
1da177e4
LT
3718 /* Update spy records */
3719 wireless_spy_update(ai->dev, sa, &wstats);
3720 }
3721#endif /* IW_WIRELESS_SPY */
459a98ed 3722 skb_reset_mac_header(skb);
1da177e4
LT
3723 skb->pkt_type = PACKET_OTHERHOST;
3724 skb->dev = ai->wifidev;
3725 skb->protocol = htons(ETH_P_802_2);
1da177e4
LT
3726 skb->ip_summed = CHECKSUM_NONE;
3727 netif_rx( skb );
f55d4517 3728
1da177e4
LT
3729badrx:
3730 if (rxd.valid == 0) {
3731 rxd.valid = 1;
3732 rxd.rdy = 0;
3733 rxd.len = PKTSIZE;
3734 memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd));
3735 }
3736}
3737
3738static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
3739{
3740 Cmd cmd;
3741 Resp rsp;
3742 int status;
3743 int i;
3744 SsidRid mySsid;
4293ea33 3745 __le16 lastindex;
1da177e4
LT
3746 WepKeyRid wkr;
3747 int rc;
3748
3749 memset( &mySsid, 0, sizeof( mySsid ) );
b4558ea9
JJ
3750 kfree (ai->flash);
3751 ai->flash = NULL;
1da177e4
LT
3752
3753 /* The NOP is the first step in getting the card going */
3754 cmd.cmd = NOP;
3755 cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;
3756 if (lock && down_interruptible(&ai->sem))
3757 return ERROR;
3758 if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {
3759 if (lock)
3760 up(&ai->sem);
3761 return ERROR;
3762 }
3763 disable_MAC( ai, 0);
3764
3765 // Let's figure out if we need to use the AUX port
3766 if (!test_bit(FLAG_MPI,&ai->flags)) {
3767 cmd.cmd = CMD_ENABLEAUX;
3768 if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
3769 if (lock)
3770 up(&ai->sem);
934d8bf1 3771 airo_print_err(ai->dev->name, "Error checking for AUX port");
1da177e4
LT
3772 return ERROR;
3773 }
3774 if (!aux_bap || rsp.status & 0xff00) {
3775 ai->bap_read = fast_bap_read;
934d8bf1 3776 airo_print_dbg(ai->dev->name, "Doing fast bap_reads");
1da177e4
LT
3777 } else {
3778 ai->bap_read = aux_bap_read;
934d8bf1 3779 airo_print_dbg(ai->dev->name, "Doing AUX bap_reads");
1da177e4
LT
3780 }
3781 }
3782 if (lock)
3783 up(&ai->sem);
3784 if (ai->config.len == 0) {
3785 tdsRssiRid rssi_rid;
3786 CapabilityRid cap_rid;
3787
b4558ea9
JJ
3788 kfree(ai->APList);
3789 ai->APList = NULL;
3790 kfree(ai->SSID);
3791 ai->SSID = NULL;
1da177e4
LT
3792 // general configuration (read/modify/write)
3793 status = readConfigRid(ai, lock);
3794 if ( status != SUCCESS ) return ERROR;
3795
3796 status = readCapabilityRid(ai, &cap_rid, lock);
3797 if ( status != SUCCESS ) return ERROR;
3798
3799 status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
3800 if ( status == SUCCESS ) {
3801 if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
41480af2 3802 memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
1da177e4
LT
3803 }
3804 else {
b4558ea9
JJ
3805 kfree(ai->rssi);
3806 ai->rssi = NULL;
56d81bd3 3807 if (cap_rid.softCap & cpu_to_le16(8))
1da177e4
LT
3808 ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
3809 else
934d8bf1
DW
3810 airo_print_warn(ai->dev->name, "unknown received signal "
3811 "level scale");
1da177e4
LT
3812 }
3813 ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
3814 ai->config.authType = AUTH_OPEN;
3815 ai->config.modulation = MOD_CCK;
3816
56d81bd3 3817 if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
15617858 3818 (cap_rid.extSoftCap & cpu_to_le16(1)) &&
56d81bd3 3819 micsetup(ai) == SUCCESS) {
1da177e4
LT
3820 ai->config.opmode |= MODE_MIC;
3821 set_bit(FLAG_MIC_CAPABLE, &ai->flags);
3822 }
1da177e4
LT
3823
3824 /* Save off the MAC */
3825 for( i = 0; i < ETH_ALEN; i++ ) {
3826 mac[i] = ai->config.macAddr[i];
3827 }
3828
3829 /* Check to see if there are any insmod configured
3830 rates to add */
3831 if ( rates[0] ) {
3832 int i = 0;
3833 memset(ai->config.rates,0,sizeof(ai->config.rates));
3834 for( i = 0; i < 8 && rates[i]; i++ ) {
3835 ai->config.rates[i] = rates[i];
3836 }
3837 }
3838 if ( basic_rate > 0 ) {
3839 int i;
3840 for( i = 0; i < 8; i++ ) {
3841 if ( ai->config.rates[i] == basic_rate ||
3842 !ai->config.rates ) {
3843 ai->config.rates[i] = basic_rate | 0x80;
3844 break;
3845 }
3846 }
3847 }
3848 set_bit (FLAG_COMMIT, &ai->flags);
3849 }
3850
3851 /* Setup the SSIDs if present */
3852 if ( ssids[0] ) {
3853 int i;
3854 for( i = 0; i < 3 && ssids[i]; i++ ) {
0dd2212f
AV
3855 size_t len = strlen(ssids[i]);
3856 if (len > 32)
3857 len = 32;
3858 mySsid.ssids[i].len = cpu_to_le16(len);
3859 memcpy(mySsid.ssids[i].ssid, ssids[i], len);
1da177e4 3860 }
0dd2212f 3861 mySsid.len = cpu_to_le16(sizeof(mySsid));
1da177e4
LT
3862 }
3863
3864 status = writeConfigRid(ai, lock);
3865 if ( status != SUCCESS ) return ERROR;
3866
3867 /* Set up the SSID list */
3868 if ( ssids[0] ) {
3869 status = writeSsidRid(ai, &mySsid, lock);
3870 if ( status != SUCCESS ) return ERROR;
3871 }
3872
175ec1a1
MS
3873 status = enable_MAC(ai, lock);
3874 if (status != SUCCESS)
1da177e4 3875 return ERROR;
1da177e4
LT
3876
3877 /* Grab the initial wep key, we gotta save it for auto_wep */
3878 rc = readWepKeyRid(ai, &wkr, 1, lock);
3879 if (rc == SUCCESS) do {
3880 lastindex = wkr.kindex;
4293ea33 3881 if (wkr.kindex == cpu_to_le16(0xffff)) {
1da177e4
LT
3882 ai->defindex = wkr.mac[0];
3883 }
3884 rc = readWepKeyRid(ai, &wkr, 0, lock);
3885 } while(lastindex != wkr.kindex);
3886
1c2b7db8 3887 try_auto_wep(ai);
1da177e4
LT
3888
3889 return SUCCESS;
3890}
3891
3892static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
3893 // Im really paranoid about letting it run forever!
3894 int max_tries = 600000;
3895
3896 if (IN4500(ai, EVSTAT) & EV_CMD)
3897 OUT4500(ai, EVACK, EV_CMD);
3898
3899 OUT4500(ai, PARAM0, pCmd->parm0);
3900 OUT4500(ai, PARAM1, pCmd->parm1);
3901 OUT4500(ai, PARAM2, pCmd->parm2);
3902 OUT4500(ai, COMMAND, pCmd->cmd);
3903
3904 while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
3905 if ((IN4500(ai, COMMAND)) == pCmd->cmd)
3906 // PC4500 didn't notice command, try again
3907 OUT4500(ai, COMMAND, pCmd->cmd);
3908 if (!in_atomic() && (max_tries & 255) == 0)
3909 schedule();
3910 }
3911
3912 if ( max_tries == -1 ) {
934d8bf1
DW
3913 airo_print_err(ai->dev->name,
3914 "Max tries exceeded when issueing command");
1da177e4
LT
3915 if (IN4500(ai, COMMAND) & COMMAND_BUSY)
3916 OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
3917 return ERROR;
3918 }
3919
3920 // command completed
3921 pRsp->status = IN4500(ai, STATUS);
3922 pRsp->rsp0 = IN4500(ai, RESP0);
3923 pRsp->rsp1 = IN4500(ai, RESP1);
3924 pRsp->rsp2 = IN4500(ai, RESP2);
13dca9b8
RS
3925 if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET)
3926 airo_print_err(ai->dev->name,
3927 "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x",
3928 pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1,
3929 pRsp->rsp2);
1da177e4
LT
3930
3931 // clear stuck command busy if necessary
3932 if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
3933 OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
3934 }
3935 // acknowledge processing the status/response
3936 OUT4500(ai, EVACK, EV_CMD);
3937
3938 return SUCCESS;
3939}
3940
3941/* Sets up the bap to start exchange data. whichbap should
3942 * be one of the BAP0 or BAP1 defines. Locks should be held before
3943 * calling! */
3944static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
3945{
3946 int timeout = 50;
3947 int max_tries = 3;
3948
3949 OUT4500(ai, SELECT0+whichbap, rid);
3950 OUT4500(ai, OFFSET0+whichbap, offset);
3951 while (1) {
3952 int status = IN4500(ai, OFFSET0+whichbap);
3953 if (status & BAP_BUSY) {
3954 /* This isn't really a timeout, but its kinda
3955 close */
3956 if (timeout--) {
3957 continue;
3958 }
3959 } else if ( status & BAP_ERR ) {
3960 /* invalid rid or offset */
934d8bf1 3961 airo_print_err(ai->dev->name, "BAP error %x %d",
1da177e4
LT
3962 status, whichbap );
3963 return ERROR;
3964 } else if (status & BAP_DONE) { // success
3965 return SUCCESS;
3966 }
3967 if ( !(max_tries--) ) {
934d8bf1 3968 airo_print_err(ai->dev->name,
1138c37b 3969 "BAP setup error too many retries\n");
1da177e4
LT
3970 return ERROR;
3971 }
3972 // -- PC4500 missed it, try again
3973 OUT4500(ai, SELECT0+whichbap, rid);
3974 OUT4500(ai, OFFSET0+whichbap, offset);
3975 timeout = 50;
3976 }
3977}
3978
3979/* should only be called by aux_bap_read. This aux function and the
3980 following use concepts not documented in the developers guide. I
3981 got them from a patch given to my by Aironet */
3982static u16 aux_setup(struct airo_info *ai, u16 page,
3983 u16 offset, u16 *len)
3984{
3985 u16 next;
3986
3987 OUT4500(ai, AUXPAGE, page);
3988 OUT4500(ai, AUXOFF, 0);
3989 next = IN4500(ai, AUXDATA);
3990 *len = IN4500(ai, AUXDATA)&0xff;
3991 if (offset != 4) OUT4500(ai, AUXOFF, offset);
3992 return next;
3993}
3994
3995/* requires call to bap_setup() first */
b8c06bc1 3996static int aux_bap_read(struct airo_info *ai, __le16 *pu16Dst,
1da177e4
LT
3997 int bytelen, int whichbap)
3998{
3999 u16 len;
4000 u16 page;
4001 u16 offset;
4002 u16 next;
4003 int words;
4004 int i;
4005 unsigned long flags;
4006
4007 spin_lock_irqsave(&ai->aux_lock, flags);
4008 page = IN4500(ai, SWS0+whichbap);
4009 offset = IN4500(ai, SWS2+whichbap);
4010 next = aux_setup(ai, page, offset, &len);
4011 words = (bytelen+1)>>1;
4012
4013 for (i=0; i<words;) {
4014 int count;
4015 count = (len>>1) < (words-i) ? (len>>1) : (words-i);
4016 if ( !do8bitIO )
4017 insw( ai->dev->base_addr+DATA0+whichbap,
4018 pu16Dst+i,count );
4019 else
4020 insb( ai->dev->base_addr+DATA0+whichbap,
4021 pu16Dst+i, count << 1 );
4022 i += count;
4023 if (i<words) {
4024 next = aux_setup(ai, next, 4, &len);
4025 }
4026 }
4027 spin_unlock_irqrestore(&ai->aux_lock, flags);
4028 return SUCCESS;
4029}
4030
4031
4032/* requires call to bap_setup() first */
b8c06bc1 4033static int fast_bap_read(struct airo_info *ai, __le16 *pu16Dst,
1da177e4
LT
4034 int bytelen, int whichbap)
4035{
4036 bytelen = (bytelen + 1) & (~1); // round up to even value
4037 if ( !do8bitIO )
4038 insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 );
4039 else
4040 insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen );
4041 return SUCCESS;
4042}
4043
4044/* requires call to bap_setup() first */
b8c06bc1 4045static int bap_write(struct airo_info *ai, const __le16 *pu16Src,
1da177e4
LT
4046 int bytelen, int whichbap)
4047{
4048 bytelen = (bytelen + 1) & (~1); // round up to even value
4049 if ( !do8bitIO )
4050 outsw( ai->dev->base_addr+DATA0+whichbap,
4051 pu16Src, bytelen>>1 );
4052 else
4053 outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen );
4054 return SUCCESS;
4055}
4056
4057static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
4058{
4059 Cmd cmd; /* for issuing commands */
4060 Resp rsp; /* response from commands */
4061 u16 status;
4062
4063 memset(&cmd, 0, sizeof(cmd));
4064 cmd.cmd = accmd;
4065 cmd.parm0 = rid;
4066 status = issuecommand(ai, &cmd, &rsp);
4067 if (status != 0) return status;
4068 if ( (rsp.status & 0x7F00) != 0) {
4069 return (accmd << 8) + (rsp.rsp0 & 0xFF);
4070 }
4071 return 0;
4072}
4073
4074/* Note, that we are using BAP1 which is also used by transmit, so
4075 * we must get a lock. */
4076static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, int lock)
4077{
4078 u16 status;
4079 int rc = SUCCESS;
4080
4081 if (lock) {
4082 if (down_interruptible(&ai->sem))
4083 return ERROR;
4084 }
4085 if (test_bit(FLAG_MPI,&ai->flags)) {
4086 Cmd cmd;
4087 Resp rsp;
4088
4089 memset(&cmd, 0, sizeof(cmd));
4090 memset(&rsp, 0, sizeof(rsp));
4091 ai->config_desc.rid_desc.valid = 1;
4092 ai->config_desc.rid_desc.len = RIDSIZE;
4093 ai->config_desc.rid_desc.rid = 0;
4094 ai->config_desc.rid_desc.host_addr = ai->ridbus;
4095
4096 cmd.cmd = CMD_ACCESS;
4097 cmd.parm0 = rid;
4098
4099 memcpy_toio(ai->config_desc.card_ram_off,
4100 &ai->config_desc.rid_desc, sizeof(Rid));
4101
4102 rc = issuecommand(ai, &cmd, &rsp);
4103
4104 if (rsp.status & 0x7f00)
4105 rc = rsp.rsp0;
4106 if (!rc)
4107 memcpy(pBuf, ai->config_desc.virtual_host_addr, len);
4108 goto done;
4109 } else {
4110 if ((status = PC4500_accessrid(ai, rid, CMD_ACCESS))!=SUCCESS) {
4111 rc = status;
4112 goto done;
4113 }
4114 if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
4115 rc = ERROR;
4116 goto done;
4117 }
4118 // read the rid length field
4119 bap_read(ai, pBuf, 2, BAP1);
4120 // length for remaining part of rid
593c2b9c 4121 len = min(len, (int)le16_to_cpu(*(__le16*)pBuf)) - 2;
1da177e4
LT
4122
4123 if ( len <= 2 ) {
934d8bf1
DW
4124 airo_print_err(ai->dev->name,
4125 "Rid %x has a length of %d which is too short",
1da177e4
LT
4126 (int)rid, (int)len );
4127 rc = ERROR;
4128 goto done;
4129 }
4130 // read remainder of the rid
b8c06bc1 4131 rc = bap_read(ai, ((__le16*)pBuf)+1, len, BAP1);
1da177e4
LT
4132 }
4133done:
4134 if (lock)
4135 up(&ai->sem);
4136 return rc;
4137}
4138
4139/* Note, that we are using BAP1 which is also used by transmit, so
4140 * make sure this isnt called when a transmit is happening */
4141static int PC4500_writerid(struct airo_info *ai, u16 rid,
4142 const void *pBuf, int len, int lock)
4143{
4144 u16 status;
4145 int rc = SUCCESS;
4146
593c2b9c 4147 *(__le16*)pBuf = cpu_to_le16((u16)len);
1da177e4
LT
4148
4149 if (lock) {
4150 if (down_interruptible(&ai->sem))
4151 return ERROR;
4152 }
4153 if (test_bit(FLAG_MPI,&ai->flags)) {
4154 Cmd cmd;
4155 Resp rsp;
4156
f89b2321 4157 if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
934d8bf1
DW
4158 airo_print_err(ai->dev->name,
4159 "%s: MAC should be disabled (rid=%04x)",
c94c93da 4160 __func__, rid);
1da177e4
LT
4161 memset(&cmd, 0, sizeof(cmd));
4162 memset(&rsp, 0, sizeof(rsp));
4163
4164 ai->config_desc.rid_desc.valid = 1;
4165 ai->config_desc.rid_desc.len = *((u16 *)pBuf);
4166 ai->config_desc.rid_desc.rid = 0;
4167
4168 cmd.cmd = CMD_WRITERID;
4169 cmd.parm0 = rid;
4170
4171 memcpy_toio(ai->config_desc.card_ram_off,
4172 &ai->config_desc.rid_desc, sizeof(Rid));
4173
4174 if (len < 4 || len > 2047) {
c94c93da 4175 airo_print_err(ai->dev->name, "%s: len=%d", __func__, len);
1da177e4
LT
4176 rc = -1;
4177 } else {
4178 memcpy((char *)ai->config_desc.virtual_host_addr,
4179 pBuf, len);
4180
4181 rc = issuecommand(ai, &cmd, &rsp);
4182 if ((rc & 0xff00) != 0) {
934d8bf1 4183 airo_print_err(ai->dev->name, "%s: Write rid Error %d",
c94c93da 4184 __func__, rc);
934d8bf1 4185 airo_print_err(ai->dev->name, "%s: Cmd=%04x",
c94c93da 4186 __func__, cmd.cmd);
1da177e4
LT
4187 }
4188
4189 if ((rsp.status & 0x7f00))
4190 rc = rsp.rsp0;
4191 }
4192 } else {
4193 // --- first access so that we can write the rid data
4194 if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) {
4195 rc = status;
4196 goto done;
4197 }
4198 // --- now write the rid data
4199 if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
4200 rc = ERROR;
4201 goto done;
4202 }
4203 bap_write(ai, pBuf, len, BAP1);
4204 // ---now commit the rid data
4205 rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS);
4206 }
4207done:
4208 if (lock)
4209 up(&ai->sem);
4210 return rc;
4211}
4212
4213/* Allocates a FID to be used for transmitting packets. We only use
4214 one for now. */
4215static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
4216{
4217 unsigned int loop = 3000;
4218 Cmd cmd;
4219 Resp rsp;
4220 u16 txFid;
593c2b9c 4221 __le16 txControl;
1da177e4
LT
4222
4223 cmd.cmd = CMD_ALLOCATETX;
4224 cmd.parm0 = lenPayload;
4225 if (down_interruptible(&ai->sem))
4226 return ERROR;
4227 if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
4228 txFid = ERROR;
4229 goto done;
4230 }
4231 if ( (rsp.status & 0xFF00) != 0) {
4232 txFid = ERROR;
4233 goto done;
4234 }
4235 /* wait for the allocate event/indication
4236 * It makes me kind of nervous that this can just sit here and spin,
4237 * but in practice it only loops like four times. */
4238 while (((IN4500(ai, EVSTAT) & EV_ALLOC) == 0) && --loop);
4239 if (!loop) {
4240 txFid = ERROR;
4241 goto done;
4242 }
4243
4244 // get the allocated fid and acknowledge
4245 txFid = IN4500(ai, TXALLOCFID);
4246 OUT4500(ai, EVACK, EV_ALLOC);
4247
4248 /* The CARD is pretty cool since it converts the ethernet packet
4249 * into 802.11. Also note that we don't release the FID since we
4250 * will be using the same one over and over again. */
4251 /* We only have to setup the control once since we are not
4252 * releasing the fid. */
4253 if (raw)
4254 txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_11
4255 | TXCTL_ETHERNET | TXCTL_NORELEASE);
4256 else
4257 txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3
4258 | TXCTL_ETHERNET | TXCTL_NORELEASE);
4259 if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS)
4260 txFid = ERROR;
4261 else
4262 bap_write(ai, &txControl, sizeof(txControl), BAP1);
4263
4264done:
4265 up(&ai->sem);
4266
4267 return txFid;
4268}
4269
4270/* In general BAP1 is dedicated to transmiting packets. However,
4271 since we need a BAP when accessing RIDs, we also use BAP1 for that.
4272 Make sure the BAP1 spinlock is held when this is called. */
4273static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
4274{
593c2b9c 4275 __le16 payloadLen;
1da177e4
LT
4276 Cmd cmd;
4277 Resp rsp;
4278 int miclen = 0;
4279 u16 txFid = len;
4280 MICBuffer pMic;
4281
4282 len >>= 16;
4283
4284 if (len <= ETH_ALEN * 2) {
934d8bf1 4285 airo_print_warn(ai->dev->name, "Short packet %d", len);
1da177e4
LT
4286 return ERROR;
4287 }
4288 len -= ETH_ALEN * 2;
4289
1da177e4 4290 if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
593c2b9c 4291 (ntohs(((__be16 *)pPacket)[6]) != 0x888E)) {
1da177e4
LT
4292 if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
4293 return ERROR;
4294 miclen = sizeof(pMic);
4295 }
1da177e4
LT
4296 // packet is destination[6], source[6], payload[len-12]
4297 // write the payload length and dst/src/payload
4298 if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
4299 /* The hardware addresses aren't counted as part of the payload, so
4300 * we have to subtract the 12 bytes for the addresses off */
4301 payloadLen = cpu_to_le16(len + miclen);
4302 bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
b8c06bc1 4303 bap_write(ai, (__le16*)pPacket, sizeof(etherHead), BAP1);
1da177e4 4304 if (miclen)
b8c06bc1
AV
4305 bap_write(ai, (__le16*)&pMic, miclen, BAP1);
4306 bap_write(ai, (__le16*)(pPacket + sizeof(etherHead)), len, BAP1);
1da177e4
LT
4307 // issue the transmit command
4308 memset( &cmd, 0, sizeof( cmd ) );
4309 cmd.cmd = CMD_TRANSMIT;
4310 cmd.parm0 = txFid;
4311 if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
4312 if ( (rsp.status & 0xFF00) != 0) return ERROR;
4313 return SUCCESS;
4314}
4315
4316static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
4317{
593c2b9c 4318 __le16 fc, payloadLen;
1da177e4
LT
4319 Cmd cmd;
4320 Resp rsp;
4321 int hdrlen;
977b143c
AV
4322 static u8 tail[(30-10) + 2 + 6] = {[30-10] = 6};
4323 /* padding of header to full size + le16 gaplen (6) + gaplen bytes */
1da177e4
LT
4324 u16 txFid = len;
4325 len >>= 16;
1da177e4 4326
0300b332
AV
4327 fc = *(__le16*)pPacket;
4328 hdrlen = header_len(fc);
1da177e4
LT
4329
4330 if (len < hdrlen) {
934d8bf1 4331 airo_print_warn(ai->dev->name, "Short packet %d", len);
1da177e4
LT
4332 return ERROR;
4333 }
4334
4335 /* packet is 802.11 header + payload
4336 * write the payload length and dst/src/payload */
4337 if (bap_setup(ai, txFid, 6, BAP1) != SUCCESS) return ERROR;
4338 /* The 802.11 header aren't counted as part of the payload, so
4339 * we have to subtract the header bytes off */
4340 payloadLen = cpu_to_le16(len-hdrlen);
4341 bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
4342 if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR;
b8c06bc1
AV
4343 bap_write(ai, (__le16 *)pPacket, hdrlen, BAP1);
4344 bap_write(ai, (__le16 *)(tail + (hdrlen - 10)), 38 - hdrlen, BAP1);
1da177e4 4345
b8c06bc1 4346 bap_write(ai, (__le16 *)(pPacket + hdrlen), len - hdrlen, BAP1);
1da177e4
LT
4347 // issue the transmit command
4348 memset( &cmd, 0, sizeof( cmd ) );
4349 cmd.cmd = CMD_TRANSMIT;
4350 cmd.parm0 = txFid;
4351 if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
4352 if ( (rsp.status & 0xFF00) != 0) return ERROR;
4353 return SUCCESS;
4354}
4355
4356/*
4357 * This is the proc_fs routines. It is a bit messier than I would
4358 * like! Feel free to clean it up!
4359 */
4360
4361static ssize_t proc_read( struct file *file,
4362 char __user *buffer,
4363 size_t len,
4364 loff_t *offset);
4365
4366static ssize_t proc_write( struct file *file,
4367 const char __user *buffer,
4368 size_t len,
4369 loff_t *offset );
4370static int proc_close( struct inode *inode, struct file *file );
4371
4372static int proc_stats_open( struct inode *inode, struct file *file );
4373static int proc_statsdelta_open( struct inode *inode, struct file *file );
4374static int proc_status_open( struct inode *inode, struct file *file );
4375static int proc_SSID_open( struct inode *inode, struct file *file );
4376static int proc_APList_open( struct inode *inode, struct file *file );
4377static int proc_BSSList_open( struct inode *inode, struct file *file );
4378static int proc_config_open( struct inode *inode, struct file *file );
4379static int proc_wepkey_open( struct inode *inode, struct file *file );
4380
d54b1fdb 4381static const struct file_operations proc_statsdelta_ops = {
a95609cb 4382 .owner = THIS_MODULE,
1da177e4
LT
4383 .read = proc_read,
4384 .open = proc_statsdelta_open,
4385 .release = proc_close
4386};
4387
d54b1fdb 4388static const struct file_operations proc_stats_ops = {
a95609cb 4389 .owner = THIS_MODULE,
1da177e4
LT
4390 .read = proc_read,
4391 .open = proc_stats_open,
4392 .release = proc_close
4393};
4394
d54b1fdb 4395static const struct file_operations proc_status_ops = {
a95609cb 4396 .owner = THIS_MODULE,
1da177e4
LT
4397 .read = proc_read,
4398 .open = proc_status_open,
4399 .release = proc_close
4400};
4401
d54b1fdb 4402static const struct file_operations proc_SSID_ops = {
a95609cb 4403 .owner = THIS_MODULE,
1da177e4
LT
4404 .read = proc_read,
4405 .write = proc_write,
4406 .open = proc_SSID_open,
4407 .release = proc_close
4408};
4409
d54b1fdb 4410static const struct file_operations proc_BSSList_ops = {
a95609cb 4411 .owner = THIS_MODULE,
1da177e4
LT
4412 .read = proc_read,
4413 .write = proc_write,
4414 .open = proc_BSSList_open,
4415 .release = proc_close
4416};
4417
d54b1fdb 4418static const struct file_operations proc_APList_ops = {
a95609cb 4419 .owner = THIS_MODULE,
1da177e4
LT
4420 .read = proc_read,
4421 .write = proc_write,
4422 .open = proc_APList_open,
4423 .release = proc_close
4424};
4425
d54b1fdb 4426static const struct file_operations proc_config_ops = {
a95609cb 4427 .owner = THIS_MODULE,
1da177e4
LT
4428 .read = proc_read,
4429 .write = proc_write,
4430 .open = proc_config_open,
4431 .release = proc_close
4432};
4433
d54b1fdb 4434static const struct file_operations proc_wepkey_ops = {
a95609cb 4435 .owner = THIS_MODULE,
1da177e4
LT
4436 .read = proc_read,
4437 .write = proc_write,
4438 .open = proc_wepkey_open,
4439 .release = proc_close
4440};
4441
4442static struct proc_dir_entry *airo_entry;
4443
4444struct proc_data {
4445 int release_buffer;
4446 int readlen;
4447 char *rbuffer;
4448 int writelen;
4449 int maxwritelen;
4450 char *wbuffer;
4451 void (*on_close) (struct inode *, struct file *);
4452};
4453
1da177e4
LT
4454static int setup_proc_entry( struct net_device *dev,
4455 struct airo_info *apriv ) {
4456 struct proc_dir_entry *entry;
4457 /* First setup the device directory */
4458 strcpy(apriv->proc_name,dev->name);
4459 apriv->proc_entry = create_proc_entry(apriv->proc_name,
4460 S_IFDIR|airo_perm,
4461 airo_entry);
431aca5a
FM
4462 if (!apriv->proc_entry)
4463 goto fail;
4464 apriv->proc_entry->uid = proc_uid;
4465 apriv->proc_entry->gid = proc_gid;
4466 apriv->proc_entry->owner = THIS_MODULE;
1da177e4
LT
4467
4468 /* Setup the StatsDelta */
a95609cb
DL
4469 entry = proc_create_data("StatsDelta",
4470 S_IFREG | (S_IRUGO&proc_perm),
4471 apriv->proc_entry, &proc_statsdelta_ops, dev);
431aca5a
FM
4472 if (!entry)
4473 goto fail_stats_delta;
4474 entry->uid = proc_uid;
4475 entry->gid = proc_gid;
1da177e4
LT
4476
4477 /* Setup the Stats */
a95609cb
DL
4478 entry = proc_create_data("Stats",
4479 S_IFREG | (S_IRUGO&proc_perm),
4480 apriv->proc_entry, &proc_stats_ops, dev);
431aca5a
FM
4481 if (!entry)
4482 goto fail_stats;
4483 entry->uid = proc_uid;
4484 entry->gid = proc_gid;
1da177e4
LT
4485
4486 /* Setup the Status */
a95609cb
DL
4487 entry = proc_create_data("Status",
4488 S_IFREG | (S_IRUGO&proc_perm),
4489 apriv->proc_entry, &proc_status_ops, dev);
431aca5a
FM
4490 if (!entry)
4491 goto fail_status;
4492 entry->uid = proc_uid;
4493 entry->gid = proc_gid;
1da177e4
LT
4494
4495 /* Setup the Config */
a95609cb
DL
4496 entry = proc_create_data("Config",
4497 S_IFREG | proc_perm,
4498 apriv->proc_entry, &proc_config_ops, dev);
431aca5a
FM
4499 if (!entry)
4500 goto fail_config;
4501 entry->uid = proc_uid;
4502 entry->gid = proc_gid;
1da177e4
LT
4503
4504 /* Setup the SSID */
a95609cb
DL
4505 entry = proc_create_data("SSID",
4506 S_IFREG | proc_perm,
4507 apriv->proc_entry, &proc_SSID_ops, dev);
431aca5a
FM
4508 if (!entry)
4509 goto fail_ssid;
4510 entry->uid = proc_uid;
4511 entry->gid = proc_gid;
1da177e4
LT
4512
4513 /* Setup the APList */
a95609cb
DL
4514 entry = proc_create_data("APList",
4515 S_IFREG | proc_perm,
4516 apriv->proc_entry, &proc_APList_ops, dev);
431aca5a
FM
4517 if (!entry)
4518 goto fail_aplist;
4519 entry->uid = proc_uid;
4520 entry->gid = proc_gid;
1da177e4
LT
4521
4522 /* Setup the BSSList */
a95609cb
DL
4523 entry = proc_create_data("BSSList",
4524 S_IFREG | proc_perm,
4525 apriv->proc_entry, &proc_BSSList_ops, dev);
431aca5a
FM
4526 if (!entry)
4527 goto fail_bsslist;
1da177e4
LT
4528 entry->uid = proc_uid;
4529 entry->gid = proc_gid;
1da177e4
LT
4530
4531 /* Setup the WepKey */
a95609cb
DL
4532 entry = proc_create_data("WepKey",
4533 S_IFREG | proc_perm,
4534 apriv->proc_entry, &proc_wepkey_ops, dev);
431aca5a
FM
4535 if (!entry)
4536 goto fail_wepkey;
4537 entry->uid = proc_uid;
4538 entry->gid = proc_gid;
1da177e4
LT
4539
4540 return 0;
431aca5a
FM
4541
4542fail_wepkey:
4543 remove_proc_entry("BSSList", apriv->proc_entry);
4544fail_bsslist:
4545 remove_proc_entry("APList", apriv->proc_entry);
4546fail_aplist:
4547 remove_proc_entry("SSID", apriv->proc_entry);
4548fail_ssid:
4549 remove_proc_entry("Config", apriv->proc_entry);
4550fail_config:
4551 remove_proc_entry("Status", apriv->proc_entry);
4552fail_status:
4553 remove_proc_entry("Stats", apriv->proc_entry);
4554fail_stats:
4555 remove_proc_entry("StatsDelta", apriv->proc_entry);
4556fail_stats_delta:
4557 remove_proc_entry(apriv->proc_name, airo_entry);
4558fail:
4559 return -ENOMEM;
1da177e4
LT
4560}
4561
4562static int takedown_proc_entry( struct net_device *dev,
4563 struct airo_info *apriv ) {
4564 if ( !apriv->proc_entry->namelen ) return 0;
4565 remove_proc_entry("Stats",apriv->proc_entry);
4566 remove_proc_entry("StatsDelta",apriv->proc_entry);
4567 remove_proc_entry("Status",apriv->proc_entry);
4568 remove_proc_entry("Config",apriv->proc_entry);
4569 remove_proc_entry("SSID",apriv->proc_entry);
4570 remove_proc_entry("APList",apriv->proc_entry);
4571 remove_proc_entry("BSSList",apriv->proc_entry);
4572 remove_proc_entry("WepKey",apriv->proc_entry);
4573 remove_proc_entry(apriv->proc_name,airo_entry);
4574 return 0;
4575}
4576
4577/*
4578 * What we want from the proc_fs is to be able to efficiently read
4579 * and write the configuration. To do this, we want to read the
4580 * configuration when the file is opened and write it when the file is
4581 * closed. So basically we allocate a read buffer at open and fill it
4582 * with data, and allocate a write buffer and read it at close.
4583 */
4584
4585/*
4586 * The read routine is generic, it relies on the preallocated rbuffer
4587 * to supply the data.
4588 */
4589static ssize_t proc_read( struct file *file,
4590 char __user *buffer,
4591 size_t len,
4592 loff_t *offset )
4593{
cc0d9ff2 4594 struct proc_data *priv = file->private_data;
1da177e4
LT
4595
4596 if (!priv->rbuffer)
4597 return -EINVAL;
4598
cc0d9ff2
AM
4599 return simple_read_from_buffer(buffer, len, offset, priv->rbuffer,
4600 priv->readlen);
1da177e4
LT
4601}
4602
4603/*
4604 * The write routine is generic, it fills in a preallocated rbuffer
4605 * to supply the data.
4606 */
4607static ssize_t proc_write( struct file *file,
4608 const char __user *buffer,
4609 size_t len,
4610 loff_t *offset )
4611{
4612 loff_t pos = *offset;
4613 struct proc_data *priv = (struct proc_data*)file->private_data;
4614
4615 if (!priv->wbuffer)
4616 return -EINVAL;
4617
4618 if (pos < 0)
4619 return -EINVAL;
4620 if (pos >= priv->maxwritelen)
4621 return 0;
4622 if (len > priv->maxwritelen - pos)
4623 len = priv->maxwritelen - pos;
4624 if (copy_from_user(priv->wbuffer + pos, buffer, len))
4625 return -EFAULT;
4626 if ( pos + len > priv->writelen )
4627 priv->writelen = len + file->f_pos;
4628 *offset = pos + len;
4629 return len;
4630}
4631
329e2c00
AV
4632static int proc_status_open(struct inode *inode, struct file *file)
4633{
1da177e4
LT
4634 struct proc_data *data;
4635 struct proc_dir_entry *dp = PDE(inode);
4636 struct net_device *dev = dp->data;
faf3994a 4637 struct airo_info *apriv = dev->ml_priv;
1da177e4
LT
4638 CapabilityRid cap_rid;
4639 StatusRid status_rid;
329e2c00 4640 u16 mode;
1da177e4
LT
4641 int i;
4642
b69a3aa8 4643 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 4644 return -ENOMEM;
1da177e4
LT
4645 data = (struct proc_data *)file->private_data;
4646 if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
4647 kfree (file->private_data);
4648 return -ENOMEM;
4649 }
4650
4651 readStatusRid(apriv, &status_rid, 1);
4652 readCapabilityRid(apriv, &cap_rid, 1);
4653
329e2c00
AV
4654 mode = le16_to_cpu(status_rid.mode);
4655
1da177e4 4656 i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n",
329e2c00
AV
4657 mode & 1 ? "CFG ": "",
4658 mode & 2 ? "ACT ": "",
4659 mode & 0x10 ? "SYN ": "",
4660 mode & 0x20 ? "LNK ": "",
4661 mode & 0x40 ? "LEAP ": "",
4662 mode & 0x80 ? "PRIV ": "",
4663 mode & 0x100 ? "KEY ": "",
4664 mode & 0x200 ? "WEP ": "",
4665 mode & 0x8000 ? "ERR ": "");
1da177e4
LT
4666 sprintf( data->rbuffer+i, "Mode: %x\n"
4667 "Signal Strength: %d\n"
4668 "Signal Quality: %d\n"
4669 "SSID: %-.*s\n"
4670 "AP: %-.16s\n"
4671 "Freq: %d\n"
4672 "BitRate: %dmbs\n"
4673 "Driver Version: %s\n"
4674 "Device: %s\nManufacturer: %s\nFirmware Version: %s\n"
4675 "Radio type: %x\nCountry: %x\nHardware Version: %x\n"
4676 "Software Version: %x\nSoftware Subversion: %x\n"
4677 "Boot block version: %x\n",
329e2c00
AV
4678 le16_to_cpu(status_rid.mode),
4679 le16_to_cpu(status_rid.normalizedSignalStrength),
4680 le16_to_cpu(status_rid.signalQuality),
4681 le16_to_cpu(status_rid.SSIDlen),
1da177e4
LT
4682 status_rid.SSID,
4683 status_rid.apName,
329e2c00
AV
4684 le16_to_cpu(status_rid.channel),
4685 le16_to_cpu(status_rid.currentXmitRate) / 2,
1da177e4
LT
4686 version,
4687 cap_rid.prodName,
4688 cap_rid.manName,
4689 cap_rid.prodVer,
56d81bd3
AV
4690 le16_to_cpu(cap_rid.radioType),
4691 le16_to_cpu(cap_rid.country),
4692 le16_to_cpu(cap_rid.hardVer),
4693 le16_to_cpu(cap_rid.softVer),
4694 le16_to_cpu(cap_rid.softSubVer),
4695 le16_to_cpu(cap_rid.bootBlockVer));
1da177e4
LT
4696 data->readlen = strlen( data->rbuffer );
4697 return 0;
4698}
4699
4700static int proc_stats_rid_open(struct inode*, struct file*, u16);
4701static int proc_statsdelta_open( struct inode *inode,
4702 struct file *file ) {
4703 if (file->f_mode&FMODE_WRITE) {
4704 return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR);
4705 }
4706 return proc_stats_rid_open(inode, file, RID_STATSDELTA);
4707}
4708
4709static int proc_stats_open( struct inode *inode, struct file *file ) {
4710 return proc_stats_rid_open(inode, file, RID_STATS);
4711}
4712
4713static int proc_stats_rid_open( struct inode *inode,
4714 struct file *file,
a23ace5f
AV
4715 u16 rid )
4716{
1da177e4
LT
4717 struct proc_data *data;
4718 struct proc_dir_entry *dp = PDE(inode);
4719 struct net_device *dev = dp->data;
faf3994a 4720 struct airo_info *apriv = dev->ml_priv;
1da177e4
LT
4721 StatsRid stats;
4722 int i, j;
a23ace5f
AV
4723 __le32 *vals = stats.vals;
4724 int len = le16_to_cpu(stats.len);
1da177e4 4725
b69a3aa8 4726 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 4727 return -ENOMEM;
1da177e4
LT
4728 data = (struct proc_data *)file->private_data;
4729 if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
4730 kfree (file->private_data);
4731 return -ENOMEM;
4732 }
4733
4734 readStatsRid(apriv, &stats, rid, 1);
4735
4736 j = 0;
a23ace5f 4737 for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) {
1da177e4
LT
4738 if (!statsLabels[i]) continue;
4739 if (j+strlen(statsLabels[i])+16>4096) {
934d8bf1
DW
4740 airo_print_warn(apriv->dev->name,
4741 "Potentially disasterous buffer overflow averted!");
1da177e4
LT
4742 break;
4743 }
a23ace5f
AV
4744 j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i],
4745 le32_to_cpu(vals[i]));
1da177e4 4746 }
a23ace5f 4747 if (i*4 >= len) {
934d8bf1 4748 airo_print_warn(apriv->dev->name, "Got a short rid");
1da177e4
LT
4749 }
4750 data->readlen = j;
4751 return 0;
4752}
4753
4754static int get_dec_u16( char *buffer, int *start, int limit ) {
4755 u16 value;
4756 int valid = 0;
4757 for( value = 0; buffer[*start] >= '0' &&
4758 buffer[*start] <= '9' &&
4759 *start < limit; (*start)++ ) {
4760 valid = 1;
4761 value *= 10;
4762 value += buffer[*start] - '0';
4763 }
4764 if ( !valid ) return -1;
4765 return value;
4766}
4767
4768static int airo_config_commit(struct net_device *dev,
4769 struct iw_request_info *info, void *zwrq,
4770 char *extra);
4771
3eb9b41f
AV
4772static inline int sniffing_mode(struct airo_info *ai)
4773{
4774 return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >=
4775 le16_to_cpu(RXMODE_RFMON);
4776}
4777
4778static void proc_config_on_close(struct inode *inode, struct file *file)
4779{
1da177e4
LT
4780 struct proc_data *data = file->private_data;
4781 struct proc_dir_entry *dp = PDE(inode);
4782 struct net_device *dev = dp->data;
faf3994a 4783 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
4784 char *line;
4785
4786 if ( !data->writelen ) return;
4787
4788 readConfigRid(ai, 1);
4789 set_bit (FLAG_COMMIT, &ai->flags);
4790
4791 line = data->wbuffer;
4792 while( line[0] ) {
4793/*** Mode processing */
4794 if ( !strncmp( line, "Mode: ", 6 ) ) {
4795 line += 6;
3eb9b41f
AV
4796 if (sniffing_mode(ai))
4797 set_bit (FLAG_RESET, &ai->flags);
4798 ai->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4 4799 clear_bit (FLAG_802_11, &ai->flags);
3eb9b41f 4800 ai->config.opmode &= ~MODE_CFG_MASK;
1da177e4
LT
4801 ai->config.scanMode = SCANMODE_ACTIVE;
4802 if ( line[0] == 'a' ) {
3eb9b41f 4803 ai->config.opmode |= MODE_STA_IBSS;
1da177e4 4804 } else {
3eb9b41f 4805 ai->config.opmode |= MODE_STA_ESS;
1da177e4
LT
4806 if ( line[0] == 'r' ) {
4807 ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
4808 ai->config.scanMode = SCANMODE_PASSIVE;
4809 set_bit (FLAG_802_11, &ai->flags);
4810 } else if ( line[0] == 'y' ) {
4811 ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
4812 ai->config.scanMode = SCANMODE_PASSIVE;
4813 set_bit (FLAG_802_11, &ai->flags);
4814 } else if ( line[0] == 'l' )
4815 ai->config.rmode |= RXMODE_LANMON;
4816 }
4817 set_bit (FLAG_COMMIT, &ai->flags);
4818 }
4819
4820/*** Radio status */
4821 else if (!strncmp(line,"Radio: ", 7)) {
4822 line += 7;
4823 if (!strncmp(line,"off",3)) {
4824 set_bit (FLAG_RADIO_OFF, &ai->flags);
4825 } else {
4826 clear_bit (FLAG_RADIO_OFF, &ai->flags);
4827 }
4828 }
4829/*** NodeName processing */
4830 else if ( !strncmp( line, "NodeName: ", 10 ) ) {
4831 int j;
4832
4833 line += 10;
4834 memset( ai->config.nodeName, 0, 16 );
4835/* Do the name, assume a space between the mode and node name */
4836 for( j = 0; j < 16 && line[j] != '\n'; j++ ) {
4837 ai->config.nodeName[j] = line[j];
4838 }
4839 set_bit (FLAG_COMMIT, &ai->flags);
4840 }
4841
4842/*** PowerMode processing */
4843 else if ( !strncmp( line, "PowerMode: ", 11 ) ) {
4844 line += 11;
4845 if ( !strncmp( line, "PSPCAM", 6 ) ) {
4846 ai->config.powerSaveMode = POWERSAVE_PSPCAM;
4847 set_bit (FLAG_COMMIT, &ai->flags);
4848 } else if ( !strncmp( line, "PSP", 3 ) ) {
4849 ai->config.powerSaveMode = POWERSAVE_PSP;
4850 set_bit (FLAG_COMMIT, &ai->flags);
4851 } else {
4852 ai->config.powerSaveMode = POWERSAVE_CAM;
4853 set_bit (FLAG_COMMIT, &ai->flags);
4854 }
4855 } else if ( !strncmp( line, "DataRates: ", 11 ) ) {
4856 int v, i = 0, k = 0; /* i is index into line,
4857 k is index to rates */
4858
4859 line += 11;
4860 while((v = get_dec_u16(line, &i, 3))!=-1) {
4861 ai->config.rates[k++] = (u8)v;
4862 line += i + 1;
4863 i = 0;
4864 }
4865 set_bit (FLAG_COMMIT, &ai->flags);
4866 } else if ( !strncmp( line, "Channel: ", 9 ) ) {
4867 int v, i = 0;
4868 line += 9;
4869 v = get_dec_u16(line, &i, i+3);
4870 if ( v != -1 ) {
3eb9b41f 4871 ai->config.channelSet = cpu_to_le16(v);
1da177e4
LT
4872 set_bit (FLAG_COMMIT, &ai->flags);
4873 }
4874 } else if ( !strncmp( line, "XmitPower: ", 11 ) ) {
4875 int v, i = 0;
4876 line += 11;
4877 v = get_dec_u16(line, &i, i+3);
4878 if ( v != -1 ) {
3eb9b41f 4879 ai->config.txPower = cpu_to_le16(v);
1da177e4
LT
4880 set_bit (FLAG_COMMIT, &ai->flags);
4881 }
4882 } else if ( !strncmp( line, "WEP: ", 5 ) ) {
4883 line += 5;
4884 switch( line[0] ) {
4885 case 's':
3eb9b41f 4886 ai->config.authType = AUTH_SHAREDKEY;
1da177e4
LT
4887 break;
4888 case 'e':
3eb9b41f 4889 ai->config.authType = AUTH_ENCRYPT;
1da177e4
LT
4890 break;
4891 default:
3eb9b41f 4892 ai->config.authType = AUTH_OPEN;
1da177e4
LT
4893 break;
4894 }
4895 set_bit (FLAG_COMMIT, &ai->flags);
4896 } else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) {
4897 int v, i = 0;
4898
4899 line += 16;
4900 v = get_dec_u16(line, &i, 3);
4901 v = (v<0) ? 0 : ((v>255) ? 255 : v);
3eb9b41f 4902 ai->config.longRetryLimit = cpu_to_le16(v);
1da177e4
LT
4903 set_bit (FLAG_COMMIT, &ai->flags);
4904 } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) {
4905 int v, i = 0;
4906
4907 line += 17;
4908 v = get_dec_u16(line, &i, 3);
4909 v = (v<0) ? 0 : ((v>255) ? 255 : v);
3eb9b41f 4910 ai->config.shortRetryLimit = cpu_to_le16(v);
1da177e4
LT
4911 set_bit (FLAG_COMMIT, &ai->flags);
4912 } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) {
4913 int v, i = 0;
4914
4915 line += 14;
4916 v = get_dec_u16(line, &i, 4);
15db2763 4917 v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
3eb9b41f 4918 ai->config.rtsThres = cpu_to_le16(v);
1da177e4
LT
4919 set_bit (FLAG_COMMIT, &ai->flags);
4920 } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
4921 int v, i = 0;
4922
4923 line += 16;
4924 v = get_dec_u16(line, &i, 5);
4925 v = (v<0) ? 0 : v;
3eb9b41f 4926 ai->config.txLifetime = cpu_to_le16(v);
1da177e4
LT
4927 set_bit (FLAG_COMMIT, &ai->flags);
4928 } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) {
4929 int v, i = 0;
4930
4931 line += 16;
4932 v = get_dec_u16(line, &i, 5);
4933 v = (v<0) ? 0 : v;
3eb9b41f 4934 ai->config.rxLifetime = cpu_to_le16(v);
1da177e4
LT
4935 set_bit (FLAG_COMMIT, &ai->flags);
4936 } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) {
4937 ai->config.txDiversity =
4938 (line[13]=='l') ? 1 :
4939 ((line[13]=='r')? 2: 3);
4940 set_bit (FLAG_COMMIT, &ai->flags);
4941 } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) {
4942 ai->config.rxDiversity =
4943 (line[13]=='l') ? 1 :
4944 ((line[13]=='r')? 2: 3);
4945 set_bit (FLAG_COMMIT, &ai->flags);
4946 } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) {
4947 int v, i = 0;
4948
4949 line += 15;
4950 v = get_dec_u16(line, &i, 4);
15db2763 4951 v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
1da177e4 4952 v = v & 0xfffe; /* Make sure its even */
3eb9b41f 4953 ai->config.fragThresh = cpu_to_le16(v);
1da177e4
LT
4954 set_bit (FLAG_COMMIT, &ai->flags);
4955 } else if (!strncmp(line, "Modulation: ", 12)) {
4956 line += 12;
4957 switch(*line) {
4958 case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break;
4959 case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break;
4960 case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break;
934d8bf1 4961 default: airo_print_warn(ai->dev->name, "Unknown modulation");
1da177e4
LT
4962 }
4963 } else if (!strncmp(line, "Preamble: ", 10)) {
4964 line += 10;
4965 switch(*line) {
4966 case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break;
4967 case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break;
4968 case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break;
934d8bf1 4969 default: airo_print_warn(ai->dev->name, "Unknown preamble");
1da177e4
LT
4970 }
4971 } else {
934d8bf1 4972 airo_print_warn(ai->dev->name, "Couldn't figure out %s", line);
1da177e4
LT
4973 }
4974 while( line[0] && line[0] != '\n' ) line++;
4975 if ( line[0] ) line++;
4976 }
4977 airo_config_commit(dev, NULL, NULL, NULL);
4978}
4979
3eb9b41f
AV
4980static char *get_rmode(__le16 mode)
4981{
4982 switch(mode & RXMODE_MASK) {
1da177e4
LT
4983 case RXMODE_RFMON: return "rfmon";
4984 case RXMODE_RFMON_ANYBSS: return "yna (any) bss rfmon";
4985 case RXMODE_LANMON: return "lanmon";
4986 }
4987 return "ESS";
4988}
4989
3eb9b41f
AV
4990static int proc_config_open(struct inode *inode, struct file *file)
4991{
1da177e4
LT
4992 struct proc_data *data;
4993 struct proc_dir_entry *dp = PDE(inode);
4994 struct net_device *dev = dp->data;
faf3994a 4995 struct airo_info *ai = dev->ml_priv;
1da177e4 4996 int i;
3eb9b41f 4997 __le16 mode;
1da177e4 4998
b69a3aa8 4999 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 5000 return -ENOMEM;
1da177e4
LT
5001 data = (struct proc_data *)file->private_data;
5002 if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
5003 kfree (file->private_data);
5004 return -ENOMEM;
5005 }
b69a3aa8 5006 if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) {
1da177e4
LT
5007 kfree (data->rbuffer);
5008 kfree (file->private_data);
5009 return -ENOMEM;
5010 }
1da177e4
LT
5011 data->maxwritelen = 2048;
5012 data->on_close = proc_config_on_close;
5013
5014 readConfigRid(ai, 1);
5015
3eb9b41f 5016 mode = ai->config.opmode & MODE_CFG_MASK;
1da177e4
LT
5017 i = sprintf( data->rbuffer,
5018 "Mode: %s\n"
5019 "Radio: %s\n"
5020 "NodeName: %-16s\n"
5021 "PowerMode: %s\n"
5022 "DataRates: %d %d %d %d %d %d %d %d\n"
5023 "Channel: %d\n"
5024 "XmitPower: %d\n",
3eb9b41f
AV
5025 mode == MODE_STA_IBSS ? "adhoc" :
5026 mode == MODE_STA_ESS ? get_rmode(ai->config.rmode):
5027 mode == MODE_AP ? "AP" :
5028 mode == MODE_AP_RPTR ? "AP RPTR" : "Error",
1da177e4
LT
5029 test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on",
5030 ai->config.nodeName,
3eb9b41f
AV
5031 ai->config.powerSaveMode == POWERSAVE_CAM ? "CAM" :
5032 ai->config.powerSaveMode == POWERSAVE_PSP ? "PSP" :
5033 ai->config.powerSaveMode == POWERSAVE_PSPCAM ? "PSPCAM" :
5034 "Error",
1da177e4
LT
5035 (int)ai->config.rates[0],
5036 (int)ai->config.rates[1],
5037 (int)ai->config.rates[2],
5038 (int)ai->config.rates[3],
5039 (int)ai->config.rates[4],
5040 (int)ai->config.rates[5],
5041 (int)ai->config.rates[6],
5042 (int)ai->config.rates[7],
3eb9b41f
AV
5043 le16_to_cpu(ai->config.channelSet),
5044 le16_to_cpu(ai->config.txPower)
1da177e4
LT
5045 );
5046 sprintf( data->rbuffer + i,
5047 "LongRetryLimit: %d\n"
5048 "ShortRetryLimit: %d\n"
5049 "RTSThreshold: %d\n"
5050 "TXMSDULifetime: %d\n"
5051 "RXMSDULifetime: %d\n"
5052 "TXDiversity: %s\n"
5053 "RXDiversity: %s\n"
5054 "FragThreshold: %d\n"
5055 "WEP: %s\n"
5056 "Modulation: %s\n"
5057 "Preamble: %s\n",
3eb9b41f
AV
5058 le16_to_cpu(ai->config.longRetryLimit),
5059 le16_to_cpu(ai->config.shortRetryLimit),
5060 le16_to_cpu(ai->config.rtsThres),
5061 le16_to_cpu(ai->config.txLifetime),
5062 le16_to_cpu(ai->config.rxLifetime),
1da177e4
LT
5063 ai->config.txDiversity == 1 ? "left" :
5064 ai->config.txDiversity == 2 ? "right" : "both",
5065 ai->config.rxDiversity == 1 ? "left" :
5066 ai->config.rxDiversity == 2 ? "right" : "both",
3eb9b41f 5067 le16_to_cpu(ai->config.fragThresh),
1da177e4
LT
5068 ai->config.authType == AUTH_ENCRYPT ? "encrypt" :
5069 ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open",
3eb9b41f 5070 ai->config.modulation == MOD_DEFAULT ? "default" :
1da177e4
LT
5071 ai->config.modulation == MOD_CCK ? "cck" :
5072 ai->config.modulation == MOD_MOK ? "mok" : "error",
5073 ai->config.preamble == PREAMBLE_AUTO ? "auto" :
5074 ai->config.preamble == PREAMBLE_LONG ? "long" :
5075 ai->config.preamble == PREAMBLE_SHORT ? "short" : "error"
5076 );
5077 data->readlen = strlen( data->rbuffer );
5078 return 0;
5079}
5080
0dd2212f
AV
5081static void proc_SSID_on_close(struct inode *inode, struct file *file)
5082{
1da177e4
LT
5083 struct proc_data *data = (struct proc_data *)file->private_data;
5084 struct proc_dir_entry *dp = PDE(inode);
5085 struct net_device *dev = dp->data;
faf3994a 5086 struct airo_info *ai = dev->ml_priv;
1da177e4 5087 SsidRid SSID_rid;
1da177e4 5088 int i;
0dd2212f
AV
5089 char *p = data->wbuffer;
5090 char *end = p + data->writelen;
1da177e4 5091
0dd2212f
AV
5092 if (!data->writelen)
5093 return;
1da177e4 5094
0dd2212f 5095 *end = '\n'; /* sentinel; we have space for it */
1da177e4 5096
0dd2212f
AV
5097 memset(&SSID_rid, 0, sizeof(SSID_rid));
5098
5099 for (i = 0; i < 3 && p < end; i++) {
5100 int j = 0;
5101 /* copy up to 32 characters from this line */
5102 while (*p != '\n' && j < 32)
5103 SSID_rid.ssids[i].ssid[j++] = *p++;
5104 if (j == 0)
5105 break;
5106 SSID_rid.ssids[i].len = cpu_to_le16(j);
5107 /* skip to the beginning of the next line */
5108 while (*p++ != '\n')
5109 ;
1da177e4
LT
5110 }
5111 if (i)
0dd2212f 5112 SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
1da177e4
LT
5113 disable_MAC(ai, 1);
5114 writeSsidRid(ai, &SSID_rid, 1);
175ec1a1 5115 enable_MAC(ai, 1);
1da177e4
LT
5116}
5117
77933d72 5118static inline u8 hexVal(char c) {
1da177e4
LT
5119 if (c>='0' && c<='9') return c -= '0';
5120 if (c>='a' && c<='f') return c -= 'a'-10;
5121 if (c>='A' && c<='F') return c -= 'A'-10;
5122 return 0;
5123}
5124
5125static void proc_APList_on_close( struct inode *inode, struct file *file ) {
5126 struct proc_data *data = (struct proc_data *)file->private_data;
5127 struct proc_dir_entry *dp = PDE(inode);
5128 struct net_device *dev = dp->data;
faf3994a 5129 struct airo_info *ai = dev->ml_priv;
1da177e4 5130 APListRid APList_rid;
1da177e4
LT
5131 int i;
5132
5133 if ( !data->writelen ) return;
5134
5135 memset( &APList_rid, 0, sizeof(APList_rid) );
a749716e 5136 APList_rid.len = cpu_to_le16(sizeof(APList_rid));
1da177e4
LT
5137
5138 for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
5139 int j;
5140 for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
5141 switch(j%3) {
5142 case 0:
5143 APList_rid.ap[i][j/3]=
5144 hexVal(data->wbuffer[j+i*6*3])<<4;
5145 break;
5146 case 1:
5147 APList_rid.ap[i][j/3]|=
5148 hexVal(data->wbuffer[j+i*6*3]);
5149 break;
5150 }
5151 }
5152 }
5153 disable_MAC(ai, 1);
5154 writeAPListRid(ai, &APList_rid, 1);
175ec1a1 5155 enable_MAC(ai, 1);
1da177e4
LT
5156}
5157
5158/* This function wraps PC4500_writerid with a MAC disable */
5159static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
5160 int len, int dummy ) {
5161 int rc;
1da177e4
LT
5162
5163 disable_MAC(ai, 1);
5164 rc = PC4500_writerid(ai, rid, rid_data, len, 1);
175ec1a1 5165 enable_MAC(ai, 1);
1da177e4
LT
5166 return rc;
5167}
5168
5169/* Returns the length of the key at the index. If index == 0xffff
5170 * the index of the transmit key is returned. If the key doesn't exist,
5171 * -1 will be returned.
5172 */
5173static int get_wep_key(struct airo_info *ai, u16 index) {
5174 WepKeyRid wkr;
5175 int rc;
4293ea33 5176 __le16 lastindex;
1da177e4
LT
5177
5178 rc = readWepKeyRid(ai, &wkr, 1, 1);
5179 if (rc == SUCCESS) do {
5180 lastindex = wkr.kindex;
4293ea33 5181 if (wkr.kindex == cpu_to_le16(index)) {
1da177e4
LT
5182 if (index == 0xffff) {
5183 return wkr.mac[0];
5184 }
4293ea33 5185 return le16_to_cpu(wkr.klen);
1da177e4
LT
5186 }
5187 readWepKeyRid(ai, &wkr, 0, 1);
4293ea33 5188 } while (lastindex != wkr.kindex);
1da177e4
LT
5189 return -1;
5190}
5191
5192static int set_wep_key(struct airo_info *ai, u16 index,
4293ea33
AV
5193 const char *key, u16 keylen, int perm, int lock )
5194{
1da177e4
LT
5195 static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
5196 WepKeyRid wkr;
1da177e4
LT
5197
5198 memset(&wkr, 0, sizeof(wkr));
5199 if (keylen == 0) {
5200// We are selecting which key to use
4293ea33
AV
5201 wkr.len = cpu_to_le16(sizeof(wkr));
5202 wkr.kindex = cpu_to_le16(0xffff);
1da177e4 5203 wkr.mac[0] = (char)index;
1da177e4
LT
5204 if (perm) ai->defindex = (char)index;
5205 } else {
5206// We are actually setting the key
4293ea33
AV
5207 wkr.len = cpu_to_le16(sizeof(wkr));
5208 wkr.kindex = cpu_to_le16(index);
5209 wkr.klen = cpu_to_le16(keylen);
1da177e4
LT
5210 memcpy( wkr.key, key, keylen );
5211 memcpy( wkr.mac, macaddr, ETH_ALEN );
1da177e4
LT
5212 }
5213
f89b2321 5214 if (perm) disable_MAC(ai, lock);
1da177e4 5215 writeWepKeyRid(ai, &wkr, perm, lock);
175ec1a1 5216 if (perm) enable_MAC(ai, lock);
1da177e4
LT
5217 return 0;
5218}
5219
5220static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
5221 struct proc_data *data;
5222 struct proc_dir_entry *dp = PDE(inode);
5223 struct net_device *dev = dp->data;
faf3994a 5224 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5225 int i;
5226 char key[16];
5227 u16 index = 0;
5228 int j = 0;
5229
5230 memset(key, 0, sizeof(key));
5231
5232 data = (struct proc_data *)file->private_data;
5233 if ( !data->writelen ) return;
5234
5235 if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
5236 (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
5237 index = data->wbuffer[0] - '0';
5238 if (data->wbuffer[1] == '\n') {
5239 set_wep_key(ai, index, NULL, 0, 1, 1);
5240 return;
5241 }
5242 j = 2;
5243 } else {
934d8bf1 5244 airo_print_err(ai->dev->name, "WepKey passed invalid key index");
1da177e4
LT
5245 return;
5246 }
5247
5248 for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) {
5249 switch(i%3) {
5250 case 0:
5251 key[i/3] = hexVal(data->wbuffer[i+j])<<4;
5252 break;
5253 case 1:
5254 key[i/3] |= hexVal(data->wbuffer[i+j]);
5255 break;
5256 }
5257 }
5258 set_wep_key(ai, index, key, i/3, 1, 1);
5259}
5260
4293ea33
AV
5261static int proc_wepkey_open( struct inode *inode, struct file *file )
5262{
1da177e4
LT
5263 struct proc_data *data;
5264 struct proc_dir_entry *dp = PDE(inode);
5265 struct net_device *dev = dp->data;
faf3994a 5266 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5267 char *ptr;
5268 WepKeyRid wkr;
4293ea33 5269 __le16 lastindex;
1da177e4
LT
5270 int j=0;
5271 int rc;
5272
b69a3aa8 5273 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 5274 return -ENOMEM;
1da177e4
LT
5275 memset(&wkr, 0, sizeof(wkr));
5276 data = (struct proc_data *)file->private_data;
b69a3aa8 5277 if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
1da177e4
LT
5278 kfree (file->private_data);
5279 return -ENOMEM;
5280 }
1da177e4
LT
5281 data->writelen = 0;
5282 data->maxwritelen = 80;
b69a3aa8 5283 if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) {
1da177e4
LT
5284 kfree (data->rbuffer);
5285 kfree (file->private_data);
5286 return -ENOMEM;
5287 }
1da177e4
LT
5288 data->on_close = proc_wepkey_on_close;
5289
5290 ptr = data->rbuffer;
5291 strcpy(ptr, "No wep keys\n");
5292 rc = readWepKeyRid(ai, &wkr, 1, 1);
5293 if (rc == SUCCESS) do {
5294 lastindex = wkr.kindex;
4293ea33 5295 if (wkr.kindex == cpu_to_le16(0xffff)) {
1da177e4
LT
5296 j += sprintf(ptr+j, "Tx key = %d\n",
5297 (int)wkr.mac[0]);
5298 } else {
5299 j += sprintf(ptr+j, "Key %d set with length = %d\n",
4293ea33
AV
5300 le16_to_cpu(wkr.kindex),
5301 le16_to_cpu(wkr.klen));
1da177e4
LT
5302 }
5303 readWepKeyRid(ai, &wkr, 0, 1);
5304 } while((lastindex != wkr.kindex) && (j < 180-30));
5305
5306 data->readlen = strlen( data->rbuffer );
5307 return 0;
5308}
5309
0dd2212f
AV
5310static int proc_SSID_open(struct inode *inode, struct file *file)
5311{
1da177e4
LT
5312 struct proc_data *data;
5313 struct proc_dir_entry *dp = PDE(inode);
5314 struct net_device *dev = dp->data;
faf3994a 5315 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5316 int i;
5317 char *ptr;
5318 SsidRid SSID_rid;
5319
b69a3aa8 5320 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 5321 return -ENOMEM;
1da177e4
LT
5322 data = (struct proc_data *)file->private_data;
5323 if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
5324 kfree (file->private_data);
5325 return -ENOMEM;
5326 }
5327 data->writelen = 0;
5328 data->maxwritelen = 33*3;
0dd2212f
AV
5329 /* allocate maxwritelen + 1; we'll want a sentinel */
5330 if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) {
1da177e4
LT
5331 kfree (data->rbuffer);
5332 kfree (file->private_data);
5333 return -ENOMEM;
5334 }
1da177e4
LT
5335 data->on_close = proc_SSID_on_close;
5336
5337 readSsidRid(ai, &SSID_rid);
5338 ptr = data->rbuffer;
0dd2212f 5339 for (i = 0; i < 3; i++) {
1da177e4 5340 int j;
0dd2212f
AV
5341 size_t len = le16_to_cpu(SSID_rid.ssids[i].len);
5342 if (!len)
5343 break;
5344 if (len > 32)
5345 len = 32;
5346 for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++)
1da177e4 5347 *ptr++ = SSID_rid.ssids[i].ssid[j];
1da177e4
LT
5348 *ptr++ = '\n';
5349 }
5350 *ptr = '\0';
5351 data->readlen = strlen( data->rbuffer );
5352 return 0;
5353}
5354
5355static int proc_APList_open( struct inode *inode, struct file *file ) {
5356 struct proc_data *data;
5357 struct proc_dir_entry *dp = PDE(inode);
5358 struct net_device *dev = dp->data;
faf3994a 5359 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5360 int i;
5361 char *ptr;
5362 APListRid APList_rid;
5363
b69a3aa8 5364 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 5365 return -ENOMEM;
1da177e4
LT
5366 data = (struct proc_data *)file->private_data;
5367 if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
5368 kfree (file->private_data);
5369 return -ENOMEM;
5370 }
5371 data->writelen = 0;
5372 data->maxwritelen = 4*6*3;
b69a3aa8 5373 if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
1da177e4
LT
5374 kfree (data->rbuffer);
5375 kfree (file->private_data);
5376 return -ENOMEM;
5377 }
1da177e4
LT
5378 data->on_close = proc_APList_on_close;
5379
5380 readAPListRid(ai, &APList_rid);
5381 ptr = data->rbuffer;
5382 for( i = 0; i < 4; i++ ) {
5383// We end when we find a zero MAC
5384 if ( !*(int*)APList_rid.ap[i] &&
5385 !*(int*)&APList_rid.ap[i][2]) break;
e174961c 5386 ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
1da177e4
LT
5387 }
5388 if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
5389
5390 *ptr = '\0';
5391 data->readlen = strlen( data->rbuffer );
5392 return 0;
5393}
5394
5395static int proc_BSSList_open( struct inode *inode, struct file *file ) {
5396 struct proc_data *data;
5397 struct proc_dir_entry *dp = PDE(inode);
5398 struct net_device *dev = dp->data;
faf3994a 5399 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5400 char *ptr;
5401 BSSListRid BSSList_rid;
5402 int rc;
5403 /* If doLoseSync is not 1, we won't do a Lose Sync */
5404 int doLoseSync = -1;
5405
b69a3aa8 5406 if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
1da177e4 5407 return -ENOMEM;
1da177e4
LT
5408 data = (struct proc_data *)file->private_data;
5409 if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
5410 kfree (file->private_data);
5411 return -ENOMEM;
5412 }
5413 data->writelen = 0;
5414 data->maxwritelen = 0;
5415 data->wbuffer = NULL;
5416 data->on_close = NULL;
5417
5418 if (file->f_mode & FMODE_WRITE) {
5419 if (!(file->f_mode & FMODE_READ)) {
5420 Cmd cmd;
5421 Resp rsp;
5422
5423 if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
5424 memset(&cmd, 0, sizeof(cmd));
5425 cmd.cmd=CMD_LISTBSS;
5426 if (down_interruptible(&ai->sem))
5427 return -ERESTARTSYS;
5428 issuecommand(ai, &cmd, &rsp);
5429 up(&ai->sem);
5430 data->readlen = 0;
5431 return 0;
5432 }
5433 doLoseSync = 1;
5434 }
5435 ptr = data->rbuffer;
5436 /* There is a race condition here if there are concurrent opens.
5437 Since it is a rare condition, we'll just live with it, otherwise
5438 we have to add a spin lock... */
5439 rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
17e70491 5440 while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
e174961c
JB
5441 ptr += sprintf(ptr, "%pM %*s rssi = %d",
5442 BSSList_rid.bssid,
1da177e4
LT
5443 (int)BSSList_rid.ssidLen,
5444 BSSList_rid.ssid,
17e70491 5445 le16_to_cpu(BSSList_rid.dBm));
1da177e4 5446 ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
17e70491 5447 le16_to_cpu(BSSList_rid.dsChannel),
1da177e4
LT
5448 BSSList_rid.cap & CAP_ESS ? "ESS" : "",
5449 BSSList_rid.cap & CAP_IBSS ? "adhoc" : "",
5450 BSSList_rid.cap & CAP_PRIVACY ? "wep" : "",
5451 BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : "");
5452 rc = readBSSListRid(ai, 0, &BSSList_rid);
5453 }
5454 *ptr = '\0';
5455 data->readlen = strlen( data->rbuffer );
5456 return 0;
5457}
5458
5459static int proc_close( struct inode *inode, struct file *file )
5460{
b4558ea9
JJ
5461 struct proc_data *data = file->private_data;
5462
5463 if (data->on_close != NULL)
5464 data->on_close(inode, file);
5465 kfree(data->rbuffer);
5466 kfree(data->wbuffer);
5467 kfree(data);
1da177e4
LT
5468 return 0;
5469}
5470
1da177e4
LT
5471/* Since the card doesn't automatically switch to the right WEP mode,
5472 we will make it do it. If the card isn't associated, every secs we
5473 will switch WEP modes to see if that will help. If the card is
5474 associated we will check every minute to see if anything has
5475 changed. */
5476static void timer_func( struct net_device *dev ) {
faf3994a 5477 struct airo_info *apriv = dev->ml_priv;
1da177e4
LT
5478
5479/* We don't have a link so try changing the authtype */
5480 readConfigRid(apriv, 0);
5481 disable_MAC(apriv, 0);
5482 switch(apriv->config.authType) {
5483 case AUTH_ENCRYPT:
5484/* So drop to OPEN */
5485 apriv->config.authType = AUTH_OPEN;
5486 break;
5487 case AUTH_SHAREDKEY:
5488 if (apriv->keyindex < auto_wep) {
5489 set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
5490 apriv->config.authType = AUTH_SHAREDKEY;
5491 apriv->keyindex++;
5492 } else {
5493 /* Drop to ENCRYPT */
5494 apriv->keyindex = 0;
5495 set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
5496 apriv->config.authType = AUTH_ENCRYPT;
5497 }
5498 break;
5499 default: /* We'll escalate to SHAREDKEY */
5500 apriv->config.authType = AUTH_SHAREDKEY;
5501 }
5502 set_bit (FLAG_COMMIT, &apriv->flags);
5503 writeConfigRid(apriv, 0);
175ec1a1 5504 enable_MAC(apriv, 0);
1da177e4
LT
5505 up(&apriv->sem);
5506
5507/* Schedule check to see if the change worked */
3c304956 5508 clear_bit(JOB_AUTOWEP, &apriv->jobs);
1da177e4
LT
5509 apriv->expires = RUN_AT(HZ*3);
5510}
5511
1da177e4
LT
5512#ifdef CONFIG_PCI
5513static int __devinit airo_pci_probe(struct pci_dev *pdev,
5514 const struct pci_device_id *pent)
5515{
5516 struct net_device *dev;
5517
5518 if (pci_enable_device(pdev))
5519 return -ENODEV;
5520 pci_set_master(pdev);
5521
5522 if (pdev->device == 0x5000 || pdev->device == 0xa504)
5523 dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
5524 else
5525 dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
777ec5e9
MS
5526 if (!dev) {
5527 pci_disable_device(pdev);
1da177e4 5528 return -ENODEV;
777ec5e9 5529 }
1da177e4
LT
5530
5531 pci_set_drvdata(pdev, dev);
5532 return 0;
5533}
5534
5535static void __devexit airo_pci_remove(struct pci_dev *pdev)
5536{
af5b5c9a
MS
5537 struct net_device *dev = pci_get_drvdata(pdev);
5538
5539 airo_print_info(dev->name, "Unregistering...");
5540 stop_airo_card(dev, 1);
777ec5e9
MS
5541 pci_disable_device(pdev);
5542 pci_set_drvdata(pdev, NULL);
1da177e4
LT
5543}
5544
05adc3b7 5545static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4
LT
5546{
5547 struct net_device *dev = pci_get_drvdata(pdev);
faf3994a 5548 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
5549 Cmd cmd;
5550 Resp rsp;
5551
e292c737
PM
5552 if (!ai->APList)
5553 ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL);
5554 if (!ai->APList)
1da177e4 5555 return -ENOMEM;
e292c737
PM
5556 if (!ai->SSID)
5557 ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL);
5558 if (!ai->SSID)
1da177e4
LT
5559 return -ENOMEM;
5560 readAPListRid(ai, ai->APList);
5561 readSsidRid(ai, ai->SSID);
5562 memset(&cmd, 0, sizeof(cmd));
5563 /* the lock will be released at the end of the resume callback */
5564 if (down_interruptible(&ai->sem))
5565 return -EAGAIN;
5566 disable_MAC(ai, 0);
5567 netif_device_detach(dev);
5568 ai->power = state;
e292c737 5569 cmd.cmd = HOSTSLEEP;
1da177e4
LT
5570 issuecommand(ai, &cmd, &rsp);
5571
1cc68ae0 5572 pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
1da177e4 5573 pci_save_state(pdev);
1cc68ae0 5574 return pci_set_power_state(pdev, pci_choose_state(pdev, state));
1da177e4
LT
5575}
5576
5577static int airo_pci_resume(struct pci_dev *pdev)
5578{
5579 struct net_device *dev = pci_get_drvdata(pdev);
faf3994a 5580 struct airo_info *ai = dev->ml_priv;
53232803 5581 pci_power_t prev_state = pdev->current_state;
1da177e4 5582
53232803 5583 pci_set_power_state(pdev, PCI_D0);
1da177e4 5584 pci_restore_state(pdev);
53232803 5585 pci_enable_wake(pdev, PCI_D0, 0);
1da177e4 5586
53232803 5587 if (prev_state != PCI_D1) {
1da177e4
LT
5588 reset_card(dev, 0);
5589 mpi_init_descriptors(ai);
5590 setup_card(ai, dev->dev_addr, 0);
5591 clear_bit(FLAG_RADIO_OFF, &ai->flags);
5592 clear_bit(FLAG_PENDING_XMIT, &ai->flags);
5593 } else {
5594 OUT4500(ai, EVACK, EV_AWAKEN);
5595 OUT4500(ai, EVACK, EV_AWAKEN);
5596 msleep(100);
5597 }
5598
e292c737 5599 set_bit(FLAG_COMMIT, &ai->flags);
1da177e4
LT
5600 disable_MAC(ai, 0);
5601 msleep(200);
5602 if (ai->SSID) {
5603 writeSsidRid(ai, ai->SSID, 0);
5604 kfree(ai->SSID);
5605 ai->SSID = NULL;
5606 }
5607 if (ai->APList) {
5608 writeAPListRid(ai, ai->APList, 0);
5609 kfree(ai->APList);
5610 ai->APList = NULL;
5611 }
5612 writeConfigRid(ai, 0);
175ec1a1 5613 enable_MAC(ai, 0);
1cc68ae0 5614 ai->power = PMSG_ON;
1da177e4
LT
5615 netif_device_attach(dev);
5616 netif_wake_queue(dev);
5617 enable_interrupts(ai);
5618 up(&ai->sem);
5619 return 0;
5620}
5621#endif
5622
5623static int __init airo_init_module( void )
5624{
de897881 5625 int i;
1da177e4 5626
928b4d8c 5627 airo_entry = create_proc_entry("driver/aironet",
1da177e4 5628 S_IFDIR | airo_perm,
928b4d8c 5629 NULL);
de897881
JG
5630
5631 if (airo_entry) {
5632 airo_entry->uid = proc_uid;
5633 airo_entry->gid = proc_gid;
5634 }
1da177e4 5635
e292c737 5636 for (i = 0; i < 4 && io[i] && irq[i]; i++) {
934d8bf1
DW
5637 airo_print_info("", "Trying to configure ISA adapter at irq=%d "
5638 "io=0x%x", irq[i], io[i] );
1da177e4 5639 if (init_airo_card( irq[i], io[i], 0, NULL ))
de897881 5640 /* do nothing */ ;
1da177e4
LT
5641 }
5642
5643#ifdef CONFIG_PCI
934d8bf1 5644 airo_print_info("", "Probing for PCI adapters");
de897881 5645 i = pci_register_driver(&airo_driver);
934d8bf1 5646 airo_print_info("", "Finished probing for PCI adapters");
de897881
JG
5647
5648 if (i) {
928b4d8c 5649 remove_proc_entry("driver/aironet", NULL);
de897881
JG
5650 return i;
5651 }
1da177e4
LT
5652#endif
5653
5654 /* Always exit with success, as we are a library module
5655 * as well as a driver module
5656 */
5657 return 0;
5658}
5659
5660static void __exit airo_cleanup_module( void )
5661{
af5b5c9a
MS
5662 struct airo_info *ai;
5663 while(!list_empty(&airo_devices)) {
5664 ai = list_entry(airo_devices.next, struct airo_info, dev_list);
5665 airo_print_info(ai->dev->name, "Unregistering...");
5666 stop_airo_card(ai->dev, 1);
1da177e4
LT
5667 }
5668#ifdef CONFIG_PCI
5669 pci_unregister_driver(&airo_driver);
5670#endif
928b4d8c 5671 remove_proc_entry("driver/aironet", NULL);
1da177e4
LT
5672}
5673
1da177e4
LT
5674/*
5675 * Initial Wireless Extension code for Aironet driver by :
5676 * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
5677 * Conversion to new driver API by :
5678 * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 26 March 02
5679 * Javier also did a good amount of work here, adding some new extensions
5680 * and fixing my code. Let's just say that without him this code just
5681 * would not work at all... - Jean II
5682 */
5683
41480af2
DW
5684static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
5685{
e292c737 5686 if (!rssi_rid)
41480af2
DW
5687 return 0;
5688
5689 return (0x100 - rssi_rid[rssi].rssidBm);
5690}
5691
5692static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
5693{
5694 int i;
5695
e292c737 5696 if (!rssi_rid)
41480af2
DW
5697 return 0;
5698
e292c737 5699 for (i = 0; i < 256; i++)
41480af2
DW
5700 if (rssi_rid[i].rssidBm == dbm)
5701 return rssi_rid[i].rssipct;
5702
5703 return 0;
5704}
5705
5706
1da177e4
LT
5707static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
5708{
5709 int quality = 0;
329e2c00 5710 u16 sq;
1da177e4 5711
329e2c00 5712 if ((status_rid->mode & cpu_to_le16(0x3f)) != cpu_to_le16(0x3f))
56d81bd3
AV
5713 return 0;
5714
5715 if (!(cap_rid->hardCap & cpu_to_le16(8)))
5716 return 0;
5717
329e2c00 5718 sq = le16_to_cpu(status_rid->signalQuality);
56d81bd3 5719 if (memcmp(cap_rid->prodName, "350", 3))
329e2c00 5720 if (sq > 0x20)
56d81bd3 5721 quality = 0;
1da177e4 5722 else
329e2c00 5723 quality = 0x20 - sq;
56d81bd3 5724 else
329e2c00 5725 if (sq > 0xb0)
56d81bd3 5726 quality = 0;
329e2c00 5727 else if (sq < 0x10)
56d81bd3
AV
5728 quality = 0xa0;
5729 else
329e2c00 5730 quality = 0xb0 - sq;
1da177e4
LT
5731 return quality;
5732}
5733
5734#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
5735#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
5736
5737/*------------------------------------------------------------------*/
5738/*
5739 * Wireless Handler : get protocol name
5740 */
5741static int airo_get_name(struct net_device *dev,
5742 struct iw_request_info *info,
5743 char *cwrq,
5744 char *extra)
5745{
5746 strcpy(cwrq, "IEEE 802.11-DS");
5747 return 0;
5748}
5749
5750/*------------------------------------------------------------------*/
5751/*
5752 * Wireless Handler : set frequency
5753 */
5754static int airo_set_freq(struct net_device *dev,
5755 struct iw_request_info *info,
5756 struct iw_freq *fwrq,
5757 char *extra)
5758{
faf3994a 5759 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5760 int rc = -EINPROGRESS; /* Call commit handler */
5761
5762 /* If setting by frequency, convert to a channel */
9ee677c2 5763 if(fwrq->e == 1) {
1da177e4 5764 int f = fwrq->m / 100000;
9ee677c2 5765
1da177e4
LT
5766 /* Hack to fall through... */
5767 fwrq->e = 0;
9ee677c2 5768 fwrq->m = ieee80211_freq_to_dsss_chan(f);
1da177e4
LT
5769 }
5770 /* Setting by channel number */
5771 if((fwrq->m > 1000) || (fwrq->e > 0))
5772 rc = -EOPNOTSUPP;
5773 else {
5774 int channel = fwrq->m;
5775 /* We should do a better check than that,
5776 * based on the card capability !!! */
2610c733 5777 if((channel < 1) || (channel > 14)) {
934d8bf1
DW
5778 airo_print_dbg(dev->name, "New channel value of %d is invalid!",
5779 fwrq->m);
1da177e4
LT
5780 rc = -EINVAL;
5781 } else {
5782 readConfigRid(local, 1);
5783 /* Yes ! We can set it !!! */
3eb9b41f 5784 local->config.channelSet = cpu_to_le16(channel);
1da177e4
LT
5785 set_bit (FLAG_COMMIT, &local->flags);
5786 }
5787 }
5788 return rc;
5789}
5790
5791/*------------------------------------------------------------------*/
5792/*
5793 * Wireless Handler : get frequency
5794 */
5795static int airo_get_freq(struct net_device *dev,
5796 struct iw_request_info *info,
5797 struct iw_freq *fwrq,
5798 char *extra)
5799{
faf3994a 5800 struct airo_info *local = dev->ml_priv;
1da177e4 5801 StatusRid status_rid; /* Card status info */
2610c733 5802 int ch;
1da177e4
LT
5803
5804 readConfigRid(local, 1);
3eb9b41f
AV
5805 if ((local->config.opmode & MODE_CFG_MASK) == MODE_STA_ESS)
5806 status_rid.channel = local->config.channelSet;
1da177e4
LT
5807 else
5808 readStatusRid(local, &status_rid, 1);
5809
329e2c00 5810 ch = le16_to_cpu(status_rid.channel);
2610c733 5811 if((ch > 0) && (ch < 15)) {
9ee677c2 5812 fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000;
1da177e4 5813 fwrq->e = 1;
2610c733
JA
5814 } else {
5815 fwrq->m = ch;
5816 fwrq->e = 0;
1da177e4 5817 }
1da177e4
LT
5818
5819 return 0;
5820}
5821
5822/*------------------------------------------------------------------*/
5823/*
5824 * Wireless Handler : set ESSID
5825 */
5826static int airo_set_essid(struct net_device *dev,
5827 struct iw_request_info *info,
5828 struct iw_point *dwrq,
5829 char *extra)
5830{
faf3994a 5831 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5832 SsidRid SSID_rid; /* SSIDs */
5833
5834 /* Reload the list of current SSID */
5835 readSsidRid(local, &SSID_rid);
5836
5837 /* Check if we asked for `any' */
5838 if(dwrq->flags == 0) {
5839 /* Just send an empty SSID list */
5840 memset(&SSID_rid, 0, sizeof(SSID_rid));
5841 } else {
5842 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
5843
5844 /* Check the size of the string */
7f8544cc 5845 if(dwrq->length > IW_ESSID_MAX_SIZE) {
1da177e4
LT
5846 return -E2BIG ;
5847 }
5848 /* Check if index is valid */
5849 if((index < 0) || (index >= 4)) {
5850 return -EINVAL;
5851 }
5852
5853 /* Set the SSID */
5854 memset(SSID_rid.ssids[index].ssid, 0,
5855 sizeof(SSID_rid.ssids[index].ssid));
5856 memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
0dd2212f 5857 SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length);
1da177e4 5858 }
0dd2212f 5859 SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
1da177e4
LT
5860 /* Write it to the card */
5861 disable_MAC(local, 1);
5862 writeSsidRid(local, &SSID_rid, 1);
175ec1a1 5863 enable_MAC(local, 1);
1da177e4
LT
5864
5865 return 0;
5866}
5867
5868/*------------------------------------------------------------------*/
5869/*
5870 * Wireless Handler : get ESSID
5871 */
5872static int airo_get_essid(struct net_device *dev,
5873 struct iw_request_info *info,
5874 struct iw_point *dwrq,
5875 char *extra)
5876{
faf3994a 5877 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5878 StatusRid status_rid; /* Card status info */
5879
5880 readStatusRid(local, &status_rid, 1);
5881
5882 /* Note : if dwrq->flags != 0, we should
5883 * get the relevant SSID from the SSID list... */
5884
5885 /* Get the current SSID */
329e2c00 5886 memcpy(extra, status_rid.SSID, le16_to_cpu(status_rid.SSIDlen));
1da177e4
LT
5887 /* If none, we may want to get the one that was set */
5888
5889 /* Push it out ! */
329e2c00 5890 dwrq->length = le16_to_cpu(status_rid.SSIDlen);
1da177e4
LT
5891 dwrq->flags = 1; /* active */
5892
5893 return 0;
5894}
5895
5896/*------------------------------------------------------------------*/
5897/*
5898 * Wireless Handler : set AP address
5899 */
5900static int airo_set_wap(struct net_device *dev,
5901 struct iw_request_info *info,
5902 struct sockaddr *awrq,
5903 char *extra)
5904{
faf3994a 5905 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5906 Cmd cmd;
5907 Resp rsp;
5908 APListRid APList_rid;
4be757dd
DW
5909 static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5910 static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1da177e4
LT
5911
5912 if (awrq->sa_family != ARPHRD_ETHER)
5913 return -EINVAL;
4be757dd
DW
5914 else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
5915 !memcmp(off, awrq->sa_data, ETH_ALEN)) {
1da177e4
LT
5916 memset(&cmd, 0, sizeof(cmd));
5917 cmd.cmd=CMD_LOSE_SYNC;
5918 if (down_interruptible(&local->sem))
5919 return -ERESTARTSYS;
5920 issuecommand(local, &cmd, &rsp);
5921 up(&local->sem);
5922 } else {
5923 memset(&APList_rid, 0, sizeof(APList_rid));
a749716e 5924 APList_rid.len = cpu_to_le16(sizeof(APList_rid));
1da177e4
LT
5925 memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
5926 disable_MAC(local, 1);
5927 writeAPListRid(local, &APList_rid, 1);
175ec1a1 5928 enable_MAC(local, 1);
1da177e4
LT
5929 }
5930 return 0;
5931}
5932
5933/*------------------------------------------------------------------*/
5934/*
5935 * Wireless Handler : get AP address
5936 */
5937static int airo_get_wap(struct net_device *dev,
5938 struct iw_request_info *info,
5939 struct sockaddr *awrq,
5940 char *extra)
5941{
faf3994a 5942 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5943 StatusRid status_rid; /* Card status info */
5944
5945 readStatusRid(local, &status_rid, 1);
5946
5947 /* Tentative. This seems to work, wow, I'm lucky !!! */
5948 memcpy(awrq->sa_data, status_rid.bssid[0], ETH_ALEN);
5949 awrq->sa_family = ARPHRD_ETHER;
5950
5951 return 0;
5952}
5953
5954/*------------------------------------------------------------------*/
5955/*
5956 * Wireless Handler : set Nickname
5957 */
5958static int airo_set_nick(struct net_device *dev,
5959 struct iw_request_info *info,
5960 struct iw_point *dwrq,
5961 char *extra)
5962{
faf3994a 5963 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5964
5965 /* Check the size of the string */
7f8544cc 5966 if(dwrq->length > 16) {
1da177e4
LT
5967 return -E2BIG;
5968 }
5969 readConfigRid(local, 1);
5970 memset(local->config.nodeName, 0, sizeof(local->config.nodeName));
5971 memcpy(local->config.nodeName, extra, dwrq->length);
5972 set_bit (FLAG_COMMIT, &local->flags);
5973
5974 return -EINPROGRESS; /* Call commit handler */
5975}
5976
5977/*------------------------------------------------------------------*/
5978/*
5979 * Wireless Handler : get Nickname
5980 */
5981static int airo_get_nick(struct net_device *dev,
5982 struct iw_request_info *info,
5983 struct iw_point *dwrq,
5984 char *extra)
5985{
faf3994a 5986 struct airo_info *local = dev->ml_priv;
1da177e4
LT
5987
5988 readConfigRid(local, 1);
5989 strncpy(extra, local->config.nodeName, 16);
5990 extra[16] = '\0';
7f8544cc 5991 dwrq->length = strlen(extra);
1da177e4
LT
5992
5993 return 0;
5994}
5995
5996/*------------------------------------------------------------------*/
5997/*
5998 * Wireless Handler : set Bit-Rate
5999 */
6000static int airo_set_rate(struct net_device *dev,
6001 struct iw_request_info *info,
6002 struct iw_param *vwrq,
6003 char *extra)
6004{
faf3994a 6005 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6006 CapabilityRid cap_rid; /* Card capability info */
6007 u8 brate = 0;
6008 int i;
6009
6010 /* First : get a valid bit rate value */
6011 readCapabilityRid(local, &cap_rid, 1);
6012
6013 /* Which type of value ? */
6014 if((vwrq->value < 8) && (vwrq->value >= 0)) {
6015 /* Setting by rate index */
6016 /* Find value in the magic rate table */
6017 brate = cap_rid.supportedRates[vwrq->value];
6018 } else {
6019 /* Setting by frequency value */
6020 u8 normvalue = (u8) (vwrq->value/500000);
6021
6022 /* Check if rate is valid */
6023 for(i = 0 ; i < 8 ; i++) {
6024 if(normvalue == cap_rid.supportedRates[i]) {
6025 brate = normvalue;
6026 break;
6027 }
6028 }
6029 }
6030 /* -1 designed the max rate (mostly auto mode) */
6031 if(vwrq->value == -1) {
6032 /* Get the highest available rate */
6033 for(i = 0 ; i < 8 ; i++) {
6034 if(cap_rid.supportedRates[i] == 0)
6035 break;
6036 }
6037 if(i != 0)
6038 brate = cap_rid.supportedRates[i - 1];
6039 }
6040 /* Check that it is valid */
6041 if(brate == 0) {
6042 return -EINVAL;
6043 }
6044
6045 readConfigRid(local, 1);
6046 /* Now, check if we want a fixed or auto value */
6047 if(vwrq->fixed == 0) {
6048 /* Fill all the rates up to this max rate */
6049 memset(local->config.rates, 0, 8);
6050 for(i = 0 ; i < 8 ; i++) {
6051 local->config.rates[i] = cap_rid.supportedRates[i];
6052 if(local->config.rates[i] == brate)
6053 break;
6054 }
6055 } else {
6056 /* Fixed mode */
6057 /* One rate, fixed */
6058 memset(local->config.rates, 0, 8);
6059 local->config.rates[0] = brate;
6060 }
6061 set_bit (FLAG_COMMIT, &local->flags);
6062
6063 return -EINPROGRESS; /* Call commit handler */
6064}
6065
6066/*------------------------------------------------------------------*/
6067/*
6068 * Wireless Handler : get Bit-Rate
6069 */
6070static int airo_get_rate(struct net_device *dev,
6071 struct iw_request_info *info,
6072 struct iw_param *vwrq,
6073 char *extra)
6074{
faf3994a 6075 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6076 StatusRid status_rid; /* Card status info */
6077
6078 readStatusRid(local, &status_rid, 1);
6079
329e2c00 6080 vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
1da177e4
LT
6081 /* If more than one rate, set auto */
6082 readConfigRid(local, 1);
6083 vwrq->fixed = (local->config.rates[1] == 0);
6084
6085 return 0;
6086}
6087
6088/*------------------------------------------------------------------*/
6089/*
6090 * Wireless Handler : set RTS threshold
6091 */
6092static int airo_set_rts(struct net_device *dev,
6093 struct iw_request_info *info,
6094 struct iw_param *vwrq,
6095 char *extra)
6096{
faf3994a 6097 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6098 int rthr = vwrq->value;
6099
6100 if(vwrq->disabled)
15db2763
DW
6101 rthr = AIRO_DEF_MTU;
6102 if((rthr < 0) || (rthr > AIRO_DEF_MTU)) {
1da177e4
LT
6103 return -EINVAL;
6104 }
6105 readConfigRid(local, 1);
3eb9b41f 6106 local->config.rtsThres = cpu_to_le16(rthr);
1da177e4
LT
6107 set_bit (FLAG_COMMIT, &local->flags);
6108
6109 return -EINPROGRESS; /* Call commit handler */
6110}
6111
6112/*------------------------------------------------------------------*/
6113/*
6114 * Wireless Handler : get RTS threshold
6115 */
6116static int airo_get_rts(struct net_device *dev,
6117 struct iw_request_info *info,
6118 struct iw_param *vwrq,
6119 char *extra)
6120{
faf3994a 6121 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6122
6123 readConfigRid(local, 1);
3eb9b41f 6124 vwrq->value = le16_to_cpu(local->config.rtsThres);
15db2763 6125 vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
1da177e4
LT
6126 vwrq->fixed = 1;
6127
6128 return 0;
6129}
6130
6131/*------------------------------------------------------------------*/
6132/*
6133 * Wireless Handler : set Fragmentation threshold
6134 */
6135static int airo_set_frag(struct net_device *dev,
6136 struct iw_request_info *info,
6137 struct iw_param *vwrq,
6138 char *extra)
6139{
faf3994a 6140 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6141 int fthr = vwrq->value;
6142
6143 if(vwrq->disabled)
15db2763
DW
6144 fthr = AIRO_DEF_MTU;
6145 if((fthr < 256) || (fthr > AIRO_DEF_MTU)) {
1da177e4
LT
6146 return -EINVAL;
6147 }
6148 fthr &= ~0x1; /* Get an even value - is it really needed ??? */
6149 readConfigRid(local, 1);
3eb9b41f 6150 local->config.fragThresh = cpu_to_le16(fthr);
1da177e4
LT
6151 set_bit (FLAG_COMMIT, &local->flags);
6152
6153 return -EINPROGRESS; /* Call commit handler */
6154}
6155
6156/*------------------------------------------------------------------*/
6157/*
6158 * Wireless Handler : get Fragmentation threshold
6159 */
6160static int airo_get_frag(struct net_device *dev,
6161 struct iw_request_info *info,
6162 struct iw_param *vwrq,
6163 char *extra)
6164{
faf3994a 6165 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6166
6167 readConfigRid(local, 1);
3eb9b41f 6168 vwrq->value = le16_to_cpu(local->config.fragThresh);
15db2763 6169 vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
1da177e4
LT
6170 vwrq->fixed = 1;
6171
6172 return 0;
6173}
6174
6175/*------------------------------------------------------------------*/
6176/*
6177 * Wireless Handler : set Mode of Operation
6178 */
6179static int airo_set_mode(struct net_device *dev,
6180 struct iw_request_info *info,
6181 __u32 *uwrq,
6182 char *extra)
6183{
faf3994a 6184 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6185 int reset = 0;
6186
6187 readConfigRid(local, 1);
3eb9b41f 6188 if (sniffing_mode(local))
1da177e4
LT
6189 reset = 1;
6190
6191 switch(*uwrq) {
6192 case IW_MODE_ADHOC:
3eb9b41f 6193 local->config.opmode &= ~MODE_CFG_MASK;
1da177e4 6194 local->config.opmode |= MODE_STA_IBSS;
3eb9b41f 6195 local->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4
LT
6196 local->config.scanMode = SCANMODE_ACTIVE;
6197 clear_bit (FLAG_802_11, &local->flags);
6198 break;
6199 case IW_MODE_INFRA:
3eb9b41f 6200 local->config.opmode &= ~MODE_CFG_MASK;
1da177e4 6201 local->config.opmode |= MODE_STA_ESS;
3eb9b41f 6202 local->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4
LT
6203 local->config.scanMode = SCANMODE_ACTIVE;
6204 clear_bit (FLAG_802_11, &local->flags);
6205 break;
6206 case IW_MODE_MASTER:
3eb9b41f 6207 local->config.opmode &= ~MODE_CFG_MASK;
1da177e4 6208 local->config.opmode |= MODE_AP;
3eb9b41f 6209 local->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4
LT
6210 local->config.scanMode = SCANMODE_ACTIVE;
6211 clear_bit (FLAG_802_11, &local->flags);
6212 break;
6213 case IW_MODE_REPEAT:
3eb9b41f 6214 local->config.opmode &= ~MODE_CFG_MASK;
1da177e4 6215 local->config.opmode |= MODE_AP_RPTR;
3eb9b41f 6216 local->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4
LT
6217 local->config.scanMode = SCANMODE_ACTIVE;
6218 clear_bit (FLAG_802_11, &local->flags);
6219 break;
6220 case IW_MODE_MONITOR:
3eb9b41f 6221 local->config.opmode &= ~MODE_CFG_MASK;
1da177e4 6222 local->config.opmode |= MODE_STA_ESS;
3eb9b41f 6223 local->config.rmode &= ~RXMODE_FULL_MASK;
1da177e4
LT
6224 local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
6225 local->config.scanMode = SCANMODE_PASSIVE;
6226 set_bit (FLAG_802_11, &local->flags);
6227 break;
6228 default:
6229 return -EINVAL;
6230 }
6231 if (reset)
6232 set_bit (FLAG_RESET, &local->flags);
6233 set_bit (FLAG_COMMIT, &local->flags);
6234
6235 return -EINPROGRESS; /* Call commit handler */
6236}
6237
6238/*------------------------------------------------------------------*/
6239/*
6240 * Wireless Handler : get Mode of Operation
6241 */
6242static int airo_get_mode(struct net_device *dev,
6243 struct iw_request_info *info,
6244 __u32 *uwrq,
6245 char *extra)
6246{
faf3994a 6247 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6248
6249 readConfigRid(local, 1);
6250 /* If not managed, assume it's ad-hoc */
3eb9b41f 6251 switch (local->config.opmode & MODE_CFG_MASK) {
1da177e4
LT
6252 case MODE_STA_ESS:
6253 *uwrq = IW_MODE_INFRA;
6254 break;
6255 case MODE_AP:
6256 *uwrq = IW_MODE_MASTER;
6257 break;
6258 case MODE_AP_RPTR:
6259 *uwrq = IW_MODE_REPEAT;
6260 break;
6261 default:
6262 *uwrq = IW_MODE_ADHOC;
6263 }
6264
6265 return 0;
6266}
6267
56d81bd3
AV
6268static inline int valid_index(CapabilityRid *p, int index)
6269{
6270 if (index < 0)
6271 return 0;
6272 return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
6273}
6274
1da177e4
LT
6275/*------------------------------------------------------------------*/
6276/*
6277 * Wireless Handler : set Encryption Key
6278 */
6279static int airo_set_encode(struct net_device *dev,
6280 struct iw_request_info *info,
6281 struct iw_point *dwrq,
6282 char *extra)
6283{
faf3994a 6284 struct airo_info *local = dev->ml_priv;
1da177e4 6285 CapabilityRid cap_rid; /* Card capability info */
f89b2321 6286 int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
3eb9b41f 6287 __le16 currentAuthType = local->config.authType;
1da177e4
LT
6288
6289 /* Is WEP supported ? */
6290 readCapabilityRid(local, &cap_rid, 1);
6291 /* Older firmware doesn't support this...
56d81bd3 6292 if(!(cap_rid.softCap & cpu_to_le16(2))) {
1da177e4
LT
6293 return -EOPNOTSUPP;
6294 } */
6295 readConfigRid(local, 1);
6296
6297 /* Basic checking: do we have a key to set ?
6298 * Note : with the new API, it's impossible to get a NULL pointer.
6299 * Therefore, we need to check a key size == 0 instead.
6300 * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
6301 * when no key is present (only change flags), but older versions
6302 * don't do it. - Jean II */
6303 if (dwrq->length > 0) {
6304 wep_key_t key;
6305 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6306 int current_index = get_wep_key(local, 0xffff);
6307 /* Check the size of the key */
6308 if (dwrq->length > MAX_KEY_SIZE) {
6309 return -EINVAL;
6310 }
6311 /* Check the index (none -> use current) */
56d81bd3 6312 if (!valid_index(&cap_rid, index))
1da177e4
LT
6313 index = current_index;
6314 /* Set the length */
6315 if (dwrq->length > MIN_KEY_SIZE)
6316 key.len = MAX_KEY_SIZE;
6317 else
6318 if (dwrq->length > 0)
6319 key.len = MIN_KEY_SIZE;
6320 else
6321 /* Disable the key */
6322 key.len = 0;
6323 /* Check if the key is not marked as invalid */
6324 if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
6325 /* Cleanup */
6326 memset(key.key, 0, MAX_KEY_SIZE);
6327 /* Copy the key in the driver */
6328 memcpy(key.key, extra, dwrq->length);
6329 /* Send the key to the card */
f89b2321 6330 set_wep_key(local, index, key.key, key.len, perm, 1);
1da177e4
LT
6331 }
6332 /* WE specify that if a valid key is set, encryption
6333 * should be enabled (user may turn it off later)
6334 * This is also how "iwconfig ethX key on" works */
6335 if((index == current_index) && (key.len > 0) &&
6336 (local->config.authType == AUTH_OPEN)) {
6337 local->config.authType = AUTH_ENCRYPT;
1da177e4
LT
6338 }
6339 } else {
6340 /* Do we want to just set the transmit key index ? */
6341 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
56d81bd3 6342 if (valid_index(&cap_rid, index)) {
f89b2321 6343 set_wep_key(local, index, NULL, 0, perm, 1);
1da177e4
LT
6344 } else
6345 /* Don't complain if only change the mode */
93a3b607 6346 if (!(dwrq->flags & IW_ENCODE_MODE))
1da177e4 6347 return -EINVAL;
1da177e4
LT
6348 }
6349 /* Read the flags */
6350 if(dwrq->flags & IW_ENCODE_DISABLED)
6351 local->config.authType = AUTH_OPEN; // disable encryption
6352 if(dwrq->flags & IW_ENCODE_RESTRICTED)
6353 local->config.authType = AUTH_SHAREDKEY; // Only Both
6354 if(dwrq->flags & IW_ENCODE_OPEN)
6355 local->config.authType = AUTH_ENCRYPT; // Only Wep
6356 /* Commit the changes to flags if needed */
f89b2321 6357 if (local->config.authType != currentAuthType)
1da177e4
LT
6358 set_bit (FLAG_COMMIT, &local->flags);
6359 return -EINPROGRESS; /* Call commit handler */
6360}
6361
6362/*------------------------------------------------------------------*/
6363/*
6364 * Wireless Handler : get Encryption Key
6365 */
6366static int airo_get_encode(struct net_device *dev,
6367 struct iw_request_info *info,
6368 struct iw_point *dwrq,
6369 char *extra)
6370{
faf3994a 6371 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6372 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6373 CapabilityRid cap_rid; /* Card capability info */
6374
6375 /* Is it supported ? */
6376 readCapabilityRid(local, &cap_rid, 1);
56d81bd3 6377 if(!(cap_rid.softCap & cpu_to_le16(2))) {
1da177e4
LT
6378 return -EOPNOTSUPP;
6379 }
6380 readConfigRid(local, 1);
6381 /* Check encryption mode */
6382 switch(local->config.authType) {
6383 case AUTH_ENCRYPT:
6384 dwrq->flags = IW_ENCODE_OPEN;
6385 break;
6386 case AUTH_SHAREDKEY:
6387 dwrq->flags = IW_ENCODE_RESTRICTED;
6388 break;
6389 default:
6390 case AUTH_OPEN:
6391 dwrq->flags = IW_ENCODE_DISABLED;
6392 break;
6393 }
6394 /* We can't return the key, so set the proper flag and return zero */
6395 dwrq->flags |= IW_ENCODE_NOKEY;
6396 memset(extra, 0, 16);
6397
6398 /* Which key do we want ? -1 -> tx index */
56d81bd3 6399 if (!valid_index(&cap_rid, index))
1da177e4
LT
6400 index = get_wep_key(local, 0xffff);
6401 dwrq->flags |= index + 1;
6402 /* Copy the key to the user buffer */
6403 dwrq->length = get_wep_key(local, index);
6404 if (dwrq->length > 16) {
6405 dwrq->length=0;
6406 }
6407 return 0;
6408}
6409
4be757dd
DW
6410/*------------------------------------------------------------------*/
6411/*
6412 * Wireless Handler : set extended Encryption parameters
6413 */
6414static int airo_set_encodeext(struct net_device *dev,
6415 struct iw_request_info *info,
6416 union iwreq_data *wrqu,
6417 char *extra)
6418{
faf3994a 6419 struct airo_info *local = dev->ml_priv;
4be757dd
DW
6420 struct iw_point *encoding = &wrqu->encoding;
6421 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6422 CapabilityRid cap_rid; /* Card capability info */
6423 int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
3eb9b41f 6424 __le16 currentAuthType = local->config.authType;
22d8846e 6425 int idx, key_len, alg = ext->alg, set_key = 1;
4be757dd
DW
6426 wep_key_t key;
6427
6428 /* Is WEP supported ? */
6429 readCapabilityRid(local, &cap_rid, 1);
6430 /* Older firmware doesn't support this...
56d81bd3 6431 if(!(cap_rid.softCap & cpu_to_le16(2))) {
4be757dd
DW
6432 return -EOPNOTSUPP;
6433 } */
6434 readConfigRid(local, 1);
6435
6436 /* Determine and validate the key index */
6437 idx = encoding->flags & IW_ENCODE_INDEX;
6438 if (idx) {
56d81bd3 6439 if (!valid_index(&cap_rid, idx - 1))
4be757dd
DW
6440 return -EINVAL;
6441 idx--;
6442 } else
6443 idx = get_wep_key(local, 0xffff);
6444
6445 if (encoding->flags & IW_ENCODE_DISABLED)
6446 alg = IW_ENCODE_ALG_NONE;
6447
4be757dd 6448 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
22d8846e
DW
6449 /* Only set transmit key index here, actual
6450 * key is set below if needed.
6451 */
4be757dd 6452 set_wep_key(local, idx, NULL, 0, perm, 1);
22d8846e
DW
6453 set_key = ext->key_len > 0 ? 1 : 0;
6454 }
6455
6456 if (set_key) {
4be757dd
DW
6457 /* Set the requested key first */
6458 memset(key.key, 0, MAX_KEY_SIZE);
6459 switch (alg) {
6460 case IW_ENCODE_ALG_NONE:
6461 key.len = 0;
6462 break;
6463 case IW_ENCODE_ALG_WEP:
6464 if (ext->key_len > MIN_KEY_SIZE) {
6465 key.len = MAX_KEY_SIZE;
6466 } else if (ext->key_len > 0) {
6467 key.len = MIN_KEY_SIZE;
6468 } else {
6469 return -EINVAL;
6470 }
6471 key_len = min (ext->key_len, key.len);
6472 memcpy(key.key, ext->key, key_len);
6473 break;
6474 default:
6475 return -EINVAL;
6476 }
6477 /* Send the key to the card */
6478 set_wep_key(local, idx, key.key, key.len, perm, 1);
6479 }
6480
6481 /* Read the flags */
6482 if(encoding->flags & IW_ENCODE_DISABLED)
6483 local->config.authType = AUTH_OPEN; // disable encryption
6484 if(encoding->flags & IW_ENCODE_RESTRICTED)
6485 local->config.authType = AUTH_SHAREDKEY; // Only Both
6486 if(encoding->flags & IW_ENCODE_OPEN)
6487 local->config.authType = AUTH_ENCRYPT; // Only Wep
6488 /* Commit the changes to flags if needed */
6489 if (local->config.authType != currentAuthType)
6490 set_bit (FLAG_COMMIT, &local->flags);
6491
6492 return -EINPROGRESS;
6493}
6494
6495
6496/*------------------------------------------------------------------*/
6497/*
6498 * Wireless Handler : get extended Encryption parameters
6499 */
6500static int airo_get_encodeext(struct net_device *dev,
6501 struct iw_request_info *info,
6502 union iwreq_data *wrqu,
6503 char *extra)
6504{
faf3994a 6505 struct airo_info *local = dev->ml_priv;
4be757dd
DW
6506 struct iw_point *encoding = &wrqu->encoding;
6507 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6508 CapabilityRid cap_rid; /* Card capability info */
6509 int idx, max_key_len;
6510
6511 /* Is it supported ? */
6512 readCapabilityRid(local, &cap_rid, 1);
56d81bd3 6513 if(!(cap_rid.softCap & cpu_to_le16(2))) {
4be757dd
DW
6514 return -EOPNOTSUPP;
6515 }
6516 readConfigRid(local, 1);
6517
6518 max_key_len = encoding->length - sizeof(*ext);
6519 if (max_key_len < 0)
6520 return -EINVAL;
6521
6522 idx = encoding->flags & IW_ENCODE_INDEX;
6523 if (idx) {
56d81bd3 6524 if (!valid_index(&cap_rid, idx - 1))
4be757dd
DW
6525 return -EINVAL;
6526 idx--;
6527 } else
6528 idx = get_wep_key(local, 0xffff);
6529
6530 encoding->flags = idx + 1;
6531 memset(ext, 0, sizeof(*ext));
6532
6533 /* Check encryption mode */
6534 switch(local->config.authType) {
6535 case AUTH_ENCRYPT:
6536 encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
6537 break;
6538 case AUTH_SHAREDKEY:
6539 encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
6540 break;
6541 default:
6542 case AUTH_OPEN:
6543 encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
6544 break;
6545 }
6546 /* We can't return the key, so set the proper flag and return zero */
6547 encoding->flags |= IW_ENCODE_NOKEY;
6548 memset(extra, 0, 16);
6549
6550 /* Copy the key to the user buffer */
6551 ext->key_len = get_wep_key(local, idx);
6552 if (ext->key_len > 16) {
6553 ext->key_len=0;
6554 }
6555
6556 return 0;
6557}
6558
6559
6560/*------------------------------------------------------------------*/
6561/*
6562 * Wireless Handler : set extended authentication parameters
6563 */
6564static int airo_set_auth(struct net_device *dev,
6565 struct iw_request_info *info,
6566 union iwreq_data *wrqu, char *extra)
6567{
faf3994a 6568 struct airo_info *local = dev->ml_priv;
4be757dd 6569 struct iw_param *param = &wrqu->param;
3eb9b41f 6570 __le16 currentAuthType = local->config.authType;
4be757dd
DW
6571
6572 switch (param->flags & IW_AUTH_INDEX) {
6573 case IW_AUTH_WPA_VERSION:
6574 case IW_AUTH_CIPHER_PAIRWISE:
6575 case IW_AUTH_CIPHER_GROUP:
6576 case IW_AUTH_KEY_MGMT:
6577 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
6578 case IW_AUTH_PRIVACY_INVOKED:
6579 /*
6580 * airo does not use these parameters
6581 */
6582 break;
6583
6584 case IW_AUTH_DROP_UNENCRYPTED:
6585 if (param->value) {
6586 /* Only change auth type if unencrypted */
6587 if (currentAuthType == AUTH_OPEN)
6588 local->config.authType = AUTH_ENCRYPT;
6589 } else {
6590 local->config.authType = AUTH_OPEN;
6591 }
6592
6593 /* Commit the changes to flags if needed */
6594 if (local->config.authType != currentAuthType)
6595 set_bit (FLAG_COMMIT, &local->flags);
6596 break;
6597
6598 case IW_AUTH_80211_AUTH_ALG: {
6599 /* FIXME: What about AUTH_OPEN? This API seems to
6600 * disallow setting our auth to AUTH_OPEN.
6601 */
6602 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
6603 local->config.authType = AUTH_SHAREDKEY;
6604 } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
6605 local->config.authType = AUTH_ENCRYPT;
6606 } else
6607 return -EINVAL;
6608 break;
6609
6610 /* Commit the changes to flags if needed */
6611 if (local->config.authType != currentAuthType)
6612 set_bit (FLAG_COMMIT, &local->flags);
6613 }
6614
6615 case IW_AUTH_WPA_ENABLED:
6616 /* Silently accept disable of WPA */
6617 if (param->value > 0)
6618 return -EOPNOTSUPP;
6619 break;
6620
6621 default:
6622 return -EOPNOTSUPP;
6623 }
6624 return -EINPROGRESS;
6625}
6626
6627
6628/*------------------------------------------------------------------*/
6629/*
6630 * Wireless Handler : get extended authentication parameters
6631 */
6632static int airo_get_auth(struct net_device *dev,
6633 struct iw_request_info *info,
6634 union iwreq_data *wrqu, char *extra)
6635{
faf3994a 6636 struct airo_info *local = dev->ml_priv;
4be757dd 6637 struct iw_param *param = &wrqu->param;
3eb9b41f 6638 __le16 currentAuthType = local->config.authType;
4be757dd
DW
6639
6640 switch (param->flags & IW_AUTH_INDEX) {
6641 case IW_AUTH_DROP_UNENCRYPTED:
6642 switch (currentAuthType) {
6643 case AUTH_SHAREDKEY:
6644 case AUTH_ENCRYPT:
6645 param->value = 1;
6646 break;
6647 default:
6648 param->value = 0;
6649 break;
6650 }
6651 break;
6652
6653 case IW_AUTH_80211_AUTH_ALG:
6654 switch (currentAuthType) {
6655 case AUTH_SHAREDKEY:
6656 param->value = IW_AUTH_ALG_SHARED_KEY;
6657 break;
6658 case AUTH_ENCRYPT:
6659 default:
6660 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
6661 break;
6662 }
6663 break;
6664
6665 case IW_AUTH_WPA_ENABLED:
6666 param->value = 0;
6667 break;
6668
6669 default:
6670 return -EOPNOTSUPP;
6671 }
6672 return 0;
6673}
6674
6675
1da177e4
LT
6676/*------------------------------------------------------------------*/
6677/*
6678 * Wireless Handler : set Tx-Power
6679 */
6680static int airo_set_txpow(struct net_device *dev,
6681 struct iw_request_info *info,
6682 struct iw_param *vwrq,
6683 char *extra)
6684{
faf3994a 6685 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6686 CapabilityRid cap_rid; /* Card capability info */
6687 int i;
6688 int rc = -EINVAL;
3eb9b41f 6689 __le16 v = cpu_to_le16(vwrq->value);
1da177e4
LT
6690
6691 readCapabilityRid(local, &cap_rid, 1);
6692
6693 if (vwrq->disabled) {
6694 set_bit (FLAG_RADIO_OFF, &local->flags);
6695 set_bit (FLAG_COMMIT, &local->flags);
6696 return -EINPROGRESS; /* Call commit handler */
6697 }
6698 if (vwrq->flags != IW_TXPOW_MWATT) {
6699 return -EINVAL;
6700 }
6701 clear_bit (FLAG_RADIO_OFF, &local->flags);
6702 for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
3eb9b41f 6703 if (v == cap_rid.txPowerLevels[i]) {
1da177e4 6704 readConfigRid(local, 1);
3eb9b41f 6705 local->config.txPower = v;
1da177e4
LT
6706 set_bit (FLAG_COMMIT, &local->flags);
6707 rc = -EINPROGRESS; /* Call commit handler */
6708 break;
6709 }
6710 return rc;
6711}
6712
6713/*------------------------------------------------------------------*/
6714/*
6715 * Wireless Handler : get Tx-Power
6716 */
6717static int airo_get_txpow(struct net_device *dev,
6718 struct iw_request_info *info,
6719 struct iw_param *vwrq,
6720 char *extra)
6721{
faf3994a 6722 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6723
6724 readConfigRid(local, 1);
3eb9b41f 6725 vwrq->value = le16_to_cpu(local->config.txPower);
1da177e4
LT
6726 vwrq->fixed = 1; /* No power control */
6727 vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags);
6728 vwrq->flags = IW_TXPOW_MWATT;
6729
6730 return 0;
6731}
6732
6733/*------------------------------------------------------------------*/
6734/*
6735 * Wireless Handler : set Retry limits
6736 */
6737static int airo_set_retry(struct net_device *dev,
6738 struct iw_request_info *info,
6739 struct iw_param *vwrq,
6740 char *extra)
6741{
faf3994a 6742 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6743 int rc = -EINVAL;
6744
6745 if(vwrq->disabled) {
6746 return -EINVAL;
6747 }
6748 readConfigRid(local, 1);
6749 if(vwrq->flags & IW_RETRY_LIMIT) {
3eb9b41f 6750 __le16 v = cpu_to_le16(vwrq->value);
7f8544cc 6751 if(vwrq->flags & IW_RETRY_LONG)
3eb9b41f 6752 local->config.longRetryLimit = v;
7f8544cc 6753 else if (vwrq->flags & IW_RETRY_SHORT)
3eb9b41f 6754 local->config.shortRetryLimit = v;
1da177e4
LT
6755 else {
6756 /* No modifier : set both */
3eb9b41f
AV
6757 local->config.longRetryLimit = v;
6758 local->config.shortRetryLimit = v;
1da177e4
LT
6759 }
6760 set_bit (FLAG_COMMIT, &local->flags);
6761 rc = -EINPROGRESS; /* Call commit handler */
6762 }
6763 if(vwrq->flags & IW_RETRY_LIFETIME) {
3eb9b41f 6764 local->config.txLifetime = cpu_to_le16(vwrq->value / 1024);
1da177e4
LT
6765 set_bit (FLAG_COMMIT, &local->flags);
6766 rc = -EINPROGRESS; /* Call commit handler */
6767 }
6768 return rc;
6769}
6770
6771/*------------------------------------------------------------------*/
6772/*
6773 * Wireless Handler : get Retry limits
6774 */
6775static int airo_get_retry(struct net_device *dev,
6776 struct iw_request_info *info,
6777 struct iw_param *vwrq,
6778 char *extra)
6779{
faf3994a 6780 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6781
6782 vwrq->disabled = 0; /* Can't be disabled */
6783
6784 readConfigRid(local, 1);
6785 /* Note : by default, display the min retry number */
6786 if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
6787 vwrq->flags = IW_RETRY_LIFETIME;
3eb9b41f 6788 vwrq->value = le16_to_cpu(local->config.txLifetime) * 1024;
7f8544cc
JT
6789 } else if((vwrq->flags & IW_RETRY_LONG)) {
6790 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
3eb9b41f 6791 vwrq->value = le16_to_cpu(local->config.longRetryLimit);
1da177e4
LT
6792 } else {
6793 vwrq->flags = IW_RETRY_LIMIT;
3eb9b41f
AV
6794 vwrq->value = le16_to_cpu(local->config.shortRetryLimit);
6795 if(local->config.shortRetryLimit != local->config.longRetryLimit)
7f8544cc 6796 vwrq->flags |= IW_RETRY_SHORT;
1da177e4
LT
6797 }
6798
6799 return 0;
6800}
6801
6802/*------------------------------------------------------------------*/
6803/*
6804 * Wireless Handler : get range info
6805 */
6806static int airo_get_range(struct net_device *dev,
6807 struct iw_request_info *info,
6808 struct iw_point *dwrq,
6809 char *extra)
6810{
faf3994a 6811 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6812 struct iw_range *range = (struct iw_range *) extra;
6813 CapabilityRid cap_rid; /* Card capability info */
6814 int i;
6815 int k;
6816
6817 readCapabilityRid(local, &cap_rid, 1);
6818
6819 dwrq->length = sizeof(struct iw_range);
6820 memset(range, 0, sizeof(*range));
6821 range->min_nwid = 0x0000;
6822 range->max_nwid = 0x0000;
6823 range->num_channels = 14;
6824 /* Should be based on cap_rid.country to give only
6825 * what the current card support */
6826 k = 0;
6827 for(i = 0; i < 14; i++) {
6828 range->freq[k].i = i + 1; /* List index */
9ee677c2
DK
6829 range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
6830 range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */
1da177e4
LT
6831 }
6832 range->num_frequency = k;
6833
41480af2
DW
6834 range->sensitivity = 65535;
6835
1da177e4 6836 /* Hum... Should put the right values there */
41480af2
DW
6837 if (local->rssi)
6838 range->max_qual.qual = 100; /* % */
6839 else
6840 range->max_qual.qual = airo_get_max_quality(&cap_rid);
ce6623c3
JT
6841 range->max_qual.level = 0x100 - 120; /* -120 dBm */
6842 range->max_qual.noise = 0x100 - 120; /* -120 dBm */
41480af2
DW
6843
6844 /* Experimental measurements - boundary 11/5.5 Mb/s */
6845 /* Note : with or without the (local->rssi), results
6846 * are somewhat different. - Jean II */
6847 if (local->rssi) {
ce6623c3
JT
6848 range->avg_qual.qual = 50; /* % */
6849 range->avg_qual.level = 0x100 - 70; /* -70 dBm */
41480af2
DW
6850 } else {
6851 range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
ce6623c3 6852 range->avg_qual.level = 0x100 - 80; /* -80 dBm */
41480af2 6853 }
ce6623c3 6854 range->avg_qual.noise = 0x100 - 85; /* -85 dBm */
1da177e4
LT
6855
6856 for(i = 0 ; i < 8 ; i++) {
6857 range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
6858 if(range->bitrate[i] == 0)
6859 break;
6860 }
6861 range->num_bitrates = i;
6862
6863 /* Set an indication of the max TCP throughput
6864 * in bit/s that we can expect using this interface.
6865 * May be use for QoS stuff... Jean II */
6866 if(i > 2)
6867 range->throughput = 5000 * 1000;
6868 else
6869 range->throughput = 1500 * 1000;
6870
6871 range->min_rts = 0;
15db2763 6872 range->max_rts = AIRO_DEF_MTU;
1da177e4 6873 range->min_frag = 256;
15db2763 6874 range->max_frag = AIRO_DEF_MTU;
1da177e4 6875
56d81bd3 6876 if(cap_rid.softCap & cpu_to_le16(2)) {
1da177e4
LT
6877 // WEP: RC4 40 bits
6878 range->encoding_size[0] = 5;
6879 // RC4 ~128 bits
56d81bd3 6880 if (cap_rid.softCap & cpu_to_le16(0x100)) {
1da177e4
LT
6881 range->encoding_size[1] = 13;
6882 range->num_encoding_sizes = 2;
6883 } else
6884 range->num_encoding_sizes = 1;
56d81bd3
AV
6885 range->max_encoding_tokens =
6886 cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1;
1da177e4
LT
6887 } else {
6888 range->num_encoding_sizes = 0;
6889 range->max_encoding_tokens = 0;
6890 }
6891 range->min_pmp = 0;
6892 range->max_pmp = 5000000; /* 5 secs */
6893 range->min_pmt = 0;
6894 range->max_pmt = 65535 * 1024; /* ??? */
6895 range->pmp_flags = IW_POWER_PERIOD;
6896 range->pmt_flags = IW_POWER_TIMEOUT;
6897 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
6898
6899 /* Transmit Power - values are in mW */
6900 for(i = 0 ; i < 8 ; i++) {
56d81bd3 6901 range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]);
1da177e4
LT
6902 if(range->txpower[i] == 0)
6903 break;
6904 }
6905 range->num_txpower = i;
6906 range->txpower_capa = IW_TXPOW_MWATT;
3c304956 6907 range->we_version_source = 19;
1da177e4
LT
6908 range->we_version_compiled = WIRELESS_EXT;
6909 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
6910 range->retry_flags = IW_RETRY_LIMIT;
6911 range->r_time_flags = IW_RETRY_LIFETIME;
6912 range->min_retry = 1;
6913 range->max_retry = 65535;
6914 range->min_r_time = 1024;
6915 range->max_r_time = 65535 * 1024;
1da177e4
LT
6916
6917 /* Event capability (kernel + driver) */
6918 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
6919 IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
6920 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
6921 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
6922 range->event_capa[1] = IW_EVENT_CAPA_K_1;
6923 range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP);
6924 return 0;
6925}
6926
6927/*------------------------------------------------------------------*/
6928/*
6929 * Wireless Handler : set Power Management
6930 */
6931static int airo_set_power(struct net_device *dev,
6932 struct iw_request_info *info,
6933 struct iw_param *vwrq,
6934 char *extra)
6935{
faf3994a 6936 struct airo_info *local = dev->ml_priv;
1da177e4
LT
6937
6938 readConfigRid(local, 1);
6939 if (vwrq->disabled) {
3eb9b41f 6940 if (sniffing_mode(local))
1da177e4 6941 return -EINVAL;
1da177e4 6942 local->config.powerSaveMode = POWERSAVE_CAM;
3eb9b41f 6943 local->config.rmode &= ~RXMODE_MASK;
1da177e4
LT
6944 local->config.rmode |= RXMODE_BC_MC_ADDR;
6945 set_bit (FLAG_COMMIT, &local->flags);
6946 return -EINPROGRESS; /* Call commit handler */
6947 }
6948 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3eb9b41f 6949 local->config.fastListenDelay = cpu_to_le16((vwrq->value + 500) / 1024);
1da177e4
LT
6950 local->config.powerSaveMode = POWERSAVE_PSPCAM;
6951 set_bit (FLAG_COMMIT, &local->flags);
6952 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
3eb9b41f
AV
6953 local->config.fastListenInterval =
6954 local->config.listenInterval =
6955 cpu_to_le16((vwrq->value + 500) / 1024);
1da177e4
LT
6956 local->config.powerSaveMode = POWERSAVE_PSPCAM;
6957 set_bit (FLAG_COMMIT, &local->flags);
6958 }
6959 switch (vwrq->flags & IW_POWER_MODE) {
6960 case IW_POWER_UNICAST_R:
3eb9b41f 6961 if (sniffing_mode(local))
1da177e4 6962 return -EINVAL;
3eb9b41f 6963 local->config.rmode &= ~RXMODE_MASK;
1da177e4
LT
6964 local->config.rmode |= RXMODE_ADDR;
6965 set_bit (FLAG_COMMIT, &local->flags);
6966 break;
6967 case IW_POWER_ALL_R:
3eb9b41f 6968 if (sniffing_mode(local))
1da177e4 6969 return -EINVAL;
3eb9b41f 6970 local->config.rmode &= ~RXMODE_MASK;
1da177e4
LT
6971 local->config.rmode |= RXMODE_BC_MC_ADDR;
6972 set_bit (FLAG_COMMIT, &local->flags);
6973 case IW_POWER_ON:
7f8544cc 6974 /* This is broken, fixme ;-) */
1da177e4
LT
6975 break;
6976 default:
6977 return -EINVAL;
6978 }
6979 // Note : we may want to factor local->need_commit here
6980 // Note2 : may also want to factor RXMODE_RFMON test
6981 return -EINPROGRESS; /* Call commit handler */
6982}
6983
6984/*------------------------------------------------------------------*/
6985/*
6986 * Wireless Handler : get Power Management
6987 */
6988static int airo_get_power(struct net_device *dev,
6989 struct iw_request_info *info,
6990 struct iw_param *vwrq,
6991 char *extra)
6992{
faf3994a 6993 struct airo_info *local = dev->ml_priv;
3eb9b41f 6994 __le16 mode;
1da177e4
LT
6995
6996 readConfigRid(local, 1);
6997 mode = local->config.powerSaveMode;
6998 if ((vwrq->disabled = (mode == POWERSAVE_CAM)))
6999 return 0;
7000 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3eb9b41f 7001 vwrq->value = le16_to_cpu(local->config.fastListenDelay) * 1024;
1da177e4
LT
7002 vwrq->flags = IW_POWER_TIMEOUT;
7003 } else {
3eb9b41f 7004 vwrq->value = le16_to_cpu(local->config.fastListenInterval) * 1024;
1da177e4
LT
7005 vwrq->flags = IW_POWER_PERIOD;
7006 }
3eb9b41f 7007 if ((local->config.rmode & RXMODE_MASK) == RXMODE_ADDR)
1da177e4
LT
7008 vwrq->flags |= IW_POWER_UNICAST_R;
7009 else
7010 vwrq->flags |= IW_POWER_ALL_R;
7011
7012 return 0;
7013}
7014
7015/*------------------------------------------------------------------*/
7016/*
7017 * Wireless Handler : set Sensitivity
7018 */
7019static int airo_set_sens(struct net_device *dev,
7020 struct iw_request_info *info,
7021 struct iw_param *vwrq,
7022 char *extra)
7023{
faf3994a 7024 struct airo_info *local = dev->ml_priv;
1da177e4
LT
7025
7026 readConfigRid(local, 1);
3eb9b41f
AV
7027 local->config.rssiThreshold =
7028 cpu_to_le16(vwrq->disabled ? RSSI_DEFAULT : vwrq->value);
1da177e4
LT
7029 set_bit (FLAG_COMMIT, &local->flags);
7030
7031 return -EINPROGRESS; /* Call commit handler */
7032}
7033
7034/*------------------------------------------------------------------*/
7035/*
7036 * Wireless Handler : get Sensitivity
7037 */
7038static int airo_get_sens(struct net_device *dev,
7039 struct iw_request_info *info,
7040 struct iw_param *vwrq,
7041 char *extra)
7042{
faf3994a 7043 struct airo_info *local = dev->ml_priv;
1da177e4
LT
7044
7045 readConfigRid(local, 1);
3eb9b41f 7046 vwrq->value = le16_to_cpu(local->config.rssiThreshold);
1da177e4
LT
7047 vwrq->disabled = (vwrq->value == 0);
7048 vwrq->fixed = 1;
7049
7050 return 0;
7051}
7052
7053/*------------------------------------------------------------------*/
7054/*
7055 * Wireless Handler : get AP List
7056 * Note : this is deprecated in favor of IWSCAN
7057 */
7058static int airo_get_aplist(struct net_device *dev,
7059 struct iw_request_info *info,
7060 struct iw_point *dwrq,
7061 char *extra)
7062{
faf3994a 7063 struct airo_info *local = dev->ml_priv;
1da177e4
LT
7064 struct sockaddr *address = (struct sockaddr *) extra;
7065 struct iw_quality qual[IW_MAX_AP];
7066 BSSListRid BSSList;
7067 int i;
7068 int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
7069
7070 for (i = 0; i < IW_MAX_AP; i++) {
17e70491 7071 u16 dBm;
1da177e4
LT
7072 if (readBSSListRid(local, loseSync, &BSSList))
7073 break;
7074 loseSync = 0;
7075 memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
7076 address[i].sa_family = ARPHRD_ETHER;
17e70491 7077 dBm = le16_to_cpu(BSSList.dBm);
41480af2 7078 if (local->rssi) {
17e70491
AV
7079 qual[i].level = 0x100 - dBm;
7080 qual[i].qual = airo_dbm_to_pct(local->rssi, dBm);
ce6623c3
JT
7081 qual[i].updated = IW_QUAL_QUAL_UPDATED
7082 | IW_QUAL_LEVEL_UPDATED
7083 | IW_QUAL_DBM;
41480af2 7084 } else {
17e70491 7085 qual[i].level = (dBm + 321) / 2;
41480af2 7086 qual[i].qual = 0;
ce6623c3
JT
7087 qual[i].updated = IW_QUAL_QUAL_INVALID
7088 | IW_QUAL_LEVEL_UPDATED
7089 | IW_QUAL_DBM;
41480af2
DW
7090 }
7091 qual[i].noise = local->wstats.qual.noise;
17e70491 7092 if (BSSList.index == cpu_to_le16(0xffff))
1da177e4
LT
7093 break;
7094 }
7095 if (!i) {
7096 StatusRid status_rid; /* Card status info */
7097 readStatusRid(local, &status_rid, 1);
7098 for (i = 0;
7099 i < min(IW_MAX_AP, 4) &&
7100 (status_rid.bssid[i][0]
7101 & status_rid.bssid[i][1]
7102 & status_rid.bssid[i][2]
7103 & status_rid.bssid[i][3]
7104 & status_rid.bssid[i][4]
7105 & status_rid.bssid[i][5])!=0xff &&
7106 (status_rid.bssid[i][0]
7107 | status_rid.bssid[i][1]
7108 | status_rid.bssid[i][2]
7109 | status_rid.bssid[i][3]
7110 | status_rid.bssid[i][4]
7111 | status_rid.bssid[i][5]);
7112 i++) {
7113 memcpy(address[i].sa_data,
7114 status_rid.bssid[i], ETH_ALEN);
7115 address[i].sa_family = ARPHRD_ETHER;
7116 }
7117 } else {
7118 dwrq->flags = 1; /* Should be define'd */
7119 memcpy(extra + sizeof(struct sockaddr)*i,
7120 &qual, sizeof(struct iw_quality)*i);
7121 }
7122 dwrq->length = i;
7123
7124 return 0;
7125}
7126
7127/*------------------------------------------------------------------*/
7128/*
7129 * Wireless Handler : Initiate Scan
7130 */
7131static int airo_set_scan(struct net_device *dev,
7132 struct iw_request_info *info,
9930ccee 7133 struct iw_point *dwrq,
1da177e4
LT
7134 char *extra)
7135{
faf3994a 7136 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
7137 Cmd cmd;
7138 Resp rsp;
9e75af30 7139 int wake = 0;
1da177e4
LT
7140
7141 /* Note : you may have realised that, as this is a SET operation,
7142 * this is privileged and therefore a normal user can't
7143 * perform scanning.
7144 * This is not an error, while the device perform scanning,
7145 * traffic doesn't flow, so it's a perfect DoS...
7146 * Jean II */
7147 if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
7148
9e75af30
DW
7149 if (down_interruptible(&ai->sem))
7150 return -ERESTARTSYS;
7151
7152 /* If there's already a scan in progress, don't
7153 * trigger another one. */
7154 if (ai->scan_timeout > 0)
7155 goto out;
7156
1da177e4 7157 /* Initiate a scan command */
6fcdf565 7158 ai->scan_timeout = RUN_AT(3*HZ);
1da177e4
LT
7159 memset(&cmd, 0, sizeof(cmd));
7160 cmd.cmd=CMD_LISTBSS;
1da177e4 7161 issuecommand(ai, &cmd, &rsp);
9e75af30 7162 wake = 1;
1da177e4 7163
9e75af30
DW
7164out:
7165 up(&ai->sem);
7166 if (wake)
7167 wake_up_interruptible(&ai->thr_wait);
1da177e4
LT
7168 return 0;
7169}
7170
7171/*------------------------------------------------------------------*/
7172/*
7173 * Translate scan data returned from the card to a card independent
7174 * format that the Wireless Tools will understand - Jean II
7175 */
7176static inline char *airo_translate_scan(struct net_device *dev,
ccc58057 7177 struct iw_request_info *info,
1da177e4
LT
7178 char *current_ev,
7179 char *end_buf,
41480af2 7180 BSSListRid *bss)
1da177e4 7181{
faf3994a 7182 struct airo_info *ai = dev->ml_priv;
1da177e4 7183 struct iw_event iwe; /* Temporary buffer */
17e70491 7184 __le16 capabilities;
1da177e4
LT
7185 char * current_val; /* For rates */
7186 int i;
3c304956 7187 char * buf;
851b3e5e 7188 u16 dBm;
1da177e4
LT
7189
7190 /* First entry *MUST* be the AP MAC address */
7191 iwe.cmd = SIOCGIWAP;
7192 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
41480af2 7193 memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
ccc58057
DM
7194 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
7195 &iwe, IW_EV_ADDR_LEN);
1da177e4
LT
7196
7197 /* Other entries will be displayed in the order we give them */
7198
7199 /* Add the ESSID */
41480af2 7200 iwe.u.data.length = bss->ssidLen;
1da177e4
LT
7201 if(iwe.u.data.length > 32)
7202 iwe.u.data.length = 32;
7203 iwe.cmd = SIOCGIWESSID;
7204 iwe.u.data.flags = 1;
ccc58057
DM
7205 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
7206 &iwe, bss->ssid);
1da177e4
LT
7207
7208 /* Add mode */
7209 iwe.cmd = SIOCGIWMODE;
17e70491 7210 capabilities = bss->cap;
1da177e4
LT
7211 if(capabilities & (CAP_ESS | CAP_IBSS)) {
7212 if(capabilities & CAP_ESS)
7213 iwe.u.mode = IW_MODE_MASTER;
7214 else
7215 iwe.u.mode = IW_MODE_ADHOC;
ccc58057
DM
7216 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
7217 &iwe, IW_EV_UINT_LEN);
1da177e4
LT
7218 }
7219
7220 /* Add frequency */
7221 iwe.cmd = SIOCGIWFREQ;
41480af2 7222 iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
9ee677c2 7223 iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000;
1da177e4 7224 iwe.u.freq.e = 1;
ccc58057
DM
7225 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
7226 &iwe, IW_EV_FREQ_LEN);
1da177e4 7227
851b3e5e
AV
7228 dBm = le16_to_cpu(bss->dBm);
7229
1da177e4
LT
7230 /* Add quality statistics */
7231 iwe.cmd = IWEVQUAL;
41480af2 7232 if (ai->rssi) {
851b3e5e
AV
7233 iwe.u.qual.level = 0x100 - dBm;
7234 iwe.u.qual.qual = airo_dbm_to_pct(ai->rssi, dBm);
ce6623c3
JT
7235 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
7236 | IW_QUAL_LEVEL_UPDATED
7237 | IW_QUAL_DBM;
41480af2 7238 } else {
851b3e5e 7239 iwe.u.qual.level = (dBm + 321) / 2;
41480af2 7240 iwe.u.qual.qual = 0;
bbeec90b 7241 iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
ce6623c3
JT
7242 | IW_QUAL_LEVEL_UPDATED
7243 | IW_QUAL_DBM;
41480af2
DW
7244 }
7245 iwe.u.qual.noise = ai->wstats.qual.noise;
ccc58057
DM
7246 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
7247 &iwe, IW_EV_QUAL_LEN);
1da177e4
LT
7248
7249 /* Add encryption capability */
7250 iwe.cmd = SIOCGIWENCODE;
7251 if(capabilities & CAP_PRIVACY)
7252 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
7253 else
7254 iwe.u.data.flags = IW_ENCODE_DISABLED;
7255 iwe.u.data.length = 0;
ccc58057
DM
7256 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
7257 &iwe, bss->ssid);
1da177e4
LT
7258
7259 /* Rate : stuffing multiple values in a single event require a bit
7260 * more of magic - Jean II */
ccc58057 7261 current_val = current_ev + iwe_stream_lcp_len(info);
1da177e4
LT
7262
7263 iwe.cmd = SIOCGIWRATE;
7264 /* Those two flags are ignored... */
7265 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
7266 /* Max 8 values */
7267 for(i = 0 ; i < 8 ; i++) {
7268 /* NULL terminated */
41480af2 7269 if(bss->rates[i] == 0)
1da177e4
LT
7270 break;
7271 /* Bit rate given in 500 kb/s units (+ 0x80) */
41480af2 7272 iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
1da177e4 7273 /* Add new value to event */
ccc58057
DM
7274 current_val = iwe_stream_add_value(info, current_ev,
7275 current_val, end_buf,
7276 &iwe, IW_EV_PARAM_LEN);
1da177e4
LT
7277 }
7278 /* Check if we added any event */
ccc58057 7279 if ((current_val - current_ev) > iwe_stream_lcp_len(info))
1da177e4
LT
7280 current_ev = current_val;
7281
3c304956
DW
7282 /* Beacon interval */
7283 buf = kmalloc(30, GFP_KERNEL);
7284 if (buf) {
7285 iwe.cmd = IWEVCUSTOM;
7286 sprintf(buf, "bcn_int=%d", bss->beaconInterval);
7287 iwe.u.data.length = strlen(buf);
ccc58057
DM
7288 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
7289 &iwe, buf);
3c304956
DW
7290 kfree(buf);
7291 }
7292
7293 /* Put WPA/RSN Information Elements into the event stream */
7294 if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
7295 unsigned int num_null_ies = 0;
7296 u16 length = sizeof (bss->extra.iep);
2c706002 7297 u8 *ie = (void *)&bss->extra.iep;
3c304956 7298
2c706002
JB
7299 while ((length >= 2) && (num_null_ies < 2)) {
7300 if (2 + ie[1] > length) {
3c304956
DW
7301 /* Invalid element, don't continue parsing IE */
7302 break;
7303 }
7304
2c706002
JB
7305 switch (ie[0]) {
7306 case WLAN_EID_SSID:
3c304956
DW
7307 /* Two zero-length SSID elements
7308 * mean we're done parsing elements */
2c706002 7309 if (!ie[1])
3c304956
DW
7310 num_null_ies++;
7311 break;
7312
2c706002
JB
7313 case WLAN_EID_GENERIC:
7314 if (ie[1] >= 4 &&
7315 ie[2] == 0x00 &&
7316 ie[3] == 0x50 &&
7317 ie[4] == 0xf2 &&
7318 ie[5] == 0x01) {
3c304956 7319 iwe.cmd = IWEVGENIE;
2c706002
JB
7320 /* 64 is an arbitrary cut-off */
7321 iwe.u.data.length = min(ie[1] + 2,
7322 64);
ccc58057
DM
7323 current_ev = iwe_stream_add_point(
7324 info, current_ev,
2c706002 7325 end_buf, &iwe, ie);
3c304956
DW
7326 }
7327 break;
7328
2c706002 7329 case WLAN_EID_RSN:
3c304956 7330 iwe.cmd = IWEVGENIE;
2c706002
JB
7331 /* 64 is an arbitrary cut-off */
7332 iwe.u.data.length = min(ie[1] + 2, 64);
ccc58057
DM
7333 current_ev = iwe_stream_add_point(
7334 info, current_ev, end_buf,
2c706002 7335 &iwe, ie);
3c304956
DW
7336 break;
7337
7338 default:
7339 break;
7340 }
7341
2c706002
JB
7342 length -= 2 + ie[1];
7343 ie += 2 + ie[1];
3c304956
DW
7344 }
7345 }
1da177e4
LT
7346 return current_ev;
7347}
7348
7349/*------------------------------------------------------------------*/
7350/*
7351 * Wireless Handler : Read Scan Results
7352 */
7353static int airo_get_scan(struct net_device *dev,
7354 struct iw_request_info *info,
7355 struct iw_point *dwrq,
7356 char *extra)
7357{
faf3994a 7358 struct airo_info *ai = dev->ml_priv;
9e75af30
DW
7359 BSSListElement *net;
7360 int err = 0;
1da177e4
LT
7361 char *current_ev = extra;
7362
9e75af30
DW
7363 /* If a scan is in-progress, return -EAGAIN */
7364 if (ai->scan_timeout > 0)
1da177e4 7365 return -EAGAIN;
1da177e4 7366
9e75af30
DW
7367 if (down_interruptible(&ai->sem))
7368 return -EAGAIN;
1da177e4 7369
9e75af30 7370 list_for_each_entry (net, &ai->network_list, list) {
1da177e4 7371 /* Translate to WE format this entry */
ccc58057 7372 current_ev = airo_translate_scan(dev, info, current_ev,
1da177e4 7373 extra + dwrq->length,
9e75af30 7374 &net->bss);
1da177e4
LT
7375
7376 /* Check if there is space for one more entry */
7377 if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
7378 /* Ask user space to try again with a bigger buffer */
9e75af30
DW
7379 err = -E2BIG;
7380 goto out;
1da177e4 7381 }
1da177e4 7382 }
9e75af30 7383
1da177e4
LT
7384 /* Length of data */
7385 dwrq->length = (current_ev - extra);
7386 dwrq->flags = 0; /* todo */
7387
9e75af30
DW
7388out:
7389 up(&ai->sem);
7390 return err;
1da177e4
LT
7391}
7392
7393/*------------------------------------------------------------------*/
7394/*
7395 * Commit handler : called after a bunch of SET operations
7396 */
7397static int airo_config_commit(struct net_device *dev,
7398 struct iw_request_info *info, /* NULL */
7399 void *zwrq, /* NULL */
7400 char *extra) /* NULL */
7401{
faf3994a 7402 struct airo_info *local = dev->ml_priv;
1da177e4
LT
7403
7404 if (!test_bit (FLAG_COMMIT, &local->flags))
7405 return 0;
7406
7407 /* Some of the "SET" function may have modified some of the
7408 * parameters. It's now time to commit them in the card */
7409 disable_MAC(local, 1);
7410 if (test_bit (FLAG_RESET, &local->flags)) {
7411 APListRid APList_rid;
7412 SsidRid SSID_rid;
7413
7414 readAPListRid(local, &APList_rid);
7415 readSsidRid(local, &SSID_rid);
7416 if (test_bit(FLAG_MPI,&local->flags))
7417 setup_card(local, dev->dev_addr, 1 );
7418 else
7419 reset_airo_card(dev);
7420 disable_MAC(local, 1);
7421 writeSsidRid(local, &SSID_rid, 1);
7422 writeAPListRid(local, &APList_rid, 1);
7423 }
7424 if (down_interruptible(&local->sem))
7425 return -ERESTARTSYS;
7426 writeConfigRid(local, 0);
175ec1a1 7427 enable_MAC(local, 0);
1da177e4
LT
7428 if (test_bit (FLAG_RESET, &local->flags))
7429 airo_set_promisc(local);
7430 else
7431 up(&local->sem);
7432
7433 return 0;
7434}
7435
7436/*------------------------------------------------------------------*/
7437/*
7438 * Structures to export the Wireless Handlers
7439 */
7440
7441static const struct iw_priv_args airo_private_args[] = {
7442/*{ cmd, set_args, get_args, name } */
7443 { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
7444 IW_PRIV_TYPE_BYTE | 2047, "airoioctl" },
7445 { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
7446 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" },
7447};
7448
7449static const iw_handler airo_handler[] =
7450{
7451 (iw_handler) airo_config_commit, /* SIOCSIWCOMMIT */
7452 (iw_handler) airo_get_name, /* SIOCGIWNAME */
7453 (iw_handler) NULL, /* SIOCSIWNWID */
7454 (iw_handler) NULL, /* SIOCGIWNWID */
7455 (iw_handler) airo_set_freq, /* SIOCSIWFREQ */
7456 (iw_handler) airo_get_freq, /* SIOCGIWFREQ */
7457 (iw_handler) airo_set_mode, /* SIOCSIWMODE */
7458 (iw_handler) airo_get_mode, /* SIOCGIWMODE */
7459 (iw_handler) airo_set_sens, /* SIOCSIWSENS */
7460 (iw_handler) airo_get_sens, /* SIOCGIWSENS */
7461 (iw_handler) NULL, /* SIOCSIWRANGE */
7462 (iw_handler) airo_get_range, /* SIOCGIWRANGE */
7463 (iw_handler) NULL, /* SIOCSIWPRIV */
7464 (iw_handler) NULL, /* SIOCGIWPRIV */
7465 (iw_handler) NULL, /* SIOCSIWSTATS */
7466 (iw_handler) NULL, /* SIOCGIWSTATS */
7467 iw_handler_set_spy, /* SIOCSIWSPY */
7468 iw_handler_get_spy, /* SIOCGIWSPY */
7469 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
7470 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
7471 (iw_handler) airo_set_wap, /* SIOCSIWAP */
7472 (iw_handler) airo_get_wap, /* SIOCGIWAP */
7473 (iw_handler) NULL, /* -- hole -- */
7474 (iw_handler) airo_get_aplist, /* SIOCGIWAPLIST */
7475 (iw_handler) airo_set_scan, /* SIOCSIWSCAN */
7476 (iw_handler) airo_get_scan, /* SIOCGIWSCAN */
7477 (iw_handler) airo_set_essid, /* SIOCSIWESSID */
7478 (iw_handler) airo_get_essid, /* SIOCGIWESSID */
7479 (iw_handler) airo_set_nick, /* SIOCSIWNICKN */
7480 (iw_handler) airo_get_nick, /* SIOCGIWNICKN */
7481 (iw_handler) NULL, /* -- hole -- */
7482 (iw_handler) NULL, /* -- hole -- */
7483 (iw_handler) airo_set_rate, /* SIOCSIWRATE */
7484 (iw_handler) airo_get_rate, /* SIOCGIWRATE */
7485 (iw_handler) airo_set_rts, /* SIOCSIWRTS */
7486 (iw_handler) airo_get_rts, /* SIOCGIWRTS */
7487 (iw_handler) airo_set_frag, /* SIOCSIWFRAG */
7488 (iw_handler) airo_get_frag, /* SIOCGIWFRAG */
7489 (iw_handler) airo_set_txpow, /* SIOCSIWTXPOW */
7490 (iw_handler) airo_get_txpow, /* SIOCGIWTXPOW */
7491 (iw_handler) airo_set_retry, /* SIOCSIWRETRY */
7492 (iw_handler) airo_get_retry, /* SIOCGIWRETRY */
7493 (iw_handler) airo_set_encode, /* SIOCSIWENCODE */
7494 (iw_handler) airo_get_encode, /* SIOCGIWENCODE */
7495 (iw_handler) airo_set_power, /* SIOCSIWPOWER */
7496 (iw_handler) airo_get_power, /* SIOCGIWPOWER */
4be757dd
DW
7497 (iw_handler) NULL, /* -- hole -- */
7498 (iw_handler) NULL, /* -- hole -- */
7499 (iw_handler) NULL, /* SIOCSIWGENIE */
7500 (iw_handler) NULL, /* SIOCGIWGENIE */
7501 (iw_handler) airo_set_auth, /* SIOCSIWAUTH */
7502 (iw_handler) airo_get_auth, /* SIOCGIWAUTH */
7503 (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */
7504 (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */
7505 (iw_handler) NULL, /* SIOCSIWPMKSA */
1da177e4
LT
7506};
7507
7508/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
7509 * We want to force the use of the ioctl code, because those can't be
7510 * won't work the iw_handler code (because they simultaneously read
7511 * and write data and iw_handler can't do that).
7512 * Note that it's perfectly legal to read/write on a single ioctl command,
7513 * you just can't use iwpriv and need to force it via the ioctl handler.
7514 * Jean II */
7515static const iw_handler airo_private_handler[] =
7516{
7517 NULL, /* SIOCIWFIRSTPRIV */
7518};
7519
7520static const struct iw_handler_def airo_handler_def =
7521{
ff8ac609
DC
7522 .num_standard = ARRAY_SIZE(airo_handler),
7523 .num_private = ARRAY_SIZE(airo_private_handler),
7524 .num_private_args = ARRAY_SIZE(airo_private_args),
1da177e4
LT
7525 .standard = airo_handler,
7526 .private = airo_private_handler,
7527 .private_args = airo_private_args,
7528 .get_wireless_stats = airo_get_wireless_stats,
7529};
7530
1da177e4
LT
7531/*
7532 * This defines the configuration part of the Wireless Extensions
7533 * Note : irq and spinlock protection will occur in the subroutines
7534 *
7535 * TODO :
7536 * o Check input value more carefully and fill correct values in range
7537 * o Test and shakeout the bugs (if any)
7538 *
7539 * Jean II
7540 *
7541 * Javier Achirica did a great job of merging code from the unnamed CISCO
7542 * developer that added support for flashing the card.
7543 */
7544static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
7545{
7546 int rc = 0;
faf3994a 7547 struct airo_info *ai = dev->ml_priv;
1da177e4 7548
ca078bae 7549 if (ai->power.event)
1da177e4
LT
7550 return 0;
7551
7552 switch (cmd) {
7553#ifdef CISCO_EXT
7554 case AIROIDIFC:
7555#ifdef AIROOLDIDIFC
7556 case AIROOLDIDIFC:
7557#endif
7558 {
7559 int val = AIROMAGIC;
7560 aironet_ioctl com;
7561 if (copy_from_user(&com,rq->ifr_data,sizeof(com)))
7562 rc = -EFAULT;
7563 else if (copy_to_user(com.data,(char *)&val,sizeof(val)))
7564 rc = -EFAULT;
7565 }
7566 break;
7567
7568 case AIROIOCTL:
7569#ifdef AIROOLDIOCTL
7570 case AIROOLDIOCTL:
7571#endif
7572 /* Get the command struct and hand it off for evaluation by
7573 * the proper subfunction
7574 */
7575 {
7576 aironet_ioctl com;
7577 if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
7578 rc = -EFAULT;
7579 break;
7580 }
7581
7582 /* Separate R/W functions bracket legality here
7583 */
7584 if ( com.command == AIRORSWVERSION ) {
7585 if (copy_to_user(com.data, swversion, sizeof(swversion)))
7586 rc = -EFAULT;
7587 else
7588 rc = 0;
7589 }
7590 else if ( com.command <= AIRORRID)
7591 rc = readrids(dev,&com);
7592 else if ( com.command >= AIROPCAP && com.command <= (AIROPLEAPUSR+2) )
7593 rc = writerids(dev,&com);
7594 else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART )
7595 rc = flashcard(dev,&com);
7596 else
7597 rc = -EINVAL; /* Bad command in ioctl */
7598 }
7599 break;
7600#endif /* CISCO_EXT */
7601
7602 // All other calls are currently unsupported
7603 default:
7604 rc = -EOPNOTSUPP;
7605 }
7606 return rc;
7607}
7608
1da177e4
LT
7609/*
7610 * Get the Wireless stats out of the driver
7611 * Note : irq and spinlock protection will occur in the subroutines
7612 *
7613 * TODO :
7614 * o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
7615 *
7616 * Jean
7617 */
7618static void airo_read_wireless_stats(struct airo_info *local)
7619{
7620 StatusRid status_rid;
7621 StatsRid stats_rid;
7622 CapabilityRid cap_rid;
a23ace5f 7623 __le32 *vals = stats_rid.vals;
1da177e4
LT
7624
7625 /* Get stats out of the card */
3c304956 7626 clear_bit(JOB_WSTATS, &local->jobs);
ca078bae 7627 if (local->power.event) {
1da177e4
LT
7628 up(&local->sem);
7629 return;
7630 }
7631 readCapabilityRid(local, &cap_rid, 0);
7632 readStatusRid(local, &status_rid, 0);
7633 readStatsRid(local, &stats_rid, RID_STATS, 0);
7634 up(&local->sem);
7635
7636 /* The status */
329e2c00 7637 local->wstats.status = le16_to_cpu(status_rid.mode);
1da177e4 7638
41480af2
DW
7639 /* Signal quality and co */
7640 if (local->rssi) {
329e2c00
AV
7641 local->wstats.qual.level =
7642 airo_rssi_to_dbm(local->rssi,
7643 le16_to_cpu(status_rid.sigQuality));
41480af2 7644 /* normalizedSignalStrength appears to be a percentage */
329e2c00
AV
7645 local->wstats.qual.qual =
7646 le16_to_cpu(status_rid.normalizedSignalStrength);
41480af2 7647 } else {
329e2c00
AV
7648 local->wstats.qual.level =
7649 (le16_to_cpu(status_rid.normalizedSignalStrength) + 321) / 2;
41480af2
DW
7650 local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
7651 }
329e2c00 7652 if (le16_to_cpu(status_rid.len) >= 124) {
41480af2 7653 local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
ce6623c3 7654 local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1da177e4
LT
7655 } else {
7656 local->wstats.qual.noise = 0;
ce6623c3 7657 local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
1da177e4
LT
7658 }
7659
7660 /* Packets discarded in the wireless adapter due to wireless
7661 * specific problems */
a23ace5f
AV
7662 local->wstats.discard.nwid = le32_to_cpu(vals[56]) +
7663 le32_to_cpu(vals[57]) +
7664 le32_to_cpu(vals[58]); /* SSID Mismatch */
7665 local->wstats.discard.code = le32_to_cpu(vals[6]);/* RxWepErr */
7666 local->wstats.discard.fragment = le32_to_cpu(vals[30]);
7667 local->wstats.discard.retries = le32_to_cpu(vals[10]);
7668 local->wstats.discard.misc = le32_to_cpu(vals[1]) +
7669 le32_to_cpu(vals[32]);
7670 local->wstats.miss.beacon = le32_to_cpu(vals[34]);
1da177e4
LT
7671}
7672
ff1d2767 7673static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
1da177e4 7674{
faf3994a 7675 struct airo_info *local = dev->ml_priv;
1da177e4 7676
3c304956 7677 if (!test_bit(JOB_WSTATS, &local->jobs)) {
1da177e4
LT
7678 /* Get stats out of the card if available */
7679 if (down_trylock(&local->sem) != 0) {
3c304956 7680 set_bit(JOB_WSTATS, &local->jobs);
1da177e4
LT
7681 wake_up_interruptible(&local->thr_wait);
7682 } else
7683 airo_read_wireless_stats(local);
7684 }
7685
7686 return &local->wstats;
7687}
1da177e4
LT
7688
7689#ifdef CISCO_EXT
7690/*
7691 * This just translates from driver IOCTL codes to the command codes to
7692 * feed to the radio's host interface. Things can be added/deleted
7693 * as needed. This represents the READ side of control I/O to
7694 * the card
7695 */
7696static int readrids(struct net_device *dev, aironet_ioctl *comp) {
7697 unsigned short ridcode;
7698 unsigned char *iobuf;
7699 int len;
faf3994a 7700 struct airo_info *ai = dev->ml_priv;
1da177e4
LT
7701
7702 if (test_bit(FLAG_FLASHING, &ai->flags))
7703 return -EIO;
7704
7705 switch(comp->command)
7706 {
7707 case AIROGCAP: ridcode = RID_CAPABILITIES; break;
7708 case AIROGCFG: ridcode = RID_CONFIG;
7709 if (test_bit(FLAG_COMMIT, &ai->flags)) {
7710 disable_MAC (ai, 1);
7711 writeConfigRid (ai, 1);
175ec1a1 7712 enable_MAC(ai, 1);
1da177e4
LT
7713 }
7714 break;
7715 case AIROGSLIST: ridcode = RID_SSID; break;
7716 case AIROGVLIST: ridcode = RID_APLIST; break;
7717 case AIROGDRVNAM: ridcode = RID_DRVNAME; break;
7718 case AIROGEHTENC: ridcode = RID_ETHERENCAP; break;
7719 case AIROGWEPKTMP: ridcode = RID_WEP_TEMP;
7720 /* Only super-user can read WEP keys */
7721 if (!capable(CAP_NET_ADMIN))
7722 return -EPERM;
7723 break;
7724 case AIROGWEPKNV: ridcode = RID_WEP_PERM;
7725 /* Only super-user can read WEP keys */
7726 if (!capable(CAP_NET_ADMIN))
7727 return -EPERM;
7728 break;
7729 case AIROGSTAT: ridcode = RID_STATUS; break;
7730 case AIROGSTATSD32: ridcode = RID_STATSDELTA; break;
7731 case AIROGSTATSC32: ridcode = RID_STATS; break;
1da177e4
LT
7732 case AIROGMICSTATS:
7733 if (copy_to_user(comp->data, &ai->micstats,
7734 min((int)comp->len,(int)sizeof(ai->micstats))))
7735 return -EFAULT;
7736 return 0;
1da177e4
LT
7737 case AIRORRID: ridcode = comp->ridnum; break;
7738 default:
7739 return -EINVAL;
7740 break;
7741 }
7742
7743 if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7744 return -ENOMEM;
7745
7746 PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1);
7747 /* get the count of bytes in the rid docs say 1st 2 bytes is it.
7748 * then return it to the user
7749 * 9/22/2000 Honor user given length
7750 */
7751 len = comp->len;
7752
7753 if (copy_to_user(comp->data, iobuf, min(len, (int)RIDSIZE))) {
7754 kfree (iobuf);
7755 return -EFAULT;
7756 }
7757 kfree (iobuf);
7758 return 0;
7759}
7760
7761/*
7762 * Danger Will Robinson write the rids here
7763 */
7764
7765static int writerids(struct net_device *dev, aironet_ioctl *comp) {
faf3994a 7766 struct airo_info *ai = dev->ml_priv;
1da177e4 7767 int ridcode;
1da177e4 7768 int enabled;
1da177e4
LT
7769 static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
7770 unsigned char *iobuf;
7771
7772 /* Only super-user can write RIDs */
7773 if (!capable(CAP_NET_ADMIN))
7774 return -EPERM;
7775
7776 if (test_bit(FLAG_FLASHING, &ai->flags))
7777 return -EIO;
7778
7779 ridcode = 0;
7780 writer = do_writerid;
7781
7782 switch(comp->command)
7783 {
7784 case AIROPSIDS: ridcode = RID_SSID; break;
7785 case AIROPCAP: ridcode = RID_CAPABILITIES; break;
7786 case AIROPAPLIST: ridcode = RID_APLIST; break;
7787 case AIROPCFG: ai->config.len = 0;
7788 clear_bit(FLAG_COMMIT, &ai->flags);
7789 ridcode = RID_CONFIG; break;
7790 case AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break;
7791 case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break;
7792 case AIROPLEAPPWD: ridcode = RID_LEAPPASSWORD; break;
7793 case AIROPWEPKEY: ridcode = RID_WEP_TEMP; writer = PC4500_writerid;
7794 break;
7795 case AIROPLEAPUSR+1: ridcode = 0xFF2A; break;
7796 case AIROPLEAPUSR+2: ridcode = 0xFF2B; break;
7797
7798 /* this is not really a rid but a command given to the card
7799 * same with MAC off
7800 */
7801 case AIROPMACON:
175ec1a1 7802 if (enable_MAC(ai, 1) != 0)
1da177e4
LT
7803 return -EIO;
7804 return 0;
7805
7806 /*
7807 * Evidently this code in the airo driver does not get a symbol
7808 * as disable_MAC. it's probably so short the compiler does not gen one.
7809 */
7810 case AIROPMACOFF:
7811 disable_MAC(ai, 1);
7812 return 0;
7813
7814 /* This command merely clears the counts does not actually store any data
7815 * only reads rid. But as it changes the cards state, I put it in the
7816 * writerid routines.
7817 */
7818 case AIROPSTCLR:
7819 if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7820 return -ENOMEM;
7821
7822 PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
7823
1da177e4
LT
7824 enabled = ai->micstats.enabled;
7825 memset(&ai->micstats,0,sizeof(ai->micstats));
7826 ai->micstats.enabled = enabled;
1da177e4
LT
7827
7828 if (copy_to_user(comp->data, iobuf,
7829 min((int)comp->len, (int)RIDSIZE))) {
7830 kfree (iobuf);
7831 return -EFAULT;
7832 }
7833 kfree (iobuf);
7834 return 0;
7835
7836 default:
7837 return -EOPNOTSUPP; /* Blarg! */
7838 }
7839 if(comp->len > RIDSIZE)
7840 return -EINVAL;
7841
7842 if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7843 return -ENOMEM;
7844
7845 if (copy_from_user(iobuf,comp->data,comp->len)) {
7846 kfree (iobuf);
7847 return -EFAULT;
7848 }
7849
7850 if (comp->command == AIROPCFG) {
7851 ConfigRid *cfg = (ConfigRid *)iobuf;
7852
7853 if (test_bit(FLAG_MIC_CAPABLE, &ai->flags))
3eb9b41f 7854 cfg->opmode |= MODE_MIC;
1da177e4 7855
3eb9b41f 7856 if ((cfg->opmode & MODE_CFG_MASK) == MODE_STA_IBSS)
1da177e4
LT
7857 set_bit (FLAG_ADHOC, &ai->flags);
7858 else
7859 clear_bit (FLAG_ADHOC, &ai->flags);
7860 }
7861
7862 if((*writer)(ai, ridcode, iobuf,comp->len,1)) {
7863 kfree (iobuf);
7864 return -EIO;
7865 }
7866 kfree (iobuf);
7867 return 0;
7868}
7869
7870/*****************************************************************************
7871 * Ancillary flash / mod functions much black magic lurkes here *
7872 *****************************************************************************
7873 */
7874
7875/*
7876 * Flash command switch table
7877 */
7878
ff1d2767 7879static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
1da177e4 7880 int z;
1da177e4
LT
7881
7882 /* Only super-user can modify flash */
7883 if (!capable(CAP_NET_ADMIN))
7884 return -EPERM;
7885
7886 switch(comp->command)
7887 {
7888 case AIROFLSHRST:
faf3994a 7889 return cmdreset((struct airo_info *)dev->ml_priv);
1da177e4
LT
7890
7891 case AIROFLSHSTFL:
faf3994a
WC
7892 if (!AIRO_FLASH(dev) &&
7893 (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL)
1da177e4 7894 return -ENOMEM;
faf3994a 7895 return setflashmode((struct airo_info *)dev->ml_priv);
1da177e4
LT
7896
7897 case AIROFLSHGCHR: /* Get char from aux */
7898 if(comp->len != sizeof(int))
7899 return -EINVAL;
7900 if (copy_from_user(&z,comp->data,comp->len))
7901 return -EFAULT;
faf3994a 7902 return flashgchar((struct airo_info *)dev->ml_priv, z, 8000);
1da177e4
LT
7903
7904 case AIROFLSHPCHR: /* Send char to card. */
7905 if(comp->len != sizeof(int))
7906 return -EINVAL;
7907 if (copy_from_user(&z,comp->data,comp->len))
7908 return -EFAULT;
faf3994a 7909 return flashpchar((struct airo_info *)dev->ml_priv, z, 8000);
1da177e4
LT
7910
7911 case AIROFLPUTBUF: /* Send 32k to card */
faf3994a 7912 if (!AIRO_FLASH(dev))
1da177e4
LT
7913 return -ENOMEM;
7914 if(comp->len > FLASHSIZE)
7915 return -EINVAL;
faf3994a 7916 if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len))
1da177e4
LT
7917 return -EFAULT;
7918
faf3994a 7919 flashputbuf((struct airo_info *)dev->ml_priv);
1da177e4
LT
7920 return 0;
7921
7922 case AIRORESTART:
faf3994a 7923 if (flashrestart((struct airo_info *)dev->ml_priv, dev))
1da177e4
LT
7924 return -EIO;
7925 return 0;
7926 }
7927 return -EINVAL;
7928}
7929
7930#define FLASH_COMMAND 0x7e7e
7931
7932/*
7933 * STEP 1)
7934 * Disable MAC and do soft reset on
7935 * card.
7936 */
7937
ff1d2767 7938static int cmdreset(struct airo_info *ai) {
1da177e4
LT
7939 disable_MAC(ai, 1);
7940
7941 if(!waitbusy (ai)){
934d8bf1 7942 airo_print_info(ai->dev->name, "Waitbusy hang before RESET");
1da177e4
LT
7943 return -EBUSY;
7944 }
7945
7946 OUT4500(ai,COMMAND,CMD_SOFTRESET);
7947
7948 ssleep(1); /* WAS 600 12/7/00 */
7949
7950 if(!waitbusy (ai)){
934d8bf1 7951 airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET");
1da177e4
LT
7952 return -EBUSY;
7953 }
7954 return 0;
7955}
7956
7957/* STEP 2)
7958 * Put the card in legendary flash
7959 * mode
7960 */
7961
ff1d2767 7962static int setflashmode (struct airo_info *ai) {
1da177e4
LT
7963 set_bit (FLAG_FLASHING, &ai->flags);
7964
7965 OUT4500(ai, SWS0, FLASH_COMMAND);
7966 OUT4500(ai, SWS1, FLASH_COMMAND);
7967 if (probe) {
7968 OUT4500(ai, SWS0, FLASH_COMMAND);
7969 OUT4500(ai, COMMAND,0x10);
7970 } else {
7971 OUT4500(ai, SWS2, FLASH_COMMAND);
7972 OUT4500(ai, SWS3, FLASH_COMMAND);
7973 OUT4500(ai, COMMAND,0);
7974 }
7975 msleep(500); /* 500ms delay */
7976
7977 if(!waitbusy(ai)) {
7978 clear_bit (FLAG_FLASHING, &ai->flags);
934d8bf1 7979 airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode");
1da177e4
LT
7980 return -EIO;
7981 }
7982 return 0;
7983}
7984
7985/* Put character to SWS0 wait for dwelltime
7986 * x 50us for echo .
7987 */
7988
ff1d2767 7989static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
1da177e4
LT
7990 int echo;
7991 int waittime;
7992
7993 byte |= 0x8000;
7994
7995 if(dwelltime == 0 )
7996 dwelltime = 200;
7997
7998 waittime=dwelltime;
7999
8000 /* Wait for busy bit d15 to go false indicating buffer empty */
8001 while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) {
8002 udelay (50);
8003 waittime -= 50;
8004 }
8005
8006 /* timeout for busy clear wait */
8007 if(waittime <= 0 ){
934d8bf1 8008 airo_print_info(ai->dev->name, "flash putchar busywait timeout!");
1da177e4
LT
8009 return -EBUSY;
8010 }
8011
8012 /* Port is clear now write byte and wait for it to echo back */
8013 do {
8014 OUT4500(ai,SWS0,byte);
8015 udelay(50);
8016 dwelltime -= 50;
8017 echo = IN4500(ai,SWS1);
8018 } while (dwelltime >= 0 && echo != byte);
8019
8020 OUT4500(ai,SWS1,0);
8021
8022 return (echo == byte) ? 0 : -EIO;
8023}
8024
8025/*
8026 * Get a character from the card matching matchbyte
8027 * Step 3)
8028 */
ff1d2767 8029static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
1da177e4
LT
8030 int rchar;
8031 unsigned char rbyte=0;
8032
8033 do {
8034 rchar = IN4500(ai,SWS1);
8035
8036 if(dwelltime && !(0x8000 & rchar)){
8037 dwelltime -= 10;
8038 mdelay(10);
8039 continue;
8040 }
8041 rbyte = 0xff & rchar;
8042
8043 if( (rbyte == matchbyte) && (0x8000 & rchar) ){
8044 OUT4500(ai,SWS1,0);
8045 return 0;
8046 }
8047 if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
8048 break;
8049 OUT4500(ai,SWS1,0);
8050
8051 }while(dwelltime > 0);
8052 return -EIO;
8053}
8054
8055/*
8056 * Transfer 32k of firmware data from user buffer to our buffer and
8057 * send to the card
8058 */
8059
ff1d2767 8060static int flashputbuf(struct airo_info *ai){
1da177e4
LT
8061 int nwords;
8062
8063 /* Write stuff */
8064 if (test_bit(FLAG_MPI,&ai->flags))
8065 memcpy_toio(ai->pciaux + 0x8000, ai->flash, FLASHSIZE);
8066 else {
8067 OUT4500(ai,AUXPAGE,0x100);
8068 OUT4500(ai,AUXOFF,0);
8069
8070 for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
8071 OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
8072 }
8073 }
8074 OUT4500(ai,SWS0,0x8000);
8075
8076 return 0;
8077}
8078
8079/*
8080 *
8081 */
ff1d2767 8082static int flashrestart(struct airo_info *ai,struct net_device *dev){
1da177e4
LT
8083 int i,status;
8084
8085 ssleep(1); /* Added 12/7/00 */
8086 clear_bit (FLAG_FLASHING, &ai->flags);
8087 if (test_bit(FLAG_MPI, &ai->flags)) {
8088 status = mpi_init_descriptors(ai);
8089 if (status != SUCCESS)
8090 return status;
8091 }
8092 status = setup_card(ai, dev->dev_addr, 1);
8093
8094 if (!test_bit(FLAG_MPI,&ai->flags))
8095 for( i = 0; i < MAX_FIDS; i++ ) {
8096 ai->fids[i] = transmit_allocate
15db2763 8097 ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 );
1da177e4
LT
8098 }
8099
8100 ssleep(1); /* Added 12/7/00 */
8101 return status;
8102}
8103#endif /* CISCO_EXT */
8104
8105/*
8106 This program is free software; you can redistribute it and/or
8107 modify it under the terms of the GNU General Public License
8108 as published by the Free Software Foundation; either version 2
8109 of the License, or (at your option) any later version.
8110
8111 This program is distributed in the hope that it will be useful,
8112 but WITHOUT ANY WARRANTY; without even the implied warranty of
8113 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8114 GNU General Public License for more details.
8115
8116 In addition:
8117
8118 Redistribution and use in source and binary forms, with or without
8119 modification, are permitted provided that the following conditions
8120 are met:
8121
8122 1. Redistributions of source code must retain the above copyright
8123 notice, this list of conditions and the following disclaimer.
8124 2. Redistributions in binary form must reproduce the above copyright
8125 notice, this list of conditions and the following disclaimer in the
8126 documentation and/or other materials provided with the distribution.
8127 3. The name of the author may not be used to endorse or promote
8128 products derived from this software without specific prior written
8129 permission.
8130
8131 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8132 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8133 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8134 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
8135 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
8136 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
8137 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8138 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
8139 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
8140 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8141 POSSIBILITY OF SUCH DAMAGE.
8142*/
8143
8144module_init(airo_init_module);
8145module_exit(airo_cleanup_module);