aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/main.c
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2009-06-18 18:21:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:01:43 -0400
commita2d1a42a4b44c97fb83c5bf53af8cd6ab4c6c110 (patch)
tree549bf23b949ec4670ded86c5bdb5e5bdb7e9589c /drivers/net/wireless/orinoco/main.c
parent27bea66c22582853ad2e1de93d26c3016493818b (diff)
orinoco: Move firmware capability determination into hw.c
This is part of refactorring the initialisation code so that we can load the firmware before registerring with netdev. Signed-off-by: David Kilroy <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco/main.c')
-rw-r--r--drivers/net/wireless/orinoco/main.c218
1 files changed, 2 insertions, 216 deletions
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);