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