diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-28 16:29:51 -0400 |
commit | ed40d0c472b136682b2fcba05f89762859c7374f (patch) | |
tree | 076b83a26bcd63d6158463735dd34c10bbc591dc /drivers/net/wireless/airo.c | |
parent | 9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff) | |
parent | 5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff) |
Merge branch 'origin' into devel
Conflicts:
sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r-- | drivers/net/wireless/airo.c | 1210 |
1 files changed, 677 insertions, 533 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index fc4322ca669f..7e80aba8a148 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -496,39 +496,41 @@ typedef struct { | |||
496 | * so all rid access should use the read/writeXXXRid routines. | 496 | * so all rid access should use the read/writeXXXRid routines. |
497 | */ | 497 | */ |
498 | 498 | ||
499 | /* This is redundant for x86 archs, but it seems necessary for ARM */ | ||
500 | #pragma pack(1) | ||
501 | |||
502 | /* This structure came from an email sent to me from an engineer at | 499 | /* This structure came from an email sent to me from an engineer at |
503 | aironet for inclusion into this driver */ | 500 | aironet for inclusion into this driver */ |
504 | typedef struct { | 501 | typedef struct WepKeyRid WepKeyRid; |
502 | struct WepKeyRid { | ||
505 | __le16 len; | 503 | __le16 len; |
506 | __le16 kindex; | 504 | __le16 kindex; |
507 | u8 mac[ETH_ALEN]; | 505 | u8 mac[ETH_ALEN]; |
508 | __le16 klen; | 506 | __le16 klen; |
509 | u8 key[16]; | 507 | u8 key[16]; |
510 | } WepKeyRid; | 508 | } __attribute__ ((packed)); |
511 | 509 | ||
512 | /* These structures are from the Aironet's PC4500 Developers Manual */ | 510 | /* These structures are from the Aironet's PC4500 Developers Manual */ |
513 | typedef struct { | 511 | typedef struct Ssid Ssid; |
512 | struct Ssid { | ||
514 | __le16 len; | 513 | __le16 len; |
515 | u8 ssid[32]; | 514 | u8 ssid[32]; |
516 | } Ssid; | 515 | } __attribute__ ((packed)); |
517 | 516 | ||
518 | typedef struct { | 517 | typedef struct SsidRid SsidRid; |
518 | struct SsidRid { | ||
519 | __le16 len; | 519 | __le16 len; |
520 | Ssid ssids[3]; | 520 | Ssid ssids[3]; |
521 | } SsidRid; | 521 | } __attribute__ ((packed)); |
522 | 522 | ||
523 | typedef struct { | 523 | typedef struct ModulationRid ModulationRid; |
524 | struct ModulationRid { | ||
524 | __le16 len; | 525 | __le16 len; |
525 | __le16 modulation; | 526 | __le16 modulation; |
526 | #define MOD_DEFAULT cpu_to_le16(0) | 527 | #define MOD_DEFAULT cpu_to_le16(0) |
527 | #define MOD_CCK cpu_to_le16(1) | 528 | #define MOD_CCK cpu_to_le16(1) |
528 | #define MOD_MOK cpu_to_le16(2) | 529 | #define MOD_MOK cpu_to_le16(2) |
529 | } ModulationRid; | 530 | } __attribute__ ((packed)); |
530 | 531 | ||
531 | typedef struct { | 532 | typedef struct ConfigRid ConfigRid; |
533 | struct ConfigRid { | ||
532 | __le16 len; /* sizeof(ConfigRid) */ | 534 | __le16 len; /* sizeof(ConfigRid) */ |
533 | __le16 opmode; /* operating mode */ | 535 | __le16 opmode; /* operating mode */ |
534 | #define MODE_STA_IBSS cpu_to_le16(0) | 536 | #define MODE_STA_IBSS cpu_to_le16(0) |
@@ -649,9 +651,10 @@ typedef struct { | |||
649 | #define MAGIC_STAY_IN_CAM (1<<10) | 651 | #define MAGIC_STAY_IN_CAM (1<<10) |
650 | u8 magicControl; | 652 | u8 magicControl; |
651 | __le16 autoWake; | 653 | __le16 autoWake; |
652 | } ConfigRid; | 654 | } __attribute__ ((packed)); |
653 | 655 | ||
654 | typedef struct { | 656 | typedef struct StatusRid StatusRid; |
657 | struct StatusRid { | ||
655 | __le16 len; | 658 | __le16 len; |
656 | u8 mac[ETH_ALEN]; | 659 | u8 mac[ETH_ALEN]; |
657 | __le16 mode; | 660 | __le16 mode; |
@@ -707,21 +710,23 @@ typedef struct { | |||
707 | #define STAT_LEAPFAILED 91 | 710 | #define STAT_LEAPFAILED 91 |
708 | #define STAT_LEAPTIMEDOUT 92 | 711 | #define STAT_LEAPTIMEDOUT 92 |
709 | #define STAT_LEAPCOMPLETE 93 | 712 | #define STAT_LEAPCOMPLETE 93 |
710 | } StatusRid; | 713 | } __attribute__ ((packed)); |
711 | 714 | ||
712 | typedef struct { | 715 | typedef struct StatsRid StatsRid; |
716 | struct StatsRid { | ||
713 | __le16 len; | 717 | __le16 len; |
714 | __le16 spacer; | 718 | __le16 spacer; |
715 | __le32 vals[100]; | 719 | __le32 vals[100]; |
716 | } StatsRid; | 720 | } __attribute__ ((packed)); |
717 | |||
718 | 721 | ||
719 | typedef struct { | 722 | typedef struct APListRid APListRid; |
723 | struct APListRid { | ||
720 | __le16 len; | 724 | __le16 len; |
721 | u8 ap[4][ETH_ALEN]; | 725 | u8 ap[4][ETH_ALEN]; |
722 | } APListRid; | 726 | } __attribute__ ((packed)); |
723 | 727 | ||
724 | typedef struct { | 728 | typedef struct CapabilityRid CapabilityRid; |
729 | struct CapabilityRid { | ||
725 | __le16 len; | 730 | __le16 len; |
726 | char oui[3]; | 731 | char oui[3]; |
727 | char zero; | 732 | char zero; |
@@ -748,17 +753,18 @@ typedef struct { | |||
748 | __le16 bootBlockVer; | 753 | __le16 bootBlockVer; |
749 | __le16 requiredHard; | 754 | __le16 requiredHard; |
750 | __le16 extSoftCap; | 755 | __le16 extSoftCap; |
751 | } CapabilityRid; | 756 | } __attribute__ ((packed)); |
752 | |||
753 | 757 | ||
754 | /* Only present on firmware >= 5.30.17 */ | 758 | /* Only present on firmware >= 5.30.17 */ |
755 | typedef struct { | 759 | typedef struct BSSListRidExtra BSSListRidExtra; |
760 | struct BSSListRidExtra { | ||
756 | __le16 unknown[4]; | 761 | __le16 unknown[4]; |
757 | u8 fixed[12]; /* WLAN management frame */ | 762 | u8 fixed[12]; /* WLAN management frame */ |
758 | u8 iep[624]; | 763 | u8 iep[624]; |
759 | } BSSListRidExtra; | 764 | } __attribute__ ((packed)); |
760 | 765 | ||
761 | typedef struct { | 766 | typedef struct BSSListRid BSSListRid; |
767 | struct BSSListRid { | ||
762 | __le16 len; | 768 | __le16 len; |
763 | __le16 index; /* First is 0 and 0xffff means end of list */ | 769 | __le16 index; /* First is 0 and 0xffff means end of list */ |
764 | #define RADIO_FH 1 /* Frequency hopping radio type */ | 770 | #define RADIO_FH 1 /* Frequency hopping radio type */ |
@@ -789,33 +795,37 @@ typedef struct { | |||
789 | 795 | ||
790 | /* Only present on firmware >= 5.30.17 */ | 796 | /* Only present on firmware >= 5.30.17 */ |
791 | BSSListRidExtra extra; | 797 | BSSListRidExtra extra; |
792 | } BSSListRid; | 798 | } __attribute__ ((packed)); |
793 | 799 | ||
794 | typedef struct { | 800 | typedef struct { |
795 | BSSListRid bss; | 801 | BSSListRid bss; |
796 | struct list_head list; | 802 | struct list_head list; |
797 | } BSSListElement; | 803 | } BSSListElement; |
798 | 804 | ||
799 | typedef struct { | 805 | typedef struct tdsRssiEntry tdsRssiEntry; |
806 | struct tdsRssiEntry { | ||
800 | u8 rssipct; | 807 | u8 rssipct; |
801 | u8 rssidBm; | 808 | u8 rssidBm; |
802 | } tdsRssiEntry; | 809 | } __attribute__ ((packed)); |
803 | 810 | ||
804 | typedef struct { | 811 | typedef struct tdsRssiRid tdsRssiRid; |
812 | struct tdsRssiRid { | ||
805 | u16 len; | 813 | u16 len; |
806 | tdsRssiEntry x[256]; | 814 | tdsRssiEntry x[256]; |
807 | } tdsRssiRid; | 815 | } __attribute__ ((packed)); |
808 | 816 | ||
809 | typedef struct { | 817 | typedef struct MICRid MICRid; |
810 | u16 len; | 818 | struct MICRid { |
811 | u16 state; | 819 | __le16 len; |
812 | u16 multicastValid; | 820 | __le16 state; |
821 | __le16 multicastValid; | ||
813 | u8 multicast[16]; | 822 | u8 multicast[16]; |
814 | u16 unicastValid; | 823 | __le16 unicastValid; |
815 | u8 unicast[16]; | 824 | u8 unicast[16]; |
816 | } MICRid; | 825 | } __attribute__ ((packed)); |
817 | 826 | ||
818 | typedef struct { | 827 | typedef struct MICBuffer MICBuffer; |
828 | struct MICBuffer { | ||
819 | __be16 typelen; | 829 | __be16 typelen; |
820 | 830 | ||
821 | union { | 831 | union { |
@@ -830,15 +840,13 @@ typedef struct { | |||
830 | } u; | 840 | } u; |
831 | __be32 mic; | 841 | __be32 mic; |
832 | __be32 seq; | 842 | __be32 seq; |
833 | } MICBuffer; | 843 | } __attribute__ ((packed)); |
834 | 844 | ||
835 | typedef struct { | 845 | typedef struct { |
836 | u8 da[ETH_ALEN]; | 846 | u8 da[ETH_ALEN]; |
837 | u8 sa[ETH_ALEN]; | 847 | u8 sa[ETH_ALEN]; |
838 | } etherHead; | 848 | } etherHead; |
839 | 849 | ||
840 | #pragma pack() | ||
841 | |||
842 | #define TXCTL_TXOK (1<<1) /* report if tx is ok */ | 850 | #define TXCTL_TXOK (1<<1) /* report if tx is ok */ |
843 | #define TXCTL_TXEX (1<<2) /* report if tx fails */ | 851 | #define TXCTL_TXEX (1<<2) /* report if tx fails */ |
844 | #define TXCTL_802_3 (0<<3) /* 802.3 packet */ | 852 | #define TXCTL_802_3 (0<<3) /* 802.3 packet */ |
@@ -981,6 +989,14 @@ typedef struct { | |||
981 | dma_addr_t host_addr; | 989 | dma_addr_t host_addr; |
982 | } TxFid; | 990 | } TxFid; |
983 | 991 | ||
992 | struct rx_hdr { | ||
993 | __le16 status, len; | ||
994 | u8 rssi[2]; | ||
995 | u8 rate; | ||
996 | u8 freq; | ||
997 | __le16 tmp[4]; | ||
998 | } __attribute__ ((packed)); | ||
999 | |||
984 | typedef struct { | 1000 | typedef struct { |
985 | unsigned int ctl: 15; | 1001 | unsigned int ctl: 15; |
986 | unsigned int rdy: 1; | 1002 | unsigned int rdy: 1; |
@@ -1070,10 +1086,6 @@ static WifiCtlHdr wifictlhdr8023 = { | |||
1070 | } | 1086 | } |
1071 | }; | 1087 | }; |
1072 | 1088 | ||
1073 | // Frequency list (map channels to frequencies) | ||
1074 | static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, | ||
1075 | 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; | ||
1076 | |||
1077 | // A few details needed for WEP (Wireless Equivalent Privacy) | 1089 | // A few details needed for WEP (Wireless Equivalent Privacy) |
1078 | #define MAX_KEY_SIZE 13 // 128 (?) bits | 1090 | #define MAX_KEY_SIZE 13 // 128 (?) bits |
1079 | #define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP | 1091 | #define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP |
@@ -1082,12 +1094,6 @@ typedef struct wep_key_t { | |||
1082 | u8 key[16]; /* 40-bit and 104-bit keys */ | 1094 | u8 key[16]; /* 40-bit and 104-bit keys */ |
1083 | } wep_key_t; | 1095 | } wep_key_t; |
1084 | 1096 | ||
1085 | /* Backward compatibility */ | ||
1086 | #ifndef IW_ENCODE_NOKEY | ||
1087 | #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ | ||
1088 | #define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) | ||
1089 | #endif /* IW_ENCODE_NOKEY */ | ||
1090 | |||
1091 | /* List of Wireless Handlers (new API) */ | 1097 | /* List of Wireless Handlers (new API) */ |
1092 | static const struct iw_handler_def airo_handler_def; | 1098 | static const struct iw_handler_def airo_handler_def; |
1093 | 1099 | ||
@@ -1155,7 +1161,7 @@ struct airo_info { | |||
1155 | use the high bit to mark whether it is in use. */ | 1161 | use the high bit to mark whether it is in use. */ |
1156 | #define MAX_FIDS 6 | 1162 | #define MAX_FIDS 6 |
1157 | #define MPI_MAX_FIDS 1 | 1163 | #define MPI_MAX_FIDS 1 |
1158 | int fids[MAX_FIDS]; | 1164 | u32 fids[MAX_FIDS]; |
1159 | ConfigRid config; | 1165 | ConfigRid config; |
1160 | char keyindex; // Used with auto wep | 1166 | char keyindex; // Used with auto wep |
1161 | char defindex; // Used with auto wep | 1167 | char defindex; // Used with auto wep |
@@ -1229,6 +1235,9 @@ struct airo_info { | |||
1229 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE | 1235 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE |
1230 | char proc_name[IFNAMSIZ]; | 1236 | char proc_name[IFNAMSIZ]; |
1231 | 1237 | ||
1238 | int wep_capable; | ||
1239 | int max_wep_idx; | ||
1240 | |||
1232 | /* WPA-related stuff */ | 1241 | /* WPA-related stuff */ |
1233 | unsigned int bssListFirst; | 1242 | unsigned int bssListFirst; |
1234 | unsigned int bssListNext; | 1243 | unsigned int bssListNext; |
@@ -1287,6 +1296,29 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len); | |||
1287 | static void emmh32_final(emmh32_context *context, u8 digest[4]); | 1296 | static void emmh32_final(emmh32_context *context, u8 digest[4]); |
1288 | static int flashpchar(struct airo_info *ai,int byte,int dwelltime); | 1297 | static int flashpchar(struct airo_info *ai,int byte,int dwelltime); |
1289 | 1298 | ||
1299 | static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len, | ||
1300 | struct crypto_cipher *tfm) | ||
1301 | { | ||
1302 | /* If the current MIC context is valid and its key is the same as | ||
1303 | * the MIC register, there's nothing to do. | ||
1304 | */ | ||
1305 | if (cur->valid && (memcmp(cur->key, key, key_len) == 0)) | ||
1306 | return; | ||
1307 | |||
1308 | /* Age current mic Context */ | ||
1309 | memcpy(old, cur, sizeof(*cur)); | ||
1310 | |||
1311 | /* Initialize new context */ | ||
1312 | memcpy(cur->key, key, key_len); | ||
1313 | cur->window = 33; /* Window always points to the middle */ | ||
1314 | cur->rx = 0; /* Rx Sequence numbers */ | ||
1315 | cur->tx = 0; /* Tx sequence numbers */ | ||
1316 | cur->valid = 1; /* Key is now valid */ | ||
1317 | |||
1318 | /* Give key to mic seed */ | ||
1319 | emmh32_setseed(&cur->seed, key, key_len, tfm); | ||
1320 | } | ||
1321 | |||
1290 | /* micinit - Initialize mic seed */ | 1322 | /* micinit - Initialize mic seed */ |
1291 | 1323 | ||
1292 | static void micinit(struct airo_info *ai) | 1324 | static void micinit(struct airo_info *ai) |
@@ -1297,49 +1329,26 @@ static void micinit(struct airo_info *ai) | |||
1297 | PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); | 1329 | PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); |
1298 | up(&ai->sem); | 1330 | up(&ai->sem); |
1299 | 1331 | ||
1300 | ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0; | 1332 | ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0; |
1301 | 1333 | if (!ai->micstats.enabled) { | |
1302 | if (ai->micstats.enabled) { | 1334 | /* So next time we have a valid key and mic is enabled, we will |
1303 | /* Key must be valid and different */ | 1335 | * update the sequence number if the key is the same as before. |
1304 | if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid || | 1336 | */ |
1305 | (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast, | ||
1306 | sizeof(ai->mod[0].mCtx.key)) != 0))) { | ||
1307 | /* Age current mic Context */ | ||
1308 | memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx)); | ||
1309 | /* Initialize new context */ | ||
1310 | memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast)); | ||
1311 | ai->mod[0].mCtx.window = 33; //Window always points to the middle | ||
1312 | ai->mod[0].mCtx.rx = 0; //Rx Sequence numbers | ||
1313 | ai->mod[0].mCtx.tx = 0; //Tx sequence numbers | ||
1314 | ai->mod[0].mCtx.valid = 1; //Key is now valid | ||
1315 | |||
1316 | /* Give key to mic seed */ | ||
1317 | emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm); | ||
1318 | } | ||
1319 | |||
1320 | /* Key must be valid and different */ | ||
1321 | if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || | ||
1322 | (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast, | ||
1323 | sizeof(ai->mod[0].uCtx.key)) != 0))) { | ||
1324 | /* Age current mic Context */ | ||
1325 | memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx)); | ||
1326 | /* Initialize new context */ | ||
1327 | memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast)); | ||
1328 | |||
1329 | ai->mod[0].uCtx.window = 33; //Window always points to the middle | ||
1330 | ai->mod[0].uCtx.rx = 0; //Rx Sequence numbers | ||
1331 | ai->mod[0].uCtx.tx = 0; //Tx sequence numbers | ||
1332 | ai->mod[0].uCtx.valid = 1; //Key is now valid | ||
1333 | |||
1334 | //Give key to mic seed | ||
1335 | emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm); | ||
1336 | } | ||
1337 | } else { | ||
1338 | /* So next time we have a valid key and mic is enabled, we will update | ||
1339 | * the sequence number if the key is the same as before. | ||
1340 | */ | ||
1341 | ai->mod[0].uCtx.valid = 0; | 1337 | ai->mod[0].uCtx.valid = 0; |
1342 | ai->mod[0].mCtx.valid = 0; | 1338 | ai->mod[0].mCtx.valid = 0; |
1339 | return; | ||
1340 | } | ||
1341 | |||
1342 | if (mic_rid.multicastValid) { | ||
1343 | age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx, | ||
1344 | mic_rid.multicast, sizeof(mic_rid.multicast), | ||
1345 | ai->tfm); | ||
1346 | } | ||
1347 | |||
1348 | if (mic_rid.unicastValid) { | ||
1349 | age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx, | ||
1350 | mic_rid.unicast, sizeof(mic_rid.unicast), | ||
1351 | ai->tfm); | ||
1343 | } | 1352 | } |
1344 | } | 1353 | } |
1345 | 1354 | ||
@@ -2637,17 +2646,21 @@ static const struct header_ops airo_header_ops = { | |||
2637 | .parse = wll_header_parse, | 2646 | .parse = wll_header_parse, |
2638 | }; | 2647 | }; |
2639 | 2648 | ||
2649 | static const struct net_device_ops airo11_netdev_ops = { | ||
2650 | .ndo_open = airo_open, | ||
2651 | .ndo_stop = airo_close, | ||
2652 | .ndo_start_xmit = airo_start_xmit11, | ||
2653 | .ndo_get_stats = airo_get_stats, | ||
2654 | .ndo_set_mac_address = airo_set_mac_address, | ||
2655 | .ndo_do_ioctl = airo_ioctl, | ||
2656 | .ndo_change_mtu = airo_change_mtu, | ||
2657 | }; | ||
2658 | |||
2640 | static void wifi_setup(struct net_device *dev) | 2659 | static void wifi_setup(struct net_device *dev) |
2641 | { | 2660 | { |
2661 | dev->netdev_ops = &airo11_netdev_ops; | ||
2642 | dev->header_ops = &airo_header_ops; | 2662 | dev->header_ops = &airo_header_ops; |
2643 | dev->hard_start_xmit = &airo_start_xmit11; | ||
2644 | dev->get_stats = &airo_get_stats; | ||
2645 | dev->set_mac_address = &airo_set_mac_address; | ||
2646 | dev->do_ioctl = &airo_ioctl; | ||
2647 | dev->wireless_handlers = &airo_handler_def; | 2663 | dev->wireless_handlers = &airo_handler_def; |
2648 | dev->change_mtu = &airo_change_mtu; | ||
2649 | dev->open = &airo_open; | ||
2650 | dev->stop = &airo_close; | ||
2651 | 2664 | ||
2652 | dev->type = ARPHRD_IEEE80211; | 2665 | dev->type = ARPHRD_IEEE80211; |
2653 | dev->hard_header_len = ETH_HLEN; | 2666 | dev->hard_header_len = ETH_HLEN; |
@@ -2730,27 +2743,32 @@ static void airo_networks_initialize(struct airo_info *ai) | |||
2730 | &ai->network_free_list); | 2743 | &ai->network_free_list); |
2731 | } | 2744 | } |
2732 | 2745 | ||
2733 | static int airo_test_wpa_capable(struct airo_info *ai) | 2746 | static const struct net_device_ops airo_netdev_ops = { |
2734 | { | 2747 | .ndo_open = airo_open, |
2735 | int status; | 2748 | .ndo_stop = airo_close, |
2736 | CapabilityRid cap_rid; | 2749 | .ndo_start_xmit = airo_start_xmit, |
2737 | 2750 | .ndo_get_stats = airo_get_stats, | |
2738 | status = readCapabilityRid(ai, &cap_rid, 1); | 2751 | .ndo_set_multicast_list = airo_set_multicast_list, |
2739 | if (status != SUCCESS) return 0; | 2752 | .ndo_set_mac_address = airo_set_mac_address, |
2753 | .ndo_do_ioctl = airo_ioctl, | ||
2754 | .ndo_change_mtu = airo_change_mtu, | ||
2755 | .ndo_set_mac_address = eth_mac_addr, | ||
2756 | .ndo_validate_addr = eth_validate_addr, | ||
2757 | }; | ||
2740 | 2758 | ||
2741 | /* Only firmware versions 5.30.17 or better can do WPA */ | 2759 | static const struct net_device_ops mpi_netdev_ops = { |
2742 | if (le16_to_cpu(cap_rid.softVer) > 0x530 | 2760 | .ndo_open = airo_open, |
2743 | || (le16_to_cpu(cap_rid.softVer) == 0x530 | 2761 | .ndo_stop = airo_close, |
2744 | && le16_to_cpu(cap_rid.softSubVer) >= 17)) { | 2762 | .ndo_start_xmit = mpi_start_xmit, |
2745 | airo_print_info("", "WPA is supported."); | 2763 | .ndo_get_stats = airo_get_stats, |
2746 | return 1; | 2764 | .ndo_set_multicast_list = airo_set_multicast_list, |
2747 | } | 2765 | .ndo_set_mac_address = airo_set_mac_address, |
2766 | .ndo_do_ioctl = airo_ioctl, | ||
2767 | .ndo_change_mtu = airo_change_mtu, | ||
2768 | .ndo_set_mac_address = eth_mac_addr, | ||
2769 | .ndo_validate_addr = eth_validate_addr, | ||
2770 | }; | ||
2748 | 2771 | ||
2749 | /* No WPA support */ | ||
2750 | airo_print_info("", "WPA unsupported (only firmware versions 5.30.17" | ||
2751 | " and greater support WPA. Detected %s)", cap_rid.prodVer); | ||
2752 | return 0; | ||
2753 | } | ||
2754 | 2772 | ||
2755 | static struct net_device *_init_airo_card( unsigned short irq, int port, | 2773 | static struct net_device *_init_airo_card( unsigned short irq, int port, |
2756 | int is_pcmcia, struct pci_dev *pci, | 2774 | int is_pcmcia, struct pci_dev *pci, |
@@ -2759,6 +2777,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2759 | struct net_device *dev; | 2777 | struct net_device *dev; |
2760 | struct airo_info *ai; | 2778 | struct airo_info *ai; |
2761 | int i, rc; | 2779 | int i, rc; |
2780 | CapabilityRid cap_rid; | ||
2762 | 2781 | ||
2763 | /* Create the network device object. */ | 2782 | /* Create the network device object. */ |
2764 | dev = alloc_netdev(sizeof(*ai), "", ether_setup); | 2783 | dev = alloc_netdev(sizeof(*ai), "", ether_setup); |
@@ -2788,22 +2807,16 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2788 | goto err_out_free; | 2807 | goto err_out_free; |
2789 | airo_networks_initialize (ai); | 2808 | airo_networks_initialize (ai); |
2790 | 2809 | ||
2810 | skb_queue_head_init (&ai->txq); | ||
2811 | |||
2791 | /* The Airo-specific entries in the device structure. */ | 2812 | /* The Airo-specific entries in the device structure. */ |
2792 | if (test_bit(FLAG_MPI,&ai->flags)) { | 2813 | if (test_bit(FLAG_MPI,&ai->flags)) |
2793 | skb_queue_head_init (&ai->txq); | 2814 | dev->netdev_ops = &mpi_netdev_ops; |
2794 | dev->hard_start_xmit = &mpi_start_xmit; | 2815 | else |
2795 | } else | 2816 | dev->netdev_ops = &airo_netdev_ops; |
2796 | dev->hard_start_xmit = &airo_start_xmit; | ||
2797 | dev->get_stats = &airo_get_stats; | ||
2798 | dev->set_multicast_list = &airo_set_multicast_list; | ||
2799 | dev->set_mac_address = &airo_set_mac_address; | ||
2800 | dev->do_ioctl = &airo_ioctl; | ||
2801 | dev->wireless_handlers = &airo_handler_def; | 2817 | dev->wireless_handlers = &airo_handler_def; |
2802 | ai->wireless_data.spy_data = &ai->spy_data; | 2818 | ai->wireless_data.spy_data = &ai->spy_data; |
2803 | dev->wireless_data = &ai->wireless_data; | 2819 | dev->wireless_data = &ai->wireless_data; |
2804 | dev->change_mtu = &airo_change_mtu; | ||
2805 | dev->open = &airo_open; | ||
2806 | dev->stop = &airo_close; | ||
2807 | dev->irq = irq; | 2820 | dev->irq = irq; |
2808 | dev->base_addr = port; | 2821 | dev->base_addr = port; |
2809 | 2822 | ||
@@ -2828,7 +2841,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2828 | } | 2841 | } |
2829 | 2842 | ||
2830 | if (probe) { | 2843 | if (probe) { |
2831 | if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { | 2844 | if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) { |
2832 | airo_print_err(dev->name, "MAC could not be enabled" ); | 2845 | airo_print_err(dev->name, "MAC could not be enabled" ); |
2833 | rc = -EIO; | 2846 | rc = -EIO; |
2834 | goto err_out_map; | 2847 | goto err_out_map; |
@@ -2838,28 +2851,50 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2838 | set_bit(FLAG_FLASHING, &ai->flags); | 2851 | set_bit(FLAG_FLASHING, &ai->flags); |
2839 | } | 2852 | } |
2840 | 2853 | ||
2854 | strcpy(dev->name, "eth%d"); | ||
2855 | rc = register_netdev(dev); | ||
2856 | if (rc) { | ||
2857 | airo_print_err(dev->name, "Couldn't register_netdev"); | ||
2858 | goto err_out_map; | ||
2859 | } | ||
2860 | ai->wifidev = init_wifidev(ai, dev); | ||
2861 | if (!ai->wifidev) | ||
2862 | goto err_out_reg; | ||
2863 | |||
2864 | rc = readCapabilityRid(ai, &cap_rid, 1); | ||
2865 | if (rc != SUCCESS) { | ||
2866 | rc = -EIO; | ||
2867 | goto err_out_wifi; | ||
2868 | } | ||
2869 | /* WEP capability discovery */ | ||
2870 | ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; | ||
2871 | ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; | ||
2872 | |||
2873 | airo_print_info(dev->name, "Firmware version %x.%x.%02x", | ||
2874 | ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), | ||
2875 | (le16_to_cpu(cap_rid.softVer) & 0xFF), | ||
2876 | le16_to_cpu(cap_rid.softSubVer)); | ||
2877 | |||
2841 | /* Test for WPA support */ | 2878 | /* Test for WPA support */ |
2842 | if (airo_test_wpa_capable(ai)) { | 2879 | /* Only firmware versions 5.30.17 or better can do WPA */ |
2880 | if (le16_to_cpu(cap_rid.softVer) > 0x530 | ||
2881 | || (le16_to_cpu(cap_rid.softVer) == 0x530 | ||
2882 | && le16_to_cpu(cap_rid.softSubVer) >= 17)) { | ||
2883 | airo_print_info(ai->dev->name, "WPA supported."); | ||
2884 | |||
2843 | set_bit(FLAG_WPA_CAPABLE, &ai->flags); | 2885 | set_bit(FLAG_WPA_CAPABLE, &ai->flags); |
2844 | ai->bssListFirst = RID_WPA_BSSLISTFIRST; | 2886 | ai->bssListFirst = RID_WPA_BSSLISTFIRST; |
2845 | ai->bssListNext = RID_WPA_BSSLISTNEXT; | 2887 | ai->bssListNext = RID_WPA_BSSLISTNEXT; |
2846 | ai->bssListRidLen = sizeof(BSSListRid); | 2888 | ai->bssListRidLen = sizeof(BSSListRid); |
2847 | } else { | 2889 | } else { |
2890 | airo_print_info(ai->dev->name, "WPA unsupported with firmware " | ||
2891 | "versions older than 5.30.17."); | ||
2892 | |||
2848 | ai->bssListFirst = RID_BSSLISTFIRST; | 2893 | ai->bssListFirst = RID_BSSLISTFIRST; |
2849 | ai->bssListNext = RID_BSSLISTNEXT; | 2894 | ai->bssListNext = RID_BSSLISTNEXT; |
2850 | ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); | 2895 | ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); |
2851 | } | 2896 | } |
2852 | 2897 | ||
2853 | strcpy(dev->name, "eth%d"); | ||
2854 | rc = register_netdev(dev); | ||
2855 | if (rc) { | ||
2856 | airo_print_err(dev->name, "Couldn't register_netdev"); | ||
2857 | goto err_out_map; | ||
2858 | } | ||
2859 | ai->wifidev = init_wifidev(ai, dev); | ||
2860 | if (!ai->wifidev) | ||
2861 | goto err_out_reg; | ||
2862 | |||
2863 | set_bit(FLAG_REGISTERED,&ai->flags); | 2898 | set_bit(FLAG_REGISTERED,&ai->flags); |
2864 | airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); | 2899 | airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); |
2865 | 2900 | ||
@@ -3127,314 +3162,354 @@ static int header_len(__le16 ctl) | |||
3127 | return 24; | 3162 | return 24; |
3128 | } | 3163 | } |
3129 | 3164 | ||
3130 | static irqreturn_t airo_interrupt(int irq, void *dev_id) | 3165 | static void airo_handle_cisco_mic(struct airo_info *ai) |
3131 | { | 3166 | { |
3132 | struct net_device *dev = dev_id; | 3167 | if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) { |
3168 | set_bit(JOB_MIC, &ai->jobs); | ||
3169 | wake_up_interruptible(&ai->thr_wait); | ||
3170 | } | ||
3171 | } | ||
3172 | |||
3173 | /* Airo Status codes */ | ||
3174 | #define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */ | ||
3175 | #define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */ | ||
3176 | #define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ | ||
3177 | #define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */ | ||
3178 | #define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ | ||
3179 | #define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */ | ||
3180 | #define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */ | ||
3181 | #define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */ | ||
3182 | #define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */ | ||
3183 | #define STAT_ASSOC 0x0400 /* Associated */ | ||
3184 | #define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ | ||
3185 | |||
3186 | static void airo_print_status(const char *devname, u16 status) | ||
3187 | { | ||
3188 | u8 reason = status & 0xFF; | ||
3189 | |||
3190 | switch (status) { | ||
3191 | case STAT_NOBEACON: | ||
3192 | airo_print_dbg(devname, "link lost (missed beacons)"); | ||
3193 | break; | ||
3194 | case STAT_MAXRETRIES: | ||
3195 | case STAT_MAXARL: | ||
3196 | airo_print_dbg(devname, "link lost (max retries)"); | ||
3197 | break; | ||
3198 | case STAT_FORCELOSS: | ||
3199 | airo_print_dbg(devname, "link lost (local choice)"); | ||
3200 | break; | ||
3201 | case STAT_TSFSYNC: | ||
3202 | airo_print_dbg(devname, "link lost (TSF sync lost)"); | ||
3203 | break; | ||
3204 | case STAT_DEAUTH: | ||
3205 | airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); | ||
3206 | break; | ||
3207 | case STAT_DISASSOC: | ||
3208 | airo_print_dbg(devname, "disassociated (reason: %d)", reason); | ||
3209 | break; | ||
3210 | case STAT_ASSOC_FAIL: | ||
3211 | airo_print_dbg(devname, "association failed (reason: %d)", | ||
3212 | reason); | ||
3213 | break; | ||
3214 | case STAT_AUTH_FAIL: | ||
3215 | airo_print_dbg(devname, "authentication failed (reason: %d)", | ||
3216 | reason); | ||
3217 | break; | ||
3218 | default: | ||
3219 | break; | ||
3220 | } | ||
3221 | } | ||
3222 | |||
3223 | static void airo_handle_link(struct airo_info *ai) | ||
3224 | { | ||
3225 | union iwreq_data wrqu; | ||
3226 | int scan_forceloss = 0; | ||
3133 | u16 status; | 3227 | u16 status; |
3134 | u16 fid; | ||
3135 | struct airo_info *apriv = dev->ml_priv; | ||
3136 | u16 savedInterrupts = 0; | ||
3137 | int handled = 0; | ||
3138 | 3228 | ||
3139 | if (!netif_device_present(dev)) | 3229 | /* Get new status and acknowledge the link change */ |
3140 | return IRQ_NONE; | 3230 | status = le16_to_cpu(IN4500(ai, LINKSTAT)); |
3231 | OUT4500(ai, EVACK, EV_LINK); | ||
3141 | 3232 | ||
3142 | for (;;) { | 3233 | if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0)) |
3143 | status = IN4500( apriv, EVSTAT ); | 3234 | scan_forceloss = 1; |
3144 | if ( !(status & STATUS_INTS) || status == 0xffff ) break; | ||
3145 | 3235 | ||
3146 | handled = 1; | 3236 | airo_print_status(ai->dev->name, status); |
3147 | 3237 | ||
3148 | if ( status & EV_AWAKE ) { | 3238 | if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) { |
3149 | OUT4500( apriv, EVACK, EV_AWAKE ); | 3239 | if (auto_wep) |
3150 | OUT4500( apriv, EVACK, EV_AWAKE ); | 3240 | ai->expires = 0; |
3151 | } | 3241 | if (ai->list_bss_task) |
3242 | wake_up_process(ai->list_bss_task); | ||
3243 | set_bit(FLAG_UPDATE_UNI, &ai->flags); | ||
3244 | set_bit(FLAG_UPDATE_MULTI, &ai->flags); | ||
3152 | 3245 | ||
3153 | if (!savedInterrupts) { | 3246 | if (down_trylock(&ai->sem) != 0) { |
3154 | savedInterrupts = IN4500( apriv, EVINTEN ); | 3247 | set_bit(JOB_EVENT, &ai->jobs); |
3155 | OUT4500( apriv, EVINTEN, 0 ); | 3248 | wake_up_interruptible(&ai->thr_wait); |
3249 | } else | ||
3250 | airo_send_event(ai->dev); | ||
3251 | } else if (!scan_forceloss) { | ||
3252 | if (auto_wep && !ai->expires) { | ||
3253 | ai->expires = RUN_AT(3*HZ); | ||
3254 | wake_up_interruptible(&ai->thr_wait); | ||
3156 | } | 3255 | } |
3157 | 3256 | ||
3158 | if ( status & EV_MIC ) { | 3257 | /* Send event to user space */ |
3159 | OUT4500( apriv, EVACK, EV_MIC ); | 3258 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); |
3160 | if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { | 3259 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
3161 | set_bit(JOB_MIC, &apriv->jobs); | 3260 | wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); |
3162 | wake_up_interruptible(&apriv->thr_wait); | 3261 | } |
3163 | } | 3262 | } |
3164 | } | ||
3165 | if ( status & EV_LINK ) { | ||
3166 | union iwreq_data wrqu; | ||
3167 | int scan_forceloss = 0; | ||
3168 | /* The link status has changed, if you want to put a | ||
3169 | monitor hook in, do it here. (Remember that | ||
3170 | interrupts are still disabled!) | ||
3171 | */ | ||
3172 | u16 newStatus = IN4500(apriv, LINKSTAT); | ||
3173 | OUT4500( apriv, EVACK, EV_LINK); | ||
3174 | /* Here is what newStatus means: */ | ||
3175 | #define NOBEACON 0x8000 /* Loss of sync - missed beacons */ | ||
3176 | #define MAXRETRIES 0x8001 /* Loss of sync - max retries */ | ||
3177 | #define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ | ||
3178 | #define FORCELOSS 0x8003 /* Loss of sync - host request */ | ||
3179 | #define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ | ||
3180 | #define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */ | ||
3181 | #define DISASS 0x8200 /* Disassociation (low byte is reason code) */ | ||
3182 | #define ASSFAIL 0x8400 /* Association failure (low byte is reason | ||
3183 | code) */ | ||
3184 | #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason | ||
3185 | code) */ | ||
3186 | #define ASSOCIATED 0x0400 /* Associated */ | ||
3187 | #define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ | ||
3188 | #define RC_RESERVED 0 /* Reserved return code */ | ||
3189 | #define RC_NOREASON 1 /* Unspecified reason */ | ||
3190 | #define RC_AUTHINV 2 /* Previous authentication invalid */ | ||
3191 | #define RC_DEAUTH 3 /* Deauthenticated because sending station is | ||
3192 | leaving */ | ||
3193 | #define RC_NOACT 4 /* Disassociated due to inactivity */ | ||
3194 | #define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle | ||
3195 | all currently associated stations */ | ||
3196 | #define RC_BADCLASS2 6 /* Class 2 frame received from | ||
3197 | non-Authenticated station */ | ||
3198 | #define RC_BADCLASS3 7 /* Class 3 frame received from | ||
3199 | non-Associated station */ | ||
3200 | #define RC_STATLEAVE 8 /* Disassociated because sending station is | ||
3201 | leaving BSS */ | ||
3202 | #define RC_NOAUTH 9 /* Station requesting (Re)Association is not | ||
3203 | Authenticated with the responding station */ | ||
3204 | if (newStatus == FORCELOSS && apriv->scan_timeout > 0) | ||
3205 | scan_forceloss = 1; | ||
3206 | if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { | ||
3207 | if (auto_wep) | ||
3208 | apriv->expires = 0; | ||
3209 | if (apriv->list_bss_task) | ||
3210 | wake_up_process(apriv->list_bss_task); | ||
3211 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); | ||
3212 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); | ||
3213 | |||
3214 | if (down_trylock(&apriv->sem) != 0) { | ||
3215 | set_bit(JOB_EVENT, &apriv->jobs); | ||
3216 | wake_up_interruptible(&apriv->thr_wait); | ||
3217 | } else | ||
3218 | airo_send_event(dev); | ||
3219 | } else if (!scan_forceloss) { | ||
3220 | if (auto_wep && !apriv->expires) { | ||
3221 | apriv->expires = RUN_AT(3*HZ); | ||
3222 | wake_up_interruptible(&apriv->thr_wait); | ||
3223 | } | ||
3224 | 3263 | ||
3225 | /* Send event to user space */ | 3264 | static void airo_handle_rx(struct airo_info *ai) |
3226 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | 3265 | { |
3227 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 3266 | struct sk_buff *skb = NULL; |
3228 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); | 3267 | __le16 fc, v, *buffer, tmpbuf[4]; |
3229 | } | 3268 | u16 len, hdrlen = 0, gap, fid; |
3230 | } | 3269 | struct rx_hdr hdr; |
3270 | int success = 0; | ||
3231 | 3271 | ||
3232 | /* Check to see if there is something to receive */ | 3272 | if (test_bit(FLAG_MPI, &ai->flags)) { |
3233 | if ( status & EV_RX ) { | 3273 | if (test_bit(FLAG_802_11, &ai->flags)) |
3234 | struct sk_buff *skb = NULL; | 3274 | mpi_receive_802_11(ai); |
3235 | __le16 fc, v; | 3275 | else |
3236 | u16 len, hdrlen = 0; | 3276 | mpi_receive_802_3(ai); |
3237 | #pragma pack(1) | 3277 | OUT4500(ai, EVACK, EV_RX); |
3238 | struct { | 3278 | return; |
3239 | __le16 status, len; | 3279 | } |
3240 | u8 rssi[2]; | ||
3241 | u8 rate; | ||
3242 | u8 freq; | ||
3243 | __le16 tmp[4]; | ||
3244 | } hdr; | ||
3245 | #pragma pack() | ||
3246 | u16 gap; | ||
3247 | __le16 tmpbuf[4]; | ||
3248 | __le16 *buffer; | ||
3249 | |||
3250 | if (test_bit(FLAG_MPI,&apriv->flags)) { | ||
3251 | if (test_bit(FLAG_802_11, &apriv->flags)) | ||
3252 | mpi_receive_802_11(apriv); | ||
3253 | else | ||
3254 | mpi_receive_802_3(apriv); | ||
3255 | OUT4500(apriv, EVACK, EV_RX); | ||
3256 | goto exitrx; | ||
3257 | } | ||
3258 | 3280 | ||
3259 | fid = IN4500( apriv, RXFID ); | 3281 | fid = IN4500(ai, RXFID); |
3260 | |||
3261 | /* Get the packet length */ | ||
3262 | if (test_bit(FLAG_802_11, &apriv->flags)) { | ||
3263 | bap_setup (apriv, fid, 4, BAP0); | ||
3264 | bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0); | ||
3265 | /* Bad CRC. Ignore packet */ | ||
3266 | if (le16_to_cpu(hdr.status) & 2) | ||
3267 | hdr.len = 0; | ||
3268 | if (apriv->wifidev == NULL) | ||
3269 | hdr.len = 0; | ||
3270 | } else { | ||
3271 | bap_setup (apriv, fid, 0x36, BAP0); | ||
3272 | bap_read (apriv, &hdr.len, 2, BAP0); | ||
3273 | } | ||
3274 | len = le16_to_cpu(hdr.len); | ||
3275 | 3282 | ||
3276 | if (len > AIRO_DEF_MTU) { | 3283 | /* Get the packet length */ |
3277 | airo_print_err(apriv->dev->name, "Bad size %d", len); | 3284 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3278 | goto badrx; | 3285 | bap_setup (ai, fid, 4, BAP0); |
3279 | } | 3286 | bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0); |
3280 | if (len == 0) | 3287 | /* Bad CRC. Ignore packet */ |
3281 | goto badrx; | 3288 | if (le16_to_cpu(hdr.status) & 2) |
3289 | hdr.len = 0; | ||
3290 | if (ai->wifidev == NULL) | ||
3291 | hdr.len = 0; | ||
3292 | } else { | ||
3293 | bap_setup(ai, fid, 0x36, BAP0); | ||
3294 | bap_read(ai, &hdr.len, 2, BAP0); | ||
3295 | } | ||
3296 | len = le16_to_cpu(hdr.len); | ||
3282 | 3297 | ||
3283 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3298 | if (len > AIRO_DEF_MTU) { |
3284 | bap_read (apriv, &fc, sizeof(fc), BAP0); | 3299 | airo_print_err(ai->dev->name, "Bad size %d", len); |
3285 | hdrlen = header_len(fc); | 3300 | goto done; |
3286 | } else | 3301 | } |
3287 | hdrlen = ETH_ALEN * 2; | 3302 | if (len == 0) |
3303 | goto done; | ||
3288 | 3304 | ||
3289 | skb = dev_alloc_skb( len + hdrlen + 2 + 2 ); | 3305 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3290 | if ( !skb ) { | 3306 | bap_read(ai, &fc, sizeof (fc), BAP0); |
3291 | dev->stats.rx_dropped++; | 3307 | hdrlen = header_len(fc); |
3292 | goto badrx; | 3308 | } else |
3293 | } | 3309 | hdrlen = ETH_ALEN * 2; |
3294 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | 3310 | |
3295 | buffer = (__le16*)skb_put (skb, len + hdrlen); | 3311 | skb = dev_alloc_skb(len + hdrlen + 2 + 2); |
3296 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3312 | if (!skb) { |
3297 | buffer[0] = fc; | 3313 | ai->dev->stats.rx_dropped++; |
3298 | bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); | 3314 | goto done; |
3299 | if (hdrlen == 24) | 3315 | } |
3300 | bap_read (apriv, tmpbuf, 6, BAP0); | 3316 | |
3301 | 3317 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | |
3302 | bap_read (apriv, &v, sizeof(v), BAP0); | 3318 | buffer = (__le16 *) skb_put(skb, len + hdrlen); |
3303 | gap = le16_to_cpu(v); | 3319 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3304 | if (gap) { | 3320 | buffer[0] = fc; |
3305 | if (gap <= 8) { | 3321 | bap_read(ai, buffer + 1, hdrlen - 2, BAP0); |
3306 | bap_read (apriv, tmpbuf, gap, BAP0); | 3322 | if (hdrlen == 24) |
3307 | } else { | 3323 | bap_read(ai, tmpbuf, 6, BAP0); |
3308 | airo_print_err(apriv->dev->name, "gaplen too " | 3324 | |
3309 | "big. Problems will follow..."); | 3325 | bap_read(ai, &v, sizeof(v), BAP0); |
3310 | } | 3326 | gap = le16_to_cpu(v); |
3311 | } | 3327 | if (gap) { |
3312 | bap_read (apriv, buffer + hdrlen/2, len, BAP0); | 3328 | if (gap <= 8) { |
3329 | bap_read(ai, tmpbuf, gap, BAP0); | ||
3313 | } else { | 3330 | } else { |
3314 | MICBuffer micbuf; | 3331 | airo_print_err(ai->dev->name, "gaplen too " |
3315 | bap_read (apriv, buffer, ETH_ALEN*2, BAP0); | 3332 | "big. Problems will follow..."); |
3316 | if (apriv->micstats.enabled) { | 3333 | } |
3317 | bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0); | 3334 | } |
3318 | if (ntohs(micbuf.typelen) > 0x05DC) | 3335 | bap_read(ai, buffer + hdrlen/2, len, BAP0); |
3319 | bap_setup (apriv, fid, 0x44, BAP0); | 3336 | } else { |
3320 | else { | 3337 | MICBuffer micbuf; |
3321 | if (len <= sizeof(micbuf)) | 3338 | |
3322 | goto badmic; | 3339 | bap_read(ai, buffer, ETH_ALEN * 2, BAP0); |
3323 | 3340 | if (ai->micstats.enabled) { | |
3324 | len -= sizeof(micbuf); | 3341 | bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0); |
3325 | skb_trim (skb, len + hdrlen); | 3342 | if (ntohs(micbuf.typelen) > 0x05DC) |
3326 | } | 3343 | bap_setup(ai, fid, 0x44, BAP0); |
3327 | } | 3344 | else { |
3328 | bap_read(apriv,buffer+ETH_ALEN,len,BAP0); | 3345 | if (len <= sizeof (micbuf)) { |
3329 | if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { | 3346 | dev_kfree_skb_irq(skb); |
3330 | badmic: | 3347 | goto done; |
3331 | dev_kfree_skb_irq (skb); | ||
3332 | badrx: | ||
3333 | OUT4500( apriv, EVACK, EV_RX); | ||
3334 | goto exitrx; | ||
3335 | } | 3348 | } |
3349 | |||
3350 | len -= sizeof(micbuf); | ||
3351 | skb_trim(skb, len + hdrlen); | ||
3336 | } | 3352 | } |
3353 | } | ||
3354 | |||
3355 | bap_read(ai, buffer + ETH_ALEN, len, BAP0); | ||
3356 | if (decapsulate(ai, &micbuf, (etherHead*) buffer, len)) | ||
3357 | dev_kfree_skb_irq (skb); | ||
3358 | else | ||
3359 | success = 1; | ||
3360 | } | ||
3361 | |||
3337 | #ifdef WIRELESS_SPY | 3362 | #ifdef WIRELESS_SPY |
3338 | if (apriv->spy_data.spy_number > 0) { | 3363 | if (success && (ai->spy_data.spy_number > 0)) { |
3339 | char *sa; | 3364 | char *sa; |
3340 | struct iw_quality wstats; | 3365 | struct iw_quality wstats; |
3341 | /* Prepare spy data : addr + qual */ | 3366 | |
3342 | if (!test_bit(FLAG_802_11, &apriv->flags)) { | 3367 | /* Prepare spy data : addr + qual */ |
3343 | sa = (char*)buffer + 6; | 3368 | if (!test_bit(FLAG_802_11, &ai->flags)) { |
3344 | bap_setup (apriv, fid, 8, BAP0); | 3369 | sa = (char *) buffer + 6; |
3345 | bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0); | 3370 | bap_setup(ai, fid, 8, BAP0); |
3346 | } else | 3371 | bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0); |
3347 | sa = (char*)buffer + 10; | 3372 | } else |
3348 | wstats.qual = hdr.rssi[0]; | 3373 | sa = (char *) buffer + 10; |
3349 | if (apriv->rssi) | 3374 | wstats.qual = hdr.rssi[0]; |
3350 | wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; | 3375 | if (ai->rssi) |
3351 | else | 3376 | wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; |
3352 | wstats.level = (hdr.rssi[1] + 321) / 2; | 3377 | else |
3353 | wstats.noise = apriv->wstats.qual.noise; | 3378 | wstats.level = (hdr.rssi[1] + 321) / 2; |
3354 | wstats.updated = IW_QUAL_LEVEL_UPDATED | 3379 | wstats.noise = ai->wstats.qual.noise; |
3355 | | IW_QUAL_QUAL_UPDATED | 3380 | wstats.updated = IW_QUAL_LEVEL_UPDATED |
3356 | | IW_QUAL_DBM; | 3381 | | IW_QUAL_QUAL_UPDATED |
3357 | /* Update spy records */ | 3382 | | IW_QUAL_DBM; |
3358 | wireless_spy_update(dev, sa, &wstats); | 3383 | /* Update spy records */ |
3359 | } | 3384 | wireless_spy_update(ai->dev, sa, &wstats); |
3385 | } | ||
3360 | #endif /* WIRELESS_SPY */ | 3386 | #endif /* WIRELESS_SPY */ |
3361 | OUT4500( apriv, EVACK, EV_RX); | ||
3362 | 3387 | ||
3363 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3388 | done: |
3364 | skb_reset_mac_header(skb); | 3389 | OUT4500(ai, EVACK, EV_RX); |
3365 | skb->pkt_type = PACKET_OTHERHOST; | 3390 | |
3366 | skb->dev = apriv->wifidev; | 3391 | if (success) { |
3367 | skb->protocol = htons(ETH_P_802_2); | 3392 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3368 | } else | 3393 | skb_reset_mac_header(skb); |
3369 | skb->protocol = eth_type_trans(skb,dev); | 3394 | skb->pkt_type = PACKET_OTHERHOST; |
3370 | skb->ip_summed = CHECKSUM_NONE; | 3395 | skb->dev = ai->wifidev; |
3396 | skb->protocol = htons(ETH_P_802_2); | ||
3397 | } else | ||
3398 | skb->protocol = eth_type_trans(skb, ai->dev); | ||
3399 | skb->ip_summed = CHECKSUM_NONE; | ||
3400 | |||
3401 | netif_rx(skb); | ||
3402 | } | ||
3403 | } | ||
3404 | |||
3405 | static void airo_handle_tx(struct airo_info *ai, u16 status) | ||
3406 | { | ||
3407 | int i, len = 0, index = -1; | ||
3408 | u16 fid; | ||
3371 | 3409 | ||
3372 | netif_rx( skb ); | 3410 | if (test_bit(FLAG_MPI, &ai->flags)) { |
3411 | unsigned long flags; | ||
3412 | |||
3413 | if (status & EV_TXEXC) | ||
3414 | get_tx_error(ai, -1); | ||
3415 | |||
3416 | spin_lock_irqsave(&ai->aux_lock, flags); | ||
3417 | if (!skb_queue_empty(&ai->txq)) { | ||
3418 | spin_unlock_irqrestore(&ai->aux_lock,flags); | ||
3419 | mpi_send_packet(ai->dev); | ||
3420 | } else { | ||
3421 | clear_bit(FLAG_PENDING_XMIT, &ai->flags); | ||
3422 | spin_unlock_irqrestore(&ai->aux_lock,flags); | ||
3423 | netif_wake_queue(ai->dev); | ||
3373 | } | 3424 | } |
3374 | exitrx: | 3425 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); |
3426 | return; | ||
3427 | } | ||
3375 | 3428 | ||
3376 | /* Check to see if a packet has been transmitted */ | 3429 | fid = IN4500(ai, TXCOMPLFID); |
3377 | if ( status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) { | 3430 | |
3378 | int i; | 3431 | for(i = 0; i < MAX_FIDS; i++) { |
3379 | int len = 0; | 3432 | if ((ai->fids[i] & 0xffff) == fid) { |
3380 | int index = -1; | 3433 | len = ai->fids[i] >> 16; |
3381 | 3434 | index = i; | |
3382 | if (test_bit(FLAG_MPI,&apriv->flags)) { | 3435 | } |
3383 | unsigned long flags; | 3436 | } |
3384 | |||
3385 | if (status & EV_TXEXC) | ||
3386 | get_tx_error(apriv, -1); | ||
3387 | spin_lock_irqsave(&apriv->aux_lock, flags); | ||
3388 | if (!skb_queue_empty(&apriv->txq)) { | ||
3389 | spin_unlock_irqrestore(&apriv->aux_lock,flags); | ||
3390 | mpi_send_packet (dev); | ||
3391 | } else { | ||
3392 | clear_bit(FLAG_PENDING_XMIT, &apriv->flags); | ||
3393 | spin_unlock_irqrestore(&apriv->aux_lock,flags); | ||
3394 | netif_wake_queue (dev); | ||
3395 | } | ||
3396 | OUT4500( apriv, EVACK, | ||
3397 | status & (EV_TX|EV_TXCPY|EV_TXEXC)); | ||
3398 | goto exittx; | ||
3399 | } | ||
3400 | 3437 | ||
3401 | fid = IN4500(apriv, TXCOMPLFID); | 3438 | if (index != -1) { |
3439 | if (status & EV_TXEXC) | ||
3440 | get_tx_error(ai, index); | ||
3402 | 3441 | ||
3403 | for( i = 0; i < MAX_FIDS; i++ ) { | 3442 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC)); |
3404 | if ( ( apriv->fids[i] & 0xffff ) == fid ) { | 3443 | |
3405 | len = apriv->fids[i] >> 16; | 3444 | /* Set up to be used again */ |
3406 | index = i; | 3445 | ai->fids[index] &= 0xffff; |
3407 | } | 3446 | if (index < MAX_FIDS / 2) { |
3408 | } | 3447 | if (!test_bit(FLAG_PENDING_XMIT, &ai->flags)) |
3409 | if (index != -1) { | 3448 | netif_wake_queue(ai->dev); |
3410 | if (status & EV_TXEXC) | 3449 | } else { |
3411 | get_tx_error(apriv, index); | 3450 | if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags)) |
3412 | OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); | 3451 | netif_wake_queue(ai->wifidev); |
3413 | /* Set up to be used again */ | 3452 | } |
3414 | apriv->fids[index] &= 0xffff; | 3453 | } else { |
3415 | if (index < MAX_FIDS / 2) { | 3454 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); |
3416 | if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags)) | 3455 | airo_print_err(ai->dev->name, "Unallocated FID was used to xmit"); |
3417 | netif_wake_queue(dev); | 3456 | } |
3418 | } else { | 3457 | } |
3419 | if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags)) | 3458 | |
3420 | netif_wake_queue(apriv->wifidev); | 3459 | static irqreturn_t airo_interrupt(int irq, void *dev_id) |
3421 | } | 3460 | { |
3422 | } else { | 3461 | struct net_device *dev = dev_id; |
3423 | OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); | 3462 | u16 status, savedInterrupts = 0; |
3424 | airo_print_err(apriv->dev->name, "Unallocated FID was " | 3463 | struct airo_info *ai = dev->ml_priv; |
3425 | "used to xmit" ); | 3464 | int handled = 0; |
3426 | } | 3465 | |
3466 | if (!netif_device_present(dev)) | ||
3467 | return IRQ_NONE; | ||
3468 | |||
3469 | for (;;) { | ||
3470 | status = IN4500(ai, EVSTAT); | ||
3471 | if (!(status & STATUS_INTS) || (status == 0xffff)) | ||
3472 | break; | ||
3473 | |||
3474 | handled = 1; | ||
3475 | |||
3476 | if (status & EV_AWAKE) { | ||
3477 | OUT4500(ai, EVACK, EV_AWAKE); | ||
3478 | OUT4500(ai, EVACK, EV_AWAKE); | ||
3479 | } | ||
3480 | |||
3481 | if (!savedInterrupts) { | ||
3482 | savedInterrupts = IN4500(ai, EVINTEN); | ||
3483 | OUT4500(ai, EVINTEN, 0); | ||
3484 | } | ||
3485 | |||
3486 | if (status & EV_MIC) { | ||
3487 | OUT4500(ai, EVACK, EV_MIC); | ||
3488 | airo_handle_cisco_mic(ai); | ||
3427 | } | 3489 | } |
3428 | exittx: | 3490 | |
3429 | if ( status & ~STATUS_INTS & ~IGNORE_INTS ) | 3491 | if (status & EV_LINK) { |
3430 | airo_print_warn(apriv->dev->name, "Got weird status %x", | 3492 | /* Link status changed */ |
3493 | airo_handle_link(ai); | ||
3494 | } | ||
3495 | |||
3496 | /* Check to see if there is something to receive */ | ||
3497 | if (status & EV_RX) | ||
3498 | airo_handle_rx(ai); | ||
3499 | |||
3500 | /* Check to see if a packet has been transmitted */ | ||
3501 | if (status & (EV_TX | EV_TXCPY | EV_TXEXC)) | ||
3502 | airo_handle_tx(ai, status); | ||
3503 | |||
3504 | if ( status & ~STATUS_INTS & ~IGNORE_INTS ) { | ||
3505 | airo_print_warn(ai->dev->name, "Got weird status %x", | ||
3431 | status & ~STATUS_INTS & ~IGNORE_INTS ); | 3506 | status & ~STATUS_INTS & ~IGNORE_INTS ); |
3507 | } | ||
3432 | } | 3508 | } |
3433 | 3509 | ||
3434 | if (savedInterrupts) | 3510 | if (savedInterrupts) |
3435 | OUT4500( apriv, EVINTEN, savedInterrupts ); | 3511 | OUT4500(ai, EVINTEN, savedInterrupts); |
3436 | 3512 | ||
3437 | /* done.. */ | ||
3438 | return IRQ_RETVAL(handled); | 3513 | return IRQ_RETVAL(handled); |
3439 | } | 3514 | } |
3440 | 3515 | ||
@@ -3613,18 +3688,10 @@ static void mpi_receive_802_11(struct airo_info *ai) | |||
3613 | struct sk_buff *skb = NULL; | 3688 | struct sk_buff *skb = NULL; |
3614 | u16 len, hdrlen = 0; | 3689 | u16 len, hdrlen = 0; |
3615 | __le16 fc; | 3690 | __le16 fc; |
3616 | #pragma pack(1) | 3691 | struct rx_hdr hdr; |
3617 | struct { | ||
3618 | __le16 status, len; | ||
3619 | u8 rssi[2]; | ||
3620 | u8 rate; | ||
3621 | u8 freq; | ||
3622 | __le16 tmp[4]; | ||
3623 | } hdr; | ||
3624 | #pragma pack() | ||
3625 | u16 gap; | 3692 | u16 gap; |
3626 | u16 *buffer; | 3693 | u16 *buffer; |
3627 | char *ptr = ai->rxfids[0].virtual_host_addr+4; | 3694 | char *ptr = ai->rxfids[0].virtual_host_addr + 4; |
3628 | 3695 | ||
3629 | memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); | 3696 | memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); |
3630 | memcpy ((char *)&hdr, ptr, sizeof(hdr)); | 3697 | memcpy ((char *)&hdr, ptr, sizeof(hdr)); |
@@ -3691,6 +3758,7 @@ static void mpi_receive_802_11(struct airo_info *ai) | |||
3691 | skb->protocol = htons(ETH_P_802_2); | 3758 | skb->protocol = htons(ETH_P_802_2); |
3692 | skb->ip_summed = CHECKSUM_NONE; | 3759 | skb->ip_summed = CHECKSUM_NONE; |
3693 | netif_rx( skb ); | 3760 | netif_rx( skb ); |
3761 | |||
3694 | badrx: | 3762 | badrx: |
3695 | if (rxd.valid == 0) { | 3763 | if (rxd.valid == 0) { |
3696 | rxd.valid = 1; | 3764 | rxd.valid = 1; |
@@ -3705,7 +3773,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3705 | Cmd cmd; | 3773 | Cmd cmd; |
3706 | Resp rsp; | 3774 | Resp rsp; |
3707 | int status; | 3775 | int status; |
3708 | int i; | ||
3709 | SsidRid mySsid; | 3776 | SsidRid mySsid; |
3710 | __le16 lastindex; | 3777 | __le16 lastindex; |
3711 | WepKeyRid wkr; | 3778 | WepKeyRid wkr; |
@@ -3747,6 +3814,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3747 | if (lock) | 3814 | if (lock) |
3748 | up(&ai->sem); | 3815 | up(&ai->sem); |
3749 | if (ai->config.len == 0) { | 3816 | if (ai->config.len == 0) { |
3817 | int i; | ||
3750 | tdsRssiRid rssi_rid; | 3818 | tdsRssiRid rssi_rid; |
3751 | CapabilityRid cap_rid; | 3819 | CapabilityRid cap_rid; |
3752 | 3820 | ||
@@ -3794,14 +3862,12 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3794 | /* Check to see if there are any insmod configured | 3862 | /* Check to see if there are any insmod configured |
3795 | rates to add */ | 3863 | rates to add */ |
3796 | if ( rates[0] ) { | 3864 | if ( rates[0] ) { |
3797 | int i = 0; | ||
3798 | memset(ai->config.rates,0,sizeof(ai->config.rates)); | 3865 | memset(ai->config.rates,0,sizeof(ai->config.rates)); |
3799 | for( i = 0; i < 8 && rates[i]; i++ ) { | 3866 | for( i = 0; i < 8 && rates[i]; i++ ) { |
3800 | ai->config.rates[i] = rates[i]; | 3867 | ai->config.rates[i] = rates[i]; |
3801 | } | 3868 | } |
3802 | } | 3869 | } |
3803 | if ( basic_rate > 0 ) { | 3870 | if ( basic_rate > 0 ) { |
3804 | int i; | ||
3805 | for( i = 0; i < 8; i++ ) { | 3871 | for( i = 0; i < 8; i++ ) { |
3806 | if ( ai->config.rates[i] == basic_rate || | 3872 | if ( ai->config.rates[i] == basic_rate || |
3807 | !ai->config.rates ) { | 3873 | !ai->config.rates ) { |
@@ -4686,7 +4752,7 @@ static int proc_stats_rid_open( struct inode *inode, | |||
4686 | StatsRid stats; | 4752 | StatsRid stats; |
4687 | int i, j; | 4753 | int i, j; |
4688 | __le32 *vals = stats.vals; | 4754 | __le32 *vals = stats.vals; |
4689 | int len = le16_to_cpu(stats.len); | 4755 | int len; |
4690 | 4756 | ||
4691 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) | 4757 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) |
4692 | return -ENOMEM; | 4758 | return -ENOMEM; |
@@ -4697,6 +4763,7 @@ static int proc_stats_rid_open( struct inode *inode, | |||
4697 | } | 4763 | } |
4698 | 4764 | ||
4699 | readStatsRid(apriv, &stats, rid, 1); | 4765 | readStatsRid(apriv, &stats, rid, 1); |
4766 | len = le16_to_cpu(stats.len); | ||
4700 | 4767 | ||
4701 | j = 0; | 4768 | j = 0; |
4702 | for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) { | 4769 | for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) { |
@@ -5131,55 +5198,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, | |||
5131 | return rc; | 5198 | return rc; |
5132 | } | 5199 | } |
5133 | 5200 | ||
5134 | /* Returns the length of the key at the index. If index == 0xffff | 5201 | /* Returns the WEP key at the specified index, or -1 if that key does |
5135 | * the index of the transmit key is returned. If the key doesn't exist, | 5202 | * not exist. The buffer is assumed to be at least 16 bytes in length. |
5136 | * -1 will be returned. | ||
5137 | */ | 5203 | */ |
5138 | static int get_wep_key(struct airo_info *ai, u16 index) { | 5204 | static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen) |
5205 | { | ||
5139 | WepKeyRid wkr; | 5206 | WepKeyRid wkr; |
5140 | int rc; | 5207 | int rc; |
5141 | __le16 lastindex; | 5208 | __le16 lastindex; |
5142 | 5209 | ||
5143 | rc = readWepKeyRid(ai, &wkr, 1, 1); | 5210 | rc = readWepKeyRid(ai, &wkr, 1, 1); |
5144 | if (rc == SUCCESS) do { | 5211 | if (rc != SUCCESS) |
5212 | return -1; | ||
5213 | do { | ||
5145 | lastindex = wkr.kindex; | 5214 | lastindex = wkr.kindex; |
5146 | if (wkr.kindex == cpu_to_le16(index)) { | 5215 | if (le16_to_cpu(wkr.kindex) == index) { |
5147 | if (index == 0xffff) { | 5216 | int klen = min_t(int, buflen, le16_to_cpu(wkr.klen)); |
5148 | return wkr.mac[0]; | 5217 | memcpy(buf, wkr.key, klen); |
5149 | } | 5218 | return klen; |
5150 | return le16_to_cpu(wkr.klen); | ||
5151 | } | 5219 | } |
5152 | readWepKeyRid(ai, &wkr, 0, 1); | 5220 | rc = readWepKeyRid(ai, &wkr, 0, 1); |
5221 | if (rc != SUCCESS) | ||
5222 | return -1; | ||
5153 | } while (lastindex != wkr.kindex); | 5223 | } while (lastindex != wkr.kindex); |
5154 | return -1; | 5224 | return -1; |
5155 | } | 5225 | } |
5156 | 5226 | ||
5157 | static int set_wep_key(struct airo_info *ai, u16 index, | 5227 | static int get_wep_tx_idx(struct airo_info *ai) |
5158 | const char *key, u16 keylen, int perm, int lock ) | 5228 | { |
5229 | WepKeyRid wkr; | ||
5230 | int rc; | ||
5231 | __le16 lastindex; | ||
5232 | |||
5233 | rc = readWepKeyRid(ai, &wkr, 1, 1); | ||
5234 | if (rc != SUCCESS) | ||
5235 | return -1; | ||
5236 | do { | ||
5237 | lastindex = wkr.kindex; | ||
5238 | if (wkr.kindex == cpu_to_le16(0xffff)) | ||
5239 | return wkr.mac[0]; | ||
5240 | rc = readWepKeyRid(ai, &wkr, 0, 1); | ||
5241 | if (rc != SUCCESS) | ||
5242 | return -1; | ||
5243 | } while (lastindex != wkr.kindex); | ||
5244 | return -1; | ||
5245 | } | ||
5246 | |||
5247 | static int set_wep_key(struct airo_info *ai, u16 index, const char *key, | ||
5248 | u16 keylen, int perm, int lock) | ||
5159 | { | 5249 | { |
5160 | static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; | 5250 | static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; |
5161 | WepKeyRid wkr; | 5251 | WepKeyRid wkr; |
5252 | int rc; | ||
5162 | 5253 | ||
5163 | memset(&wkr, 0, sizeof(wkr)); | ||
5164 | if (keylen == 0) { | 5254 | if (keylen == 0) { |
5165 | // We are selecting which key to use | 5255 | airo_print_err(ai->dev->name, "%s: key length to set was zero", |
5166 | wkr.len = cpu_to_le16(sizeof(wkr)); | 5256 | __func__); |
5167 | wkr.kindex = cpu_to_le16(0xffff); | 5257 | return -1; |
5168 | wkr.mac[0] = (char)index; | ||
5169 | if (perm) ai->defindex = (char)index; | ||
5170 | } else { | ||
5171 | // We are actually setting the key | ||
5172 | wkr.len = cpu_to_le16(sizeof(wkr)); | ||
5173 | wkr.kindex = cpu_to_le16(index); | ||
5174 | wkr.klen = cpu_to_le16(keylen); | ||
5175 | memcpy( wkr.key, key, keylen ); | ||
5176 | memcpy( wkr.mac, macaddr, ETH_ALEN ); | ||
5177 | } | 5258 | } |
5178 | 5259 | ||
5260 | memset(&wkr, 0, sizeof(wkr)); | ||
5261 | wkr.len = cpu_to_le16(sizeof(wkr)); | ||
5262 | wkr.kindex = cpu_to_le16(index); | ||
5263 | wkr.klen = cpu_to_le16(keylen); | ||
5264 | memcpy(wkr.key, key, keylen); | ||
5265 | memcpy(wkr.mac, macaddr, ETH_ALEN); | ||
5266 | |||
5179 | if (perm) disable_MAC(ai, lock); | 5267 | if (perm) disable_MAC(ai, lock); |
5180 | writeWepKeyRid(ai, &wkr, perm, lock); | 5268 | rc = writeWepKeyRid(ai, &wkr, perm, lock); |
5181 | if (perm) enable_MAC(ai, lock); | 5269 | if (perm) enable_MAC(ai, lock); |
5182 | return 0; | 5270 | return rc; |
5271 | } | ||
5272 | |||
5273 | static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock) | ||
5274 | { | ||
5275 | WepKeyRid wkr; | ||
5276 | int rc; | ||
5277 | |||
5278 | memset(&wkr, 0, sizeof(wkr)); | ||
5279 | wkr.len = cpu_to_le16(sizeof(wkr)); | ||
5280 | wkr.kindex = cpu_to_le16(0xffff); | ||
5281 | wkr.mac[0] = (char)index; | ||
5282 | |||
5283 | if (perm) { | ||
5284 | ai->defindex = (char)index; | ||
5285 | disable_MAC(ai, lock); | ||
5286 | } | ||
5287 | |||
5288 | rc = writeWepKeyRid(ai, &wkr, perm, lock); | ||
5289 | |||
5290 | if (perm) | ||
5291 | enable_MAC(ai, lock); | ||
5292 | return rc; | ||
5183 | } | 5293 | } |
5184 | 5294 | ||
5185 | static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | 5295 | static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { |
@@ -5187,7 +5297,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5187 | struct proc_dir_entry *dp = PDE(inode); | 5297 | struct proc_dir_entry *dp = PDE(inode); |
5188 | struct net_device *dev = dp->data; | 5298 | struct net_device *dev = dp->data; |
5189 | struct airo_info *ai = dev->ml_priv; | 5299 | struct airo_info *ai = dev->ml_priv; |
5190 | int i; | 5300 | int i, rc; |
5191 | char key[16]; | 5301 | char key[16]; |
5192 | u16 index = 0; | 5302 | u16 index = 0; |
5193 | int j = 0; | 5303 | int j = 0; |
@@ -5201,7 +5311,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5201 | (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { | 5311 | (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { |
5202 | index = data->wbuffer[0] - '0'; | 5312 | index = data->wbuffer[0] - '0'; |
5203 | if (data->wbuffer[1] == '\n') { | 5313 | if (data->wbuffer[1] == '\n') { |
5204 | set_wep_key(ai, index, NULL, 0, 1, 1); | 5314 | rc = set_wep_tx_idx(ai, index, 1, 1); |
5315 | if (rc < 0) { | ||
5316 | airo_print_err(ai->dev->name, "failed to set " | ||
5317 | "WEP transmit index to %d: %d.", | ||
5318 | index, rc); | ||
5319 | } | ||
5205 | return; | 5320 | return; |
5206 | } | 5321 | } |
5207 | j = 2; | 5322 | j = 2; |
@@ -5220,7 +5335,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5220 | break; | 5335 | break; |
5221 | } | 5336 | } |
5222 | } | 5337 | } |
5223 | set_wep_key(ai, index, key, i/3, 1, 1); | 5338 | |
5339 | rc = set_wep_key(ai, index, key, i/3, 1, 1); | ||
5340 | if (rc < 0) { | ||
5341 | airo_print_err(ai->dev->name, "failed to set WEP key at index " | ||
5342 | "%d: %d.", index, rc); | ||
5343 | } | ||
5224 | } | 5344 | } |
5225 | 5345 | ||
5226 | static int proc_wepkey_open( struct inode *inode, struct file *file ) | 5346 | static int proc_wepkey_open( struct inode *inode, struct file *file ) |
@@ -5451,13 +5571,13 @@ static void timer_func( struct net_device *dev ) { | |||
5451 | break; | 5571 | break; |
5452 | case AUTH_SHAREDKEY: | 5572 | case AUTH_SHAREDKEY: |
5453 | if (apriv->keyindex < auto_wep) { | 5573 | if (apriv->keyindex < auto_wep) { |
5454 | set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); | 5574 | set_wep_tx_idx(apriv, apriv->keyindex, 0, 0); |
5455 | apriv->config.authType = AUTH_SHAREDKEY; | 5575 | apriv->config.authType = AUTH_SHAREDKEY; |
5456 | apriv->keyindex++; | 5576 | apriv->keyindex++; |
5457 | } else { | 5577 | } else { |
5458 | /* Drop to ENCRYPT */ | 5578 | /* Drop to ENCRYPT */ |
5459 | apriv->keyindex = 0; | 5579 | apriv->keyindex = 0; |
5460 | set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); | 5580 | set_wep_tx_idx(apriv, apriv->defindex, 0, 0); |
5461 | apriv->config.authType = AUTH_ENCRYPT; | 5581 | apriv->config.authType = AUTH_ENCRYPT; |
5462 | } | 5582 | } |
5463 | break; | 5583 | break; |
@@ -5725,16 +5845,12 @@ static int airo_set_freq(struct net_device *dev, | |||
5725 | int rc = -EINPROGRESS; /* Call commit handler */ | 5845 | int rc = -EINPROGRESS; /* Call commit handler */ |
5726 | 5846 | ||
5727 | /* If setting by frequency, convert to a channel */ | 5847 | /* If setting by frequency, convert to a channel */ |
5728 | if((fwrq->e == 1) && | 5848 | if(fwrq->e == 1) { |
5729 | (fwrq->m >= (int) 2.412e8) && | ||
5730 | (fwrq->m <= (int) 2.487e8)) { | ||
5731 | int f = fwrq->m / 100000; | 5849 | int f = fwrq->m / 100000; |
5732 | int c = 0; | 5850 | |
5733 | while((c < 14) && (f != frequency_list[c])) | ||
5734 | c++; | ||
5735 | /* Hack to fall through... */ | 5851 | /* Hack to fall through... */ |
5736 | fwrq->e = 0; | 5852 | fwrq->e = 0; |
5737 | fwrq->m = c + 1; | 5853 | fwrq->m = ieee80211_freq_to_dsss_chan(f); |
5738 | } | 5854 | } |
5739 | /* Setting by channel number */ | 5855 | /* Setting by channel number */ |
5740 | if((fwrq->m > 1000) || (fwrq->e > 0)) | 5856 | if((fwrq->m > 1000) || (fwrq->e > 0)) |
@@ -5778,7 +5894,7 @@ static int airo_get_freq(struct net_device *dev, | |||
5778 | 5894 | ||
5779 | ch = le16_to_cpu(status_rid.channel); | 5895 | ch = le16_to_cpu(status_rid.channel); |
5780 | if((ch > 0) && (ch < 15)) { | 5896 | if((ch > 0) && (ch < 15)) { |
5781 | fwrq->m = frequency_list[ch - 1] * 100000; | 5897 | fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000; |
5782 | fwrq->e = 1; | 5898 | fwrq->e = 1; |
5783 | } else { | 5899 | } else { |
5784 | fwrq->m = ch; | 5900 | fwrq->m = ch; |
@@ -6234,11 +6350,9 @@ static int airo_get_mode(struct net_device *dev, | |||
6234 | return 0; | 6350 | return 0; |
6235 | } | 6351 | } |
6236 | 6352 | ||
6237 | static inline int valid_index(CapabilityRid *p, int index) | 6353 | static inline int valid_index(struct airo_info *ai, int index) |
6238 | { | 6354 | { |
6239 | if (index < 0) | 6355 | return (index >= 0) && (index <= ai->max_wep_idx); |
6240 | return 0; | ||
6241 | return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1); | ||
6242 | } | 6356 | } |
6243 | 6357 | ||
6244 | /*------------------------------------------------------------------*/ | 6358 | /*------------------------------------------------------------------*/ |
@@ -6251,16 +6365,13 @@ static int airo_set_encode(struct net_device *dev, | |||
6251 | char *extra) | 6365 | char *extra) |
6252 | { | 6366 | { |
6253 | struct airo_info *local = dev->ml_priv; | 6367 | struct airo_info *local = dev->ml_priv; |
6254 | CapabilityRid cap_rid; /* Card capability info */ | 6368 | int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1); |
6255 | int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); | ||
6256 | __le16 currentAuthType = local->config.authType; | 6369 | __le16 currentAuthType = local->config.authType; |
6370 | int rc = 0; | ||
6257 | 6371 | ||
6258 | /* Is WEP supported ? */ | 6372 | if (!local->wep_capable) |
6259 | readCapabilityRid(local, &cap_rid, 1); | ||
6260 | /* Older firmware doesn't support this... | ||
6261 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6262 | return -EOPNOTSUPP; | 6373 | return -EOPNOTSUPP; |
6263 | } */ | 6374 | |
6264 | readConfigRid(local, 1); | 6375 | readConfigRid(local, 1); |
6265 | 6376 | ||
6266 | /* Basic checking: do we have a key to set ? | 6377 | /* Basic checking: do we have a key to set ? |
@@ -6272,14 +6383,21 @@ static int airo_set_encode(struct net_device *dev, | |||
6272 | if (dwrq->length > 0) { | 6383 | if (dwrq->length > 0) { |
6273 | wep_key_t key; | 6384 | wep_key_t key; |
6274 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6385 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6275 | int current_index = get_wep_key(local, 0xffff); | 6386 | int current_index; |
6387 | |||
6276 | /* Check the size of the key */ | 6388 | /* Check the size of the key */ |
6277 | if (dwrq->length > MAX_KEY_SIZE) { | 6389 | if (dwrq->length > MAX_KEY_SIZE) { |
6278 | return -EINVAL; | 6390 | return -EINVAL; |
6279 | } | 6391 | } |
6392 | |||
6393 | current_index = get_wep_tx_idx(local); | ||
6394 | if (current_index < 0) | ||
6395 | current_index = 0; | ||
6396 | |||
6280 | /* Check the index (none -> use current) */ | 6397 | /* Check the index (none -> use current) */ |
6281 | if (!valid_index(&cap_rid, index)) | 6398 | if (!valid_index(local, index)) |
6282 | index = current_index; | 6399 | index = current_index; |
6400 | |||
6283 | /* Set the length */ | 6401 | /* Set the length */ |
6284 | if (dwrq->length > MIN_KEY_SIZE) | 6402 | if (dwrq->length > MIN_KEY_SIZE) |
6285 | key.len = MAX_KEY_SIZE; | 6403 | key.len = MAX_KEY_SIZE; |
@@ -6296,7 +6414,13 @@ static int airo_set_encode(struct net_device *dev, | |||
6296 | /* Copy the key in the driver */ | 6414 | /* Copy the key in the driver */ |
6297 | memcpy(key.key, extra, dwrq->length); | 6415 | memcpy(key.key, extra, dwrq->length); |
6298 | /* Send the key to the card */ | 6416 | /* Send the key to the card */ |
6299 | set_wep_key(local, index, key.key, key.len, perm, 1); | 6417 | rc = set_wep_key(local, index, key.key, key.len, perm, 1); |
6418 | if (rc < 0) { | ||
6419 | airo_print_err(local->dev->name, "failed to set" | ||
6420 | " WEP key at index %d: %d.", | ||
6421 | index, rc); | ||
6422 | return rc; | ||
6423 | } | ||
6300 | } | 6424 | } |
6301 | /* WE specify that if a valid key is set, encryption | 6425 | /* WE specify that if a valid key is set, encryption |
6302 | * should be enabled (user may turn it off later) | 6426 | * should be enabled (user may turn it off later) |
@@ -6308,12 +6432,19 @@ static int airo_set_encode(struct net_device *dev, | |||
6308 | } else { | 6432 | } else { |
6309 | /* Do we want to just set the transmit key index ? */ | 6433 | /* Do we want to just set the transmit key index ? */ |
6310 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6434 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6311 | if (valid_index(&cap_rid, index)) { | 6435 | if (valid_index(local, index)) { |
6312 | set_wep_key(local, index, NULL, 0, perm, 1); | 6436 | rc = set_wep_tx_idx(local, index, perm, 1); |
6313 | } else | 6437 | if (rc < 0) { |
6438 | airo_print_err(local->dev->name, "failed to set" | ||
6439 | " WEP transmit index to %d: %d.", | ||
6440 | index, rc); | ||
6441 | return rc; | ||
6442 | } | ||
6443 | } else { | ||
6314 | /* Don't complain if only change the mode */ | 6444 | /* Don't complain if only change the mode */ |
6315 | if (!(dwrq->flags & IW_ENCODE_MODE)) | 6445 | if (!(dwrq->flags & IW_ENCODE_MODE)) |
6316 | return -EINVAL; | 6446 | return -EINVAL; |
6447 | } | ||
6317 | } | 6448 | } |
6318 | /* Read the flags */ | 6449 | /* Read the flags */ |
6319 | if(dwrq->flags & IW_ENCODE_DISABLED) | 6450 | if(dwrq->flags & IW_ENCODE_DISABLED) |
@@ -6339,14 +6470,13 @@ static int airo_get_encode(struct net_device *dev, | |||
6339 | { | 6470 | { |
6340 | struct airo_info *local = dev->ml_priv; | 6471 | struct airo_info *local = dev->ml_priv; |
6341 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6472 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6342 | CapabilityRid cap_rid; /* Card capability info */ | 6473 | u8 buf[16]; |
6343 | 6474 | ||
6344 | /* Is it supported ? */ | 6475 | if (!local->wep_capable) |
6345 | readCapabilityRid(local, &cap_rid, 1); | ||
6346 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6347 | return -EOPNOTSUPP; | 6476 | return -EOPNOTSUPP; |
6348 | } | 6477 | |
6349 | readConfigRid(local, 1); | 6478 | readConfigRid(local, 1); |
6479 | |||
6350 | /* Check encryption mode */ | 6480 | /* Check encryption mode */ |
6351 | switch(local->config.authType) { | 6481 | switch(local->config.authType) { |
6352 | case AUTH_ENCRYPT: | 6482 | case AUTH_ENCRYPT: |
@@ -6365,14 +6495,17 @@ static int airo_get_encode(struct net_device *dev, | |||
6365 | memset(extra, 0, 16); | 6495 | memset(extra, 0, 16); |
6366 | 6496 | ||
6367 | /* Which key do we want ? -1 -> tx index */ | 6497 | /* Which key do we want ? -1 -> tx index */ |
6368 | if (!valid_index(&cap_rid, index)) | 6498 | if (!valid_index(local, index)) { |
6369 | index = get_wep_key(local, 0xffff); | 6499 | index = get_wep_tx_idx(local); |
6500 | if (index < 0) | ||
6501 | index = 0; | ||
6502 | } | ||
6370 | dwrq->flags |= index + 1; | 6503 | dwrq->flags |= index + 1; |
6504 | |||
6371 | /* Copy the key to the user buffer */ | 6505 | /* Copy the key to the user buffer */ |
6372 | dwrq->length = get_wep_key(local, index); | 6506 | dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf)); |
6373 | if (dwrq->length > 16) { | 6507 | memcpy(extra, buf, dwrq->length); |
6374 | dwrq->length=0; | 6508 | |
6375 | } | ||
6376 | return 0; | 6509 | return 0; |
6377 | } | 6510 | } |
6378 | 6511 | ||
@@ -6388,28 +6521,27 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6388 | struct airo_info *local = dev->ml_priv; | 6521 | struct airo_info *local = dev->ml_priv; |
6389 | struct iw_point *encoding = &wrqu->encoding; | 6522 | struct iw_point *encoding = &wrqu->encoding; |
6390 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 6523 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
6391 | CapabilityRid cap_rid; /* Card capability info */ | ||
6392 | int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); | 6524 | int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); |
6393 | __le16 currentAuthType = local->config.authType; | 6525 | __le16 currentAuthType = local->config.authType; |
6394 | int idx, key_len, alg = ext->alg, set_key = 1; | 6526 | int idx, key_len, alg = ext->alg, set_key = 1, rc; |
6395 | wep_key_t key; | 6527 | wep_key_t key; |
6396 | 6528 | ||
6397 | /* Is WEP supported ? */ | 6529 | if (!local->wep_capable) |
6398 | readCapabilityRid(local, &cap_rid, 1); | ||
6399 | /* Older firmware doesn't support this... | ||
6400 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6401 | return -EOPNOTSUPP; | 6530 | return -EOPNOTSUPP; |
6402 | } */ | 6531 | |
6403 | readConfigRid(local, 1); | 6532 | readConfigRid(local, 1); |
6404 | 6533 | ||
6405 | /* Determine and validate the key index */ | 6534 | /* Determine and validate the key index */ |
6406 | idx = encoding->flags & IW_ENCODE_INDEX; | 6535 | idx = encoding->flags & IW_ENCODE_INDEX; |
6407 | if (idx) { | 6536 | if (idx) { |
6408 | if (!valid_index(&cap_rid, idx - 1)) | 6537 | if (!valid_index(local, idx - 1)) |
6409 | return -EINVAL; | 6538 | return -EINVAL; |
6410 | idx--; | 6539 | idx--; |
6411 | } else | 6540 | } else { |
6412 | idx = get_wep_key(local, 0xffff); | 6541 | idx = get_wep_tx_idx(local); |
6542 | if (idx < 0) | ||
6543 | idx = 0; | ||
6544 | } | ||
6413 | 6545 | ||
6414 | if (encoding->flags & IW_ENCODE_DISABLED) | 6546 | if (encoding->flags & IW_ENCODE_DISABLED) |
6415 | alg = IW_ENCODE_ALG_NONE; | 6547 | alg = IW_ENCODE_ALG_NONE; |
@@ -6418,7 +6550,13 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6418 | /* Only set transmit key index here, actual | 6550 | /* Only set transmit key index here, actual |
6419 | * key is set below if needed. | 6551 | * key is set below if needed. |
6420 | */ | 6552 | */ |
6421 | set_wep_key(local, idx, NULL, 0, perm, 1); | 6553 | rc = set_wep_tx_idx(local, idx, perm, 1); |
6554 | if (rc < 0) { | ||
6555 | airo_print_err(local->dev->name, "failed to set " | ||
6556 | "WEP transmit index to %d: %d.", | ||
6557 | idx, rc); | ||
6558 | return rc; | ||
6559 | } | ||
6422 | set_key = ext->key_len > 0 ? 1 : 0; | 6560 | set_key = ext->key_len > 0 ? 1 : 0; |
6423 | } | 6561 | } |
6424 | 6562 | ||
@@ -6444,7 +6582,12 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6444 | return -EINVAL; | 6582 | return -EINVAL; |
6445 | } | 6583 | } |
6446 | /* Send the key to the card */ | 6584 | /* Send the key to the card */ |
6447 | set_wep_key(local, idx, key.key, key.len, perm, 1); | 6585 | rc = set_wep_key(local, idx, key.key, key.len, perm, 1); |
6586 | if (rc < 0) { | ||
6587 | airo_print_err(local->dev->name, "failed to set WEP key" | ||
6588 | " at index %d: %d.", idx, rc); | ||
6589 | return rc; | ||
6590 | } | ||
6448 | } | 6591 | } |
6449 | 6592 | ||
6450 | /* Read the flags */ | 6593 | /* Read the flags */ |
@@ -6474,14 +6617,12 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6474 | struct airo_info *local = dev->ml_priv; | 6617 | struct airo_info *local = dev->ml_priv; |
6475 | struct iw_point *encoding = &wrqu->encoding; | 6618 | struct iw_point *encoding = &wrqu->encoding; |
6476 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 6619 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
6477 | CapabilityRid cap_rid; /* Card capability info */ | ||
6478 | int idx, max_key_len; | 6620 | int idx, max_key_len; |
6621 | u8 buf[16]; | ||
6479 | 6622 | ||
6480 | /* Is it supported ? */ | 6623 | if (!local->wep_capable) |
6481 | readCapabilityRid(local, &cap_rid, 1); | ||
6482 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6483 | return -EOPNOTSUPP; | 6624 | return -EOPNOTSUPP; |
6484 | } | 6625 | |
6485 | readConfigRid(local, 1); | 6626 | readConfigRid(local, 1); |
6486 | 6627 | ||
6487 | max_key_len = encoding->length - sizeof(*ext); | 6628 | max_key_len = encoding->length - sizeof(*ext); |
@@ -6490,11 +6631,14 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6490 | 6631 | ||
6491 | idx = encoding->flags & IW_ENCODE_INDEX; | 6632 | idx = encoding->flags & IW_ENCODE_INDEX; |
6492 | if (idx) { | 6633 | if (idx) { |
6493 | if (!valid_index(&cap_rid, idx - 1)) | 6634 | if (!valid_index(local, idx - 1)) |
6494 | return -EINVAL; | 6635 | return -EINVAL; |
6495 | idx--; | 6636 | idx--; |
6496 | } else | 6637 | } else { |
6497 | idx = get_wep_key(local, 0xffff); | 6638 | idx = get_wep_tx_idx(local); |
6639 | if (idx < 0) | ||
6640 | idx = 0; | ||
6641 | } | ||
6498 | 6642 | ||
6499 | encoding->flags = idx + 1; | 6643 | encoding->flags = idx + 1; |
6500 | memset(ext, 0, sizeof(*ext)); | 6644 | memset(ext, 0, sizeof(*ext)); |
@@ -6517,10 +6661,8 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6517 | memset(extra, 0, 16); | 6661 | memset(extra, 0, 16); |
6518 | 6662 | ||
6519 | /* Copy the key to the user buffer */ | 6663 | /* Copy the key to the user buffer */ |
6520 | ext->key_len = get_wep_key(local, idx); | 6664 | ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf)); |
6521 | if (ext->key_len > 16) { | 6665 | memcpy(extra, buf, ext->key_len); |
6522 | ext->key_len=0; | ||
6523 | } | ||
6524 | 6666 | ||
6525 | return 0; | 6667 | return 0; |
6526 | } | 6668 | } |
@@ -6795,8 +6937,8 @@ static int airo_get_range(struct net_device *dev, | |||
6795 | k = 0; | 6937 | k = 0; |
6796 | for(i = 0; i < 14; i++) { | 6938 | for(i = 0; i < 14; i++) { |
6797 | range->freq[k].i = i + 1; /* List index */ | 6939 | range->freq[k].i = i + 1; /* List index */ |
6798 | range->freq[k].m = frequency_list[i] * 100000; | 6940 | range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; |
6799 | range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ | 6941 | range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ |
6800 | } | 6942 | } |
6801 | range->num_frequency = k; | 6943 | range->num_frequency = k; |
6802 | 6944 | ||
@@ -7031,11 +7173,15 @@ static int airo_get_aplist(struct net_device *dev, | |||
7031 | { | 7173 | { |
7032 | struct airo_info *local = dev->ml_priv; | 7174 | struct airo_info *local = dev->ml_priv; |
7033 | struct sockaddr *address = (struct sockaddr *) extra; | 7175 | struct sockaddr *address = (struct sockaddr *) extra; |
7034 | struct iw_quality qual[IW_MAX_AP]; | 7176 | struct iw_quality *qual; |
7035 | BSSListRid BSSList; | 7177 | BSSListRid BSSList; |
7036 | int i; | 7178 | int i; |
7037 | int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; | 7179 | int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; |
7038 | 7180 | ||
7181 | qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL); | ||
7182 | if (!qual) | ||
7183 | return -ENOMEM; | ||
7184 | |||
7039 | for (i = 0; i < IW_MAX_AP; i++) { | 7185 | for (i = 0; i < IW_MAX_AP; i++) { |
7040 | u16 dBm; | 7186 | u16 dBm; |
7041 | if (readBSSListRid(local, loseSync, &BSSList)) | 7187 | if (readBSSListRid(local, loseSync, &BSSList)) |
@@ -7090,6 +7236,7 @@ static int airo_get_aplist(struct net_device *dev, | |||
7090 | } | 7236 | } |
7091 | dwrq->length = i; | 7237 | dwrq->length = i; |
7092 | 7238 | ||
7239 | kfree(qual); | ||
7093 | return 0; | 7240 | return 0; |
7094 | } | 7241 | } |
7095 | 7242 | ||
@@ -7189,10 +7336,7 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7189 | /* Add frequency */ | 7336 | /* Add frequency */ |
7190 | iwe.cmd = SIOCGIWFREQ; | 7337 | iwe.cmd = SIOCGIWFREQ; |
7191 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); | 7338 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); |
7192 | /* iwe.u.freq.m containt the channel (starting 1), our | 7339 | iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000; |
7193 | * frequency_list array start at index 0... | ||
7194 | */ | ||
7195 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; | ||
7196 | iwe.u.freq.e = 1; | 7340 | iwe.u.freq.e = 1; |
7197 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | 7341 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7198 | &iwe, IW_EV_FREQ_LEN); | 7342 | &iwe, IW_EV_FREQ_LEN); |