]> git.ipfire.org Git - people/arne_f/kernel.git/blame - drivers/net/wireless/intersil/hostap/hostap_download.c
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[people/arne_f/kernel.git] / drivers / net / wireless / intersil / hostap / hostap_download.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
ff1d2767
JM
2static int prism2_enable_aux_port(struct net_device *dev, int enable)
3{
4 u16 val, reg;
5 int i, tries;
6 unsigned long flags;
7 struct hostap_interface *iface;
8 local_info_t *local;
9
10 iface = netdev_priv(dev);
11 local = iface->local;
12
13 if (local->no_pri) {
14 if (enable) {
15 PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
16 "port is already enabled\n", dev->name);
17 }
18 return 0;
19 }
20
21 spin_lock_irqsave(&local->cmdlock, flags);
22
23 /* wait until busy bit is clear */
24 tries = HFA384X_CMD_BUSY_TIMEOUT;
25 while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
26 tries--;
27 udelay(1);
28 }
29 if (tries == 0) {
30 reg = HFA384X_INW(HFA384X_CMD_OFF);
31 spin_unlock_irqrestore(&local->cmdlock, flags);
32 printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
33 dev->name, reg);
34 return -ETIMEDOUT;
35 }
36
37 val = HFA384X_INW(HFA384X_CONTROL_OFF);
38
39 if (enable) {
40 HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
41 HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
42 HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
43
44 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
45 printk("prism2_enable_aux_port: was not disabled!?\n");
46 val &= ~HFA384X_AUX_PORT_MASK;
47 val |= HFA384X_AUX_PORT_ENABLE;
48 } else {
49 HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
50 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
51 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
52
53 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
54 printk("prism2_enable_aux_port: was not enabled!?\n");
55 val &= ~HFA384X_AUX_PORT_MASK;
56 val |= HFA384X_AUX_PORT_DISABLE;
57 }
58 HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
59
60 udelay(5);
61
62 i = 10000;
63 while (i > 0) {
64 val = HFA384X_INW(HFA384X_CONTROL_OFF);
65 val &= HFA384X_AUX_PORT_MASK;
66
67 if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
68 (!enable && val == HFA384X_AUX_PORT_DISABLED))
69 break;
70
71 udelay(10);
72 i--;
73 }
74
75 spin_unlock_irqrestore(&local->cmdlock, flags);
76
77 if (i == 0) {
78 printk("prism2_enable_aux_port(%d) timed out\n",
79 enable);
80 return -ETIMEDOUT;
81 }
82
83 return 0;
84}
85
86
87static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
88 void *buf)
89{
90 u16 page, offset;
91 if (addr & 1 || len & 1)
92 return -1;
93
94 page = addr >> 7;
95 offset = addr & 0x7f;
96
97 HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
98 HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
99
100 udelay(5);
101
102#ifdef PRISM2_PCI
103 {
8a9faf3c 104 __le16 *pos = (__le16 *) buf;
ff1d2767
JM
105 while (len > 0) {
106 *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
107 len -= 2;
108 }
109 }
110#else /* PRISM2_PCI */
111 HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
112#endif /* PRISM2_PCI */
113
114 return 0;
115}
116
117
118static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
119 void *buf)
120{
121 u16 page, offset;
122 if (addr & 1 || len & 1)
123 return -1;
124
125 page = addr >> 7;
126 offset = addr & 0x7f;
127
128 HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
129 HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
130
131 udelay(5);
132
133#ifdef PRISM2_PCI
134 {
8a9faf3c 135 __le16 *pos = (__le16 *) buf;
ff1d2767
JM
136 while (len > 0) {
137 HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
138 len -= 2;
139 }
140 }
141#else /* PRISM2_PCI */
142 HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
143#endif /* PRISM2_PCI */
144
145 return 0;
146}
147
148
149static int prism2_pda_ok(u8 *buf)
150{
8a9faf3c 151 __le16 *pda = (__le16 *) buf;
ff1d2767
JM
152 int pos;
153 u16 len, pdr;
154
155 if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
156 buf[3] == 0x00)
157 return 0;
158
159 pos = 0;
160 while (pos + 1 < PRISM2_PDA_SIZE / 2) {
161 len = le16_to_cpu(pda[pos]);
162 pdr = le16_to_cpu(pda[pos + 1]);
163 if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
164 return 0;
165
166 if (pdr == 0x0000 && len == 2) {
167 /* PDA end found */
168 return 1;
169 }
170
171 pos += len + 1;
172 }
173
174 return 0;
175}
176
177
6bbefe86 178#define prism2_download_aux_dump_npages 65536
ff1d2767 179
6bbefe86
DH
180struct prism2_download_aux_dump {
181 local_info_t *local;
182 u16 page[0x80];
183};
184
185static int prism2_download_aux_dump_proc_show(struct seq_file *m, void *v)
186{
187 struct prism2_download_aux_dump *ctx = m->private;
ff1d2767 188
6bbefe86
DH
189 hfa384x_from_aux(ctx->local->dev, (unsigned long)v - 1, 0x80, ctx->page);
190 seq_write(m, ctx->page, 0x80);
ff1d2767
JM
191 return 0;
192}
193
6bbefe86
DH
194static void *prism2_download_aux_dump_proc_start(struct seq_file *m, loff_t *_pos)
195{
196 struct prism2_download_aux_dump *ctx = m->private;
197 prism2_enable_aux_port(ctx->local->dev, 1);
198 if (*_pos >= prism2_download_aux_dump_npages)
199 return NULL;
200 return (void *)((unsigned long)*_pos + 1);
201}
202
203static void *prism2_download_aux_dump_proc_next(struct seq_file *m, void *v, loff_t *_pos)
204{
205 ++*_pos;
206 if (*_pos >= prism2_download_aux_dump_npages)
207 return NULL;
208 return (void *)((unsigned long)*_pos + 1);
209}
210
211static void prism2_download_aux_dump_proc_stop(struct seq_file *m, void *v)
212{
213 struct prism2_download_aux_dump *ctx = m->private;
214 prism2_enable_aux_port(ctx->local->dev, 0);
215}
216
217static const struct seq_operations prism2_download_aux_dump_proc_seqops = {
218 .start = prism2_download_aux_dump_proc_start,
219 .next = prism2_download_aux_dump_proc_next,
220 .stop = prism2_download_aux_dump_proc_stop,
221 .show = prism2_download_aux_dump_proc_show,
222};
223
224static int prism2_download_aux_dump_proc_open(struct inode *inode, struct file *file)
225{
226 int ret = seq_open_private(file, &prism2_download_aux_dump_proc_seqops,
227 sizeof(struct prism2_download_aux_dump));
228 if (ret == 0) {
229 struct seq_file *m = file->private_data;
230 m->private = PDE_DATA(inode);
231 }
232 return ret;
233}
234
235static const struct file_operations prism2_download_aux_dump_proc_fops = {
236 .open = prism2_download_aux_dump_proc_open,
237 .read = seq_read,
238 .llseek = seq_lseek,
239 .release = seq_release_private,
240};
241
ff1d2767
JM
242
243static u8 * prism2_read_pda(struct net_device *dev)
244{
245 u8 *buf;
246 int res, i, found = 0;
247#define NUM_PDA_ADDRS 4
248 unsigned int pda_addr[NUM_PDA_ADDRS] = {
249 0x7f0000 /* others than HFA3841 */,
250 0x3f0000 /* HFA3841 */,
251 0x390000 /* apparently used in older cards */,
252 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
253 };
254
5cbded58 255 buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
ff1d2767
JM
256 if (buf == NULL)
257 return NULL;
258
259 /* Note: wlan card should be in initial state (just after init cmd)
260 * and no other operations should be performed concurrently. */
261
262 prism2_enable_aux_port(dev, 1);
263
264 for (i = 0; i < NUM_PDA_ADDRS; i++) {
265 PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
266 dev->name, pda_addr[i]);
267 res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
268 if (res)
269 continue;
270 if (res == 0 && prism2_pda_ok(buf)) {
271 PDEBUG2(DEBUG_EXTRA2, ": OK\n");
272 found = 1;
273 break;
274 } else {
275 PDEBUG2(DEBUG_EXTRA2, ": failed\n");
276 }
277 }
278
279 prism2_enable_aux_port(dev, 0);
280
281 if (!found) {
282 printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
283 kfree(buf);
284 buf = NULL;
285 }
286
287 return buf;
288}
289
290
291static int prism2_download_volatile(local_info_t *local,
292 struct prism2_download_data *param)
293{
294 struct net_device *dev = local->dev;
295 int ret = 0, i;
296 u16 param0, param1;
297
298 if (local->hw_downloading) {
299 printk(KERN_WARNING "%s: Already downloading - aborting new "
300 "request\n", dev->name);
301 return -1;
302 }
303
304 local->hw_downloading = 1;
305 if (local->pri_only) {
306 hfa384x_disable_interrupts(dev);
307 } else {
308 prism2_hw_shutdown(dev, 0);
309
310 if (prism2_hw_init(dev, 0)) {
311 printk(KERN_WARNING "%s: Could not initialize card for"
312 " download\n", dev->name);
313 ret = -1;
314 goto out;
315 }
316 }
317
318 if (prism2_enable_aux_port(dev, 1)) {
319 printk(KERN_WARNING "%s: Could not enable AUX port\n",
320 dev->name);
321 ret = -1;
322 goto out;
323 }
324
325 param0 = param->start_addr & 0xffff;
326 param1 = param->start_addr >> 16;
327
328 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
329 HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
330 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
331 (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
332 param0)) {
333 printk(KERN_WARNING "%s: Download command execution failed\n",
334 dev->name);
335 ret = -1;
336 goto out;
337 }
338
339 for (i = 0; i < param->num_areas; i++) {
340 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
341 dev->name, param->data[i].len, param->data[i].addr);
342 if (hfa384x_to_aux(dev, param->data[i].addr,
343 param->data[i].len, param->data[i].data)) {
344 printk(KERN_WARNING "%s: RAM download at 0x%08x "
345 "(len=%d) failed\n", dev->name,
346 param->data[i].addr, param->data[i].len);
347 ret = -1;
348 goto out;
349 }
350 }
351
352 HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
353 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
354 if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
355 (HFA384X_PROGMODE_DISABLE << 8), param0)) {
356 printk(KERN_WARNING "%s: Download command execution failed\n",
357 dev->name);
358 ret = -1;
359 goto out;
360 }
361 /* ProgMode disable causes the hardware to restart itself from the
362 * given starting address. Give hw some time and ACK command just in
363 * case restart did not happen. */
364 mdelay(5);
365 HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
366
367 if (prism2_enable_aux_port(dev, 0)) {
368 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
369 dev->name);
370 /* continue anyway.. restart should have taken care of this */
371 }
372
373 mdelay(5);
374 local->hw_downloading = 0;
375 if (prism2_hw_config(dev, 2)) {
376 printk(KERN_WARNING "%s: Card configuration after RAM "
377 "download failed\n", dev->name);
378 ret = -1;
379 goto out;
380 }
381
382 out:
383 local->hw_downloading = 0;
384 return ret;
385}
386
387
388static int prism2_enable_genesis(local_info_t *local, int hcr)
389{
390 struct net_device *dev = local->dev;
391 u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
392 u8 readbuf[4];
393
394 printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
395 dev->name, hcr);
396 local->func->cor_sreset(local);
397 hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
398 local->func->genesis_reset(local, hcr);
399
400 /* Readback test */
401 hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
402 hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
403 hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
404
405 if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
406 printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
407 hcr);
408 return 0;
409 } else {
410 printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
411 "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
412 hcr, initseq[0], initseq[1], initseq[2], initseq[3],
413 readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
414 return 1;
415 }
416}
417
418
419static int prism2_get_ram_size(local_info_t *local)
420{
421 int ret;
422
423 /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
424 if (prism2_enable_genesis(local, 0x1f) == 0)
425 ret = 8;
426 else if (prism2_enable_genesis(local, 0x0f) == 0)
427 ret = 16;
428 else
429 ret = -1;
430
431 /* Disable genesis mode */
432 local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
433
434 return ret;
435}
436
437
438static int prism2_download_genesis(local_info_t *local,
439 struct prism2_download_data *param)
440{
441 struct net_device *dev = local->dev;
442 int ram16 = 0, i;
443 int ret = 0;
444
445 if (local->hw_downloading) {
446 printk(KERN_WARNING "%s: Already downloading - aborting new "
447 "request\n", dev->name);
448 return -EBUSY;
449 }
450
451 if (!local->func->genesis_reset || !local->func->cor_sreset) {
452 printk(KERN_INFO "%s: Genesis mode downloading not supported "
453 "with this hwmodel\n", dev->name);
454 return -EOPNOTSUPP;
455 }
456
457 local->hw_downloading = 1;
458
459 if (prism2_enable_aux_port(dev, 1)) {
460 printk(KERN_DEBUG "%s: failed to enable AUX port\n",
461 dev->name);
462 ret = -EIO;
463 goto out;
464 }
465
466 if (local->sram_type == -1) {
467 /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
468 if (prism2_enable_genesis(local, 0x1f) == 0) {
469 ram16 = 0;
470 PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
471 "SRAM\n", dev->name);
472 } else if (prism2_enable_genesis(local, 0x0f) == 0) {
473 ram16 = 1;
474 PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
475 "SRAM\n", dev->name);
476 } else {
477 printk(KERN_DEBUG "%s: Could not initiate genesis "
478 "mode\n", dev->name);
479 ret = -EIO;
480 goto out;
481 }
482 } else {
483 if (prism2_enable_genesis(local, local->sram_type == 8 ?
484 0x1f : 0x0f)) {
485 printk(KERN_DEBUG "%s: Failed to set Genesis "
486 "mode (sram_type=%d)\n", dev->name,
487 local->sram_type);
488 ret = -EIO;
489 goto out;
490 }
491 ram16 = local->sram_type != 8;
492 }
493
494 for (i = 0; i < param->num_areas; i++) {
495 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
496 dev->name, param->data[i].len, param->data[i].addr);
497 if (hfa384x_to_aux(dev, param->data[i].addr,
498 param->data[i].len, param->data[i].data)) {
499 printk(KERN_WARNING "%s: RAM download at 0x%08x "
500 "(len=%d) failed\n", dev->name,
501 param->data[i].addr, param->data[i].len);
502 ret = -EIO;
503 goto out;
504 }
505 }
506
507 PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
508 local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
509 if (prism2_enable_aux_port(dev, 0)) {
510 printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
511 dev->name);
512 }
513
514 mdelay(5);
515 local->hw_downloading = 0;
516
517 PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
518 /*
519 * Make sure the INIT command does not generate a command completion
520 * event by disabling interrupts.
521 */
522 hfa384x_disable_interrupts(dev);
523 if (prism2_hw_init(dev, 1)) {
524 printk(KERN_DEBUG "%s: Initialization after genesis mode "
525 "download failed\n", dev->name);
526 ret = -EIO;
527 goto out;
528 }
529
530 PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
531 if (prism2_hw_init2(dev, 1)) {
532 printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
533 "download failed\n", dev->name);
534 ret = -EIO;
535 goto out;
536 }
537
538 out:
539 local->hw_downloading = 0;
540 return ret;
541}
542
543
544#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
545/* Note! Non-volatile downloading functionality has not yet been tested
546 * thoroughly and it may corrupt flash image and effectively kill the card that
547 * is being updated. You have been warned. */
548
549static inline int prism2_download_block(struct net_device *dev,
550 u32 addr, u8 *data,
551 u32 bufaddr, int rest_len)
552{
553 u16 param0, param1;
554 int block_len;
555
556 block_len = rest_len < 4096 ? rest_len : 4096;
557
558 param0 = addr & 0xffff;
559 param1 = addr >> 16;
560
561 HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
562 HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
563
564 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
565 (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
566 param0)) {
567 printk(KERN_WARNING "%s: Flash download command execution "
568 "failed\n", dev->name);
569 return -1;
570 }
571
572 if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
573 printk(KERN_WARNING "%s: flash download at 0x%08x "
574 "(len=%d) failed\n", dev->name, addr, block_len);
575 return -1;
576 }
577
578 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
579 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
580 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
581 (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
582 0)) {
583 printk(KERN_WARNING "%s: Flash write command execution "
584 "failed\n", dev->name);
585 return -1;
586 }
587
588 return block_len;
589}
590
591
592static int prism2_download_nonvolatile(local_info_t *local,
593 struct prism2_download_data *dl)
594{
595 struct net_device *dev = local->dev;
596 int ret = 0, i;
597 struct {
8a9faf3c
AV
598 __le16 page;
599 __le16 offset;
600 __le16 len;
ff1d2767
JM
601 } dlbuffer;
602 u32 bufaddr;
603
604 if (local->hw_downloading) {
605 printk(KERN_WARNING "%s: Already downloading - aborting new "
606 "request\n", dev->name);
607 return -1;
608 }
609
610 ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
611 &dlbuffer, 6, 0);
612
613 if (ret < 0) {
614 printk(KERN_WARNING "%s: Could not read download buffer "
615 "parameters\n", dev->name);
616 goto out;
617 }
618
ff1d2767 619 printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
8a9faf3c
AV
620 le16_to_cpu(dlbuffer.len),
621 le16_to_cpu(dlbuffer.page),
622 le16_to_cpu(dlbuffer.offset));
ff1d2767 623
8a9faf3c 624 bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
ff1d2767
JM
625
626 local->hw_downloading = 1;
627
628 if (!local->pri_only) {
629 prism2_hw_shutdown(dev, 0);
630
631 if (prism2_hw_init(dev, 0)) {
632 printk(KERN_WARNING "%s: Could not initialize card for"
633 " download\n", dev->name);
634 ret = -1;
635 goto out;
636 }
637 }
638
639 hfa384x_disable_interrupts(dev);
640
641 if (prism2_enable_aux_port(dev, 1)) {
642 printk(KERN_WARNING "%s: Could not enable AUX port\n",
643 dev->name);
644 ret = -1;
645 goto out;
646 }
647
648 printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
649 for (i = 0; i < dl->num_areas; i++) {
650 int rest_len = dl->data[i].len;
651 int data_off = 0;
652
653 while (rest_len > 0) {
654 int block_len;
655
656 block_len = prism2_download_block(
657 dev, dl->data[i].addr + data_off,
658 dl->data[i].data + data_off, bufaddr,
659 rest_len);
660
661 if (block_len < 0) {
662 ret = -1;
663 goto out;
664 }
665
666 rest_len -= block_len;
667 data_off += block_len;
668 }
669 }
670
671 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
672 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
673 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
674 (HFA384X_PROGMODE_DISABLE << 8), 0)) {
675 printk(KERN_WARNING "%s: Download command execution failed\n",
676 dev->name);
677 ret = -1;
678 goto out;
679 }
680
681 if (prism2_enable_aux_port(dev, 0)) {
682 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
683 dev->name);
684 /* continue anyway.. restart should have taken care of this */
685 }
686
687 mdelay(5);
688
689 local->func->hw_reset(dev);
690 local->hw_downloading = 0;
691 if (prism2_hw_config(dev, 2)) {
692 printk(KERN_WARNING "%s: Card configuration after flash "
693 "download failed\n", dev->name);
694 ret = -1;
695 } else {
696 printk(KERN_INFO "%s: Card initialized successfully after "
697 "flash download\n", dev->name);
698 }
699
700 out:
701 local->hw_downloading = 0;
702 return ret;
703}
704#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
705
706
707static void prism2_download_free_data(struct prism2_download_data *dl)
708{
709 int i;
710
711 if (dl == NULL)
712 return;
713
714 for (i = 0; i < dl->num_areas; i++)
715 kfree(dl->data[i].data);
716 kfree(dl);
717}
718
719
720static int prism2_download(local_info_t *local,
721 struct prism2_download_param *param)
722{
723 int ret = 0;
724 int i;
725 u32 total_len = 0;
726 struct prism2_download_data *dl = NULL;
727
728 printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
729 "num_areas=%d\n",
730 param->dl_cmd, param->start_addr, param->num_areas);
731
732 if (param->num_areas > 100) {
733 ret = -EINVAL;
734 goto out;
735 }
736
b0471bb7 737 dl = kzalloc(sizeof(*dl) + param->num_areas *
ff1d2767
JM
738 sizeof(struct prism2_download_data_area), GFP_KERNEL);
739 if (dl == NULL) {
740 ret = -ENOMEM;
741 goto out;
742 }
ff1d2767
JM
743 dl->dl_cmd = param->dl_cmd;
744 dl->start_addr = param->start_addr;
745 dl->num_areas = param->num_areas;
746 for (i = 0; i < param->num_areas; i++) {
747 PDEBUG(DEBUG_EXTRA2,
748 " area %d: addr=0x%08x len=%d ptr=0x%p\n",
749 i, param->data[i].addr, param->data[i].len,
750 param->data[i].ptr);
751
752 dl->data[i].addr = param->data[i].addr;
753 dl->data[i].len = param->data[i].len;
754
755 total_len += param->data[i].len;
756 if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
757 total_len > PRISM2_MAX_DOWNLOAD_LEN) {
758 ret = -E2BIG;
759 goto out;
760 }
761
762 dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
763 if (dl->data[i].data == NULL) {
764 ret = -ENOMEM;
765 goto out;
766 }
767
768 if (copy_from_user(dl->data[i].data, param->data[i].ptr,
769 param->data[i].len)) {
770 ret = -EFAULT;
771 goto out;
772 }
773 }
774
775 switch (param->dl_cmd) {
776 case PRISM2_DOWNLOAD_VOLATILE:
777 case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
778 ret = prism2_download_volatile(local, dl);
779 break;
780 case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
781 case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
782 ret = prism2_download_genesis(local, dl);
783 break;
784 case PRISM2_DOWNLOAD_NON_VOLATILE:
785#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
786 ret = prism2_download_nonvolatile(local, dl);
787#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
788 printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
789 local->dev->name);
790 ret = -EOPNOTSUPP;
791#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
792 break;
793 default:
794 printk(KERN_DEBUG "%s: unsupported download command %d\n",
795 local->dev->name, param->dl_cmd);
796 ret = -EINVAL;
797 break;
ee289b64 798 }
ff1d2767
JM
799
800 out:
801 if (ret == 0 && dl &&
802 param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
803 prism2_download_free_data(local->dl_pri);
804 local->dl_pri = dl;
805 } else if (ret == 0 && dl &&
806 param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
807 prism2_download_free_data(local->dl_sec);
808 local->dl_sec = dl;
809 } else
810 prism2_download_free_data(dl);
811
812 return ret;
813}