File: /usr/src/linux/drivers/net/wireless/airo.c

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         and Jean Tourrilhes <jt@hpl.hp.com>.  Code was also integrated from
16         the Cisco Aironet driver for Linux.
17         
18     ======================================================================*/
19     
20     #include <linux/config.h>
21     #include <linux/version.h>
22     #include <asm/segment.h>
23     #include <linux/init.h>
24     
25     #include <linux/kernel.h>
26     #include <linux/module.h>
27     #include <linux/proc_fs.h>
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 <asm/io.h>
37     #include <asm/system.h>
38     #include <asm/bitops.h>
39     
40     #include <linux/netdevice.h>
41     #include <linux/etherdevice.h>
42     #include <linux/skbuff.h>
43     #include <linux/if_arp.h>
44     #include <linux/ioport.h>
45     #include <linux/config.h>
46     #include <linux/pci.h>
47     #include <asm/uaccess.h>
48     
49     #ifdef CONFIG_PCI
50     static struct pci_device_id card_ids[] = __devinitdata {
51     	{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
52     	{ 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
53     	{ 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
54     	{ 0x14b9, 0x0340, PCI_ANY_ID, PCI_ANY_ID, },
55     	{ 0x14b9, 0x0350, PCI_ANY_ID, PCI_ANY_ID, },
56     	{ 0, } 
57     };
58     MODULE_DEVICE_TABLE(pci, card_ids);
59     
60     static int airo_pci_probe(struct pci_dev *, const struct pci_device_id *);
61     static void airo_pci_remove(struct pci_dev *);
62     
63     static struct pci_driver airo_driver = {
64     	name:     "airo",
65     	id_table: card_ids,
66     	probe:    airo_pci_probe,
67     	remove:   airo_pci_remove,
68     };
69     #endif /* CONFIG_PCI */
70     
71     /* Include Wireless Extension definition and check version - Jean II */
72     #include <linux/wireless.h>
73     #define WIRELESS_SPY		// enable iwspy support
74     #if WIRELESS_EXT < 9
75     #warning "Wireless extension v9 or newer required - please upgrade your kernel"
76     #undef WIRELESS_EXT
77     #undef WIRELESS_SPY
78     #endif
79     #define CISCO_EXT		// enable Cisco extensions
80     
81     #ifdef CISCO_EXT
82     #include <linux/delay.h>
83     #endif
84     
85     /* As you can see this list is HUGH!
86        I really don't know what a lot of these counts are about, but they
87        are all here for completeness.  If the IGNLABEL macro is put in
88        infront of the label, that statistic will not be included in the list
89        of statistics in the /proc filesystem */
90     
91     #define IGNLABEL 0&(int)
92     static char *statsLabels[] = {
93     	"RxOverrun",
94     	IGNLABEL "RxPlcpCrcErr",
95     	IGNLABEL "RxPlcpFormatErr",
96     	IGNLABEL "RxPlcpLengthErr",
97     	"RxMacCrcErr",
98     	"RxMacCrcOk",
99     	"RxWepErr",
100     	"RxWepOk",
101     	"RetryLong",
102     	"RetryShort",
103     	"MaxRetries",
104     	"NoAck",
105     	"NoCts",
106     	"RxAck",
107     	"RxCts",
108     	"TxAck",
109     	"TxRts",
110     	"TxCts",
111     	"TxMc",
112     	"TxBc",
113     	"TxUcFrags",
114     	"TxUcPackets",
115     	"TxBeacon",
116     	"RxBeacon",
117     	"TxSinColl",
118     	"TxMulColl",
119     	"DefersNo",
120     	"DefersProt",
121     	"DefersEngy",
122     	"DupFram",
123     	"RxFragDisc",
124     	"TxAged",
125     	"RxAged",
126     	"LostSync-MaxRetry",
127     	"LostSync-MissedBeacons",
128     	"LostSync-ArlExceeded",
129     	"LostSync-Deauth",
130     	"LostSync-Disassoced",
131     	"LostSync-TsfTiming",
132     	"HostTxMc",
133     	"HostTxBc",
134     	"HostTxUc",
135     	"HostTxFail",
136     	"HostRxMc",
137     	"HostRxBc",
138     	"HostRxUc",
139     	"HostRxDiscard",
140     	IGNLABEL "HmacTxMc",
141     	IGNLABEL "HmacTxBc",
142     	IGNLABEL "HmacTxUc",
143     	IGNLABEL "HmacTxFail",
144     	IGNLABEL "HmacRxMc",
145     	IGNLABEL "HmacRxBc",
146     	IGNLABEL "HmacRxUc",
147     	IGNLABEL "HmacRxDiscard",
148     	IGNLABEL "HmacRxAccepted",
149     	"SsidMismatch",
150     	"ApMismatch",
151     	"RatesMismatch",
152     	"AuthReject",
153     	"AuthTimeout",
154     	"AssocReject",
155     	"AssocTimeout",
156     	IGNLABEL "ReasonOutsideTable",
157     	IGNLABEL "ReasonStatus1",
158     	IGNLABEL "ReasonStatus2",
159     	IGNLABEL "ReasonStatus3",
160     	IGNLABEL "ReasonStatus4",
161     	IGNLABEL "ReasonStatus5",
162     	IGNLABEL "ReasonStatus6",
163     	IGNLABEL "ReasonStatus7",
164     	IGNLABEL "ReasonStatus8",
165     	IGNLABEL "ReasonStatus9",
166     	IGNLABEL "ReasonStatus10",
167     	IGNLABEL "ReasonStatus11",
168     	IGNLABEL "ReasonStatus12",
169     	IGNLABEL "ReasonStatus13",
170     	IGNLABEL "ReasonStatus14",
171     	IGNLABEL "ReasonStatus15",
172     	IGNLABEL "ReasonStatus16",
173     	IGNLABEL "ReasonStatus17",
174     	IGNLABEL "ReasonStatus18",
175     	IGNLABEL "ReasonStatus19",
176     	"RxMan",
177     	"TxMan",
178     	"RxRefresh",
179     	"TxRefresh",
180     	"RxPoll",
181     	"TxPoll",
182     	"HostRetries",
183     	"LostSync-HostReq",
184     	"HostTxBytes",
185     	"HostRxBytes",
186     	"ElapsedUsec",
187     	"ElapsedSec",
188     	"LostSyncBetterAP",
189     	"PrivacyMismatch",
190     	"Jammed",
191     	"DiscRxNotWepped",
192     	"PhyEleMismatch",
193     	(char*)-1 };
194     #ifndef RUN_AT
195     #define RUN_AT(x) (jiffies+(x))
196     #endif
197     
198     
199     /* These variables are for insmod, since it seems that the rates
200        can only be set in setup_card.  Rates should be a comma separated
201        (no spaces) list of rates (up to 8). */
202     
203     static int rates[8];
204     static int basic_rate;
205     static char *ssids[3];
206     
207     static int io[4];
208     static int irq[4];
209     
210     static
211     int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at.
212     		       0 means no limit.  For old cards this was 4 */
213     
214     static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */
215     static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read
216     		    the bap, needed on some older cards and buses. */   
217     static int adhoc;
218     
219     static int proc_uid /* = 0 */;
220     
221     static int proc_gid /* = 0 */;
222     
223     static int airo_perm = 0555;
224     
225     static int proc_perm = 0644;
226     
227     MODULE_AUTHOR("Benjamin Reed");
228     MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
229                        cards.  Direct support for ISA/PCI cards and support \
230     		   for PCMCIA when used with airo_cs.");
231     MODULE_LICENSE("Dual BSD/GPL");
232     MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340");
233     MODULE_PARM(io,"1-4i");
234     MODULE_PARM(irq,"1-4i");
235     MODULE_PARM(basic_rate,"i");
236     MODULE_PARM(rates,"1-8i");
237     MODULE_PARM(ssids,"1-3s");
238     MODULE_PARM(auto_wep,"i");
239     MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \
240     the authentication options until an association is made.  The value of \
241     auto_wep is number of the wep keys to check.  A value of 2 will try using \
242     the key at index 0 and index 1.");
243     MODULE_PARM(aux_bap,"i");
244     MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \
245     than seems to work better for older cards with some older buses.  Before \
246     switching it checks that the switch is needed.");
247     MODULE_PARM(maxencrypt, "i");
248     MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \
249     encryption.  Units are in 512kbs.  Zero (default) means there is no limit. \
250     Older cards used to be limited to 2mbs (4).");
251     MODULE_PARM(adhoc, "i");
252     MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode.");
253     
254     MODULE_PARM(proc_uid, "i");
255     MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to.");
256     MODULE_PARM(proc_gid, "i");
257     MODULE_PARM_DESC(proc_gid, "The gid that the /proc files will belong to.");
258     MODULE_PARM(airo_perm, "i");
259     MODULE_PARM_DESC(airo_perm, "The permission bits of /proc/[driver/]aironet.");
260     MODULE_PARM(proc_perm, "i");
261     MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc");
262     
263     #include <asm/uaccess.h>
264     
265     /* This is a kind of sloppy hack to get this information to OUT4500 and
266        IN4500.  I would be extremely interested in the situation where this
267        doesnt work though!!! */
268     static int do8bitIO = 0;
269     
270     /* Return codes */
271     #define SUCCESS 0
272     #define ERROR -1
273     #define NO_PACKET -2
274     
275     /* Commands */
276     #define NOP 0x0010
277     #define MAC_ENABLE 0x0001
278     #define MAC_DISABLE 0x0002
279     #define CMD_LOSE_SYNC 0x0003 /* Not sure what this does... */
280     #define CMD_ACCESS 0x0021
281     #define CMD_ALLOCATETX 0x000a
282     #define CMD_TRANSMIT 0x000b
283     #define HOSTSLEEP 0x85
284     #define CMD_SETMODE 0x0009
285     #define CMD_ENABLEAUX 0x0111
286     #define CMD_SOFTRESET 0x0004
287     #define CMD_LISTBSS 0x0103
288     
289     /* Registers */
290     #define COMMAND 0x00
291     #define PARAM0 0x02
292     #define PARAM1 0x04
293     #define PARAM2 0x06
294     #define STATUS 0x08
295     #define RESP0 0x0a
296     #define RESP1 0x0c
297     #define RESP2 0x0e
298     #define LINKSTAT 0x10
299     #define SELECT0 0x18
300     #define OFFSET0 0x1c
301     #define RXFID 0x20
302     #define TXALLOCFID 0x22
303     #define TXCOMPLFID 0x24
304     #define DATA0 0x36
305     #define EVSTAT 0x30
306     #define EVINTEN 0x32
307     #define EVACK 0x34
308     #define SWS0 0x28
309     #define SWS1 0x2a
310     #define SWS2 0x2c
311     #define SWS3 0x2e
312     #define AUXPAGE 0x3A
313     #define AUXOFF 0x3C
314     #define AUXDATA 0x3E
315     
316     /* BAP selectors */
317     #define BAP0 0 // Used for receiving packets
318     #define BAP1 2 // Used for xmiting packets and working with RIDS
319     
320     /* Flags */
321     #define COMMAND_BUSY 0x8000
322     
323     #define BAP_BUSY 0x8000
324     #define BAP_ERR 0x4000
325     #define BAP_DONE 0x2000
326     
327     #define PROMISC 0xffff
328     #define NOPROMISC 0x0000
329     
330     #define EV_CMD 0x10
331     #define EV_CLEARCOMMANDBUSY 0x4000
332     #define EV_RX 0x01
333     #define EV_TX 0x02
334     #define EV_TXEXC 0x04
335     #define EV_ALLOC 0x08
336     #define EV_LINK 0x80
337     #define EV_AWAKE 0x100
338     #define EV_UNKNOWN 0x800
339     #define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX)
340     #define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
341     
342     /* The RIDs */
343     #define RID_CAPABILITIES 0xFF00
344     #define RID_CONFIG     0xFF10
345     #define RID_SSID       0xFF11
346     #define RID_APLIST     0xFF12
347     #define RID_DRVNAME    0xFF13
348     #define RID_ETHERENCAP 0xFF14
349     #define RID_WEP_TEMP   0xFF15
350     #define RID_WEP_PERM   0xFF16
351     #define RID_MODULATION 0xFF17
352     #define RID_ACTUALCONFIG 0xFF20 /*readonly*/
353     #define RID_LEAPUSERNAME 0xFF23
354     #define RID_LEAPPASSWORD 0xFF24
355     #define RID_STATUS     0xFF50
356     #define RID_STATS      0xFF68
357     #define RID_STATSDELTA 0xFF69
358     #define RID_STATSDELTACLEAR 0xFF6A
359     #define RID_BSSLISTFIRST 0xFF72
360     #define RID_BSSLISTNEXT  0xFF73
361     
362     typedef struct {
363     	u16 cmd;
364     	u16 parm0;
365     	u16 parm1;
366     	u16 parm2;
367     } Cmd;
368     
369     typedef struct {
370     	u16 status;
371     	u16 rsp0;
372     	u16 rsp1;
373     	u16 rsp2;
374     } Resp;
375     
376     /*
377      * Rids and endian-ness:  The Rids will always be in cpu endian, since
378      * this all the patches from the big-endian guys end up doing that.
379      * so all rid access should use the read/writeXXXRid routines.
380      */
381     
382     /* This is redundant for x86 archs, but it seems necessary for ARM */
383     #pragma pack(1)
384     
385     /* This structure came from an email sent to me from an engineer at
386        aironet for inclusion into this driver */
387     typedef struct {
388     	u16 len;
389     	u16 kindex;
390     	u8 mac[6];
391     	u16 klen;
392     	u8 key[16];
393     } WepKeyRid;
394     
395     /* These structures are from the Aironet's PC4500 Developers Manual */
396     typedef struct {
397     	u16 len;
398     	u8 ssid[32];
399     } Ssid;
400     
401     typedef struct {
402     	u16 len;
403     	Ssid ssids[3];
404     } SsidRid;
405     
406     typedef struct {
407             u16 len;
408             u16 modulation;
409     #define MOD_DEFAULT 0
410     #define MOD_CCK 1
411     #define MOD_MOK 2
412     } ModulationRid;
413     
414     typedef struct {
415     	u16 len; /* sizeof(ConfigRid) */
416     	u16 opmode; /* operating mode */
417     #define MODE_STA_IBSS 0
418     #define MODE_STA_ESS 1
419     #define MODE_AP 2
420     #define MODE_AP_RPTR 3
421     #define MODE_ETHERNET_HOST (0<<8) /* rx payloads converted */
422     #define MODE_LLC_HOST (1<<8) /* rx payloads left as is */
423     #define MODE_AIRONET_EXTEND (1<<9) /* enable Aironet extenstions */
424     #define MODE_AP_INTERFACE (1<<10) /* enable ap interface extensions */
425     #define MODE_ANTENNA_ALIGN (1<<11) /* enable antenna alignment */
426     #define MODE_ETHER_LLC (1<<12) /* enable ethernet LLC */
427     #define MODE_LEAF_NODE (1<<13) /* enable leaf node bridge */
428     #define MODE_CF_POLLABLE (1<<14) /* enable CF pollable */
429     	u16 rmode; /* receive mode */
430     #define RXMODE_BC_MC_ADDR 0
431     #define RXMODE_BC_ADDR 1 /* ignore multicasts */
432     #define RXMODE_ADDR 2 /* ignore multicast and broadcast */
433     #define RXMODE_RFMON 3 /* wireless monitor mode */
434     #define RXMODE_RFMON_ANYBSS 4
435     #define RXMODE_LANMON 5 /* lan style monitor -- data packets only */
436     #define RXMODE_DISABLE_802_3_HEADER (1<<8) /* disables 802.3 header on rx */
437     #define RXMODE_NORMALIZED_RSSI (1<<9) /* return normalized RSSI */
438     	u16 fragThresh;
439     	u16 rtsThres;
440     	u8 macAddr[6];
441     	u8 rates[8];
442     	u16 shortRetryLimit;
443     	u16 longRetryLimit;
444     	u16 txLifetime; /* in kusec */
445     	u16 rxLifetime; /* in kusec */
446     	u16 stationary;
447     	u16 ordering;
448     	u16 u16deviceType; /* for overriding device type */
449     	u16 cfpRate;
450     	u16 cfpDuration;
451     	u16 _reserved1[3];
452     	/*---------- Scanning/Associating ----------*/
453     	u16 scanMode;
454     #define SCANMODE_ACTIVE 0
455     #define SCANMODE_PASSIVE 1
456     #define SCANMODE_AIROSCAN 2
457     	u16 probeDelay; /* in kusec */
458     	u16 probeEnergyTimeout; /* in kusec */
459             u16 probeResponseTimeout;
460     	u16 beaconListenTimeout;
461     	u16 joinNetTimeout;
462     	u16 authTimeout;
463     	u16 authType;
464     #define AUTH_OPEN 0x1
465     #define AUTH_ENCRYPT 0x101
466     #define AUTH_SHAREDKEY 0x102
467     #define AUTH_ALLOW_UNENCRYPTED 0x200
468     	u16 associationTimeout;
469     	u16 specifiedApTimeout;
470     	u16 offlineScanInterval;
471     	u16 offlineScanDuration;
472     	u16 linkLossDelay;
473     	u16 maxBeaconLostTime;
474     	u16 refreshInterval;
475     #define DISABLE_REFRESH 0xFFFF
476     	u16 _reserved1a[1];
477     	/*---------- Power save operation ----------*/
478     	u16 powerSaveMode;
479     #define POWERSAVE_CAM 0
480     #define POWERSAVE_PSP 1
481     #define POWERSAVE_PSPCAM 2
482     	u16 sleepForDtims;
483     	u16 listenInterval;
484     	u16 fastListenInterval;
485     	u16 listenDecay;
486     	u16 fastListenDelay;
487     	u16 _reserved2[2];
488     	/*---------- Ap/Ibss config items ----------*/
489     	u16 beaconPeriod;
490     	u16 atimDuration;
491     	u16 hopPeriod;
492     	u16 channelSet;
493     	u16 channel;
494     	u16 dtimPeriod;
495     	u16 bridgeDistance;
496     	u16 radioID;
497     	/*---------- Radio configuration ----------*/
498     	u16 radioType;
499     #define RADIOTYPE_DEFAULT 0
500     #define RADIOTYPE_802_11 1
501     #define RADIOTYPE_LEGACY 2
502     	u8 rxDiversity;
503     	u8 txDiversity;
504     	u16 txPower;
505     #define TXPOWER_DEFAULT 0
506     	u16 rssiThreshold;
507     #define RSSI_DEFAULT 0
508             u16 modulation;
509     #define PREAMBLE_AUTO 0
510     #define PREAMBLE_LONG 1
511     #define PREAMBLE_SHORT 2
512     	u16 preamble;
513     	u16 homeProduct;
514     	u16 radioSpecific;
515     	/*---------- Aironet Extensions ----------*/
516     	u8 nodeName[16];
517     	u16 arlThreshold;
518     	u16 arlDecay;
519     	u16 arlDelay;
520     	u16 _reserved4[1];
521     	/*---------- Aironet Extensions ----------*/
522     	u16 magicAction;
523     #define MAGIC_ACTION_STSCHG 1
524     #define MACIC_ACTION_RESUME 2
525     #define MAGIC_IGNORE_MCAST (1<<8)
526     #define MAGIC_IGNORE_BCAST (1<<9)
527     #define MAGIC_SWITCH_TO_PSP (0<<10)
528     #define MAGIC_STAY_IN_CAM (1<<10)
529     	u16 magicControl;
530     	u16 autoWake;
531     } ConfigRid;
532     
533     typedef struct {
534     	u16 len;
535     	u8 mac[6];
536     	u16 mode;
537     	u16 errorCode;
538     	u16 sigQuality;
539     	u16 SSIDlen;
540     	char SSID[32];
541     	char apName[16];
542     	char bssid[4][6];
543     	u16 beaconPeriod;
544     	u16 dimPeriod;
545     	u16 atimDuration;
546     	u16 hopPeriod;
547     	u16 channelSet;
548     	u16 channel;
549     	u16 hopsToBackbone;
550     	u16 apTotalLoad;
551     	u16 generatedLoad;
552     	u16 accumulatedArl;
553     	u16 signalQuality;
554     	u16 currentXmitRate;
555     	u16 apDevExtensions;
556     	u16 normalizedSignalStrength;
557     	u16 _reserved[10];
558     } StatusRid;
559     
560     typedef struct {
561     	u16 len;
562     	u16 spacer;
563     	u32 vals[100];
564     } StatsRid;
565     	
566     
567     typedef struct {
568     	u16 len;
569     	u8 ap[4][6];
570     } APListRid;
571     
572     typedef struct {
573     	u16 len;
574     	char oui[3];
575     	char zero;
576     	u16 prodNum;
577     	char manName[32];
578     	char prodName[16];
579     	char prodVer[8];
580     	char factoryAddr[6];
581     	char aironetAddr[6];
582     	u16 radioType;
583     	u16 country;
584     	char callid[6];
585     	char supportedRates[8];
586     	char rxDiversity;
587     	char txDiversity;
588     	u16 txPowerLevels[8];
589     	u16 hardVer;
590     	u16 hardCap;
591     	u16 tempRange;
592     	u16 softVer;
593     	u16 softSubVer;
594     	u16 interfaceVer;
595     	u16 softCap;
596     	u16 bootBlockVer;
597     	u16 requiredHard;
598     } CapabilityRid;
599     
600     typedef struct {
601       u16 len;
602       u16 index; /* First is 0 and 0xffff means end of list */
603     #define RADIO_FH 1 /* Frequency hopping radio type */
604     #define RADIO_DS 2 /* Direct sequence radio type */
605     #define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */
606       u16 radioType; 
607       u8 bssid[6]; /* Mac address of the BSS */
608       u8 zero;
609       u8 ssidLen;
610       u8 ssid[32];
611       u16 rssi;
612     #define CAP_ESS (1<<0)
613     #define CAP_IBSS (1<<1)
614     #define CAP_PRIVACY (1<<4)
615     #define CAP_SHORTHDR (1<<5)
616       u16 cap;
617       u16 beaconInterval;
618       u8 rates[8]; /* Same as rates for config rid */
619       struct { /* For frequency hopping only */
620         u16 dwell;
621         u8 hopSet;
622         u8 hopPattern;
623         u8 hopIndex;
624         u8 fill;
625       } fh;
626       u16 dsChannel;
627       u16 atimWindow;
628     } BSSListRid;
629     
630     #pragma pack()
631     
632     #define TXCTL_TXOK (1<<1) /* report if tx is ok */
633     #define TXCTL_TXEX (1<<2) /* report if tx fails */
634     #define TXCTL_802_3 (0<<3) /* 802.3 packet */
635     #define TXCTL_802_11 (1<<3) /* 802.11 mac packet */
636     #define TXCTL_ETHERNET (0<<4) /* payload has ethertype */
637     #define TXCTL_LLC (1<<4) /* payload is llc */
638     #define TXCTL_RELEASE (0<<5) /* release after completion */
639     #define TXCTL_NORELEASE (1<<5) /* on completion returns to host */
640     
641     #define BUSY_FID 0x10000
642     
643     #ifdef CISCO_EXT
644     #define AIROMAGIC	0xa55a
645     #define AIROIOCTL	SIOCDEVPRIVATE
646     #define AIROIDIFC 	AIROIOCTL + 1
647     
648     /* Ioctl constants to be used in airo_ioctl.command */
649     
650     #define	AIROGCAP  		0	// Capability rid
651     #define AIROGCFG		1       // USED A LOT 
652     #define AIROGSLIST		2	// System ID list 
653     #define AIROGVLIST		3       // List of specified AP's
654     #define AIROGDRVNAM		4	//  NOTUSED
655     #define AIROGEHTENC		5	// NOTUSED
656     #define AIROGWEPKTMP		6
657     #define AIROGWEPKNV		7
658     #define AIROGSTAT		8
659     #define AIROGSTATSC32		9
660     #define AIROGSTATSD32		10
661     
662     /* Leave gap of 40 commands after AIROGSTATSD32 for future */
663     
664     #define AIROPCAP               	AIROGSTATSD32 + 40
665     #define AIROPVLIST              AIROPCAP      + 1
666     #define AIROPSLIST		AIROPVLIST    + 1
667     #define AIROPCFG		AIROPSLIST    + 1
668     #define AIROPSIDS		AIROPCFG      + 1
669     #define AIROPAPLIST		AIROPSIDS     + 1
670     #define AIROPMACON		AIROPAPLIST   + 1	/* Enable mac  */
671     #define AIROPMACOFF		AIROPMACON    + 1 	/* Disable mac */
672     #define AIROPSTCLR		AIROPMACOFF   + 1
673     #define AIROPWEPKEY		AIROPSTCLR    + 1
674     #define AIROPWEPKEYNV		AIROPWEPKEY   + 1
675     #define AIROPLEAPPWD            AIROPWEPKEYNV + 1
676     #define AIROPLEAPUSR            AIROPLEAPPWD  + 1
677     
678     /* Flash codes */
679     
680     #define AIROFLSHRST	       AIROPWEPKEYNV  + 40
681     #define AIROFLSHGCHR           AIROFLSHRST    + 1
682     #define AIROFLSHSTFL           AIROFLSHGCHR   + 1
683     #define AIROFLSHPCHR           AIROFLSHSTFL   + 1
684     #define AIROFLPUTBUF           AIROFLSHPCHR   + 1
685     #define AIRORESTART            AIROFLPUTBUF   + 1
686     
687     #define FLASHSIZE	32768
688     
689     typedef struct aironet_ioctl {
690     	unsigned short command;	// What to do
691     	unsigned short len;		// Len of data
692     	unsigned char *data;		// d-data
693     } aironet_ioctl;
694     #endif /* CISCO_EXT */
695     
696     #ifdef WIRELESS_EXT
697     // Frequency list (map channels to frequencies)
698     const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
699     				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
700     
701     // A few details needed for WEP (Wireless Equivalent Privacy)
702     #define MAX_KEY_SIZE 13			// 128 (?) bits
703     #define MIN_KEY_SIZE  5			// 40 bits RC4 - WEP
704     typedef struct wep_key_t {
705     	u16	len;
706     	u8	key[16];	/* 40-bit and 104-bit keys */
707     } wep_key_t;
708     #endif /* WIRELESS_EXT */
709     
710     static const char version[] = "airo.c 0.3 (Ben Reed & Javier Achirica)";
711     
712     struct airo_info;
713     
714     static int get_dec_u16( char *buffer, int *start, int limit );
715     static void OUT4500( struct airo_info *, u16 register, u16 value );
716     static unsigned short IN4500( struct airo_info *, u16 register );
717     static u16 setup_card(struct airo_info*, u8 *mac, ConfigRid *);
718     static void enable_interrupts(struct airo_info*);
719     static void disable_interrupts(struct airo_info*);
720     static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
721     static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
722     static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, 
723     			int whichbap);
724     static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, 
725     			 int whichbap);
726     static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen,
727     		     int whichbap);
728     static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);
729     static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len);
730     static int PC4500_writerid(struct airo_info*, u16 rid, const void
731     			   *pBuf, int len);
732     static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, 
733     			int len );
734     static u16 transmit_allocate(struct airo_info*, int lenPayload);
735     static int transmit_802_3_packet(struct airo_info*, u16 TxFid, char
736     				 *pPacket, int len);
737     
738     static void airo_interrupt( int irq, void* dev_id, struct pt_regs
739     			    *regs);
740     static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
741     #ifdef WIRELESS_EXT
742     struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
743     #endif /* WIRELESS_EXT */
744     #ifdef CISCO_EXT
745     static int readrids(struct net_device *dev, aironet_ioctl *comp);
746     static int writerids(struct net_device *dev, aironet_ioctl *comp);
747     int flashcard(struct net_device *dev, aironet_ioctl *comp);
748     #endif /* CISCO_EXT */
749     
750     struct airo_info {
751     	struct net_device_stats	stats;
752     	int open;
753     	struct net_device             *dev;
754     	/* Note, we can have MAX_FIDS outstanding.  FIDs are 16-bits, so we
755     	   use the high bit to mark wether it is in use. */
756     #define MAX_FIDS 6
757     	int                           fids[MAX_FIDS];
758     	int registered;
759     	ConfigRid config;
760     	u16 authtype; // Used with auto_wep 
761     	char keyindex; // Used with auto wep
762     	char defindex; // Used with auto wep
763     	struct timer_list timer;
764     	struct proc_dir_entry *proc_entry;
765     	struct airo_info *next;
766             spinlock_t bap0_lock;
767             spinlock_t bap1_lock;
768             spinlock_t aux_lock;
769             spinlock_t cmd_lock;
770             int flags;
771     #define FLAG_PROMISC   IFF_PROMISC
772     #define FLAG_RADIO_OFF 0x02
773     	int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, 
774     			int whichbap);
775     	int (*header_parse)(struct sk_buff*, unsigned char *);
776     	unsigned short *flash;
777     #ifdef WIRELESS_EXT
778     	int			need_commit;	// Need to set config
779     	struct iw_statistics	wstats;		// wireless stats
780     #ifdef WIRELESS_SPY
781     	int			spy_number;
782     	u_char			spy_address[IW_MAX_SPY][6];
783     	struct iw_quality	spy_stat[IW_MAX_SPY];
784     #endif /* WIRELESS_SPY */
785     #endif /* WIRELESS_EXT */
786     };
787     
788     static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, 
789     			   int whichbap) {
790     	return ai->bap_read(ai, pu16Dst, bytelen, whichbap);
791     }
792     
793     static int setup_proc_entry( struct net_device *dev,
794     			     struct airo_info *apriv );
795     static int takedown_proc_entry( struct net_device *dev,
796     				struct airo_info *apriv );
797     
798     static int readBSSListRid(struct airo_info *ai, int first,
799     		      BSSListRid *list) {
800     	int rc;
801     			Cmd cmd;
802     			Resp rsp;
803     
804     	if (first == 1) {
805     			memset(&cmd, 0, sizeof(cmd));
806     			cmd.cmd=CMD_LISTBSS;
807     			issuecommand(ai, &cmd, &rsp);
808     			/* Let the command take effect */
809     			set_current_state (TASK_INTERRUPTIBLE);
810     			schedule_timeout (3*HZ);
811     		}
812     	rc = PC4500_readrid(ai, 
813     		            first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
814     			    list, sizeof(*list));
815     
816     	list->len = le16_to_cpu(list->len);
817     	list->index = le16_to_cpu(list->index);
818     	list->radioType = le16_to_cpu(list->radioType);
819     	list->cap = le16_to_cpu(list->cap);
820     	list->beaconInterval = le16_to_cpu(list->beaconInterval);
821     	list->fh.dwell = le16_to_cpu(list->fh.dwell);
822     	list->dsChannel = le16_to_cpu(list->dsChannel);
823     	list->atimWindow = le16_to_cpu(list->atimWindow);
824     	return rc;
825     }
826     
827     static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) {
828     	int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, 
829     				wkr, sizeof(*wkr));
830     	
831     	wkr->len = le16_to_cpu(wkr->len);
832     	wkr->kindex = le16_to_cpu(wkr->kindex);
833     	wkr->klen = le16_to_cpu(wkr->klen);
834     	return rc;
835     }
836     /* In the writeXXXRid routines we copy the rids so that we don't screwup
837      * the originals when we endian them... */
838     static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) {
839     	int rc;
840     	WepKeyRid wkr = *pwkr;
841     
842     	wkr.len = cpu_to_le16(wkr.len);
843     	wkr.kindex = cpu_to_le16(wkr.kindex);
844     	wkr.klen = cpu_to_le16(wkr.klen);
845     	rc = do_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr));
846     	if (rc!=SUCCESS) printk(KERN_ERR "airo:  WEP_TEMP set %x\n", rc); 
847     	if (perm) {
848     		rc = do_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr));
849     		if (rc!=SUCCESS) {
850     			printk(KERN_ERR "airo:  WEP_PERM set %x\n", rc);
851     		}
852     	}
853     	return rc;
854     }
855     
856     static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {
857     	int i;
858     	int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr));
859     
860     	ssidr->len = le16_to_cpu(ssidr->len);
861     	for(i = 0; i < 3; i++) {
862     		ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len);
863     	}
864     	return rc;
865     }
866     static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr) {
867     	int rc;
868     	int i;
869     	SsidRid ssidr = *pssidr;
870     
871     	ssidr.len = cpu_to_le16(ssidr.len);
872     	for(i = 0; i < 3; i++) {
873     		ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);
874     	}
875     	rc = do_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr));
876     	return rc;
877     }
878     static int readConfigRid(struct airo_info*ai, ConfigRid *cfgr) {
879     	int rc = PC4500_readrid(ai, RID_ACTUALCONFIG, cfgr, sizeof(*cfgr));
880     	u16 *s;
881     	
882     	for(s = &cfgr->len; s <= &cfgr->rtsThres; s++) *s = le16_to_cpu(*s);
883     
884     	for(s = &cfgr->shortRetryLimit; s <= &cfgr->radioType; s++)
885     		*s = le16_to_cpu(*s);
886     
887     	for(s = &cfgr->txPower; s <= &cfgr->radioSpecific; s++)
888     		*s = le16_to_cpu(*s);
889     	
890     	for(s = &cfgr->arlThreshold; s <= &cfgr->autoWake; s++)
891     		*s = le16_to_cpu(*s);
892     	
893     	return rc;
894     }
895     static int writeConfigRid(struct airo_info*ai, ConfigRid *pcfgr) {
896     	u16 *s;
897     	ConfigRid cfgr = *pcfgr;
898     	
899     	for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);
900     
901     	for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++)
902     		*s = cpu_to_le16(*s);
903     
904     	for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++)
905     		*s = cpu_to_le16(*s);
906     	
907     	for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++)
908     		*s = cpu_to_le16(*s);
909     	
910     	return do_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr));
911     }
912     static int readStatusRid(struct airo_info*ai, StatusRid *statr) {
913     	int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr));
914     	u16 *s;
915     
916     	statr->len = le16_to_cpu(statr->len);
917     	for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);
918     
919     	for(s = &statr->beaconPeriod; s <= &statr->_reserved[9]; s++)
920     		*s = le16_to_cpu(*s);
921     
922     	return rc;
923     }
924     static int readAPListRid(struct airo_info*ai, APListRid *aplr) {
925     	int rc =  PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr));
926     	aplr->len = le16_to_cpu(aplr->len);
927     	return rc;
928     }
929     static int writeAPListRid(struct airo_info*ai, APListRid *aplr) {
930     	int rc;
931     	aplr->len = cpu_to_le16(aplr->len);
932     	rc = do_writerid(ai, RID_APLIST, aplr, sizeof(*aplr));
933     	return rc;
934     }
935     static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) {
936     	int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr));
937     	u16 *s;
938     	
939     	capr->len = le16_to_cpu(capr->len);
940     	capr->prodNum = le16_to_cpu(capr->prodNum);
941     	capr->radioType = le16_to_cpu(capr->radioType);
942     	capr->country = le16_to_cpu(capr->country);
943     	for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)
944     		*s = le16_to_cpu(*s);
945     	return rc;
946     }
947     static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid) {
948     	int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr));
949     	u32 *i;
950     
951     	sr->len = le16_to_cpu(sr->len);
952     	for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i);
953     	return rc;
954     }
955     
956     static int airo_open(struct net_device *dev) {
957     	struct airo_info *info = dev->priv;
958     
959     	enable_interrupts(info);
960     
961     	netif_start_queue(dev);
962     	return 0;
963     }
964     
965     static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
966     	s16 len;
967     	s16 retval = 0;
968     	u16 status;
969     	u32 flags;
970     	s8 *buffer;
971     	int i,j;
972     	struct airo_info *priv = (struct airo_info*)dev->priv;
973     	u32 *fids = priv->fids;
974     	
975     	if ( skb == NULL ) {
976     		printk( KERN_ERR "airo:  skb == NULL!!!\n" );
977     		return 0;
978     	}
979     	
980     	/* Find a vacant FID */
981     	spin_lock_irqsave(&priv->bap1_lock, flags);
982     	for( j = 0, i = -1; j < MAX_FIDS; j++ ) {
983     		if ( !( fids[j] & 0xffff0000 ) ) {
984     			if ( i == -1 ) i = j;
985     			else break;
986     		}
987     	}
988     	if ( j == MAX_FIDS ) netif_stop_queue(dev);
989     	if ( i == -1 ) {
990     		retval = -EBUSY;
991     		goto tx_done;
992     	}
993     	
994     	len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/
995     	buffer = skb->data;
996     	status = transmit_802_3_packet( priv, 
997     					fids[i],
998     					skb->data, len );
999     	
1000     	if ( status == SUCCESS ) {
1001                     /* Mark fid as used & save length for later */
1002     		fids[i] |= (len << 16); 
1003     		dev->trans_start = jiffies;
1004     	} else {
1005     		priv->stats.tx_errors++;
1006     	}
1007      tx_done:
1008     	spin_unlock_irqrestore(&priv->bap1_lock, flags);
1009     	dev_kfree_skb(skb);
1010     	return 0;
1011     }
1012     
1013     static struct net_device_stats *airo_get_stats(struct net_device *dev) {
1014     	return &(((struct airo_info*)dev->priv)->stats);
1015     }
1016     
1017     static int enable_MAC( struct airo_info *ai, Resp *rsp );
1018     static void disable_MAC(struct airo_info *ai);
1019     
1020     static void airo_set_multicast_list(struct net_device *dev) {
1021     	struct airo_info *ai = (struct airo_info*)dev->priv;
1022     	Cmd cmd;
1023     	Resp rsp;
1024     	  
1025     	/* For some reason this command takes a lot of time (~20 ms) and it's
1026     	 * run in an interrupt handler, so we'd better be sure we needed it
1027     	 * before executing it.
1028     	 */
1029     	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
1030     		memset(&cmd, 0, sizeof(cmd));
1031     		cmd.cmd=CMD_SETMODE;
1032     		cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
1033     		issuecommand(ai, &cmd, &rsp);
1034     		ai->flags^=IFF_PROMISC;
1035     	}
1036     
1037     	if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
1038     		/* Turn on multicast.  (Should be already setup...) */
1039     	}
1040     }
1041     
1042     static int airo_set_mac_address(struct net_device *dev, void *p)
1043     {
1044     	struct airo_info *ai = (struct airo_info*)dev->priv;
1045     	struct sockaddr *addr = p;
1046     	ConfigRid cfg;
1047     
1048     	readConfigRid (ai, &cfg);
1049     	memcpy (cfg.macAddr, addr->sa_data, dev->addr_len);
1050     	writeConfigRid (ai, &cfg);
1051     	memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
1052     	return 0;
1053     }
1054     
1055     static int airo_change_mtu(struct net_device *dev, int new_mtu)
1056     {
1057     	if ((new_mtu < 68) || (new_mtu > 2400))
1058     		return -EINVAL;
1059     	dev->mtu = new_mtu;
1060     	return 0;
1061     }
1062     
1063     
1064     static int airo_close(struct net_device *dev) { 
1065     	struct airo_info *ai = (struct airo_info*)dev->priv;
1066     
1067     	netif_stop_queue(dev);
1068     	disable_interrupts( ai );
1069     	return 0;
1070     }
1071     
1072     static void del_airo_dev( struct net_device *dev );
1073     
1074     void stop_airo_card( struct net_device *dev, int freeres ) 
1075     {
1076     	struct airo_info *ai = (struct airo_info*)dev->priv;
1077     	if (ai->flash)
1078     		kfree(ai->flash);
1079     	takedown_proc_entry( dev, ai );
1080     	if (ai->registered) {
1081     		unregister_netdev( dev );
1082     		ai->registered = 0;
1083     	}
1084     	disable_interrupts(ai);
1085     	free_irq( dev->irq, dev );
1086     	if (auto_wep) del_timer_sync(&ai->timer);
1087     	if (freeres) {
1088     		/* PCMCIA frees this stuff, so only for PCI and ISA */
1089     	        release_region( dev->base_addr, 64 );
1090             }
1091     	del_airo_dev( dev );
1092     	kfree( dev );
1093     }
1094     
1095     static int add_airo_dev( struct net_device *dev ); 
1096     
1097     struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
1098     {
1099     	struct net_device *dev;
1100     	struct airo_info *ai;
1101     	int i, rc;
1102     	
1103     	/* Create the network device object. */
1104             dev = alloc_etherdev(sizeof(*ai));
1105             if (!dev) {
1106     		printk(KERN_ERR "airo:  Couldn't alloc_etherdev\n");
1107     		return NULL;
1108             }
1109     	ai = dev->priv;
1110     	ai->registered = 1;
1111             ai->dev = dev;
1112     	ai->bap0_lock = SPIN_LOCK_UNLOCKED;
1113     	ai->bap1_lock = SPIN_LOCK_UNLOCKED;
1114     	ai->aux_lock = SPIN_LOCK_UNLOCKED;
1115     	ai->cmd_lock = SPIN_LOCK_UNLOCKED;
1116     	ai->header_parse = dev->hard_header_parse;
1117     	rc = add_airo_dev( dev );
1118     	if (rc)
1119     		goto err_out_free;
1120     	
1121     	/* The Airo-specific entries in the device structure. */
1122     	dev->hard_start_xmit = &airo_start_xmit;
1123     	dev->get_stats = &airo_get_stats;
1124     	dev->set_multicast_list = &airo_set_multicast_list;
1125     	dev->set_mac_address = &airo_set_mac_address;
1126     	dev->do_ioctl = &airo_ioctl;
1127     #ifdef WIRELESS_EXT
1128     	dev->get_wireless_stats = airo_get_wireless_stats;
1129     #endif /* WIRELESS_EXT */
1130     	dev->change_mtu = &airo_change_mtu;
1131     	dev->open = &airo_open;
1132     	dev->stop = &airo_close;
1133     	dev->irq = irq;
1134     	dev->base_addr = port;
1135     	
1136     	rc = register_netdev(dev);
1137     	if (rc)
1138     		goto err_out_unlink;
1139     	
1140     	rc = request_irq( dev->irq, airo_interrupt, 
1141     			  SA_SHIRQ | SA_INTERRUPT, dev->name, dev );
1142     	if (rc) {
1143     		printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );
1144     		goto err_out_unregister;
1145     	}
1146     	if (!is_pcmcia) {
1147     		if (!request_region( dev->base_addr, 64, dev->name )) {
1148     			rc = -EBUSY;
1149     			goto err_out_irq;
1150     		}
1151     	}
1152     	
1153     	if ( setup_card( ai, dev->dev_addr, &ai->config) != SUCCESS ) {
1154     		printk( KERN_ERR "airo: MAC could not be enabled\n" );
1155     		rc = -EIO;
1156     		goto err_out_res;
1157     	}
1158     
1159     	printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
1160     		dev->name,
1161     		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
1162     		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
1163     
1164     	/* Allocate the transmit buffers */
1165     	for( i = 0; i < MAX_FIDS; i++ )
1166     		ai->fids[i] = transmit_allocate( ai, 2312 );
1167     
1168     	setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
1169     	netif_start_queue(dev);
1170     	SET_MODULE_OWNER(dev);
1171     	return dev;
1172     
1173     err_out_res:
1174     	if (!is_pcmcia)
1175     	        release_region( dev->base_addr, 64 );
1176     err_out_irq:
1177     	free_irq(dev->irq, dev);
1178     err_out_unregister:
1179     	unregister_netdev(dev);
1180     err_out_unlink:
1181     	del_airo_dev(dev);
1182     err_out_free:
1183     	kfree(dev);
1184     	return NULL;
1185     }
1186     
1187     int waitbusy (struct airo_info *ai) {
1188     	int delay = 0;
1189     	while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) & (delay < 10000)) {
1190     		udelay (10);
1191     		if (++delay % 20)
1192     			OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
1193     	}  
1194     	return delay < 10000;
1195     }
1196     
1197     int reset_airo_card( struct net_device *dev ) {
1198     	int i;
1199     	struct airo_info *ai = (struct airo_info*)dev->priv;
1200     
1201     	disable_MAC(ai);
1202     	waitbusy (ai);
1203     	OUT4500(ai,COMMAND,CMD_SOFTRESET);
1204     	set_current_state (TASK_UNINTERRUPTIBLE);
1205     	schedule_timeout (HZ/5);
1206     	waitbusy (ai);
1207     	set_current_state (TASK_UNINTERRUPTIBLE);
1208     	schedule_timeout (HZ/5);
1209     	if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) {
1210     		printk( KERN_ERR "airo: MAC could not be enabled\n" );
1211     		return -1;
1212     	} else {
1213     		printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
1214     			dev->name,
1215     			dev->dev_addr[0],
1216     			dev->dev_addr[1],
1217     			dev->dev_addr[2],
1218     			dev->dev_addr[3],
1219     			dev->dev_addr[4],
1220     			dev->dev_addr[5]
1221     			);
1222     		/* Allocate the transmit buffers */
1223     		for( i = 0; i < MAX_FIDS; i++ )
1224     			ai->fids[i] = transmit_allocate( ai, 2312 );
1225     	}
1226     	enable_interrupts( ai );
1227     	netif_wake_queue(dev);
1228     	return 0;
1229     }
1230     
1231     int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
1232     {
1233     	memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
1234     	return ETH_ALEN;
1235     }
1236     
1237     static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
1238     	struct net_device *dev = (struct net_device *)dev_id;
1239     	u16 status;
1240     	u16 fid;
1241     	struct airo_info *apriv = (struct airo_info *)dev->priv;
1242     	u16 savedInterrupts;
1243     	
1244     	if (!netif_device_present(dev))
1245     		return;
1246     	
1247     	status = IN4500( apriv, EVSTAT );
1248     	if ( !status || status == 0xffff ) return;
1249     	
1250     	if ( status & EV_AWAKE ) {
1251     		OUT4500( apriv, EVACK, EV_AWAKE );
1252     		OUT4500( apriv, EVACK, EV_AWAKE );
1253     	}
1254     	
1255     	savedInterrupts = IN4500( apriv, EVINTEN );
1256     	OUT4500( apriv, EVINTEN, 0 );
1257     	
1258     	if ( status & EV_LINK ) {
1259     		/* The link status has changed, if you want to put a
1260     		   monitor hook in, do it here.  (Remember that
1261     		   interrupts are still disabled!)
1262     		*/
1263     		u16 newStatus = IN4500(apriv, LINKSTAT);
1264     		/* Here is what newStatus means: */
1265     #define NOBEACON 0x8000 /* Loss of sync - missed beacons */
1266     #define MAXRETRIES 0x8001 /* Loss of sync - max retries */
1267     #define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
1268     #define FORCELOSS 0x8003 /* Loss of sync - host request */
1269     #define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
1270     #define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
1271     #define DISASS 0x8200 /* Disassociation (low byte is reason code) */
1272     #define ASSFAIL 0x8400 /* Association failure (low byte is reason
1273     			  code) */
1274     #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
1275     			   code) */
1276     #define ASSOCIATED 0x0400 /* Assocatied */
1277     #define RC_RESERVED 0 /* Reserved return code */
1278     #define RC_NOREASON 1 /* Unspecified reason */
1279     #define RC_AUTHINV 2 /* Previous authentication invalid */
1280     #define RC_DEAUTH 3 /* Deauthenticated because sending station is
1281     		       leaving */
1282     #define RC_NOACT 4 /* Disassociated due to inactivity */
1283     #define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
1284     			all currently associated stations */
1285     #define RC_BADCLASS2 6 /* Class 2 frame received from
1286     			  non-Authenticated station */
1287     #define RC_BADCLASS3 7 /* Class 3 frame received from
1288     			  non-Associated station */
1289     #define RC_STATLEAVE 8 /* Disassociated because sending station is
1290     			  leaving BSS */
1291     #define RC_NOAUTH 9 /* Station requesting (Re)Association is not
1292     		       Authenticated with the responding station */
1293     		if (newStatus != ASSOCIATED) {
1294     			if (auto_wep && !timer_pending(&apriv->timer)) {
1295     				apriv->timer.expires = RUN_AT(HZ*3);
1296     	      			add_timer(&apriv->timer);
1297     			}
1298     		}
1299     	}
1300     	
1301     	/* Check to see if there is something to receive */
1302     	if ( status & EV_RX  ) {
1303     		struct sk_buff *skb = NULL;
1304     		long flags;
1305     		u16 fc, len, hdrlen = 0;
1306     		struct {
1307     			u16 status, len;
1308     			u8 rssi[2];
1309     		} hdr;
1310     
1311     		fid = IN4500( apriv, RXFID );
1312     
1313     		/* Get the packet length */
1314     	        spin_lock_irqsave(&apriv->bap0_lock, flags);
1315     		if (dev->type == ARPHRD_IEEE80211) {
1316     			bap_setup (apriv, fid, 4, BAP0);
1317     			bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0);
1318     			/* Bad CRC. Ignore packet */
1319     			if (le16_to_cpu(hdr.status) == 2) {
1320     				apriv->stats.rx_crc_errors++;
1321     				apriv->stats.rx_errors++;
1322     				hdr.len = 0;
1323     			}
1324     		} else {
1325     			bap_setup (apriv, fid, 6, BAP0);
1326     			bap_read (apriv, (u16*)&hdr.len, 4, BAP0);
1327     		}
1328     		len = le16_to_cpu(hdr.len);
1329     
1330     		if (len > 2312) {
1331     			apriv->stats.rx_length_errors++;
1332     			apriv->stats.rx_errors++;
1333     			printk( KERN_ERR 
1334     				"airo: Bad size %d\n", len );
1335     			len = 0;
1336     		}
1337     		if (len) {
1338     			if (dev->type == ARPHRD_IEEE80211) {
1339     				bap_setup (apriv, fid, 0x14, BAP0);
1340     				bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);
1341     				if ((le16_to_cpu(fc) & 0x300) == 0x300)
1342     					hdrlen = 30;
1343     				else
1344     					hdrlen = 24;
1345     			} else
1346     				hdrlen = 12;
1347     
1348     			skb = dev_alloc_skb( len + hdrlen + 2 );
1349     			if ( !skb ) {
1350     				apriv->stats.rx_dropped++;
1351     				len = 0;
1352     			}
1353     		}
1354     		if (len) {
1355     			u16 *buffer;
1356     			buffer = (u16*)skb_put (skb, len + hdrlen);
1357     			if (dev->type == ARPHRD_IEEE80211) {
1358     				u16 gap, tmpbuf[4];
1359     				buffer[0] = fc;
1360     				bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
1361     				if (hdrlen == 24)
1362     					bap_read (apriv, tmpbuf, 6, BAP0);
1363     
1364     				bap_read (apriv, &gap, sizeof(gap), BAP0);
1365     				gap = le16_to_cpu(gap);
1366     				if (gap && gap <= 8)
1367     					bap_read (apriv, tmpbuf, gap, BAP0);
1368     
1369     				bap_read (apriv, buffer + hdrlen/2, len, BAP0);
1370     			} else {
1371     		                bap_setup (apriv, fid, 0x38, BAP0);
1372     				bap_read (apriv, buffer,len + hdrlen,BAP0);
1373     			}
1374     #ifdef WIRELESS_SPY
1375     			if (apriv->spy_number > 0) {
1376     				int i;
1377     				char *sa;
1378     
1379     				sa = (char*)buffer + ((dev->type == ARPHRD_IEEE80211) ? 10 : 6);
1380     
1381     				for (i=0; i<apriv->spy_number; i++)
1382     					if (!memcmp(sa,apriv->spy_address[i],6))
1383     					{
1384     						apriv->spy_stat[i].qual = hdr.rssi[0];
1385     						apriv->spy_stat[i].level = hdr.rssi[1];
1386     						apriv->spy_stat[i].noise = 0;
1387     						apriv->spy_stat[i].updated = 3;
1388     						break;
1389     					}
1390     			}
1391     #endif /* WIRELESS_SPY  */
1392     			apriv->stats.rx_packets++;
1393     			apriv->stats.rx_bytes += len + hdrlen;
1394     			dev->last_rx = jiffies;
1395     			skb->dev = dev;
1396     			skb->ip_summed = CHECKSUM_NONE;
1397     			if (dev->type == ARPHRD_IEEE80211) {
1398     				skb->mac.raw = skb->data;
1399     				skb_pull (skb, hdrlen);
1400     				skb->pkt_type = PACKET_OTHERHOST;
1401     				skb->protocol = htons(ETH_P_802_2);
1402     			} else
1403     				skb->protocol = eth_type_trans( skb, dev );
1404     
1405     			netif_rx( skb );
1406     		}
1407     		spin_unlock_irqrestore(&apriv->bap0_lock, flags);
1408     	}
1409     
1410     	/* Check to see if a packet has been transmitted */
1411     	if (  status & ( EV_TX|EV_TXEXC ) ) {
1412     		int i;
1413     		int len = 0;
1414     		int full = 1;
1415     		int index = -1;
1416     		
1417     		fid = IN4500(apriv, TXCOMPLFID);
1418     		
1419     		for( i = 0; i < MAX_FIDS; i++ ) {
1420     			if (!(apriv->fids[i] & 0xffff0000)) full = 0;
1421     			if ( ( apriv->fids[i] & 0xffff ) == fid ) {
1422     				len = apriv->fids[i] >> 16;
1423     				index = i;
1424     				/* Set up to be used again */
1425     				apriv->fids[i] &= 0xffff; 
1426     			}
1427     		}
1428     		if (full) netif_wake_queue(dev);
1429     		if (index==-1) {
1430     			printk( KERN_ERR
1431     				"airo: Unallocated FID was used to xmit\n" );
1432     		}
1433     		if ( status & EV_TX ) {
1434     			apriv->stats.tx_packets++;
1435     			if(index!=-1)
1436     				apriv->stats.tx_bytes += len;
1437     		} else {
1438     			if (bap_setup(apriv, fid, 0x0004, BAP1) == SUCCESS) {
1439     				u16 status;
1440     				bap_read(apriv, &status, 2, BAP1);
1441     				if (le16_to_cpu(status) & 2)
1442     					apriv->stats.tx_aborted_errors++;
1443     				if (le16_to_cpu(status) & 4)
1444     					apriv->stats.tx_heartbeat_errors++;
1445     				if (le16_to_cpu(status) & 0x10)
1446     					apriv->stats.tx_carrier_errors++;
1447     			}
1448     			apriv->stats.tx_errors++;
1449     		}
1450     	}
1451     	if ( status & ~STATUS_INTS & ~IGNORE_INTS ) 
1452     		printk( KERN_WARNING 
1453     			"airo: Got weird status %x\n", 
1454     			status & ~STATUS_INTS & ~IGNORE_INTS );
1455     	OUT4500( apriv, EVACK, status & STATUS_INTS );
1456     	OUT4500( apriv, EVINTEN, savedInterrupts );
1457     	
1458     	/* done.. */
1459     	return;     
1460     }
1461     
1462     /*
1463      *  Routines to talk to the card
1464      */
1465     
1466     /*
1467      *  This was originally written for the 4500, hence the name
1468      *  NOTE:  If use with 8bit mode and SMP bad things will happen!
1469      *         Why would some one do 8 bit IO in an SMP machine?!?
1470      */
1471     static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) {
1472     	if ( !do8bitIO )
1473     		outw( val, ai->dev->base_addr + reg );
1474     	else {
1475     		outb( val & 0xff, ai->dev->base_addr + reg );
1476     		outb( val >> 8, ai->dev->base_addr + reg + 1 );
1477     	}
1478     }
1479     
1480     static u16 IN4500( struct airo_info *ai, u16 reg ) {
1481     	unsigned short rc;
1482     	
1483     	if ( !do8bitIO )
1484     		rc = inw( ai->dev->base_addr + reg );
1485     	else {
1486     		rc = inb( ai->dev->base_addr + reg );
1487     		rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8;
1488     	}
1489     	return rc;
1490     }
1491     
1492     static int enable_MAC( struct airo_info *ai, Resp *rsp ) {
1493             Cmd cmd;
1494     
1495             if (ai->flags&FLAG_RADIO_OFF) return SUCCESS;
1496     	memset(&cmd, 0, sizeof(cmd));
1497     	cmd.cmd = MAC_ENABLE;
1498     	return issuecommand(ai, &cmd, rsp);
1499     }
1500     
1501     static void disable_MAC( struct airo_info *ai ) {
1502             Cmd cmd;
1503     	Resp rsp;
1504     
1505     	memset(&cmd, 0, sizeof(cmd));
1506     	cmd.cmd = MAC_DISABLE; // disable in case already enabled
1507     	issuecommand(ai, &cmd, &rsp);
1508     }
1509     
1510     static void enable_interrupts( struct airo_info *ai ) {
1511     	/* Reset the status register */
1512     	u16 status = IN4500( ai, EVSTAT );
1513     	OUT4500( ai, EVACK, status );
1514     	/* Enable the interrupts */
1515     	OUT4500( ai, EVINTEN, STATUS_INTS );
1516     	/* Note there is a race condition between the last two lines that
1517     	   I dont know how to get rid of right now... */
1518     }
1519     
1520     static void disable_interrupts( struct airo_info *ai ) {
1521     	OUT4500( ai, EVINTEN, 0 );
1522     }
1523     
1524     static u16 setup_card(struct airo_info *ai, u8 *mac, 
1525     		      ConfigRid *config)
1526     {
1527     	Cmd cmd; 
1528     	Resp rsp;
1529     	ConfigRid cfg;
1530     	int status;
1531     	int i;
1532     	SsidRid mySsid;
1533     	u16 lastindex;
1534     	WepKeyRid wkr;
1535     	int rc;
1536     
1537     	memset( &mySsid, 0, sizeof( mySsid ) );
1538     	if (ai->flash) {
1539     		kfree (ai->flash);
1540     		ai->flash = NULL;
1541     	}
1542     
1543     	/* The NOP is the first step in getting the card going */
1544     	cmd.cmd = NOP;
1545     	cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;
1546     	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {
1547     		return ERROR;
1548     	}
1549     	memset(&cmd, 0, sizeof(cmd));
1550     	cmd.cmd = MAC_DISABLE; // disable in case already enabled
1551     	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {
1552     		return ERROR;
1553     	}
1554     	
1555     	// Let's figure out if we need to use the AUX port
1556     	cmd.cmd = CMD_ENABLEAUX;
1557     	if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
1558     		printk(KERN_ERR "airo: Error checking for AUX port\n");
1559     		return ERROR;
1560     	}
1561     	if (!aux_bap || rsp.status & 0xff00) {
1562     		ai->bap_read = fast_bap_read;
1563     		printk(KERN_DEBUG "airo: Doing fast bap_reads\n");
1564     	} else {
1565     		ai->bap_read = aux_bap_read;
1566     		printk(KERN_DEBUG "airo: Doing AUX bap_reads\n");
1567     	}
1568     	if ( config->len ) {
1569     		cfg = *config;
1570     	} else {
1571     		// general configuration (read/modify/write)
1572     		status = readConfigRid(ai, &cfg);
1573     		if ( status != SUCCESS ) return ERROR;
1574     		cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
1575         
1576     		/* Save off the MAC */
1577     		for( i = 0; i < 6; i++ ) {
1578     			mac[i] = cfg.macAddr[i];
1579     		}
1580     
1581     		/* Check to see if there are any insmod configured 
1582     		   rates to add */
1583     		if ( rates ) {
1584     			int i = 0;
1585     			if ( rates[0] ) memset(cfg.rates,0,sizeof(cfg.rates));
1586     			for( i = 0; i < 8 && rates[i]; i++ ) {
1587     				cfg.rates[i] = rates[i];
1588     			}    
1589     		}
1590     		if ( basic_rate > 0 ) {
1591     			int i;
1592     			for( i = 0; i < 8; i++ ) {
1593     				if ( cfg.rates[i] == basic_rate ||
1594     				     !cfg.rates ) {
1595     					cfg.rates[i] = basic_rate | 0x80;
1596     					break;
1597     				}
1598     			}
1599     		}
1600     		cfg.authType = ai->authtype;
1601     		*config = cfg;
1602     	}
1603     	
1604     	/* Setup the SSIDs if present */
1605     	if ( ssids[0] ) {
1606     		int i = 0;
1607     		for( i = 0; i < 3 && ssids[i]; i++ ) {
1608     			mySsid.ssids[i].len = strlen(ssids[i]);
1609     			if ( mySsid.ssids[i].len > 32 ) 
1610     				mySsid.ssids[i].len = 32;
1611     			memcpy(mySsid.ssids[i].ssid, ssids[i],
1612     			       mySsid.ssids[i].len);
1613     			mySsid.ssids[i].len = mySsid.ssids[i].len;
1614     		}
1615     	}
1616     	
1617     	status = writeConfigRid(ai, &cfg);
1618     	if ( status != SUCCESS ) return ERROR;
1619     	
1620     	/* Set up the SSID list */
1621     	status = writeSsidRid(ai, &mySsid);
1622     	if ( status != SUCCESS ) return ERROR;
1623     	
1624     	/* Grab the initial wep key, we gotta save it for auto_wep */
1625     	rc = readWepKeyRid(ai, &wkr, 1);
1626     	if (rc == SUCCESS) do {
1627     		lastindex = wkr.kindex;
1628     		if (wkr.kindex == 0xffff) {
1629     			ai->defindex = wkr.mac[0];
1630     		}
1631     		rc = readWepKeyRid(ai, &wkr, 0);
1632     	} while(lastindex != wkr.kindex);
1633     	
1634     	if (auto_wep && !timer_pending(&ai->timer)) {
1635     		ai->timer.expires = RUN_AT(HZ*3);
1636     		add_timer(&ai->timer);
1637     	}
1638     	return SUCCESS;
1639     }
1640     
1641     static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
1642             // Im really paranoid about letting it run forever!
1643     	int max_tries = 600000;  
1644             int rc = SUCCESS;
1645     	long flags;
1646     
1647     	spin_lock_irqsave(&ai->cmd_lock, flags);
1648     	OUT4500(ai, PARAM0, pCmd->parm0);
1649     	OUT4500(ai, PARAM1, pCmd->parm1);
1650     	OUT4500(ai, PARAM2, pCmd->parm2);
1651     	OUT4500(ai, COMMAND, pCmd->cmd);
1652     	while ( max_tries-- &&
1653     		(IN4500(ai, EVSTAT) & EV_CMD) == 0) {
1654     		if ( IN4500(ai, COMMAND) == pCmd->cmd) { 
1655     			// PC4500 didn't notice command, try again
1656     			OUT4500(ai, COMMAND, pCmd->cmd);
1657     		}
1658     		if (!(max_tries & 255) && !in_interrupt()) {
1659     			set_current_state(TASK_RUNNING);
1660     			schedule();
1661     		}
1662     	}
1663     	if ( max_tries == -1 ) {
1664     		printk( KERN_ERR 
1665     			"airo: Max tries exceeded when issueing command\n" );
1666                     rc = ERROR;
1667                     goto done;
1668     	}
1669     	// command completed
1670     	pRsp->status = IN4500(ai, STATUS);
1671     	pRsp->rsp0 = IN4500(ai, RESP0);
1672     	pRsp->rsp1 = IN4500(ai, RESP1);
1673     	pRsp->rsp2 = IN4500(ai, RESP2);
1674     	
1675     	// clear stuck command busy if necessary
1676     	if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
1677     		OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
1678     	}
1679     	// acknowledge processing the status/response
1680     	OUT4500(ai, EVACK, EV_CMD);
1681      done:
1682     	spin_unlock_irqrestore(&ai->cmd_lock, flags);
1683     	return rc;
1684     }
1685     
1686     /* Sets up the bap to start exchange data.  whichbap should
1687      * be one of the BAP0 or BAP1 defines.  Locks should be held before
1688      * calling! */
1689     static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
1690     {
1691     	int timeout = 50;
1692     	int max_tries = 3;
1693     	
1694     	OUT4500(ai, SELECT0+whichbap, rid);
1695     	OUT4500(ai, OFFSET0+whichbap, offset);
1696     	while (1) {
1697     		int status = IN4500(ai, OFFSET0+whichbap);
1698     		if (status & BAP_BUSY) {
1699                             /* This isn't really a timeout, but its kinda
1700     			   close */
1701     			if (timeout--) { 
1702     				continue;
1703     			}
1704     		} else if ( status & BAP_ERR ) {
1705     			/* invalid rid or offset */
1706     			printk( KERN_ERR "airo: BAP error %x %d\n", 
1707     				status, whichbap );
1708     			return ERROR;
1709     		} else if (status & BAP_DONE) { // success
1710     			return SUCCESS;
1711     		}
1712     		if ( !(max_tries--) ) {
1713     			printk( KERN_ERR 
1714     				"airo: BAP setup error too many retries\n" );
1715     			return ERROR;
1716     		}
1717     		// -- PC4500 missed it, try again
1718     		OUT4500(ai, SELECT0+whichbap, rid);
1719     		OUT4500(ai, OFFSET0+whichbap, offset);
1720     		timeout = 50;
1721     	}
1722     }
1723     
1724     /* should only be called by aux_bap_read.  This aux function and the
1725        following use concepts not documented in the developers guide.  I
1726        got them from a patch given to my by Aironet */
1727     static u16 aux_setup(struct airo_info *ai, u16 page,
1728     		     u16 offset, u16 *len)
1729     {
1730     	u16 next;
1731     
1732     	OUT4500(ai, AUXPAGE, page);
1733     	OUT4500(ai, AUXOFF, 0);
1734     	next = IN4500(ai, AUXDATA);
1735     	*len = IN4500(ai, AUXDATA)&0xff;
1736     	if (offset != 4) OUT4500(ai, AUXOFF, offset);
1737     	return next;
1738     }
1739     
1740     /* requires call to bap_setup() first */
1741     static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst,
1742     			int bytelen, int whichbap) 
1743     {
1744     	u16 len;
1745     	u16 page;
1746     	u16 offset;
1747     	u16 next;
1748     	int words;
1749     	int i;
1750     	long flags;
1751     
1752     	spin_lock_irqsave(&ai->aux_lock, flags);
1753     	page = IN4500(ai, SWS0+whichbap);
1754     	offset = IN4500(ai, SWS2+whichbap);
1755     	next = aux_setup(ai, page, offset, &len);
1756     	words = (bytelen+1)>>1;
1757     
1758     	for (i=0; i<words;) {
1759     		int count;
1760     		count = (len>>1) < (words-i) ? (len>>1) : (words-i);
1761     		if ( !do8bitIO ) 
1762     			insw( ai->dev->base_addr+DATA0+whichbap, 
1763     			      pu16Dst+i,count );
1764     		else
1765     			insb( ai->dev->base_addr+DATA0+whichbap, 
1766     			      pu16Dst+i, count << 1 );
1767     		i += count;
1768     		if (i<words) {
1769     			next = aux_setup(ai, next, 4, &len);
1770     		}
1771     	}
1772     	spin_unlock_irqrestore(&ai->aux_lock, flags);
1773     	return SUCCESS;
1774     }
1775     
1776     
1777     /* requires call to bap_setup() first */
1778     static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst, 
1779     			 int bytelen, int whichbap)
1780     {
1781     	bytelen = (bytelen + 1) & (~1); // round up to even value
1782     	if ( !do8bitIO ) 
1783     		insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 );
1784     	else
1785     		insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen );
1786     	return SUCCESS;
1787     }
1788     
1789     /* requires call to bap_setup() first */
1790     static int bap_write(struct airo_info *ai, const u16 *pu16Src, 
1791     		     int bytelen, int whichbap)
1792     {
1793     	bytelen = (bytelen + 1) & (~1); // round up to even value
1794     	if ( !do8bitIO ) 
1795     		outsw( ai->dev->base_addr+DATA0+whichbap, 
1796     		       pu16Src, bytelen>>1 );
1797     	else
1798     		outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen );
1799     	return SUCCESS;
1800     }
1801     
1802     static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
1803     {
1804     	Cmd cmd; /* for issuing commands */
1805     	Resp rsp; /* response from commands */
1806     	u16 status;
1807     
1808     	memset(&cmd, 0, sizeof(cmd));
1809     	cmd.cmd = accmd;
1810     	cmd.parm0 = rid;
1811     	status = issuecommand(ai, &cmd, &rsp);
1812     	if (status != 0) return status;
1813     	if ( (rsp.status & 0x7F00) != 0) {
1814     		return (accmd << 8) + (rsp.rsp0 & 0xFF);
1815     	}
1816     	return 0;
1817     }
1818     
1819     /*  Note, that we are using BAP1 which is also used by transmit, so
1820      *  we must get a lock. */
1821     static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len)
1822     {
1823     	u16 status;
1824             long flags;
1825             int rc = SUCCESS;
1826     
1827     	spin_lock_irqsave(&ai->bap1_lock, flags);
1828     	if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != SUCCESS) {
1829                     rc = status;
1830                     goto done;
1831             }
1832     	if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
1833     		rc = ERROR;
1834                     goto done;
1835             }
1836     	// read the rid length field
1837     	bap_read(ai, pBuf, 2, BAP1);
1838     	// length for remaining part of rid
1839     	len = min_t(unsigned int, len, le16_to_cpu(*(u16*)pBuf)) - 2;
1840     	
1841     	if ( len <= 2 ) {
1842     		printk( KERN_ERR 
1843     			"airo: Rid %x has a length of %d which is too short\n",
1844     			(int)rid,
1845     			(int)len );
1846     		rc = ERROR;
1847                     goto done;
1848     	}
1849     	// read remainder of the rid
1850     	if (bap_setup(ai, rid, 2, BAP1) != SUCCESS) {
1851                     rc = ERROR;
1852                     goto done;
1853             }
1854     	rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1);
1855      done:
1856     	spin_unlock_irqrestore(&ai->bap1_lock, flags);
1857     	return rc;
1858     }
1859     
1860     /*  Note, that we are using BAP1 which is also used by transmit, so
1861      *  make sure this isnt called when a transmit is happening */
1862     static int PC4500_writerid(struct airo_info *ai, u16 rid, 
1863     			   const void *pBuf, int len)
1864     {
1865     	u16 status;
1866             long flags;
1867     	int rc = SUCCESS;
1868     
1869     	spin_lock_irqsave(&ai->bap1_lock, flags);
1870     	// --- first access so that we can write the rid data
1871     	if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) {
1872                     rc = status;
1873                     goto done;
1874             }
1875     	// --- now write the rid data
1876     	if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
1877                     rc = ERROR;
1878                     goto done;
1879             }
1880     	bap_write(ai, pBuf, len, BAP1);
1881     	// ---now commit the rid data
1882     	rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS);
1883      done:
1884     	spin_unlock_irqrestore(&ai->bap1_lock, flags);
1885             return rc;
1886     }
1887     
1888     /* Allocates a FID to be used for transmitting packets.  We only use
1889        one for now. */
1890     static u16 transmit_allocate(struct airo_info *ai, int lenPayload)
1891     {
1892     	Cmd cmd;
1893     	Resp rsp;
1894     	u16 txFid;
1895     	u16 txControl;
1896             long flags;
1897     
1898     	cmd.cmd = CMD_ALLOCATETX;
1899     	cmd.parm0 = lenPayload;
1900     	if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return 0;
1901     	if ( (rsp.status & 0xFF00) != 0) return 0;
1902     	/* wait for the allocate event/indication
1903     	 * It makes me kind of nervous that this can just sit here and spin,
1904     	 * but in practice it only loops like four times. */
1905     	while ( (IN4500(ai, EVSTAT) & EV_ALLOC) == 0) ;
1906     	// get the allocated fid and acknowledge
1907     	txFid = IN4500(ai, TXALLOCFID);
1908     	OUT4500(ai, EVACK, EV_ALLOC);
1909       
1910     	/*  The CARD is pretty cool since it converts the ethernet packet
1911     	 *  into 802.11.  Also note that we don't release the FID since we
1912     	 *  will be using the same one over and over again. */
1913     	/*  We only have to setup the control once since we are not
1914     	 *  releasing the fid. */
1915     	txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3
1916     		| TXCTL_ETHERNET | TXCTL_NORELEASE);
1917     	spin_lock_irqsave(&ai->bap1_lock, flags);
1918     	if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) {
1919     		spin_unlock_irqrestore(&ai->bap1_lock, flags);
1920     		return ERROR;
1921     	}
1922     	bap_write(ai, &txControl, sizeof(txControl), BAP1);
1923     	spin_unlock_irqrestore(&ai->bap1_lock, flags);
1924     
1925     	return txFid;
1926     }
1927     
1928     /* In general BAP1 is dedicated to transmiting packets.  However,
1929        since we need a BAP when accessing RIDs, we also use BAP1 for that.
1930        Make sure the BAP1 spinlock is held when this is called. */
1931     static int transmit_802_3_packet(struct airo_info *ai, u16 txFid, 
1932     				 char *pPacket, int len)
1933     {
1934     	u16 payloadLen;
1935     	Cmd cmd;
1936     	Resp rsp;
1937     	
1938     	if (len < 12) {
1939     		printk( KERN_WARNING "Short packet %d\n", len );
1940     		return ERROR;
1941     	}
1942     	
1943     	// packet is destination[6], source[6], payload[len-12]
1944     	// write the payload length and dst/src/payload
1945     	if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
1946     	/* The hardware addresses aren't counted as part of the payload, so
1947     	 * we have to subtract the 12 bytes for the addresses off */
1948     	payloadLen = cpu_to_le16(len-12);
1949     	bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
1950     	bap_write(ai, (const u16*)pPacket, len, BAP1);
1951     	// issue the transmit command
1952     	memset( &cmd, 0, sizeof( cmd ) );
1953     	cmd.cmd = CMD_TRANSMIT;
1954     	cmd.parm0 = txFid;
1955     	if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
1956     	if ( (rsp.status & 0xFF00) != 0) return ERROR;
1957     	return SUCCESS;
1958     }
1959     
1960     /*
1961      *  This is the proc_fs routines.  It is a bit messier than I would
1962      *  like!  Feel free to clean it up!
1963      */
1964     
1965     static ssize_t proc_read( struct file *file,
1966     			  char *buffer,
1967     			  size_t len,
1968     			  loff_t *offset);
1969     
1970     static ssize_t proc_write( struct file *file,
1971     			   const char *buffer,
1972     			   size_t len,
1973     			   loff_t *offset );
1974     static int proc_close( struct inode *inode, struct file *file );
1975     
1976     static int proc_stats_open( struct inode *inode, struct file *file );
1977     static int proc_statsdelta_open( struct inode *inode, struct file *file );
1978     static int proc_status_open( struct inode *inode, struct file *file );
1979     static int proc_SSID_open( struct inode *inode, struct file *file );
1980     static int proc_APList_open( struct inode *inode, struct file *file );
1981     static int proc_BSSList_open( struct inode *inode, struct file *file );
1982     static int proc_config_open( struct inode *inode, struct file *file );
1983     static int proc_wepkey_open( struct inode *inode, struct file *file );
1984     
1985     static struct file_operations proc_statsdelta_ops = {
1986     	read:           proc_read,
1987     	open:           proc_statsdelta_open,
1988     	release:        proc_close
1989     };
1990     
1991     static struct file_operations proc_stats_ops = {
1992     	read:           proc_read,
1993     	open:           proc_stats_open,
1994     	release:        proc_close
1995     };
1996     
1997     static struct file_operations proc_status_ops = {
1998     	read:            proc_read,
1999     	open:            proc_status_open,
2000     	release:         proc_close
2001     };
2002     
2003     static struct file_operations proc_SSID_ops = {
2004     	read:          proc_read,
2005     	write:         proc_write,
2006     	open:          proc_SSID_open,
2007     	release:       proc_close
2008     };
2009     
2010     static struct file_operations proc_BSSList_ops = {
2011     	read:          proc_read,
2012     	write:         proc_write,
2013     	open:          proc_BSSList_open,
2014     	release:       proc_close
2015     };
2016     
2017     static struct file_operations proc_APList_ops = {
2018     	read:          proc_read,
2019     	write:         proc_write,
2020     	open:          proc_APList_open,
2021     	release:       proc_close
2022     };
2023     
2024     static struct file_operations proc_config_ops = {
2025     	read:          proc_read,
2026     	write:         proc_write,
2027     	open:          proc_config_open,
2028     	release:       proc_close
2029     };
2030     
2031     static struct file_operations proc_wepkey_ops = {
2032     	read:          proc_read,
2033     	write:         proc_write,
2034     	open:          proc_wepkey_open,
2035     	release:       proc_close
2036     };
2037     
2038     static struct proc_dir_entry *airo_entry = 0;
2039     
2040     struct proc_data {
2041     	int release_buffer;
2042     	int readlen;
2043     	char *rbuffer;
2044     	int writelen;
2045     	int maxwritelen;
2046     	char *wbuffer;
2047     	void (*on_close) (struct inode *, struct file *);
2048     };
2049     
2050     #ifndef SETPROC_OPS
2051     #define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops)
2052     #endif
2053     
2054     static int setup_proc_entry( struct net_device *dev,
2055     			     struct airo_info *apriv ) {
2056     	struct proc_dir_entry *entry;
2057     	/* First setup the device directory */
2058     	apriv->proc_entry = create_proc_entry(dev->name,
2059     					      S_IFDIR|airo_perm,
2060     					      airo_entry);
2061             apriv->proc_entry->uid = proc_uid;
2062             apriv->proc_entry->gid = proc_gid;
2063     
2064     	/* Setup the StatsDelta */
2065     	entry = create_proc_entry("StatsDelta",
2066     				  S_IFREG | (S_IRUGO&proc_perm),
2067     				  apriv->proc_entry);
2068             entry->uid = proc_uid;
2069             entry->gid = proc_gid;
2070     	entry->data = dev;
2071     	SETPROC_OPS(entry, proc_statsdelta_ops);
2072     	
2073     	/* Setup the Stats */
2074     	entry = create_proc_entry("Stats",
2075     				  S_IFREG | (S_IRUGO&proc_perm),
2076     				  apriv->proc_entry);
2077             entry->uid = proc_uid;
2078             entry->gid = proc_gid;
2079     	entry->data = dev;
2080     	SETPROC_OPS(entry, proc_stats_ops);
2081     	
2082     	/* Setup the Status */
2083     	entry = create_proc_entry("Status",
2084     				  S_IFREG | (S_IRUGO&proc_perm),
2085     				  apriv->proc_entry);
2086             entry->uid = proc_uid;
2087             entry->gid = proc_gid;
2088     	entry->data = dev;
2089     	SETPROC_OPS(entry, proc_status_ops);
2090     	
2091     	/* Setup the Config */
2092     	entry = create_proc_entry("Config",
2093     				  S_IFREG | proc_perm,
2094     				  apriv->proc_entry);
2095             entry->uid = proc_uid;
2096             entry->gid = proc_gid;
2097     	entry->data = dev;
2098     	SETPROC_OPS(entry, proc_config_ops);
2099     
2100     	/* Setup the SSID */
2101     	entry = create_proc_entry("SSID",
2102     				  S_IFREG | proc_perm,
2103     				  apriv->proc_entry);
2104             entry->uid = proc_uid;
2105             entry->gid = proc_gid;
2106     	entry->data = dev;
2107     	SETPROC_OPS(entry, proc_SSID_ops);
2108     
2109     	/* Setup the APList */
2110     	entry = create_proc_entry("APList",
2111     				  S_IFREG | proc_perm,
2112     				  apriv->proc_entry);
2113             entry->uid = proc_uid;
2114             entry->gid = proc_gid;
2115     	entry->data = dev;
2116     	SETPROC_OPS(entry, proc_APList_ops);
2117     
2118     	/* Setup the BSSList */
2119     	entry = create_proc_entry("BSSList",
2120     				  S_IFREG | proc_perm,
2121     				  apriv->proc_entry);
2122     	entry->uid = proc_uid;
2123     	entry->gid = proc_gid;
2124     	entry->data = dev;
2125     	SETPROC_OPS(entry, proc_BSSList_ops);
2126     
2127     	/* Setup the WepKey */
2128     	entry = create_proc_entry("WepKey",
2129     				  S_IFREG | proc_perm,
2130     				  apriv->proc_entry);
2131             entry->uid = proc_uid;
2132             entry->gid = proc_gid;
2133     	entry->data = dev;
2134     	SETPROC_OPS(entry, proc_wepkey_ops);
2135     
2136     	return 0;
2137     }
2138     
2139     static int takedown_proc_entry( struct net_device *dev,
2140     				struct airo_info *apriv ) {
2141     	if ( !apriv->proc_entry->namelen ) return 0;
2142     	remove_proc_entry("Stats",apriv->proc_entry);
2143     	remove_proc_entry("StatsDelta",apriv->proc_entry);
2144     	remove_proc_entry("Status",apriv->proc_entry);
2145     	remove_proc_entry("Config",apriv->proc_entry);
2146     	remove_proc_entry("SSID",apriv->proc_entry);
2147     	remove_proc_entry("APList",apriv->proc_entry);
2148     	remove_proc_entry("BSSList",apriv->proc_entry);
2149     	remove_proc_entry("WepKey",apriv->proc_entry);
2150     	remove_proc_entry(dev->name,airo_entry);
2151     	return 0;
2152     }
2153     
2154     /*
2155      *  What we want from the proc_fs is to be able to efficiently read
2156      *  and write the configuration.  To do this, we want to read the
2157      *  configuration when the file is opened and write it when the file is
2158      *  closed.  So basically we allocate a read buffer at open and fill it
2159      *  with data, and allocate a write buffer and read it at close.
2160      */
2161     
2162     /*
2163      *  The read routine is generic, it relies on the preallocated rbuffer
2164      *  to supply the data.
2165      */
2166     static ssize_t proc_read( struct file *file,
2167     			  char *buffer,
2168     			  size_t len,
2169     			  loff_t *offset )
2170     {
2171     	int i;
2172     	int pos;
2173     	struct proc_data *priv = (struct proc_data*)file->private_data;
2174     	
2175     	if( !priv->rbuffer ) return -EINVAL;
2176     	
2177     	pos = *offset;
2178     	for( i = 0; i+pos < priv->readlen && i < len; i++ ) {
2179     		if (put_user( priv->rbuffer[i+pos], buffer+i ))
2180     			return -EFAULT;
2181     	}
2182     	*offset += i;
2183     	return i;
2184     }
2185     
2186     /*
2187      *  The write routine is generic, it fills in a preallocated rbuffer
2188      *  to supply the data.
2189      */
2190     static ssize_t proc_write( struct file *file,
2191     			   const char *buffer,
2192     			   size_t len,
2193     			   loff_t *offset ) 
2194     {
2195     	int i;
2196     	int pos;
2197     	struct proc_data *priv = (struct proc_data*)file->private_data;
2198     	
2199     	if ( !priv->wbuffer ) {
2200     		return -EINVAL;
2201     	}
2202     	
2203     	pos = *offset;
2204     	
2205     	for( i = 0; i + pos <  priv->maxwritelen &&
2206     		     i < len; i++ ) {
2207     		if (get_user( priv->wbuffer[i+pos], buffer + i ))
2208     			return -EFAULT;
2209     	}
2210     	if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos;
2211     	*offset += i;
2212     	return i;
2213     }
2214     
2215     static int proc_status_open( struct inode *inode, struct file *file ) {
2216     	struct proc_data *data;
2217     	struct proc_dir_entry *dp = inode->u.generic_ip;
2218     	struct net_device *dev = dp->data;
2219     	struct airo_info *apriv = (struct airo_info *)dev->priv;
2220     	CapabilityRid cap_rid;
2221     	StatusRid status_rid;
2222     	int i;
2223     	
2224     	MOD_INC_USE_COUNT;
2225     	
2226     	dp = inode->u.generic_ip;
2227     	
2228     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2229     		return -ENOMEM;
2230     	memset(file->private_data, 0, sizeof(struct proc_data));
2231     	data = (struct proc_data *)file->private_data;
2232     	if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
2233     		kfree (file->private_data);
2234     		return -ENOMEM;
2235     	}
2236     	
2237     	readStatusRid(apriv, &status_rid);
2238     	readCapabilityRid(apriv, &cap_rid);
2239     	
2240             i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n",
2241                         status_rid.mode & 1 ? "CFG ": "",
2242                         status_rid.mode & 2 ? "ACT ": "",
2243                         status_rid.mode & 0x10 ? "SYN ": "",
2244                         status_rid.mode & 0x20 ? "LNK ": "",
2245                         status_rid.mode & 0x40 ? "LEAP ": "",
2246                         status_rid.mode & 0x80 ? "PRIV ": "",
2247                         status_rid.mode & 0x100 ? "KEY ": "",
2248                         status_rid.mode & 0x200 ? "WEP ": "",
2249                         status_rid.mode & 0x8000 ? "ERR ": "");
2250     	sprintf( data->rbuffer+i, "Mode: %x\n"
2251     		 "Signal Strength: %d\n"
2252     		 "Signal Quality: %d\n"
2253     		 "SSID: %-.*s\n"
2254     		 "AP: %-.16s\n"
2255     		 "Freq: %d\n"
2256     		 "BitRate: %dmbs\n"
2257     		 "Driver Version: %s\n"
2258     		 "Device: %s\nManufacturer: %s\nFirmware Version: %s\n"
2259     		 "Radio type: %x\nCountry: %x\nHardware Version: %x\n"
2260     		 "Software Version: %x\nSoftware Subversion: %x\n"
2261     		 "Boot block version: %x\n",
2262     		 (int)status_rid.mode,
2263     		 (int)status_rid.normalizedSignalStrength,
2264     		 (int)status_rid.signalQuality,
2265     		 (int)status_rid.SSIDlen,
2266     		 status_rid.SSID,
2267     		 status_rid.apName,
2268     		 (int)status_rid.channel,
2269     		 (int)status_rid.currentXmitRate/2,
2270     		 version,
2271     		 cap_rid.prodName,
2272     		 cap_rid.manName,
2273     		 cap_rid.prodVer,
2274     		 cap_rid.radioType,
2275     		 cap_rid.country,
2276     		 cap_rid.hardVer,
2277     		 (int)cap_rid.softVer,
2278     		 (int)cap_rid.softSubVer,
2279     		 (int)cap_rid.bootBlockVer );
2280     	data->readlen = strlen( data->rbuffer );
2281     	return 0;
2282     }
2283     
2284     static int proc_stats_rid_open(struct inode*, struct file*, u16);
2285     static int proc_statsdelta_open( struct inode *inode, 
2286     				 struct file *file ) {
2287     	if (file->f_mode&FMODE_WRITE) {
2288     		return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR);
2289     	}
2290     	return proc_stats_rid_open(inode, file, RID_STATSDELTA);
2291     }
2292     
2293     static int proc_stats_open( struct inode *inode, struct file *file ) {
2294     	return proc_stats_rid_open(inode, file, RID_STATS);
2295     }
2296     
2297     static int proc_stats_rid_open( struct inode *inode, 
2298     				struct file *file,
2299     				u16 rid ) {
2300     	struct proc_data *data;
2301     	struct proc_dir_entry *dp = inode->u.generic_ip;
2302     	struct net_device *dev = dp->data;
2303     	struct airo_info *apriv = (struct airo_info *)dev->priv;
2304     	StatsRid stats;
2305     	int i, j;
2306     	int *vals = stats.vals;
2307     	MOD_INC_USE_COUNT;
2308     	
2309     	
2310     	dp = inode->u.generic_ip;
2311     	
2312     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2313     		return -ENOMEM;
2314     	memset(file->private_data, 0, sizeof(struct proc_data));
2315     	data = (struct proc_data *)file->private_data;
2316     	if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
2317     		kfree (file->private_data);
2318     		return -ENOMEM;
2319     	}
2320     	
2321     	readStatsRid(apriv, &stats, rid);
2322     	
2323             j = 0;
2324     	for(i=0; (int)statsLabels[i]!=-1 && 
2325     		    i*4<stats.len; i++){
2326     		if (!statsLabels[i]) continue;
2327     		if (j+strlen(statsLabels[i])+16>4096) {
2328     			printk(KERN_WARNING
2329     			       "airo: Potentially disasterous buffer overflow averted!\n");
2330     			break;
2331     		}
2332     		j+=sprintf(data->rbuffer+j, "%s: %d\n", statsLabels[i], vals[i]);
2333     	}
2334     	if (i*4>=stats.len){
2335     		printk(KERN_WARNING
2336     		       "airo: Got a short rid\n");
2337     	}
2338     	data->readlen = j;
2339     	return 0;
2340     }
2341     
2342     static int get_dec_u16( char *buffer, int *start, int limit ) {
2343     	u16 value;
2344     	int valid = 0;
2345     	for( value = 0; buffer[*start] >= '0' &&
2346     		     buffer[*start] <= '9' &&
2347     		     *start < limit; (*start)++ ) {
2348     		valid = 1;
2349     		value *= 10;
2350     		value += buffer[*start] - '0';
2351     	}
2352     	if ( !valid ) return -1;
2353     	return value;
2354     }
2355     
2356     static void checkThrottle(ConfigRid *config) {
2357     	int i;
2358     /* Old hardware had a limit on encryption speed */
2359     	if (config->authType != AUTH_OPEN && maxencrypt) {
2360     		for(i=0; i<8; i++) {
2361     			if (config->rates[i] > maxencrypt) {
2362     				config->rates[i] = 0;
2363     			}
2364     		}
2365     	}
2366     }
2367     
2368     static void proc_config_on_close( struct inode *inode, struct file *file ) {
2369     	struct proc_data *data = file->private_data;
2370     	struct proc_dir_entry *dp = inode->u.generic_ip;
2371     	struct net_device *dev = dp->data;
2372     	struct airo_info *ai = (struct airo_info*)dev->priv;
2373     	ConfigRid config;
2374     	Resp rsp;
2375     	char *line;
2376     	int need_reset = 0;
2377     	
2378     	if ( !data->writelen ) return;
2379     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2380     	
2381     	disable_MAC(ai);
2382     	readConfigRid(ai, &config);
2383     
2384     	line = data->wbuffer;
2385     	while( line[0] ) {
2386     /*** Mode processing */
2387     		if ( !strncmp( line, "Mode: ", 6 ) ) {
2388     			line += 6;
2389     			config.rmode &= 0xfe00;
2390     			if ( line[0] == 'a' ) {
2391     				config.opmode = 0;
2392     			} else {
2393     				config.opmode = 1;
2394     				if ( line[0] == 'r' )
2395     					config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
2396     				else if ( line[0] == 'y' )
2397     					config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
2398     			}
2399     			if (config.rmode & RXMODE_DISABLE_802_3_HEADER) {
2400     				dev->type = ARPHRD_IEEE80211;
2401     				dev->hard_header_parse = wll_header_parse;
2402     			} else if (dev->type == ARPHRD_IEEE80211) {
2403     				dev->type = ARPHRD_ETHER;
2404     				dev->hard_header_parse = ai->header_parse;
2405     				need_reset = 1;
2406     			}
2407     		}
2408     		
2409     /*** Radio status */
2410     		else if (!strncmp(line,"Radio: ", 7)) {
2411     			line += 7;
2412     			if (!strncmp(line,"off",3)) {
2413     				ai->flags |= FLAG_RADIO_OFF;
2414     			} else {
2415     				ai->flags &= ~FLAG_RADIO_OFF;
2416     			}
2417     		}
2418     /*** NodeName processing */
2419     		else if ( !strncmp( line, "NodeName: ", 10 ) ) {
2420     			int j;
2421     			
2422     			line += 10;
2423     			memset( config.nodeName, 0, 16 );
2424     /* Do the name, assume a space between the mode and node name */
2425     			for( j = 0; j < 16 && line[j] != '\n'; j++ ) {
2426     				config.nodeName[j] = line[j];
2427     			}
2428     		} 
2429     		
2430     /*** PowerMode processing */
2431     		else if ( !strncmp( line, "PowerMode: ", 11 ) ) {
2432     			line += 11;
2433     			if ( !strncmp( line, "PSPCAM", 6 ) ) {
2434     				config.powerSaveMode = POWERSAVE_PSPCAM;
2435     			} else if ( !strncmp( line, "PSP", 3 ) ) {
2436     				config.powerSaveMode = POWERSAVE_PSP;
2437     			} else {
2438     				config.powerSaveMode = POWERSAVE_CAM;
2439     			}	
2440     		} else if ( !strncmp( line, "DataRates: ", 11 ) ) {
2441     			int v, i = 0, k = 0; /* i is index into line, 
2442     						k is index to rates */
2443     			
2444     			line += 11;
2445     			while((v = get_dec_u16(line, &i, 3))!=-1) {
2446     				config.rates[k++] = (u8)v;
2447     				line += i + 1;
2448     				i = 0;
2449     			}
2450     		} else if ( !strncmp( line, "Channel: ", 9 ) ) {
2451     			int v, i = 0;
2452     			line += 9;
2453     			v = get_dec_u16(line, &i, i+3);
2454     			if ( v != -1 ) 
2455     				config.channelSet = (u16)v;
2456     		} else if ( !strncmp( line, "XmitPower: ", 11 ) ) {
2457     			int v, i = 0;
2458     			line += 11;
2459     			v = get_dec_u16(line, &i, i+3);
2460     			if ( v != -1 ) config.txPower = (u16)v;
2461     		} else if ( !strncmp( line, "WEP: ", 5 ) ) {
2462     			line += 5;
2463     			switch( line[0] ) {
2464     			case 's':
2465     				config.authType = (u16)AUTH_SHAREDKEY;
2466     				break;
2467     			case 'e':
2468     				config.authType = (u16)AUTH_ENCRYPT;
2469     				break;
2470     			default:
2471     				config.authType = (u16)AUTH_OPEN;
2472     				break;
2473     			}
2474     		} else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) {
2475     			int v, i = 0;
2476     			
2477     			line += 16;
2478     			v = get_dec_u16(line, &i, 3);
2479     			v = (v<0) ? 0 : ((v>255) ? 255 : v);
2480     			config.longRetryLimit = (u16)v;
2481     		} else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) {
2482     			int v, i = 0;
2483     			
2484     			line += 17;
2485     			v = get_dec_u16(line, &i, 3);
2486     			v = (v<0) ? 0 : ((v>255) ? 255 : v);
2487     			config.shortRetryLimit = (u16)v;
2488     		} else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) {
2489     			int v, i = 0;
2490     			
2491     			line += 14;
2492     			v = get_dec_u16(line, &i, 4);
2493     			v = (v<0) ? 0 : ((v>2312) ? 2312 : v);
2494     			config.rtsThres = (u16)v;
2495     		} else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
2496     			int v, i = 0;
2497     			
2498     			line += 16;
2499     			v = get_dec_u16(line, &i, 5);
2500     			v = (v<0) ? 0 : v;
2501     			config.txLifetime = (u16)v;
2502     		} else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) {
2503     			int v, i = 0;
2504     			
2505     			line += 16;
2506     			v = get_dec_u16(line, &i, 5);
2507     			v = (v<0) ? 0 : v;
2508     			config.rxLifetime = (u16)v;
2509     		} else if ( !strncmp( line, "TXDiversity: ", 13 ) ) {
2510     			config.txDiversity = 
2511     				(line[13]=='l') ? 1 :
2512     				((line[13]=='r')? 2: 3);
2513     		} else if ( !strncmp( line, "RXDiversity: ", 13 ) ) {
2514     			config.rxDiversity = 
2515     				(line[13]=='l') ? 1 :
2516     				((line[13]=='r')? 2: 3);
2517     		} else if ( !strncmp( line, "FragThreshold: ", 15 ) ) {
2518     			int v, i = 0;
2519     			
2520     			line += 15;
2521     			v = get_dec_u16(line, &i, 4);
2522     			v = (v<256) ? 256 : ((v>2312) ? 2312 : v);
2523     			v = v & 0xfffe; /* Make sure its even */
2524     			config.fragThresh = (u16)v;
2525     		} else if (!strncmp(line, "Modulation: ", 12)) {
2526     			line += 12;
2527     			switch(*line) {
2528     			case 'd':  config.modulation=MOD_DEFAULT; break;
2529     			case 'c':  config.modulation=MOD_CCK; break;
2530     			case 'm':  config.modulation=MOD_MOK; break;
2531     			default:
2532     				printk( KERN_WARNING "airo: Unknown modulation\n" );
2533     			}
2534     		} else if (!strncmp(line, "Preamble: ", 10)) {
2535     			line += 10;
2536     			switch(*line) {
2537     			case 'a': config.preamble=PREAMBLE_AUTO; break;
2538     			case 'l': config.preamble=PREAMBLE_LONG; break;
2539     			case 's': config.preamble=PREAMBLE_SHORT; break;
2540     		        default: printk(KERN_WARNING "airo: Unknown preamble\n");
2541     			}
2542     		} else {
2543     			printk( KERN_WARNING "Couldn't figure out %s\n", line );
2544     		}
2545     		while( line[0] && line[0] != '\n' ) line++;
2546     		if ( line[0] ) line++;
2547     	}
2548     	checkThrottle(&config);
2549     	ai->config = config;
2550     	if (need_reset) {
2551     		APListRid APList_rid;
2552     		SsidRid SSID_rid;
2553     
2554     		readAPListRid(ai, &APList_rid);
2555     		readSsidRid(ai, &SSID_rid);
2556     		reset_airo_card(dev);
2557     		writeSsidRid(ai, &SSID_rid);
2558     		writeAPListRid(ai, &APList_rid);
2559     	}
2560     	writeConfigRid(ai, &config);
2561     	enable_MAC(ai, &rsp);
2562     }
2563     
2564     static int proc_config_open( struct inode *inode, struct file *file ) {
2565     	struct proc_data *data;
2566     	struct proc_dir_entry *dp = inode->u.generic_ip;
2567     	struct net_device *dev = dp->data;
2568     	struct airo_info *ai = (struct airo_info*)dev->priv;
2569     	ConfigRid config;
2570     	int i;
2571     	
2572     	MOD_INC_USE_COUNT;
2573     	
2574     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2575     	
2576     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2577     		return -ENOMEM;
2578     	memset(file->private_data, 0, sizeof(struct proc_data));
2579     	data = (struct proc_data *)file->private_data;
2580     	if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
2581     		kfree (file->private_data);
2582     		return -ENOMEM;
2583     	}
2584     	if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
2585     		kfree (data->rbuffer);
2586     		kfree (file->private_data);
2587     		return -ENOMEM;
2588     	}
2589     	memset( data->wbuffer, 0, 2048 );
2590     	data->maxwritelen = 2048;
2591     	data->on_close = proc_config_on_close;
2592     	
2593     	readConfigRid(ai, &config);
2594     	
2595     	i = sprintf( data->rbuffer, 
2596     		     "Mode: %s\n"
2597     		     "Radio: %s\n"
2598     		     "NodeName: %-16s\n"
2599     		     "PowerMode: %s\n"
2600     		     "DataRates: %d %d %d %d %d %d %d %d\n"
2601     		     "Channel: %d\n"
2602     		     "XmitPower: %d\n",
2603     		     config.opmode == 0 ? "adhoc" : 
2604     		     config.opmode == 1 ? "ESS" :
2605     		     config.opmode == 2 ? "AP" : 
2606     		     config.opmode == 3 ? "AP RPTR" : "Error",
2607     		     ai->flags&FLAG_RADIO_OFF ? "off" : "on",
2608     		     config.nodeName,
2609     		     config.powerSaveMode == 0 ? "CAM" :
2610     		     config.powerSaveMode == 1 ? "PSP" :
2611     		     config.powerSaveMode == 2 ? "PSPCAM" : "Error",
2612     		     (int)config.rates[0],
2613     		     (int)config.rates[1],
2614     		     (int)config.rates[2],
2615     		     (int)config.rates[3],
2616     		     (int)config.rates[4],
2617     		     (int)config.rates[5],
2618     		     (int)config.rates[6],
2619     		     (int)config.rates[7],
2620     		     (int)config.channelSet,
2621     		     (int)config.txPower
2622     		);
2623     	sprintf( data->rbuffer + i,
2624     		 "LongRetryLimit: %d\n"
2625     		 "ShortRetryLimit: %d\n"
2626     		 "RTSThreshold: %d\n"
2627     		 "TXMSDULifetime: %d\n"
2628     		 "RXMSDULifetime: %d\n"
2629     		 "TXDiversity: %s\n"
2630     		 "RXDiversity: %s\n"
2631     		 "FragThreshold: %d\n"
2632     		 "WEP: %s\n"
2633     		 "Modulation: %s\n"
2634     		 "Preamble: %s\n",
2635     		 (int)config.longRetryLimit,
2636     		 (int)config.shortRetryLimit,
2637     		 (int)config.rtsThres,
2638     		 (int)config.txLifetime,
2639     		 (int)config.rxLifetime,
2640     		 config.txDiversity == 1 ? "left" :
2641     		 config.txDiversity == 2 ? "right" : "both",
2642     		 config.rxDiversity == 1 ? "left" :
2643     		 config.rxDiversity == 2 ? "right" : "both",
2644     		 (int)config.fragThresh,
2645     		 config.authType == AUTH_ENCRYPT ? "encrypt" :
2646     		 config.authType == AUTH_SHAREDKEY ? "shared" : "open",
2647     		 config.modulation == 0 ? "default" :
2648     		 config.modulation == MOD_CCK ? "cck" :
2649     		 config.modulation == MOD_MOK ? "mok" : "error",
2650     		 config.preamble == PREAMBLE_AUTO ? "auto" :
2651     		 config.preamble == PREAMBLE_LONG ? "long" :
2652     		 config.preamble == PREAMBLE_SHORT ? "short" : "error"
2653     		);
2654     	data->readlen = strlen( data->rbuffer );
2655     	return 0;
2656     }
2657     
2658     static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
2659     	struct proc_data *data = (struct proc_data *)file->private_data;
2660     	struct proc_dir_entry *dp = inode->u.generic_ip;
2661     	struct net_device *dev = dp->data;
2662     	struct airo_info *ai = (struct airo_info*)dev->priv;
2663     	SsidRid SSID_rid;
2664     	int i;
2665     	int offset = 0;
2666     	
2667     	if ( !data->writelen ) return;
2668     	
2669     	memset( &SSID_rid, 0, sizeof( SSID_rid ) );
2670     	
2671     	for( i = 0; i < 3; i++ ) {
2672     		int j;
2673     		for( j = 0; j+offset < data->writelen && j < 32 &&
2674     			     data->wbuffer[offset+j] != '\n'; j++ ) {
2675     			SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j];
2676     		}
2677     		if ( j == 0 ) break;
2678     		SSID_rid.ssids[i].len = j;
2679     		offset += j;
2680     		while( data->wbuffer[offset] != '\n' && 
2681     		       offset < data->writelen ) offset++;
2682     		offset++;
2683     	}
2684     	writeSsidRid(ai, &SSID_rid);
2685     }
2686     
2687     inline static u8 hexVal(char c) {
2688     	if (c>='0' && c<='9') return c -= '0';
2689     	if (c>='a' && c<='f') return c -= 'a'-10;
2690     	if (c>='A' && c<='F') return c -= 'A'-10;
2691     	return 0;
2692     }
2693     
2694     static void proc_APList_on_close( struct inode *inode, struct file *file ) {
2695     	struct proc_data *data = (struct proc_data *)file->private_data;
2696     	struct proc_dir_entry *dp = inode->u.generic_ip;
2697     	struct net_device *dev = dp->data;
2698     	struct airo_info *ai = (struct airo_info*)dev->priv;
2699     	APListRid APList_rid;
2700     	int i;
2701     	
2702     	if ( !data->writelen ) return;
2703     	
2704     	memset( &APList_rid, 0, sizeof(APList_rid) );
2705     	APList_rid.len = sizeof(APList_rid);
2706     	
2707     	for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
2708     		int j;
2709     		for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
2710     			switch(j%3) {
2711     			case 0:
2712     				APList_rid.ap[i][j/3]=
2713     					hexVal(data->wbuffer[j+i*6*3])<<4;
2714     				break;
2715     			case 1:
2716     				APList_rid.ap[i][j/3]|=
2717     					hexVal(data->wbuffer[j+i*6*3]);
2718     				break;
2719     			}
2720     		}
2721     	}
2722     	writeAPListRid(ai, &APList_rid);
2723     }
2724     
2725     /* This function wraps PC4500_writerid with a MAC disable */
2726     static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
2727     			int len ) {
2728     	int rc;
2729     	Resp rsp;
2730     	
2731     	disable_MAC(ai);
2732     	rc = PC4500_writerid(ai, rid, rid_data, len);
2733     	enable_MAC(ai, &rsp);
2734     	return rc;
2735     }
2736     
2737     /* Returns the length of the key at the index.  If index == 0xffff
2738      * the index of the transmit key is returned.  If the key doesn't exist,
2739      * -1 will be returned.
2740      */
2741     static int get_wep_key(struct airo_info *ai, u16 index) {
2742     	WepKeyRid wkr;
2743     	int rc;
2744     	u16 lastindex;
2745     
2746     	rc = readWepKeyRid(ai, &wkr, 1);
2747     	if (rc == SUCCESS) do {
2748     		lastindex = wkr.kindex;
2749     		if (wkr.kindex == index) {
2750     			if (index == 0xffff) {
2751     				return wkr.mac[0];
2752     			}
2753     			return wkr.klen;
2754     		}
2755     		readWepKeyRid(ai, &wkr, 0);
2756     	} while(lastindex != wkr.kindex);
2757     	return -1;
2758     }
2759     
2760     static int set_wep_key(struct airo_info *ai, u16 index,
2761     		       const char *key, u16 keylen, int perm ) {
2762     	static const unsigned char macaddr[6] = { 0x01, 0, 0, 0, 0, 0 };
2763     	WepKeyRid wkr;
2764     
2765     	memset(&wkr, 0, sizeof(wkr));
2766     	if (keylen == 0) {
2767     // We are selecting which key to use
2768     		wkr.len = sizeof(wkr);
2769     		wkr.kindex = 0xffff;
2770     		wkr.mac[0] = (char)index;
2771     		if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index);
2772     		if (perm) ai->defindex = (char)index;
2773     	} else {
2774     // We are actually setting the key
2775     		wkr.len = sizeof(wkr);
2776     		wkr.kindex = index;
2777     		wkr.klen = keylen;
2778     		memcpy( wkr.key, key, keylen );
2779     		memcpy( wkr.mac, macaddr, 6 );
2780     		printk(KERN_INFO "Setting key %d\n", index);
2781     	}
2782     	
2783     	writeWepKeyRid(ai, &wkr, perm);
2784     	return 0;
2785     }
2786     
2787     static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
2788     	struct proc_data *data;
2789     	struct proc_dir_entry *dp = inode->u.generic_ip;
2790     	struct net_device *dev = dp->data;
2791     	struct airo_info *ai = (struct airo_info*)dev->priv;
2792     	int i;
2793     	char key[16];
2794     	u16 index = 0;
2795     	int j = 0;
2796     
2797     	memset(key, 0, sizeof(key));
2798     	
2799     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2800     	data = (struct proc_data *)file->private_data;
2801     	if ( !data->writelen ) return;
2802     	
2803     	if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
2804     	    (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
2805     		index = data->wbuffer[0] - '0';
2806     		if (data->wbuffer[1] == '\n') {
2807     			set_wep_key(ai, index, 0, 0, 1);
2808     			return;
2809     		}
2810     		j = 2;
2811     	} else {
2812     		printk(KERN_ERR "airo:  WepKey passed invalid key index\n");
2813     		return;
2814     	}
2815     
2816     	for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) {
2817     		switch(i%3) {
2818     		case 0:
2819     			key[i/3] = hexVal(data->wbuffer[i+j])<<4;
2820     			break;
2821     		case 1:
2822     			key[i/3] |= hexVal(data->wbuffer[i+j]);
2823     			break;
2824     		}
2825     	}
2826     	set_wep_key(ai, index, key, i/3, 1);
2827     }
2828     
2829     static int proc_wepkey_open( struct inode *inode, struct file *file ) {
2830     	struct proc_data *data;
2831     	struct proc_dir_entry *dp = inode->u.generic_ip;
2832     	struct net_device *dev = dp->data;
2833     	struct airo_info *ai = (struct airo_info*)dev->priv;
2834     	char *ptr;
2835     	WepKeyRid wkr;
2836     	u16 lastindex;
2837     	int j=0;
2838     	int rc;
2839     	
2840     	MOD_INC_USE_COUNT;
2841     	
2842     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2843     	
2844     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2845     		return -ENOMEM;
2846     	memset(file->private_data, 0, sizeof(struct proc_data));
2847     	memset(&wkr, 0, sizeof(wkr));
2848     	data = (struct proc_data *)file->private_data;
2849     	if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) {
2850     		kfree (file->private_data);
2851     		return -ENOMEM;
2852     	}
2853     	memset(data->rbuffer, 0, 180);
2854     	data->writelen = 0;
2855     	data->maxwritelen = 80;
2856     	if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) {
2857     		kfree (data->rbuffer);
2858     		kfree (file->private_data);
2859     		return -ENOMEM;
2860     	}
2861     	memset( data->wbuffer, 0, 80 );
2862     	data->on_close = proc_wepkey_on_close;
2863     	
2864     	ptr = data->rbuffer;
2865     	strcpy(ptr, "No wep keys\n");
2866     	rc = readWepKeyRid(ai, &wkr, 1);
2867     	if (rc == SUCCESS) do {
2868     		lastindex = wkr.kindex;
2869     		if (wkr.kindex == 0xffff) {
2870     			j += sprintf(ptr+j, "Tx key = %d\n",
2871     				     (int)wkr.mac[0]);
2872     		} else {
2873     			j += sprintf(ptr+j, "Key %d set with length = %d\n",
2874     				     (int)wkr.kindex, (int)wkr.klen);
2875     		}
2876     		readWepKeyRid(ai, &wkr, 0);
2877     	} while((lastindex != wkr.kindex) && (j < 180-30));
2878     
2879     	data->readlen = strlen( data->rbuffer );
2880     	return 0;
2881     }
2882     
2883     static int proc_SSID_open( struct inode *inode, struct file *file ) {
2884     	struct proc_data *data;
2885     	struct proc_dir_entry *dp = inode->u.generic_ip;
2886     	struct net_device *dev = dp->data;
2887     	struct airo_info *ai = (struct airo_info*)dev->priv;
2888     	int i;
2889     	char *ptr;
2890     	SsidRid SSID_rid;
2891     
2892     	MOD_INC_USE_COUNT;
2893     	
2894     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2895     	
2896     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2897     		return -ENOMEM;
2898     	memset(file->private_data, 0, sizeof(struct proc_data));
2899     	data = (struct proc_data *)file->private_data;
2900     	if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
2901     		kfree (file->private_data);
2902     		return -ENOMEM;
2903     	}
2904     	data->writelen = 0;
2905     	data->maxwritelen = 33*3;
2906     	if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) {
2907     		kfree (data->rbuffer);
2908     		kfree (file->private_data);
2909     		return -ENOMEM;
2910     	}
2911     	memset( data->wbuffer, 0, 33*3 );
2912     	data->on_close = proc_SSID_on_close;
2913     	
2914     	readSsidRid(ai, &SSID_rid);
2915     	ptr = data->rbuffer;
2916     	for( i = 0; i < 3; i++ ) {
2917     		int j;
2918     		if ( !SSID_rid.ssids[i].len ) break;
2919     		for( j = 0; j < 32 && 
2920     			     j < SSID_rid.ssids[i].len && 
2921     			     SSID_rid.ssids[i].ssid[j]; j++ ) {
2922     			*ptr++ = SSID_rid.ssids[i].ssid[j]; 
2923     		}
2924     		*ptr++ = '\n';
2925     	}
2926     	*ptr = '\0';
2927     	data->readlen = strlen( data->rbuffer );
2928     	return 0;
2929     }
2930     
2931     static int proc_APList_open( struct inode *inode, struct file *file ) {
2932     	struct proc_data *data;
2933     	struct proc_dir_entry *dp = inode->u.generic_ip;
2934     	struct net_device *dev = dp->data;
2935     	struct airo_info *ai = (struct airo_info*)dev->priv;
2936     	int i;
2937     	char *ptr;
2938     	APListRid APList_rid;
2939     
2940     	MOD_INC_USE_COUNT;
2941     	
2942     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2943     	
2944     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2945     		return -ENOMEM;
2946     	memset(file->private_data, 0, sizeof(struct proc_data));
2947     	data = (struct proc_data *)file->private_data;
2948     	if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
2949     		kfree (file->private_data);
2950     		return -ENOMEM;
2951     	}
2952     	data->writelen = 0;
2953     	data->maxwritelen = 4*6*3;
2954     	if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
2955     		kfree (data->rbuffer);
2956     		kfree (file->private_data);
2957     		return -ENOMEM;
2958     	}
2959     	memset( data->wbuffer, 0, data->maxwritelen );
2960     	data->on_close = proc_APList_on_close;
2961     	
2962     	readAPListRid(ai, &APList_rid);
2963     	ptr = data->rbuffer;
2964     	for( i = 0; i < 4; i++ ) {
2965     // We end when we find a zero MAC
2966     		if ( !*(int*)APList_rid.ap[i] &&
2967     		     !*(int*)&APList_rid.ap[i][2]) break;
2968     		ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x\n",
2969     			       (int)APList_rid.ap[i][0],
2970     			       (int)APList_rid.ap[i][1],
2971     			       (int)APList_rid.ap[i][2],
2972     			       (int)APList_rid.ap[i][3],
2973     			       (int)APList_rid.ap[i][4],
2974     			       (int)APList_rid.ap[i][5]);
2975     	}
2976     	if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
2977     
2978     	*ptr = '\0';
2979     	data->readlen = strlen( data->rbuffer );
2980     	return 0;
2981     }
2982     
2983     static int proc_BSSList_open( struct inode *inode, struct file *file ) {
2984     	struct proc_data *data;
2985     	struct proc_dir_entry *dp = inode->u.generic_ip;
2986     	struct net_device *dev = dp->data;
2987     	struct airo_info *ai = (struct airo_info*)dev->priv;
2988     	char *ptr;
2989     	BSSListRid BSSList_rid;
2990     	int rc;
2991     	/* If doLoseSync is not 1, we won't do a Lose Sync */
2992     	int doLoseSync = -1;
2993             
2994     	MOD_INC_USE_COUNT;
2995     	
2996     	dp = (struct proc_dir_entry *) inode->u.generic_ip;
2997     	
2998     	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
2999     		return -ENOMEM;
3000     	memset(file->private_data, 0, sizeof(struct proc_data));
3001     	data = (struct proc_data *)file->private_data;
3002     	if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
3003     		kfree (file->private_data);
3004     		return -ENOMEM;
3005     	}
3006     	data->writelen = 0;
3007     	data->maxwritelen = 0;
3008     	data->wbuffer = 0;
3009     	data->on_close = 0;
3010     	
3011     	if (file->f_mode & FMODE_WRITE) {
3012     		if (!(file->f_mode & FMODE_READ)) {
3013     			Cmd cmd;
3014     			Resp rsp;
3015                             
3016     			memset(&cmd, 0, sizeof(cmd));
3017     			cmd.cmd=CMD_LISTBSS;
3018     			issuecommand(ai, &cmd, &rsp);
3019     			data->readlen = 0;
3020     			return 0;
3021     		}
3022     		doLoseSync = 1;
3023     	}
3024     	ptr = data->rbuffer;
3025     	/* There is a race condition here if there are concurrent opens.
3026                Since it is a rare condition, we'll just live with it, otherwise
3027                we have to add a spin lock... */
3028     	rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
3029     	while(rc == 0 && BSSList_rid.index != 0xffff) {
3030     		ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x %*s rssi = %d",
3031     				(int)BSSList_rid.bssid[0],
3032     				(int)BSSList_rid.bssid[1],
3033     				(int)BSSList_rid.bssid[2],
3034     				(int)BSSList_rid.bssid[3],
3035     				(int)BSSList_rid.bssid[4],
3036     				(int)BSSList_rid.bssid[5],
3037     				(int)BSSList_rid.ssidLen,
3038     				BSSList_rid.ssid,
3039     				(int)BSSList_rid.rssi);
3040     		ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
3041     				(int)BSSList_rid.dsChannel,
3042     				BSSList_rid.cap & CAP_ESS ? "ESS" : "",
3043     				BSSList_rid.cap & CAP_IBSS ? "adhoc" : "",
3044     				BSSList_rid.cap & CAP_PRIVACY ? "wep" : "",
3045     				BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : "");
3046     		rc = readBSSListRid(ai, 0, &BSSList_rid);
3047     	}
3048     	*ptr = '\0';
3049     	data->readlen = strlen( data->rbuffer );
3050     	return 0;
3051     }
3052     
3053     static int proc_close( struct inode *inode, struct file *file ) 
3054     {
3055     	struct proc_data *data = (struct proc_data *)file->private_data;
3056     	if ( data->on_close != NULL ) data->on_close( inode, file );
3057     	MOD_DEC_USE_COUNT;
3058     	if ( data->rbuffer ) kfree( data->rbuffer );
3059     	if ( data->wbuffer ) kfree( data->wbuffer );
3060     	kfree( data );
3061     	return 0;
3062     }
3063     
3064     static struct net_device_list {
3065     	struct net_device *dev;
3066     	struct net_device_list *next;
3067     } *airo_devices = 0;
3068     
3069     /* Since the card doesnt automatically switch to the right WEP mode,
3070        we will make it do it.  If the card isn't associated, every secs we
3071        will switch WEP modes to see if that will help.  If the card is
3072        associated we will check every minute to see if anything has
3073        changed. */
3074     static void timer_func( u_long data ) {
3075     	struct net_device *dev = (struct net_device*)data;
3076     	struct airo_info *apriv = (struct airo_info *)dev->priv;
3077     	u16 linkstat = IN4500(apriv, LINKSTAT);
3078     	
3079     	if (linkstat != 0x400 ) {
3080     /* We don't have a link so try changing the authtype */
3081     		ConfigRid config = apriv->config;
3082     
3083     		switch(apriv->authtype) {
3084     		case AUTH_ENCRYPT:
3085     /* So drop to OPEN */
3086     			config.authType = AUTH_OPEN;
3087     			apriv->authtype = AUTH_OPEN;
3088     			break;
3089     		case AUTH_SHAREDKEY:
3090     			if (apriv->keyindex < auto_wep) {
3091     				set_wep_key(apriv, apriv->keyindex, 0, 0, 0);
3092     				config.authType = AUTH_SHAREDKEY;
3093     				apriv->authtype = AUTH_SHAREDKEY;
3094     				apriv->keyindex++;
3095     			} else {
3096     			        /* Drop to ENCRYPT */
3097     				apriv->keyindex = 0;
3098     				set_wep_key(apriv, apriv->defindex, 0, 0, 0);
3099     				config.authType = AUTH_ENCRYPT;
3100     				apriv->authtype = AUTH_ENCRYPT;
3101     			}
3102     			break;
3103     		default:  /* We'll escalate to SHAREDKEY */
3104     			config.authType = AUTH_SHAREDKEY;
3105     			apriv->authtype = AUTH_SHAREDKEY;
3106     		}
3107     		checkThrottle(&config);
3108     		writeConfigRid(apriv, &config);
3109     
3110     /* Schedule check to see if the change worked */
3111     		apriv->timer.expires = RUN_AT(HZ*3);
3112     		add_timer(&apriv->timer);
3113     	}
3114     }
3115     
3116     static int add_airo_dev( struct net_device *dev ) {
3117     	struct net_device_list *node = kmalloc( sizeof( *node ), GFP_KERNEL );
3118     	if ( !node )
3119     		return -ENOMEM;
3120     
3121     	if ( auto_wep ) {
3122     		struct airo_info *apriv=dev->priv;
3123     		struct timer_list *timer = &apriv->timer;
3124     			
3125     		timer->function = timer_func;
3126     		timer->data = (u_long)dev;
3127     		init_timer(timer);
3128     		apriv->authtype = AUTH_SHAREDKEY;
3129     	}
3130     		
3131     	node->dev = dev;
3132     	node->next = airo_devices;
3133     	airo_devices = node;
3134     
3135     	return 0;
3136     }
3137     
3138     static void del_airo_dev( struct net_device *dev ) {
3139     	struct net_device_list **p = &airo_devices;
3140     	while( *p && ( (*p)->dev != dev ) )
3141     		p = &(*p)->next;
3142     	if ( *p && (*p)->dev == dev )
3143     		*p = (*p)->next; 
3144     }
3145     
3146     #ifdef CONFIG_PCI
3147     static int __devinit airo_pci_probe(struct pci_dev *pdev, 
3148     				    const struct pci_device_id *pent)
3149     {
3150     	pdev->driver_data = init_airo_card(pdev->irq, 
3151     					   pdev->resource[2].start, 0);
3152     	if (!pdev->driver_data) {
3153     		return -ENODEV;
3154     	}
3155     	return 0;
3156     }
3157     
3158     static void __devexit airo_pci_remove(struct pci_dev *pdev)
3159     {
3160     	stop_airo_card(pdev->driver_data, 1);
3161     }
3162     #endif
3163     
3164     static int __init airo_init_module( void )
3165     {
3166     	int i, rc = 0, have_isa_dev = 0;
3167     	
3168     	airo_entry = create_proc_entry("aironet",
3169     				       S_IFDIR | airo_perm,
3170     				       proc_root_driver);
3171             airo_entry->uid = proc_uid;
3172             airo_entry->gid = proc_gid;
3173     	
3174     	for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
3175     		printk( KERN_INFO 
3176     			"airo:  Trying to configure ISA adapter at irq=%d io=0x%x\n",
3177     			irq[i], io[i] );
3178     		if (init_airo_card( irq[i], io[i], 0 ))
3179     			have_isa_dev = 1;
3180     	}
3181     	
3182     #ifdef CONFIG_PCI
3183     	printk( KERN_INFO "airo:  Probing for PCI adapters\n" );
3184     	rc = pci_module_init(&airo_driver);
3185     	printk( KERN_INFO "airo:  Finished probing for PCI adapters\n" );
3186     #endif
3187     
3188     	/* Always exit with success, as we are a library module
3189     	 * as well as a driver module
3190     	 */
3191     	return 0;
3192     }
3193     
3194     static void __exit airo_cleanup_module( void )
3195     {
3196     	while( airo_devices ) {
3197     		printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
3198     		stop_airo_card( airo_devices->dev, 1 );
3199     	}
3200     	remove_proc_entry("aironet", proc_root_driver);
3201     }
3202     
3203     #ifdef WIRELESS_EXT
3204     /*
3205      * Initial Wireless Extension code for Aironet driver by :
3206      *	Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
3207      */
3208     #ifndef IW_ENCODE_NOKEY
3209     #define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
3210     #define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
3211     #endif /* IW_ENCODE_NOKEY */
3212     #endif /* WIRELESS_EXT */
3213     
3214     /*
3215      * This defines the configuration part of the Wireless Extensions
3216      * Note : irq and spinlock protection will occur in the subroutines
3217      *
3218      * TODO :
3219      *	o Check input value more carefully and fill correct values in range
3220      *	o Implement : POWER, SPY, APLIST
3221      *	o Optimise when adapter is closed (aggregate changes, commit later)
3222      *	o Test and shakeout the bugs (if any)
3223      *
3224      * Jean II
3225      *
3226      * Javier Achirica did a great job of merging code from the unnamed CISCO
3227      * developer that added support for flashing the card.
3228      */
3229     static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3230     {
3231     	int i, rc = 0;
3232     #ifdef WIRELESS_EXT
3233     	struct airo_info *local = (struct airo_info*) dev->priv;
3234     	struct iwreq *wrq = (struct iwreq *) rq;
3235     	ConfigRid config;		/* Configuration info */
3236     	CapabilityRid cap_rid;		/* Card capability info */
3237     	StatusRid status_rid;		/* Card status info */
3238     
3239     #ifdef CISCO_EXT
3240     	if (cmd != SIOCGIWPRIV && cmd != AIROIOCTL && cmd != AIROIDIFC)
3241     #endif /* CISCO_EXT */
3242     	{
3243     		/* If the command read some stuff, we better get it out of
3244     		 * the card first... */
3245     		if(IW_IS_GET(cmd))
3246     			readStatusRid(local, &status_rid);
3247     		if(IW_IS_GET(cmd) || (cmd == SIOCSIWRATE) || (cmd == SIOCSIWENCODE))
3248     			readCapabilityRid(local, &cap_rid);
3249     		/* Get config in all cases, because SET will just modify it */
3250     		readConfigRid(local, &config);
3251     	}
3252     #endif /* WIRELESS_EXT */
3253     
3254     	switch (cmd) {
3255     #ifdef WIRELESS_EXT
3256     		// Get name
3257     	case SIOCGIWNAME:
3258     		strcpy(wrq->u.name, "IEEE 802.11-DS");
3259     		break;
3260     
3261     		// Set frequency/channel
3262     	case SIOCSIWFREQ:
3263     		/* If setting by frequency, convert to a channel */
3264     		if((wrq->u.freq.e == 1) &&
3265     		   (wrq->u.freq.m >= (int) 2.412e8) &&
3266     		   (wrq->u.freq.m <= (int) 2.487e8)) {
3267     			int f = wrq->u.freq.m / 100000;
3268     			int c = 0;
3269     			while((c < 14) && (f != frequency_list[c]))
3270     				c++;
3271     			/* Hack to fall through... */
3272     			wrq->u.freq.e = 0;
3273     			wrq->u.freq.m = c + 1;
3274     		}
3275     		/* Setting by channel number */
3276     		if((wrq->u.freq.m > 1000) || (wrq->u.freq.e > 0))
3277     			rc = -EOPNOTSUPP;
3278     		else {
3279     			int channel = wrq->u.freq.m;
3280     			/* We should do a better check than that,
3281     			 * based on the card capability !!! */
3282     			if((channel < 1) || (channel > 16)) {
3283     				printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, wrq->u.freq.m);
3284     				rc = -EINVAL;
3285     			} else {
3286     				/* Yes ! We can set it !!! */
3287     				config.channelSet = (u16)(channel - 1);
3288     				local->need_commit = 1;
3289     			}
3290     		}
3291     		break;
3292     
3293     		// Get frequency/channel
3294     	case SIOCGIWFREQ:
3295     #ifdef WEXT_USECHANNELS
3296     		wrq->u.freq.m = ((int)status_rid.channel) + 1;
3297     		wrq->u.freq.e = 0;
3298     #else
3299     		{
3300     			int f = (int)status_rid.channel;
3301     			wrq->u.freq.m = frequency_list[f] * 100000;
3302     			wrq->u.freq.e = 1;
3303     		}
3304     #endif
3305     		break;
3306     
3307     		// Set desired network name (ESSID)
3308     	case SIOCSIWESSID:
3309     		if (wrq->u.data.pointer) {
3310     			char	essid[IW_ESSID_MAX_SIZE + 1];
3311     			SsidRid SSID_rid;		/* SSIDs */
3312     
3313     			/* Reload the list of current SSID */
3314     			readSsidRid(local, &SSID_rid);
3315     
3316     			/* Check if we asked for `any' */
3317     			if(wrq->u.data.flags == 0) {
3318     				/* Just send an empty SSID list */
3319     				memset(&SSID_rid, 0, sizeof(SSID_rid));
3320     			} else {
3321     				int	index = (wrq->u.data.flags &
3322     						 IW_ENCODE_INDEX) - 1;
3323     
3324     				/* Check the size of the string */
3325     				if(wrq->u.data.length > IW_ESSID_MAX_SIZE+1) {
3326     					rc = -E2BIG;
3327     					break;
3328     				}
3329     				/* Check if index is valid */
3330     				if((index < 0) || (index >= 4)) {
3331     					rc = -EINVAL;
3332     					break;
3333     				}
3334     
3335     				/* Set the SSID */
3336     				memset(essid, 0, sizeof(essid));
3337     				if (copy_from_user(essid,
3338     					       wrq->u.data.pointer,
3339     					       wrq->u.data.length)) {
3340     					rc = -EFAULT;
3341     					break;
3342     				}
3343     				memcpy(SSID_rid.ssids[index].ssid, essid,
3344     				       sizeof(essid) - 1);
3345     				SSID_rid.ssids[index].len = wrq->u.data.length - 1;
3346     			}
3347     			/* Write it to the card */
3348     			writeSsidRid(local, &SSID_rid);
3349     		}
3350     		break;
3351     
3352     		// Get current network name (ESSID)
3353     	case SIOCGIWESSID:
3354     		if (wrq->u.data.pointer) {
3355     			char essid[IW_ESSID_MAX_SIZE + 1];
3356     
3357     			/* Note : if wrq->u.data.flags != 0, we should
3358     			 * get the relevant SSID from the SSID list... */
3359     
3360     			/* Get the current SSID */
3361     			memcpy(essid, status_rid.SSID, status_rid.SSIDlen);
3362     			essid[status_rid.SSIDlen] = '\0';
3363     			/* If none, we may want to get the one that was set */
3364     
3365     			/* Push it out ! */
3366     			wrq->u.data.length = strlen(essid) + 1;
3367     			wrq->u.data.flags = 1; /* active */
3368     			if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)))
3369     				rc = -EFAULT;
3370     		}
3371     		break;
3372     
3373     	case SIOCSIWAP:
3374     		if (wrq->u.ap_addr.sa_family != ARPHRD_ETHER)
3375     			rc = -EINVAL;
3376     		else {
3377     			APListRid APList_rid;
3378     
3379     			memset(&APList_rid, 0, sizeof(APList_rid));
3380     			APList_rid.len = sizeof(APList_rid);
3381     			memcpy(APList_rid.ap[0], wrq->u.ap_addr.sa_data, 6);
3382     			writeAPListRid(local, &APList_rid);
3383     			local->need_commit = 1;
3384     		}
3385     		break;
3386     
3387     		// Get current Access Point (BSSID)
3388     	case SIOCGIWAP:
3389     		/* Tentative. This seems to work, wow, I'm lucky !!! */
3390     		memcpy(wrq->u.ap_addr.sa_data, status_rid.bssid[0], 6);
3391     		wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
3392     		break;
3393     
3394     		// Set desired station name
3395     	case SIOCSIWNICKN:
3396     		if (wrq->u.data.pointer) {
3397     			char	name[16 + 1];
3398     
3399     			/* Check the size of the string */
3400     			if(wrq->u.data.length > 16 + 1) {
3401     				rc = -E2BIG;
3402     				break;
3403     			}
3404     			memset(name, 0, sizeof(name));
3405     			if (copy_from_user(name, wrq->u.data.pointer,
3406     					   wrq->u.data.length)) {
3407     				rc = -EFAULT;
3408     				break;
3409     			}
3410     			memcpy(config.nodeName, name, 16);
3411     			local->need_commit = 1;
3412     		}
3413     		break;
3414     
3415     		// Get current station name
3416     	case SIOCGIWNICKN:
3417     		if (wrq->u.data.pointer) {
3418     			char name[IW_ESSID_MAX_SIZE + 1];
3419     
3420     			strncpy(name, config.nodeName, 16);
3421     			name[16] = '\0';
3422     			wrq->u.data.length = strlen(name) + 1;
3423     			if (copy_to_user(wrq->u.data.pointer, name, sizeof(name)))
3424     				rc = -EFAULT;
3425     		}
3426     		break;
3427     
3428     		// Set the desired bit-rate
3429     	case SIOCSIWRATE:
3430     	{
3431     		/* First : get a valid bit rate value */
3432     		u8	brate = 0;
3433     		int	i;
3434     
3435     		/* Which type of value ? */
3436     		if((wrq->u.bitrate.value < 8) &&
3437     		   (wrq->u.bitrate.value >= 0)) {
3438     			/* Setting by rate index */
3439     			/* Find value in the magic rate table */
3440     			brate = cap_rid.supportedRates[wrq->u.bitrate.value];
3441     		} else {
3442     			/* Setting by frequency value */
3443     			u8	normvalue = (u8) (wrq->u.bitrate.value/500000);
3444     
3445     			/* Check if rate is valid */
3446     			for(i = 0 ; i < 8 ; i++) {
3447     				if(normvalue == cap_rid.supportedRates[i]) {
3448     					brate = normvalue;
3449     					break;
3450     				}
3451     			}
3452     		}
3453     		/* -1 designed the max rate (mostly auto mode) */
3454     		if(wrq->u.bitrate.value == -1) {
3455     			/* Get the highest available rate */
3456     			for(i = 0 ; i < 8 ; i++) {
3457     				if(cap_rid.supportedRates[i] == 0)
3458     					break;
3459     			}
3460     			if(i != 0)
3461     				brate = cap_rid.supportedRates[i - 1];
3462     		}
3463     		/* Check that it is valid */
3464     		if(brate == 0) {
3465     			rc = -EINVAL;
3466     			break;
3467     		}
3468     
3469     		/* Now, check if we want a fixed or auto value */
3470     		if(wrq->u.bitrate.fixed == 0) {
3471     			/* Fill all the rates up to this max rate */
3472     			memset(config.rates, 0, 8);
3473     			for(i = 0 ; i < 8 ; i++) {
3474     				config.rates[i] = cap_rid.supportedRates[i];
3475     				if(config.rates[i] == brate)
3476     					break;
3477     			}
3478     			local->need_commit = 1;
3479     		} else {
3480     			/* Fixed mode */
3481     			/* One rate, fixed */
3482     			memset(config.rates, 0, 8);
3483     			config.rates[0] = brate;
3484     			local->need_commit = 1;
3485     		}
3486     		break;
3487     	}
3488     
3489     	// Get the current bit-rate
3490     	case SIOCGIWRATE:
3491     	{
3492     		int brate = status_rid.currentXmitRate;
3493     		wrq->u.bitrate.value = brate * 500000;
3494     		/* If more than one rate, set auto */
3495     		wrq->u.rts.fixed = (config.rates[1] == 0);
3496     	}
3497     	break;
3498     
3499     	// Set the desired RTS threshold
3500     	case SIOCSIWRTS:
3501     	{
3502     		int rthr = wrq->u.rts.value;
3503     		if(wrq->u.rts.disabled)
3504     			rthr = 2312;
3505     		if((rthr < 0) || (rthr > 2312)) {
3506     			rc = -EINVAL;
3507     		} else {
3508     			config.rtsThres = rthr;
3509     			local->need_commit = 1;
3510     		}
3511     	}
3512     	break;
3513     
3514     	// Get the current RTS threshold
3515     	case SIOCGIWRTS:
3516     		wrq->u.rts.value = config.rtsThres;
3517     		wrq->u.rts.disabled = (wrq->u.rts.value >= 2312);
3518     		wrq->u.rts.fixed = 1;
3519     		break;
3520     
3521     		// Set the desired fragmentation threshold
3522     	case SIOCSIWFRAG:
3523     	{
3524     		int fthr = wrq->u.frag.value;
3525     		if(wrq->u.frag.disabled)
3526     			fthr = 2312;
3527     		if((fthr < 256) || (fthr > 2312)) {
3528     			rc = -EINVAL;
3529     		} else {
3530     			fthr &= ~0x1;	/* Get an even value */
3531     			config.fragThresh = (u16)fthr;
3532     			local->need_commit = 1;
3533     		}
3534     	}
3535     	break;
3536     
3537     	// Get the current fragmentation threshold
3538     	case SIOCGIWFRAG:
3539     		wrq->u.frag.value = config.fragThresh;
3540     		wrq->u.frag.disabled = (wrq->u.frag.value >= 2312);
3541     		wrq->u.frag.fixed = 1;
3542     		break;
3543     
3544     		// Set mode of operation
3545     	case SIOCSIWMODE:
3546     		switch(wrq->u.mode) {
3547     		case IW_MODE_ADHOC:
3548     			config.opmode = MODE_STA_IBSS;
3549     			local->need_commit = 1;
3550     			break;
3551     		case IW_MODE_INFRA:
3552     			config.opmode = MODE_STA_ESS;
3553     			local->need_commit = 1;
3554     			break;
3555     		case IW_MODE_MASTER:
3556     			config.opmode = MODE_AP;
3557     			local->need_commit = 1;
3558     			break;
3559     		case IW_MODE_REPEAT:
3560     			config.opmode = MODE_AP_RPTR;
3561     			local->need_commit = 1;
3562     			break;
3563     		default:
3564     			rc = -EINVAL;
3565     		}
3566     		break;
3567     
3568     		// Get mode of operation
3569     	case SIOCGIWMODE:
3570     		/* If not managed, assume it's ad-hoc */
3571     		switch (config.opmode & 0xFF) {
3572     		case MODE_STA_ESS:
3573     			wrq->u.mode = IW_MODE_INFRA;
3574     			break;
3575     		case MODE_AP:
3576     			wrq->u.mode = IW_MODE_MASTER;
3577     			break;
3578     		case MODE_AP_RPTR:
3579     			wrq->u.mode = IW_MODE_REPEAT;
3580     			break;
3581     		default:
3582     			wrq->u.mode = IW_MODE_ADHOC;
3583     		}
3584     		break;
3585     
3586     		// Set WEP keys and mode
3587     	case SIOCSIWENCODE:
3588     		/* Is WEP supported ? */
3589     		/* Older firmware doesn't support this...
3590     		if(!(cap_rid.softCap & 2)) {
3591     			rc = -EOPNOTSUPP;
3592     			break;
3593     		} */
3594     		/* Basic checking: do we have a key to set ? */
3595     		if (wrq->u.encoding.pointer != (caddr_t) 0) {
3596     			wep_key_t key;
3597     			int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
3598     			int current_index = get_wep_key(local, 0xffff);
3599     			/* Check the size of the key */
3600     			if (wrq->u.encoding.length > MAX_KEY_SIZE) {
3601     				rc = -EINVAL;
3602     				break;
3603     			}
3604     			/* Check the index (none -> use current) */
3605     			if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1))
3606     				index = current_index;
3607     			/* Set the length */
3608     			if (wrq->u.encoding.length > MIN_KEY_SIZE)
3609     				key.len = MAX_KEY_SIZE;
3610     			else
3611     				if (wrq->u.encoding.length > 0)
3612     					key.len = MIN_KEY_SIZE;
3613     				else
3614     					/* Disable the key */
3615     					key.len = 0;
3616     			/* Check if the key is not marked as invalid */
3617     			if(!(wrq->u.encoding.flags & IW_ENCODE_NOKEY)) {
3618     				/* Cleanup */
3619     				memset(key.key, 0, MAX_KEY_SIZE);
3620     				/* Copy the key in the driver */
3621     				if(copy_from_user(key.key,
3622     						  wrq->u.encoding.pointer,
3623     						  wrq->u.encoding.length)) {
3624     					key.len = 0;
3625     					rc = -EFAULT;
3626     					break;
3627     				}
3628     				/* Send the key to the card */
3629     				set_wep_key(local, index, key.key,
3630     					    key.len, 1);
3631     			}
3632     			/* WE specify that if a valid key is set, encryption
3633     			 * should be enabled (user may turn it off later)
3634     			 * This is also how "iwconfig ethX key on" works */
3635     			if((index == current_index) && (key.len > 0) &&
3636     			   (config.authType == AUTH_OPEN)) {
3637     				config.authType = AUTH_ENCRYPT;
3638     				local->need_commit = 1;
3639     			}
3640     		} else {
3641     			/* Do we want to just set the transmit key index ? */
3642     			int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
3643     			if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) {
3644     				set_wep_key(local, index, 0, 0, 1);
3645     			} else
3646     				/* Don't complain if only change the mode */
3647     				if(!wrq->u.encoding.flags & IW_ENCODE_MODE) {
3648     					rc = -EINVAL;
3649     					break;
3650     				}
3651     		}
3652     		/* Read the flags */
3653     		if(wrq->u.encoding.flags & IW_ENCODE_DISABLED)
3654     			config.authType = AUTH_OPEN;	// disable encryption
3655     		if(wrq->u.encoding.flags & IW_ENCODE_RESTRICTED)
3656     			config.authType = AUTH_SHAREDKEY;	// Only Both
3657     		if(wrq->u.encoding.flags & IW_ENCODE_OPEN)
3658     			config.authType = AUTH_ENCRYPT;	// Only Wep
3659     		/* Commit the changes if needed */
3660     		if(wrq->u.encoding.flags & IW_ENCODE_MODE)
3661     			local->need_commit = 1;
3662     		break;
3663     
3664     		// Get the WEP keys and mode
3665     	case SIOCGIWENCODE:
3666     		/* Is it supported ? */
3667     		if(!(cap_rid.softCap & 2)) {
3668     			rc = -EOPNOTSUPP;
3669     			break;
3670     		}
3671     		// Only super-user can see WEP key
3672     		if (!capable(CAP_NET_ADMIN)) {
3673     			rc = -EPERM;
3674     			break;
3675     		}
3676     
3677     		// Basic checking...
3678     		if (wrq->u.encoding.pointer != (caddr_t) 0) {
3679     			char zeros[16];
3680     			int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
3681     
3682     			memset(zeros,0, sizeof(zeros));
3683     			/* Check encryption mode */
3684     			wrq->u.encoding.flags = IW_ENCODE_NOKEY;
3685     			/* Is WEP enabled ??? */
3686     			switch(config.authType)	{
3687     			case AUTH_ENCRYPT:
3688     				wrq->u.encoding.flags |= IW_ENCODE_OPEN;
3689     				break;
3690     			case AUTH_SHAREDKEY:
3691     				wrq->u.encoding.flags |= IW_ENCODE_RESTRICTED;
3692     				break;
3693     			default:
3694     			case AUTH_OPEN:
3695     				wrq->u.encoding.flags |= IW_ENCODE_DISABLED;
3696     				break;
3697     			}
3698     
3699     			/* Which key do we want ? -1 -> tx index */
3700     			if((index < 0) || (index >= (cap_rid.softCap&0x80)?4:1))
3701     				index = get_wep_key(local, 0xffff);
3702     			wrq->u.encoding.flags |= index + 1;
3703     			/* Copy the key to the user buffer */
3704     			wrq->u.encoding.length = get_wep_key(local, index);
3705     			if (wrq->u.encoding.length > 16) {
3706     				wrq->u.encoding.length=0;
3707     			}
3708     
3709     			if(copy_to_user(wrq->u.encoding.pointer, zeros,
3710     					wrq->u.encoding.length))
3711     				rc = -EFAULT;
3712     		}
3713     		break;
3714     
3715     #if WIRELESS_EXT > 9
3716     		// Get the current Tx-Power
3717     	case SIOCGIWTXPOW:
3718     		wrq->u.txpower.value = config.txPower;
3719     		wrq->u.txpower.fixed = 1;	/* No power control */
3720     		wrq->u.txpower.disabled = (local->flags & FLAG_RADIO_OFF);
3721     		wrq->u.txpower.flags = IW_TXPOW_MWATT;
3722     		break;
3723     	case SIOCSIWTXPOW:
3724     		if (wrq->u.txpower.disabled) {
3725     			local->flags |= FLAG_RADIO_OFF;
3726     			local->need_commit = 1;
3727     			break;
3728     		}
3729     		if (wrq->u.txpower.flags != IW_TXPOW_MWATT) {
3730     			rc = -EINVAL;
3731     			break;
3732     		}
3733     		local->flags &= ~FLAG_RADIO_OFF;
3734     		rc = -EINVAL;
3735     		for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
3736     			if ((wrq->u.txpower.value==cap_rid.txPowerLevels[i])) {
3737     				config.txPower = wrq->u.txpower.value;
3738     				local->need_commit = 1;
3739     				rc = 0;
3740     				break;
3741     			}
3742     		break;
3743     #endif /* WIRELESS_EXT > 9 */
3744     
3745     #if WIRELESS_EXT > 10
3746     	case SIOCSIWRETRY:
3747     		if(wrq->u.retry.disabled) {
3748     			rc = -EINVAL;
3749     			break;
3750     		}
3751     		local->need_commit = 0;
3752     		if(wrq->u.retry.flags & IW_RETRY_LIMIT) {
3753     			if(wrq->u.retry.flags & IW_RETRY_MAX)
3754     				config.longRetryLimit = wrq->u.retry.value;
3755     			else if (wrq->u.retry.flags & IW_RETRY_MIN)
3756     				config.shortRetryLimit = wrq->u.retry.value;
3757     			else {
3758     				/* No modifier : set both */
3759     				config.longRetryLimit = wrq->u.retry.value;
3760     				config.shortRetryLimit = wrq->u.retry.value;
3761     			}
3762     			local->need_commit = 1;
3763     		}
3764     		if(wrq->u.retry.flags & IW_RETRY_LIFETIME) {
3765     			config.txLifetime = wrq->u.retry.value / 1024;
3766     			local->need_commit = 1;
3767     		}
3768     		if(local->need_commit == 0) {
3769     			rc = -EINVAL;
3770     		}
3771     		break;
3772     
3773     	case SIOCGIWRETRY:
3774     		wrq->u.retry.disabled = 0;      /* Can't be disabled */
3775     
3776     		/* Note : by default, display the min retry number */
3777     		if((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
3778     			wrq->u.retry.flags = IW_RETRY_LIFETIME;
3779     			wrq->u.retry.value = (int)config.txLifetime * 1024;
3780     		} else if((wrq->u.retry.flags & IW_RETRY_MAX)) {
3781     			wrq->u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
3782     			wrq->u.retry.value = (int)config.longRetryLimit;
3783     		} else {
3784     			wrq->u.retry.flags = IW_RETRY_LIMIT;
3785     			wrq->u.retry.value = (int)config.shortRetryLimit;
3786     			if((int)config.shortRetryLimit != (int)config.longRetryLimit)
3787     				wrq->u.retry.flags |= IW_RETRY_MIN;
3788     		}
3789     
3790     		break;
3791     #endif /* WIRELESS_EXT > 10 */
3792     
3793     		// Get range of parameters
3794     	case SIOCGIWRANGE:
3795     		if (wrq->u.data.pointer) {
3796     			struct iw_range range;
3797     			int		i;
3798     			int		k;
3799     
3800     			wrq->u.data.length = sizeof(range);
3801     			memset(&range, 0, sizeof(range));
3802     			range.min_nwid = 0x0000;
3803     			range.max_nwid = 0x0000;
3804     			range.num_channels = 14;
3805     			/* Should be based on cap_rid.country to give only
3806     			 * what the current card support */
3807     			k = 0;
3808     			for(i = 0; i < 14; i++) {
3809     				range.freq[k].i = i + 1; /* List index */
3810     				range.freq[k].m = frequency_list[i] * 100000;
3811     				range.freq[k++].e = 1;	/* Values in table in MHz -> * 10^5 * 10 */
3812     			}
3813     			range.num_frequency = k;
3814     
3815     			/* Hum... Should put the right values there */
3816     			range.max_qual.qual = 10;
3817     			range.max_qual.level = 100;
3818     			range.max_qual.noise = 0;
3819     			range.sensitivity = 65535;
3820     
3821     			for(i = 0 ; i < 8 ; i++) {
3822     				range.bitrate[i] = cap_rid.supportedRates[i] * 500000;
3823     				if(range.bitrate[i] == 0)
3824     					break;
3825     			}
3826     			range.num_bitrates = i;
3827     
3828     			/* Set an indication of the max TCP throughput
3829     			 * in bit/s that we can expect using this interface.
3830     			 * May be use for QoS stuff... Jean II */
3831     			if(i > 2)
3832     				range.throughput = 5 * 1000 * 1000;
3833     			else
3834     				range.throughput = 1.5 * 1000 * 1000;
3835     
3836     			range.min_rts = 0;
3837     			range.max_rts = 2312;
3838     			range.min_frag = 256;
3839     			range.max_frag = 2312;
3840     
3841     			if(cap_rid.softCap & 2) {
3842     				// WEP: RC4 40 bits
3843     				range.encoding_size[0] = 5;
3844     				// RC4 ~128 bits
3845     				if (cap_rid.softCap & 0x100) {
3846     					range.encoding_size[1] = 13;
3847     					range.num_encoding_sizes = 2;
3848     				} else
3849     					range.num_encoding_sizes = 1;
3850     				range.max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
3851     			} else {
3852     				range.num_encoding_sizes = 0;
3853     				range.max_encoding_tokens = 0;
3854     			}
3855     #if WIRELESS_EXT > 9
3856     			range.min_pmp = 0;
3857     			range.max_pmp = 5000000;	/* 5 secs */
3858     			range.min_pmt = 0;
3859     			range.max_pmt = 65535 * 1024;	/* ??? */
3860     			range.pmp_flags = IW_POWER_PERIOD;
3861     			range.pmt_flags = IW_POWER_TIMEOUT;
3862     			range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
3863     
3864     			/* Transmit Power - values are in mW */
3865     			for(i = 0 ; i < 8 ; i++) {
3866     				range.txpower[i] = cap_rid.txPowerLevels[i];
3867     				if(range.txpower[i] == 0)
3868     					break;
3869     			}
3870     			range.num_txpower = i;
3871     			range.txpower_capa = IW_TXPOW_MWATT;
3872     #endif /* WIRELESS_EXT > 9 */
3873     #if WIRELESS_EXT > 10
3874     			range.we_version_source = 11;
3875     			range.we_version_compiled = WIRELESS_EXT;
3876     			range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
3877     			range.retry_flags = IW_RETRY_LIMIT;
3878     			range.r_time_flags = IW_RETRY_LIFETIME;
3879     			range.min_retry = 1;
3880     			range.max_retry = 65535;
3881     			range.min_r_time = 1024;
3882     			range.max_r_time = 65535 * 1024;
3883     #endif /* WIRELESS_EXT > 10 */
3884     
3885     			if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
3886     				rc = -EFAULT;
3887     		}
3888     		break;
3889     
3890     	case SIOCGIWPOWER:
3891     	{
3892     		int mode = config.powerSaveMode;
3893     		if ((wrq->u.power.disabled = (mode == POWERSAVE_CAM)))
3894     			break;
3895     		if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3896     			wrq->u.power.value = (int)config.fastListenDelay * 1024;
3897     			wrq->u.power.flags = IW_POWER_TIMEOUT;
3898     		} else {
3899     			wrq->u.power.value = (int)config.fastListenInterval * 1024;
3900     			wrq->u.power.flags = IW_POWER_PERIOD;
3901     		}
3902     		if ((config.rmode & 0xFF) == RXMODE_ADDR)
3903     			wrq->u.power.flags |= IW_POWER_UNICAST_R;
3904     		else
3905     			wrq->u.power.flags |= IW_POWER_ALL_R;
3906     	}
3907     	break;
3908     
3909     	case SIOCSIWPOWER: 
3910     		if (wrq->u.power.disabled) {
3911     			if ((config.rmode & 0xFF) >= RXMODE_RFMON) {
3912     				rc = -EINVAL;
3913     				break;
3914     			}
3915     			config.powerSaveMode = POWERSAVE_CAM;
3916     			config.rmode &= 0xFF00;
3917     			config.rmode |= RXMODE_BC_MC_ADDR;
3918     			local->need_commit = 1;
3919     			break;
3920     		}
3921     		if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3922     			config.fastListenDelay = (wrq->u.power.value + 500) / 1024;
3923     			config.powerSaveMode = POWERSAVE_PSPCAM;
3924     			local->need_commit = 1;
3925     		} else if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
3926     			config.fastListenInterval = config.listenInterval = (wrq->u.power.value + 500) / 1024;
3927     			config.powerSaveMode = POWERSAVE_PSPCAM;
3928     			local->need_commit = 1;
3929     		}
3930     		switch (wrq->u.power.flags & IW_POWER_MODE) {
3931     		case IW_POWER_UNICAST_R:
3932     			if ((config.rmode & 0xFF) >= RXMODE_RFMON) {
3933     				rc = -EINVAL;
3934     				break;
3935     			}
3936     			config.rmode &= 0xFF00;
3937     			config.rmode |= RXMODE_ADDR;
3938     			local->need_commit = 1;
3939     			break;
3940     		case IW_POWER_ALL_R:
3941     			if ((config.rmode & 0xFF) >= RXMODE_RFMON) {
3942     				rc = -EINVAL;
3943     				break;
3944     			}
3945     			config.rmode &= 0xFF00;
3946     			config.rmode |= RXMODE_BC_MC_ADDR;
3947     			local->need_commit = 1;
3948     		case IW_POWER_ON:
3949     			break;
3950     		default:
3951     			rc = -EINVAL;
3952     		}
3953     		break;
3954     
3955     	case SIOCGIWSENS:
3956     		wrq->u.sens.value = config.rssiThreshold;
3957     		wrq->u.sens.disabled = (wrq->u.sens.value == 0);
3958     		wrq->u.sens.fixed = 1;
3959     		break;
3960     
3961     	case SIOCSIWSENS:
3962     		config.rssiThreshold = wrq->u.sens.disabled ? RSSI_DEFAULT : wrq->u.sens.value;
3963     		local->need_commit = 1;
3964     		break;
3965     
3966     	case SIOCGIWAPLIST:
3967     		if (wrq->u.data.pointer) {
3968     			int i, rc;
3969     			struct sockaddr s[IW_MAX_AP];
3970     			struct iw_quality qual[IW_MAX_AP];
3971     			BSSListRid BSSList;
3972     			int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
3973     			for (i = 0; i < IW_MAX_AP; i++) {
3974     				if (readBSSListRid(local, loseSync, &BSSList))
3975     					break;
3976     				loseSync = 0;
3977     				memcpy(s[i].sa_data, BSSList.bssid, 6);
3978     				s[i].sa_family = ARPHRD_ETHER;
3979     				qual[i].level = BSSList.rssi;
3980     				qual[i].qual = qual[i].noise = 0;
3981     				qual[i].updated = 2;
3982     				if (BSSList.index == 0xffff) break;
3983     			}
3984     			if (!i) {
3985     				for (i = 0; 
3986     				     i < min(IW_MAX_AP, 4) &&
3987     					     (status_rid.bssid[i][0]
3988     					      & status_rid.bssid[i][1]
3989     					      & status_rid.bssid[i][2]
3990     					      & status_rid.bssid[i][3]
3991     					      & status_rid.bssid[i][4]
3992     					      & status_rid.bssid[i][5])!=-1 &&
3993     					     (status_rid.bssid[i][0]
3994     					      | status_rid.bssid[i][1]
3995     					      | status_rid.bssid[i][2]
3996     					      | status_rid.bssid[i][3]
3997     					      | status_rid.bssid[i][4]
3998     					      | status_rid.bssid[i][5]);
3999     				     i++) {
4000     					memcpy(s[i].sa_data, 
4001     					       status_rid.bssid[i], 6);
4002     					s[i].sa_family = ARPHRD_ETHER;
4003     				}
4004     			} else {
4005     				wrq->u.data.flags = 1; /* Should be define'd */
4006     				if (copy_to_user(wrq->u.data.pointer
4007     						 + sizeof(struct sockaddr)*i,
4008     						 &qual,
4009     						 sizeof(struct iw_quality)*i))
4010     					rc = -EFAULT;
4011     			}
4012     			wrq->u.data.length = i;
4013     			if (copy_to_user(wrq->u.data.pointer, &s, 
4014     					 sizeof(struct sockaddr)*i))
4015     				rc = -EFAULT;
4016     		}
4017     		break;
4018     
4019     #ifdef WIRELESS_SPY
4020     		// Set the spy list
4021     	case SIOCSIWSPY:
4022     		if (wrq->u.data.length > IW_MAX_SPY)
4023     		{
4024     			rc = -E2BIG;
4025     			break;
4026     		}
4027     		local->spy_number = wrq->u.data.length;
4028     		if (local->spy_number > 0)
4029     		{
4030     			struct sockaddr address[IW_MAX_SPY];
4031     			int i;
4032     
4033     			if (copy_from_user(address, wrq->u.data.pointer,
4034     					   sizeof(struct sockaddr) * local->spy_number)) {
4035     				rc = -EFAULT;
4036     				break;
4037     			}
4038     			for (i=0; i<local->spy_number; i++)
4039     				memcpy(local->spy_address[i], address[i].sa_data, 6);
4040     			memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
4041     		}
4042     		break;
4043     
4044     		// Get the spy list
4045     	case SIOCGIWSPY:
4046     		wrq->u.data.length = local->spy_number;
4047     		if ((local->spy_number > 0) && (wrq->u.data.pointer))
4048     		{
4049     			struct sockaddr address[IW_MAX_SPY];
4050     			int i;
4051     			rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(struct iw_quality)+sizeof(struct sockaddr)) * IW_MAX_SPY);
4052     			if (rc)
4053     				break;
4054     			for (i=0; i<local->spy_number; i++)
4055     			{
4056     				memcpy(address[i].sa_data, local->spy_address[i], 6);
4057     				address[i].sa_family = AF_UNIX;
4058     			}
4059     			if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number)) {
4060     				rc = -EFAULT;
4061     				break;
4062     			}
4063     			if (copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number)) {
4064     				rc = -EFAULT;
4065     				break;
4066     			}
4067     			for (i=0; i<local->spy_number; i++)
4068     				local->spy_stat[i].updated = 0;
4069     		}
4070     		break;
4071     #endif /* WIRELESS_SPY */
4072     
4073     #ifdef CISCO_EXT
4074     	case SIOCGIWPRIV:
4075     		if(wrq->u.data.pointer)
4076     		{
4077     			struct iw_priv_args   priv[] =
4078     			{ /* cmd, set_args, get_args, name */
4079     				{ AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), IW_PRIV_TYPE_BYTE | 2047, "airoioctl" },
4080     				{ AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" },
4081     			};
4082     
4083     			/* Set the number of ioctl available */
4084     			wrq->u.data.length = 2;
4085     
4086     			/* Copy structure to the user buffer */
4087     			if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
4088     					sizeof(priv)))
4089     				rc = -EFAULT;
4090     		}
4091     		break;
4092     #endif /* CISCO_EXT */
4093     #endif /* WIRELESS_EXT */
4094     
4095     #ifdef CISCO_EXT
4096     	case AIROIDIFC:
4097     	{
4098     		int val = AIROMAGIC;
4099     		aironet_ioctl com;
4100     		if (copy_from_user(&com,rq->ifr_data,sizeof(com)))
4101     			rc = -EFAULT;
4102     		else if (copy_to_user(com.data,(char *)&val,sizeof(val)))
4103     			rc = -EFAULT;
4104     	}
4105     	break;
4106       
4107     	case AIROIOCTL:
4108     		/* Get the command struct and hand it off for evaluation by 
4109     		 * the proper subfunction
4110     		 */
4111     	{
4112     		aironet_ioctl com;
4113     		if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
4114     			rc = -EFAULT;
4115     			break;
4116     		}
4117     
4118     		/* Seperate R/W functions bracket legality here
4119     		 */
4120     		if ( com.command <= AIROGSTATSD32 )
4121     			rc = readrids(dev,&com);
4122     		else if ( com.command >= AIROPCAP && com.command <= AIROPLEAPUSR )
4123     			rc = writerids(dev,&com);
4124     		else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART )
4125     			rc = flashcard(dev,&com);
4126     		else
4127     			rc = -EINVAL;      /* Bad command in ioctl */
4128     	}
4129     	break;
4130     #endif /* CISCO_EXT */
4131     
4132     	// All other calls are currently unsupported
4133     	default:
4134     		rc = -EOPNOTSUPP;
4135     	}
4136     
4137     #ifdef WIRELESS_EXT
4138     	/* Some of the "SET" function may have modified some of the
4139     	 * parameters. It's now time to commit them in the card */
4140     	if(local->need_commit) {
4141     		/* A classical optimisation here is to not commit any change
4142     		 * if the card is not "opened". This is what we do in
4143     		 * wvlan_cs (see for details).
4144     		 * For that, we would need to have the config RID saved in
4145     		 * the airo_info struct and make sure to not re-read it if
4146     		 * local->need_commit != 0. Then, you need to patch "open"
4147     		 * to do the final commit of all parameters...
4148     		 * Jean II */
4149     		Resp rsp;
4150     
4151     		disable_MAC(local);
4152     		local->config = config;	/* ???? config is local !!! */
4153     		checkThrottle(&config);
4154     		writeConfigRid(local, &config);
4155     		enable_MAC(local, &rsp);
4156     
4157     		local->need_commit = 0;
4158     	}
4159     #endif /* WIRELESS_EXT */
4160     
4161     	return(rc);
4162     }
4163     
4164     #ifdef WIRELESS_EXT
4165     /*
4166      * Get the Wireless stats out of the driver
4167      * Note : irq and spinlock protection will occur in the subroutines
4168      *
4169      * TODO :
4170      *	o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
4171      *	o Find the noise level
4172      *	o Convert values to dBm
4173      *	o Fill out discard.misc with something interesting
4174      *
4175      * Jean
4176      */
4177     struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
4178     {
4179     	struct airo_info *local = (struct airo_info*) dev->priv;
4180     	StatusRid status_rid;
4181     	StatsRid stats_rid;
4182     	int *vals = stats_rid.vals;
4183     
4184     	/* Get stats out of the card */
4185     	readStatusRid(local, &status_rid);
4186     	readStatsRid(local, &stats_rid, RID_STATS);
4187     
4188     	/* The status */
4189     	local->wstats.status = status_rid.mode;
4190     
4191     	/* Signal quality and co. But where is the noise level ??? */
4192     	local->wstats.qual.qual = status_rid.signalQuality;
4193     	local->wstats.qual.level = status_rid.normalizedSignalStrength;
4194     	local->wstats.qual.noise = 0;
4195     	local->wstats.qual.updated = 3;
4196     
4197     	/* Packets discarded in the wireless adapter due to wireless
4198     	 * specific problems */
4199     	local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */
4200     	local->wstats.discard.code = vals[6];/* RxWepErr */
4201     	local->wstats.discard.misc = vals[1] + vals[2] + vals[3] + vals[4] + vals[30] + vals[32];
4202     	return (&local->wstats);
4203     }
4204     #endif /* WIRELESS_EXT */
4205     
4206     #ifdef CISCO_EXT
4207     /*
4208      * This just translates from driver IOCTL codes to the command codes to 
4209      * feed to the radio's host interface. Things can be added/deleted 
4210      * as needed.  This represents the READ side of control I/O to 
4211      * the card
4212      */
4213     static int readrids(struct net_device *dev, aironet_ioctl *comp) {
4214     	unsigned short ridcode;
4215     	unsigned char iobuf[2048]; 
4216     
4217     	switch(comp->command)
4218     	{
4219     	case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
4220     	case AIROGCFG:      ridcode = RID_CONFIG;       break;
4221     	case AIROGSLIST:    ridcode = RID_SSID;         break;
4222     	case AIROGVLIST:    ridcode = RID_APLIST;       break;
4223     	case AIROGDRVNAM:   ridcode = RID_DRVNAME;      break;
4224     	case AIROGEHTENC:   ridcode = RID_ETHERENCAP;   break;
4225     	case AIROGWEPKTMP:  ridcode = RID_WEP_TEMP;
4226     		/* Only super-user can read WEP keys */
4227     		if (!capable(CAP_NET_ADMIN))
4228     			return -EPERM;
4229     		break;
4230     	case AIROGWEPKNV:   ridcode = RID_WEP_PERM;
4231     		/* Only super-user can read WEP keys */
4232     		if (!capable(CAP_NET_ADMIN))
4233     			return -EPERM;
4234     		break;
4235     	case AIROGSTAT:     ridcode = RID_STATUS;       break;
4236     	case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
4237     	case AIROGSTATSC32: ridcode = RID_STATS;        break;
4238     	default:
4239     		return -EINVAL;  
4240     		break;
4241     	}
4242     
4243     	PC4500_readrid((struct airo_info *)dev->priv,ridcode,iobuf,sizeof(iobuf));
4244     	/* get the count of bytes in the rid  docs say 1st 2 bytes is it.
4245     	 * then return it to the user 
4246     	 * 9/22/2000 Honor user given length
4247     	 */
4248     
4249     	if (copy_to_user(comp->data, iobuf,
4250     			 min_t(unsigned int, comp->len, sizeof(iobuf))))
4251     		return -EFAULT;
4252     	return 0;
4253     }
4254     
4255     /*
4256      * Danger Will Robinson write the rids here
4257      */
4258     
4259     static int writerids(struct net_device *dev, aironet_ioctl *comp) {
4260     	int  ridcode;
4261     	Resp      rsp;
4262     	static int (* writer)(struct airo_info *, u16 rid, const void *, int);
4263     	unsigned char iobuf[2048]; 
4264     
4265     	/* Only super-user can write RIDs */
4266     	if (!capable(CAP_NET_ADMIN))
4267     		return -EPERM;
4268     
4269     	ridcode = 0;
4270     	writer = do_writerid;
4271     
4272     	switch(comp->command)
4273     	{
4274     	case AIROPSIDS:     ridcode = RID_SSID;         break;
4275     	case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
4276     	case AIROPAPLIST:   ridcode = RID_APLIST;       break;
4277     	case AIROPCFG:      ridcode = RID_CONFIG;       break;
4278     	case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
4279     	case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
4280     	case AIROPLEAPPWD:  ridcode = RID_LEAPPASSWORD; break;
4281     	case AIROPWEPKEY:   ridcode = RID_WEP_TEMP; writer = PC4500_writerid;
4282     		break;
4283     
4284     		/* this is not really a rid but a command given to the card 
4285     		 * same with MAC off
4286     		 */
4287     	case AIROPMACON:
4288     		if (enable_MAC(dev->priv, &rsp) != 0)
4289     			return -EIO;
4290     		return 0;
4291     
4292     		/* 
4293     		 * Evidently this code in the airo driver does not get a symbol
4294     		 * as disable_MAC. it's probably so short the compiler does not gen one.
4295     		 */
4296     	case AIROPMACOFF:
4297     		disable_MAC(dev->priv);
4298     		return 0;
4299     
4300     		/* This command merely clears the counts does not actually store any data
4301     		 * only reads rid. But as it changes the cards state, I put it in the
4302     		 * writerid routines.
4303     		 */
4304     	case AIROPSTCLR:
4305     		ridcode = RID_STATSDELTACLEAR;
4306     
4307     		PC4500_readrid(dev->priv,ridcode,iobuf,sizeof(iobuf));
4308     
4309     		if (copy_to_user(comp->data, iobuf,
4310     				 min_t(unsigned int, comp->len, sizeof(iobuf))))
4311     			return -EFAULT;
4312     		return 0;
4313     
4314     	default:
4315     		return -EOPNOTSUPP;	/* Blarg! */
4316     	}
4317     	if(comp->len > sizeof(iobuf))
4318     		return -EINVAL;
4319     
4320     	if (copy_from_user(iobuf,comp->data,comp->len))
4321     		return -EFAULT;
4322     	if((*writer)((struct airo_info *)dev->priv, ridcode, iobuf,comp->len))
4323     		return -EIO;
4324     	return 0;
4325     }
4326     
4327     /*****************************************************************************
4328      * Ancillary flash / mod functions much black magic lurkes here              *
4329      *****************************************************************************
4330      */
4331     
4332     /* 
4333      * Flash command switch table
4334      */
4335     
4336     int flashcard(struct net_device *dev, aironet_ioctl *comp) {
4337     	int z;
4338     	int cmdreset(struct airo_info *);
4339     	int setflashmode(struct airo_info *);
4340     	int flashgchar(struct airo_info *,int,int);
4341     	int flashpchar(struct airo_info *,int,int);
4342     	int flashputbuf(struct airo_info *);
4343     	int flashrestart(struct airo_info *,struct net_device *);
4344     
4345     	/* Only super-user can modify flash */
4346     	if (!capable(CAP_NET_ADMIN))
4347     		return -EPERM;
4348     
4349     	switch(comp->command)
4350     	{
4351     	case AIROFLSHRST:
4352     		return cmdreset((struct airo_info *)dev->priv);
4353     
4354     	case AIROFLSHSTFL:
4355     		if (!((struct airo_info *)dev->priv)->flash &&
4356     			(((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
4357     			return -ENOMEM;
4358     		return setflashmode((struct airo_info *)dev->priv);
4359     
4360     	case AIROFLSHGCHR: /* Get char from aux */
4361     		if(comp->len != sizeof(int))
4362     			return -EINVAL;
4363     		if (copy_from_user(&z,comp->data,comp->len))
4364     			return -EFAULT;
4365     		return flashgchar((struct airo_info *)dev->priv,z,8000);
4366     
4367     	case AIROFLSHPCHR: /* Send char to card. */
4368     		if(comp->len != sizeof(int))
4369     			return -EINVAL;
4370     		if (copy_from_user(&z,comp->data,comp->len))
4371     			return -EFAULT;
4372     		return flashpchar((struct airo_info *)dev->priv,z,8000);
4373     
4374     	case AIROFLPUTBUF: /* Send 32k to card */
4375     		if (!((struct airo_info *)dev->priv)->flash)
4376     			return -ENOMEM;
4377     		if(comp->len > FLASHSIZE)
4378     			return -EINVAL;
4379     		if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
4380     			return -EFAULT;
4381     
4382     		flashputbuf((struct airo_info *)dev->priv);
4383     		return 0;
4384     
4385     	case AIRORESTART:
4386     		if(flashrestart((struct airo_info *)dev->priv,dev))
4387     			return -EIO;
4388     		return 0;
4389     	}
4390     	return -EINVAL;
4391     }
4392     
4393     #define FLASH_COMMAND  0x7e7e
4394     
4395     /* 
4396      * STEP 1)
4397      * Disable MAC and do soft reset on 
4398      * card. 
4399      */
4400     
4401     int cmdreset(struct airo_info *ai) {
4402     	disable_MAC(ai);
4403     
4404     	if(!waitbusy (ai)){
4405     		printk(KERN_INFO "Waitbusy hang before RESET\n");
4406     		return -EBUSY;
4407     	}
4408         
4409     	OUT4500(ai,COMMAND,CMD_SOFTRESET);
4410     
4411     	set_current_state (TASK_UNINTERRUPTIBLE);
4412     	schedule_timeout (HZ);          /* WAS 600 12/7/00 */
4413     
4414     	if(!waitbusy (ai)){
4415     		printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
4416     		return -EBUSY;
4417     	}
4418     	return 0;
4419     }
4420     
4421     /* STEP 2)
4422      * Put the card in legendary flash 
4423      * mode
4424      */
4425     
4426     int setflashmode (struct airo_info *ai) {
4427     	OUT4500(ai, SWS0, FLASH_COMMAND);
4428     	OUT4500(ai, SWS1, FLASH_COMMAND);
4429     	OUT4500(ai, SWS0, FLASH_COMMAND);
4430     	OUT4500(ai, COMMAND,0x10);
4431     	set_current_state (TASK_UNINTERRUPTIBLE);
4432     	schedule_timeout (HZ/2); /* 500ms delay */
4433       
4434     	if(!waitbusy(ai)) {
4435     		printk(KERN_INFO "Waitbusy hang after setflash mode\n");
4436     		return -EIO;
4437     	}
4438     	return 0;
4439     }
4440     
4441     /* Put character to SWS0 wait for dwelltime 
4442      * x 50us for  echo . 
4443      */
4444     
4445     int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
4446     	int echo;
4447     	int waittime;
4448     
4449     	byte |= 0x8000;
4450     
4451     	if(dwelltime == 0 )
4452     		dwelltime = 200;
4453       
4454     	waittime=dwelltime;
4455     
4456     	/* Wait for busy bit d15 to go false indicating buffer empty */
4457     	while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) {
4458     		udelay (50);
4459     		waittime -= 50;
4460     	}
4461     
4462     	/* timeout for busy clear wait */
4463     	if(waittime <= 0 ){
4464     		printk(KERN_INFO "flash putchar busywait timeout! \n");
4465     		return -EBUSY;
4466     	}
4467     
4468     	/* Port is clear now write byte and wait for it to echo back */
4469     	do {
4470     		OUT4500(ai,SWS0,byte);
4471     		udelay(50);
4472     		dwelltime -= 50;
4473     		echo = IN4500(ai,SWS1);
4474     	} while (dwelltime >= 0 && echo != byte);
4475     
4476     	OUT4500(ai,SWS1,0);
4477     
4478     	return (echo == byte) ? 0 : -EIO;
4479     }
4480     
4481     /*
4482      * Get a character from the card matching matchbyte
4483      * Step 3)
4484      */
4485     int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
4486     	int           rchar;
4487     	unsigned char rbyte=0;
4488     
4489     	do {
4490     		rchar = IN4500(ai,SWS1);
4491         
4492     		if(dwelltime && !(0x8000 & rchar)){
4493     			dwelltime -= 10;
4494     			mdelay(10);
4495     			continue;
4496     		}
4497     		rbyte = 0xff & rchar;
4498     
4499     		if( (rbyte == matchbyte) && (0x8000 & rchar) ){
4500     			OUT4500(ai,SWS1,0);
4501     			return 0;
4502     		}
4503     		if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
4504     			break;
4505     		OUT4500(ai,SWS1,0);
4506     
4507     	}while(dwelltime > 0);
4508     	return -EIO;
4509     }
4510     
4511     /* 
4512      * Transfer 32k of firmware data from user buffer to our buffer and 
4513      * send to the card 
4514      */
4515     
4516     int flashputbuf(struct airo_info *ai){
4517     	int            nwords;
4518     
4519     	/* Write stuff */
4520     	OUT4500(ai,AUXPAGE,0x100);
4521     	OUT4500(ai,AUXOFF,0);
4522     
4523     	for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
4524     		OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
4525     	}
4526       
4527     	OUT4500(ai,SWS0,0x8000);
4528     
4529     	return 0;
4530     }
4531     
4532     /*
4533      *
4534      */
4535     int flashrestart(struct airo_info *ai,struct net_device *dev){
4536     	int    i,status;
4537     
4538     	set_current_state (TASK_UNINTERRUPTIBLE);
4539     	schedule_timeout (HZ);          /* Added 12/7/00 */
4540     	status = setup_card(ai, dev->dev_addr,&((struct airo_info*)dev->priv)->config);
4541     
4542     	for( i = 0; i < MAX_FIDS; i++ ) {
4543     		ai->fids[i] = transmit_allocate( ai, 2312 );
4544     	}
4545     
4546     	set_current_state (TASK_UNINTERRUPTIBLE);
4547     	schedule_timeout (HZ);          /* Added 12/7/00 */
4548     	return status;
4549     }
4550     #endif /* CISCO_EXT */
4551     
4552     /*
4553         This program is free software; you can redistribute it and/or
4554         modify it under the terms of the GNU General Public License
4555         as published by the Free Software Foundation; either version 2
4556         of the License, or (at your option) any later version.
4557     
4558         This program is distributed in the hope that it will be useful,
4559         but WITHOUT ANY WARRANTY; without even the implied warranty of
4560         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4561         GNU General Public License for more details.
4562     
4563         In addition:
4564     
4565         Redistribution and use in source and binary forms, with or without
4566         modification, are permitted provided that the following conditions
4567         are met:
4568     
4569         1. Redistributions of source code must retain the above copyright
4570            notice, this list of conditions and the following disclaimer.
4571         2. Redistributions in binary form must reproduce the above copyright
4572            notice, this list of conditions and the following disclaimer in the
4573            documentation and/or other materials provided with the distribution.
4574         3. The name of the author may not be used to endorse or promote
4575            products derived from this software without specific prior written
4576            permission.
4577     
4578         THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4579         IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4580         WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4581         ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
4582         INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4583         (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
4584         SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4585         HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4586         STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4587         IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4588         POSSIBILITY OF SUCH DAMAGE.    
4589     */
4590     
4591     module_init(airo_init_module);
4592     module_exit(airo_cleanup_module);
4593