1#include <linux/fs.h>
2
3#include "headers.h"
4
5static int bcm_handle_nvm_read_cmd(struct bcm_mini_adapter *ad,
6				   PUCHAR read_data,
7				   struct bcm_nvm_readwrite *nvm_rw)
8{
9	INT status = STATUS_FAILURE;
10
11	down(&ad->NVMRdmWrmLock);
12
13	if ((ad->IdleMode == TRUE) || (ad->bShutStatus == TRUE) ||
14			(ad->bPreparingForLowPowerMode == TRUE)) {
15
16		BCM_DEBUG_PRINT(ad,
17			DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
18			"Device is in Idle/Shutdown Mode\n");
19		up(&ad->NVMRdmWrmLock);
20		kfree(read_data);
21		return -EACCES;
22	}
23
24	status = BeceemNVMRead(ad, (PUINT)read_data,
25			       nvm_rw->uiOffset,
26			       nvm_rw->uiNumBytes);
27	up(&ad->NVMRdmWrmLock);
28
29	if (status != STATUS_SUCCESS) {
30		kfree(read_data);
31		return status;
32	}
33
34	if (copy_to_user(nvm_rw->pBuffer, read_data, nvm_rw->uiNumBytes)) {
35		kfree(read_data);
36		return -EFAULT;
37	}
38
39	return STATUS_SUCCESS;
40}
41
42static int handle_flash2x_adapter(struct bcm_mini_adapter *ad,
43				  PUCHAR read_data,
44				  struct bcm_nvm_readwrite *nvm_rw)
45{
46	/*
47	 * New Requirement:-
48	 * DSD section updation will be allowed in two case:-
49	 * 1.  if DSD sig is present in DSD header means dongle
50	 * is ok and updation is fruitfull
51	 * 2.  if point 1 failes then user buff should have
52	 * DSD sig. this point ensures that if dongle is
53	 * corrupted then user space program first modify
54	 * the DSD header with valid DSD sig so that this
55	 * as well as further write may be worthwhile.
56	 *
57	 * This restriction has been put assuming that
58	 * if DSD sig is corrupted, DSD data won't be
59	 * considered valid.
60	 */
61	INT status;
62	ULONG dsd_magic_num_in_usr_buff = 0;
63
64	status = BcmFlash2xCorruptSig(ad, ad->eActiveDSD);
65	if (status == STATUS_SUCCESS)
66		return STATUS_SUCCESS;
67
68	if (((nvm_rw->uiOffset + nvm_rw->uiNumBytes) !=
69			ad->uiNVMDSDSize) ||
70			(nvm_rw->uiNumBytes < SIGNATURE_SIZE)) {
71
72		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
73				"DSD Sig is present neither in Flash nor User provided Input..");
74		up(&ad->NVMRdmWrmLock);
75		kfree(read_data);
76		return status;
77	}
78
79	dsd_magic_num_in_usr_buff =
80		ntohl(*(PUINT)(read_data + nvm_rw->uiNumBytes -
81		      SIGNATURE_SIZE));
82	if (dsd_magic_num_in_usr_buff != DSD_IMAGE_MAGIC_NUMBER) {
83		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
84				"DSD Sig is present neither in Flash nor User provided Input..");
85		up(&ad->NVMRdmWrmLock);
86		kfree(read_data);
87		return status;
88	}
89
90	return STATUS_SUCCESS;
91}
92
93/***************************************************************
94* Function	  - bcm_char_open()
95*
96* Description - This is the "open" entry point for the character
97*				driver.
98*
99* Parameters  - inode: Pointer to the Inode structure of char device
100*				filp : File pointer of the char device
101*
102* Returns	  - Zero(Success)
103****************************************************************/
104
105static int bcm_char_open(struct inode *inode, struct file *filp)
106{
107	struct bcm_mini_adapter *ad = NULL;
108	struct bcm_tarang_data *tarang = NULL;
109
110	ad = GET_BCM_ADAPTER(gblpnetdev);
111	tarang = kzalloc(sizeof(struct bcm_tarang_data), GFP_KERNEL);
112	if (!tarang)
113		return -ENOMEM;
114
115	tarang->Adapter = ad;
116	tarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
117
118	down(&ad->RxAppControlQueuelock);
119	tarang->next = ad->pTarangs;
120	ad->pTarangs = tarang;
121	up(&ad->RxAppControlQueuelock);
122
123	/* Store the Adapter structure */
124	filp->private_data = tarang;
125
126	/* Start Queuing the control response Packets */
127	atomic_inc(&ad->ApplicationRunning);
128
129	nonseekable_open(inode, filp);
130	return 0;
131}
132
133static int bcm_char_release(struct inode *inode, struct file *filp)
134{
135	struct bcm_tarang_data *tarang, *tmp, *ptmp;
136	struct bcm_mini_adapter *ad = NULL;
137	struct sk_buff *pkt, *npkt;
138
139	tarang = (struct bcm_tarang_data *)filp->private_data;
140
141	if (tarang == NULL)
142		return 0;
143
144	ad = tarang->Adapter;
145
146	down(&ad->RxAppControlQueuelock);
147
148	tmp = ad->pTarangs;
149	for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
150		if (tmp == tarang)
151			break;
152	}
153
154	if (tmp) {
155		if (!ptmp)
156			ad->pTarangs = tmp->next;
157		else
158			ptmp->next = tmp->next;
159	} else {
160		up(&ad->RxAppControlQueuelock);
161		return 0;
162	}
163
164	pkt = tarang->RxAppControlHead;
165	while (pkt) {
166		npkt = pkt->next;
167		kfree_skb(pkt);
168		pkt = npkt;
169	}
170
171	up(&ad->RxAppControlQueuelock);
172
173	/* Stop Queuing the control response Packets */
174	atomic_dec(&ad->ApplicationRunning);
175
176	kfree(tarang);
177
178	/* remove this filp from the asynchronously notified filp's */
179	filp->private_data = NULL;
180	return 0;
181}
182
183static ssize_t bcm_char_read(struct file *filp,
184			     char __user *buf,
185			     size_t size,
186			     loff_t *f_pos)
187{
188	struct bcm_tarang_data *tarang = filp->private_data;
189	struct bcm_mini_adapter *ad = tarang->Adapter;
190	struct sk_buff *packet = NULL;
191	ssize_t pkt_len = 0;
192	int wait_ret_val = 0;
193	unsigned long ret = 0;
194
195	wait_ret_val = wait_event_interruptible(
196				ad->process_read_wait_queue,
197				(tarang->RxAppControlHead ||
198				ad->device_removed));
199
200	if ((wait_ret_val == -ERESTARTSYS)) {
201		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
202				"Exiting as i've been asked to exit!!!\n");
203		return wait_ret_val;
204	}
205
206	if (ad->device_removed) {
207		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
208				"Device Removed... Killing the Apps...\n");
209		return -ENODEV;
210	}
211
212	if (false == ad->fw_download_done)
213		return -EACCES;
214
215	down(&ad->RxAppControlQueuelock);
216
217	if (tarang->RxAppControlHead) {
218		packet = tarang->RxAppControlHead;
219		DEQUEUEPACKET(tarang->RxAppControlHead,
220			      tarang->RxAppControlTail);
221		tarang->AppCtrlQueueLen--;
222	}
223
224	up(&ad->RxAppControlQueuelock);
225
226	if (packet) {
227		pkt_len = packet->len;
228		ret = copy_to_user(buf, packet->data,
229				   min_t(size_t, pkt_len, size));
230		if (ret) {
231			dev_kfree_skb(packet);
232			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
233					"Returning from copy to user failure\n");
234			return -EFAULT;
235		}
236		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
237				"Read %zd Bytes From Adapter packet = %p by process %d!\n",
238				pkt_len, packet, current->pid);
239		dev_kfree_skb(packet);
240	}
241
242	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
243	return pkt_len;
244}
245
246static int bcm_char_ioctl_reg_read_private(void __user *argp,
247					   struct bcm_mini_adapter *ad)
248{
249	struct bcm_rdm_buffer rdm_buff = {0};
250	struct bcm_ioctl_buffer io_buff;
251	PCHAR temp_buff;
252	INT status = STATUS_FAILURE;
253	UINT buff_len;
254	u16 temp_value;
255	int bytes;
256
257	/* Copy Ioctl Buffer structure */
258	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
259		return -EFAULT;
260
261	if (io_buff.InputLength > sizeof(rdm_buff))
262		return -EINVAL;
263
264	if (copy_from_user(&rdm_buff, io_buff.InputBuffer,
265		io_buff.InputLength))
266		return -EFAULT;
267
268	if (io_buff.OutputLength > USHRT_MAX ||
269		io_buff.OutputLength == 0) {
270		return -EINVAL;
271	}
272
273	buff_len = io_buff.OutputLength;
274	temp_value = 4 - (buff_len % 4);
275	buff_len += temp_value % 4;
276
277	temp_buff = kmalloc(buff_len, GFP_KERNEL);
278	if (!temp_buff)
279		return -ENOMEM;
280
281	bytes = rdmalt(ad, (UINT)rdm_buff.Register,
282			(PUINT)temp_buff, buff_len);
283	if (bytes > 0) {
284		status = STATUS_SUCCESS;
285		if (copy_to_user(io_buff.OutputBuffer, temp_buff, bytes)) {
286			kfree(temp_buff);
287			return -EFAULT;
288		}
289	} else {
290		status = bytes;
291	}
292
293	kfree(temp_buff);
294	return status;
295}
296
297static int bcm_char_ioctl_reg_write_private(void __user *argp,
298					    struct bcm_mini_adapter *ad)
299{
300	struct bcm_wrm_buffer wrm_buff = {0};
301	struct bcm_ioctl_buffer io_buff;
302	UINT tmp = 0;
303	INT status;
304
305	/* Copy Ioctl Buffer structure */
306
307	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
308		return -EFAULT;
309
310	if (io_buff.InputLength > sizeof(wrm_buff))
311		return -EINVAL;
312
313	/* Get WrmBuffer structure */
314	if (copy_from_user(&wrm_buff, io_buff.InputBuffer,
315		io_buff.InputLength))
316		return -EFAULT;
317
318	tmp = wrm_buff.Register & EEPROM_REJECT_MASK;
319	if (!((ad->pstargetparams->m_u32Customize) & VSG_MODE) &&
320		((tmp == EEPROM_REJECT_REG_1) ||
321			(tmp == EEPROM_REJECT_REG_2) ||
322			(tmp == EEPROM_REJECT_REG_3) ||
323			(tmp == EEPROM_REJECT_REG_4))) {
324
325		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
326				"EEPROM Access Denied, not in VSG Mode\n");
327		return -EFAULT;
328	}
329
330	status = wrmalt(ad, (UINT)wrm_buff.Register,
331			(PUINT)wrm_buff.Data, sizeof(ULONG));
332
333	if (status == STATUS_SUCCESS) {
334		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
335				DBG_LVL_ALL, "WRM Done\n");
336	} else {
337		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
338				DBG_LVL_ALL, "WRM Failed\n");
339		status = -EFAULT;
340	}
341	return status;
342}
343
344static int bcm_char_ioctl_eeprom_reg_read(void __user *argp,
345					  struct bcm_mini_adapter *ad)
346{
347	struct bcm_rdm_buffer rdm_buff = {0};
348	struct bcm_ioctl_buffer io_buff;
349	PCHAR temp_buff = NULL;
350	UINT tmp = 0;
351	INT status;
352	int bytes;
353
354	if ((ad->IdleMode == TRUE) ||
355		(ad->bShutStatus == TRUE) ||
356		(ad->bPreparingForLowPowerMode == TRUE)) {
357
358		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
359				"Device in Idle Mode, Blocking Rdms\n");
360		return -EACCES;
361	}
362
363	/* Copy Ioctl Buffer structure */
364	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
365		return -EFAULT;
366
367	if (io_buff.InputLength > sizeof(rdm_buff))
368		return -EINVAL;
369
370	if (copy_from_user(&rdm_buff, io_buff.InputBuffer,
371		io_buff.InputLength))
372		return -EFAULT;
373
374	if (io_buff.OutputLength > USHRT_MAX ||
375		io_buff.OutputLength == 0) {
376		return -EINVAL;
377	}
378
379	temp_buff = kmalloc(io_buff.OutputLength, GFP_KERNEL);
380	if (!temp_buff)
381		return STATUS_FAILURE;
382
383	if ((((ULONG)rdm_buff.Register & 0x0F000000) != 0x0F000000) ||
384		((ULONG)rdm_buff.Register & 0x3)) {
385
386		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
387				"RDM Done On invalid Address : %x Access Denied.\n",
388				(int)rdm_buff.Register);
389
390		kfree(temp_buff);
391		return -EINVAL;
392	}
393
394	tmp = rdm_buff.Register & EEPROM_REJECT_MASK;
395	bytes = rdmaltWithLock(ad, (UINT)rdm_buff.Register,
396			       (PUINT)temp_buff, io_buff.OutputLength);
397
398	if (bytes > 0) {
399		status = STATUS_SUCCESS;
400		if (copy_to_user(io_buff.OutputBuffer, temp_buff, bytes)) {
401			kfree(temp_buff);
402			return -EFAULT;
403		}
404	} else {
405		status = bytes;
406	}
407
408	kfree(temp_buff);
409	return status;
410}
411
412static int bcm_char_ioctl_eeprom_reg_write(void __user *argp,
413					   struct bcm_mini_adapter *ad,
414					   UINT cmd)
415{
416	struct bcm_wrm_buffer wrm_buff = {0};
417	struct bcm_ioctl_buffer io_buff;
418	UINT tmp = 0;
419	INT status;
420
421	if ((ad->IdleMode == TRUE) ||
422		(ad->bShutStatus == TRUE) ||
423		(ad->bPreparingForLowPowerMode == TRUE)) {
424
425		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
426				"Device in Idle Mode, Blocking Wrms\n");
427		return -EACCES;
428	}
429
430	/* Copy Ioctl Buffer structure */
431	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
432		return -EFAULT;
433
434	if (io_buff.InputLength > sizeof(wrm_buff))
435		return -EINVAL;
436
437	/* Get WrmBuffer structure */
438	if (copy_from_user(&wrm_buff, io_buff.InputBuffer,
439		io_buff.InputLength))
440		return -EFAULT;
441
442	if ((((ULONG)wrm_buff.Register & 0x0F000000) != 0x0F000000) ||
443		((ULONG)wrm_buff.Register & 0x3)) {
444
445		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
446				"WRM Done On invalid Address : %x Access Denied.\n",
447				(int)wrm_buff.Register);
448		return -EINVAL;
449	}
450
451	tmp = wrm_buff.Register & EEPROM_REJECT_MASK;
452	if (!((ad->pstargetparams->m_u32Customize) & VSG_MODE) &&
453			((tmp == EEPROM_REJECT_REG_1) ||
454			(tmp == EEPROM_REJECT_REG_2) ||
455			(tmp == EEPROM_REJECT_REG_3) ||
456			(tmp == EEPROM_REJECT_REG_4)) &&
457			(cmd == IOCTL_BCM_REGISTER_WRITE)) {
458
459			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
460					"EEPROM Access Denied, not in VSG Mode\n");
461			return -EFAULT;
462	}
463
464	status = wrmaltWithLock(ad, (UINT)wrm_buff.Register,
465				(PUINT)wrm_buff.Data,
466				wrm_buff.Length);
467
468	if (status == STATUS_SUCCESS) {
469		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, OSAL_DBG,
470				DBG_LVL_ALL, "WRM Done\n");
471	} else {
472		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
473				DBG_LVL_ALL, "WRM Failed\n");
474		status = -EFAULT;
475	}
476	return status;
477}
478
479static int bcm_char_ioctl_gpio_set_request(void __user *argp,
480					   struct bcm_mini_adapter *ad)
481{
482	struct bcm_gpio_info gpio_info = {0};
483	struct bcm_ioctl_buffer io_buff;
484	UCHAR reset_val[4];
485	UINT value = 0;
486	UINT bit = 0;
487	UINT operation = 0;
488	INT status;
489	int bytes;
490
491	if ((ad->IdleMode == TRUE) ||
492		(ad->bShutStatus == TRUE) ||
493		(ad->bPreparingForLowPowerMode == TRUE)) {
494
495		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
496				DBG_LVL_ALL,
497				"GPIO Can't be set/clear in Low power Mode");
498		return -EACCES;
499	}
500
501	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
502		return -EFAULT;
503
504	if (io_buff.InputLength > sizeof(gpio_info))
505		return -EINVAL;
506
507	if (copy_from_user(&gpio_info, io_buff.InputBuffer,
508			   io_buff.InputLength))
509		return -EFAULT;
510
511	bit  = gpio_info.uiGpioNumber;
512	operation = gpio_info.uiGpioValue;
513	value = (1<<bit);
514
515	if (IsReqGpioIsLedInNVM(ad, value) == false) {
516		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
517				DBG_LVL_ALL,
518				"Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",
519				value);
520		return -EINVAL;
521	}
522
523	/* Set - setting 1 */
524	if (operation) {
525		/* Set the gpio output register */
526		status = wrmaltWithLock(ad,
527					BCM_GPIO_OUTPUT_SET_REG,
528					(PUINT)(&value), sizeof(UINT));
529
530		if (status == STATUS_SUCCESS) {
531			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
532					OSAL_DBG, DBG_LVL_ALL,
533					"Set the GPIO bit\n");
534		} else {
535			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
536					OSAL_DBG, DBG_LVL_ALL,
537					"Failed to set the %dth GPIO\n",
538					bit);
539			return status;
540		}
541	} else {
542		/* Set the gpio output register */
543		status = wrmaltWithLock(ad,
544					BCM_GPIO_OUTPUT_CLR_REG,
545					(PUINT)(&value), sizeof(UINT));
546
547		if (status == STATUS_SUCCESS) {
548			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
549					OSAL_DBG, DBG_LVL_ALL,
550					"Set the GPIO bit\n");
551		} else {
552			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
553					OSAL_DBG, DBG_LVL_ALL,
554					"Failed to clear the %dth GPIO\n",
555					bit);
556			return status;
557		}
558	}
559
560	bytes = rdmaltWithLock(ad, (UINT)GPIO_MODE_REGISTER,
561			       (PUINT)reset_val, sizeof(UINT));
562	if (bytes < 0) {
563		status = bytes;
564		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
565				"GPIO_MODE_REGISTER read failed");
566		return status;
567	}
568	status = STATUS_SUCCESS;
569
570	/* Set the gpio mode register to output */
571	*(UINT *)reset_val |= (1<<bit);
572	status = wrmaltWithLock(ad, GPIO_MODE_REGISTER,
573				(PUINT)reset_val, sizeof(UINT));
574
575	if (status == STATUS_SUCCESS) {
576		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
577				DBG_LVL_ALL,
578				"Set the GPIO to output Mode\n");
579	} else {
580		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
581				DBG_LVL_ALL,
582				"Failed to put GPIO in Output Mode\n");
583	}
584
585	return status;
586}
587
588static int bcm_char_ioctl_led_thread_state_change_req(void __user *argp,
589		struct bcm_mini_adapter *ad)
590{
591	struct bcm_user_thread_req thread_req = {0};
592	struct bcm_ioctl_buffer io_buff;
593
594	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
595			"User made LED thread InActive");
596
597	if ((ad->IdleMode == TRUE) ||
598		(ad->bShutStatus == TRUE) ||
599		(ad->bPreparingForLowPowerMode == TRUE)) {
600
601		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
602				DBG_LVL_ALL,
603				"GPIO Can't be set/clear in Low power Mode");
604		return -EACCES;
605	}
606
607	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
608		return -EFAULT;
609
610	if (io_buff.InputLength > sizeof(thread_req))
611		return -EINVAL;
612
613	if (copy_from_user(&thread_req, io_buff.InputBuffer,
614			   io_buff.InputLength))
615		return -EFAULT;
616
617	/* if LED thread is running(Actively or Inactively)
618	 * set it state to make inactive
619	 */
620	if (ad->LEDInfo.led_thread_running) {
621		if (thread_req.ThreadState == LED_THREAD_ACTIVATION_REQ) {
622			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
623					OSAL_DBG, DBG_LVL_ALL,
624					"Activating thread req");
625			ad->DriverState = LED_THREAD_ACTIVE;
626		} else {
627			BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
628					OSAL_DBG, DBG_LVL_ALL,
629					"DeActivating Thread req.....");
630			ad->DriverState = LED_THREAD_INACTIVE;
631		}
632
633		/* signal thread. */
634		wake_up(&ad->LEDInfo.notify_led_event);
635	}
636	return STATUS_SUCCESS;
637}
638
639static int bcm_char_ioctl_gpio_status_request(void __user *argp,
640					      struct bcm_mini_adapter *ad)
641{
642	struct bcm_gpio_info gpio_info = {0};
643	struct bcm_ioctl_buffer io_buff;
644	ULONG bit = 0;
645	UCHAR read[4];
646	INT status;
647	int bytes;
648
649	if ((ad->IdleMode == TRUE) ||
650		(ad->bShutStatus == TRUE) ||
651		(ad->bPreparingForLowPowerMode == TRUE))
652		return -EACCES;
653
654	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
655		return -EFAULT;
656
657	if (io_buff.InputLength > sizeof(gpio_info))
658		return -EINVAL;
659
660	if (copy_from_user(&gpio_info, io_buff.InputBuffer,
661		io_buff.InputLength))
662		return -EFAULT;
663
664	bit = gpio_info.uiGpioNumber;
665
666	/* Set the gpio output register */
667	bytes = rdmaltWithLock(ad, (UINT)GPIO_PIN_STATE_REGISTER,
668				(PUINT)read, sizeof(UINT));
669
670	if (bytes < 0) {
671		status = bytes;
672		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
673				"RDM Failed\n");
674		return status;
675	}
676	status = STATUS_SUCCESS;
677	return status;
678}
679
680static int bcm_char_ioctl_gpio_multi_request(void __user *argp,
681					     struct bcm_mini_adapter *ad)
682{
683	struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
684	struct bcm_gpio_multi_info *pgpio_multi_info =
685		(struct bcm_gpio_multi_info *)gpio_multi_info;
686	struct bcm_ioctl_buffer io_buff;
687	UCHAR reset_val[4];
688	INT status = STATUS_FAILURE;
689	int bytes;
690
691	memset(pgpio_multi_info, 0,
692	       MAX_IDX * sizeof(struct bcm_gpio_multi_info));
693
694	if ((ad->IdleMode == TRUE) ||
695		(ad->bShutStatus == TRUE) ||
696		(ad->bPreparingForLowPowerMode == TRUE))
697		return -EINVAL;
698
699	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
700		return -EFAULT;
701
702	if (io_buff.InputLength > sizeof(gpio_multi_info))
703		return -EINVAL;
704	if (io_buff.OutputLength > sizeof(gpio_multi_info))
705		io_buff.OutputLength = sizeof(gpio_multi_info);
706
707	if (copy_from_user(&gpio_multi_info, io_buff.InputBuffer,
708			   io_buff.InputLength))
709		return -EFAULT;
710
711	if (IsReqGpioIsLedInNVM(ad, pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
712			== false) {
713		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
714				DBG_LVL_ALL,
715				"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
716				pgpio_multi_info[WIMAX_IDX].uiGPIOMask,
717				ad->gpioBitMap);
718		return -EINVAL;
719	}
720
721	/* Set the gpio output register */
722	if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
723		(pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
724		/* Set 1's in GPIO OUTPUT REGISTER */
725		*(UINT *)reset_val = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
726			pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
727			pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
728
729		if (*(UINT *) reset_val)
730			status = wrmaltWithLock(ad,
731				BCM_GPIO_OUTPUT_SET_REG,
732				(PUINT)reset_val, sizeof(ULONG));
733
734		if (status != STATUS_SUCCESS) {
735			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
736				"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
737			return status;
738		}
739
740		/* Clear to 0's in GPIO OUTPUT REGISTER */
741		*(UINT *)reset_val =
742			(pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
743			pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
744			(~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
745
746		if (*(UINT *) reset_val)
747			status = wrmaltWithLock(ad,
748				BCM_GPIO_OUTPUT_CLR_REG, (PUINT)reset_val,
749				sizeof(ULONG));
750
751		if (status != STATUS_SUCCESS) {
752			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
753					"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
754			return status;
755		}
756	}
757
758	if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
759		bytes = rdmaltWithLock(ad, (UINT)GPIO_PIN_STATE_REGISTER,
760				       (PUINT)reset_val, sizeof(UINT));
761
762		if (bytes < 0) {
763			status = bytes;
764			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
765					"RDM to GPIO_PIN_STATE_REGISTER Failed.");
766			return status;
767		}
768		status = STATUS_SUCCESS;
769
770		pgpio_multi_info[WIMAX_IDX].uiGPIOValue =
771			(*(UINT *)reset_val &
772			pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
773	}
774
775	status = copy_to_user(io_buff.OutputBuffer, &gpio_multi_info,
776		io_buff.OutputLength);
777	if (status) {
778		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
779			"Failed while copying Content to IOBufer for user space err:%d",
780			status);
781		return -EFAULT;
782	}
783	return status;
784}
785
786static int bcm_char_ioctl_gpio_mode_request(void __user *argp,
787					    struct bcm_mini_adapter *ad)
788{
789	struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
790	struct bcm_gpio_multi_mode *pgpio_multi_mode =
791		(struct bcm_gpio_multi_mode *)gpio_multi_mode;
792	struct bcm_ioctl_buffer io_buff;
793	UCHAR reset_val[4];
794	INT status;
795	int bytes;
796
797	if ((ad->IdleMode == TRUE) ||
798		(ad->bShutStatus == TRUE) ||
799		(ad->bPreparingForLowPowerMode == TRUE))
800		return -EINVAL;
801
802	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
803		return -EFAULT;
804
805	if (io_buff.InputLength > sizeof(gpio_multi_mode))
806		return -EINVAL;
807	if (io_buff.OutputLength > sizeof(gpio_multi_mode))
808		io_buff.OutputLength = sizeof(gpio_multi_mode);
809
810	if (copy_from_user(&gpio_multi_mode, io_buff.InputBuffer,
811		io_buff.InputLength))
812		return -EFAULT;
813
814	bytes = rdmaltWithLock(ad, (UINT)GPIO_MODE_REGISTER,
815		(PUINT)reset_val, sizeof(UINT));
816
817	if (bytes < 0) {
818		status = bytes;
819		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
820			"Read of GPIO_MODE_REGISTER failed");
821		return status;
822	}
823	status = STATUS_SUCCESS;
824
825	/* Validating the request */
826	if (IsReqGpioIsLedInNVM(ad, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
827			== false) {
828		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
829				"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
830				pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,
831				ad->gpioBitMap);
832		return -EINVAL;
833	}
834
835	if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
836		/* write all OUT's (1's) */
837		*(UINT *) reset_val |=
838			(pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
839					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
840
841		/* write all IN's (0's) */
842		*(UINT *) reset_val &=
843			~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
844					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
845
846		/* Currently implemented return the modes of all GPIO's
847		 * else needs to bit AND with  mask
848		 */
849		pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)reset_val;
850
851		status = wrmaltWithLock(ad, GPIO_MODE_REGISTER,
852			(PUINT)reset_val, sizeof(ULONG));
853		if (status == STATUS_SUCCESS) {
854			BCM_DEBUG_PRINT(ad,
855				DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
856				"WRM to GPIO_MODE_REGISTER Done");
857		} else {
858			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
859					"WRM to GPIO_MODE_REGISTER Failed");
860			return -EFAULT;
861		}
862	} else {
863		/* if uiGPIOMask is 0 then return mode register configuration */
864		pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)reset_val;
865	}
866
867	status = copy_to_user(io_buff.OutputBuffer, &gpio_multi_mode,
868		io_buff.OutputLength);
869	if (status) {
870		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
871			"Failed while copying Content to IOBufer for user space err:%d",
872			status);
873		return -EFAULT;
874	}
875	return status;
876}
877
878static int bcm_char_ioctl_misc_request(void __user *argp,
879				       struct bcm_mini_adapter *ad)
880{
881	struct bcm_ioctl_buffer io_buff;
882	PVOID buff = NULL;
883	INT status;
884
885	/* Copy Ioctl Buffer structure */
886	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
887		return -EFAULT;
888
889	if (io_buff.InputLength < sizeof(struct bcm_link_request))
890		return -EINVAL;
891
892	if (io_buff.InputLength > MAX_CNTL_PKT_SIZE)
893		return -EINVAL;
894
895	buff = memdup_user(io_buff.InputBuffer,
896			       io_buff.InputLength);
897	if (IS_ERR(buff))
898		return PTR_ERR(buff);
899
900	down(&ad->LowPowerModeSync);
901	status = wait_event_interruptible_timeout(
902			ad->lowpower_mode_wait_queue,
903			!ad->bPreparingForLowPowerMode,
904			(1 * HZ));
905
906	if (status == -ERESTARTSYS)
907		goto cntrlEnd;
908
909	if (ad->bPreparingForLowPowerMode) {
910		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
911				"Preparing Idle Mode is still True - Hence Rejecting control message\n");
912		status = STATUS_FAILURE;
913		goto cntrlEnd;
914	}
915	status = CopyBufferToControlPacket(ad, (PVOID)buff);
916
917cntrlEnd:
918	up(&ad->LowPowerModeSync);
919	kfree(buff);
920	return status;
921}
922
923static int bcm_char_ioctl_buffer_download_start(
924		struct bcm_mini_adapter *ad)
925{
926	INT status;
927
928	if (down_trylock(&ad->NVMRdmWrmLock)) {
929		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
930				"IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
931		return -EACCES;
932	}
933
934	BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
935			"Starting the firmware download PID =0x%x!!!!\n",
936			current->pid);
937
938	if (down_trylock(&ad->fw_download_sema))
939		return -EBUSY;
940
941	ad->bBinDownloaded = false;
942	ad->fw_download_process_pid = current->pid;
943	ad->bCfgDownloaded = false;
944	ad->fw_download_done = false;
945	netif_carrier_off(ad->dev);
946	netif_stop_queue(ad->dev);
947	status = reset_card_proc(ad);
948	if (status) {
949		pr_err(PFX "%s: reset_card_proc Failed!\n", ad->dev->name);
950		up(&ad->fw_download_sema);
951		up(&ad->NVMRdmWrmLock);
952		return status;
953	}
954	mdelay(10);
955
956	up(&ad->NVMRdmWrmLock);
957	return status;
958}
959
960static int bcm_char_ioctl_buffer_download(void __user *argp,
961					  struct bcm_mini_adapter *ad)
962{
963	struct bcm_firmware_info *fw_info = NULL;
964	struct bcm_ioctl_buffer io_buff;
965	INT status;
966
967	BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
968		"Starting the firmware download PID =0x%x!!!!\n", current->pid);
969
970	if (!down_trylock(&ad->fw_download_sema)) {
971		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
972				"Invalid way to download buffer. Use Start and then call this!!!\n");
973		up(&ad->fw_download_sema);
974		return -EINVAL;
975	}
976
977	/* Copy Ioctl Buffer structure */
978	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
979		up(&ad->fw_download_sema);
980		return -EFAULT;
981	}
982
983	BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
984			"Length for FW DLD is : %lx\n", io_buff.InputLength);
985
986	if (io_buff.InputLength > sizeof(struct bcm_firmware_info)) {
987		up(&ad->fw_download_sema);
988		return -EINVAL;
989	}
990
991	fw_info = kmalloc(sizeof(*fw_info), GFP_KERNEL);
992	if (!fw_info) {
993		up(&ad->fw_download_sema);
994		return -ENOMEM;
995	}
996
997	if (copy_from_user(fw_info, io_buff.InputBuffer,
998		io_buff.InputLength)) {
999		up(&ad->fw_download_sema);
1000		kfree(fw_info);
1001		return -EFAULT;
1002	}
1003
1004	if (!fw_info->pvMappedFirmwareAddress ||
1005		(fw_info->u32FirmwareLength == 0)) {
1006
1007		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1008				"Something else is wrong %lu\n",
1009				fw_info->u32FirmwareLength);
1010		up(&ad->fw_download_sema);
1011		kfree(fw_info);
1012		status = -EINVAL;
1013		return status;
1014	}
1015
1016	status = bcm_ioctl_fw_download(ad, fw_info);
1017
1018	if (status != STATUS_SUCCESS) {
1019		if (fw_info->u32StartingAddress == CONFIG_BEGIN_ADDR)
1020			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1021				"IOCTL: Configuration File Upload Failed\n");
1022		else
1023			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1024				"IOCTL: Firmware File Upload Failed\n");
1025
1026		/* up(&ad->fw_download_sema); */
1027
1028		if (ad->LEDInfo.led_thread_running &
1029			BCM_LED_THREAD_RUNNING_ACTIVELY) {
1030			ad->DriverState = DRIVER_INIT;
1031			ad->LEDInfo.bLedInitDone = false;
1032			wake_up(&ad->LEDInfo.notify_led_event);
1033		}
1034	}
1035
1036	if (status != STATUS_SUCCESS)
1037		up(&ad->fw_download_sema);
1038
1039	BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL,
1040		"IOCTL: Firmware File Uploaded\n");
1041	kfree(fw_info);
1042	return status;
1043}
1044
1045static int bcm_char_ioctl_buffer_download_stop(void __user *argp,
1046					       struct bcm_mini_adapter *ad)
1047{
1048	INT status;
1049	int timeout = 0;
1050
1051	if (!down_trylock(&ad->fw_download_sema)) {
1052		up(&ad->fw_download_sema);
1053		return -EINVAL;
1054	}
1055
1056	if (down_trylock(&ad->NVMRdmWrmLock)) {
1057		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1058				"FW download blocked as EEPROM Read/Write is in progress\n");
1059		up(&ad->fw_download_sema);
1060		return -EACCES;
1061	}
1062
1063	ad->bBinDownloaded = TRUE;
1064	ad->bCfgDownloaded = TRUE;
1065	atomic_set(&ad->CurrNumFreeTxDesc, 0);
1066	ad->CurrNumRecvDescs = 0;
1067	ad->downloadDDR = 0;
1068
1069	/* setting the Mips to Run */
1070	status = run_card_proc(ad);
1071
1072	if (status) {
1073		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1074			"Firm Download Failed\n");
1075		up(&ad->fw_download_sema);
1076		up(&ad->NVMRdmWrmLock);
1077		return status;
1078	}
1079	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1080			DBG_LVL_ALL, "Firm Download Over...\n");
1081
1082	mdelay(10);
1083
1084	/* Wait for MailBox Interrupt */
1085	if (StartInterruptUrb((struct bcm_interface_adapter *)ad->pvInterfaceAdapter))
1086		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1087			"Unable to send interrupt...\n");
1088
1089	timeout = 5*HZ;
1090	ad->waiting_to_fw_download_done = false;
1091	wait_event_timeout(ad->ioctl_fw_dnld_wait_queue,
1092			ad->waiting_to_fw_download_done, timeout);
1093	ad->fw_download_process_pid = INVALID_PID;
1094	ad->fw_download_done = TRUE;
1095	atomic_set(&ad->CurrNumFreeTxDesc, 0);
1096	ad->CurrNumRecvDescs = 0;
1097	ad->PrevNumRecvDescs = 0;
1098	atomic_set(&ad->cntrlpktCnt, 0);
1099	ad->LinkUpStatus = 0;
1100	ad->LinkStatus = 0;
1101
1102	if (ad->LEDInfo.led_thread_running &
1103		BCM_LED_THREAD_RUNNING_ACTIVELY) {
1104		ad->DriverState = FW_DOWNLOAD_DONE;
1105		wake_up(&ad->LEDInfo.notify_led_event);
1106	}
1107
1108	if (!timeout)
1109		status = -ENODEV;
1110
1111	up(&ad->fw_download_sema);
1112	up(&ad->NVMRdmWrmLock);
1113	return status;
1114}
1115
1116static int bcm_char_ioctl_chip_reset(struct bcm_mini_adapter *ad)
1117{
1118	INT status;
1119	INT nvm_access;
1120
1121	nvm_access = down_trylock(&ad->NVMRdmWrmLock);
1122	if (nvm_access) {
1123		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1124			" IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
1125		return -EACCES;
1126	}
1127
1128	down(&ad->RxAppControlQueuelock);
1129	status = reset_card_proc(ad);
1130	flushAllAppQ();
1131	up(&ad->RxAppControlQueuelock);
1132	up(&ad->NVMRdmWrmLock);
1133	ResetCounters(ad);
1134	return status;
1135}
1136
1137static int bcm_char_ioctl_qos_threshold(ULONG arg,
1138					struct bcm_mini_adapter *ad)
1139{
1140	USHORT i;
1141
1142	for (i = 0; i < NO_OF_QUEUES; i++) {
1143		if (get_user(ad->PackInfo[i].uiThreshold,
1144				(unsigned long __user *)arg)) {
1145			return -EFAULT;
1146		}
1147	}
1148	return 0;
1149}
1150
1151static int bcm_char_ioctl_switch_transfer_mode(void __user *argp,
1152					       struct bcm_mini_adapter *ad)
1153{
1154	UINT data = 0;
1155
1156	if (copy_from_user(&data, argp, sizeof(UINT)))
1157		return -EFAULT;
1158
1159	if (data) {
1160		/* Allow All Packets */
1161		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1162			"IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
1163			ad->TransferMode = ETH_PACKET_TUNNELING_MODE;
1164	} else {
1165		/* Allow IP only Packets */
1166		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1167			"IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
1168		ad->TransferMode = IP_PACKET_ONLY_MODE;
1169	}
1170	return STATUS_SUCCESS;
1171}
1172
1173static int bcm_char_ioctl_get_driver_version(void __user *argp)
1174{
1175	struct bcm_ioctl_buffer io_buff;
1176	ulong len;
1177
1178	/* Copy Ioctl Buffer structure */
1179	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1180		return -EFAULT;
1181
1182	len = min_t(ulong, io_buff.OutputLength, strlen(DRV_VERSION) + 1);
1183
1184	if (copy_to_user(io_buff.OutputBuffer, DRV_VERSION, len))
1185		return -EFAULT;
1186
1187	return STATUS_SUCCESS;
1188}
1189
1190static int bcm_char_ioctl_get_current_status(void __user *argp,
1191					     struct bcm_mini_adapter *ad)
1192{
1193	struct bcm_link_state link_state;
1194	struct bcm_ioctl_buffer io_buff;
1195
1196	/* Copy Ioctl Buffer structure */
1197	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
1198		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1199			"copy_from_user failed..\n");
1200		return -EFAULT;
1201	}
1202
1203	if (io_buff.OutputLength != sizeof(link_state))
1204		return -EINVAL;
1205
1206	memset(&link_state, 0, sizeof(link_state));
1207	link_state.bIdleMode = ad->IdleMode;
1208	link_state.bShutdownMode = ad->bShutStatus;
1209	link_state.ucLinkStatus = ad->LinkStatus;
1210
1211	if (copy_to_user(io_buff.OutputBuffer, &link_state, min_t(size_t,
1212		sizeof(link_state), io_buff.OutputLength))) {
1213		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1214			"Copy_to_user Failed..\n");
1215		return -EFAULT;
1216	}
1217	return STATUS_SUCCESS;
1218}
1219
1220
1221static int bcm_char_ioctl_set_mac_tracing(void __user *argp,
1222					  struct bcm_mini_adapter *ad)
1223{
1224	struct bcm_ioctl_buffer io_buff;
1225	UINT tracing_flag;
1226
1227	/* copy ioctl Buffer structure */
1228	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1229		return -EFAULT;
1230
1231	if (copy_from_user(&tracing_flag, io_buff.InputBuffer, sizeof(UINT)))
1232		return -EFAULT;
1233
1234	if (tracing_flag)
1235		ad->pTarangs->MacTracingEnabled = TRUE;
1236	else
1237		ad->pTarangs->MacTracingEnabled = false;
1238
1239	return STATUS_SUCCESS;
1240}
1241
1242static int bcm_char_ioctl_get_dsx_indication(void __user *argp,
1243					     struct bcm_mini_adapter *ad)
1244{
1245	struct bcm_ioctl_buffer io_buff;
1246	ULONG sf_id = 0;
1247
1248	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1249		return -EFAULT;
1250
1251	if (io_buff.OutputLength < sizeof(struct bcm_add_indication_alt)) {
1252		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1253			"Mismatch req: %lx needed is =0x%zx!!!",
1254			io_buff.OutputLength,
1255			sizeof(struct bcm_add_indication_alt));
1256		return -EINVAL;
1257	}
1258
1259	if (copy_from_user(&sf_id, io_buff.InputBuffer, sizeof(sf_id)))
1260		return -EFAULT;
1261
1262	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1263		"Get DSX Data SF ID is =%lx\n", sf_id);
1264	get_dsx_sf_data_to_application(ad, sf_id, io_buff.OutputBuffer);
1265	return STATUS_SUCCESS;
1266}
1267
1268static int bcm_char_ioctl_get_host_mibs(void __user *argp,
1269					struct bcm_mini_adapter *ad,
1270					struct bcm_tarang_data *tarang)
1271{
1272	struct bcm_ioctl_buffer io_buff;
1273	INT status = STATUS_FAILURE;
1274	PVOID temp_buff;
1275
1276	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1277		return -EFAULT;
1278
1279	if (io_buff.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
1280		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1281			"Length Check failed %lu %zd\n", io_buff.OutputLength,
1282			sizeof(struct bcm_host_stats_mibs));
1283		return -EINVAL;
1284	}
1285
1286	/* FIXME: HOST_STATS are too big for kmalloc (122048)! */
1287	temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
1288	if (!temp_buff)
1289		return STATUS_FAILURE;
1290
1291	status = ProcessGetHostMibs(ad, temp_buff);
1292	GetDroppedAppCntrlPktMibs(temp_buff, tarang);
1293
1294	if (status != STATUS_FAILURE) {
1295		if (copy_to_user(io_buff.OutputBuffer, temp_buff,
1296			sizeof(struct bcm_host_stats_mibs))) {
1297			kfree(temp_buff);
1298			return -EFAULT;
1299		}
1300	}
1301
1302	kfree(temp_buff);
1303	return status;
1304}
1305
1306static int bcm_char_ioctl_bulk_wrm(void __user *argp,
1307				   struct bcm_mini_adapter *ad, UINT cmd)
1308{
1309	struct bcm_bulk_wrm_buffer *bulk_buff;
1310	struct bcm_ioctl_buffer io_buff;
1311	UINT tmp = 0;
1312	INT status = STATUS_FAILURE;
1313	PCHAR buff = NULL;
1314
1315	if ((ad->IdleMode == TRUE) ||
1316		(ad->bShutStatus == TRUE) ||
1317		(ad->bPreparingForLowPowerMode == TRUE)) {
1318
1319		BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1320			"Device in Idle/Shutdown Mode, Blocking Wrms\n");
1321		return -EACCES;
1322	}
1323
1324	/* Copy Ioctl Buffer structure */
1325	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1326		return -EFAULT;
1327
1328	if (io_buff.InputLength < sizeof(ULONG) * 2)
1329		return -EINVAL;
1330
1331	buff = memdup_user(io_buff.InputBuffer,
1332			       io_buff.InputLength);
1333	if (IS_ERR(buff))
1334		return PTR_ERR(buff);
1335
1336	bulk_buff = (struct bcm_bulk_wrm_buffer *)buff;
1337
1338	if (((ULONG)bulk_buff->Register & 0x0F000000) != 0x0F000000 ||
1339		((ULONG)bulk_buff->Register & 0x3)) {
1340		BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1341			"WRM Done On invalid Address : %x Access Denied.\n",
1342			(int)bulk_buff->Register);
1343		kfree(buff);
1344		return -EINVAL;
1345	}
1346
1347	tmp = bulk_buff->Register & EEPROM_REJECT_MASK;
1348	if (!((ad->pstargetparams->m_u32Customize)&VSG_MODE) &&
1349		((tmp == EEPROM_REJECT_REG_1) ||
1350			(tmp == EEPROM_REJECT_REG_2) ||
1351			(tmp == EEPROM_REJECT_REG_3) ||
1352			(tmp == EEPROM_REJECT_REG_4)) &&
1353		(cmd == IOCTL_BCM_REGISTER_WRITE)) {
1354
1355		kfree(buff);
1356		BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1357			"EEPROM Access Denied, not in VSG Mode\n");
1358		return -EFAULT;
1359	}
1360
1361	if (bulk_buff->SwapEndian == false)
1362		status = wrmWithLock(ad, (UINT)bulk_buff->Register,
1363			(PCHAR)bulk_buff->Values,
1364			io_buff.InputLength - 2*sizeof(ULONG));
1365	else
1366		status = wrmaltWithLock(ad, (UINT)bulk_buff->Register,
1367			(PUINT)bulk_buff->Values,
1368			io_buff.InputLength - 2*sizeof(ULONG));
1369
1370	if (status != STATUS_SUCCESS)
1371		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
1372
1373	kfree(buff);
1374	return status;
1375}
1376
1377static int bcm_char_ioctl_get_nvm_size(void __user *argp,
1378				       struct bcm_mini_adapter *ad)
1379{
1380	struct bcm_ioctl_buffer io_buff;
1381
1382	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1383		return -EFAULT;
1384
1385	if (ad->eNVMType == NVM_EEPROM || ad->eNVMType == NVM_FLASH) {
1386		if (copy_to_user(io_buff.OutputBuffer, &ad->uiNVMDSDSize,
1387			sizeof(UINT)))
1388			return -EFAULT;
1389	}
1390
1391	return STATUS_SUCCESS;
1392}
1393
1394static int bcm_char_ioctl_cal_init(void __user *argp,
1395				   struct bcm_mini_adapter *ad)
1396{
1397	struct bcm_ioctl_buffer io_buff;
1398	UINT sector_size = 0;
1399	INT status = STATUS_FAILURE;
1400
1401	if (ad->eNVMType == NVM_FLASH) {
1402		if (copy_from_user(&io_buff, argp,
1403			sizeof(struct bcm_ioctl_buffer)))
1404			return -EFAULT;
1405
1406		if (copy_from_user(&sector_size, io_buff.InputBuffer,
1407			sizeof(UINT)))
1408			return -EFAULT;
1409
1410		if ((sector_size < MIN_SECTOR_SIZE) ||
1411			(sector_size > MAX_SECTOR_SIZE)) {
1412			if (copy_to_user(io_buff.OutputBuffer,
1413				&ad->uiSectorSize, sizeof(UINT)))
1414				return -EFAULT;
1415		} else {
1416			if (IsFlash2x(ad)) {
1417				if (copy_to_user(io_buff.OutputBuffer,
1418					&ad->uiSectorSize, sizeof(UINT)))
1419					return -EFAULT;
1420			} else {
1421				if ((TRUE == ad->bShutStatus) ||
1422					(TRUE == ad->IdleMode)) {
1423					BCM_DEBUG_PRINT(ad,
1424						DBG_TYPE_PRINTK, 0, 0,
1425						"Device is in Idle/Shutdown Mode\n");
1426					return -EACCES;
1427				}
1428
1429				ad->uiSectorSize = sector_size;
1430				BcmUpdateSectorSize(ad,
1431					ad->uiSectorSize);
1432			}
1433		}
1434		status = STATUS_SUCCESS;
1435	} else {
1436		status = STATUS_FAILURE;
1437	}
1438	return status;
1439}
1440
1441static int bcm_char_ioctl_set_debug(void __user *argp,
1442				    struct bcm_mini_adapter *ad)
1443{
1444#ifdef DEBUG
1445	struct bcm_ioctl_buffer io_buff;
1446	struct bcm_user_debug_state user_debug_state;
1447
1448	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1449		"In SET_DEBUG ioctl\n");
1450	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1451		return -EFAULT;
1452
1453	if (copy_from_user(&user_debug_state, io_buff.InputBuffer,
1454		sizeof(struct bcm_user_debug_state)))
1455		return -EFAULT;
1456
1457	BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1458			"IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
1459			user_debug_state.OnOff, user_debug_state.Type);
1460	/* user_debug_state.Subtype <<= 1; */
1461	user_debug_state.Subtype = 1 << user_debug_state.Subtype;
1462	BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1463		"actual Subtype=0x%x\n", user_debug_state.Subtype);
1464
1465	/* Update new 'DebugState' in the ad */
1466	ad->stDebugState.type |= user_debug_state.Type;
1467	/* Subtype: A bitmap of 32 bits for Subtype per Type.
1468	 * Valid indexes in 'subtype' array: 1,2,4,8
1469	 * corresponding to valid Type values. Hence we can use the 'Type' field
1470	 * as the index value, ignoring the array entries 0,3,5,6,7 !
1471	 */
1472	if (user_debug_state.OnOff)
1473		ad->stDebugState.subtype[user_debug_state.Type] |=
1474			user_debug_state.Subtype;
1475	else
1476		ad->stDebugState.subtype[user_debug_state.Type] &=
1477			~user_debug_state.Subtype;
1478
1479	BCM_SHOW_DEBUG_BITMAP(ad);
1480#endif
1481	return STATUS_SUCCESS;
1482}
1483
1484static int bcm_char_ioctl_nvm_rw(void __user *argp,
1485				 struct bcm_mini_adapter *ad, UINT cmd)
1486{
1487	struct bcm_nvm_readwrite nvm_rw;
1488	struct timeval tv0, tv1;
1489	struct bcm_ioctl_buffer io_buff;
1490	PUCHAR read_data = NULL;
1491	INT status = STATUS_FAILURE;
1492
1493	memset(&tv0, 0, sizeof(struct timeval));
1494	memset(&tv1, 0, sizeof(struct timeval));
1495	if ((ad->eNVMType == NVM_FLASH) &&
1496		(ad->uiFlashLayoutMajorVersion == 0)) {
1497		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1498			"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
1499		return -EFAULT;
1500	}
1501
1502	if (IsFlash2x(ad)) {
1503		if ((ad->eActiveDSD != DSD0) &&
1504			(ad->eActiveDSD != DSD1) &&
1505			(ad->eActiveDSD != DSD2)) {
1506
1507			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1508				"No DSD is active..hence NVM Command is blocked");
1509			return STATUS_FAILURE;
1510		}
1511	}
1512
1513	/* Copy Ioctl Buffer structure */
1514	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1515		return -EFAULT;
1516
1517	if (copy_from_user(&nvm_rw,
1518				(IOCTL_BCM_NVM_READ == cmd) ?
1519				io_buff.OutputBuffer : io_buff.InputBuffer,
1520				sizeof(struct bcm_nvm_readwrite)))
1521		return -EFAULT;
1522
1523	/*
1524	 * Deny the access if the offset crosses the cal area limit.
1525	 */
1526	if (nvm_rw.uiNumBytes > ad->uiNVMDSDSize)
1527		return STATUS_FAILURE;
1528
1529	if (nvm_rw.uiOffset >
1530		ad->uiNVMDSDSize - nvm_rw.uiNumBytes)
1531		return STATUS_FAILURE;
1532
1533	read_data = memdup_user(nvm_rw.pBuffer,
1534				nvm_rw.uiNumBytes);
1535	if (IS_ERR(read_data))
1536		return PTR_ERR(read_data);
1537
1538	do_gettimeofday(&tv0);
1539	if (IOCTL_BCM_NVM_READ == cmd) {
1540		int ret = bcm_handle_nvm_read_cmd(ad, read_data,
1541				&nvm_rw);
1542		if (ret != STATUS_SUCCESS)
1543			return ret;
1544	} else {
1545		down(&ad->NVMRdmWrmLock);
1546
1547		if ((ad->IdleMode == TRUE) ||
1548			(ad->bShutStatus == TRUE) ||
1549			(ad->bPreparingForLowPowerMode == TRUE)) {
1550
1551			BCM_DEBUG_PRINT(ad,
1552				DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1553				"Device is in Idle/Shutdown Mode\n");
1554			up(&ad->NVMRdmWrmLock);
1555			kfree(read_data);
1556			return -EACCES;
1557		}
1558
1559		ad->bHeaderChangeAllowed = TRUE;
1560		if (IsFlash2x(ad)) {
1561			int ret = handle_flash2x_adapter(ad,
1562							read_data,
1563							&nvm_rw);
1564			if (ret != STATUS_SUCCESS)
1565				return ret;
1566		}
1567
1568		status = BeceemNVMWrite(ad, (PUINT)read_data,
1569			nvm_rw.uiOffset, nvm_rw.uiNumBytes,
1570			nvm_rw.bVerify);
1571		if (IsFlash2x(ad))
1572			BcmFlash2xWriteSig(ad, ad->eActiveDSD);
1573
1574		ad->bHeaderChangeAllowed = false;
1575
1576		up(&ad->NVMRdmWrmLock);
1577
1578		if (status != STATUS_SUCCESS) {
1579			kfree(read_data);
1580			return status;
1581		}
1582	}
1583
1584	do_gettimeofday(&tv1);
1585	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1586		" timetaken by Write/read :%ld msec\n",
1587		(tv1.tv_sec - tv0.tv_sec)*1000 +
1588		(tv1.tv_usec - tv0.tv_usec)/1000);
1589
1590	kfree(read_data);
1591	return STATUS_SUCCESS;
1592}
1593
1594static int bcm_char_ioctl_flash2x_section_read(void __user *argp,
1595	struct bcm_mini_adapter *ad)
1596{
1597	struct bcm_flash2x_readwrite flash_2x_read = {0};
1598	struct bcm_ioctl_buffer io_buff;
1599	PUCHAR read_buff = NULL;
1600	UINT nob = 0;
1601	UINT buff_size = 0;
1602	UINT read_bytes = 0;
1603	UINT read_offset = 0;
1604	INT status = STATUS_FAILURE;
1605	void __user *OutPutBuff;
1606
1607	if (IsFlash2x(ad) != TRUE)	{
1608		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1609			"Flash Does not have 2.x map");
1610		return -EINVAL;
1611	}
1612
1613	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1614		DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
1615	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1616		return -EFAULT;
1617
1618	/* Reading FLASH 2.x READ structure */
1619	if (copy_from_user(&flash_2x_read, io_buff.InputBuffer,
1620		sizeof(struct bcm_flash2x_readwrite)))
1621		return -EFAULT;
1622
1623	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1624			"\nflash_2x_read.Section :%x",
1625			flash_2x_read.Section);
1626	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1627			"\nflash_2x_read.offset :%x",
1628			flash_2x_read.offset);
1629	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1630			"\nflash_2x_read.numOfBytes :%x",
1631			flash_2x_read.numOfBytes);
1632	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1633			"\nflash_2x_read.bVerify :%x\n",
1634			flash_2x_read.bVerify);
1635
1636	/* This was internal to driver for raw read.
1637	 * now it has ben exposed to user space app.
1638	 */
1639	if (validateFlash2xReadWrite(ad, &flash_2x_read) == false)
1640		return STATUS_FAILURE;
1641
1642	nob = flash_2x_read.numOfBytes;
1643	if (nob > ad->uiSectorSize)
1644		buff_size = ad->uiSectorSize;
1645	else
1646		buff_size = nob;
1647
1648	read_offset = flash_2x_read.offset;
1649	OutPutBuff = io_buff.OutputBuffer;
1650	read_buff = kzalloc(buff_size , GFP_KERNEL);
1651
1652	if (read_buff == NULL) {
1653		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1654				"Memory allocation failed for Flash 2.x Read Structure");
1655		return -ENOMEM;
1656	}
1657	down(&ad->NVMRdmWrmLock);
1658
1659	if ((ad->IdleMode == TRUE) ||
1660		(ad->bShutStatus == TRUE) ||
1661		(ad->bPreparingForLowPowerMode == TRUE)) {
1662
1663		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1664				DBG_LVL_ALL,
1665				"Device is in Idle/Shutdown Mode\n");
1666		up(&ad->NVMRdmWrmLock);
1667		kfree(read_buff);
1668		return -EACCES;
1669	}
1670
1671	while (nob) {
1672		if (nob > ad->uiSectorSize)
1673			read_bytes = ad->uiSectorSize;
1674		else
1675			read_bytes = nob;
1676
1677		/* Reading the data from Flash 2.x */
1678		status = BcmFlash2xBulkRead(ad, (PUINT)read_buff,
1679			flash_2x_read.Section, read_offset, read_bytes);
1680		if (status) {
1681			BCM_DEBUG_PRINT(ad,
1682				DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1683				"Flash 2x read err with status :%d",
1684				status);
1685			break;
1686		}
1687
1688		BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1689			DBG_LVL_ALL, read_buff, read_bytes);
1690
1691		status = copy_to_user(OutPutBuff, read_buff, read_bytes);
1692		if (status) {
1693			BCM_DEBUG_PRINT(ad,
1694				DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1695				"Copy to use failed with status :%d", status);
1696			up(&ad->NVMRdmWrmLock);
1697			kfree(read_buff);
1698			return -EFAULT;
1699		}
1700		nob = nob - read_bytes;
1701		if (nob) {
1702			read_offset = read_offset + read_bytes;
1703			OutPutBuff = OutPutBuff + read_bytes;
1704		}
1705	}
1706
1707	up(&ad->NVMRdmWrmLock);
1708	kfree(read_buff);
1709	return status;
1710}
1711
1712static int bcm_char_ioctl_flash2x_section_write(void __user *argp,
1713	struct bcm_mini_adapter *ad)
1714{
1715	struct bcm_flash2x_readwrite sFlash2xWrite = {0};
1716	struct bcm_ioctl_buffer io_buff;
1717	PUCHAR write_buff;
1718	void __user *input_addr;
1719	UINT nob = 0;
1720	UINT buff_size = 0;
1721	UINT write_off = 0;
1722	UINT write_bytes = 0;
1723	INT status = STATUS_FAILURE;
1724
1725	if (IsFlash2x(ad) != TRUE) {
1726		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1727			"Flash Does not have 2.x map");
1728		return -EINVAL;
1729	}
1730
1731	/* First make this False so that we can enable the Sector
1732	 * Permission Check in BeceemFlashBulkWrite
1733	 */
1734	ad->bAllDSDWriteAllow = false;
1735
1736	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1737		"IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
1738
1739	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1740		return -EFAULT;
1741
1742	/* Reading FLASH 2.x READ structure */
1743	if (copy_from_user(&sFlash2xWrite, io_buff.InputBuffer,
1744		sizeof(struct bcm_flash2x_readwrite)))
1745		return -EFAULT;
1746
1747	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1748		"\nsFlash2xWrite.Section :%x", sFlash2xWrite.Section);
1749	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1750		"\nsFlash2xWrite.offset :%d", sFlash2xWrite.offset);
1751	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1752		"\nsFlash2xWrite.numOfBytes :%x", sFlash2xWrite.numOfBytes);
1753	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1754		"\nsFlash2xWrite.bVerify :%x\n", sFlash2xWrite.bVerify);
1755
1756	if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1)
1757		&& (sFlash2xWrite.Section != VSA2)) {
1758		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1759			"Only VSA write is allowed");
1760		return -EINVAL;
1761	}
1762
1763	if (validateFlash2xReadWrite(ad, &sFlash2xWrite) == false)
1764		return STATUS_FAILURE;
1765
1766	input_addr = sFlash2xWrite.pDataBuff;
1767	write_off = sFlash2xWrite.offset;
1768	nob = sFlash2xWrite.numOfBytes;
1769
1770	if (nob > ad->uiSectorSize)
1771		buff_size = ad->uiSectorSize;
1772	else
1773		buff_size = nob;
1774
1775	write_buff = kmalloc(buff_size, GFP_KERNEL);
1776
1777	if (write_buff == NULL)
1778		return -ENOMEM;
1779
1780	/* extracting the remainder of the given offset. */
1781	write_bytes = ad->uiSectorSize;
1782	if (write_off % ad->uiSectorSize) {
1783		write_bytes = ad->uiSectorSize -
1784			(write_off % ad->uiSectorSize);
1785	}
1786
1787	if (nob < write_bytes)
1788		write_bytes = nob;
1789
1790	down(&ad->NVMRdmWrmLock);
1791
1792	if ((ad->IdleMode == TRUE) ||
1793		(ad->bShutStatus == TRUE) ||
1794		(ad->bPreparingForLowPowerMode == TRUE)) {
1795
1796		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1797			"Device is in Idle/Shutdown Mode\n");
1798		up(&ad->NVMRdmWrmLock);
1799		kfree(write_buff);
1800		return -EACCES;
1801	}
1802
1803	BcmFlash2xCorruptSig(ad, sFlash2xWrite.Section);
1804	do {
1805		status = copy_from_user(write_buff, input_addr, write_bytes);
1806		if (status) {
1807			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1808				"Copy to user failed with status :%d", status);
1809			up(&ad->NVMRdmWrmLock);
1810			kfree(write_buff);
1811			return -EFAULT;
1812		}
1813		BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS,
1814			OSAL_DBG, DBG_LVL_ALL, write_buff, write_bytes);
1815
1816		/* Writing the data from Flash 2.x */
1817		status = BcmFlash2xBulkWrite(ad, (PUINT)write_buff,
1818					     sFlash2xWrite.Section,
1819					     write_off,
1820					     write_bytes,
1821					     sFlash2xWrite.bVerify);
1822
1823		if (status) {
1824			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1825				"Flash 2x read err with status :%d", status);
1826			break;
1827		}
1828
1829		nob = nob - write_bytes;
1830		if (nob) {
1831			write_off = write_off + write_bytes;
1832			input_addr = input_addr + write_bytes;
1833			if (nob > ad->uiSectorSize)
1834				write_bytes = ad->uiSectorSize;
1835			else
1836				write_bytes = nob;
1837		}
1838	} while (nob > 0);
1839
1840	BcmFlash2xWriteSig(ad, sFlash2xWrite.Section);
1841	up(&ad->NVMRdmWrmLock);
1842	kfree(write_buff);
1843	return status;
1844}
1845
1846static int bcm_char_ioctl_flash2x_section_bitmap(void __user *argp,
1847	struct bcm_mini_adapter *ad)
1848{
1849	struct bcm_flash2x_bitmap *flash_2x_bit_map;
1850	struct bcm_ioctl_buffer io_buff;
1851
1852BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1853	"IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
1854
1855	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1856		return -EFAULT;
1857
1858	if (io_buff.OutputLength != sizeof(struct bcm_flash2x_bitmap))
1859		return -EINVAL;
1860
1861	flash_2x_bit_map = kzalloc(sizeof(struct bcm_flash2x_bitmap),
1862			GFP_KERNEL);
1863
1864	if (flash_2x_bit_map == NULL) {
1865		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1866			"Memory is not available");
1867		return -ENOMEM;
1868	}
1869
1870	/* Reading the Flash Sectio Bit map */
1871	down(&ad->NVMRdmWrmLock);
1872
1873	if ((ad->IdleMode == TRUE) ||
1874		(ad->bShutStatus == TRUE) ||
1875		(ad->bPreparingForLowPowerMode == TRUE)) {
1876
1877		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1878			"Device is in Idle/Shutdown Mode\n");
1879		up(&ad->NVMRdmWrmLock);
1880		kfree(flash_2x_bit_map);
1881		return -EACCES;
1882	}
1883
1884	BcmGetFlash2xSectionalBitMap(ad, flash_2x_bit_map);
1885	up(&ad->NVMRdmWrmLock);
1886	if (copy_to_user(io_buff.OutputBuffer, flash_2x_bit_map,
1887		sizeof(struct bcm_flash2x_bitmap))) {
1888		kfree(flash_2x_bit_map);
1889		return -EFAULT;
1890	}
1891
1892	kfree(flash_2x_bit_map);
1893	return STATUS_FAILURE;
1894}
1895
1896static int bcm_char_ioctl_set_active_section(void __user *argp,
1897					     struct bcm_mini_adapter *ad)
1898{
1899	enum bcm_flash2x_section_val flash_2x_section_val = 0;
1900	INT status = STATUS_FAILURE;
1901	struct bcm_ioctl_buffer io_buff;
1902
1903	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1904			"IOCTL_BCM_SET_ACTIVE_SECTION Called");
1905
1906	if (IsFlash2x(ad) != TRUE) {
1907		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1908				"Flash Does not have 2.x map");
1909		return -EINVAL;
1910	}
1911
1912	status = copy_from_user(&io_buff, argp,
1913				sizeof(struct bcm_ioctl_buffer));
1914	if (status) {
1915		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1916				"Copy of IOCTL BUFFER failed");
1917		return -EFAULT;
1918	}
1919
1920	status = copy_from_user(&flash_2x_section_val,
1921				io_buff.InputBuffer, sizeof(INT));
1922	if (status) {
1923		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1924			"Copy of flash section val failed");
1925		return -EFAULT;
1926	}
1927
1928	down(&ad->NVMRdmWrmLock);
1929
1930	if ((ad->IdleMode == TRUE) ||
1931		(ad->bShutStatus == TRUE) ||
1932		(ad->bPreparingForLowPowerMode == TRUE)) {
1933
1934		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1935				"Device is in Idle/Shutdown Mode\n");
1936		up(&ad->NVMRdmWrmLock);
1937		return -EACCES;
1938	}
1939
1940	status = BcmSetActiveSection(ad, flash_2x_section_val);
1941	if (status)
1942		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1943				"Failed to make it's priority Highest. status %d",
1944				status);
1945
1946	up(&ad->NVMRdmWrmLock);
1947
1948	return status;
1949}
1950
1951static int bcm_char_ioctl_copy_section(void __user *argp,
1952				       struct bcm_mini_adapter *ad)
1953{
1954	struct bcm_flash2x_copy_section copy_sect_strut = {0};
1955	struct bcm_ioctl_buffer io_buff;
1956	INT status = STATUS_SUCCESS;
1957
1958	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1959			"IOCTL_BCM_COPY_SECTION  Called");
1960
1961	ad->bAllDSDWriteAllow = false;
1962	if (IsFlash2x(ad) != TRUE) {
1963		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1964				"Flash Does not have 2.x map");
1965		return -EINVAL;
1966	}
1967
1968	status = copy_from_user(&io_buff, argp,
1969				sizeof(struct bcm_ioctl_buffer));
1970	if (status) {
1971		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1972				"Copy of IOCTL BUFFER failed status :%d",
1973				status);
1974		return -EFAULT;
1975	}
1976
1977	status = copy_from_user(&copy_sect_strut, io_buff.InputBuffer,
1978				sizeof(struct bcm_flash2x_copy_section));
1979	if (status) {
1980		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1981				"Copy of Copy_Section_Struct failed with status :%d",
1982				status);
1983		return -EFAULT;
1984	}
1985
1986	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1987			"Source SEction :%x", copy_sect_strut.SrcSection);
1988	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1989			"Destination SEction :%x", copy_sect_strut.DstSection);
1990	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1991			"offset :%x", copy_sect_strut.offset);
1992	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1993			"nob :%x", copy_sect_strut.numOfBytes);
1994
1995	if (IsSectionExistInFlash(ad, copy_sect_strut.SrcSection) == false) {
1996		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1997				"Source Section<%x> does not exist in Flash ",
1998				copy_sect_strut.SrcSection);
1999		return -EINVAL;
2000	}
2001
2002	if (IsSectionExistInFlash(ad, copy_sect_strut.DstSection) == false) {
2003		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2004				"Destinatio Section<%x> does not exist in Flash ",
2005				copy_sect_strut.DstSection);
2006		return -EINVAL;
2007	}
2008
2009	if (copy_sect_strut.SrcSection == copy_sect_strut.DstSection) {
2010		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2011				"Source and Destination section should be different");
2012		return -EINVAL;
2013	}
2014
2015	down(&ad->NVMRdmWrmLock);
2016
2017	if ((ad->IdleMode == TRUE) ||
2018		(ad->bShutStatus == TRUE) ||
2019		(ad->bPreparingForLowPowerMode == TRUE)) {
2020
2021		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2022				"Device is in Idle/Shutdown Mode\n");
2023		up(&ad->NVMRdmWrmLock);
2024		return -EACCES;
2025	}
2026
2027	if (copy_sect_strut.SrcSection == ISO_IMAGE1 ||
2028		copy_sect_strut.SrcSection == ISO_IMAGE2) {
2029		if (IsNonCDLessDevice(ad)) {
2030			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2031					"Device is Non-CDLess hence won't have ISO !!");
2032			status = -EINVAL;
2033		} else if (copy_sect_strut.numOfBytes == 0) {
2034			status = BcmCopyISO(ad, copy_sect_strut);
2035		} else {
2036			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2037					"Partial Copy of ISO section is not Allowed..");
2038			status = STATUS_FAILURE;
2039		}
2040		up(&ad->NVMRdmWrmLock);
2041		return status;
2042	}
2043
2044	status = BcmCopySection(ad, copy_sect_strut.SrcSection,
2045				copy_sect_strut.DstSection,
2046				copy_sect_strut.offset,
2047				copy_sect_strut.numOfBytes);
2048	up(&ad->NVMRdmWrmLock);
2049	return status;
2050}
2051
2052static int bcm_char_ioctl_get_flash_cs_info(void __user *argp,
2053					    struct bcm_mini_adapter *ad)
2054{
2055	struct bcm_ioctl_buffer io_buff;
2056	INT status = STATUS_SUCCESS;
2057
2058	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2059			" IOCTL_BCM_GET_FLASH_CS_INFO Called");
2060
2061	status = copy_from_user(&io_buff, argp,
2062			sizeof(struct bcm_ioctl_buffer));
2063	if (status) {
2064		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2065				"Copy of IOCTL BUFFER failed");
2066		return -EFAULT;
2067	}
2068
2069	if (ad->eNVMType != NVM_FLASH) {
2070		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2071				"Connected device does not have flash");
2072		return -EINVAL;
2073	}
2074
2075	if (IsFlash2x(ad) == TRUE) {
2076		if (io_buff.OutputLength < sizeof(struct bcm_flash2x_cs_info))
2077			return -EINVAL;
2078
2079		if (copy_to_user(io_buff.OutputBuffer,
2080				 ad->psFlash2xCSInfo,
2081				 sizeof(struct bcm_flash2x_cs_info)))
2082			return -EFAULT;
2083	} else {
2084		if (io_buff.OutputLength < sizeof(struct bcm_flash_cs_info))
2085			return -EINVAL;
2086
2087		if (copy_to_user(io_buff.OutputBuffer, ad->psFlashCSInfo,
2088				 sizeof(struct bcm_flash_cs_info)))
2089			return -EFAULT;
2090	}
2091	return status;
2092}
2093
2094static int bcm_char_ioctl_select_dsd(void __user *argp,
2095				     struct bcm_mini_adapter *ad)
2096{
2097	struct bcm_ioctl_buffer io_buff;
2098	INT status = STATUS_FAILURE;
2099	UINT sect_offset = 0;
2100	enum bcm_flash2x_section_val flash_2x_section_val;
2101
2102	flash_2x_section_val = NO_SECTION_VAL;
2103	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2104			"IOCTL_BCM_SELECT_DSD Called");
2105
2106	if (IsFlash2x(ad) != TRUE) {
2107		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2108				"Flash Does not have 2.x map");
2109		return -EINVAL;
2110	}
2111
2112	status = copy_from_user(&io_buff, argp,
2113				sizeof(struct bcm_ioctl_buffer));
2114	if (status) {
2115		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2116				"Copy of IOCTL BUFFER failed");
2117		return -EFAULT;
2118	}
2119	status = copy_from_user(&flash_2x_section_val, io_buff.InputBuffer,
2120		sizeof(INT));
2121	if (status) {
2122		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2123				"Copy of flash section val failed");
2124		return -EFAULT;
2125	}
2126
2127	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2128			"Read Section :%d", flash_2x_section_val);
2129	if ((flash_2x_section_val != DSD0) &&
2130		(flash_2x_section_val != DSD1) &&
2131		(flash_2x_section_val != DSD2)) {
2132
2133		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2134				"Passed section<%x> is not DSD section",
2135				flash_2x_section_val);
2136		return STATUS_FAILURE;
2137	}
2138
2139	sect_offset = BcmGetSectionValStartOffset(ad, flash_2x_section_val);
2140	if (sect_offset == INVALID_OFFSET) {
2141		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2142				"Provided Section val <%d> does not exist in Flash 2.x",
2143				flash_2x_section_val);
2144		return -EINVAL;
2145	}
2146
2147	ad->bAllDSDWriteAllow = TRUE;
2148	ad->ulFlashCalStart = sect_offset;
2149	ad->eActiveDSD = flash_2x_section_val;
2150
2151	return STATUS_SUCCESS;
2152}
2153
2154static int bcm_char_ioctl_nvm_raw_read(void __user *argp,
2155				       struct bcm_mini_adapter *ad)
2156{
2157	struct bcm_nvm_readwrite nvm_read;
2158	struct bcm_ioctl_buffer io_buff;
2159	unsigned int nob;
2160	INT buff_size;
2161	INT read_offset = 0;
2162	UINT read_bytes = 0;
2163	PUCHAR read_buff;
2164	void __user *OutPutBuff;
2165	INT status = STATUS_FAILURE;
2166
2167	if (ad->eNVMType != NVM_FLASH) {
2168		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2169				"NVM TYPE is not Flash");
2170		return -EINVAL;
2171	}
2172
2173	/* Copy Ioctl Buffer structure */
2174	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
2175		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2176				"copy_from_user 1 failed\n");
2177		return -EFAULT;
2178	}
2179
2180	if (copy_from_user(&nvm_read, io_buff.OutputBuffer,
2181		sizeof(struct bcm_nvm_readwrite)))
2182		return -EFAULT;
2183
2184	nob = nvm_read.uiNumBytes;
2185	/* In Raw-Read max Buff size : 64MB */
2186
2187	if (nob > DEFAULT_BUFF_SIZE)
2188		buff_size = DEFAULT_BUFF_SIZE;
2189	else
2190		buff_size = nob;
2191
2192	read_offset = nvm_read.uiOffset;
2193	OutPutBuff = nvm_read.pBuffer;
2194
2195	read_buff = kzalloc(buff_size , GFP_KERNEL);
2196	if (read_buff == NULL) {
2197		BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2198				"Memory allocation failed for Flash 2.x Read Structure");
2199		return -ENOMEM;
2200	}
2201	down(&ad->NVMRdmWrmLock);
2202
2203	if ((ad->IdleMode == TRUE) ||
2204		(ad->bShutStatus == TRUE) ||
2205		(ad->bPreparingForLowPowerMode == TRUE)) {
2206
2207		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2208				"Device is in Idle/Shutdown Mode\n");
2209		kfree(read_buff);
2210		up(&ad->NVMRdmWrmLock);
2211		return -EACCES;
2212	}
2213
2214	ad->bFlashRawRead = TRUE;
2215
2216	while (nob) {
2217		if (nob > DEFAULT_BUFF_SIZE)
2218			read_bytes = DEFAULT_BUFF_SIZE;
2219		else
2220			read_bytes = nob;
2221
2222		/* Reading the data from Flash 2.x */
2223		status = BeceemNVMRead(ad, (PUINT)read_buff,
2224			read_offset, read_bytes);
2225		if (status) {
2226			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2227					"Flash 2x read err with status :%d",
2228					status);
2229			break;
2230		}
2231
2232		BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS, OSAL_DBG,
2233				       DBG_LVL_ALL, read_buff, read_bytes);
2234
2235		status = copy_to_user(OutPutBuff, read_buff, read_bytes);
2236		if (status) {
2237			BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2238					"Copy to use failed with status :%d",
2239					status);
2240			up(&ad->NVMRdmWrmLock);
2241			kfree(read_buff);
2242			return -EFAULT;
2243		}
2244		nob = nob - read_bytes;
2245		if (nob) {
2246			read_offset = read_offset + read_bytes;
2247			OutPutBuff = OutPutBuff + read_bytes;
2248		}
2249	}
2250	ad->bFlashRawRead = false;
2251	up(&ad->NVMRdmWrmLock);
2252	kfree(read_buff);
2253	return status;
2254}
2255
2256static int bcm_char_ioctl_cntrlmsg_mask(void __user *argp,
2257					struct bcm_mini_adapter *ad,
2258					struct bcm_tarang_data *tarang)
2259{
2260	struct bcm_ioctl_buffer io_buff;
2261	INT status = STATUS_FAILURE;
2262	ULONG rx_cntrl_msg_bit_mask = 0;
2263
2264	/* Copy Ioctl Buffer structure */
2265	status = copy_from_user(&io_buff, argp,
2266			sizeof(struct bcm_ioctl_buffer));
2267	if (status) {
2268		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2269				"copy of Ioctl buffer is failed from user space");
2270		return -EFAULT;
2271	}
2272
2273	if (io_buff.InputLength != sizeof(unsigned long))
2274		return -EINVAL;
2275
2276	status = copy_from_user(&rx_cntrl_msg_bit_mask, io_buff.InputBuffer,
2277				io_buff.InputLength);
2278	if (status) {
2279		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2280				"copy of control bit mask failed from user space");
2281		return -EFAULT;
2282	}
2283	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2284			"\n Got user defined cntrl msg bit mask :%lx",
2285			rx_cntrl_msg_bit_mask);
2286	tarang->RxCntrlMsgBitMask = rx_cntrl_msg_bit_mask;
2287
2288	return status;
2289}
2290
2291static int bcm_char_ioctl_get_device_driver_info(void __user *argp,
2292	struct bcm_mini_adapter *ad)
2293{
2294	struct bcm_driver_info dev_info;
2295	struct bcm_ioctl_buffer io_buff;
2296
2297	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2298			"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
2299
2300	memset(&dev_info, 0, sizeof(dev_info));
2301	dev_info.MaxRDMBufferSize = BUFFER_4K;
2302	dev_info.u32DSDStartOffset = EEPROM_CALPARAM_START;
2303	dev_info.u32RxAlignmentCorrection = 0;
2304	dev_info.u32NVMType = ad->eNVMType;
2305	dev_info.u32InterfaceType = BCM_USB;
2306
2307	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
2308		return -EFAULT;
2309
2310	if (io_buff.OutputLength < sizeof(dev_info))
2311		return -EINVAL;
2312
2313	if (copy_to_user(io_buff.OutputBuffer, &dev_info, sizeof(dev_info)))
2314		return -EFAULT;
2315
2316	return STATUS_SUCCESS;
2317}
2318
2319static int bcm_char_ioctl_time_since_net_entry(void __user *argp,
2320	struct bcm_mini_adapter *ad)
2321{
2322	struct bcm_time_elapsed time_elapsed_since_net_entry = {0};
2323	struct bcm_ioctl_buffer io_buff;
2324
2325	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2326			"IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
2327
2328	if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
2329		return -EFAULT;
2330
2331	if (io_buff.OutputLength < sizeof(struct bcm_time_elapsed))
2332		return -EINVAL;
2333
2334	time_elapsed_since_net_entry.ul64TimeElapsedSinceNetEntry =
2335		get_seconds() - ad->liTimeSinceLastNetEntry;
2336
2337	if (copy_to_user(io_buff.OutputBuffer, &time_elapsed_since_net_entry,
2338			 sizeof(struct bcm_time_elapsed)))
2339		return -EFAULT;
2340
2341	return STATUS_SUCCESS;
2342}
2343
2344
2345static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
2346{
2347	struct bcm_tarang_data *tarang = filp->private_data;
2348	void __user *argp = (void __user *)arg;
2349	struct bcm_mini_adapter *ad = tarang->Adapter;
2350	INT status = STATUS_FAILURE;
2351
2352	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2353			"Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX",
2354			cmd, arg);
2355
2356	if (_IOC_TYPE(cmd) != BCM_IOCTL)
2357		return -EFAULT;
2358	if (_IOC_DIR(cmd) & _IOC_READ)
2359		status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
2360	else if (_IOC_DIR(cmd) & _IOC_WRITE)
2361		status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
2362	else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
2363		status = STATUS_SUCCESS;
2364
2365	if (status)
2366		return -EFAULT;
2367
2368	if (ad->device_removed)
2369		return -EFAULT;
2370
2371	if (false == ad->fw_download_done) {
2372		switch (cmd) {
2373		case IOCTL_MAC_ADDR_REQ:
2374		case IOCTL_LINK_REQ:
2375		case IOCTL_CM_REQUEST:
2376		case IOCTL_SS_INFO_REQ:
2377		case IOCTL_SEND_CONTROL_MESSAGE:
2378		case IOCTL_IDLE_REQ:
2379		case IOCTL_BCM_GPIO_SET_REQUEST:
2380		case IOCTL_BCM_GPIO_STATUS_REQUEST:
2381			return -EACCES;
2382		default:
2383			break;
2384		}
2385	}
2386
2387	status = vendorextnIoctl(ad, cmd, arg);
2388	if (status != CONTINUE_COMMON_PATH)
2389		return status;
2390
2391	switch (cmd) {
2392	/* Rdms for Swin Idle... */
2393	case IOCTL_BCM_REGISTER_READ_PRIVATE:
2394		status = bcm_char_ioctl_reg_read_private(argp, ad);
2395		return status;
2396
2397	case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
2398		status = bcm_char_ioctl_reg_write_private(argp, ad);
2399		return status;
2400
2401	case IOCTL_BCM_REGISTER_READ:
2402	case IOCTL_BCM_EEPROM_REGISTER_READ:
2403		status = bcm_char_ioctl_eeprom_reg_read(argp, ad);
2404		return status;
2405
2406	case IOCTL_BCM_REGISTER_WRITE:
2407	case IOCTL_BCM_EEPROM_REGISTER_WRITE:
2408		status = bcm_char_ioctl_eeprom_reg_write(argp, ad, cmd);
2409		return status;
2410
2411	case IOCTL_BCM_GPIO_SET_REQUEST:
2412		status = bcm_char_ioctl_gpio_set_request(argp, ad);
2413		return status;
2414
2415	case BCM_LED_THREAD_STATE_CHANGE_REQ:
2416		status = bcm_char_ioctl_led_thread_state_change_req(argp,
2417								    ad);
2418		return status;
2419
2420	case IOCTL_BCM_GPIO_STATUS_REQUEST:
2421		status = bcm_char_ioctl_gpio_status_request(argp, ad);
2422		return status;
2423
2424	case IOCTL_BCM_GPIO_MULTI_REQUEST:
2425		status = bcm_char_ioctl_gpio_multi_request(argp, ad);
2426		return status;
2427
2428	case IOCTL_BCM_GPIO_MODE_REQUEST:
2429		status = bcm_char_ioctl_gpio_mode_request(argp, ad);
2430		return status;
2431
2432	case IOCTL_MAC_ADDR_REQ:
2433	case IOCTL_LINK_REQ:
2434	case IOCTL_CM_REQUEST:
2435	case IOCTL_SS_INFO_REQ:
2436	case IOCTL_SEND_CONTROL_MESSAGE:
2437	case IOCTL_IDLE_REQ:
2438		status = bcm_char_ioctl_misc_request(argp, ad);
2439		return status;
2440
2441	case IOCTL_BCM_BUFFER_DOWNLOAD_START:
2442		status = bcm_char_ioctl_buffer_download_start(ad);
2443		return status;
2444
2445	case IOCTL_BCM_BUFFER_DOWNLOAD:
2446		status = bcm_char_ioctl_buffer_download(argp, ad);
2447		return status;
2448
2449	case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
2450		status = bcm_char_ioctl_buffer_download_stop(argp, ad);
2451		return status;
2452
2453
2454	case IOCTL_BE_BUCKET_SIZE:
2455		status = 0;
2456		if (get_user(ad->BEBucketSize,
2457			     (unsigned long __user *)arg))
2458			status = -EFAULT;
2459		break;
2460
2461	case IOCTL_RTPS_BUCKET_SIZE:
2462		status = 0;
2463		if (get_user(ad->rtPSBucketSize,
2464			     (unsigned long __user *)arg))
2465			status = -EFAULT;
2466		break;
2467
2468	case IOCTL_CHIP_RESET:
2469		status = bcm_char_ioctl_chip_reset(ad);
2470		return status;
2471
2472	case IOCTL_QOS_THRESHOLD:
2473		status = bcm_char_ioctl_qos_threshold(arg, ad);
2474		return status;
2475
2476	case IOCTL_DUMP_PACKET_INFO:
2477		DumpPackInfo(ad);
2478		DumpPhsRules(&ad->stBCMPhsContext);
2479		status = STATUS_SUCCESS;
2480		break;
2481
2482	case IOCTL_GET_PACK_INFO:
2483		if (copy_to_user(argp, &ad->PackInfo,
2484				 sizeof(struct bcm_packet_info)*NO_OF_QUEUES))
2485			return -EFAULT;
2486		status = STATUS_SUCCESS;
2487		break;
2488
2489	case IOCTL_BCM_SWITCH_TRANSFER_MODE:
2490		status = bcm_char_ioctl_switch_transfer_mode(argp, ad);
2491		return status;
2492
2493	case IOCTL_BCM_GET_DRIVER_VERSION:
2494		status = bcm_char_ioctl_get_driver_version(argp);
2495		return status;
2496
2497	case IOCTL_BCM_GET_CURRENT_STATUS:
2498		status = bcm_char_ioctl_get_current_status(argp, ad);
2499		return status;
2500
2501	case IOCTL_BCM_SET_MAC_TRACING:
2502		status = bcm_char_ioctl_set_mac_tracing(argp, ad);
2503		return status;
2504
2505	case IOCTL_BCM_GET_DSX_INDICATION:
2506		status = bcm_char_ioctl_get_dsx_indication(argp, ad);
2507		return status;
2508
2509	case IOCTL_BCM_GET_HOST_MIBS:
2510		status = bcm_char_ioctl_get_host_mibs(argp, ad, tarang);
2511		return status;
2512
2513	case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
2514		if ((false == ad->bTriedToWakeUpFromlowPowerMode) &&
2515				(TRUE == ad->IdleMode)) {
2516			ad->usIdleModePattern = ABORT_IDLE_MODE;
2517			ad->bWakeUpDevice = TRUE;
2518			wake_up(&ad->process_rx_cntrlpkt);
2519		}
2520
2521		status = STATUS_SUCCESS;
2522		break;
2523
2524	case IOCTL_BCM_BULK_WRM:
2525		status = bcm_char_ioctl_bulk_wrm(argp, ad, cmd);
2526		return status;
2527
2528	case IOCTL_BCM_GET_NVM_SIZE:
2529		status = bcm_char_ioctl_get_nvm_size(argp, ad);
2530		return status;
2531
2532	case IOCTL_BCM_CAL_INIT:
2533		status = bcm_char_ioctl_cal_init(argp, ad);
2534		return status;
2535
2536	case IOCTL_BCM_SET_DEBUG:
2537		status = bcm_char_ioctl_set_debug(argp, ad);
2538		return status;
2539
2540	case IOCTL_BCM_NVM_READ:
2541	case IOCTL_BCM_NVM_WRITE:
2542		status = bcm_char_ioctl_nvm_rw(argp, ad, cmd);
2543		return status;
2544
2545	case IOCTL_BCM_FLASH2X_SECTION_READ:
2546		status = bcm_char_ioctl_flash2x_section_read(argp, ad);
2547		return status;
2548
2549	case IOCTL_BCM_FLASH2X_SECTION_WRITE:
2550		status = bcm_char_ioctl_flash2x_section_write(argp, ad);
2551		return status;
2552
2553	case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP:
2554		status = bcm_char_ioctl_flash2x_section_bitmap(argp, ad);
2555		return status;
2556
2557	case IOCTL_BCM_SET_ACTIVE_SECTION:
2558		status = bcm_char_ioctl_set_active_section(argp, ad);
2559		return status;
2560
2561	case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION:
2562		/* Right Now we are taking care of only DSD */
2563		ad->bAllDSDWriteAllow = false;
2564		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2565				"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
2566		status = STATUS_SUCCESS;
2567		break;
2568
2569	case IOCTL_BCM_COPY_SECTION:
2570		status = bcm_char_ioctl_copy_section(argp, ad);
2571		return status;
2572
2573	case IOCTL_BCM_GET_FLASH_CS_INFO:
2574		status = bcm_char_ioctl_get_flash_cs_info(argp, ad);
2575		return status;
2576
2577	case IOCTL_BCM_SELECT_DSD:
2578		status = bcm_char_ioctl_select_dsd(argp, ad);
2579		return status;
2580
2581	case IOCTL_BCM_NVM_RAW_READ:
2582		status = bcm_char_ioctl_nvm_raw_read(argp, ad);
2583		return status;
2584
2585	case IOCTL_BCM_CNTRLMSG_MASK:
2586		status = bcm_char_ioctl_cntrlmsg_mask(argp, ad, tarang);
2587		return status;
2588
2589	case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
2590		status = bcm_char_ioctl_get_device_driver_info(argp, ad);
2591		return status;
2592
2593	case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
2594		status = bcm_char_ioctl_time_since_net_entry(argp, ad);
2595		return status;
2596
2597	case IOCTL_CLOSE_NOTIFICATION:
2598		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2599				"IOCTL_CLOSE_NOTIFICATION");
2600		break;
2601
2602	default:
2603		pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
2604		status = STATUS_FAILURE;
2605		break;
2606	}
2607	return status;
2608}
2609
2610
2611static const struct file_operations bcm_fops = {
2612	.owner    = THIS_MODULE,
2613	.open     = bcm_char_open,
2614	.release  = bcm_char_release,
2615	.read     = bcm_char_read,
2616	.unlocked_ioctl    = bcm_char_ioctl,
2617	.llseek = no_llseek,
2618};
2619
2620int register_control_device_interface(struct bcm_mini_adapter *ad)
2621{
2622
2623	if (ad->major > 0)
2624		return ad->major;
2625
2626	ad->major = register_chrdev(0, DEV_NAME, &bcm_fops);
2627	if (ad->major < 0) {
2628		pr_err(DRV_NAME ": could not created character device\n");
2629		return ad->major;
2630	}
2631
2632	ad->pstCreatedClassDevice = device_create(bcm_class, NULL,
2633						       MKDEV(ad->major, 0),
2634						       ad, DEV_NAME);
2635
2636	if (IS_ERR(ad->pstCreatedClassDevice)) {
2637		pr_err(DRV_NAME ": class device create failed\n");
2638		unregister_chrdev(ad->major, DEV_NAME);
2639		return PTR_ERR(ad->pstCreatedClassDevice);
2640	}
2641
2642	return 0;
2643}
2644
2645void unregister_control_device_interface(struct bcm_mini_adapter *ad)
2646{
2647	if (ad->major > 0) {
2648		device_destroy(bcm_class, MKDEV(ad->major, 0));
2649		unregister_chrdev(ad->major, DEV_NAME);
2650	}
2651}
2652
2653