diff options
-rw-r--r-- | drivers/net/wireless/hermes_dld.c | 209 | ||||
-rw-r--r-- | drivers/net/wireless/hermes_dld.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 23 |
3 files changed, 182 insertions, 72 deletions
diff --git a/drivers/net/wireless/hermes_dld.c b/drivers/net/wireless/hermes_dld.c index 9a8ef3040d59..22ae79dae41e 100644 --- a/drivers/net/wireless/hermes_dld.c +++ b/drivers/net/wireless/hermes_dld.c | |||
@@ -64,14 +64,34 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
64 | #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ | 64 | #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ |
65 | #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ | 65 | #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ |
66 | #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ | 66 | #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ |
67 | #define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */ | ||
67 | 68 | ||
68 | #define HERMES_AUX_PW0 0xFE01 | 69 | #define HERMES_AUX_PW0 0xFE01 |
69 | #define HERMES_AUX_PW1 0xDC23 | 70 | #define HERMES_AUX_PW1 0xDC23 |
70 | #define HERMES_AUX_PW2 0xBA45 | 71 | #define HERMES_AUX_PW2 0xBA45 |
71 | 72 | ||
72 | /* End markers */ | 73 | /* End markers used in dblocks */ |
73 | #define PDI_END 0x00000000 /* End of PDA */ | 74 | #define PDI_END 0x00000000 /* End of PDA */ |
74 | #define BLOCK_END 0xFFFFFFFF /* Last image block */ | 75 | #define BLOCK_END 0xFFFFFFFF /* Last image block */ |
76 | #define TEXT_END 0x1A /* End of text header */ | ||
77 | |||
78 | /* | ||
79 | * PDA == Production Data Area | ||
80 | * | ||
81 | * In principle, the max. size of the PDA is is 4096 words. Currently, | ||
82 | * however, only about 500 bytes of this area are used. | ||
83 | * | ||
84 | * Some USB implementations can't handle sizes in excess of 1016. Note | ||
85 | * that PDA is not actually used in those USB environments, but may be | ||
86 | * retrieved by common code. | ||
87 | */ | ||
88 | #define MAX_PDA_SIZE 1000 | ||
89 | |||
90 | /* Limit the amout we try to download in a single shot. | ||
91 | * Size is in bytes. | ||
92 | */ | ||
93 | #define MAX_DL_SIZE 1024 | ||
94 | #define LIMIT_PROGRAM_SIZE 0 | ||
75 | 95 | ||
76 | /* | 96 | /* |
77 | * The following structures have little-endian fields denoted by | 97 | * The following structures have little-endian fields denoted by |
@@ -112,7 +132,8 @@ struct pdi { | |||
112 | char data[0]; /* plug data */ | 132 | char data[0]; /* plug data */ |
113 | } __attribute__ ((packed)); | 133 | } __attribute__ ((packed)); |
114 | 134 | ||
115 | /* Functions for access to little-endian data */ | 135 | /*** FW data block access functions ***/ |
136 | |||
116 | static inline u32 | 137 | static inline u32 |
117 | dblock_addr(const struct dblock *blk) | 138 | dblock_addr(const struct dblock *blk) |
118 | { | 139 | { |
@@ -125,6 +146,8 @@ dblock_len(const struct dblock *blk) | |||
125 | return le16_to_cpu(blk->len); | 146 | return le16_to_cpu(blk->len); |
126 | } | 147 | } |
127 | 148 | ||
149 | /*** PDR Access functions ***/ | ||
150 | |||
128 | static inline u32 | 151 | static inline u32 |
129 | pdr_id(const struct pdr *pdr) | 152 | pdr_id(const struct pdr *pdr) |
130 | { | 153 | { |
@@ -143,6 +166,8 @@ pdr_len(const struct pdr *pdr) | |||
143 | return le32_to_cpu(pdr->len); | 166 | return le32_to_cpu(pdr->len); |
144 | } | 167 | } |
145 | 168 | ||
169 | /*** PDI Access functions ***/ | ||
170 | |||
146 | static inline u32 | 171 | static inline u32 |
147 | pdi_id(const struct pdi *pdi) | 172 | pdi_id(const struct pdi *pdi) |
148 | { | 173 | { |
@@ -156,49 +181,55 @@ pdi_len(const struct pdi *pdi) | |||
156 | return 2 * (le16_to_cpu(pdi->len) - 1); | 181 | return 2 * (le16_to_cpu(pdi->len) - 1); |
157 | } | 182 | } |
158 | 183 | ||
159 | /* Set address of the auxiliary port */ | 184 | /*** Hermes AUX control ***/ |
185 | |||
160 | static inline void | 186 | static inline void |
161 | spectrum_aux_setaddr(hermes_t *hw, u32 addr) | 187 | hermes_aux_setaddr(hermes_t *hw, u32 addr) |
162 | { | 188 | { |
163 | hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); | 189 | hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); |
164 | hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); | 190 | hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); |
165 | } | 191 | } |
166 | 192 | ||
167 | /* Open access to the auxiliary port */ | 193 | static inline int |
168 | static int | 194 | hermes_aux_control(hermes_t *hw, int enabled) |
169 | spectrum_aux_open(hermes_t *hw) | ||
170 | { | 195 | { |
196 | int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; | ||
197 | int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; | ||
171 | int i; | 198 | int i; |
172 | 199 | ||
173 | /* Already open? */ | 200 | /* Already open? */ |
174 | if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED) | 201 | if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) |
175 | return 0; | 202 | return 0; |
176 | 203 | ||
177 | hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); | 204 | hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); |
178 | hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); | 205 | hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); |
179 | hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); | 206 | hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); |
180 | hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE); | 207 | hermes_write_reg(hw, HERMES_CONTROL, action); |
181 | 208 | ||
182 | for (i = 0; i < 20; i++) { | 209 | for (i = 0; i < 20; i++) { |
183 | udelay(10); | 210 | udelay(10); |
184 | if (hermes_read_reg(hw, HERMES_CONTROL) == | 211 | if (hermes_read_reg(hw, HERMES_CONTROL) == |
185 | HERMES_AUX_ENABLED) | 212 | desired_state) |
186 | return 0; | 213 | return 0; |
187 | } | 214 | } |
188 | 215 | ||
189 | return -EBUSY; | 216 | return -EBUSY; |
190 | } | 217 | } |
191 | 218 | ||
219 | /*** Plug Data Functions ***/ | ||
220 | |||
192 | /* | 221 | /* |
193 | * Scan PDR for the record with the specified RECORD_ID. | 222 | * Scan PDR for the record with the specified RECORD_ID. |
194 | * If it's not found, return NULL. | 223 | * If it's not found, return NULL. |
195 | */ | 224 | */ |
196 | static struct pdr * | 225 | static struct pdr * |
197 | spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) | 226 | hermes_find_pdr(struct pdr *first_pdr, u32 record_id) |
198 | { | 227 | { |
199 | struct pdr *pdr = first_pdr; | 228 | struct pdr *pdr = first_pdr; |
229 | void *end = (void *)first_pdr + MAX_PDA_SIZE; | ||
200 | 230 | ||
201 | while (pdr_id(pdr) != PDI_END) { | 231 | while (((void *)pdr < end) && |
232 | (pdr_id(pdr) != PDI_END)) { | ||
202 | /* | 233 | /* |
203 | * PDR area is currently not terminated by PDI_END. | 234 | * PDR area is currently not terminated by PDI_END. |
204 | * It's followed by CRC records, which have the type | 235 | * It's followed by CRC records, which have the type |
@@ -218,12 +249,12 @@ spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) | |||
218 | 249 | ||
219 | /* Process one Plug Data Item - find corresponding PDR and plug it */ | 250 | /* Process one Plug Data Item - find corresponding PDR and plug it */ |
220 | static int | 251 | static int |
221 | spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) | 252 | hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi) |
222 | { | 253 | { |
223 | struct pdr *pdr; | 254 | struct pdr *pdr; |
224 | 255 | ||
225 | /* Find the PDI corresponding to this PDR */ | 256 | /* Find the PDR corresponding to this PDI */ |
226 | pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi)); | 257 | pdr = hermes_find_pdr(first_pdr, pdi_id(pdi)); |
227 | 258 | ||
228 | /* No match is found, safe to ignore */ | 259 | /* No match is found, safe to ignore */ |
229 | if (!pdr) | 260 | if (!pdr) |
@@ -234,96 +265,172 @@ spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) | |||
234 | return -EINVAL; | 265 | return -EINVAL; |
235 | 266 | ||
236 | /* do the actual plugging */ | 267 | /* do the actual plugging */ |
237 | spectrum_aux_setaddr(hw, pdr_addr(pdr)); | 268 | hermes_aux_setaddr(hw, pdr_addr(pdr)); |
238 | hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); | 269 | hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); |
239 | 270 | ||
240 | return 0; | 271 | return 0; |
241 | } | 272 | } |
242 | 273 | ||
243 | /* Read PDA from the adapter */ | 274 | /* Read PDA from the adapter */ |
244 | int | 275 | int hermes_read_pda(hermes_t *hw, |
245 | spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len) | 276 | __le16 *pda, |
277 | u32 pda_addr, | ||
278 | u16 pda_len, | ||
279 | int use_eeprom) /* can we get this into hw? */ | ||
246 | { | 280 | { |
247 | int ret; | 281 | int ret; |
248 | int pda_size; | 282 | u16 pda_size; |
283 | u16 data_len = pda_len; | ||
284 | __le16 *data = pda; | ||
249 | 285 | ||
250 | /* Issue command to read EEPROM */ | 286 | if (use_eeprom) { |
251 | ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); | 287 | /* PDA of spectrum symbol is in eeprom */ |
252 | if (ret) | 288 | |
253 | return ret; | 289 | /* Issue command to read EEPROM */ |
290 | ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); | ||
291 | if (ret) | ||
292 | return ret; | ||
293 | } | ||
254 | 294 | ||
255 | /* Open auxiliary port */ | 295 | /* Open auxiliary port */ |
256 | ret = spectrum_aux_open(hw); | 296 | ret = hermes_aux_control(hw, 1); |
297 | printk(KERN_DEBUG PFX "AUX enable returned %d\n", ret); | ||
257 | if (ret) | 298 | if (ret) |
258 | return ret; | 299 | return ret; |
259 | 300 | ||
260 | /* read PDA from EEPROM */ | 301 | /* read PDA from EEPROM */ |
261 | spectrum_aux_setaddr(hw, PDA_ADDR); | 302 | hermes_aux_setaddr(hw, pda_addr); |
262 | hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2); | 303 | hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); |
304 | |||
305 | /* Close aux port */ | ||
306 | ret = hermes_aux_control(hw, 0); | ||
307 | printk(KERN_DEBUG PFX "AUX disable returned %d\n", ret); | ||
263 | 308 | ||
264 | /* Check PDA length */ | 309 | /* Check PDA length */ |
265 | pda_size = le16_to_cpu(pda[0]); | 310 | pda_size = le16_to_cpu(pda[0]); |
311 | printk(KERN_DEBUG PFX "Actual PDA length %d, Max allowed %d\n", | ||
312 | pda_size, pda_len); | ||
266 | if (pda_size > pda_len) | 313 | if (pda_size > pda_len) |
267 | return -EINVAL; | 314 | return -EINVAL; |
268 | 315 | ||
269 | return 0; | 316 | return 0; |
270 | } | 317 | } |
271 | EXPORT_SYMBOL(spectrum_read_pda); | 318 | EXPORT_SYMBOL(hermes_read_pda); |
272 | 319 | ||
273 | /* Parse PDA and write the records into the adapter */ | 320 | /* Parse PDA and write the records into the adapter |
274 | int | 321 | * |
275 | spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, | 322 | * Attempt to write every records that is in the specified pda |
276 | __le16 *pda) | 323 | * which also has a valid production data record for the firmware. |
324 | */ | ||
325 | int hermes_apply_pda(hermes_t *hw, | ||
326 | const char *first_pdr, | ||
327 | const __le16 *pda) | ||
277 | { | 328 | { |
278 | int ret; | 329 | int ret; |
279 | struct pdi *pdi; | 330 | const struct pdi *pdi; |
280 | struct pdr *first_pdr; | 331 | struct pdr *pdr; |
281 | const struct dblock *blk = first_block; | ||
282 | |||
283 | /* Skip all blocks to locate Plug Data References */ | ||
284 | while (dblock_addr(blk) != BLOCK_END) | ||
285 | blk = (struct dblock *) &blk->data[dblock_len(blk)]; | ||
286 | 332 | ||
287 | first_pdr = (struct pdr *) blk; | 333 | pdr = (struct pdr *) first_pdr; |
288 | 334 | ||
289 | /* Go through every PDI and plug them into the adapter */ | 335 | /* Go through every PDI and plug them into the adapter */ |
290 | pdi = (struct pdi *) (pda + 2); | 336 | pdi = (const struct pdi *) (pda + 2); |
291 | while (pdi_id(pdi) != PDI_END) { | 337 | while (pdi_id(pdi) != PDI_END) { |
292 | ret = spectrum_plug_pdi(hw, first_pdr, pdi); | 338 | ret = hermes_plug_pdi(hw, pdr, pdi); |
293 | if (ret) | 339 | if (ret) |
294 | return ret; | 340 | return ret; |
295 | 341 | ||
296 | /* Increment to the next PDI */ | 342 | /* Increment to the next PDI */ |
297 | pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; | 343 | pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)]; |
298 | } | 344 | } |
299 | return 0; | 345 | return 0; |
300 | } | 346 | } |
301 | EXPORT_SYMBOL(spectrum_apply_pda); | 347 | EXPORT_SYMBOL(hermes_apply_pda); |
348 | |||
349 | /* Identify the total number of bytes in all blocks | ||
350 | * including the header data. | ||
351 | */ | ||
352 | size_t | ||
353 | hermes_blocks_length(const char *first_block) | ||
354 | { | ||
355 | const struct dblock *blk = (const struct dblock *) first_block; | ||
356 | int total_len = 0; | ||
357 | int len; | ||
358 | |||
359 | /* Skip all blocks to locate Plug Data References | ||
360 | * (Spectrum CS) */ | ||
361 | while (dblock_addr(blk) != BLOCK_END) { | ||
362 | len = dblock_len(blk); | ||
363 | total_len += sizeof(*blk) + len; | ||
364 | blk = (struct dblock *) &blk->data[len]; | ||
365 | } | ||
366 | |||
367 | return total_len; | ||
368 | } | ||
369 | EXPORT_SYMBOL(hermes_blocks_length); | ||
370 | |||
371 | /*** Hermes programming ***/ | ||
302 | 372 | ||
303 | /* Load firmware blocks into the adapter */ | 373 | /* Program the data blocks */ |
304 | int | 374 | int hermes_program(hermes_t *hw, const char *first_block, const char *end) |
305 | spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) | ||
306 | { | 375 | { |
307 | const struct dblock *blk; | 376 | const struct dblock *blk; |
308 | u32 blkaddr; | 377 | u32 blkaddr; |
309 | u32 blklen; | 378 | u32 blklen; |
379 | #if LIMIT_PROGRAM_SIZE | ||
380 | u32 addr; | ||
381 | u32 len; | ||
382 | #endif | ||
383 | |||
384 | blk = (const struct dblock *) first_block; | ||
385 | |||
386 | if ((const char *) blk > (end - sizeof(*blk))) | ||
387 | return -EIO; | ||
310 | 388 | ||
311 | blk = first_block; | ||
312 | blkaddr = dblock_addr(blk); | 389 | blkaddr = dblock_addr(blk); |
313 | blklen = dblock_len(blk); | 390 | blklen = dblock_len(blk); |
314 | 391 | ||
315 | while (dblock_addr(blk) != BLOCK_END) { | 392 | while ((blkaddr != BLOCK_END) && |
316 | spectrum_aux_setaddr(hw, blkaddr); | 393 | (((const char *) blk + blklen) <= end)) { |
394 | printk(KERN_DEBUG PFX | ||
395 | "Programming block of length %d to address 0x%08x\n", | ||
396 | blklen, blkaddr); | ||
397 | |||
398 | #if !LIMIT_PROGRAM_SIZE | ||
399 | /* wl_lkm driver splits this into writes of 2000 bytes */ | ||
400 | hermes_aux_setaddr(hw, blkaddr); | ||
317 | hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, | 401 | hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, |
318 | blklen); | 402 | blklen); |
403 | #else | ||
404 | len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE; | ||
405 | addr = blkaddr; | ||
406 | |||
407 | while (addr < (blkaddr + blklen)) { | ||
408 | printk(KERN_DEBUG PFX | ||
409 | "Programming subblock of length %d " | ||
410 | "to address 0x%08x. Data @ %p\n", | ||
411 | len, addr, &blk->data[addr - blkaddr]); | ||
412 | |||
413 | hermes_aux_setaddr(hw, addr); | ||
414 | hermes_write_bytes(hw, HERMES_AUXDATA, | ||
415 | &blk->data[addr - blkaddr], | ||
416 | len); | ||
417 | |||
418 | addr += len; | ||
419 | len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ? | ||
420 | (blkaddr + blklen - addr) : MAX_DL_SIZE; | ||
421 | } | ||
422 | #endif | ||
423 | blk = (const struct dblock *) &blk->data[blklen]; | ||
424 | |||
425 | if ((const char *) blk > (end - sizeof(*blk))) | ||
426 | return -EIO; | ||
319 | 427 | ||
320 | blk = (struct dblock *) &blk->data[blklen]; | ||
321 | blkaddr = dblock_addr(blk); | 428 | blkaddr = dblock_addr(blk); |
322 | blklen = dblock_len(blk); | 429 | blklen = dblock_len(blk); |
323 | } | 430 | } |
324 | return 0; | 431 | return 0; |
325 | } | 432 | } |
326 | EXPORT_SYMBOL(spectrum_load_blocks); | 433 | EXPORT_SYMBOL(hermes_program); |
327 | 434 | ||
328 | static int __init init_hermes_dld(void) | 435 | static int __init init_hermes_dld(void) |
329 | { | 436 | { |
diff --git a/drivers/net/wireless/hermes_dld.h b/drivers/net/wireless/hermes_dld.h index 2c8892ac635b..af75c030b11b 100644 --- a/drivers/net/wireless/hermes_dld.h +++ b/drivers/net/wireless/hermes_dld.h | |||
@@ -27,19 +27,17 @@ | |||
27 | 27 | ||
28 | #include "hermes.h" | 28 | #include "hermes.h" |
29 | 29 | ||
30 | /* Position of PDA in the adapter memory */ | 30 | int hermes_program(hermes_t *hw, const char *first_block, const char *end); |
31 | #define EEPROM_ADDR 0x3000 | ||
32 | #define EEPROM_LEN 0x200 | ||
33 | #define PDA_OFFSET 0x100 | ||
34 | 31 | ||
35 | #define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET) | 32 | int hermes_read_pda(hermes_t *hw, |
36 | #define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2) | 33 | __le16 *pda, |
34 | u32 pda_addr, | ||
35 | u16 pda_len, | ||
36 | int use_eeprom); | ||
37 | int hermes_apply_pda(hermes_t *hw, | ||
38 | const char *first_pdr, | ||
39 | const __le16 *pda); | ||
37 | 40 | ||
38 | struct dblock; | 41 | size_t hermes_blocks_length(const char *first_block); |
39 | |||
40 | int spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len); | ||
41 | int spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, | ||
42 | __le16 *pda); | ||
43 | int spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block); | ||
44 | 42 | ||
45 | #endif /* _HERMES_DLD_H */ | 43 | #endif /* _HERMES_DLD_H */ |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 579873d0e8c9..2fb00183cd71 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -166,11 +166,12 @@ spectrum_reset(struct pcmcia_device *link, int idle) | |||
166 | */ | 166 | */ |
167 | static int | 167 | static int |
168 | spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, | 168 | spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, |
169 | const unsigned char *image, int secondary) | 169 | const unsigned char *image, const unsigned char *end, |
170 | int secondary) | ||
170 | { | 171 | { |
171 | int ret; | 172 | int ret; |
172 | const unsigned char *ptr; | 173 | const unsigned char *ptr; |
173 | const struct dblock *first_block; | 174 | const unsigned char *first_block; |
174 | 175 | ||
175 | /* Plug Data Area (PDA) */ | 176 | /* Plug Data Area (PDA) */ |
176 | __le16 pda[PDA_WORDS]; | 177 | __le16 pda[PDA_WORDS]; |
@@ -178,11 +179,11 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, | |||
178 | /* Binary block begins after the 0x1A marker */ | 179 | /* Binary block begins after the 0x1A marker */ |
179 | ptr = image; | 180 | ptr = image; |
180 | while (*ptr++ != TEXT_END); | 181 | while (*ptr++ != TEXT_END); |
181 | first_block = (const struct dblock *) ptr; | 182 | first_block = ptr; |
182 | 183 | ||
183 | /* Read the PDA */ | 184 | /* Read the PDA from EEPROM */ |
184 | if (secondary) { | 185 | if (secondary) { |
185 | ret = spectrum_read_pda(hw, pda, sizeof(pda)); | 186 | ret = hermes_read_pda(hw, pda, PDA_ADDR, sizeof(pda), 1); |
186 | if (ret) | 187 | if (ret) |
187 | return ret; | 188 | return ret; |
188 | } | 189 | } |
@@ -193,13 +194,15 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, | |||
193 | return ret; | 194 | return ret; |
194 | 195 | ||
195 | /* Program the adapter with new firmware */ | 196 | /* Program the adapter with new firmware */ |
196 | ret = spectrum_load_blocks(hw, first_block); | 197 | ret = hermes_program(hw, first_block, end); |
197 | if (ret) | 198 | if (ret) |
198 | return ret; | 199 | return ret; |
199 | 200 | ||
200 | /* Write the PDA to the adapter */ | 201 | /* Write the PDA to the adapter */ |
201 | if (secondary) { | 202 | if (secondary) { |
202 | ret = spectrum_apply_pda(hw, first_block, pda); | 203 | size_t len = hermes_blocks_length(first_block); |
204 | ptr = first_block + len; | ||
205 | ret = hermes_apply_pda(hw, ptr, pda); | ||
203 | if (ret) | 206 | if (ret) |
204 | return ret; | 207 | return ret; |
205 | } | 208 | } |
@@ -242,7 +245,8 @@ spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) | |||
242 | } | 245 | } |
243 | 246 | ||
244 | /* Load primary firmware */ | 247 | /* Load primary firmware */ |
245 | ret = spectrum_dl_image(hw, link, fw_entry->data, 0); | 248 | ret = spectrum_dl_image(hw, link, fw_entry->data, |
249 | fw_entry->data + fw_entry->size, 0); | ||
246 | release_firmware(fw_entry); | 250 | release_firmware(fw_entry); |
247 | if (ret) { | 251 | if (ret) { |
248 | printk(KERN_ERR PFX "Primary firmware download failed\n"); | 252 | printk(KERN_ERR PFX "Primary firmware download failed\n"); |
@@ -257,7 +261,8 @@ spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) | |||
257 | } | 261 | } |
258 | 262 | ||
259 | /* Load secondary firmware */ | 263 | /* Load secondary firmware */ |
260 | ret = spectrum_dl_image(hw, link, fw_entry->data, 1); | 264 | ret = spectrum_dl_image(hw, link, fw_entry->data, |
265 | fw_entry->data + fw_entry->size, 1); | ||
261 | release_firmware(fw_entry); | 266 | release_firmware(fw_entry); |
262 | if (ret) { | 267 | if (ret) { |
263 | printk(KERN_ERR PFX "Secondary firmware download failed\n"); | 268 | printk(KERN_ERR PFX "Secondary firmware download failed\n"); |