aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/orinoco/hw.c216
-rw-r--r--drivers/net/wireless/orinoco/hw.h1
-rw-r--r--drivers/net/wireless/orinoco/main.c218
3 files changed, 219 insertions, 216 deletions
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 632fac86a308..209c6bef0cd9 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -13,6 +13,8 @@
13 13
14#include "hw.h" 14#include "hw.h"
15 15
16#define SYMBOL_MAX_VER_LEN (14)
17
16/********************************************************************/ 18/********************************************************************/
17/* Data tables */ 19/* Data tables */
18/********************************************************************/ 20/********************************************************************/
@@ -36,6 +38,220 @@ static const struct {
36}; 38};
37#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table) 39#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
38 40
41/* Firmware version encoding */
42struct comp_id {
43 u16 id, variant, major, minor;
44} __attribute__ ((packed));
45
46static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
47{
48 if (nic_id->id < 0x8000)
49 return FIRMWARE_TYPE_AGERE;
50 else if (nic_id->id == 0x8000 && nic_id->major == 0)
51 return FIRMWARE_TYPE_SYMBOL;
52 else
53 return FIRMWARE_TYPE_INTERSIL;
54}
55
56/* Set priv->firmware type, determine firmware properties */
57int determine_fw_capabilities(struct orinoco_private *priv)
58{
59 struct net_device *dev = priv->ndev;
60 hermes_t *hw = &priv->hw;
61 int err;
62 struct comp_id nic_id, sta_id;
63 unsigned int firmver;
64 char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
65
66 /* Get the hardware version */
67 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
68 if (err) {
69 printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
70 dev->name, err);
71 return err;
72 }
73
74 le16_to_cpus(&nic_id.id);
75 le16_to_cpus(&nic_id.variant);
76 le16_to_cpus(&nic_id.major);
77 le16_to_cpus(&nic_id.minor);
78 printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
79 dev->name, nic_id.id, nic_id.variant,
80 nic_id.major, nic_id.minor);
81
82 priv->firmware_type = determine_firmware_type(&nic_id);
83
84 /* Get the firmware version */
85 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
86 if (err) {
87 printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
88 dev->name, err);
89 return err;
90 }
91
92 le16_to_cpus(&sta_id.id);
93 le16_to_cpus(&sta_id.variant);
94 le16_to_cpus(&sta_id.major);
95 le16_to_cpus(&sta_id.minor);
96 printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
97 dev->name, sta_id.id, sta_id.variant,
98 sta_id.major, sta_id.minor);
99
100 switch (sta_id.id) {
101 case 0x15:
102 printk(KERN_ERR "%s: Primary firmware is active\n",
103 dev->name);
104 return -ENODEV;
105 case 0x14b:
106 printk(KERN_ERR "%s: Tertiary firmware is active\n",
107 dev->name);
108 return -ENODEV;
109 case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
110 case 0x21: /* Symbol Spectrum24 Trilogy */
111 break;
112 default:
113 printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
114 dev->name);
115 break;
116 }
117
118 /* Default capabilities */
119 priv->has_sensitivity = 1;
120 priv->has_mwo = 0;
121 priv->has_preamble = 0;
122 priv->has_port3 = 1;
123 priv->has_ibss = 1;
124 priv->has_wep = 0;
125 priv->has_big_wep = 0;
126 priv->has_alt_txcntl = 0;
127 priv->has_ext_scan = 0;
128 priv->has_wpa = 0;
129 priv->do_fw_download = 0;
130
131 /* Determine capabilities from the firmware version */
132 switch (priv->firmware_type) {
133 case FIRMWARE_TYPE_AGERE:
134 /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
135 ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
136 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
137 "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
138
139 firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
140
141 priv->has_ibss = (firmver >= 0x60006);
142 priv->has_wep = (firmver >= 0x40020);
143 priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
144 Gold cards from the others? */
145 priv->has_mwo = (firmver >= 0x60000);
146 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
147 priv->ibss_port = 1;
148 priv->has_hostscan = (firmver >= 0x8000a);
149 priv->do_fw_download = 1;
150 priv->broken_monitor = (firmver >= 0x80000);
151 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
152 priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
153 priv->has_wpa = (firmver >= 0x9002a);
154 /* Tested with Agere firmware :
155 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
156 * Tested CableTron firmware : 4.32 => Anton */
157 break;
158 case FIRMWARE_TYPE_SYMBOL:
159 /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
160 /* Intel MAC : 00:02:B3:* */
161 /* 3Com MAC : 00:50:DA:* */
162 memset(tmp, 0, sizeof(tmp));
163 /* Get the Symbol firmware version */
164 err = hermes_read_ltv(hw, USER_BAP,
165 HERMES_RID_SECONDARYVERSION_SYMBOL,
166 SYMBOL_MAX_VER_LEN, NULL, &tmp);
167 if (err) {
168 printk(KERN_WARNING
169 "%s: Error %d reading Symbol firmware info. "
170 "Wildly guessing capabilities...\n",
171 dev->name, err);
172 firmver = 0;
173 tmp[0] = '\0';
174 } else {
175 /* The firmware revision is a string, the format is
176 * something like : "V2.20-01".
177 * Quick and dirty parsing... - Jean II
178 */
179 firmver = ((tmp[1] - '0') << 16)
180 | ((tmp[3] - '0') << 12)
181 | ((tmp[4] - '0') << 8)
182 | ((tmp[6] - '0') << 4)
183 | (tmp[7] - '0');
184
185 tmp[SYMBOL_MAX_VER_LEN] = '\0';
186 }
187
188 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
189 "Symbol %s", tmp);
190
191 priv->has_ibss = (firmver >= 0x20000);
192 priv->has_wep = (firmver >= 0x15012);
193 priv->has_big_wep = (firmver >= 0x20000);
194 priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
195 (firmver >= 0x29000 && firmver < 0x30000) ||
196 firmver >= 0x31000;
197 priv->has_preamble = (firmver >= 0x20000);
198 priv->ibss_port = 4;
199
200 /* Symbol firmware is found on various cards, but
201 * there has been no attempt to check firmware
202 * download on non-spectrum_cs based cards.
203 *
204 * Given that the Agere firmware download works
205 * differently, we should avoid doing a firmware
206 * download with the Symbol algorithm on non-spectrum
207 * cards.
208 *
209 * For now we can identify a spectrum_cs based card
210 * because it has a firmware reset function.
211 */
212 priv->do_fw_download = (priv->stop_fw != NULL);
213
214 priv->broken_disableport = (firmver == 0x25013) ||
215 (firmver >= 0x30000 && firmver <= 0x31000);
216 priv->has_hostscan = (firmver >= 0x31001) ||
217 (firmver >= 0x29057 && firmver < 0x30000);
218 /* Tested with Intel firmware : 0x20015 => Jean II */
219 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
220 break;
221 case FIRMWARE_TYPE_INTERSIL:
222 /* D-Link, Linksys, Adtron, ZoomAir, and many others...
223 * Samsung, Compaq 100/200 and Proxim are slightly
224 * different and less well tested */
225 /* D-Link MAC : 00:40:05:* */
226 /* Addtron MAC : 00:90:D1:* */
227 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
228 "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
229 sta_id.variant);
230
231 firmver = ((unsigned long)sta_id.major << 16) |
232 ((unsigned long)sta_id.minor << 8) | sta_id.variant;
233
234 priv->has_ibss = (firmver >= 0x000700); /* FIXME */
235 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
236 priv->has_pm = (firmver >= 0x000700);
237 priv->has_hostscan = (firmver >= 0x010301);
238
239 if (firmver >= 0x000800)
240 priv->ibss_port = 0;
241 else {
242 printk(KERN_NOTICE "%s: Intersil firmware earlier "
243 "than v0.8.x - several features not supported\n",
244 dev->name);
245 priv->ibss_port = 1;
246 }
247 break;
248 }
249 printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
250 priv->fw_name);
251
252 return 0;
253}
254
39int orinoco_get_bitratemode(int bitrate, int automatic) 255int orinoco_get_bitratemode(int bitrate, int automatic)
40{ 256{
41 int ratemode = -1; 257 int ratemode = -1;
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index dc3f23a9c1c7..f7845b855f76 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -23,6 +23,7 @@
23struct orinoco_private; 23struct orinoco_private;
24struct dev_addr_list; 24struct dev_addr_list;
25 25
26int determine_fw_capabilities(struct orinoco_private *priv);
26int orinoco_get_bitratemode(int bitrate, int automatic); 27int orinoco_get_bitratemode(int bitrate, int automatic);
27void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic); 28void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic);
28 29
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 345593c4accb..33326d6ef815 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -142,7 +142,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
142#define ORINOCO_MIN_MTU 256 142#define ORINOCO_MIN_MTU 256
143#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) 143#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
144 144
145#define SYMBOL_MAX_VER_LEN (14)
146#define MAX_IRQLOOPS_PER_IRQ 10 145#define MAX_IRQLOOPS_PER_IRQ 10
147#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of 146#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
148 * how many events the 147 * how many events the
@@ -2096,219 +2095,6 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
2096/* Initialization */ 2095/* Initialization */
2097/********************************************************************/ 2096/********************************************************************/
2098 2097
2099struct comp_id {
2100 u16 id, variant, major, minor;
2101} __attribute__ ((packed));
2102
2103static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
2104{
2105 if (nic_id->id < 0x8000)
2106 return FIRMWARE_TYPE_AGERE;
2107 else if (nic_id->id == 0x8000 && nic_id->major == 0)
2108 return FIRMWARE_TYPE_SYMBOL;
2109 else
2110 return FIRMWARE_TYPE_INTERSIL;
2111}
2112
2113/* Set priv->firmware type, determine firmware properties */
2114static int determine_firmware(struct net_device *dev)
2115{
2116 struct orinoco_private *priv = netdev_priv(dev);
2117 hermes_t *hw = &priv->hw;
2118 int err;
2119 struct comp_id nic_id, sta_id;
2120 unsigned int firmver;
2121 char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
2122
2123 /* Get the hardware version */
2124 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
2125 if (err) {
2126 printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
2127 dev->name, err);
2128 return err;
2129 }
2130
2131 le16_to_cpus(&nic_id.id);
2132 le16_to_cpus(&nic_id.variant);
2133 le16_to_cpus(&nic_id.major);
2134 le16_to_cpus(&nic_id.minor);
2135 printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
2136 dev->name, nic_id.id, nic_id.variant,
2137 nic_id.major, nic_id.minor);
2138
2139 priv->firmware_type = determine_firmware_type(&nic_id);
2140
2141 /* Get the firmware version */
2142 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
2143 if (err) {
2144 printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
2145 dev->name, err);
2146 return err;
2147 }
2148
2149 le16_to_cpus(&sta_id.id);
2150 le16_to_cpus(&sta_id.variant);
2151 le16_to_cpus(&sta_id.major);
2152 le16_to_cpus(&sta_id.minor);
2153 printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
2154 dev->name, sta_id.id, sta_id.variant,
2155 sta_id.major, sta_id.minor);
2156
2157 switch (sta_id.id) {
2158 case 0x15:
2159 printk(KERN_ERR "%s: Primary firmware is active\n",
2160 dev->name);
2161 return -ENODEV;
2162 case 0x14b:
2163 printk(KERN_ERR "%s: Tertiary firmware is active\n",
2164 dev->name);
2165 return -ENODEV;
2166 case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
2167 case 0x21: /* Symbol Spectrum24 Trilogy */
2168 break;
2169 default:
2170 printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
2171 dev->name);
2172 break;
2173 }
2174
2175 /* Default capabilities */
2176 priv->has_sensitivity = 1;
2177 priv->has_mwo = 0;
2178 priv->has_preamble = 0;
2179 priv->has_port3 = 1;
2180 priv->has_ibss = 1;
2181 priv->has_wep = 0;
2182 priv->has_big_wep = 0;
2183 priv->has_alt_txcntl = 0;
2184 priv->has_ext_scan = 0;
2185 priv->has_wpa = 0;
2186 priv->do_fw_download = 0;
2187
2188 /* Determine capabilities from the firmware version */
2189 switch (priv->firmware_type) {
2190 case FIRMWARE_TYPE_AGERE:
2191 /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
2192 ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
2193 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2194 "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
2195
2196 firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
2197
2198 priv->has_ibss = (firmver >= 0x60006);
2199 priv->has_wep = (firmver >= 0x40020);
2200 priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
2201 Gold cards from the others? */
2202 priv->has_mwo = (firmver >= 0x60000);
2203 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2204 priv->ibss_port = 1;
2205 priv->has_hostscan = (firmver >= 0x8000a);
2206 priv->do_fw_download = 1;
2207 priv->broken_monitor = (firmver >= 0x80000);
2208 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
2209 priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
2210 priv->has_wpa = (firmver >= 0x9002a);
2211 /* Tested with Agere firmware :
2212 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
2213 * Tested CableTron firmware : 4.32 => Anton */
2214 break;
2215 case FIRMWARE_TYPE_SYMBOL:
2216 /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
2217 /* Intel MAC : 00:02:B3:* */
2218 /* 3Com MAC : 00:50:DA:* */
2219 memset(tmp, 0, sizeof(tmp));
2220 /* Get the Symbol firmware version */
2221 err = hermes_read_ltv(hw, USER_BAP,
2222 HERMES_RID_SECONDARYVERSION_SYMBOL,
2223 SYMBOL_MAX_VER_LEN, NULL, &tmp);
2224 if (err) {
2225 printk(KERN_WARNING
2226 "%s: Error %d reading Symbol firmware info. "
2227 "Wildly guessing capabilities...\n",
2228 dev->name, err);
2229 firmver = 0;
2230 tmp[0] = '\0';
2231 } else {
2232 /* The firmware revision is a string, the format is
2233 * something like : "V2.20-01".
2234 * Quick and dirty parsing... - Jean II
2235 */
2236 firmver = ((tmp[1] - '0') << 16)
2237 | ((tmp[3] - '0') << 12)
2238 | ((tmp[4] - '0') << 8)
2239 | ((tmp[6] - '0') << 4)
2240 | (tmp[7] - '0');
2241
2242 tmp[SYMBOL_MAX_VER_LEN] = '\0';
2243 }
2244
2245 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2246 "Symbol %s", tmp);
2247
2248 priv->has_ibss = (firmver >= 0x20000);
2249 priv->has_wep = (firmver >= 0x15012);
2250 priv->has_big_wep = (firmver >= 0x20000);
2251 priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
2252 (firmver >= 0x29000 && firmver < 0x30000) ||
2253 firmver >= 0x31000;
2254 priv->has_preamble = (firmver >= 0x20000);
2255 priv->ibss_port = 4;
2256
2257 /* Symbol firmware is found on various cards, but
2258 * there has been no attempt to check firmware
2259 * download on non-spectrum_cs based cards.
2260 *
2261 * Given that the Agere firmware download works
2262 * differently, we should avoid doing a firmware
2263 * download with the Symbol algorithm on non-spectrum
2264 * cards.
2265 *
2266 * For now we can identify a spectrum_cs based card
2267 * because it has a firmware reset function.
2268 */
2269 priv->do_fw_download = (priv->stop_fw != NULL);
2270
2271 priv->broken_disableport = (firmver == 0x25013) ||
2272 (firmver >= 0x30000 && firmver <= 0x31000);
2273 priv->has_hostscan = (firmver >= 0x31001) ||
2274 (firmver >= 0x29057 && firmver < 0x30000);
2275 /* Tested with Intel firmware : 0x20015 => Jean II */
2276 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
2277 break;
2278 case FIRMWARE_TYPE_INTERSIL:
2279 /* D-Link, Linksys, Adtron, ZoomAir, and many others...
2280 * Samsung, Compaq 100/200 and Proxim are slightly
2281 * different and less well tested */
2282 /* D-Link MAC : 00:40:05:* */
2283 /* Addtron MAC : 00:90:D1:* */
2284 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2285 "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
2286 sta_id.variant);
2287
2288 firmver = ((unsigned long)sta_id.major << 16) |
2289 ((unsigned long)sta_id.minor << 8) | sta_id.variant;
2290
2291 priv->has_ibss = (firmver >= 0x000700); /* FIXME */
2292 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
2293 priv->has_pm = (firmver >= 0x000700);
2294 priv->has_hostscan = (firmver >= 0x010301);
2295
2296 if (firmver >= 0x000800)
2297 priv->ibss_port = 0;
2298 else {
2299 printk(KERN_NOTICE "%s: Intersil firmware earlier "
2300 "than v0.8.x - several features not supported\n",
2301 dev->name);
2302 priv->ibss_port = 1;
2303 }
2304 break;
2305 }
2306 printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
2307 priv->fw_name);
2308
2309 return 0;
2310}
2311
2312static int orinoco_init(struct net_device *dev) 2098static int orinoco_init(struct net_device *dev)
2313{ 2099{
2314 struct orinoco_private *priv = netdev_priv(dev); 2100 struct orinoco_private *priv = netdev_priv(dev);
@@ -2330,7 +2116,7 @@ static int orinoco_init(struct net_device *dev)
2330 goto out; 2116 goto out;
2331 } 2117 }
2332 2118
2333 err = determine_firmware(dev); 2119 err = determine_fw_capabilities(priv);
2334 if (err != 0) { 2120 if (err != 0) {
2335 printk(KERN_ERR "%s: Incompatible firmware, aborting\n", 2121 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
2336 dev->name); 2122 dev->name);
@@ -2347,7 +2133,7 @@ static int orinoco_init(struct net_device *dev)
2347 priv->do_fw_download = 0; 2133 priv->do_fw_download = 0;
2348 2134
2349 /* Check firmware version again */ 2135 /* Check firmware version again */
2350 err = determine_firmware(dev); 2136 err = determine_fw_capabilities(priv);
2351 if (err != 0) { 2137 if (err != 0) {
2352 printk(KERN_ERR "%s: Incompatible firmware, aborting\n", 2138 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
2353 dev->name); 2139 dev->name);