1#include "headers.h"
2
3int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
4{
5	/* unsigned int reg = 0; */
6	mm_segment_t oldfs = {0};
7	int errno = 0, len = 0; /* ,is_config_file = 0 */
8	loff_t pos = 0;
9	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
10	/* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */
11	char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
12
13	if (!buff)
14		return -ENOMEM;
15
16	while (1) {
17		oldfs = get_fs();
18		set_fs(get_ds());
19		len = vfs_read(flp, (void __force __user *)buff,
20			MAX_TRANSFER_CTRL_BYTE_USB, &pos);
21		set_fs(oldfs);
22		if (len <= 0) {
23			if (len < 0) {
24				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
25						DBG_TYPE_INITEXIT, MP_INIT,
26						DBG_LVL_ALL, "len < 0");
27				errno = len;
28			} else {
29				errno = 0;
30				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
31						DBG_TYPE_INITEXIT, MP_INIT,
32						DBG_LVL_ALL,
33						"Got end of file!");
34			}
35			break;
36		}
37		/* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
38		 *			  DBG_LVL_ALL, buff,
39		 *			  MAX_TRANSFER_CTRL_BYTE_USB);
40		 */
41		errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
42		if (errno) {
43			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
44					DBG_TYPE_PRINTK, 0, 0,
45					"WRM Failed! status: %d", errno);
46			break;
47		}
48		on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
49	}
50
51	kfree(buff);
52	return errno;
53}
54
55int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
56{
57	char *buff, *buff_readback;
58	unsigned int reg = 0;
59	mm_segment_t oldfs = {0};
60	int errno = 0, len = 0, is_config_file = 0;
61	loff_t pos = 0;
62	static int fw_down;
63	INT Status = STATUS_SUCCESS;
64	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
65	int bytes;
66
67	buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
68	buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
69	if (!buff || !buff_readback) {
70		kfree(buff);
71		kfree(buff_readback);
72
73		return -ENOMEM;
74	}
75
76	is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
77
78	memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
79	memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
80	while (1) {
81		oldfs = get_fs();
82		set_fs(get_ds());
83		len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
84		set_fs(oldfs);
85		fw_down++;
86
87		if (len <= 0) {
88			if (len < 0) {
89				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
90				errno = len;
91			} else {
92				errno = 0;
93				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
94			}
95			break;
96		}
97
98		bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
99		if (bytes < 0) {
100			Status = bytes;
101			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
102			goto exit;
103		}
104		reg++;
105		if ((len-sizeof(unsigned int)) < 4) {
106			if (memcmp(buff_readback, buff, len)) {
107				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
108				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
109				Status = -EIO;
110				goto exit;
111			}
112		} else {
113			len -= 4;
114
115			while (len) {
116				if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
117					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
118					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
119					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
120					Status = -EIO;
121					goto exit;
122				}
123				len -= 4;
124			}
125		}
126		on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
127	} /* End of while(1) */
128
129exit:
130	kfree(buff);
131	kfree(buff_readback);
132	return Status;
133}
134
135static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
136{
137	int retval = STATUS_SUCCESS;
138	B_UINT32 value = 0;
139
140	if (Adapter->pstargetparams == NULL) {
141		Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
142		if (Adapter->pstargetparams == NULL)
143			return -ENOMEM;
144	}
145
146	if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
147		return -EIO;
148
149	retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
150	if (retval) {
151		kfree(Adapter->pstargetparams);
152		Adapter->pstargetparams = NULL;
153		return -EFAULT;
154	}
155
156	/* Parse the structure and then Download the Firmware */
157	beceem_parse_target_struct(Adapter);
158
159	/* Initializing the NVM. */
160	BcmInitNVM(Adapter);
161	retval = InitLedSettings(Adapter);
162
163	if (retval) {
164		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
165		return retval;
166	}
167
168	if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
169		Adapter->LEDInfo.bLedInitDone = FALSE;
170		Adapter->DriverState = DRIVER_INIT;
171		wake_up(&Adapter->LEDInfo.notify_led_event);
172	}
173
174	if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
175		Adapter->DriverState = FW_DOWNLOAD;
176		wake_up(&Adapter->LEDInfo.notify_led_event);
177	}
178
179	/* Initialize the DDR Controller */
180	retval = ddr_init(Adapter);
181	if (retval) {
182		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
183		return retval;
184	}
185
186	value = 0;
187	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
188	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
189
190	if (Adapter->eNVMType == NVM_FLASH) {
191		retval = PropagateCalParamsFromFlashToMemory(Adapter);
192		if (retval) {
193			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
194			return retval;
195		}
196	}
197
198	retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR);
199
200	if (retval)
201		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
202	else
203		Adapter->bCfgDownloaded = TRUE;
204
205	return retval;
206}
207
208static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
209{
210	int retval = STATUS_SUCCESS;
211	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
212	if ((len-sizeof(unsigned int)) < 4) {
213		if (memcmp(readbackbuff , buff, len))
214			retval = -EINVAL;
215	} else {
216		len -= 4;
217
218		while (len) {
219			if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
220				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
221				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
222				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
223				retval = -EINVAL;
224				break;
225			}
226			len -= 4;
227		}
228	}
229	return retval;
230}
231
232int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
233{
234	int retval = STATUS_SUCCESS;
235	PUCHAR buff = NULL;
236
237	/* Config File is needed for the Driver to download the Config file and
238	 * Firmware. Check for the Config file to be first to be sent from the
239	 * Application
240	 */
241	atomic_set(&Adapter->uiMBupdate, FALSE);
242	if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
243		/* Can't Download Firmware. */
244		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
245		return -EINVAL;
246	}
247
248	/* If Config File, Finish the DDR Settings and then Download CFG File */
249	if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
250		retval = bcm_download_config_file(Adapter, psFwInfo);
251	} else {
252		buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
253		if (buff == NULL) {
254			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
255			return -ENOMEM;
256		}
257
258		retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
259		if (retval != STATUS_SUCCESS) {
260			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
261			retval = -EFAULT;
262			goto error;
263		}
264
265		retval = buffDnldVerify(Adapter,
266					buff,
267					psFwInfo->u32FirmwareLength,
268					psFwInfo->u32StartingAddress);
269
270		if (retval != STATUS_SUCCESS) {
271			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
272			goto error;
273		}
274	}
275
276error:
277	kfree(buff);
278	return retval;
279}
280
281static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
282{
283	unsigned int len = 0;
284	int retval = STATUS_SUCCESS;
285	len = u32FirmwareLength;
286
287	while (u32FirmwareLength) {
288		len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
289		retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
290
291		if (retval) {
292			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
293			break;
294		}
295		u32StartingAddress += len;
296		u32FirmwareLength -= len;
297		mappedbuffer += len;
298	}
299	return retval;
300}
301
302static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
303{
304	UINT len = u32FirmwareLength;
305	INT retval = STATUS_SUCCESS;
306	PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
307	int bytes;
308
309	if (NULL == readbackbuff) {
310		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
311		return -ENOMEM;
312	}
313
314	while (u32FirmwareLength && !retval) {
315		len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
316		bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
317
318		if (bytes < 0) {
319			retval = bytes;
320			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
321			break;
322		}
323
324		retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
325		if (STATUS_SUCCESS != retval)
326			break;
327
328		u32StartingAddress += len;
329		u32FirmwareLength -= len;
330		mappedbuffer += len;
331
332	} /* end of while (u32FirmwareLength && !retval) */
333	kfree(readbackbuff);
334	return retval;
335}
336
337INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
338{
339	INT status = STATUS_SUCCESS;
340
341	status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
342	if (status != STATUS_SUCCESS) {
343		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
344		goto error;
345	}
346
347	status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
348	if (status != STATUS_SUCCESS) {
349		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
350		goto error;
351	}
352error:
353	return status;
354}
355