diff options
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r-- | drivers/net/wireless/airo.c | 1137 |
1 files changed, 626 insertions, 511 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index fc4322ca669f..acda45838e98 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 | ||
@@ -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 | ||
@@ -2730,28 +2739,6 @@ static void airo_networks_initialize(struct airo_info *ai) | |||
2730 | &ai->network_free_list); | 2739 | &ai->network_free_list); |
2731 | } | 2740 | } |
2732 | 2741 | ||
2733 | static int airo_test_wpa_capable(struct airo_info *ai) | ||
2734 | { | ||
2735 | int status; | ||
2736 | CapabilityRid cap_rid; | ||
2737 | |||
2738 | status = readCapabilityRid(ai, &cap_rid, 1); | ||
2739 | if (status != SUCCESS) return 0; | ||
2740 | |||
2741 | /* Only firmware versions 5.30.17 or better can do WPA */ | ||
2742 | if (le16_to_cpu(cap_rid.softVer) > 0x530 | ||
2743 | || (le16_to_cpu(cap_rid.softVer) == 0x530 | ||
2744 | && le16_to_cpu(cap_rid.softSubVer) >= 17)) { | ||
2745 | airo_print_info("", "WPA is supported."); | ||
2746 | return 1; | ||
2747 | } | ||
2748 | |||
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 | |||
2755 | static struct net_device *_init_airo_card( unsigned short irq, int port, | 2742 | static struct net_device *_init_airo_card( unsigned short irq, int port, |
2756 | int is_pcmcia, struct pci_dev *pci, | 2743 | int is_pcmcia, struct pci_dev *pci, |
2757 | struct device *dmdev ) | 2744 | struct device *dmdev ) |
@@ -2759,6 +2746,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2759 | struct net_device *dev; | 2746 | struct net_device *dev; |
2760 | struct airo_info *ai; | 2747 | struct airo_info *ai; |
2761 | int i, rc; | 2748 | int i, rc; |
2749 | CapabilityRid cap_rid; | ||
2762 | 2750 | ||
2763 | /* Create the network device object. */ | 2751 | /* Create the network device object. */ |
2764 | dev = alloc_netdev(sizeof(*ai), "", ether_setup); | 2752 | dev = alloc_netdev(sizeof(*ai), "", ether_setup); |
@@ -2828,7 +2816,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2828 | } | 2816 | } |
2829 | 2817 | ||
2830 | if (probe) { | 2818 | if (probe) { |
2831 | if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { | 2819 | if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) { |
2832 | airo_print_err(dev->name, "MAC could not be enabled" ); | 2820 | airo_print_err(dev->name, "MAC could not be enabled" ); |
2833 | rc = -EIO; | 2821 | rc = -EIO; |
2834 | goto err_out_map; | 2822 | goto err_out_map; |
@@ -2838,28 +2826,50 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2838 | set_bit(FLAG_FLASHING, &ai->flags); | 2826 | set_bit(FLAG_FLASHING, &ai->flags); |
2839 | } | 2827 | } |
2840 | 2828 | ||
2829 | strcpy(dev->name, "eth%d"); | ||
2830 | rc = register_netdev(dev); | ||
2831 | if (rc) { | ||
2832 | airo_print_err(dev->name, "Couldn't register_netdev"); | ||
2833 | goto err_out_map; | ||
2834 | } | ||
2835 | ai->wifidev = init_wifidev(ai, dev); | ||
2836 | if (!ai->wifidev) | ||
2837 | goto err_out_reg; | ||
2838 | |||
2839 | rc = readCapabilityRid(ai, &cap_rid, 1); | ||
2840 | if (rc != SUCCESS) { | ||
2841 | rc = -EIO; | ||
2842 | goto err_out_wifi; | ||
2843 | } | ||
2844 | /* WEP capability discovery */ | ||
2845 | ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; | ||
2846 | ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; | ||
2847 | |||
2848 | airo_print_info(dev->name, "Firmware version %x.%x.%02x", | ||
2849 | ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), | ||
2850 | (le16_to_cpu(cap_rid.softVer) & 0xFF), | ||
2851 | le16_to_cpu(cap_rid.softSubVer)); | ||
2852 | |||
2841 | /* Test for WPA support */ | 2853 | /* Test for WPA support */ |
2842 | if (airo_test_wpa_capable(ai)) { | 2854 | /* Only firmware versions 5.30.17 or better can do WPA */ |
2855 | if (le16_to_cpu(cap_rid.softVer) > 0x530 | ||
2856 | || (le16_to_cpu(cap_rid.softVer) == 0x530 | ||
2857 | && le16_to_cpu(cap_rid.softSubVer) >= 17)) { | ||
2858 | airo_print_info(ai->dev->name, "WPA supported."); | ||
2859 | |||
2843 | set_bit(FLAG_WPA_CAPABLE, &ai->flags); | 2860 | set_bit(FLAG_WPA_CAPABLE, &ai->flags); |
2844 | ai->bssListFirst = RID_WPA_BSSLISTFIRST; | 2861 | ai->bssListFirst = RID_WPA_BSSLISTFIRST; |
2845 | ai->bssListNext = RID_WPA_BSSLISTNEXT; | 2862 | ai->bssListNext = RID_WPA_BSSLISTNEXT; |
2846 | ai->bssListRidLen = sizeof(BSSListRid); | 2863 | ai->bssListRidLen = sizeof(BSSListRid); |
2847 | } else { | 2864 | } else { |
2865 | airo_print_info(ai->dev->name, "WPA unsupported with firmware " | ||
2866 | "versions older than 5.30.17."); | ||
2867 | |||
2848 | ai->bssListFirst = RID_BSSLISTFIRST; | 2868 | ai->bssListFirst = RID_BSSLISTFIRST; |
2849 | ai->bssListNext = RID_BSSLISTNEXT; | 2869 | ai->bssListNext = RID_BSSLISTNEXT; |
2850 | ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); | 2870 | ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); |
2851 | } | 2871 | } |
2852 | 2872 | ||
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); | 2873 | set_bit(FLAG_REGISTERED,&ai->flags); |
2864 | airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); | 2874 | airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); |
2865 | 2875 | ||
@@ -3127,314 +3137,354 @@ static int header_len(__le16 ctl) | |||
3127 | return 24; | 3137 | return 24; |
3128 | } | 3138 | } |
3129 | 3139 | ||
3130 | static irqreturn_t airo_interrupt(int irq, void *dev_id) | 3140 | static void airo_handle_cisco_mic(struct airo_info *ai) |
3131 | { | 3141 | { |
3132 | struct net_device *dev = dev_id; | 3142 | if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) { |
3143 | set_bit(JOB_MIC, &ai->jobs); | ||
3144 | wake_up_interruptible(&ai->thr_wait); | ||
3145 | } | ||
3146 | } | ||
3147 | |||
3148 | /* Airo Status codes */ | ||
3149 | #define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */ | ||
3150 | #define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */ | ||
3151 | #define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ | ||
3152 | #define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */ | ||
3153 | #define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ | ||
3154 | #define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */ | ||
3155 | #define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */ | ||
3156 | #define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */ | ||
3157 | #define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */ | ||
3158 | #define STAT_ASSOC 0x0400 /* Associated */ | ||
3159 | #define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ | ||
3160 | |||
3161 | static void airo_print_status(const char *devname, u16 status) | ||
3162 | { | ||
3163 | u8 reason = status & 0xFF; | ||
3164 | |||
3165 | switch (status) { | ||
3166 | case STAT_NOBEACON: | ||
3167 | airo_print_dbg(devname, "link lost (missed beacons)"); | ||
3168 | break; | ||
3169 | case STAT_MAXRETRIES: | ||
3170 | case STAT_MAXARL: | ||
3171 | airo_print_dbg(devname, "link lost (max retries)"); | ||
3172 | break; | ||
3173 | case STAT_FORCELOSS: | ||
3174 | airo_print_dbg(devname, "link lost (local choice)"); | ||
3175 | break; | ||
3176 | case STAT_TSFSYNC: | ||
3177 | airo_print_dbg(devname, "link lost (TSF sync lost)"); | ||
3178 | break; | ||
3179 | case STAT_DEAUTH: | ||
3180 | airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); | ||
3181 | break; | ||
3182 | case STAT_DISASSOC: | ||
3183 | airo_print_dbg(devname, "disassociated (reason: %d)", reason); | ||
3184 | break; | ||
3185 | case STAT_ASSOC_FAIL: | ||
3186 | airo_print_dbg(devname, "association failed (reason: %d)", | ||
3187 | reason); | ||
3188 | break; | ||
3189 | case STAT_AUTH_FAIL: | ||
3190 | airo_print_dbg(devname, "authentication failed (reason: %d)", | ||
3191 | reason); | ||
3192 | break; | ||
3193 | default: | ||
3194 | break; | ||
3195 | } | ||
3196 | } | ||
3197 | |||
3198 | static void airo_handle_link(struct airo_info *ai) | ||
3199 | { | ||
3200 | union iwreq_data wrqu; | ||
3201 | int scan_forceloss = 0; | ||
3133 | u16 status; | 3202 | u16 status; |
3134 | u16 fid; | ||
3135 | struct airo_info *apriv = dev->ml_priv; | ||
3136 | u16 savedInterrupts = 0; | ||
3137 | int handled = 0; | ||
3138 | 3203 | ||
3139 | if (!netif_device_present(dev)) | 3204 | /* Get new status and acknowledge the link change */ |
3140 | return IRQ_NONE; | 3205 | status = le16_to_cpu(IN4500(ai, LINKSTAT)); |
3206 | OUT4500(ai, EVACK, EV_LINK); | ||
3141 | 3207 | ||
3142 | for (;;) { | 3208 | if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0)) |
3143 | status = IN4500( apriv, EVSTAT ); | 3209 | scan_forceloss = 1; |
3144 | if ( !(status & STATUS_INTS) || status == 0xffff ) break; | ||
3145 | 3210 | ||
3146 | handled = 1; | 3211 | airo_print_status(ai->dev->name, status); |
3147 | 3212 | ||
3148 | if ( status & EV_AWAKE ) { | 3213 | if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) { |
3149 | OUT4500( apriv, EVACK, EV_AWAKE ); | 3214 | if (auto_wep) |
3150 | OUT4500( apriv, EVACK, EV_AWAKE ); | 3215 | ai->expires = 0; |
3151 | } | 3216 | if (ai->list_bss_task) |
3217 | wake_up_process(ai->list_bss_task); | ||
3218 | set_bit(FLAG_UPDATE_UNI, &ai->flags); | ||
3219 | set_bit(FLAG_UPDATE_MULTI, &ai->flags); | ||
3152 | 3220 | ||
3153 | if (!savedInterrupts) { | 3221 | if (down_trylock(&ai->sem) != 0) { |
3154 | savedInterrupts = IN4500( apriv, EVINTEN ); | 3222 | set_bit(JOB_EVENT, &ai->jobs); |
3155 | OUT4500( apriv, EVINTEN, 0 ); | 3223 | wake_up_interruptible(&ai->thr_wait); |
3224 | } else | ||
3225 | airo_send_event(ai->dev); | ||
3226 | } else if (!scan_forceloss) { | ||
3227 | if (auto_wep && !ai->expires) { | ||
3228 | ai->expires = RUN_AT(3*HZ); | ||
3229 | wake_up_interruptible(&ai->thr_wait); | ||
3156 | } | 3230 | } |
3157 | 3231 | ||
3158 | if ( status & EV_MIC ) { | 3232 | /* Send event to user space */ |
3159 | OUT4500( apriv, EVACK, EV_MIC ); | 3233 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); |
3160 | if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { | 3234 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
3161 | set_bit(JOB_MIC, &apriv->jobs); | 3235 | wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); |
3162 | wake_up_interruptible(&apriv->thr_wait); | 3236 | } |
3163 | } | 3237 | } |
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 | 3238 | ||
3225 | /* Send event to user space */ | 3239 | static void airo_handle_rx(struct airo_info *ai) |
3226 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | 3240 | { |
3227 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 3241 | struct sk_buff *skb = NULL; |
3228 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); | 3242 | __le16 fc, v, *buffer, tmpbuf[4]; |
3229 | } | 3243 | u16 len, hdrlen = 0, gap, fid; |
3230 | } | 3244 | struct rx_hdr hdr; |
3245 | int success = 0; | ||
3231 | 3246 | ||
3232 | /* Check to see if there is something to receive */ | 3247 | if (test_bit(FLAG_MPI, &ai->flags)) { |
3233 | if ( status & EV_RX ) { | 3248 | if (test_bit(FLAG_802_11, &ai->flags)) |
3234 | struct sk_buff *skb = NULL; | 3249 | mpi_receive_802_11(ai); |
3235 | __le16 fc, v; | 3250 | else |
3236 | u16 len, hdrlen = 0; | 3251 | mpi_receive_802_3(ai); |
3237 | #pragma pack(1) | 3252 | OUT4500(ai, EVACK, EV_RX); |
3238 | struct { | 3253 | return; |
3239 | __le16 status, len; | 3254 | } |
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 | 3255 | ||
3259 | fid = IN4500( apriv, RXFID ); | 3256 | 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 | 3257 | ||
3276 | if (len > AIRO_DEF_MTU) { | 3258 | /* Get the packet length */ |
3277 | airo_print_err(apriv->dev->name, "Bad size %d", len); | 3259 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3278 | goto badrx; | 3260 | bap_setup (ai, fid, 4, BAP0); |
3279 | } | 3261 | bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0); |
3280 | if (len == 0) | 3262 | /* Bad CRC. Ignore packet */ |
3281 | goto badrx; | 3263 | if (le16_to_cpu(hdr.status) & 2) |
3264 | hdr.len = 0; | ||
3265 | if (ai->wifidev == NULL) | ||
3266 | hdr.len = 0; | ||
3267 | } else { | ||
3268 | bap_setup(ai, fid, 0x36, BAP0); | ||
3269 | bap_read(ai, &hdr.len, 2, BAP0); | ||
3270 | } | ||
3271 | len = le16_to_cpu(hdr.len); | ||
3282 | 3272 | ||
3283 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3273 | if (len > AIRO_DEF_MTU) { |
3284 | bap_read (apriv, &fc, sizeof(fc), BAP0); | 3274 | airo_print_err(ai->dev->name, "Bad size %d", len); |
3285 | hdrlen = header_len(fc); | 3275 | goto done; |
3286 | } else | 3276 | } |
3287 | hdrlen = ETH_ALEN * 2; | 3277 | if (len == 0) |
3278 | goto done; | ||
3288 | 3279 | ||
3289 | skb = dev_alloc_skb( len + hdrlen + 2 + 2 ); | 3280 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3290 | if ( !skb ) { | 3281 | bap_read(ai, &fc, sizeof (fc), BAP0); |
3291 | dev->stats.rx_dropped++; | 3282 | hdrlen = header_len(fc); |
3292 | goto badrx; | 3283 | } else |
3293 | } | 3284 | hdrlen = ETH_ALEN * 2; |
3294 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | 3285 | |
3295 | buffer = (__le16*)skb_put (skb, len + hdrlen); | 3286 | skb = dev_alloc_skb(len + hdrlen + 2 + 2); |
3296 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3287 | if (!skb) { |
3297 | buffer[0] = fc; | 3288 | ai->dev->stats.rx_dropped++; |
3298 | bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); | 3289 | goto done; |
3299 | if (hdrlen == 24) | 3290 | } |
3300 | bap_read (apriv, tmpbuf, 6, BAP0); | 3291 | |
3301 | 3292 | skb_reserve(skb, 2); /* This way the IP header is aligned */ | |
3302 | bap_read (apriv, &v, sizeof(v), BAP0); | 3293 | buffer = (__le16 *) skb_put(skb, len + hdrlen); |
3303 | gap = le16_to_cpu(v); | 3294 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3304 | if (gap) { | 3295 | buffer[0] = fc; |
3305 | if (gap <= 8) { | 3296 | bap_read(ai, buffer + 1, hdrlen - 2, BAP0); |
3306 | bap_read (apriv, tmpbuf, gap, BAP0); | 3297 | if (hdrlen == 24) |
3307 | } else { | 3298 | bap_read(ai, tmpbuf, 6, BAP0); |
3308 | airo_print_err(apriv->dev->name, "gaplen too " | 3299 | |
3309 | "big. Problems will follow..."); | 3300 | bap_read(ai, &v, sizeof(v), BAP0); |
3310 | } | 3301 | gap = le16_to_cpu(v); |
3311 | } | 3302 | if (gap) { |
3312 | bap_read (apriv, buffer + hdrlen/2, len, BAP0); | 3303 | if (gap <= 8) { |
3304 | bap_read(ai, tmpbuf, gap, BAP0); | ||
3313 | } else { | 3305 | } else { |
3314 | MICBuffer micbuf; | 3306 | airo_print_err(ai->dev->name, "gaplen too " |
3315 | bap_read (apriv, buffer, ETH_ALEN*2, BAP0); | 3307 | "big. Problems will follow..."); |
3316 | if (apriv->micstats.enabled) { | 3308 | } |
3317 | bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0); | 3309 | } |
3318 | if (ntohs(micbuf.typelen) > 0x05DC) | 3310 | bap_read(ai, buffer + hdrlen/2, len, BAP0); |
3319 | bap_setup (apriv, fid, 0x44, BAP0); | 3311 | } else { |
3320 | else { | 3312 | MICBuffer micbuf; |
3321 | if (len <= sizeof(micbuf)) | 3313 | |
3322 | goto badmic; | 3314 | bap_read(ai, buffer, ETH_ALEN * 2, BAP0); |
3323 | 3315 | if (ai->micstats.enabled) { | |
3324 | len -= sizeof(micbuf); | 3316 | bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0); |
3325 | skb_trim (skb, len + hdrlen); | 3317 | if (ntohs(micbuf.typelen) > 0x05DC) |
3326 | } | 3318 | bap_setup(ai, fid, 0x44, BAP0); |
3327 | } | 3319 | else { |
3328 | bap_read(apriv,buffer+ETH_ALEN,len,BAP0); | 3320 | if (len <= sizeof (micbuf)) { |
3329 | if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { | 3321 | dev_kfree_skb_irq(skb); |
3330 | badmic: | 3322 | goto done; |
3331 | dev_kfree_skb_irq (skb); | ||
3332 | badrx: | ||
3333 | OUT4500( apriv, EVACK, EV_RX); | ||
3334 | goto exitrx; | ||
3335 | } | 3323 | } |
3324 | |||
3325 | len -= sizeof(micbuf); | ||
3326 | skb_trim(skb, len + hdrlen); | ||
3336 | } | 3327 | } |
3328 | } | ||
3329 | |||
3330 | bap_read(ai, buffer + ETH_ALEN, len, BAP0); | ||
3331 | if (decapsulate(ai, &micbuf, (etherHead*) buffer, len)) | ||
3332 | dev_kfree_skb_irq (skb); | ||
3333 | else | ||
3334 | success = 1; | ||
3335 | } | ||
3336 | |||
3337 | #ifdef WIRELESS_SPY | 3337 | #ifdef WIRELESS_SPY |
3338 | if (apriv->spy_data.spy_number > 0) { | 3338 | if (success && (ai->spy_data.spy_number > 0)) { |
3339 | char *sa; | 3339 | char *sa; |
3340 | struct iw_quality wstats; | 3340 | struct iw_quality wstats; |
3341 | /* Prepare spy data : addr + qual */ | 3341 | |
3342 | if (!test_bit(FLAG_802_11, &apriv->flags)) { | 3342 | /* Prepare spy data : addr + qual */ |
3343 | sa = (char*)buffer + 6; | 3343 | if (!test_bit(FLAG_802_11, &ai->flags)) { |
3344 | bap_setup (apriv, fid, 8, BAP0); | 3344 | sa = (char *) buffer + 6; |
3345 | bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0); | 3345 | bap_setup(ai, fid, 8, BAP0); |
3346 | } else | 3346 | bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0); |
3347 | sa = (char*)buffer + 10; | 3347 | } else |
3348 | wstats.qual = hdr.rssi[0]; | 3348 | sa = (char *) buffer + 10; |
3349 | if (apriv->rssi) | 3349 | wstats.qual = hdr.rssi[0]; |
3350 | wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; | 3350 | if (ai->rssi) |
3351 | else | 3351 | wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; |
3352 | wstats.level = (hdr.rssi[1] + 321) / 2; | 3352 | else |
3353 | wstats.noise = apriv->wstats.qual.noise; | 3353 | wstats.level = (hdr.rssi[1] + 321) / 2; |
3354 | wstats.updated = IW_QUAL_LEVEL_UPDATED | 3354 | wstats.noise = ai->wstats.qual.noise; |
3355 | | IW_QUAL_QUAL_UPDATED | 3355 | wstats.updated = IW_QUAL_LEVEL_UPDATED |
3356 | | IW_QUAL_DBM; | 3356 | | IW_QUAL_QUAL_UPDATED |
3357 | /* Update spy records */ | 3357 | | IW_QUAL_DBM; |
3358 | wireless_spy_update(dev, sa, &wstats); | 3358 | /* Update spy records */ |
3359 | } | 3359 | wireless_spy_update(ai->dev, sa, &wstats); |
3360 | } | ||
3360 | #endif /* WIRELESS_SPY */ | 3361 | #endif /* WIRELESS_SPY */ |
3361 | OUT4500( apriv, EVACK, EV_RX); | ||
3362 | 3362 | ||
3363 | if (test_bit(FLAG_802_11, &apriv->flags)) { | 3363 | done: |
3364 | skb_reset_mac_header(skb); | 3364 | OUT4500(ai, EVACK, EV_RX); |
3365 | skb->pkt_type = PACKET_OTHERHOST; | 3365 | |
3366 | skb->dev = apriv->wifidev; | 3366 | if (success) { |
3367 | skb->protocol = htons(ETH_P_802_2); | 3367 | if (test_bit(FLAG_802_11, &ai->flags)) { |
3368 | } else | 3368 | skb_reset_mac_header(skb); |
3369 | skb->protocol = eth_type_trans(skb,dev); | 3369 | skb->pkt_type = PACKET_OTHERHOST; |
3370 | skb->ip_summed = CHECKSUM_NONE; | 3370 | skb->dev = ai->wifidev; |
3371 | skb->protocol = htons(ETH_P_802_2); | ||
3372 | } else | ||
3373 | skb->protocol = eth_type_trans(skb, ai->dev); | ||
3374 | skb->ip_summed = CHECKSUM_NONE; | ||
3375 | |||
3376 | netif_rx(skb); | ||
3377 | } | ||
3378 | } | ||
3379 | |||
3380 | static void airo_handle_tx(struct airo_info *ai, u16 status) | ||
3381 | { | ||
3382 | int i, len = 0, index = -1; | ||
3383 | u16 fid; | ||
3371 | 3384 | ||
3372 | netif_rx( skb ); | 3385 | if (test_bit(FLAG_MPI, &ai->flags)) { |
3386 | unsigned long flags; | ||
3387 | |||
3388 | if (status & EV_TXEXC) | ||
3389 | get_tx_error(ai, -1); | ||
3390 | |||
3391 | spin_lock_irqsave(&ai->aux_lock, flags); | ||
3392 | if (!skb_queue_empty(&ai->txq)) { | ||
3393 | spin_unlock_irqrestore(&ai->aux_lock,flags); | ||
3394 | mpi_send_packet(ai->dev); | ||
3395 | } else { | ||
3396 | clear_bit(FLAG_PENDING_XMIT, &ai->flags); | ||
3397 | spin_unlock_irqrestore(&ai->aux_lock,flags); | ||
3398 | netif_wake_queue(ai->dev); | ||
3373 | } | 3399 | } |
3374 | exitrx: | 3400 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); |
3401 | return; | ||
3402 | } | ||
3375 | 3403 | ||
3376 | /* Check to see if a packet has been transmitted */ | 3404 | fid = IN4500(ai, TXCOMPLFID); |
3377 | if ( status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) { | ||
3378 | int i; | ||
3379 | int len = 0; | ||
3380 | int index = -1; | ||
3381 | |||
3382 | if (test_bit(FLAG_MPI,&apriv->flags)) { | ||
3383 | unsigned long flags; | ||
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 | 3405 | ||
3401 | fid = IN4500(apriv, TXCOMPLFID); | 3406 | for(i = 0; i < MAX_FIDS; i++) { |
3407 | if ((ai->fids[i] & 0xffff) == fid) { | ||
3408 | len = ai->fids[i] >> 16; | ||
3409 | index = i; | ||
3410 | } | ||
3411 | } | ||
3402 | 3412 | ||
3403 | for( i = 0; i < MAX_FIDS; i++ ) { | 3413 | if (index != -1) { |
3404 | if ( ( apriv->fids[i] & 0xffff ) == fid ) { | 3414 | if (status & EV_TXEXC) |
3405 | len = apriv->fids[i] >> 16; | 3415 | get_tx_error(ai, index); |
3406 | index = i; | 3416 | |
3407 | } | 3417 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC)); |
3408 | } | 3418 | |
3409 | if (index != -1) { | 3419 | /* Set up to be used again */ |
3410 | if (status & EV_TXEXC) | 3420 | ai->fids[index] &= 0xffff; |
3411 | get_tx_error(apriv, index); | 3421 | if (index < MAX_FIDS / 2) { |
3412 | OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); | 3422 | if (!test_bit(FLAG_PENDING_XMIT, &ai->flags)) |
3413 | /* Set up to be used again */ | 3423 | netif_wake_queue(ai->dev); |
3414 | apriv->fids[index] &= 0xffff; | 3424 | } else { |
3415 | if (index < MAX_FIDS / 2) { | 3425 | if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags)) |
3416 | if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags)) | 3426 | netif_wake_queue(ai->wifidev); |
3417 | netif_wake_queue(dev); | 3427 | } |
3418 | } else { | 3428 | } else { |
3419 | if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags)) | 3429 | OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); |
3420 | netif_wake_queue(apriv->wifidev); | 3430 | airo_print_err(ai->dev->name, "Unallocated FID was used to xmit"); |
3421 | } | 3431 | } |
3422 | } else { | 3432 | } |
3423 | OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); | 3433 | |
3424 | airo_print_err(apriv->dev->name, "Unallocated FID was " | 3434 | static irqreturn_t airo_interrupt(int irq, void *dev_id) |
3425 | "used to xmit" ); | 3435 | { |
3426 | } | 3436 | struct net_device *dev = dev_id; |
3437 | u16 status, savedInterrupts = 0; | ||
3438 | struct airo_info *ai = dev->ml_priv; | ||
3439 | int handled = 0; | ||
3440 | |||
3441 | if (!netif_device_present(dev)) | ||
3442 | return IRQ_NONE; | ||
3443 | |||
3444 | for (;;) { | ||
3445 | status = IN4500(ai, EVSTAT); | ||
3446 | if (!(status & STATUS_INTS) || (status == 0xffff)) | ||
3447 | break; | ||
3448 | |||
3449 | handled = 1; | ||
3450 | |||
3451 | if (status & EV_AWAKE) { | ||
3452 | OUT4500(ai, EVACK, EV_AWAKE); | ||
3453 | OUT4500(ai, EVACK, EV_AWAKE); | ||
3454 | } | ||
3455 | |||
3456 | if (!savedInterrupts) { | ||
3457 | savedInterrupts = IN4500(ai, EVINTEN); | ||
3458 | OUT4500(ai, EVINTEN, 0); | ||
3459 | } | ||
3460 | |||
3461 | if (status & EV_MIC) { | ||
3462 | OUT4500(ai, EVACK, EV_MIC); | ||
3463 | airo_handle_cisco_mic(ai); | ||
3427 | } | 3464 | } |
3428 | exittx: | 3465 | |
3429 | if ( status & ~STATUS_INTS & ~IGNORE_INTS ) | 3466 | if (status & EV_LINK) { |
3430 | airo_print_warn(apriv->dev->name, "Got weird status %x", | 3467 | /* Link status changed */ |
3468 | airo_handle_link(ai); | ||
3469 | } | ||
3470 | |||
3471 | /* Check to see if there is something to receive */ | ||
3472 | if (status & EV_RX) | ||
3473 | airo_handle_rx(ai); | ||
3474 | |||
3475 | /* Check to see if a packet has been transmitted */ | ||
3476 | if (status & (EV_TX | EV_TXCPY | EV_TXEXC)) | ||
3477 | airo_handle_tx(ai, status); | ||
3478 | |||
3479 | if ( status & ~STATUS_INTS & ~IGNORE_INTS ) { | ||
3480 | airo_print_warn(ai->dev->name, "Got weird status %x", | ||
3431 | status & ~STATUS_INTS & ~IGNORE_INTS ); | 3481 | status & ~STATUS_INTS & ~IGNORE_INTS ); |
3482 | } | ||
3432 | } | 3483 | } |
3433 | 3484 | ||
3434 | if (savedInterrupts) | 3485 | if (savedInterrupts) |
3435 | OUT4500( apriv, EVINTEN, savedInterrupts ); | 3486 | OUT4500(ai, EVINTEN, savedInterrupts); |
3436 | 3487 | ||
3437 | /* done.. */ | ||
3438 | return IRQ_RETVAL(handled); | 3488 | return IRQ_RETVAL(handled); |
3439 | } | 3489 | } |
3440 | 3490 | ||
@@ -3613,18 +3663,10 @@ static void mpi_receive_802_11(struct airo_info *ai) | |||
3613 | struct sk_buff *skb = NULL; | 3663 | struct sk_buff *skb = NULL; |
3614 | u16 len, hdrlen = 0; | 3664 | u16 len, hdrlen = 0; |
3615 | __le16 fc; | 3665 | __le16 fc; |
3616 | #pragma pack(1) | 3666 | 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; | 3667 | u16 gap; |
3626 | u16 *buffer; | 3668 | u16 *buffer; |
3627 | char *ptr = ai->rxfids[0].virtual_host_addr+4; | 3669 | char *ptr = ai->rxfids[0].virtual_host_addr + 4; |
3628 | 3670 | ||
3629 | memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); | 3671 | memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); |
3630 | memcpy ((char *)&hdr, ptr, sizeof(hdr)); | 3672 | memcpy ((char *)&hdr, ptr, sizeof(hdr)); |
@@ -3691,6 +3733,7 @@ static void mpi_receive_802_11(struct airo_info *ai) | |||
3691 | skb->protocol = htons(ETH_P_802_2); | 3733 | skb->protocol = htons(ETH_P_802_2); |
3692 | skb->ip_summed = CHECKSUM_NONE; | 3734 | skb->ip_summed = CHECKSUM_NONE; |
3693 | netif_rx( skb ); | 3735 | netif_rx( skb ); |
3736 | |||
3694 | badrx: | 3737 | badrx: |
3695 | if (rxd.valid == 0) { | 3738 | if (rxd.valid == 0) { |
3696 | rxd.valid = 1; | 3739 | rxd.valid = 1; |
@@ -5131,55 +5174,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, | |||
5131 | return rc; | 5174 | return rc; |
5132 | } | 5175 | } |
5133 | 5176 | ||
5134 | /* Returns the length of the key at the index. If index == 0xffff | 5177 | /* 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, | 5178 | * not exist. The buffer is assumed to be at least 16 bytes in length. |
5136 | * -1 will be returned. | ||
5137 | */ | 5179 | */ |
5138 | static int get_wep_key(struct airo_info *ai, u16 index) { | 5180 | static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen) |
5181 | { | ||
5139 | WepKeyRid wkr; | 5182 | WepKeyRid wkr; |
5140 | int rc; | 5183 | int rc; |
5141 | __le16 lastindex; | 5184 | __le16 lastindex; |
5142 | 5185 | ||
5143 | rc = readWepKeyRid(ai, &wkr, 1, 1); | 5186 | rc = readWepKeyRid(ai, &wkr, 1, 1); |
5144 | if (rc == SUCCESS) do { | 5187 | if (rc != SUCCESS) |
5188 | return -1; | ||
5189 | do { | ||
5145 | lastindex = wkr.kindex; | 5190 | lastindex = wkr.kindex; |
5146 | if (wkr.kindex == cpu_to_le16(index)) { | 5191 | if (le16_to_cpu(wkr.kindex) == index) { |
5147 | if (index == 0xffff) { | 5192 | int klen = min_t(int, buflen, le16_to_cpu(wkr.klen)); |
5148 | return wkr.mac[0]; | 5193 | memcpy(buf, wkr.key, klen); |
5149 | } | 5194 | return klen; |
5150 | return le16_to_cpu(wkr.klen); | ||
5151 | } | 5195 | } |
5152 | readWepKeyRid(ai, &wkr, 0, 1); | 5196 | rc = readWepKeyRid(ai, &wkr, 0, 1); |
5197 | if (rc != SUCCESS) | ||
5198 | return -1; | ||
5153 | } while (lastindex != wkr.kindex); | 5199 | } while (lastindex != wkr.kindex); |
5154 | return -1; | 5200 | return -1; |
5155 | } | 5201 | } |
5156 | 5202 | ||
5157 | static int set_wep_key(struct airo_info *ai, u16 index, | 5203 | static int get_wep_tx_idx(struct airo_info *ai) |
5158 | const char *key, u16 keylen, int perm, int lock ) | 5204 | { |
5205 | WepKeyRid wkr; | ||
5206 | int rc; | ||
5207 | __le16 lastindex; | ||
5208 | |||
5209 | rc = readWepKeyRid(ai, &wkr, 1, 1); | ||
5210 | if (rc != SUCCESS) | ||
5211 | return -1; | ||
5212 | do { | ||
5213 | lastindex = wkr.kindex; | ||
5214 | if (wkr.kindex == cpu_to_le16(0xffff)) | ||
5215 | return wkr.mac[0]; | ||
5216 | rc = readWepKeyRid(ai, &wkr, 0, 1); | ||
5217 | if (rc != SUCCESS) | ||
5218 | return -1; | ||
5219 | } while (lastindex != wkr.kindex); | ||
5220 | return -1; | ||
5221 | } | ||
5222 | |||
5223 | static int set_wep_key(struct airo_info *ai, u16 index, const char *key, | ||
5224 | u16 keylen, int perm, int lock) | ||
5159 | { | 5225 | { |
5160 | static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; | 5226 | static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; |
5161 | WepKeyRid wkr; | 5227 | WepKeyRid wkr; |
5228 | int rc; | ||
5162 | 5229 | ||
5163 | memset(&wkr, 0, sizeof(wkr)); | ||
5164 | if (keylen == 0) { | 5230 | if (keylen == 0) { |
5165 | // We are selecting which key to use | 5231 | airo_print_err(ai->dev->name, "%s: key length to set was zero", |
5166 | wkr.len = cpu_to_le16(sizeof(wkr)); | 5232 | __func__); |
5167 | wkr.kindex = cpu_to_le16(0xffff); | 5233 | 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 | } | 5234 | } |
5178 | 5235 | ||
5236 | memset(&wkr, 0, sizeof(wkr)); | ||
5237 | wkr.len = cpu_to_le16(sizeof(wkr)); | ||
5238 | wkr.kindex = cpu_to_le16(index); | ||
5239 | wkr.klen = cpu_to_le16(keylen); | ||
5240 | memcpy(wkr.key, key, keylen); | ||
5241 | memcpy(wkr.mac, macaddr, ETH_ALEN); | ||
5242 | |||
5179 | if (perm) disable_MAC(ai, lock); | 5243 | if (perm) disable_MAC(ai, lock); |
5180 | writeWepKeyRid(ai, &wkr, perm, lock); | 5244 | rc = writeWepKeyRid(ai, &wkr, perm, lock); |
5181 | if (perm) enable_MAC(ai, lock); | 5245 | if (perm) enable_MAC(ai, lock); |
5182 | return 0; | 5246 | return rc; |
5247 | } | ||
5248 | |||
5249 | static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock) | ||
5250 | { | ||
5251 | WepKeyRid wkr; | ||
5252 | int rc; | ||
5253 | |||
5254 | memset(&wkr, 0, sizeof(wkr)); | ||
5255 | wkr.len = cpu_to_le16(sizeof(wkr)); | ||
5256 | wkr.kindex = cpu_to_le16(0xffff); | ||
5257 | wkr.mac[0] = (char)index; | ||
5258 | |||
5259 | if (perm) { | ||
5260 | ai->defindex = (char)index; | ||
5261 | disable_MAC(ai, lock); | ||
5262 | } | ||
5263 | |||
5264 | rc = writeWepKeyRid(ai, &wkr, perm, lock); | ||
5265 | |||
5266 | if (perm) | ||
5267 | enable_MAC(ai, lock); | ||
5268 | return rc; | ||
5183 | } | 5269 | } |
5184 | 5270 | ||
5185 | static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | 5271 | static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { |
@@ -5187,7 +5273,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5187 | struct proc_dir_entry *dp = PDE(inode); | 5273 | struct proc_dir_entry *dp = PDE(inode); |
5188 | struct net_device *dev = dp->data; | 5274 | struct net_device *dev = dp->data; |
5189 | struct airo_info *ai = dev->ml_priv; | 5275 | struct airo_info *ai = dev->ml_priv; |
5190 | int i; | 5276 | int i, rc; |
5191 | char key[16]; | 5277 | char key[16]; |
5192 | u16 index = 0; | 5278 | u16 index = 0; |
5193 | int j = 0; | 5279 | int j = 0; |
@@ -5201,7 +5287,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5201 | (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { | 5287 | (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { |
5202 | index = data->wbuffer[0] - '0'; | 5288 | index = data->wbuffer[0] - '0'; |
5203 | if (data->wbuffer[1] == '\n') { | 5289 | if (data->wbuffer[1] == '\n') { |
5204 | set_wep_key(ai, index, NULL, 0, 1, 1); | 5290 | rc = set_wep_tx_idx(ai, index, 1, 1); |
5291 | if (rc < 0) { | ||
5292 | airo_print_err(ai->dev->name, "failed to set " | ||
5293 | "WEP transmit index to %d: %d.", | ||
5294 | index, rc); | ||
5295 | } | ||
5205 | return; | 5296 | return; |
5206 | } | 5297 | } |
5207 | j = 2; | 5298 | j = 2; |
@@ -5220,7 +5311,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | |||
5220 | break; | 5311 | break; |
5221 | } | 5312 | } |
5222 | } | 5313 | } |
5223 | set_wep_key(ai, index, key, i/3, 1, 1); | 5314 | |
5315 | rc = set_wep_key(ai, index, key, i/3, 1, 1); | ||
5316 | if (rc < 0) { | ||
5317 | airo_print_err(ai->dev->name, "failed to set WEP key at index " | ||
5318 | "%d: %d.", index, rc); | ||
5319 | } | ||
5224 | } | 5320 | } |
5225 | 5321 | ||
5226 | static int proc_wepkey_open( struct inode *inode, struct file *file ) | 5322 | static int proc_wepkey_open( struct inode *inode, struct file *file ) |
@@ -5451,13 +5547,13 @@ static void timer_func( struct net_device *dev ) { | |||
5451 | break; | 5547 | break; |
5452 | case AUTH_SHAREDKEY: | 5548 | case AUTH_SHAREDKEY: |
5453 | if (apriv->keyindex < auto_wep) { | 5549 | if (apriv->keyindex < auto_wep) { |
5454 | set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); | 5550 | set_wep_tx_idx(apriv, apriv->keyindex, 0, 0); |
5455 | apriv->config.authType = AUTH_SHAREDKEY; | 5551 | apriv->config.authType = AUTH_SHAREDKEY; |
5456 | apriv->keyindex++; | 5552 | apriv->keyindex++; |
5457 | } else { | 5553 | } else { |
5458 | /* Drop to ENCRYPT */ | 5554 | /* Drop to ENCRYPT */ |
5459 | apriv->keyindex = 0; | 5555 | apriv->keyindex = 0; |
5460 | set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); | 5556 | set_wep_tx_idx(apriv, apriv->defindex, 0, 0); |
5461 | apriv->config.authType = AUTH_ENCRYPT; | 5557 | apriv->config.authType = AUTH_ENCRYPT; |
5462 | } | 5558 | } |
5463 | break; | 5559 | break; |
@@ -5725,16 +5821,12 @@ static int airo_set_freq(struct net_device *dev, | |||
5725 | int rc = -EINPROGRESS; /* Call commit handler */ | 5821 | int rc = -EINPROGRESS; /* Call commit handler */ |
5726 | 5822 | ||
5727 | /* If setting by frequency, convert to a channel */ | 5823 | /* If setting by frequency, convert to a channel */ |
5728 | if((fwrq->e == 1) && | 5824 | if(fwrq->e == 1) { |
5729 | (fwrq->m >= (int) 2.412e8) && | ||
5730 | (fwrq->m <= (int) 2.487e8)) { | ||
5731 | int f = fwrq->m / 100000; | 5825 | int f = fwrq->m / 100000; |
5732 | int c = 0; | 5826 | |
5733 | while((c < 14) && (f != frequency_list[c])) | ||
5734 | c++; | ||
5735 | /* Hack to fall through... */ | 5827 | /* Hack to fall through... */ |
5736 | fwrq->e = 0; | 5828 | fwrq->e = 0; |
5737 | fwrq->m = c + 1; | 5829 | fwrq->m = ieee80211_freq_to_dsss_chan(f); |
5738 | } | 5830 | } |
5739 | /* Setting by channel number */ | 5831 | /* Setting by channel number */ |
5740 | if((fwrq->m > 1000) || (fwrq->e > 0)) | 5832 | if((fwrq->m > 1000) || (fwrq->e > 0)) |
@@ -5778,7 +5870,7 @@ static int airo_get_freq(struct net_device *dev, | |||
5778 | 5870 | ||
5779 | ch = le16_to_cpu(status_rid.channel); | 5871 | ch = le16_to_cpu(status_rid.channel); |
5780 | if((ch > 0) && (ch < 15)) { | 5872 | if((ch > 0) && (ch < 15)) { |
5781 | fwrq->m = frequency_list[ch - 1] * 100000; | 5873 | fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000; |
5782 | fwrq->e = 1; | 5874 | fwrq->e = 1; |
5783 | } else { | 5875 | } else { |
5784 | fwrq->m = ch; | 5876 | fwrq->m = ch; |
@@ -6234,11 +6326,9 @@ static int airo_get_mode(struct net_device *dev, | |||
6234 | return 0; | 6326 | return 0; |
6235 | } | 6327 | } |
6236 | 6328 | ||
6237 | static inline int valid_index(CapabilityRid *p, int index) | 6329 | static inline int valid_index(struct airo_info *ai, int index) |
6238 | { | 6330 | { |
6239 | if (index < 0) | 6331 | return (index >= 0) && (index <= ai->max_wep_idx); |
6240 | return 0; | ||
6241 | return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1); | ||
6242 | } | 6332 | } |
6243 | 6333 | ||
6244 | /*------------------------------------------------------------------*/ | 6334 | /*------------------------------------------------------------------*/ |
@@ -6251,16 +6341,13 @@ static int airo_set_encode(struct net_device *dev, | |||
6251 | char *extra) | 6341 | char *extra) |
6252 | { | 6342 | { |
6253 | struct airo_info *local = dev->ml_priv; | 6343 | struct airo_info *local = dev->ml_priv; |
6254 | CapabilityRid cap_rid; /* Card capability info */ | 6344 | 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; | 6345 | __le16 currentAuthType = local->config.authType; |
6346 | int rc = 0; | ||
6257 | 6347 | ||
6258 | /* Is WEP supported ? */ | 6348 | 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; | 6349 | return -EOPNOTSUPP; |
6263 | } */ | 6350 | |
6264 | readConfigRid(local, 1); | 6351 | readConfigRid(local, 1); |
6265 | 6352 | ||
6266 | /* Basic checking: do we have a key to set ? | 6353 | /* Basic checking: do we have a key to set ? |
@@ -6272,14 +6359,21 @@ static int airo_set_encode(struct net_device *dev, | |||
6272 | if (dwrq->length > 0) { | 6359 | if (dwrq->length > 0) { |
6273 | wep_key_t key; | 6360 | wep_key_t key; |
6274 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6361 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6275 | int current_index = get_wep_key(local, 0xffff); | 6362 | int current_index; |
6363 | |||
6276 | /* Check the size of the key */ | 6364 | /* Check the size of the key */ |
6277 | if (dwrq->length > MAX_KEY_SIZE) { | 6365 | if (dwrq->length > MAX_KEY_SIZE) { |
6278 | return -EINVAL; | 6366 | return -EINVAL; |
6279 | } | 6367 | } |
6368 | |||
6369 | current_index = get_wep_tx_idx(local); | ||
6370 | if (current_index < 0) | ||
6371 | current_index = 0; | ||
6372 | |||
6280 | /* Check the index (none -> use current) */ | 6373 | /* Check the index (none -> use current) */ |
6281 | if (!valid_index(&cap_rid, index)) | 6374 | if (!valid_index(local, index)) |
6282 | index = current_index; | 6375 | index = current_index; |
6376 | |||
6283 | /* Set the length */ | 6377 | /* Set the length */ |
6284 | if (dwrq->length > MIN_KEY_SIZE) | 6378 | if (dwrq->length > MIN_KEY_SIZE) |
6285 | key.len = MAX_KEY_SIZE; | 6379 | key.len = MAX_KEY_SIZE; |
@@ -6296,7 +6390,13 @@ static int airo_set_encode(struct net_device *dev, | |||
6296 | /* Copy the key in the driver */ | 6390 | /* Copy the key in the driver */ |
6297 | memcpy(key.key, extra, dwrq->length); | 6391 | memcpy(key.key, extra, dwrq->length); |
6298 | /* Send the key to the card */ | 6392 | /* Send the key to the card */ |
6299 | set_wep_key(local, index, key.key, key.len, perm, 1); | 6393 | rc = set_wep_key(local, index, key.key, key.len, perm, 1); |
6394 | if (rc < 0) { | ||
6395 | airo_print_err(local->dev->name, "failed to set" | ||
6396 | " WEP key at index %d: %d.", | ||
6397 | index, rc); | ||
6398 | return rc; | ||
6399 | } | ||
6300 | } | 6400 | } |
6301 | /* WE specify that if a valid key is set, encryption | 6401 | /* WE specify that if a valid key is set, encryption |
6302 | * should be enabled (user may turn it off later) | 6402 | * should be enabled (user may turn it off later) |
@@ -6308,12 +6408,19 @@ static int airo_set_encode(struct net_device *dev, | |||
6308 | } else { | 6408 | } else { |
6309 | /* Do we want to just set the transmit key index ? */ | 6409 | /* Do we want to just set the transmit key index ? */ |
6310 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6410 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6311 | if (valid_index(&cap_rid, index)) { | 6411 | if (valid_index(local, index)) { |
6312 | set_wep_key(local, index, NULL, 0, perm, 1); | 6412 | rc = set_wep_tx_idx(local, index, perm, 1); |
6313 | } else | 6413 | if (rc < 0) { |
6414 | airo_print_err(local->dev->name, "failed to set" | ||
6415 | " WEP transmit index to %d: %d.", | ||
6416 | index, rc); | ||
6417 | return rc; | ||
6418 | } | ||
6419 | } else { | ||
6314 | /* Don't complain if only change the mode */ | 6420 | /* Don't complain if only change the mode */ |
6315 | if (!(dwrq->flags & IW_ENCODE_MODE)) | 6421 | if (!(dwrq->flags & IW_ENCODE_MODE)) |
6316 | return -EINVAL; | 6422 | return -EINVAL; |
6423 | } | ||
6317 | } | 6424 | } |
6318 | /* Read the flags */ | 6425 | /* Read the flags */ |
6319 | if(dwrq->flags & IW_ENCODE_DISABLED) | 6426 | if(dwrq->flags & IW_ENCODE_DISABLED) |
@@ -6339,14 +6446,13 @@ static int airo_get_encode(struct net_device *dev, | |||
6339 | { | 6446 | { |
6340 | struct airo_info *local = dev->ml_priv; | 6447 | struct airo_info *local = dev->ml_priv; |
6341 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6448 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6342 | CapabilityRid cap_rid; /* Card capability info */ | 6449 | u8 buf[16]; |
6343 | 6450 | ||
6344 | /* Is it supported ? */ | 6451 | if (!local->wep_capable) |
6345 | readCapabilityRid(local, &cap_rid, 1); | ||
6346 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6347 | return -EOPNOTSUPP; | 6452 | return -EOPNOTSUPP; |
6348 | } | 6453 | |
6349 | readConfigRid(local, 1); | 6454 | readConfigRid(local, 1); |
6455 | |||
6350 | /* Check encryption mode */ | 6456 | /* Check encryption mode */ |
6351 | switch(local->config.authType) { | 6457 | switch(local->config.authType) { |
6352 | case AUTH_ENCRYPT: | 6458 | case AUTH_ENCRYPT: |
@@ -6365,14 +6471,17 @@ static int airo_get_encode(struct net_device *dev, | |||
6365 | memset(extra, 0, 16); | 6471 | memset(extra, 0, 16); |
6366 | 6472 | ||
6367 | /* Which key do we want ? -1 -> tx index */ | 6473 | /* Which key do we want ? -1 -> tx index */ |
6368 | if (!valid_index(&cap_rid, index)) | 6474 | if (!valid_index(local, index)) { |
6369 | index = get_wep_key(local, 0xffff); | 6475 | index = get_wep_tx_idx(local); |
6476 | if (index < 0) | ||
6477 | index = 0; | ||
6478 | } | ||
6370 | dwrq->flags |= index + 1; | 6479 | dwrq->flags |= index + 1; |
6480 | |||
6371 | /* Copy the key to the user buffer */ | 6481 | /* Copy the key to the user buffer */ |
6372 | dwrq->length = get_wep_key(local, index); | 6482 | dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf)); |
6373 | if (dwrq->length > 16) { | 6483 | memcpy(extra, buf, dwrq->length); |
6374 | dwrq->length=0; | 6484 | |
6375 | } | ||
6376 | return 0; | 6485 | return 0; |
6377 | } | 6486 | } |
6378 | 6487 | ||
@@ -6388,28 +6497,27 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6388 | struct airo_info *local = dev->ml_priv; | 6497 | struct airo_info *local = dev->ml_priv; |
6389 | struct iw_point *encoding = &wrqu->encoding; | 6498 | struct iw_point *encoding = &wrqu->encoding; |
6390 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 6499 | 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 ); | 6500 | int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); |
6393 | __le16 currentAuthType = local->config.authType; | 6501 | __le16 currentAuthType = local->config.authType; |
6394 | int idx, key_len, alg = ext->alg, set_key = 1; | 6502 | int idx, key_len, alg = ext->alg, set_key = 1, rc; |
6395 | wep_key_t key; | 6503 | wep_key_t key; |
6396 | 6504 | ||
6397 | /* Is WEP supported ? */ | 6505 | 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; | 6506 | return -EOPNOTSUPP; |
6402 | } */ | 6507 | |
6403 | readConfigRid(local, 1); | 6508 | readConfigRid(local, 1); |
6404 | 6509 | ||
6405 | /* Determine and validate the key index */ | 6510 | /* Determine and validate the key index */ |
6406 | idx = encoding->flags & IW_ENCODE_INDEX; | 6511 | idx = encoding->flags & IW_ENCODE_INDEX; |
6407 | if (idx) { | 6512 | if (idx) { |
6408 | if (!valid_index(&cap_rid, idx - 1)) | 6513 | if (!valid_index(local, idx - 1)) |
6409 | return -EINVAL; | 6514 | return -EINVAL; |
6410 | idx--; | 6515 | idx--; |
6411 | } else | 6516 | } else { |
6412 | idx = get_wep_key(local, 0xffff); | 6517 | idx = get_wep_tx_idx(local); |
6518 | if (idx < 0) | ||
6519 | idx = 0; | ||
6520 | } | ||
6413 | 6521 | ||
6414 | if (encoding->flags & IW_ENCODE_DISABLED) | 6522 | if (encoding->flags & IW_ENCODE_DISABLED) |
6415 | alg = IW_ENCODE_ALG_NONE; | 6523 | alg = IW_ENCODE_ALG_NONE; |
@@ -6418,7 +6526,13 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6418 | /* Only set transmit key index here, actual | 6526 | /* Only set transmit key index here, actual |
6419 | * key is set below if needed. | 6527 | * key is set below if needed. |
6420 | */ | 6528 | */ |
6421 | set_wep_key(local, idx, NULL, 0, perm, 1); | 6529 | rc = set_wep_tx_idx(local, idx, perm, 1); |
6530 | if (rc < 0) { | ||
6531 | airo_print_err(local->dev->name, "failed to set " | ||
6532 | "WEP transmit index to %d: %d.", | ||
6533 | idx, rc); | ||
6534 | return rc; | ||
6535 | } | ||
6422 | set_key = ext->key_len > 0 ? 1 : 0; | 6536 | set_key = ext->key_len > 0 ? 1 : 0; |
6423 | } | 6537 | } |
6424 | 6538 | ||
@@ -6444,7 +6558,12 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6444 | return -EINVAL; | 6558 | return -EINVAL; |
6445 | } | 6559 | } |
6446 | /* Send the key to the card */ | 6560 | /* Send the key to the card */ |
6447 | set_wep_key(local, idx, key.key, key.len, perm, 1); | 6561 | rc = set_wep_key(local, idx, key.key, key.len, perm, 1); |
6562 | if (rc < 0) { | ||
6563 | airo_print_err(local->dev->name, "failed to set WEP key" | ||
6564 | " at index %d: %d.", idx, rc); | ||
6565 | return rc; | ||
6566 | } | ||
6448 | } | 6567 | } |
6449 | 6568 | ||
6450 | /* Read the flags */ | 6569 | /* Read the flags */ |
@@ -6474,14 +6593,12 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6474 | struct airo_info *local = dev->ml_priv; | 6593 | struct airo_info *local = dev->ml_priv; |
6475 | struct iw_point *encoding = &wrqu->encoding; | 6594 | struct iw_point *encoding = &wrqu->encoding; |
6476 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 6595 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
6477 | CapabilityRid cap_rid; /* Card capability info */ | ||
6478 | int idx, max_key_len; | 6596 | int idx, max_key_len; |
6597 | u8 buf[16]; | ||
6479 | 6598 | ||
6480 | /* Is it supported ? */ | 6599 | if (!local->wep_capable) |
6481 | readCapabilityRid(local, &cap_rid, 1); | ||
6482 | if(!(cap_rid.softCap & cpu_to_le16(2))) { | ||
6483 | return -EOPNOTSUPP; | 6600 | return -EOPNOTSUPP; |
6484 | } | 6601 | |
6485 | readConfigRid(local, 1); | 6602 | readConfigRid(local, 1); |
6486 | 6603 | ||
6487 | max_key_len = encoding->length - sizeof(*ext); | 6604 | max_key_len = encoding->length - sizeof(*ext); |
@@ -6490,11 +6607,14 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6490 | 6607 | ||
6491 | idx = encoding->flags & IW_ENCODE_INDEX; | 6608 | idx = encoding->flags & IW_ENCODE_INDEX; |
6492 | if (idx) { | 6609 | if (idx) { |
6493 | if (!valid_index(&cap_rid, idx - 1)) | 6610 | if (!valid_index(local, idx - 1)) |
6494 | return -EINVAL; | 6611 | return -EINVAL; |
6495 | idx--; | 6612 | idx--; |
6496 | } else | 6613 | } else { |
6497 | idx = get_wep_key(local, 0xffff); | 6614 | idx = get_wep_tx_idx(local); |
6615 | if (idx < 0) | ||
6616 | idx = 0; | ||
6617 | } | ||
6498 | 6618 | ||
6499 | encoding->flags = idx + 1; | 6619 | encoding->flags = idx + 1; |
6500 | memset(ext, 0, sizeof(*ext)); | 6620 | memset(ext, 0, sizeof(*ext)); |
@@ -6517,10 +6637,8 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6517 | memset(extra, 0, 16); | 6637 | memset(extra, 0, 16); |
6518 | 6638 | ||
6519 | /* Copy the key to the user buffer */ | 6639 | /* Copy the key to the user buffer */ |
6520 | ext->key_len = get_wep_key(local, idx); | 6640 | ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf)); |
6521 | if (ext->key_len > 16) { | 6641 | memcpy(extra, buf, ext->key_len); |
6522 | ext->key_len=0; | ||
6523 | } | ||
6524 | 6642 | ||
6525 | return 0; | 6643 | return 0; |
6526 | } | 6644 | } |
@@ -6795,8 +6913,8 @@ static int airo_get_range(struct net_device *dev, | |||
6795 | k = 0; | 6913 | k = 0; |
6796 | for(i = 0; i < 14; i++) { | 6914 | for(i = 0; i < 14; i++) { |
6797 | range->freq[k].i = i + 1; /* List index */ | 6915 | range->freq[k].i = i + 1; /* List index */ |
6798 | range->freq[k].m = frequency_list[i] * 100000; | 6916 | 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 */ | 6917 | range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ |
6800 | } | 6918 | } |
6801 | range->num_frequency = k; | 6919 | range->num_frequency = k; |
6802 | 6920 | ||
@@ -7189,10 +7307,7 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7189 | /* Add frequency */ | 7307 | /* Add frequency */ |
7190 | iwe.cmd = SIOCGIWFREQ; | 7308 | iwe.cmd = SIOCGIWFREQ; |
7191 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); | 7309 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); |
7192 | /* iwe.u.freq.m containt the channel (starting 1), our | 7310 | 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; | 7311 | iwe.u.freq.e = 1; |
7197 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | 7312 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7198 | &iwe, IW_EV_FREQ_LEN); | 7313 | &iwe, IW_EV_FREQ_LEN); |