This source file includes following definitions.
- prism2_enable_aux_port
- hfa384x_from_aux
- hfa384x_to_aux
- prism2_pda_ok
- prism2_download_aux_dump_proc_show
- prism2_download_aux_dump_proc_start
- prism2_download_aux_dump_proc_next
- prism2_download_aux_dump_proc_stop
- prism2_download_aux_dump_proc_open
- prism2_read_pda
- prism2_download_volatile
- prism2_enable_genesis
- prism2_get_ram_size
- prism2_download_genesis
- prism2_download_block
- prism2_download_nonvolatile
- prism2_download_free_data
- prism2_download
1
2 static 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
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
87 static 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 {
104 __le16 *pos = (__le16 *) buf;
105 while (len > 0) {
106 *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
107 len -= 2;
108 }
109 }
110 #else
111 HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
112 #endif
113
114 return 0;
115 }
116
117
118 static 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 {
135 __le16 *pos = (__le16 *) buf;
136 while (len > 0) {
137 HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
138 len -= 2;
139 }
140 }
141 #else
142 HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
143 #endif
144
145 return 0;
146 }
147
148
149 static int prism2_pda_ok(u8 *buf)
150 {
151 __le16 *pda = (__le16 *) buf;
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
168 return 1;
169 }
170
171 pos += len + 1;
172 }
173
174 return 0;
175 }
176
177
178 #define prism2_download_aux_dump_npages 65536
179
180 struct prism2_download_aux_dump {
181 local_info_t *local;
182 u16 page[0x80];
183 };
184
185 static int prism2_download_aux_dump_proc_show(struct seq_file *m, void *v)
186 {
187 struct prism2_download_aux_dump *ctx = m->private;
188
189 hfa384x_from_aux(ctx->local->dev, (unsigned long)v - 1, 0x80, ctx->page);
190 seq_write(m, ctx->page, 0x80);
191 return 0;
192 }
193
194 static 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
203 static 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
211 static 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
217 static 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
224 static 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
235 static 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
242
243 static 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 ,
250 0x3f0000 ,
251 0x390000 ,
252 0x7f0002 ,
253 };
254
255 buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
256 if (buf == NULL)
257 return NULL;
258
259
260
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
291 static 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
362
363
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
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
388 static 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
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 write %4ph read %4ph\n",
411 hcr, initseq, readbuf);
412 return 1;
413 }
414 }
415
416
417 static int prism2_get_ram_size(local_info_t *local)
418 {
419 int ret;
420
421
422 if (prism2_enable_genesis(local, 0x1f) == 0)
423 ret = 8;
424 else if (prism2_enable_genesis(local, 0x0f) == 0)
425 ret = 16;
426 else
427 ret = -1;
428
429
430 local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
431
432 return ret;
433 }
434
435
436 static int prism2_download_genesis(local_info_t *local,
437 struct prism2_download_data *param)
438 {
439 struct net_device *dev = local->dev;
440 int ram16 = 0, i;
441 int ret = 0;
442
443 if (local->hw_downloading) {
444 printk(KERN_WARNING "%s: Already downloading - aborting new "
445 "request\n", dev->name);
446 return -EBUSY;
447 }
448
449 if (!local->func->genesis_reset || !local->func->cor_sreset) {
450 printk(KERN_INFO "%s: Genesis mode downloading not supported "
451 "with this hwmodel\n", dev->name);
452 return -EOPNOTSUPP;
453 }
454
455 local->hw_downloading = 1;
456
457 if (prism2_enable_aux_port(dev, 1)) {
458 printk(KERN_DEBUG "%s: failed to enable AUX port\n",
459 dev->name);
460 ret = -EIO;
461 goto out;
462 }
463
464 if (local->sram_type == -1) {
465
466 if (prism2_enable_genesis(local, 0x1f) == 0) {
467 ram16 = 0;
468 PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
469 "SRAM\n", dev->name);
470 } else if (prism2_enable_genesis(local, 0x0f) == 0) {
471 ram16 = 1;
472 PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
473 "SRAM\n", dev->name);
474 } else {
475 printk(KERN_DEBUG "%s: Could not initiate genesis "
476 "mode\n", dev->name);
477 ret = -EIO;
478 goto out;
479 }
480 } else {
481 if (prism2_enable_genesis(local, local->sram_type == 8 ?
482 0x1f : 0x0f)) {
483 printk(KERN_DEBUG "%s: Failed to set Genesis "
484 "mode (sram_type=%d)\n", dev->name,
485 local->sram_type);
486 ret = -EIO;
487 goto out;
488 }
489 ram16 = local->sram_type != 8;
490 }
491
492 for (i = 0; i < param->num_areas; i++) {
493 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
494 dev->name, param->data[i].len, param->data[i].addr);
495 if (hfa384x_to_aux(dev, param->data[i].addr,
496 param->data[i].len, param->data[i].data)) {
497 printk(KERN_WARNING "%s: RAM download at 0x%08x "
498 "(len=%d) failed\n", dev->name,
499 param->data[i].addr, param->data[i].len);
500 ret = -EIO;
501 goto out;
502 }
503 }
504
505 PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
506 local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
507 if (prism2_enable_aux_port(dev, 0)) {
508 printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
509 dev->name);
510 }
511
512 mdelay(5);
513 local->hw_downloading = 0;
514
515 PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
516
517
518
519
520 hfa384x_disable_interrupts(dev);
521 if (prism2_hw_init(dev, 1)) {
522 printk(KERN_DEBUG "%s: Initialization after genesis mode "
523 "download failed\n", dev->name);
524 ret = -EIO;
525 goto out;
526 }
527
528 PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
529 if (prism2_hw_init2(dev, 1)) {
530 printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
531 "download failed\n", dev->name);
532 ret = -EIO;
533 goto out;
534 }
535
536 out:
537 local->hw_downloading = 0;
538 return ret;
539 }
540
541
542 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
543
544
545
546
547 static inline int prism2_download_block(struct net_device *dev,
548 u32 addr, u8 *data,
549 u32 bufaddr, int rest_len)
550 {
551 u16 param0, param1;
552 int block_len;
553
554 block_len = rest_len < 4096 ? rest_len : 4096;
555
556 param0 = addr & 0xffff;
557 param1 = addr >> 16;
558
559 HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
560 HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
561
562 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
563 (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
564 param0)) {
565 printk(KERN_WARNING "%s: Flash download command execution "
566 "failed\n", dev->name);
567 return -1;
568 }
569
570 if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
571 printk(KERN_WARNING "%s: flash download at 0x%08x "
572 "(len=%d) failed\n", dev->name, addr, block_len);
573 return -1;
574 }
575
576 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
577 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
578 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
579 (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
580 0)) {
581 printk(KERN_WARNING "%s: Flash write command execution "
582 "failed\n", dev->name);
583 return -1;
584 }
585
586 return block_len;
587 }
588
589
590 static int prism2_download_nonvolatile(local_info_t *local,
591 struct prism2_download_data *dl)
592 {
593 struct net_device *dev = local->dev;
594 int ret = 0, i;
595 struct {
596 __le16 page;
597 __le16 offset;
598 __le16 len;
599 } dlbuffer;
600 u32 bufaddr;
601
602 if (local->hw_downloading) {
603 printk(KERN_WARNING "%s: Already downloading - aborting new "
604 "request\n", dev->name);
605 return -1;
606 }
607
608 ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
609 &dlbuffer, 6, 0);
610
611 if (ret < 0) {
612 printk(KERN_WARNING "%s: Could not read download buffer "
613 "parameters\n", dev->name);
614 goto out;
615 }
616
617 printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
618 le16_to_cpu(dlbuffer.len),
619 le16_to_cpu(dlbuffer.page),
620 le16_to_cpu(dlbuffer.offset));
621
622 bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
623
624 local->hw_downloading = 1;
625
626 if (!local->pri_only) {
627 prism2_hw_shutdown(dev, 0);
628
629 if (prism2_hw_init(dev, 0)) {
630 printk(KERN_WARNING "%s: Could not initialize card for"
631 " download\n", dev->name);
632 ret = -1;
633 goto out;
634 }
635 }
636
637 hfa384x_disable_interrupts(dev);
638
639 if (prism2_enable_aux_port(dev, 1)) {
640 printk(KERN_WARNING "%s: Could not enable AUX port\n",
641 dev->name);
642 ret = -1;
643 goto out;
644 }
645
646 printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
647 for (i = 0; i < dl->num_areas; i++) {
648 int rest_len = dl->data[i].len;
649 int data_off = 0;
650
651 while (rest_len > 0) {
652 int block_len;
653
654 block_len = prism2_download_block(
655 dev, dl->data[i].addr + data_off,
656 dl->data[i].data + data_off, bufaddr,
657 rest_len);
658
659 if (block_len < 0) {
660 ret = -1;
661 goto out;
662 }
663
664 rest_len -= block_len;
665 data_off += block_len;
666 }
667 }
668
669 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
670 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
671 if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
672 (HFA384X_PROGMODE_DISABLE << 8), 0)) {
673 printk(KERN_WARNING "%s: Download command execution failed\n",
674 dev->name);
675 ret = -1;
676 goto out;
677 }
678
679 if (prism2_enable_aux_port(dev, 0)) {
680 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
681 dev->name);
682
683 }
684
685 mdelay(5);
686
687 local->func->hw_reset(dev);
688 local->hw_downloading = 0;
689 if (prism2_hw_config(dev, 2)) {
690 printk(KERN_WARNING "%s: Card configuration after flash "
691 "download failed\n", dev->name);
692 ret = -1;
693 } else {
694 printk(KERN_INFO "%s: Card initialized successfully after "
695 "flash download\n", dev->name);
696 }
697
698 out:
699 local->hw_downloading = 0;
700 return ret;
701 }
702 #endif
703
704
705 static void prism2_download_free_data(struct prism2_download_data *dl)
706 {
707 int i;
708
709 if (dl == NULL)
710 return;
711
712 for (i = 0; i < dl->num_areas; i++)
713 kfree(dl->data[i].data);
714 kfree(dl);
715 }
716
717
718 static int prism2_download(local_info_t *local,
719 struct prism2_download_param *param)
720 {
721 int ret = 0;
722 int i;
723 u32 total_len = 0;
724 struct prism2_download_data *dl = NULL;
725
726 printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
727 "num_areas=%d\n",
728 param->dl_cmd, param->start_addr, param->num_areas);
729
730 if (param->num_areas > 100) {
731 ret = -EINVAL;
732 goto out;
733 }
734
735 dl = kzalloc(sizeof(*dl) + param->num_areas *
736 sizeof(struct prism2_download_data_area), GFP_KERNEL);
737 if (dl == NULL) {
738 ret = -ENOMEM;
739 goto out;
740 }
741 dl->dl_cmd = param->dl_cmd;
742 dl->start_addr = param->start_addr;
743 dl->num_areas = param->num_areas;
744 for (i = 0; i < param->num_areas; i++) {
745 PDEBUG(DEBUG_EXTRA2,
746 " area %d: addr=0x%08x len=%d ptr=0x%p\n",
747 i, param->data[i].addr, param->data[i].len,
748 param->data[i].ptr);
749
750 dl->data[i].addr = param->data[i].addr;
751 dl->data[i].len = param->data[i].len;
752
753 total_len += param->data[i].len;
754 if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
755 total_len > PRISM2_MAX_DOWNLOAD_LEN) {
756 ret = -E2BIG;
757 goto out;
758 }
759
760 dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
761 if (dl->data[i].data == NULL) {
762 ret = -ENOMEM;
763 goto out;
764 }
765
766 if (copy_from_user(dl->data[i].data, param->data[i].ptr,
767 param->data[i].len)) {
768 ret = -EFAULT;
769 goto out;
770 }
771 }
772
773 switch (param->dl_cmd) {
774 case PRISM2_DOWNLOAD_VOLATILE:
775 case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
776 ret = prism2_download_volatile(local, dl);
777 break;
778 case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
779 case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
780 ret = prism2_download_genesis(local, dl);
781 break;
782 case PRISM2_DOWNLOAD_NON_VOLATILE:
783 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
784 ret = prism2_download_nonvolatile(local, dl);
785 #else
786 printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
787 local->dev->name);
788 ret = -EOPNOTSUPP;
789 #endif
790 break;
791 default:
792 printk(KERN_DEBUG "%s: unsupported download command %d\n",
793 local->dev->name, param->dl_cmd);
794 ret = -EINVAL;
795 break;
796 }
797
798 out:
799 if (ret == 0 && dl &&
800 param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
801 prism2_download_free_data(local->dl_pri);
802 local->dl_pri = dl;
803 } else if (ret == 0 && dl &&
804 param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
805 prism2_download_free_data(local->dl_sec);
806 local->dl_sec = dl;
807 } else
808 prism2_download_free_data(dl);
809
810 return ret;
811 }