PageRenderTime 93ms CodeModel.GetById 16ms app.highlight 70ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/net/wireless/hostap/hostap_download.c

http://github.com/mirrors/linux
C | 812 lines | 652 code | 140 blank | 20 comment | 131 complexity | 96337b4904db518cc0cb0f46890b9211 MD5 | raw file
  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		__le16 *pos = (__le16 *) 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		__le16 *pos = (__le16 *) 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	__le16 *pda = (__le16 *) 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
177#define prism2_download_aux_dump_npages 65536
178
179struct prism2_download_aux_dump {
180	local_info_t *local;
181	u16 page[0x80];
182};
183
184static int prism2_download_aux_dump_proc_show(struct seq_file *m, void *v)
185{
186	struct prism2_download_aux_dump *ctx = m->private;
187
188	hfa384x_from_aux(ctx->local->dev, (unsigned long)v - 1, 0x80, ctx->page);
189	seq_write(m, ctx->page, 0x80);
190	return 0;
191}
192
193static void *prism2_download_aux_dump_proc_start(struct seq_file *m, loff_t *_pos)
194{
195	struct prism2_download_aux_dump *ctx = m->private;
196	prism2_enable_aux_port(ctx->local->dev, 1);
197	if (*_pos >= prism2_download_aux_dump_npages)
198		return NULL;
199	return (void *)((unsigned long)*_pos + 1);
200}
201
202static void *prism2_download_aux_dump_proc_next(struct seq_file *m, void *v, loff_t *_pos)
203{
204	++*_pos;
205	if (*_pos >= prism2_download_aux_dump_npages)
206		return NULL;
207	return (void *)((unsigned long)*_pos + 1);
208}
209
210static void prism2_download_aux_dump_proc_stop(struct seq_file *m, void *v)
211{
212	struct prism2_download_aux_dump *ctx = m->private;
213	prism2_enable_aux_port(ctx->local->dev, 0);
214}
215
216static const struct seq_operations prism2_download_aux_dump_proc_seqops = {
217	.start	= prism2_download_aux_dump_proc_start,
218	.next	= prism2_download_aux_dump_proc_next,
219	.stop	= prism2_download_aux_dump_proc_stop,
220	.show	= prism2_download_aux_dump_proc_show,
221};
222
223static int prism2_download_aux_dump_proc_open(struct inode *inode, struct file *file)
224{
225	int ret = seq_open_private(file, &prism2_download_aux_dump_proc_seqops,
226				   sizeof(struct prism2_download_aux_dump));
227	if (ret == 0) {
228		struct seq_file *m = file->private_data;
229		m->private = PDE_DATA(inode);
230	}
231	return ret;
232}
233
234static const struct file_operations prism2_download_aux_dump_proc_fops = {
235	.open		= prism2_download_aux_dump_proc_open,
236	.read		= seq_read,
237	.llseek		= seq_lseek,
238	.release	= seq_release_private,
239};
240
241
242static u8 * prism2_read_pda(struct net_device *dev)
243{
244	u8 *buf;
245	int res, i, found = 0;
246#define NUM_PDA_ADDRS 4
247	unsigned int pda_addr[NUM_PDA_ADDRS] = {
248		0x7f0000 /* others than HFA3841 */,
249		0x3f0000 /* HFA3841 */,
250		0x390000 /* apparently used in older cards */,
251		0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
252	};
253
254	buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
255	if (buf == NULL)
256		return NULL;
257
258	/* Note: wlan card should be in initial state (just after init cmd)
259	 * and no other operations should be performed concurrently. */
260
261	prism2_enable_aux_port(dev, 1);
262
263	for (i = 0; i < NUM_PDA_ADDRS; i++) {
264		PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
265		       dev->name, pda_addr[i]);
266		res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
267		if (res)
268			continue;
269		if (res == 0 && prism2_pda_ok(buf)) {
270			PDEBUG2(DEBUG_EXTRA2, ": OK\n");
271			found = 1;
272			break;
273		} else {
274			PDEBUG2(DEBUG_EXTRA2, ": failed\n");
275		}
276	}
277
278	prism2_enable_aux_port(dev, 0);
279
280	if (!found) {
281		printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
282		kfree(buf);
283		buf = NULL;
284	}
285
286	return buf;
287}
288
289
290static int prism2_download_volatile(local_info_t *local,
291				    struct prism2_download_data *param)
292{
293	struct net_device *dev = local->dev;
294	int ret = 0, i;
295	u16 param0, param1;
296
297	if (local->hw_downloading) {
298		printk(KERN_WARNING "%s: Already downloading - aborting new "
299		       "request\n", dev->name);
300		return -1;
301	}
302
303	local->hw_downloading = 1;
304	if (local->pri_only) {
305		hfa384x_disable_interrupts(dev);
306	} else {
307		prism2_hw_shutdown(dev, 0);
308
309		if (prism2_hw_init(dev, 0)) {
310			printk(KERN_WARNING "%s: Could not initialize card for"
311			       " download\n", dev->name);
312			ret = -1;
313			goto out;
314		}
315	}
316
317	if (prism2_enable_aux_port(dev, 1)) {
318		printk(KERN_WARNING "%s: Could not enable AUX port\n",
319		       dev->name);
320		ret = -1;
321		goto out;
322	}
323
324	param0 = param->start_addr & 0xffff;
325	param1 = param->start_addr >> 16;
326
327	HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
328	HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
329	if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
330			     (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
331			     param0)) {
332		printk(KERN_WARNING "%s: Download command execution failed\n",
333		       dev->name);
334		ret = -1;
335		goto out;
336	}
337
338	for (i = 0; i < param->num_areas; i++) {
339		PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
340		       dev->name, param->data[i].len, param->data[i].addr);
341		if (hfa384x_to_aux(dev, param->data[i].addr,
342				   param->data[i].len, param->data[i].data)) {
343			printk(KERN_WARNING "%s: RAM download at 0x%08x "
344			       "(len=%d) failed\n", dev->name,
345			       param->data[i].addr, param->data[i].len);
346			ret = -1;
347			goto out;
348		}
349	}
350
351	HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
352	HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
353	if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
354				(HFA384X_PROGMODE_DISABLE << 8), param0)) {
355		printk(KERN_WARNING "%s: Download command execution failed\n",
356		       dev->name);
357		ret = -1;
358		goto out;
359	}
360	/* ProgMode disable causes the hardware to restart itself from the
361	 * given starting address. Give hw some time and ACK command just in
362	 * case restart did not happen. */
363	mdelay(5);
364	HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
365
366	if (prism2_enable_aux_port(dev, 0)) {
367		printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
368		       dev->name);
369		/* continue anyway.. restart should have taken care of this */
370	}
371
372	mdelay(5);
373	local->hw_downloading = 0;
374	if (prism2_hw_config(dev, 2)) {
375		printk(KERN_WARNING "%s: Card configuration after RAM "
376		       "download failed\n", dev->name);
377		ret = -1;
378		goto out;
379	}
380
381 out:
382	local->hw_downloading = 0;
383	return ret;
384}
385
386
387static int prism2_enable_genesis(local_info_t *local, int hcr)
388{
389	struct net_device *dev = local->dev;
390	u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
391	u8 readbuf[4];
392
393	printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
394	       dev->name, hcr);
395	local->func->cor_sreset(local);
396	hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
397	local->func->genesis_reset(local, hcr);
398
399	/* Readback test */
400	hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
401	hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
402	hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
403
404	if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
405		printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
406		       hcr);
407		return 0;
408	} else {
409		printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
410		       "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
411		       hcr, initseq[0], initseq[1], initseq[2], initseq[3],
412		       readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
413		return 1;
414	}
415}
416
417
418static int prism2_get_ram_size(local_info_t *local)
419{
420	int ret;
421
422	/* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
423	if (prism2_enable_genesis(local, 0x1f) == 0)
424		ret = 8;
425	else if (prism2_enable_genesis(local, 0x0f) == 0)
426		ret = 16;
427	else
428		ret = -1;
429
430	/* Disable genesis mode */
431	local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
432
433	return ret;
434}
435
436
437static int prism2_download_genesis(local_info_t *local,
438				   struct prism2_download_data *param)
439{
440	struct net_device *dev = local->dev;
441	int ram16 = 0, i;
442	int ret = 0;
443
444	if (local->hw_downloading) {
445		printk(KERN_WARNING "%s: Already downloading - aborting new "
446		       "request\n", dev->name);
447		return -EBUSY;
448	}
449
450	if (!local->func->genesis_reset || !local->func->cor_sreset) {
451		printk(KERN_INFO "%s: Genesis mode downloading not supported "
452		       "with this hwmodel\n", dev->name);
453		return -EOPNOTSUPP;
454	}
455
456	local->hw_downloading = 1;
457
458	if (prism2_enable_aux_port(dev, 1)) {
459		printk(KERN_DEBUG "%s: failed to enable AUX port\n",
460		       dev->name);
461		ret = -EIO;
462		goto out;
463	}
464
465	if (local->sram_type == -1) {
466		/* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
467		if (prism2_enable_genesis(local, 0x1f) == 0) {
468			ram16 = 0;
469			PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
470			       "SRAM\n", dev->name);
471		} else if (prism2_enable_genesis(local, 0x0f) == 0) {
472			ram16 = 1;
473			PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
474			       "SRAM\n", dev->name);
475		} else {
476			printk(KERN_DEBUG "%s: Could not initiate genesis "
477			       "mode\n", dev->name);
478			ret = -EIO;
479			goto out;
480		}
481	} else {
482		if (prism2_enable_genesis(local, local->sram_type == 8 ?
483					  0x1f : 0x0f)) {
484			printk(KERN_DEBUG "%s: Failed to set Genesis "
485			       "mode (sram_type=%d)\n", dev->name,
486			       local->sram_type);
487			ret = -EIO;
488			goto out;
489		}
490		ram16 = local->sram_type != 8;
491	}
492
493	for (i = 0; i < param->num_areas; i++) {
494		PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
495		       dev->name, param->data[i].len, param->data[i].addr);
496		if (hfa384x_to_aux(dev, param->data[i].addr,
497				   param->data[i].len, param->data[i].data)) {
498			printk(KERN_WARNING "%s: RAM download at 0x%08x "
499			       "(len=%d) failed\n", dev->name,
500			       param->data[i].addr, param->data[i].len);
501			ret = -EIO;
502			goto out;
503		}
504	}
505
506	PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
507	local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
508	if (prism2_enable_aux_port(dev, 0)) {
509		printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
510		       dev->name);
511	}
512
513	mdelay(5);
514	local->hw_downloading = 0;
515
516	PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
517	/*
518	 * Make sure the INIT command does not generate a command completion
519	 * event by disabling interrupts.
520	 */
521	hfa384x_disable_interrupts(dev);
522	if (prism2_hw_init(dev, 1)) {
523		printk(KERN_DEBUG "%s: Initialization after genesis mode "
524		       "download failed\n", dev->name);
525		ret = -EIO;
526		goto out;
527	}
528
529	PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
530	if (prism2_hw_init2(dev, 1)) {
531		printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
532		       "download failed\n", dev->name);
533		ret = -EIO;
534		goto out;
535	}
536
537 out:
538	local->hw_downloading = 0;
539	return ret;
540}
541
542
543#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
544/* Note! Non-volatile downloading functionality has not yet been tested
545 * thoroughly and it may corrupt flash image and effectively kill the card that
546 * is being updated. You have been warned. */
547
548static inline int prism2_download_block(struct net_device *dev,
549					u32 addr, u8 *data,
550					u32 bufaddr, int rest_len)
551{
552	u16 param0, param1;
553	int block_len;
554
555	block_len = rest_len < 4096 ? rest_len : 4096;
556
557	param0 = addr & 0xffff;
558	param1 = addr >> 16;
559
560	HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
561	HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
562
563	if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
564			     (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
565			     param0)) {
566		printk(KERN_WARNING "%s: Flash download command execution "
567		       "failed\n", dev->name);
568		return -1;
569	}
570
571	if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
572		printk(KERN_WARNING "%s: flash download at 0x%08x "
573		       "(len=%d) failed\n", dev->name, addr, block_len);
574		return -1;
575	}
576
577	HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
578	HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
579	if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
580			     (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
581			     0)) {
582		printk(KERN_WARNING "%s: Flash write command execution "
583		       "failed\n", dev->name);
584		return -1;
585	}
586
587	return block_len;
588}
589
590
591static int prism2_download_nonvolatile(local_info_t *local,
592				       struct prism2_download_data *dl)
593{
594	struct net_device *dev = local->dev;
595	int ret = 0, i;
596	struct {
597		__le16 page;
598		__le16 offset;
599		__le16 len;
600	} dlbuffer;
601	u32 bufaddr;
602
603	if (local->hw_downloading) {
604		printk(KERN_WARNING "%s: Already downloading - aborting new "
605		       "request\n", dev->name);
606		return -1;
607	}
608
609	ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
610				   &dlbuffer, 6, 0);
611
612	if (ret < 0) {
613		printk(KERN_WARNING "%s: Could not read download buffer "
614		       "parameters\n", dev->name);
615		goto out;
616	}
617
618	printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
619	       le16_to_cpu(dlbuffer.len),
620	       le16_to_cpu(dlbuffer.page),
621	       le16_to_cpu(dlbuffer.offset));
622
623	bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
624
625	local->hw_downloading = 1;
626
627	if (!local->pri_only) {
628		prism2_hw_shutdown(dev, 0);
629
630		if (prism2_hw_init(dev, 0)) {
631			printk(KERN_WARNING "%s: Could not initialize card for"
632			       " download\n", dev->name);
633			ret = -1;
634			goto out;
635		}
636	}
637
638	hfa384x_disable_interrupts(dev);
639
640	if (prism2_enable_aux_port(dev, 1)) {
641		printk(KERN_WARNING "%s: Could not enable AUX port\n",
642		       dev->name);
643		ret = -1;
644		goto out;
645	}
646
647	printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
648	for (i = 0; i < dl->num_areas; i++) {
649		int rest_len = dl->data[i].len;
650		int data_off = 0;
651
652		while (rest_len > 0) {
653			int block_len;
654
655			block_len = prism2_download_block(
656				dev, dl->data[i].addr + data_off,
657				dl->data[i].data + data_off, bufaddr,
658				rest_len);
659
660			if (block_len < 0) {
661				ret = -1;
662				goto out;
663			}
664
665			rest_len -= block_len;
666			data_off += block_len;
667		}
668	}
669
670	HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
671	HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
672	if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
673				(HFA384X_PROGMODE_DISABLE << 8), 0)) {
674		printk(KERN_WARNING "%s: Download command execution failed\n",
675		       dev->name);
676		ret = -1;
677		goto out;
678	}
679
680	if (prism2_enable_aux_port(dev, 0)) {
681		printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
682		       dev->name);
683		/* continue anyway.. restart should have taken care of this */
684	}
685
686	mdelay(5);
687
688	local->func->hw_reset(dev);
689	local->hw_downloading = 0;
690	if (prism2_hw_config(dev, 2)) {
691		printk(KERN_WARNING "%s: Card configuration after flash "
692		       "download failed\n", dev->name);
693		ret = -1;
694	} else {
695		printk(KERN_INFO "%s: Card initialized successfully after "
696		       "flash download\n", dev->name);
697	}
698
699 out:
700	local->hw_downloading = 0;
701	return ret;
702}
703#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
704
705
706static void prism2_download_free_data(struct prism2_download_data *dl)
707{
708	int i;
709
710	if (dl == NULL)
711		return;
712
713	for (i = 0; i < dl->num_areas; i++)
714		kfree(dl->data[i].data);
715	kfree(dl);
716}
717
718
719static int prism2_download(local_info_t *local,
720			   struct prism2_download_param *param)
721{
722	int ret = 0;
723	int i;
724	u32 total_len = 0;
725	struct prism2_download_data *dl = NULL;
726
727	printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
728	       "num_areas=%d\n",
729	       param->dl_cmd, param->start_addr, param->num_areas);
730
731	if (param->num_areas > 100) {
732		ret = -EINVAL;
733		goto out;
734	}
735
736	dl = kzalloc(sizeof(*dl) + param->num_areas *
737		     sizeof(struct prism2_download_data_area), GFP_KERNEL);
738	if (dl == NULL) {
739		ret = -ENOMEM;
740		goto out;
741	}
742	dl->dl_cmd = param->dl_cmd;
743	dl->start_addr = param->start_addr;
744	dl->num_areas = param->num_areas;
745	for (i = 0; i < param->num_areas; i++) {
746		PDEBUG(DEBUG_EXTRA2,
747		       "  area %d: addr=0x%08x len=%d ptr=0x%p\n",
748		       i, param->data[i].addr, param->data[i].len,
749		       param->data[i].ptr);
750
751		dl->data[i].addr = param->data[i].addr;
752		dl->data[i].len = param->data[i].len;
753
754		total_len += param->data[i].len;
755		if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
756		    total_len > PRISM2_MAX_DOWNLOAD_LEN) {
757			ret = -E2BIG;
758			goto out;
759		}
760
761		dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
762		if (dl->data[i].data == NULL) {
763			ret = -ENOMEM;
764			goto out;
765		}
766
767		if (copy_from_user(dl->data[i].data, param->data[i].ptr,
768				   param->data[i].len)) {
769			ret = -EFAULT;
770			goto out;
771		}
772	}
773
774	switch (param->dl_cmd) {
775	case PRISM2_DOWNLOAD_VOLATILE:
776	case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
777		ret = prism2_download_volatile(local, dl);
778		break;
779	case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
780	case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
781		ret = prism2_download_genesis(local, dl);
782		break;
783	case PRISM2_DOWNLOAD_NON_VOLATILE:
784#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
785		ret = prism2_download_nonvolatile(local, dl);
786#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
787		printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
788		       local->dev->name);
789		ret = -EOPNOTSUPP;
790#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
791		break;
792	default:
793		printk(KERN_DEBUG "%s: unsupported download command %d\n",
794		       local->dev->name, param->dl_cmd);
795		ret = -EINVAL;
796		break;
797	}
798
799 out:
800	if (ret == 0 && dl &&
801	    param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
802		prism2_download_free_data(local->dl_pri);
803		local->dl_pri = dl;
804	} else if (ret == 0 && dl &&
805		   param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
806		prism2_download_free_data(local->dl_sec);
807		local->dl_sec = dl;
808	} else
809		prism2_download_free_data(dl);
810
811	return ret;
812}