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