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