diff options
author | David Kilroy <kilroyd@googlemail.com> | 2009-06-18 18:21:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 15:01:43 -0400 |
commit | a2d1a42a4b44c97fb83c5bf53af8cd6ab4c6c110 (patch) | |
tree | 549bf23b949ec4670ded86c5bdb5e5bdb7e9589c /drivers/net/wireless/orinoco/hw.c | |
parent | 27bea66c22582853ad2e1de93d26c3016493818b (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.c | 216 |
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 */ | ||
42 | struct comp_id { | ||
43 | u16 id, variant, major, minor; | ||
44 | } __attribute__ ((packed)); | ||
45 | |||
46 | static 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 */ | ||
57 | int 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 | |||
39 | int orinoco_get_bitratemode(int bitrate, int automatic) | 255 | int orinoco_get_bitratemode(int bitrate, int automatic) |
40 | { | 256 | { |
41 | int ratemode = -1; | 257 | int ratemode = -1; |