aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/hw.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/hw.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/hw.c')
-rw-r--r--drivers/net/wireless/orinoco/hw.c216
1 files changed, 216 insertions, 0 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;