cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hostap_download.c (20011B)


      1// SPDX-License-Identifier: GPL-2.0
      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	{
    104		__le16 *pos = (__le16 *) buf;
    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	{
    135		__le16 *pos = (__le16 *) buf;
    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{
    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			/* PDA end found */
    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
    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;
    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
    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 proc_ops prism2_download_aux_dump_proc_ops = {
    236	.proc_open		= prism2_download_aux_dump_proc_open,
    237	.proc_read		= seq_read,
    238	.proc_lseek		= seq_lseek,
    239	.proc_release		= seq_release_private,
    240};
    241
    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
    255	buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
    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 write %4ph read %4ph\n",
    411		       hcr, initseq, readbuf);
    412		return 1;
    413	}
    414}
    415
    416
    417static int prism2_get_ram_size(local_info_t *local)
    418{
    419	int ret;
    420
    421	/* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
    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	/* Disable genesis mode */
    430	local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
    431
    432	return ret;
    433}
    434
    435
    436static 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		/* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
    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	 * Make sure the INIT command does not generate a command completion
    518	 * event by disabling interrupts.
    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/* Note! Non-volatile downloading functionality has not yet been tested
    544 * thoroughly and it may corrupt flash image and effectively kill the card that
    545 * is being updated. You have been warned. */
    546
    547static 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
    590static 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		/* continue anyway.. restart should have taken care of this */
    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 /* PRISM2_NON_VOLATILE_DOWNLOAD */
    703
    704
    705static 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
    718static 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 /* PRISM2_NON_VOLATILE_DOWNLOAD */
    786		printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
    787		       local->dev->name);
    788		ret = -EOPNOTSUPP;
    789#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
    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}