diff options
author | David Kilroy <kilroyd@gmail.com> | 2008-08-21 18:27:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 19:28:05 -0400 |
commit | 3994d502017a2239e30152d1231843ad05d04a7b (patch) | |
tree | c4f15d1b95783d035d954173167ff08e65665461 /drivers/net/wireless/spectrum_cs.c | |
parent | 8f5ae73c5366128d3800cf9765507422bcf1ef96 (diff) |
orinoco: Invoke firmware download in main driver
Firmware download is enabled for Agere in orinoco_cs. Symbol firmware
download has been moved out of spectrum_cs into orinoco_cs. Firmware
download is not enabled for Intersil.
Symbol based firmware is restricted to only download on spectrum_cs
based cards.
The firmware names are hardcoded for each firmware type.
Signed-off-by: David Kilroy <kilroyd@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 159 |
1 files changed, 14 insertions, 145 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 2fb00183cd71..e368759d1d89 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/firmware.h> | ||
29 | #include <pcmcia/cs_types.h> | 28 | #include <pcmcia/cs_types.h> |
30 | #include <pcmcia/cs.h> | 29 | #include <pcmcia/cs.h> |
31 | #include <pcmcia/cistpl.h> | 30 | #include <pcmcia/cistpl.h> |
@@ -33,10 +32,6 @@ | |||
33 | #include <pcmcia/ds.h> | 32 | #include <pcmcia/ds.h> |
34 | 33 | ||
35 | #include "orinoco.h" | 34 | #include "orinoco.h" |
36 | #include "hermes_dld.h" | ||
37 | |||
38 | static const char primary_fw_name[] = "symbol_sp24t_prim_fw"; | ||
39 | static const char secondary_fw_name[] = "symbol_sp24t_sec_fw"; | ||
40 | 35 | ||
41 | /********************************************************************/ | 36 | /********************************************************************/ |
42 | /* Module stuff */ | 37 | /* Module stuff */ |
@@ -72,26 +67,11 @@ struct orinoco_pccard { | |||
72 | static int spectrum_cs_config(struct pcmcia_device *link); | 67 | static int spectrum_cs_config(struct pcmcia_device *link); |
73 | static void spectrum_cs_release(struct pcmcia_device *link); | 68 | static void spectrum_cs_release(struct pcmcia_device *link); |
74 | 69 | ||
75 | /********************************************************************/ | ||
76 | /* Firmware downloader */ | ||
77 | /********************************************************************/ | ||
78 | |||
79 | /* Position of PDA in the adapter memory */ | ||
80 | #define EEPROM_ADDR 0x3000 | ||
81 | #define EEPROM_LEN 0x200 | ||
82 | #define PDA_OFFSET 0x100 | ||
83 | |||
84 | #define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET) | ||
85 | #define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2) | ||
86 | |||
87 | /* Constants for the CISREG_CCSR register */ | 70 | /* Constants for the CISREG_CCSR register */ |
88 | #define HCR_RUN 0x07 /* run firmware after reset */ | 71 | #define HCR_RUN 0x07 /* run firmware after reset */ |
89 | #define HCR_IDLE 0x0E /* don't run firmware after reset */ | 72 | #define HCR_IDLE 0x0E /* don't run firmware after reset */ |
90 | #define HCR_MEM16 0x10 /* memory width bit, should be preserved */ | 73 | #define HCR_MEM16 0x10 /* memory width bit, should be preserved */ |
91 | 74 | ||
92 | /* End markers */ | ||
93 | #define TEXT_END 0x1A /* End of text header */ | ||
94 | |||
95 | 75 | ||
96 | #define CS_CHECK(fn, ret) \ | 76 | #define CS_CHECK(fn, ret) \ |
97 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 77 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
@@ -158,142 +138,29 @@ spectrum_reset(struct pcmcia_device *link, int idle) | |||
158 | return -ENODEV; | 138 | return -ENODEV; |
159 | } | 139 | } |
160 | 140 | ||
141 | /********************************************************************/ | ||
142 | /* Device methods */ | ||
143 | /********************************************************************/ | ||
161 | 144 | ||
162 | /* | ||
163 | * Process a firmware image - stop the card, load the firmware, reset | ||
164 | * the card and make sure it responds. For the secondary firmware take | ||
165 | * care of the PDA - read it and then write it on top of the firmware. | ||
166 | */ | ||
167 | static int | 145 | static int |
168 | spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, | 146 | spectrum_cs_hard_reset(struct orinoco_private *priv) |
169 | const unsigned char *image, const unsigned char *end, | ||
170 | int secondary) | ||
171 | { | 147 | { |
172 | int ret; | 148 | struct orinoco_pccard *card = priv->card; |
173 | const unsigned char *ptr; | 149 | struct pcmcia_device *link = card->p_dev; |
174 | const unsigned char *first_block; | ||
175 | |||
176 | /* Plug Data Area (PDA) */ | ||
177 | __le16 pda[PDA_WORDS]; | ||
178 | |||
179 | /* Binary block begins after the 0x1A marker */ | ||
180 | ptr = image; | ||
181 | while (*ptr++ != TEXT_END); | ||
182 | first_block = ptr; | ||
183 | |||
184 | /* Read the PDA from EEPROM */ | ||
185 | if (secondary) { | ||
186 | ret = hermes_read_pda(hw, pda, PDA_ADDR, sizeof(pda), 1); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | /* Stop the firmware, so that it can be safely rewritten */ | ||
192 | ret = spectrum_reset(link, 1); | ||
193 | if (ret) | ||
194 | return ret; | ||
195 | |||
196 | /* Program the adapter with new firmware */ | ||
197 | ret = hermes_program(hw, first_block, end); | ||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | /* Write the PDA to the adapter */ | ||
202 | if (secondary) { | ||
203 | size_t len = hermes_blocks_length(first_block); | ||
204 | ptr = first_block + len; | ||
205 | ret = hermes_apply_pda(hw, ptr, pda); | ||
206 | if (ret) | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* Run the firmware */ | ||
211 | ret = spectrum_reset(link, 0); | ||
212 | if (ret) | ||
213 | return ret; | ||
214 | |||
215 | /* Reset hermes chip and make sure it responds */ | ||
216 | ret = hermes_init(hw); | ||
217 | |||
218 | /* hermes_reset() should return 0 with the secondary firmware */ | ||
219 | if (secondary && ret != 0) | ||
220 | return -ENODEV; | ||
221 | 150 | ||
222 | /* And this should work with any firmware */ | 151 | /* Soft reset using COR and HCR */ |
223 | if (!hermes_present(hw)) | 152 | spectrum_reset(link, 0); |
224 | return -ENODEV; | ||
225 | 153 | ||
226 | return 0; | 154 | return 0; |
227 | } | 155 | } |
228 | 156 | ||
229 | |||
230 | /* | ||
231 | * Download the firmware into the card, this also does a PCMCIA soft | ||
232 | * reset on the card, to make sure it's in a sane state. | ||
233 | */ | ||
234 | static int | 157 | static int |
235 | spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) | 158 | spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle) |
236 | { | ||
237 | int ret; | ||
238 | const struct firmware *fw_entry; | ||
239 | |||
240 | if (request_firmware(&fw_entry, primary_fw_name, | ||
241 | &handle_to_dev(link)) != 0) { | ||
242 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | ||
243 | primary_fw_name); | ||
244 | return -ENOENT; | ||
245 | } | ||
246 | |||
247 | /* Load primary firmware */ | ||
248 | ret = spectrum_dl_image(hw, link, fw_entry->data, | ||
249 | fw_entry->data + fw_entry->size, 0); | ||
250 | release_firmware(fw_entry); | ||
251 | if (ret) { | ||
252 | printk(KERN_ERR PFX "Primary firmware download failed\n"); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | if (request_firmware(&fw_entry, secondary_fw_name, | ||
257 | &handle_to_dev(link)) != 0) { | ||
258 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | ||
259 | secondary_fw_name); | ||
260 | return -ENOENT; | ||
261 | } | ||
262 | |||
263 | /* Load secondary firmware */ | ||
264 | ret = spectrum_dl_image(hw, link, fw_entry->data, | ||
265 | fw_entry->data + fw_entry->size, 1); | ||
266 | release_firmware(fw_entry); | ||
267 | if (ret) { | ||
268 | printk(KERN_ERR PFX "Secondary firmware download failed\n"); | ||
269 | } | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | /********************************************************************/ | ||
275 | /* Device methods */ | ||
276 | /********************************************************************/ | ||
277 | |||
278 | static int | ||
279 | spectrum_cs_hard_reset(struct orinoco_private *priv) | ||
280 | { | 159 | { |
281 | struct orinoco_pccard *card = priv->card; | 160 | struct orinoco_pccard *card = priv->card; |
282 | struct pcmcia_device *link = card->p_dev; | 161 | struct pcmcia_device *link = card->p_dev; |
283 | int err; | ||
284 | 162 | ||
285 | if (!hermes_present(&priv->hw)) { | 163 | return spectrum_reset(link, idle); |
286 | /* The firmware needs to be reloaded */ | ||
287 | if (spectrum_dl_firmware(&priv->hw, link) != 0) { | ||
288 | printk(KERN_ERR PFX "Firmware download failed\n"); | ||
289 | err = -ENODEV; | ||
290 | } | ||
291 | } else { | ||
292 | /* Soft reset using COR and HCR */ | ||
293 | spectrum_reset(link, 0); | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | } | 164 | } |
298 | 165 | ||
299 | /********************************************************************/ | 166 | /********************************************************************/ |
@@ -315,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link) | |||
315 | struct orinoco_private *priv; | 182 | struct orinoco_private *priv; |
316 | struct orinoco_pccard *card; | 183 | struct orinoco_pccard *card; |
317 | 184 | ||
318 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); | 185 | dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), |
186 | spectrum_cs_hard_reset, | ||
187 | spectrum_cs_stop_firmware); | ||
319 | if (! dev) | 188 | if (! dev) |
320 | return -ENOMEM; | 189 | return -ENOMEM; |
321 | priv = netdev_priv(dev); | 190 | priv = netdev_priv(dev); |
@@ -517,7 +386,7 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
517 | dev->irq = link->irq.AssignedIRQ; | 386 | dev->irq = link->irq.AssignedIRQ; |
518 | card->node.major = card->node.minor = 0; | 387 | card->node.major = card->node.minor = 0; |
519 | 388 | ||
520 | /* Reset card and download firmware */ | 389 | /* Reset card */ |
521 | if (spectrum_cs_hard_reset(priv) != 0) { | 390 | if (spectrum_cs_hard_reset(priv) != 0) { |
522 | goto failed; | 391 | goto failed; |
523 | } | 392 | } |