aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco/hw.c')
-rw-r--r--drivers/net/wireless/orinoco/hw.c120
1 files changed, 94 insertions, 26 deletions
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index fa508af1a351..40d8dfa7eace 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -642,7 +642,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
642{ 642{
643 hermes_t *hw = &priv->hw; 643 hermes_t *hw = &priv->hw;
644 int err = 0; 644 int err = 0;
645 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; 645 u8 tsc_arr[4][ORINOCO_SEQ_LEN];
646 646
647 if ((key < 0) || (key > 4)) 647 if ((key < 0) || (key > 4))
648 return -EINVAL; 648 return -EINVAL;
@@ -768,12 +768,29 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
768{ 768{
769 hermes_t *hw = &priv->hw; 769 hermes_t *hw = &priv->hw;
770 int err = 0; 770 int err = 0;
771 int i;
771 772
772 switch (priv->firmware_type) { 773 switch (priv->firmware_type) {
773 case FIRMWARE_TYPE_AGERE: 774 case FIRMWARE_TYPE_AGERE:
775 {
776 struct orinoco_key keys[ORINOCO_MAX_KEYS];
777
778 memset(&keys, 0, sizeof(keys));
779 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
780 int len = min(priv->keys[i].key_len,
781 ORINOCO_MAX_KEY_SIZE);
782 memcpy(&keys[i].data, priv->keys[i].key, len);
783 if (len > SMALL_KEY_SIZE)
784 keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
785 else if (len > 0)
786 keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
787 else
788 keys[i].len = cpu_to_le16(0);
789 }
790
774 err = HERMES_WRITE_RECORD(hw, USER_BAP, 791 err = HERMES_WRITE_RECORD(hw, USER_BAP,
775 HERMES_RID_CNFWEPKEYS_AGERE, 792 HERMES_RID_CNFWEPKEYS_AGERE,
776 &priv->keys); 793 &keys);
777 if (err) 794 if (err)
778 return err; 795 return err;
779 err = hermes_write_wordrec(hw, USER_BAP, 796 err = hermes_write_wordrec(hw, USER_BAP,
@@ -782,28 +799,38 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
782 if (err) 799 if (err)
783 return err; 800 return err;
784 break; 801 break;
802 }
785 case FIRMWARE_TYPE_INTERSIL: 803 case FIRMWARE_TYPE_INTERSIL:
786 case FIRMWARE_TYPE_SYMBOL: 804 case FIRMWARE_TYPE_SYMBOL:
787 { 805 {
788 int keylen; 806 int keylen;
789 int i;
790 807
791 /* Force uniform key length to work around 808 /* Force uniform key length to work around
792 * firmware bugs */ 809 * firmware bugs */
793 keylen = le16_to_cpu(priv->keys[priv->tx_key].len); 810 keylen = priv->keys[priv->tx_key].key_len;
794 811
795 if (keylen > LARGE_KEY_SIZE) { 812 if (keylen > LARGE_KEY_SIZE) {
796 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", 813 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
797 priv->ndev->name, priv->tx_key, keylen); 814 priv->ndev->name, priv->tx_key, keylen);
798 return -E2BIG; 815 return -E2BIG;
799 } 816 } else if (keylen > SMALL_KEY_SIZE)
817 keylen = LARGE_KEY_SIZE;
818 else if (keylen > 0)
819 keylen = SMALL_KEY_SIZE;
820 else
821 keylen = 0;
800 822
801 /* Write all 4 keys */ 823 /* Write all 4 keys */
802 for (i = 0; i < ORINOCO_MAX_KEYS; i++) { 824 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
825 u8 key[LARGE_KEY_SIZE] = { 0 };
826
827 memcpy(key, priv->keys[i].key,
828 priv->keys[i].key_len);
829
803 err = hermes_write_ltv(hw, USER_BAP, 830 err = hermes_write_ltv(hw, USER_BAP,
804 HERMES_RID_CNFDEFAULTKEY0 + i, 831 HERMES_RID_CNFDEFAULTKEY0 + i,
805 HERMES_BYTES_TO_RECLEN(keylen), 832 HERMES_BYTES_TO_RECLEN(keylen),
806 priv->keys[i].data); 833 key);
807 if (err) 834 if (err)
808 return err; 835 return err;
809 } 836 }
@@ -829,8 +856,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
829 int auth_flag; 856 int auth_flag;
830 int enc_flag; 857 int enc_flag;
831 858
832 /* Setup WEP keys for WEP and WPA */ 859 /* Setup WEP keys */
833 if (priv->encode_alg) 860 if (priv->encode_alg == ORINOCO_ALG_WEP)
834 __orinoco_hw_setup_wepkeys(priv); 861 __orinoco_hw_setup_wepkeys(priv);
835 862
836 if (priv->wep_restrict) 863 if (priv->wep_restrict)
@@ -840,14 +867,14 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
840 867
841 if (priv->wpa_enabled) 868 if (priv->wpa_enabled)
842 enc_flag = 2; 869 enc_flag = 2;
843 else if (priv->encode_alg == IW_ENCODE_ALG_WEP) 870 else if (priv->encode_alg == ORINOCO_ALG_WEP)
844 enc_flag = 1; 871 enc_flag = 1;
845 else 872 else
846 enc_flag = 0; 873 enc_flag = 0;
847 874
848 switch (priv->firmware_type) { 875 switch (priv->firmware_type) {
849 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ 876 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
850 if (priv->encode_alg == IW_ENCODE_ALG_WEP) { 877 if (priv->encode_alg == ORINOCO_ALG_WEP) {
851 /* Enable the shared-key authentication. */ 878 /* Enable the shared-key authentication. */
852 err = hermes_write_wordrec(hw, USER_BAP, 879 err = hermes_write_wordrec(hw, USER_BAP,
853 HERMES_RID_CNFAUTHENTICATION_AGERE, 880 HERMES_RID_CNFAUTHENTICATION_AGERE,
@@ -872,7 +899,7 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
872 899
873 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ 900 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
874 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ 901 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
875 if (priv->encode_alg == IW_ENCODE_ALG_WEP) { 902 if (priv->encode_alg == ORINOCO_ALG_WEP) {
876 if (priv->wep_restrict || 903 if (priv->wep_restrict ||
877 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)) 904 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
878 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED | 905 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
@@ -905,19 +932,20 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
905} 932}
906 933
907/* key must be 32 bytes, including the tx and rx MIC keys. 934/* key must be 32 bytes, including the tx and rx MIC keys.
908 * rsc must be 8 bytes 935 * rsc must be NULL or up to 8 bytes
909 * tsc must be 8 bytes or NULL 936 * tsc must be NULL or up to 8 bytes
910 */ 937 */
911int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, 938int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
912 int set_tx, u8 *key, u8 *rsc, u8 *tsc) 939 int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
940 u8 *tsc, size_t tsc_len)
913{ 941{
914 struct { 942 struct {
915 __le16 idx; 943 __le16 idx;
916 u8 rsc[IW_ENCODE_SEQ_MAX_SIZE]; 944 u8 rsc[ORINOCO_SEQ_LEN];
917 u8 key[TKIP_KEYLEN]; 945 u8 key[TKIP_KEYLEN];
918 u8 tx_mic[MIC_KEYLEN]; 946 u8 tx_mic[MIC_KEYLEN];
919 u8 rx_mic[MIC_KEYLEN]; 947 u8 rx_mic[MIC_KEYLEN];
920 u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; 948 u8 tsc[ORINOCO_SEQ_LEN];
921 } __attribute__ ((packed)) buf; 949 } __attribute__ ((packed)) buf;
922 hermes_t *hw = &priv->hw; 950 hermes_t *hw = &priv->hw;
923 int ret; 951 int ret;
@@ -934,17 +962,22 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
934 memcpy(buf.key, key, 962 memcpy(buf.key, key,
935 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic)); 963 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
936 964
937 if (rsc == NULL) 965 if (rsc_len > sizeof(buf.rsc))
938 memset(buf.rsc, 0, sizeof(buf.rsc)); 966 rsc_len = sizeof(buf.rsc);
939 else
940 memcpy(buf.rsc, rsc, sizeof(buf.rsc));
941 967
942 if (tsc == NULL) { 968 if (tsc_len > sizeof(buf.tsc))
943 memset(buf.tsc, 0, sizeof(buf.tsc)); 969 tsc_len = sizeof(buf.tsc);
970
971 memset(buf.rsc, 0, sizeof(buf.rsc));
972 memset(buf.tsc, 0, sizeof(buf.tsc));
973
974 if (rsc != NULL)
975 memcpy(buf.rsc, rsc, rsc_len);
976
977 if (tsc != NULL)
978 memcpy(buf.tsc, tsc, tsc_len);
979 else
944 buf.tsc[4] = 0x10; 980 buf.tsc[4] = 0x10;
945 } else {
946 memcpy(buf.tsc, tsc, sizeof(buf.tsc));
947 }
948 981
949 /* Wait upto 100ms for tx queue to empty */ 982 /* Wait upto 100ms for tx queue to empty */
950 for (k = 100; k > 0; k--) { 983 for (k = 100; k > 0; k--) {
@@ -970,7 +1003,6 @@ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
970 hermes_t *hw = &priv->hw; 1003 hermes_t *hw = &priv->hw;
971 int err; 1004 int err;
972 1005
973 memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
974 err = hermes_write_wordrec(hw, USER_BAP, 1006 err = hermes_write_wordrec(hw, USER_BAP,
975 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE, 1007 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
976 key_idx); 1008 key_idx);
@@ -1242,3 +1274,39 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
1242 1274
1243 return err; 1275 return err;
1244} 1276}
1277
1278/* Disassociate from node with BSSID addr */
1279int orinoco_hw_disassociate(struct orinoco_private *priv,
1280 u8 *addr, u16 reason_code)
1281{
1282 hermes_t *hw = &priv->hw;
1283 int err;
1284
1285 struct {
1286 u8 addr[ETH_ALEN];
1287 __le16 reason_code;
1288 } __attribute__ ((packed)) buf;
1289
1290 /* Currently only supported by WPA enabled Agere fw */
1291 if (!priv->has_wpa)
1292 return -EOPNOTSUPP;
1293
1294 memcpy(buf.addr, addr, ETH_ALEN);
1295 buf.reason_code = cpu_to_le16(reason_code);
1296 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1297 HERMES_RID_CNFDISASSOCIATE,
1298 &buf);
1299 return err;
1300}
1301
1302int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
1303 u8 *addr)
1304{
1305 hermes_t *hw = &priv->hw;
1306 int err;
1307
1308 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1309 ETH_ALEN, NULL, addr);
1310
1311 return err;
1312}