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