diff options
author | Karl Relton <karllinuxtest.relton@ntlworld.com> | 2009-04-17 05:15:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-19 14:00:38 -0400 |
commit | 76e3e7c4095237ceeb962e3bd8bdc0797fb943e1 (patch) | |
tree | 8fe9b54c1dd8f0447fdbdbccb35542f33ce928cd /drivers/staging | |
parent | 24b8a9dfc7746273bde5a2030e4f16391251e830 (diff) |
Staging: wlan-ng: Move firmware loading into driver
Move prism2 firmware loading from userspace into driver, using linux
request_firmware(). Firmware is now loaded (if available) on device
probing, before it is registered as a netdevice and advertised to userspace.
Signed-off-by: Karl Relton <karllinuxtest.relton@ntlworld.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/wlan-ng/hfa384x.h | 244 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211metadef.h | 48 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211netdev.c | 14 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/p80211netdev.h | 3 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/prism2fw.c | 1410 | ||||
-rw-r--r-- | drivers/staging/wlan-ng/prism2usb.c | 9 |
6 files changed, 1707 insertions, 21 deletions
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f3e87173471..24d8708ec12 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h | |||
@@ -64,6 +64,7 @@ | |||
64 | #define HFA384x_PORTID_MAX ((u16)7) | 64 | #define HFA384x_PORTID_MAX ((u16)7) |
65 | #define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1)) | 65 | #define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1)) |
66 | #define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ | 66 | #define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ |
67 | #define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */ | ||
67 | #define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */ | 68 | #define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */ |
68 | #define HFA384x_SCANRESULT_MAX ((u16)31) | 69 | #define HFA384x_SCANRESULT_MAX ((u16)31) |
69 | #define HFA384x_HSCANRESULT_MAX ((u16)31) | 70 | #define HFA384x_HSCANRESULT_MAX ((u16)31) |
@@ -882,6 +883,249 @@ typedef union hfa384x_usbin { | |||
882 | u8 boguspad[3000]; | 883 | u8 boguspad[3000]; |
883 | } __attribute__ ((packed)) hfa384x_usbin_t; | 884 | } __attribute__ ((packed)) hfa384x_usbin_t; |
884 | 885 | ||
886 | /*-------------------------------------------------------------------- | ||
887 | PD record structures. | ||
888 | --------------------------------------------------------------------*/ | ||
889 | |||
890 | typedef struct hfa384x_pdr_pcb_partnum | ||
891 | { | ||
892 | u8 num[8]; | ||
893 | } __attribute__ ((packed)) hfa384x_pdr_pcb_partnum_t; | ||
894 | |||
895 | typedef struct hfa384x_pdr_pcb_tracenum | ||
896 | { | ||
897 | u8 num[8]; | ||
898 | } __attribute__ ((packed)) hfa384x_pdr_pcb_tracenum_t; | ||
899 | |||
900 | typedef struct hfa384x_pdr_nic_serial | ||
901 | { | ||
902 | u8 num[12]; | ||
903 | } __attribute__ ((packed)) hfa384x_pdr_nic_serial_t; | ||
904 | |||
905 | typedef struct hfa384x_pdr_mkk_measurements | ||
906 | { | ||
907 | double carrier_freq; | ||
908 | double occupied_band; | ||
909 | double power_density; | ||
910 | double tx_spur_f1; | ||
911 | double tx_spur_f2; | ||
912 | double tx_spur_f3; | ||
913 | double tx_spur_f4; | ||
914 | double tx_spur_l1; | ||
915 | double tx_spur_l2; | ||
916 | double tx_spur_l3; | ||
917 | double tx_spur_l4; | ||
918 | double rx_spur_f1; | ||
919 | double rx_spur_f2; | ||
920 | double rx_spur_l1; | ||
921 | double rx_spur_l2; | ||
922 | } __attribute__ ((packed)) hfa384x_pdr_mkk_measurements_t; | ||
923 | |||
924 | typedef struct hfa384x_pdr_nic_ramsize | ||
925 | { | ||
926 | u8 size[12]; /* units of KB */ | ||
927 | } __attribute__ ((packed)) hfa384x_pdr_nic_ramsize_t; | ||
928 | |||
929 | typedef struct hfa384x_pdr_mfisuprange | ||
930 | { | ||
931 | u16 id; | ||
932 | u16 variant; | ||
933 | u16 bottom; | ||
934 | u16 top; | ||
935 | } __attribute__ ((packed)) hfa384x_pdr_mfisuprange_t; | ||
936 | |||
937 | typedef struct hfa384x_pdr_cfisuprange | ||
938 | { | ||
939 | u16 id; | ||
940 | u16 variant; | ||
941 | u16 bottom; | ||
942 | u16 top; | ||
943 | } __attribute__ ((packed)) hfa384x_pdr_cfisuprange_t; | ||
944 | |||
945 | typedef struct hfa384x_pdr_nicid | ||
946 | { | ||
947 | u16 id; | ||
948 | u16 variant; | ||
949 | u16 major; | ||
950 | u16 minor; | ||
951 | } __attribute__ ((packed)) hfa384x_pdr_nicid_t; | ||
952 | |||
953 | |||
954 | typedef struct hfa384x_pdr_refdac_measurements | ||
955 | { | ||
956 | u16 value[0]; | ||
957 | } __attribute__ ((packed)) hfa384x_pdr_refdac_measurements_t; | ||
958 | |||
959 | typedef struct hfa384x_pdr_vgdac_measurements | ||
960 | { | ||
961 | u16 value[0]; | ||
962 | } __attribute__ ((packed)) hfa384x_pdr_vgdac_measurements_t; | ||
963 | |||
964 | typedef struct hfa384x_pdr_level_comp_measurements | ||
965 | { | ||
966 | u16 value[0]; | ||
967 | } __attribute__ ((packed)) hfa384x_pdr_level_compc_measurements_t; | ||
968 | |||
969 | typedef struct hfa384x_pdr_mac_address | ||
970 | { | ||
971 | u8 addr[6]; | ||
972 | } __attribute__ ((packed)) hfa384x_pdr_mac_address_t; | ||
973 | |||
974 | typedef struct hfa384x_pdr_mkk_callname | ||
975 | { | ||
976 | u8 callname[8]; | ||
977 | } __attribute__ ((packed)) hfa384x_pdr_mkk_callname_t; | ||
978 | |||
979 | typedef struct hfa384x_pdr_regdomain | ||
980 | { | ||
981 | u16 numdomains; | ||
982 | u16 domain[5]; | ||
983 | } __attribute__ ((packed)) hfa384x_pdr_regdomain_t; | ||
984 | |||
985 | typedef struct hfa384x_pdr_allowed_channel | ||
986 | { | ||
987 | u16 ch_bitmap; | ||
988 | } __attribute__ ((packed)) hfa384x_pdr_allowed_channel_t; | ||
989 | |||
990 | typedef struct hfa384x_pdr_default_channel | ||
991 | { | ||
992 | u16 channel; | ||
993 | } __attribute__ ((packed)) hfa384x_pdr_default_channel_t; | ||
994 | |||
995 | typedef struct hfa384x_pdr_privacy_option | ||
996 | { | ||
997 | u16 available; | ||
998 | } __attribute__ ((packed)) hfa384x_pdr_privacy_option_t; | ||
999 | |||
1000 | typedef struct hfa384x_pdr_temptype | ||
1001 | { | ||
1002 | u16 type; | ||
1003 | } __attribute__ ((packed)) hfa384x_pdr_temptype_t; | ||
1004 | |||
1005 | typedef struct hfa384x_pdr_refdac_setup | ||
1006 | { | ||
1007 | u16 ch_value[14]; | ||
1008 | } __attribute__ ((packed)) hfa384x_pdr_refdac_setup_t; | ||
1009 | |||
1010 | typedef struct hfa384x_pdr_vgdac_setup | ||
1011 | { | ||
1012 | u16 ch_value[14]; | ||
1013 | } __attribute__ ((packed)) hfa384x_pdr_vgdac_setup_t; | ||
1014 | |||
1015 | typedef struct hfa384x_pdr_level_comp_setup | ||
1016 | { | ||
1017 | u16 ch_value[14]; | ||
1018 | } __attribute__ ((packed)) hfa384x_pdr_level_comp_setup_t; | ||
1019 | |||
1020 | typedef struct hfa384x_pdr_trimdac_setup | ||
1021 | { | ||
1022 | u16 trimidac; | ||
1023 | u16 trimqdac; | ||
1024 | } __attribute__ ((packed)) hfa384x_pdr_trimdac_setup_t; | ||
1025 | |||
1026 | typedef struct hfa384x_pdr_ifr_setting | ||
1027 | { | ||
1028 | u16 value[3]; | ||
1029 | } __attribute__ ((packed)) hfa384x_pdr_ifr_setting_t; | ||
1030 | |||
1031 | typedef struct hfa384x_pdr_rfr_setting | ||
1032 | { | ||
1033 | u16 value[3]; | ||
1034 | } __attribute__ ((packed)) hfa384x_pdr_rfr_setting_t; | ||
1035 | |||
1036 | typedef struct hfa384x_pdr_hfa3861_baseline | ||
1037 | { | ||
1038 | u16 value[50]; | ||
1039 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_baseline_t; | ||
1040 | |||
1041 | typedef struct hfa384x_pdr_hfa3861_shadow | ||
1042 | { | ||
1043 | u32 value[32]; | ||
1044 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_shadow_t; | ||
1045 | |||
1046 | typedef struct hfa384x_pdr_hfa3861_ifrf | ||
1047 | { | ||
1048 | u32 value[20]; | ||
1049 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_ifrf_t; | ||
1050 | |||
1051 | typedef struct hfa384x_pdr_hfa3861_chcalsp | ||
1052 | { | ||
1053 | u16 value[14]; | ||
1054 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_chcalsp_t; | ||
1055 | |||
1056 | typedef struct hfa384x_pdr_hfa3861_chcali | ||
1057 | { | ||
1058 | u16 value[17]; | ||
1059 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_chcali_t; | ||
1060 | |||
1061 | typedef struct hfa384x_pdr_hfa3861_nic_config | ||
1062 | { | ||
1063 | u16 config_bitmap; | ||
1064 | } __attribute__ ((packed)) hfa384x_pdr_nic_config_t; | ||
1065 | |||
1066 | typedef struct hfa384x_pdr_hfo_delay | ||
1067 | { | ||
1068 | u8 hfo_delay; | ||
1069 | } __attribute__ ((packed)) hfa384x_hfo_delay_t; | ||
1070 | |||
1071 | typedef struct hfa384x_pdr_hfa3861_manf_testsp | ||
1072 | { | ||
1073 | u16 value[30]; | ||
1074 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_manf_testsp_t; | ||
1075 | |||
1076 | typedef struct hfa384x_pdr_hfa3861_manf_testi | ||
1077 | { | ||
1078 | u16 value[30]; | ||
1079 | } __attribute__ ((packed)) hfa384x_pdr_hfa3861_manf_testi_t; | ||
1080 | |||
1081 | typedef struct hfa384x_end_of_pda | ||
1082 | { | ||
1083 | u16 crc; | ||
1084 | } __attribute__ ((packed)) hfa384x_pdr_end_of_pda_t; | ||
1085 | |||
1086 | typedef struct hfa384x_pdrec | ||
1087 | { | ||
1088 | u16 len; /* in words */ | ||
1089 | u16 code; | ||
1090 | union pdr { | ||
1091 | hfa384x_pdr_pcb_partnum_t pcb_partnum; | ||
1092 | hfa384x_pdr_pcb_tracenum_t pcb_tracenum; | ||
1093 | hfa384x_pdr_nic_serial_t nic_serial; | ||
1094 | hfa384x_pdr_mkk_measurements_t mkk_measurements; | ||
1095 | hfa384x_pdr_nic_ramsize_t nic_ramsize; | ||
1096 | hfa384x_pdr_mfisuprange_t mfisuprange; | ||
1097 | hfa384x_pdr_cfisuprange_t cfisuprange; | ||
1098 | hfa384x_pdr_nicid_t nicid; | ||
1099 | hfa384x_pdr_refdac_measurements_t refdac_measurements; | ||
1100 | hfa384x_pdr_vgdac_measurements_t vgdac_measurements; | ||
1101 | hfa384x_pdr_level_compc_measurements_t level_compc_measurements; | ||
1102 | hfa384x_pdr_mac_address_t mac_address; | ||
1103 | hfa384x_pdr_mkk_callname_t mkk_callname; | ||
1104 | hfa384x_pdr_regdomain_t regdomain; | ||
1105 | hfa384x_pdr_allowed_channel_t allowed_channel; | ||
1106 | hfa384x_pdr_default_channel_t default_channel; | ||
1107 | hfa384x_pdr_privacy_option_t privacy_option; | ||
1108 | hfa384x_pdr_temptype_t temptype; | ||
1109 | hfa384x_pdr_refdac_setup_t refdac_setup; | ||
1110 | hfa384x_pdr_vgdac_setup_t vgdac_setup; | ||
1111 | hfa384x_pdr_level_comp_setup_t level_comp_setup; | ||
1112 | hfa384x_pdr_trimdac_setup_t trimdac_setup; | ||
1113 | hfa384x_pdr_ifr_setting_t ifr_setting; | ||
1114 | hfa384x_pdr_rfr_setting_t rfr_setting; | ||
1115 | hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; | ||
1116 | hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; | ||
1117 | hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; | ||
1118 | hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; | ||
1119 | hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; | ||
1120 | hfa384x_pdr_nic_config_t nic_config; | ||
1121 | hfa384x_hfo_delay_t hfo_delay; | ||
1122 | hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; | ||
1123 | hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; | ||
1124 | hfa384x_pdr_end_of_pda_t end_of_pda; | ||
1125 | |||
1126 | } data; | ||
1127 | } __attribute__ ((packed)) hfa384x_pdrec_t; | ||
1128 | |||
885 | #ifdef __KERNEL__ | 1129 | #ifdef __KERNEL__ |
886 | /*-------------------------------------------------------------------- | 1130 | /*-------------------------------------------------------------------- |
887 | --- MAC state structure, argument to all functions -- | 1131 | --- MAC state structure, argument to all functions -- |
diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index a29d6ae3e77..da8b6f53c74 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h | |||
@@ -50,6 +50,14 @@ | |||
50 | #define DIDmsg_dot11req_mibget \ | 50 | #define DIDmsg_dot11req_mibget \ |
51 | (P80211DID_MKSECTION(1) | \ | 51 | (P80211DID_MKSECTION(1) | \ |
52 | P80211DID_MKGROUP(1)) | 52 | P80211DID_MKGROUP(1)) |
53 | #define DIDmsg_dot11req_mibget_mibattribute \ | ||
54 | (P80211DID_MKSECTION(1) | \ | ||
55 | P80211DID_MKGROUP(1) | \ | ||
56 | P80211DID_MKITEM(1) | 0x00000000) | ||
57 | #define DIDmsg_dot11req_mibget_resultcode \ | ||
58 | (P80211DID_MKSECTION(1) | \ | ||
59 | P80211DID_MKGROUP(1) | \ | ||
60 | P80211DID_MKITEM(2) | 0x00000000) | ||
53 | #define DIDmsg_dot11req_mibset \ | 61 | #define DIDmsg_dot11req_mibset \ |
54 | (P80211DID_MKSECTION(1) | \ | 62 | (P80211DID_MKSECTION(1) | \ |
55 | P80211DID_MKGROUP(2)) | 63 | P80211DID_MKGROUP(2)) |
@@ -94,12 +102,48 @@ | |||
94 | #define DIDmsg_p2req_readpda \ | 102 | #define DIDmsg_p2req_readpda \ |
95 | (P80211DID_MKSECTION(5) | \ | 103 | (P80211DID_MKSECTION(5) | \ |
96 | P80211DID_MKGROUP(2)) | 104 | P80211DID_MKGROUP(2)) |
105 | #define DIDmsg_p2req_readpda_pda \ | ||
106 | (P80211DID_MKSECTION(5) | \ | ||
107 | P80211DID_MKGROUP(2) | \ | ||
108 | P80211DID_MKITEM(1) | 0x00000000) | ||
109 | #define DIDmsg_p2req_readpda_resultcode \ | ||
110 | (P80211DID_MKSECTION(5) | \ | ||
111 | P80211DID_MKGROUP(2) | \ | ||
112 | P80211DID_MKITEM(2) | 0x00000000) | ||
97 | #define DIDmsg_p2req_ramdl_state \ | 113 | #define DIDmsg_p2req_ramdl_state \ |
98 | (P80211DID_MKSECTION(5) | \ | 114 | (P80211DID_MKSECTION(5) | \ |
99 | P80211DID_MKGROUP(11)) | 115 | P80211DID_MKGROUP(11)) |
116 | #define DIDmsg_p2req_ramdl_state_enable \ | ||
117 | (P80211DID_MKSECTION(5) | \ | ||
118 | P80211DID_MKGROUP(11) | \ | ||
119 | P80211DID_MKITEM(1) | 0x00000000) | ||
120 | #define DIDmsg_p2req_ramdl_state_exeaddr \ | ||
121 | (P80211DID_MKSECTION(5) | \ | ||
122 | P80211DID_MKGROUP(11) | \ | ||
123 | P80211DID_MKITEM(2) | 0x00000000) | ||
124 | #define DIDmsg_p2req_ramdl_state_resultcode \ | ||
125 | (P80211DID_MKSECTION(5) | \ | ||
126 | P80211DID_MKGROUP(11) | \ | ||
127 | P80211DID_MKITEM(3) | 0x00000000) | ||
100 | #define DIDmsg_p2req_ramdl_write \ | 128 | #define DIDmsg_p2req_ramdl_write \ |
101 | (P80211DID_MKSECTION(5) | \ | 129 | (P80211DID_MKSECTION(5) | \ |
102 | P80211DID_MKGROUP(12)) | 130 | P80211DID_MKGROUP(12)) |
131 | #define DIDmsg_p2req_ramdl_write_addr \ | ||
132 | (P80211DID_MKSECTION(5) | \ | ||
133 | P80211DID_MKGROUP(12) | \ | ||
134 | P80211DID_MKITEM(1) | 0x00000000) | ||
135 | #define DIDmsg_p2req_ramdl_write_len \ | ||
136 | (P80211DID_MKSECTION(5) | \ | ||
137 | P80211DID_MKGROUP(12) | \ | ||
138 | P80211DID_MKITEM(2) | 0x00000000) | ||
139 | #define DIDmsg_p2req_ramdl_write_data \ | ||
140 | (P80211DID_MKSECTION(5) | \ | ||
141 | P80211DID_MKGROUP(12) | \ | ||
142 | P80211DID_MKITEM(3) | 0x00000000) | ||
143 | #define DIDmsg_p2req_ramdl_write_resultcode \ | ||
144 | (P80211DID_MKSECTION(5) | \ | ||
145 | P80211DID_MKGROUP(12) | \ | ||
146 | P80211DID_MKITEM(4) | 0x00000000) | ||
103 | #define DIDmsg_p2req_flashdl_state \ | 147 | #define DIDmsg_p2req_flashdl_state \ |
104 | (P80211DID_MKSECTION(5) | \ | 148 | (P80211DID_MKSECTION(5) | \ |
105 | P80211DID_MKGROUP(13)) | 149 | P80211DID_MKGROUP(13)) |
@@ -203,6 +247,10 @@ | |||
203 | (P80211DID_MKSECTION(5) | \ | 247 | (P80211DID_MKSECTION(5) | \ |
204 | P80211DID_MKGROUP(2) | \ | 248 | P80211DID_MKGROUP(2) | \ |
205 | P80211DID_MKITEM(1) | 0x18000000) | 249 | P80211DID_MKITEM(1) | 0x18000000) |
250 | #define DIDmib_p2_p2NIC_p2PRISupRange \ | ||
251 | (P80211DID_MKSECTION(5) | \ | ||
252 | P80211DID_MKGROUP(5) | \ | ||
253 | P80211DID_MKITEM(6) | 0x10000000) | ||
206 | #define DIDmib_p2_p2MAC \ | 254 | #define DIDmib_p2_p2MAC \ |
207 | (P80211DID_MKSECTION(5) | \ | 255 | (P80211DID_MKSECTION(5) | \ |
208 | P80211DID_MKGROUP(6)) | 256 | P80211DID_MKGROUP(6)) |
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index d88184d73a8..ef8e459214b 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c | |||
@@ -566,8 +566,6 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) | |||
566 | 566 | ||
567 | pr_debug("rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); | 567 | pr_debug("rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); |
568 | 568 | ||
569 | mutex_lock(&wlandev->ioctl_lock); | ||
570 | |||
571 | #ifdef SIOCETHTOOL | 569 | #ifdef SIOCETHTOOL |
572 | if (cmd == SIOCETHTOOL) { | 570 | if (cmd == SIOCETHTOOL) { |
573 | result = | 571 | result = |
@@ -608,8 +606,6 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) | |||
608 | result = -ENOMEM; | 606 | result = -ENOMEM; |
609 | } | 607 | } |
610 | bail: | 608 | bail: |
611 | mutex_unlock(&wlandev->ioctl_lock); | ||
612 | |||
613 | return result; /* If allocate,copyfrom or copyto fails, return errno */ | 609 | return result; /* If allocate,copyfrom or copyto fails, return errno */ |
614 | } | 610 | } |
615 | 611 | ||
@@ -771,11 +767,6 @@ int wlan_setup(wlandevice_t *wlandev) | |||
771 | dev->ml_priv = wlandev; | 767 | dev->ml_priv = wlandev; |
772 | dev->netdev_ops = &p80211_netdev_ops; | 768 | dev->netdev_ops = &p80211_netdev_ops; |
773 | 769 | ||
774 | mutex_init(&wlandev->ioctl_lock); | ||
775 | /* block ioctls until fully initialised. Don't forget to call | ||
776 | allow_ioctls at some point!*/ | ||
777 | mutex_lock(&wlandev->ioctl_lock); | ||
778 | |||
779 | #if (WIRELESS_EXT < 21) | 770 | #if (WIRELESS_EXT < 21) |
780 | dev->get_wireless_stats = p80211wext_get_wireless_stats; | 771 | dev->get_wireless_stats = p80211wext_get_wireless_stats; |
781 | #endif | 772 | #endif |
@@ -1116,8 +1107,3 @@ static void p80211knetdev_tx_timeout(netdevice_t *netdev) | |||
1116 | netif_wake_queue(wlandev->netdev); | 1107 | netif_wake_queue(wlandev->netdev); |
1117 | } | 1108 | } |
1118 | } | 1109 | } |
1119 | |||
1120 | void p80211_allow_ioctls(wlandevice_t *wlandev) | ||
1121 | { | ||
1122 | mutex_unlock(&wlandev->ioctl_lock); | ||
1123 | } | ||
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index b96090d8788..94a91b910b2 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h | |||
@@ -227,8 +227,6 @@ typedef struct wlandevice { | |||
227 | u8 spy_number; | 227 | u8 spy_number; |
228 | char spy_address[IW_MAX_SPY][ETH_ALEN]; | 228 | char spy_address[IW_MAX_SPY][ETH_ALEN]; |
229 | struct iw_quality spy_stat[IW_MAX_SPY]; | 229 | struct iw_quality spy_stat[IW_MAX_SPY]; |
230 | |||
231 | struct mutex ioctl_lock; | ||
232 | } wlandevice_t; | 230 | } wlandevice_t; |
233 | 231 | ||
234 | /* WEP stuff */ | 232 | /* WEP stuff */ |
@@ -244,5 +242,4 @@ int register_wlandev(wlandevice_t *wlandev); | |||
244 | int unregister_wlandev(wlandevice_t *wlandev); | 242 | int unregister_wlandev(wlandevice_t *wlandev); |
245 | void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); | 243 | void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); |
246 | void p80211netdev_hwremoved(wlandevice_t *wlandev); | 244 | void p80211netdev_hwremoved(wlandevice_t *wlandev); |
247 | void p80211_allow_ioctls(wlandevice_t *wlandev); | ||
248 | #endif | 245 | #endif |
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c new file mode 100644 index 00000000000..48bfb8331dd --- /dev/null +++ b/drivers/staging/wlan-ng/prism2fw.c | |||
@@ -0,0 +1,1410 @@ | |||
1 | /* from src/prism2/download/prism2dl.c | ||
2 | * | ||
3 | * utility for downloading prism2 images moved into kernelspace | ||
4 | * | ||
5 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
6 | * -------------------------------------------------------------------- | ||
7 | * | ||
8 | * linux-wlan | ||
9 | * | ||
10 | * The contents of this file are subject to the Mozilla Public | ||
11 | * License Version 1.1 (the "License"); you may not use this file | ||
12 | * except in compliance with the License. You may obtain a copy of | ||
13 | * the License at http://www.mozilla.org/MPL/ | ||
14 | * | ||
15 | * Software distributed under the License is distributed on an "AS | ||
16 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
17 | * implied. See the License for the specific language governing | ||
18 | * rights and limitations under the License. | ||
19 | * | ||
20 | * Alternatively, the contents of this file may be used under the | ||
21 | * terms of the GNU Public License version 2 (the "GPL"), in which | ||
22 | * case the provisions of the GPL are applicable instead of the | ||
23 | * above. If you wish to allow the use of your version of this file | ||
24 | * only under the terms of the GPL and not to allow others to use | ||
25 | * your version of this file under the MPL, indicate your decision | ||
26 | * by deleting the provisions above and replace them with the notice | ||
27 | * and other provisions required by the GPL. If you do not delete | ||
28 | * the provisions above, a recipient may use your version of this | ||
29 | * file under either the MPL or the GPL. | ||
30 | * | ||
31 | * -------------------------------------------------------------------- | ||
32 | * | ||
33 | * Inquiries regarding the linux-wlan Open Source project can be | ||
34 | * made directly to: | ||
35 | * | ||
36 | * AbsoluteValue Systems Inc. | ||
37 | * info@linux-wlan.com | ||
38 | * http://www.linux-wlan.com | ||
39 | * | ||
40 | * -------------------------------------------------------------------- | ||
41 | * | ||
42 | * Portions of the development of this software were funded by | ||
43 | * Intersil Corporation as part of PRISM(R) chipset product development. | ||
44 | * | ||
45 | * -------------------------------------------------------------------- | ||
46 | */ | ||
47 | |||
48 | /*================================================================*/ | ||
49 | /* System Includes */ | ||
50 | #include <linux/sort.h> | ||
51 | #include <linux/firmware.h> | ||
52 | |||
53 | |||
54 | /*================================================================*/ | ||
55 | /* Local Constants */ | ||
56 | |||
57 | #define PRISM2_USB_FWFILE "prism2_ru.hex" | ||
58 | |||
59 | #define S3DATA_MAX 5000 | ||
60 | #define S3PLUG_MAX 200 | ||
61 | #define S3CRC_MAX 200 | ||
62 | #define S3INFO_MAX 50 | ||
63 | #define SREC_LINE_MAX 264 | ||
64 | #define S3LEN_TXTOFFSET 2 | ||
65 | #define S3LEN_TXTLEN 2 | ||
66 | #define S3ADDR_TXTOFFSET 4 | ||
67 | #define S3ADDR_TXTLEN 8 | ||
68 | #define S3DATA_TXTOFFSET 12 | ||
69 | /*S3DATA_TXTLEN variable, depends on len field */ | ||
70 | /*S3CKSUM_TXTOFFSET variable, depends on len field */ | ||
71 | #define S3CKSUM_TXTLEN 2 | ||
72 | #define SERNUM_LEN_MAX 12 | ||
73 | |||
74 | #define S3PLUG_ITEMCODE_TXTOFFSET (S3DATA_TXTOFFSET) | ||
75 | #define S3PLUG_ITEMCODE_TXTLEN 8 | ||
76 | #define S3PLUG_ADDR_TXTOFFSET (S3DATA_TXTOFFSET+8) | ||
77 | #define S3PLUG_ADDR_TXTLEN 8 | ||
78 | #define S3PLUG_LEN_TXTOFFSET (S3DATA_TXTOFFSET+16) | ||
79 | #define S3PLUG_LEN_TXTLEN 8 | ||
80 | |||
81 | #define S3CRC_ADDR_TXTOFFSET (S3DATA_TXTOFFSET) | ||
82 | #define S3CRC_ADDR_TXTLEN 8 | ||
83 | #define S3CRC_LEN_TXTOFFSET (S3DATA_TXTOFFSET+8) | ||
84 | #define S3CRC_LEN_TXTLEN 8 | ||
85 | #define S3CRC_DOWRITE_TXTOFFSET (S3DATA_TXTOFFSET+16) | ||
86 | #define S3CRC_DOWRITE_TXTLEN 8 | ||
87 | |||
88 | #define S3INFO_LEN_TXTOFFSET (S3DATA_TXTOFFSET) | ||
89 | #define S3INFO_LEN_TXTLEN 4 | ||
90 | #define S3INFO_TYPE_TXTOFFSET (S3DATA_TXTOFFSET+4) | ||
91 | #define S3INFO_TYPE_TXTLEN 4 | ||
92 | #define S3INFO_DATA_TXTOFFSET (S3DATA_TXTOFFSET+8) | ||
93 | /* S3INFO_DATA_TXTLEN variable, depends on INFO_LEN field */ | ||
94 | |||
95 | #define S3ADDR_PLUG (0xff000000UL) | ||
96 | #define S3ADDR_CRC (0xff100000UL) | ||
97 | #define S3ADDR_INFO (0xff200000UL) | ||
98 | |||
99 | #define PDAFILE_LINE_MAX 1024 | ||
100 | |||
101 | #define CHUNKS_MAX 100 | ||
102 | |||
103 | #define WRITESIZE_MAX 4096 | ||
104 | |||
105 | /*================================================================*/ | ||
106 | /* Local Macros */ | ||
107 | |||
108 | #define bswap_16(x) \ | ||
109 | (__extension__ \ | ||
110 | ({ register unsigned short int __v, __x = (x); \ | ||
111 | __asm__ ("rorw $8, %w0" \ | ||
112 | : "=r" (__v) \ | ||
113 | : "0" (__x) \ | ||
114 | : "cc"); \ | ||
115 | __v; })) | ||
116 | |||
117 | #define bswap_32(x) \ | ||
118 | (__extension__ \ | ||
119 | ({ register unsigned int __v, __x = (x); \ | ||
120 | __asm__ ("rorw $8, %w0;" \ | ||
121 | "rorl $16, %0;" \ | ||
122 | "rorw $8, %w0" \ | ||
123 | : "=r" (__v) \ | ||
124 | : "0" (__x) \ | ||
125 | : "cc"); \ | ||
126 | __v; })) | ||
127 | |||
128 | |||
129 | |||
130 | /*================================================================*/ | ||
131 | /* Local Types */ | ||
132 | |||
133 | typedef struct s3datarec | ||
134 | { | ||
135 | u32 len; | ||
136 | u32 addr; | ||
137 | u8 checksum; | ||
138 | u8 *data; | ||
139 | } s3datarec_t; | ||
140 | |||
141 | typedef struct s3plugrec | ||
142 | { | ||
143 | u32 itemcode; | ||
144 | u32 addr; | ||
145 | u32 len; | ||
146 | } s3plugrec_t; | ||
147 | |||
148 | typedef struct s3crcrec | ||
149 | { | ||
150 | u32 addr; | ||
151 | u32 len; | ||
152 | unsigned int dowrite; | ||
153 | } s3crcrec_t; | ||
154 | |||
155 | typedef struct s3inforec | ||
156 | { | ||
157 | u16 len; | ||
158 | u16 type; | ||
159 | union { | ||
160 | hfa384x_compident_t version; | ||
161 | hfa384x_caplevel_t compat; | ||
162 | u16 buildseq; | ||
163 | hfa384x_compident_t platform; | ||
164 | } info; | ||
165 | } s3inforec_t; | ||
166 | |||
167 | typedef struct pda | ||
168 | { | ||
169 | u8 buf[HFA384x_PDA_LEN_MAX]; | ||
170 | hfa384x_pdrec_t *rec[HFA384x_PDA_RECS_MAX]; | ||
171 | unsigned int nrec; | ||
172 | } pda_t; | ||
173 | |||
174 | typedef struct imgchunk | ||
175 | { | ||
176 | u32 addr; /* start address */ | ||
177 | u32 len; /* in bytes */ | ||
178 | u16 crc; /* CRC value (if it falls at a chunk boundary) */ | ||
179 | u8 *data; | ||
180 | } imgchunk_t; | ||
181 | |||
182 | /*================================================================*/ | ||
183 | /* Local Static Definitions */ | ||
184 | |||
185 | |||
186 | /*----------------------------------------------------------------*/ | ||
187 | /* s-record image processing */ | ||
188 | |||
189 | /* Data records */ | ||
190 | unsigned int ns3data = 0; | ||
191 | s3datarec_t s3data[S3DATA_MAX]; | ||
192 | |||
193 | /* Plug records */ | ||
194 | unsigned int ns3plug = 0; | ||
195 | s3plugrec_t s3plug[S3PLUG_MAX]; | ||
196 | |||
197 | /* CRC records */ | ||
198 | unsigned int ns3crc = 0; | ||
199 | s3crcrec_t s3crc[S3CRC_MAX]; | ||
200 | |||
201 | /* Info records */ | ||
202 | unsigned int ns3info = 0; | ||
203 | s3inforec_t s3info[S3INFO_MAX]; | ||
204 | |||
205 | /* S7 record (there _better_ be only one) */ | ||
206 | u32 startaddr; | ||
207 | |||
208 | /* Load image chunks */ | ||
209 | unsigned int nfchunks; | ||
210 | imgchunk_t fchunk[CHUNKS_MAX]; | ||
211 | |||
212 | /* Note that for the following pdrec_t arrays, the len and code */ | ||
213 | /* fields are stored in HOST byte order. The mkpdrlist() function */ | ||
214 | /* does the conversion. */ | ||
215 | /*----------------------------------------------------------------*/ | ||
216 | /* PDA, built from [card|newfile]+[addfile1+addfile2...] */ | ||
217 | |||
218 | pda_t pda; | ||
219 | hfa384x_compident_t nicid; | ||
220 | hfa384x_caplevel_t rfid; | ||
221 | hfa384x_caplevel_t macid; | ||
222 | hfa384x_caplevel_t priid; | ||
223 | |||
224 | |||
225 | /*================================================================*/ | ||
226 | /* Local Function Declarations */ | ||
227 | |||
228 | int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev); | ||
229 | int read_srecfile(char *rfptr, int rfsize); | ||
230 | int mkimage(imgchunk_t *clist, unsigned int *ccnt); | ||
231 | int read_cardpda(pda_t *pda, wlandevice_t *wlandev); | ||
232 | int mkpdrlist( pda_t *pda); | ||
233 | int s3datarec_compare(const void *p1, const void *p2); | ||
234 | int plugimage( imgchunk_t *fchunk, unsigned int nfchunks, | ||
235 | s3plugrec_t* s3plug, unsigned int ns3plug, pda_t *pda); | ||
236 | int crcimage( imgchunk_t *fchunk, unsigned int nfchunks, | ||
237 | s3crcrec_t *s3crc, unsigned int ns3crc); | ||
238 | int writeimage(wlandevice_t *wlandev, imgchunk_t *fchunk, unsigned int nfchunks); | ||
239 | void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks); | ||
240 | void free_srecs(void); | ||
241 | |||
242 | int validate_identity(void); | ||
243 | |||
244 | /*================================================================*/ | ||
245 | /* Function Definitions */ | ||
246 | |||
247 | |||
248 | /*---------------------------------------------------------------- | ||
249 | * prism2_fwtry | ||
250 | * | ||
251 | * Try and get firmware into memory | ||
252 | * | ||
253 | * Arguments: | ||
254 | * udev usb device structure | ||
255 | * wlandev wlan device structure | ||
256 | * | ||
257 | * Returns: | ||
258 | * 0 - success | ||
259 | * ~0 - failure | ||
260 | ----------------------------------------------------------------*/ | ||
261 | int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) | ||
262 | { | ||
263 | const struct firmware *fw_entry = NULL; | ||
264 | |||
265 | printk(KERN_INFO "prism2_usb: Checking for firmware %s\n", PRISM2_USB_FWFILE); | ||
266 | if(request_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) | ||
267 | { | ||
268 | printk(KERN_INFO | ||
269 | "prism2_usb: Firmware not available, but not essential\n"); | ||
270 | printk(KERN_INFO | ||
271 | "prism2_usb: can continue to use card anyway.\n"); | ||
272 | return 1; | ||
273 | } | ||
274 | |||
275 | printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n", PRISM2_USB_FWFILE, fw_entry->size); | ||
276 | prism2_fwapply((char *)fw_entry->data, fw_entry->size, wlandev); | ||
277 | |||
278 | release_firmware(fw_entry); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | |||
283 | /*---------------------------------------------------------------- | ||
284 | * prism2_fwapply | ||
285 | * | ||
286 | * Apply the firmware loaded into memory | ||
287 | * | ||
288 | * Arguments: | ||
289 | * rfptr firmware image in kernel memory | ||
290 | * rfsize firmware size in kernel memory | ||
291 | * wlandev device | ||
292 | * | ||
293 | * Returns: | ||
294 | * 0 - success | ||
295 | * ~0 - failure | ||
296 | ----------------------------------------------------------------*/ | ||
297 | int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev) | ||
298 | { | ||
299 | signed int result = 0; | ||
300 | p80211msg_dot11req_mibget_t getmsg; | ||
301 | p80211itemd_t *item; | ||
302 | u32 *data; | ||
303 | |||
304 | /* Initialize the data structures */ | ||
305 | ns3data = 0; | ||
306 | memset(s3data, 0, sizeof(s3data)); | ||
307 | ns3plug = 0; | ||
308 | memset(s3plug, 0, sizeof(s3plug)); | ||
309 | ns3crc = 0; | ||
310 | memset(s3crc, 0, sizeof(s3crc)); | ||
311 | ns3info = 0; | ||
312 | memset(s3info, 0, sizeof(s3info)); | ||
313 | startaddr = 0; | ||
314 | |||
315 | nfchunks = 0; | ||
316 | memset( fchunk, 0, sizeof(fchunk)); | ||
317 | memset( &nicid, 0, sizeof(nicid)); | ||
318 | memset( &rfid, 0, sizeof(rfid)); | ||
319 | memset( &macid, 0, sizeof(macid)); | ||
320 | memset( &priid, 0, sizeof(priid)); | ||
321 | |||
322 | /* clear the pda and add an initial END record */ | ||
323 | memset(&pda, 0, sizeof(pda)); | ||
324 | pda.rec[0] = (hfa384x_pdrec_t*)pda.buf; | ||
325 | pda.rec[0]->len = cpu_to_le16(2); /* len in words */ /* len in words */ | ||
326 | pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA); | ||
327 | pda.nrec = 1; | ||
328 | |||
329 | |||
330 | /*-----------------------------------------------------*/ | ||
331 | /* Put card into fwload state */ | ||
332 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); | ||
333 | |||
334 | /* Build the PDA we're going to use. */ | ||
335 | if (read_cardpda(&pda, wlandev)) { | ||
336 | printk(KERN_ERR "load_cardpda failed, exiting.\n"); | ||
337 | return(1); | ||
338 | } | ||
339 | |||
340 | /* read the card's PRI-SUP */ | ||
341 | memset(&getmsg, 0, sizeof(getmsg)); | ||
342 | getmsg.msgcode = DIDmsg_dot11req_mibget; | ||
343 | getmsg.msglen = sizeof(getmsg); | ||
344 | strcpy(getmsg.devname, wlandev->name); | ||
345 | |||
346 | getmsg.mibattribute.did = DIDmsg_dot11req_mibget_mibattribute; | ||
347 | getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok; | ||
348 | getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode; | ||
349 | getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value; | ||
350 | |||
351 | item = (p80211itemd_t *) getmsg.mibattribute.data; | ||
352 | item->did = DIDmib_p2_p2NIC_p2PRISupRange; | ||
353 | item->status = P80211ENUM_msgitem_status_no_value; | ||
354 | |||
355 | data = (u32*) item->data; | ||
356 | |||
357 | /* DIDmsg_dot11req_mibget */ | ||
358 | prism2mgmt_mibset_mibget(wlandev, &getmsg); | ||
359 | if (getmsg.resultcode.data != P80211ENUM_resultcode_success) { | ||
360 | printk(KERN_ERR "Couldn't fetch PRI-SUP info\n"); | ||
361 | } | ||
362 | |||
363 | /* Already in host order */ | ||
364 | priid.role = *data++; | ||
365 | priid.id = *data++; | ||
366 | priid.variant = *data++; | ||
367 | priid.bottom = *data++; | ||
368 | priid.top = *data++; | ||
369 | |||
370 | |||
371 | /* Read the S3 file */ | ||
372 | result = read_srecfile(rfptr, rfsize); | ||
373 | if ( result ) { | ||
374 | printk(KERN_ERR "Failed to read the data exiting.\n"); | ||
375 | return(1); | ||
376 | } | ||
377 | /* Sort the S3 data records */ | ||
378 | sort( s3data, | ||
379 | ns3data, | ||
380 | sizeof(s3datarec_t), | ||
381 | s3datarec_compare, NULL); | ||
382 | |||
383 | result = validate_identity(); | ||
384 | |||
385 | if ( result ) { | ||
386 | printk(KERN_ERR "Incompatible firmware image.\n"); | ||
387 | return(1); | ||
388 | } | ||
389 | |||
390 | if (startaddr == 0x00000000) { | ||
391 | printk(KERN_ERR "Can't RAM download a Flash image!\n"); | ||
392 | return(1); | ||
393 | } | ||
394 | |||
395 | /* Make the image chunks */ | ||
396 | result = mkimage(fchunk, &nfchunks); | ||
397 | |||
398 | /* Do any plugging */ | ||
399 | result = plugimage(fchunk, nfchunks, s3plug, ns3plug, | ||
400 | &pda); | ||
401 | if ( result ) { | ||
402 | printk(KERN_ERR "Failed to plug data.\n"); | ||
403 | return(1); | ||
404 | } | ||
405 | |||
406 | /* Insert any CRCs */ | ||
407 | if (crcimage(fchunk, nfchunks, s3crc, ns3crc) ) { | ||
408 | printk(KERN_ERR "Failed to insert all CRCs\n"); | ||
409 | return(1); | ||
410 | } | ||
411 | |||
412 | /* Write the image */ | ||
413 | result = writeimage(wlandev, fchunk, nfchunks); | ||
414 | if ( result ) { | ||
415 | printk(KERN_ERR "Failed to ramwrite image data.\n"); | ||
416 | return(1); | ||
417 | } | ||
418 | |||
419 | /* clear any allocated memory */ | ||
420 | free_chunks(fchunk, &nfchunks); | ||
421 | free_srecs(); | ||
422 | |||
423 | printk(KERN_INFO "prism2_usb: firmware loading finished.\n"); | ||
424 | |||
425 | return result; | ||
426 | } | ||
427 | |||
428 | |||
429 | /*---------------------------------------------------------------- | ||
430 | * crcimage | ||
431 | * | ||
432 | * Adds a CRC16 in the two bytes prior to each block identified by | ||
433 | * an S3 CRC record. Currently, we don't actually do a CRC we just | ||
434 | * insert the value 0xC0DE in hfa384x order. | ||
435 | * | ||
436 | * Arguments: | ||
437 | * fchunk Array of image chunks | ||
438 | * nfchunks Number of image chunks | ||
439 | * s3crc Array of crc records | ||
440 | * ns3crc Number of crc records | ||
441 | * | ||
442 | * Returns: | ||
443 | * 0 success | ||
444 | * ~0 failure | ||
445 | ----------------------------------------------------------------*/ | ||
446 | int crcimage(imgchunk_t *fchunk, unsigned int nfchunks, s3crcrec_t *s3crc, | ||
447 | unsigned int ns3crc) | ||
448 | { | ||
449 | int result = 0; | ||
450 | int i; | ||
451 | int c; | ||
452 | u32 crcstart; | ||
453 | u32 crcend; | ||
454 | u32 cstart = 0; | ||
455 | u32 cend; | ||
456 | u8 *dest; | ||
457 | u32 chunkoff; | ||
458 | |||
459 | for ( i = 0; i < ns3crc; i++ ) { | ||
460 | if ( !s3crc[i].dowrite ) continue; | ||
461 | crcstart = s3crc[i].addr; | ||
462 | crcend = s3crc[i].addr + s3crc[i].len; | ||
463 | /* Find chunk */ | ||
464 | for ( c = 0; c < nfchunks; c++) { | ||
465 | cstart = fchunk[c].addr; | ||
466 | cend = fchunk[c].addr + fchunk[c].len; | ||
467 | /* the line below does an address & len match search */ | ||
468 | /* unfortunately, I've found that the len fields of */ | ||
469 | /* some crc records don't match with the length of */ | ||
470 | /* the actual data, so we're not checking right */ | ||
471 | /* now */ | ||
472 | /* if ( crcstart-2 >= cstart && crcend <= cend ) break;*/ | ||
473 | |||
474 | /* note the -2 below, it's to make sure the chunk has */ | ||
475 | /* space for the CRC value */ | ||
476 | if ( crcstart-2 >= cstart && crcstart < cend ) break; | ||
477 | } | ||
478 | if ( c >= nfchunks ) { | ||
479 | printk(KERN_ERR | ||
480 | "Failed to find chunk for " | ||
481 | "crcrec[%d], addr=0x%06x len=%d , " | ||
482 | "aborting crc.\n", | ||
483 | i, s3crc[i].addr, s3crc[i].len); | ||
484 | return 1; | ||
485 | } | ||
486 | |||
487 | /* Insert crc */ | ||
488 | pr_debug("Adding crc @ 0x%06x\n", s3crc[i].addr-2); | ||
489 | chunkoff = crcstart - cstart - 2; | ||
490 | dest = fchunk[c].data + chunkoff; | ||
491 | *dest = 0xde; | ||
492 | *(dest+1) = 0xc0; | ||
493 | |||
494 | } | ||
495 | return result; | ||
496 | } | ||
497 | |||
498 | |||
499 | /*---------------------------------------------------------------- | ||
500 | * free_chunks | ||
501 | * | ||
502 | * Clears the chunklist data structures in preparation for a new file. | ||
503 | * | ||
504 | * Arguments: | ||
505 | * none | ||
506 | * | ||
507 | * Returns: | ||
508 | * nothing | ||
509 | ----------------------------------------------------------------*/ | ||
510 | void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks) | ||
511 | { | ||
512 | int i; | ||
513 | for ( i = 0; i < *nfchunks; i++) { | ||
514 | if ( fchunk[i].data != NULL ) { | ||
515 | kfree(fchunk[i].data); | ||
516 | } | ||
517 | } | ||
518 | *nfchunks = 0; | ||
519 | memset( fchunk, 0, sizeof(fchunk)); | ||
520 | |||
521 | } | ||
522 | |||
523 | |||
524 | /*---------------------------------------------------------------- | ||
525 | * free_srecs | ||
526 | * | ||
527 | * Clears the srec data structures in preparation for a new file. | ||
528 | * | ||
529 | * Arguments: | ||
530 | * none | ||
531 | * | ||
532 | * Returns: | ||
533 | * nothing | ||
534 | ----------------------------------------------------------------*/ | ||
535 | void free_srecs(void) | ||
536 | { | ||
537 | int i; | ||
538 | for ( i = 0; i < ns3data; i++) { | ||
539 | kfree(s3data[i].data); | ||
540 | } | ||
541 | ns3data = 0; | ||
542 | memset(s3data, 0, sizeof(s3data)); | ||
543 | ns3plug = 0; | ||
544 | memset(s3plug, 0, sizeof(s3plug)); | ||
545 | ns3crc = 0; | ||
546 | memset(s3crc, 0, sizeof(s3crc)); | ||
547 | ns3info = 0; | ||
548 | memset(s3info, 0, sizeof(s3info)); | ||
549 | startaddr = 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | /*---------------------------------------------------------------- | ||
554 | * mkimage | ||
555 | * | ||
556 | * Scans the currently loaded set of S records for data residing | ||
557 | * in contiguous memory regions. Each contiguous region is then | ||
558 | * made into a 'chunk'. This function assumes that we're building | ||
559 | * a new chunk list. Assumes the s3data items are in sorted order. | ||
560 | * | ||
561 | * Arguments: none | ||
562 | * | ||
563 | * Returns: | ||
564 | * 0 - success | ||
565 | * ~0 - failure (probably an errno) | ||
566 | ----------------------------------------------------------------*/ | ||
567 | int mkimage(imgchunk_t *clist, unsigned int *ccnt) | ||
568 | { | ||
569 | int result = 0; | ||
570 | int i; | ||
571 | int j; | ||
572 | int currchunk = 0; | ||
573 | u32 nextaddr = 0; | ||
574 | u32 s3start; | ||
575 | u32 s3end; | ||
576 | u32 cstart = 0; | ||
577 | u32 cend; | ||
578 | u32 coffset; | ||
579 | |||
580 | /* There may already be data in the chunklist */ | ||
581 | *ccnt = 0; | ||
582 | |||
583 | /* Establish the location and size of each chunk */ | ||
584 | for ( i = 0; i < ns3data; i++) { | ||
585 | if ( s3data[i].addr == nextaddr ) { | ||
586 | /* existing chunk, grow it */ | ||
587 | clist[currchunk].len += s3data[i].len; | ||
588 | nextaddr += s3data[i].len; | ||
589 | } else { | ||
590 | /* New chunk */ | ||
591 | (*ccnt)++; | ||
592 | currchunk = *ccnt - 1; | ||
593 | clist[currchunk].addr = s3data[i].addr; | ||
594 | clist[currchunk].len = s3data[i].len; | ||
595 | nextaddr = s3data[i].addr + s3data[i].len; | ||
596 | /* Expand the chunk if there is a CRC record at */ | ||
597 | /* their beginning bound */ | ||
598 | for ( j = 0; j < ns3crc; j++) { | ||
599 | if ( s3crc[j].dowrite && | ||
600 | s3crc[j].addr == clist[currchunk].addr ) { | ||
601 | clist[currchunk].addr -= 2; | ||
602 | clist[currchunk].len += 2; | ||
603 | } | ||
604 | } | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /* We're currently assuming there aren't any overlapping chunks */ | ||
609 | /* if this proves false, we'll need to add code to coalesce. */ | ||
610 | |||
611 | /* Allocate buffer space for chunks */ | ||
612 | for ( i = 0; i < *ccnt; i++) { | ||
613 | clist[i].data = kmalloc(clist[i].len, GFP_KERNEL); | ||
614 | if ( clist[i].data == NULL ) { | ||
615 | printk(KERN_ERR "failed to allocate image space, exitting.\n"); | ||
616 | return(1); | ||
617 | } | ||
618 | memset(clist[i].data, 0, clist[i].len); | ||
619 | } | ||
620 | |||
621 | |||
622 | /* Display chunks */ | ||
623 | for ( i = 0; i < *ccnt; i++) { | ||
624 | pr_debug("chunk[%d]: addr=0x%06x len=%d\n", | ||
625 | i, clist[i].addr, clist[i].len); | ||
626 | } | ||
627 | |||
628 | /* Copy srec data to chunks */ | ||
629 | for ( i = 0; i < ns3data; i++) { | ||
630 | s3start = s3data[i].addr; | ||
631 | s3end = s3start + s3data[i].len - 1; | ||
632 | for ( j = 0; j < *ccnt; j++) { | ||
633 | cstart = clist[j].addr; | ||
634 | cend = cstart + clist[j].len - 1; | ||
635 | if ( s3start >= cstart && s3end <= cend ) { | ||
636 | break; | ||
637 | } | ||
638 | } | ||
639 | if ( ((unsigned int)j) >= (*ccnt) ) { | ||
640 | printk(KERN_ERR | ||
641 | "s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n", | ||
642 | s3start, s3data[i].len); | ||
643 | return(1); | ||
644 | } | ||
645 | coffset = s3start - cstart; | ||
646 | memcpy( clist[j].data + coffset, s3data[i].data, s3data[i].len); | ||
647 | } | ||
648 | |||
649 | return result; | ||
650 | } | ||
651 | |||
652 | /*---------------------------------------------------------------- | ||
653 | * mkpdrlist | ||
654 | * | ||
655 | * Reads a raw PDA and builds an array of pdrec_t structures. | ||
656 | * | ||
657 | * Arguments: | ||
658 | * pda buffer containing raw PDA bytes | ||
659 | * pdrec ptr to an array of pdrec_t's. Will be filled on exit. | ||
660 | * nrec ptr to a variable that will contain the count of PDRs | ||
661 | * | ||
662 | * Returns: | ||
663 | * 0 - success | ||
664 | * ~0 - failure (probably an errno) | ||
665 | ----------------------------------------------------------------*/ | ||
666 | int mkpdrlist( pda_t *pda) | ||
667 | { | ||
668 | int result = 0; | ||
669 | u16 *pda16 = (u16*)pda->buf; | ||
670 | int curroff; /* in 'words' */ | ||
671 | |||
672 | pda->nrec = 0; | ||
673 | curroff = 0; | ||
674 | while ( curroff < (HFA384x_PDA_LEN_MAX / 2) && | ||
675 | le16_to_cpu(pda16[curroff + 1]) != | ||
676 | HFA384x_PDR_END_OF_PDA ) { | ||
677 | pda->rec[pda->nrec] = (hfa384x_pdrec_t*)&(pda16[curroff]); | ||
678 | |||
679 | if (le16_to_cpu(pda->rec[pda->nrec]->code) == | ||
680 | HFA384x_PDR_NICID) { | ||
681 | memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid, | ||
682 | sizeof(nicid)); | ||
683 | nicid.id = le16_to_cpu(nicid.id); | ||
684 | nicid.variant = le16_to_cpu(nicid.variant); | ||
685 | nicid.major = le16_to_cpu(nicid.major); | ||
686 | nicid.minor = le16_to_cpu(nicid.minor); | ||
687 | } | ||
688 | if (le16_to_cpu(pda->rec[pda->nrec]->code) == | ||
689 | HFA384x_PDR_MFISUPRANGE) { | ||
690 | memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange, | ||
691 | sizeof(rfid)); | ||
692 | rfid.id = le16_to_cpu(rfid.id); | ||
693 | rfid.variant = le16_to_cpu(rfid.variant); | ||
694 | rfid.bottom = le16_to_cpu(rfid.bottom); | ||
695 | rfid.top = le16_to_cpu(rfid.top); | ||
696 | } | ||
697 | if (le16_to_cpu(pda->rec[pda->nrec]->code) == | ||
698 | HFA384x_PDR_CFISUPRANGE) { | ||
699 | memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange, | ||
700 | sizeof(macid)); | ||
701 | macid.id = le16_to_cpu(macid.id); | ||
702 | macid.variant = le16_to_cpu(macid.variant); | ||
703 | macid.bottom = le16_to_cpu(macid.bottom); | ||
704 | macid.top = le16_to_cpu(macid.top); | ||
705 | } | ||
706 | |||
707 | (pda->nrec)++; | ||
708 | curroff += le16_to_cpu(pda16[curroff]) + 1; | ||
709 | |||
710 | } | ||
711 | if ( curroff >= (HFA384x_PDA_LEN_MAX / 2) ) { | ||
712 | printk(KERN_ERR | ||
713 | "no end record found or invalid lengths in " | ||
714 | "PDR data, exiting. %x %d\n", curroff, pda->nrec); | ||
715 | return(1); | ||
716 | } | ||
717 | if (le16_to_cpu(pda16[curroff + 1]) == HFA384x_PDR_END_OF_PDA ) { | ||
718 | pda->rec[pda->nrec] = (hfa384x_pdrec_t*)&(pda16[curroff]); | ||
719 | (pda->nrec)++; | ||
720 | } | ||
721 | return result; | ||
722 | } | ||
723 | |||
724 | |||
725 | |||
726 | /*---------------------------------------------------------------- | ||
727 | * plugimage | ||
728 | * | ||
729 | * Plugs the given image using the given plug records from the given | ||
730 | * PDA and filename. | ||
731 | * | ||
732 | * Arguments: | ||
733 | * fchunk Array of image chunks | ||
734 | * nfchunks Number of image chunks | ||
735 | * s3plug Array of plug records | ||
736 | * ns3plug Number of plug records | ||
737 | * pda Current pda data | ||
738 | * | ||
739 | * Returns: | ||
740 | * 0 success | ||
741 | * ~0 failure | ||
742 | ----------------------------------------------------------------*/ | ||
743 | int plugimage( imgchunk_t *fchunk, unsigned int nfchunks, | ||
744 | s3plugrec_t* s3plug, unsigned int ns3plug, pda_t *pda) | ||
745 | { | ||
746 | int result = 0; | ||
747 | int i; /* plug index */ | ||
748 | int j; /* index of PDR or -1 if fname plug */ | ||
749 | int c; /* chunk index */ | ||
750 | u32 pstart; | ||
751 | u32 pend; | ||
752 | u32 cstart = 0; | ||
753 | u32 cend; | ||
754 | u32 chunkoff; | ||
755 | u8 *dest; | ||
756 | |||
757 | /* for each plug record */ | ||
758 | for ( i = 0; i < ns3plug; i++) { | ||
759 | pstart = s3plug[i].addr; | ||
760 | pend = s3plug[i].addr + s3plug[i].len; | ||
761 | /* find the matching PDR (or filename) */ | ||
762 | if ( s3plug[i].itemcode != 0xffffffffUL ) { /* not filename */ | ||
763 | for ( j = 0; j < pda->nrec; j++) { | ||
764 | if ( s3plug[i].itemcode == | ||
765 | le16_to_cpu(pda->rec[j]->code) ) break; | ||
766 | } | ||
767 | } else { | ||
768 | j = -1; | ||
769 | } | ||
770 | if ( j >= pda->nrec && j != -1 ) { /* if no matching PDR, fail */ | ||
771 | printk(KERN_WARNING | ||
772 | "warning: Failed to find PDR for " | ||
773 | "plugrec 0x%04x.\n", | ||
774 | s3plug[i].itemcode); | ||
775 | continue; /* and move on to the next PDR */ | ||
776 | #if 0 | ||
777 | /* MSM: They swear that unless it's the MAC address, | ||
778 | * the serial number, or the TX calibration records, | ||
779 | * then there's reasonable defaults in the f/w | ||
780 | * image. Therefore, missing PDRs in the card | ||
781 | * should only be a warning, not fatal. | ||
782 | * TODO: add fatals for the PDRs mentioned above. | ||
783 | */ | ||
784 | result = 1; | ||
785 | continue; | ||
786 | #endif | ||
787 | } | ||
788 | |||
789 | /* Validate plug len against PDR len */ | ||
790 | if ( j != -1 && | ||
791 | s3plug[i].len < le16_to_cpu(pda->rec[j]->len) ) { | ||
792 | printk(KERN_ERR | ||
793 | "error: Plug vs. PDR len mismatch for " | ||
794 | "plugrec 0x%04x, abort plugging.\n", | ||
795 | s3plug[i].itemcode); | ||
796 | result = 1; | ||
797 | continue; | ||
798 | } | ||
799 | |||
800 | /* Validate plug address against chunk data and identify chunk */ | ||
801 | for ( c = 0; c < nfchunks; c++) { | ||
802 | cstart = fchunk[c].addr; | ||
803 | cend = fchunk[c].addr + fchunk[c].len; | ||
804 | if ( pstart >= cstart && pend <= cend ) break; | ||
805 | } | ||
806 | if ( c >= nfchunks ) { | ||
807 | printk(KERN_ERR | ||
808 | "error: Failed to find image chunk for " | ||
809 | "plugrec 0x%04x.\n", | ||
810 | s3plug[i].itemcode); | ||
811 | result = 1; | ||
812 | continue; | ||
813 | } | ||
814 | |||
815 | /* Plug data */ | ||
816 | chunkoff = pstart - cstart; | ||
817 | dest = fchunk[c].data + chunkoff; | ||
818 | pr_debug("Plugging item 0x%04x @ 0x%06x, len=%d, " | ||
819 | "cnum=%d coff=0x%06x\n", | ||
820 | s3plug[i].itemcode, pstart, s3plug[i].len, | ||
821 | c, chunkoff); | ||
822 | |||
823 | if ( j == -1 ) { /* plug the filename */ | ||
824 | memset(dest, 0, s3plug[i].len); | ||
825 | strncpy(dest, PRISM2_USB_FWFILE, s3plug[i].len - 1); | ||
826 | } else { /* plug a PDR */ | ||
827 | memcpy( dest, &(pda->rec[j]->data), s3plug[i].len); | ||
828 | } | ||
829 | } | ||
830 | return result; | ||
831 | |||
832 | } | ||
833 | |||
834 | |||
835 | /*---------------------------------------------------------------- | ||
836 | * read_cardpda | ||
837 | * | ||
838 | * Sends the command for the driver to read the pda from the card | ||
839 | * named in the device variable. Upon success, the card pda is | ||
840 | * stored in the "cardpda" variables. Note that the pda structure | ||
841 | * is considered 'well formed' after this function. That means | ||
842 | * that the nrecs is valid, the rec array has been set up, and there's | ||
843 | * a valid PDAEND record in the raw PDA data. | ||
844 | * | ||
845 | * Arguments: | ||
846 | * pda pda structure | ||
847 | * wlandev device | ||
848 | * | ||
849 | * Returns: | ||
850 | * 0 - success | ||
851 | * ~0 - failure (probably an errno) | ||
852 | ----------------------------------------------------------------*/ | ||
853 | int read_cardpda(pda_t *pda, wlandevice_t *wlandev) | ||
854 | { | ||
855 | int result = 0; | ||
856 | p80211msg_p2req_readpda_t msg; | ||
857 | |||
858 | /* set up the msg */ | ||
859 | msg.msgcode = DIDmsg_p2req_readpda; | ||
860 | msg.msglen = sizeof(msg); | ||
861 | strcpy(msg.devname, wlandev->name); | ||
862 | msg.pda.did = DIDmsg_p2req_readpda_pda; | ||
863 | msg.pda.len = HFA384x_PDA_LEN_MAX; | ||
864 | msg.pda.status = P80211ENUM_msgitem_status_no_value; | ||
865 | msg.resultcode.did = DIDmsg_p2req_readpda_resultcode; | ||
866 | msg.resultcode.len = sizeof(u32); | ||
867 | msg.resultcode.status = P80211ENUM_msgitem_status_no_value; | ||
868 | |||
869 | if ( prism2mgmt_readpda(wlandev, &msg) != 0 ) { | ||
870 | /* prism2mgmt_readpda prints an errno if appropriate */ | ||
871 | result = -1; | ||
872 | } else if ( msg.resultcode.data == P80211ENUM_resultcode_success ) { | ||
873 | memcpy(pda->buf, msg.pda.data, HFA384x_PDA_LEN_MAX); | ||
874 | result = mkpdrlist(pda); | ||
875 | } else { | ||
876 | /* resultcode must've been something other than success */ | ||
877 | result = -1; | ||
878 | } | ||
879 | |||
880 | return result; | ||
881 | } | ||
882 | |||
883 | |||
884 | /*---------------------------------------------------------------- | ||
885 | * copy_line | ||
886 | * | ||
887 | * Copies a line of text, up to \n, \0, or SREC_LINE_MAX, or limit of | ||
888 | * From array | ||
889 | * | ||
890 | * Arguments: | ||
891 | * from From addr | ||
892 | * to To addr | ||
893 | * limit Addr of last character in From array that can be copied | ||
894 | * | ||
895 | * Returns: | ||
896 | * Num characters copied | ||
897 | ----------------------------------------------------------------*/ | ||
898 | int copyline(char *from, char *to, char *limit) | ||
899 | { | ||
900 | int c = 0; | ||
901 | |||
902 | while ((c < SREC_LINE_MAX - 1) && (from + c <= limit) && | ||
903 | (from[c] != '\n') && (from[c] != '\0')) { | ||
904 | to[c] = from[c]; | ||
905 | c++; | ||
906 | } | ||
907 | |||
908 | to[c] = '\0'; | ||
909 | return (c < SREC_LINE_MAX - 1) ? c + 1 : c; | ||
910 | } | ||
911 | |||
912 | |||
913 | /*---------------------------------------------------------------- | ||
914 | * read_srecfile | ||
915 | * | ||
916 | * Reads the given srecord file and loads the records into the | ||
917 | * s3xxx arrays. This function can be called repeatedly (once for | ||
918 | * each of a set of files), if necessary. This function performs | ||
919 | * no validation of the data except for the grossest of S-record | ||
920 | * line format checks. Don't forget that these will be DOS files... | ||
921 | * CR/LF at the end of each line. | ||
922 | * | ||
923 | * Here's the SREC format we're dealing with: | ||
924 | * S[37]nnaaaaaaaaddd...dddcc | ||
925 | * | ||
926 | * nn - number of bytes starting with the address field | ||
927 | * aaaaaaaa - address in readable (or big endian) format | ||
928 | * dd....dd - 0-245 data bytes (two chars per byte) | ||
929 | * cc - checksum | ||
930 | * | ||
931 | * The S7 record's (there should be only one) address value gets | ||
932 | * saved in startaddr. It's the start execution address used | ||
933 | * for RAM downloads. | ||
934 | * | ||
935 | * The S3 records have a collection of subformats indicated by the | ||
936 | * value of aaaaaaaa: | ||
937 | * 0xff000000 - Plug record, data field format: | ||
938 | * xxxxxxxxaaaaaaaassssssss | ||
939 | * x - PDR code number (little endian) | ||
940 | * a - Address in load image to plug (little endian) | ||
941 | * s - Length of plug data area (little endian) | ||
942 | * | ||
943 | * 0xff100000 - CRC16 generation record, data field format: | ||
944 | * aaaaaaaassssssssbbbbbbbb | ||
945 | * a - Start address for CRC calculation (little endian) | ||
946 | * s - Length of data to calculate over (little endian) | ||
947 | * b - Boolean, true=write crc, false=don't write | ||
948 | * | ||
949 | * 0xff200000 - Info record, data field format: | ||
950 | * ssssttttdd..dd | ||
951 | * s - Size in words (little endian) | ||
952 | * t - Info type (little endian), see #defines and | ||
953 | * s3inforec_t for details about types. | ||
954 | * d - (s - 1) little endian words giving the contents of | ||
955 | * the given info type. | ||
956 | * | ||
957 | * Arguments: | ||
958 | * rfptr firmware image (s-record structure) in kernel memory | ||
959 | * rfsize firmware size in kernel memory | ||
960 | * | ||
961 | * Returns: | ||
962 | * 0 - success | ||
963 | * ~0 - failure (probably an errno) | ||
964 | ----------------------------------------------------------------*/ | ||
965 | int read_srecfile(char *rfptr, int rfsize) | ||
966 | { | ||
967 | int result = 0; | ||
968 | char buf[SREC_LINE_MAX]; | ||
969 | char tmpbuf[30]; | ||
970 | s3datarec_t tmprec; | ||
971 | int i, c; | ||
972 | int line = 0; | ||
973 | u16 *tmpinfo; | ||
974 | char *endptr = rfptr + rfsize; | ||
975 | |||
976 | |||
977 | pr_debug("Reading S-record file ...\n"); | ||
978 | |||
979 | while ( (c = copyline(rfptr, buf, endptr)) >= 12 ) { | ||
980 | rfptr = rfptr + c; | ||
981 | line++; | ||
982 | if ( buf[0] != 'S' ) { | ||
983 | printk(KERN_ERR "%d warning: No initial \'S\'\n", line); | ||
984 | return 1; | ||
985 | } | ||
986 | if ( buf[1] == '7' ) { /* S7 record, start address */ | ||
987 | buf[12] = '\0'; | ||
988 | startaddr = simple_strtoul(buf+4, NULL, 16); | ||
989 | pr_debug(" S7 start addr, line=%d " | ||
990 | " addr=0x%08x\n", | ||
991 | line, | ||
992 | startaddr); | ||
993 | continue; | ||
994 | } else if ( buf[1] == '3') { | ||
995 | /* Ok, it's an S3, parse and put it in the right array */ | ||
996 | /* Record Length field (we only want datalen) */ | ||
997 | memcpy(tmpbuf, buf+S3LEN_TXTOFFSET, S3LEN_TXTLEN); | ||
998 | tmpbuf[S3LEN_TXTLEN] = '\0'; | ||
999 | tmprec.len = simple_strtoul( tmpbuf, NULL, 16) - 4 - 1; /* 4=addr, 1=cksum */ | ||
1000 | /* Address field */ | ||
1001 | memcpy(tmpbuf, buf+S3ADDR_TXTOFFSET, S3ADDR_TXTLEN); | ||
1002 | tmpbuf[S3ADDR_TXTLEN] = '\0'; | ||
1003 | tmprec.addr = simple_strtoul( tmpbuf, NULL, 16); | ||
1004 | /* Checksum field */ | ||
1005 | tmprec.checksum = simple_strtoul( buf+strlen(buf)-2, NULL, 16); | ||
1006 | |||
1007 | switch( tmprec.addr ) | ||
1008 | { | ||
1009 | case S3ADDR_PLUG: | ||
1010 | memcpy(tmpbuf, buf+S3PLUG_ITEMCODE_TXTOFFSET, S3PLUG_ITEMCODE_TXTLEN); | ||
1011 | tmpbuf[S3PLUG_ITEMCODE_TXTLEN] = '\0'; | ||
1012 | s3plug[ns3plug].itemcode = simple_strtoul(tmpbuf,NULL,16); | ||
1013 | s3plug[ns3plug].itemcode = bswap_32(s3plug[ns3plug].itemcode); | ||
1014 | |||
1015 | memcpy(tmpbuf, buf+S3PLUG_ADDR_TXTOFFSET, S3PLUG_ADDR_TXTLEN); | ||
1016 | tmpbuf[S3PLUG_ADDR_TXTLEN] = '\0'; | ||
1017 | s3plug[ns3plug].addr = simple_strtoul(tmpbuf,NULL,16); | ||
1018 | s3plug[ns3plug].addr = bswap_32(s3plug[ns3plug].addr); | ||
1019 | |||
1020 | memcpy(tmpbuf, buf+S3PLUG_LEN_TXTOFFSET, S3PLUG_LEN_TXTLEN); | ||
1021 | tmpbuf[S3PLUG_LEN_TXTLEN] = '\0'; | ||
1022 | s3plug[ns3plug].len = simple_strtoul(tmpbuf,NULL,16); | ||
1023 | s3plug[ns3plug].len = bswap_32(s3plug[ns3plug].len); | ||
1024 | |||
1025 | pr_debug(" S3 plugrec, line=%d " | ||
1026 | "itemcode=0x%04x addr=0x%08x len=%d\n", | ||
1027 | line, | ||
1028 | s3plug[ns3plug].itemcode, | ||
1029 | s3plug[ns3plug].addr, | ||
1030 | s3plug[ns3plug].len); | ||
1031 | |||
1032 | ns3plug++; | ||
1033 | if ( ns3plug == S3PLUG_MAX ) { | ||
1034 | printk(KERN_ERR "S3 plugrec limit reached - aborting\n"); | ||
1035 | return 1; | ||
1036 | } | ||
1037 | break; | ||
1038 | case S3ADDR_CRC: | ||
1039 | memcpy(tmpbuf, buf+S3CRC_ADDR_TXTOFFSET, S3CRC_ADDR_TXTLEN); | ||
1040 | tmpbuf[S3CRC_ADDR_TXTLEN] = '\0'; | ||
1041 | s3crc[ns3crc].addr = simple_strtoul(tmpbuf,NULL,16); | ||
1042 | s3crc[ns3crc].addr = bswap_32(s3crc[ns3crc].addr); | ||
1043 | |||
1044 | memcpy(tmpbuf, buf+S3CRC_LEN_TXTOFFSET, S3CRC_LEN_TXTLEN); | ||
1045 | tmpbuf[S3CRC_LEN_TXTLEN] = '\0'; | ||
1046 | s3crc[ns3crc].len = simple_strtoul(tmpbuf,NULL,16); | ||
1047 | s3crc[ns3crc].len = bswap_32(s3crc[ns3crc].len); | ||
1048 | |||
1049 | memcpy(tmpbuf, buf+S3CRC_DOWRITE_TXTOFFSET, S3CRC_DOWRITE_TXTLEN); | ||
1050 | tmpbuf[S3CRC_DOWRITE_TXTLEN] = '\0'; | ||
1051 | s3crc[ns3crc].dowrite = simple_strtoul(tmpbuf,NULL,16); | ||
1052 | s3crc[ns3crc].dowrite = bswap_32(s3crc[ns3crc].dowrite); | ||
1053 | |||
1054 | pr_debug(" S3 crcrec, line=%d " | ||
1055 | "addr=0x%08x len=%d write=0x%08x\n", | ||
1056 | line, | ||
1057 | s3crc[ns3crc].addr, | ||
1058 | s3crc[ns3crc].len, | ||
1059 | s3crc[ns3crc].dowrite); | ||
1060 | ns3crc++; | ||
1061 | if ( ns3crc == S3CRC_MAX ) { | ||
1062 | printk(KERN_ERR "S3 crcrec limit reached - aborting\n"); | ||
1063 | return 1; | ||
1064 | } | ||
1065 | break; | ||
1066 | case S3ADDR_INFO: | ||
1067 | memcpy(tmpbuf, buf+S3INFO_LEN_TXTOFFSET, S3INFO_LEN_TXTLEN); | ||
1068 | tmpbuf[S3INFO_LEN_TXTLEN] = '\0'; | ||
1069 | s3info[ns3info].len = simple_strtoul(tmpbuf,NULL,16); | ||
1070 | s3info[ns3info].len = bswap_16(s3info[ns3info].len); | ||
1071 | |||
1072 | memcpy(tmpbuf, buf+S3INFO_TYPE_TXTOFFSET, S3INFO_TYPE_TXTLEN); | ||
1073 | tmpbuf[S3INFO_TYPE_TXTLEN] = '\0'; | ||
1074 | s3info[ns3info].type = simple_strtoul(tmpbuf,NULL,16); | ||
1075 | s3info[ns3info].type = bswap_16(s3info[ns3info].type); | ||
1076 | |||
1077 | pr_debug(" S3 inforec, line=%d " | ||
1078 | "len=0x%04x type=0x%04x\n", | ||
1079 | line, | ||
1080 | s3info[ns3info].len, | ||
1081 | s3info[ns3info].type); | ||
1082 | if ( ((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info) ) { | ||
1083 | printk(KERN_ERR " S3 inforec length too long - aborting\n"); | ||
1084 | return 1; | ||
1085 | } | ||
1086 | |||
1087 | tmpinfo = (u16*)&(s3info[ns3info].info.version); | ||
1088 | for (i = 0; i < s3info[ns3info].len - 1; i++) { | ||
1089 | memcpy( tmpbuf, buf+S3INFO_DATA_TXTOFFSET+(i*4), 4); | ||
1090 | tmpbuf[4] = '\0'; | ||
1091 | tmpinfo[i] = simple_strtoul(tmpbuf,NULL,16); | ||
1092 | tmpinfo[i] = bswap_16(tmpinfo[i]); | ||
1093 | } | ||
1094 | pr_debug(" info="); | ||
1095 | for (i = 0; i < s3info[ns3info].len - 1; i++) { | ||
1096 | pr_debug("%04x ", tmpinfo[i]); | ||
1097 | } | ||
1098 | pr_debug("\n"); | ||
1099 | |||
1100 | ns3info++; | ||
1101 | if ( ns3info == S3INFO_MAX ) { | ||
1102 | printk(KERN_ERR "S3 inforec limit reached - aborting\n"); | ||
1103 | return 1; | ||
1104 | } | ||
1105 | break; | ||
1106 | default: /* Data record */ | ||
1107 | s3data[ns3data].addr = tmprec.addr; | ||
1108 | s3data[ns3data].len = tmprec.len; | ||
1109 | s3data[ns3data].checksum = tmprec.checksum; | ||
1110 | s3data[ns3data].data = kmalloc(tmprec.len, GFP_KERNEL); | ||
1111 | for ( i = 0; i < tmprec.len; i++) { | ||
1112 | memcpy(tmpbuf, buf+S3DATA_TXTOFFSET+(i*2), 2); | ||
1113 | tmpbuf[2] = '\0'; | ||
1114 | s3data[ns3data].data[i] = simple_strtoul(tmpbuf, NULL, 16); | ||
1115 | } | ||
1116 | ns3data++; | ||
1117 | if ( ns3data == S3DATA_MAX ) { | ||
1118 | printk(KERN_ERR "S3 datarec limit reached - aborting\n"); | ||
1119 | return 1; | ||
1120 | } | ||
1121 | break; | ||
1122 | } | ||
1123 | } else { | ||
1124 | printk(KERN_WARNING "%d warning: Unknown S-record detected.\n", line); | ||
1125 | } | ||
1126 | } | ||
1127 | return result; | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /*---------------------------------------------------------------- | ||
1132 | * s3datarec_compare | ||
1133 | * | ||
1134 | * Comparison function for sort(). | ||
1135 | * | ||
1136 | * Arguments: | ||
1137 | * p1 ptr to the first item | ||
1138 | * p2 ptr to the second item | ||
1139 | * Returns: | ||
1140 | * 0 items are equal | ||
1141 | * <0 p1 < p2 | ||
1142 | * >0 p1 > p2 | ||
1143 | ----------------------------------------------------------------*/ | ||
1144 | int s3datarec_compare(const void *p1, const void *p2) | ||
1145 | { | ||
1146 | const s3datarec_t *s1 = p1; | ||
1147 | const s3datarec_t *s2 = p2; | ||
1148 | if ( s1->addr == s2->addr ) return 0; | ||
1149 | if ( s1->addr < s2->addr ) return -1; | ||
1150 | return 1; | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | /*---------------------------------------------------------------- | ||
1155 | * writeimage | ||
1156 | * | ||
1157 | * Takes the chunks, builds p80211 messages and sends them down | ||
1158 | * to the driver for writing to the card. | ||
1159 | * | ||
1160 | * Arguments: | ||
1161 | * wlandev device | ||
1162 | * fchunk Array of image chunks | ||
1163 | * nfchunks Number of image chunks | ||
1164 | * | ||
1165 | * Returns: | ||
1166 | * 0 success | ||
1167 | * ~0 failure | ||
1168 | ----------------------------------------------------------------*/ | ||
1169 | int writeimage(wlandevice_t *wlandev, imgchunk_t *fchunk, unsigned int nfchunks) | ||
1170 | { | ||
1171 | int result = 0; | ||
1172 | p80211msg_p2req_ramdl_state_t rstatemsg; | ||
1173 | p80211msg_p2req_ramdl_write_t rwritemsg; | ||
1174 | p80211msg_t *msgp; | ||
1175 | u32 resultcode; | ||
1176 | int i; | ||
1177 | int j; | ||
1178 | unsigned int nwrites; | ||
1179 | u32 curroff; | ||
1180 | u32 currlen; | ||
1181 | u32 currdaddr; | ||
1182 | |||
1183 | /* Initialize the messages */ | ||
1184 | memset(&rstatemsg, 0, sizeof(rstatemsg)); | ||
1185 | strcpy(rstatemsg.devname, wlandev->name); | ||
1186 | rstatemsg.msgcode = DIDmsg_p2req_ramdl_state; | ||
1187 | rstatemsg.msglen = sizeof(rstatemsg); | ||
1188 | rstatemsg.enable.did = DIDmsg_p2req_ramdl_state_enable; | ||
1189 | rstatemsg.exeaddr.did = DIDmsg_p2req_ramdl_state_exeaddr; | ||
1190 | rstatemsg.resultcode.did = DIDmsg_p2req_ramdl_state_resultcode; | ||
1191 | rstatemsg.enable.status = P80211ENUM_msgitem_status_data_ok; | ||
1192 | rstatemsg.exeaddr.status = P80211ENUM_msgitem_status_data_ok; | ||
1193 | rstatemsg.resultcode.status = P80211ENUM_msgitem_status_no_value; | ||
1194 | rstatemsg.enable.len = sizeof(u32); | ||
1195 | rstatemsg.exeaddr.len = sizeof(u32); | ||
1196 | rstatemsg.resultcode.len = sizeof(u32); | ||
1197 | |||
1198 | memset(&rwritemsg, 0, sizeof(rwritemsg)); | ||
1199 | strcpy(rwritemsg.devname, wlandev->name); | ||
1200 | rwritemsg.msgcode = DIDmsg_p2req_ramdl_write; | ||
1201 | rwritemsg.msglen = sizeof(rwritemsg); | ||
1202 | rwritemsg.addr.did = DIDmsg_p2req_ramdl_write_addr; | ||
1203 | rwritemsg.len.did = DIDmsg_p2req_ramdl_write_len; | ||
1204 | rwritemsg.data.did = DIDmsg_p2req_ramdl_write_data; | ||
1205 | rwritemsg.resultcode.did = DIDmsg_p2req_ramdl_write_resultcode; | ||
1206 | rwritemsg.addr.status = P80211ENUM_msgitem_status_data_ok; | ||
1207 | rwritemsg.len.status = P80211ENUM_msgitem_status_data_ok; | ||
1208 | rwritemsg.data.status = P80211ENUM_msgitem_status_data_ok; | ||
1209 | rwritemsg.resultcode.status = P80211ENUM_msgitem_status_no_value; | ||
1210 | rwritemsg.addr.len = sizeof(u32); | ||
1211 | rwritemsg.len.len = sizeof(u32); | ||
1212 | rwritemsg.data.len = WRITESIZE_MAX; | ||
1213 | rwritemsg.resultcode.len = sizeof(u32); | ||
1214 | |||
1215 | /* Send xxx_state(enable) */ | ||
1216 | pr_debug("Sending dl_state(enable) message.\n"); | ||
1217 | rstatemsg.enable.data = P80211ENUM_truth_true; | ||
1218 | rstatemsg.exeaddr.data = startaddr; | ||
1219 | |||
1220 | msgp = (p80211msg_t*)&rstatemsg; | ||
1221 | result = prism2mgmt_ramdl_state(wlandev, msgp); | ||
1222 | if ( result ) { | ||
1223 | printk(KERN_ERR | ||
1224 | "writeimage state enable failed w/ result=%d, " | ||
1225 | "aborting download\n", result); | ||
1226 | return result; | ||
1227 | } | ||
1228 | resultcode = rstatemsg.resultcode.data; | ||
1229 | if ( resultcode != P80211ENUM_resultcode_success ) { | ||
1230 | printk(KERN_ERR | ||
1231 | "writeimage()->xxxdl_state msg indicates failure, " | ||
1232 | "w/ resultcode=%d, aborting download.\n", | ||
1233 | resultcode); | ||
1234 | return 1; | ||
1235 | } | ||
1236 | |||
1237 | /* Now, loop through the data chunks and send WRITESIZE_MAX data */ | ||
1238 | for ( i = 0; i < nfchunks; i++) { | ||
1239 | nwrites = fchunk[i].len / WRITESIZE_MAX; | ||
1240 | nwrites += (fchunk[i].len % WRITESIZE_MAX) ? 1 : 0; | ||
1241 | curroff = 0; | ||
1242 | for ( j = 0; j < nwrites; j++) { | ||
1243 | currlen = | ||
1244 | (fchunk[i].len - (WRITESIZE_MAX * j)) > WRITESIZE_MAX ? | ||
1245 | WRITESIZE_MAX : | ||
1246 | (fchunk[i].len - (WRITESIZE_MAX * j)); | ||
1247 | curroff = j * WRITESIZE_MAX; | ||
1248 | currdaddr = fchunk[i].addr + curroff; | ||
1249 | /* Setup the message */ | ||
1250 | rwritemsg.addr.data = currdaddr; | ||
1251 | rwritemsg.len.data = currlen; | ||
1252 | memcpy(rwritemsg.data.data, | ||
1253 | fchunk[i].data + curroff, | ||
1254 | currlen); | ||
1255 | |||
1256 | /* Send flashdl_write(pda) */ | ||
1257 | pr_debug("Sending xxxdl_write message addr=%06x len=%d.\n", | ||
1258 | currdaddr, currlen); | ||
1259 | |||
1260 | msgp = (p80211msg_t*)&rwritemsg; | ||
1261 | result = prism2mgmt_ramdl_write(wlandev, msgp); | ||
1262 | |||
1263 | /* Check the results */ | ||
1264 | if ( result ) { | ||
1265 | printk(KERN_ERR | ||
1266 | "writeimage chunk write failed w/ result=%d, " | ||
1267 | "aborting download\n", result); | ||
1268 | return result; | ||
1269 | } | ||
1270 | resultcode = rstatemsg.resultcode.data; | ||
1271 | if ( resultcode != P80211ENUM_resultcode_success ) { | ||
1272 | printk(KERN_ERR | ||
1273 | "writeimage()->xxxdl_write msg indicates failure, " | ||
1274 | "w/ resultcode=%d, aborting download.\n", | ||
1275 | resultcode); | ||
1276 | return 1; | ||
1277 | } | ||
1278 | |||
1279 | } | ||
1280 | } | ||
1281 | |||
1282 | /* Send xxx_state(disable) */ | ||
1283 | pr_debug("Sending dl_state(disable) message.\n"); | ||
1284 | rstatemsg.enable.data = P80211ENUM_truth_false; | ||
1285 | rstatemsg.exeaddr.data = 0; | ||
1286 | |||
1287 | msgp = (p80211msg_t*)&rstatemsg; | ||
1288 | result = prism2mgmt_ramdl_state(wlandev, msgp); | ||
1289 | if ( result ) { | ||
1290 | printk(KERN_ERR | ||
1291 | "writeimage state disable failed w/ result=%d, " | ||
1292 | "aborting download\n", result); | ||
1293 | return result; | ||
1294 | } | ||
1295 | resultcode = rstatemsg.resultcode.data; | ||
1296 | if ( resultcode != P80211ENUM_resultcode_success ) { | ||
1297 | printk(KERN_ERR | ||
1298 | "writeimage()->xxxdl_state msg indicates failure, " | ||
1299 | "w/ resultcode=%d, aborting download.\n", | ||
1300 | resultcode); | ||
1301 | return 1; | ||
1302 | } | ||
1303 | return result; | ||
1304 | } | ||
1305 | |||
1306 | |||
1307 | |||
1308 | int validate_identity(void) | ||
1309 | { | ||
1310 | int i; | ||
1311 | int result = 1; | ||
1312 | |||
1313 | pr_debug("NIC ID: %#x v%d.%d.%d\n", | ||
1314 | nicid.id, | ||
1315 | nicid.major, | ||
1316 | nicid.minor, | ||
1317 | nicid.variant); | ||
1318 | pr_debug("MFI ID: %#x v%d %d->%d\n", | ||
1319 | rfid.id, | ||
1320 | rfid.variant, | ||
1321 | rfid.bottom, | ||
1322 | rfid.top); | ||
1323 | pr_debug("CFI ID: %#x v%d %d->%d\n", | ||
1324 | macid.id, | ||
1325 | macid.variant, | ||
1326 | macid.bottom, | ||
1327 | macid.top); | ||
1328 | pr_debug("PRI ID: %#x v%d %d->%d\n", | ||
1329 | priid.id, | ||
1330 | priid.variant, | ||
1331 | priid.bottom, | ||
1332 | priid.top); | ||
1333 | |||
1334 | for (i = 0 ; i < ns3info ; i ++) { | ||
1335 | switch (s3info[i].type) { | ||
1336 | case 1: | ||
1337 | pr_debug("Version: ID %#x %d.%d.%d\n", | ||
1338 | s3info[i].info.version.id, | ||
1339 | s3info[i].info.version.major, | ||
1340 | s3info[i].info.version.minor, | ||
1341 | s3info[i].info.version.variant); | ||
1342 | break; | ||
1343 | case 2: | ||
1344 | pr_debug("Compat: Role %#x Id %#x v%d %d->%d\n", | ||
1345 | s3info[i].info.compat.role, | ||
1346 | s3info[i].info.compat.id, | ||
1347 | s3info[i].info.compat.variant, | ||
1348 | s3info[i].info.compat.bottom, | ||
1349 | s3info[i].info.compat.top); | ||
1350 | |||
1351 | /* MAC compat range */ | ||
1352 | if ((s3info[i].info.compat.role == 1) && | ||
1353 | (s3info[i].info.compat.id == 2)) { | ||
1354 | if (s3info[i].info.compat.variant != | ||
1355 | macid.variant) { | ||
1356 | result = 2; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | /* PRI compat range */ | ||
1361 | if ((s3info[i].info.compat.role == 1) && | ||
1362 | (s3info[i].info.compat.id == 3)) { | ||
1363 | if ((s3info[i].info.compat.bottom > priid.top) || | ||
1364 | (s3info[i].info.compat.top < priid.bottom)){ | ||
1365 | result = 3; | ||
1366 | } | ||
1367 | } | ||
1368 | /* SEC compat range */ | ||
1369 | if ((s3info[i].info.compat.role == 1) && | ||
1370 | (s3info[i].info.compat.id == 4)) { | ||
1371 | |||
1372 | } | ||
1373 | |||
1374 | break; | ||
1375 | case 3: | ||
1376 | pr_debug("Seq: %#x\n", s3info[i].info.buildseq); | ||
1377 | |||
1378 | break; | ||
1379 | case 4: | ||
1380 | pr_debug("Platform: ID %#x %d.%d.%d\n", | ||
1381 | s3info[i].info.version.id, | ||
1382 | s3info[i].info.version.major, | ||
1383 | s3info[i].info.version.minor, | ||
1384 | s3info[i].info.version.variant); | ||
1385 | |||
1386 | if (nicid.id != s3info[i].info.version.id) | ||
1387 | continue; | ||
1388 | if (nicid.major != s3info[i].info.version.major) | ||
1389 | continue; | ||
1390 | if (nicid.minor != s3info[i].info.version.minor) | ||
1391 | continue; | ||
1392 | if ((nicid.variant != s3info[i].info.version.variant) && | ||
1393 | (nicid.id != 0x8008)) | ||
1394 | continue; | ||
1395 | |||
1396 | if (result != 2) | ||
1397 | result = 0; | ||
1398 | break; | ||
1399 | case 0x8001: | ||
1400 | pr_debug("name inforec len %d\n", s3info[i].len); | ||
1401 | |||
1402 | break; | ||
1403 | default: | ||
1404 | pr_debug("Unknown inforec type %d\n", s3info[i].type); | ||
1405 | } | ||
1406 | } | ||
1407 | // walk through | ||
1408 | |||
1409 | return result; | ||
1410 | } | ||
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index d8a12982135..d9c6f5a97cf 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include "prism2mgmt.c" | 2 | #include "prism2mgmt.c" |
3 | #include "prism2mib.c" | 3 | #include "prism2mib.c" |
4 | #include "prism2sta.c" | 4 | #include "prism2sta.c" |
5 | #include "prism2fw.c" | ||
5 | 6 | ||
6 | #define PRISM_USB_DEVICE(vid, pid, name) \ | 7 | #define PRISM_USB_DEVICE(vid, pid, name) \ |
7 | USB_DEVICE(vid, pid), \ | 8 | USB_DEVICE(vid, pid), \ |
@@ -153,15 +154,16 @@ static int prism2sta_probe_usb(struct usb_interface *interface, | |||
153 | 154 | ||
154 | wlandev->msdstate = WLAN_MSD_HWPRESENT; | 155 | wlandev->msdstate = WLAN_MSD_HWPRESENT; |
155 | 156 | ||
157 | /* Try and load firmware, then enable card before we register */ | ||
158 | prism2_fwtry(dev, wlandev); | ||
159 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); | ||
160 | |||
156 | if (register_wlandev(wlandev) != 0) { | 161 | if (register_wlandev(wlandev) != 0) { |
157 | printk(KERN_ERR "%s: register_wlandev() failed.\n", dev_info); | 162 | printk(KERN_ERR "%s: register_wlandev() failed.\n", dev_info); |
158 | result = -EIO; | 163 | result = -EIO; |
159 | goto failed; | 164 | goto failed; |
160 | } | 165 | } |
161 | 166 | ||
162 | /* enable the card */ | ||
163 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); | ||
164 | |||
165 | goto done; | 167 | goto done; |
166 | 168 | ||
167 | failed: | 169 | failed: |
@@ -170,7 +172,6 @@ failed: | |||
170 | wlandev = NULL; | 172 | wlandev = NULL; |
171 | 173 | ||
172 | done: | 174 | done: |
173 | p80211_allow_ioctls(wlandev); | ||
174 | usb_set_intfdata(interface, wlandev); | 175 | usb_set_intfdata(interface, wlandev); |
175 | return result; | 176 | return result; |
176 | } | 177 | } |