aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/Bcmchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm/Bcmchar.c')
-rw-r--r--drivers/staging/bcm/Bcmchar.c2438
1 files changed, 2438 insertions, 0 deletions
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
new file mode 100644
index 000000000000..77fdfe24d999
--- /dev/null
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -0,0 +1,2438 @@
+#include <linux/fs.h>
+
+#include "headers.h"
+/***************************************************************
+* Function - bcm_char_open()
+*
+* Description - This is the "open" entry point for the character
+* driver.
+*
+* Parameters - inode: Pointer to the Inode structure of char device
+* filp : File pointer of the char device
+*
+* Returns - Zero(Success)
+****************************************************************/
+static struct class *bcm_class = NULL;
+static int bcm_char_open(struct inode *inode, struct file * filp)
+{
+ PMINI_ADAPTER Adapter = NULL;
+ PPER_TARANG_DATA pTarang = NULL;
+
+ Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ pTarang = (PPER_TARANG_DATA)kmalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
+ if (!pTarang)
+ return -ENOMEM;
+
+ memset (pTarang, 0, sizeof(PER_TARANG_DATA));
+ pTarang->Adapter = Adapter;
+ pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB) ;
+
+ down(&Adapter->RxAppControlQueuelock);
+ pTarang->next = Adapter->pTarangs;
+ Adapter->pTarangs = pTarang;
+ up(&Adapter->RxAppControlQueuelock);
+
+ /* Store the Adapter structure */
+ filp->private_data = pTarang;
+
+ /*Start Queuing the control response Packets*/
+ atomic_inc(&Adapter->ApplicationRunning);
+
+ nonseekable_open(inode, filp);
+ return 0;
+}
+static int bcm_char_release(struct inode *inode, struct file *filp)
+{
+ PPER_TARANG_DATA pTarang, tmp, ptmp;
+ PMINI_ADAPTER Adapter=NULL;
+ struct sk_buff * pkt, * npkt;
+
+ pTarang = (PPER_TARANG_DATA)filp->private_data;
+
+ if(pTarang == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ptarang is null\n");
+ return 0;
+ }
+
+ Adapter = pTarang->Adapter;
+
+ down( &Adapter->RxAppControlQueuelock);
+
+ tmp = Adapter->pTarangs;
+ for ( ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next )
+ {
+ if ( tmp == pTarang )
+ break;
+ }
+
+ if ( tmp )
+ {
+ if ( !ptmp )
+ Adapter->pTarangs = tmp->next;
+ else
+ ptmp->next = tmp->next;
+ }
+
+ else
+ {
+ up( &Adapter->RxAppControlQueuelock);
+ return 0;
+ }
+
+ pkt = pTarang->RxAppControlHead;
+ while ( pkt )
+ {
+ npkt = pkt->next;
+ kfree_skb(pkt);
+ pkt = npkt;
+ }
+
+ up( &Adapter->RxAppControlQueuelock);
+
+ /*Stop Queuing the control response Packets*/
+ atomic_dec(&Adapter->ApplicationRunning);
+
+ bcm_kfree(pTarang);
+
+ /* remove this filp from the asynchronously notified filp's */
+ filp->private_data = NULL;
+ return 0;
+}
+
+static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
+{
+ PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data;
+ PMINI_ADAPTER Adapter = pTarang->Adapter;
+ struct sk_buff* Packet = NULL;
+ UINT PktLen = 0;
+ int wait_ret_val=0;
+
+ wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
+ (pTarang->RxAppControlHead || Adapter->device_removed));
+ if((wait_ret_val == -ERESTARTSYS))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Exiting as i've been asked to exit!!!\n");
+ return wait_ret_val;
+ }
+
+ if(Adapter->device_removed)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device Removed... Killing the Apps...\n");
+ return -ENODEV;
+ }
+
+ if(FALSE == Adapter->fw_download_done)
+ return -EACCES;
+
+ down( &Adapter->RxAppControlQueuelock);
+
+ if(pTarang->RxAppControlHead)
+ {
+ Packet = pTarang->RxAppControlHead;
+ DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
+ pTarang->AppCtrlQueueLen--;
+ }
+
+ up(&Adapter->RxAppControlQueuelock);
+
+ if(Packet)
+ {
+ PktLen = Packet->len;
+ if(copy_to_user(buf, Packet->data, PktLen))
+ {
+ bcm_kfree_skb(Packet);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nReturning from copy to user failure \n");
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read %d Bytes From Adapter packet = 0x%p by process %d!\n", PktLen, Packet, current->pid);
+ bcm_kfree_skb(Packet);
+ }
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<====\n");
+ return PktLen;
+}
+
+static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
+{
+ PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data;
+ void __user *argp = (void __user *)argp;
+ PMINI_ADAPTER Adapter = pTarang->Adapter;
+ INT Status = STATUS_FAILURE;
+ IOCTL_BUFFER IoBuffer={};
+#ifndef BCM_SHM_INTERFACE
+ int timeout = 0;
+#endif
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
+
+ if(_IOC_TYPE(cmd) != BCM_IOCTL)
+ return -EFAULT;
+ if(_IOC_DIR(cmd) & _IOC_READ)
+ Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+ else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
+ Status = STATUS_SUCCESS;
+
+ if(Status)
+ return -EFAULT;
+
+ if(Adapter->device_removed)
+ {
+ return -EFAULT;
+ }
+
+ if(FALSE == Adapter->fw_download_done)
+ {
+ switch (cmd)
+ {
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ return -EACCES;
+ default:
+ break;
+ }
+ }
+
+ Status = vendorextnIoctl(Adapter, cmd, arg);
+ if(Status != CONTINUE_COMMON_PATH )
+ {
+ return Status;
+ }
+
+ switch(cmd){
+ // Rdms for Swin Idle...
+ case IOCTL_BCM_REGISTER_READ_PRIVATE:
+ {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff = NULL;
+ UINT Bufflen = 0;
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user((PCHAR)&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4;
+ temp_buff = (PCHAR)kmalloc(Bufflen, GFP_KERNEL);
+ if(!temp_buff)
+ {
+ return STATUS_FAILURE;
+ }
+ if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, Bufflen);
+ if(Status != STATUS_SUCCESS)
+ {
+ bcm_kfree(temp_buff);
+ return Status;
+ }
+ if(copy_to_user(IoBuffer.OutputBuffer,
+ (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength))
+ {
+ Status = -EFAULT;
+ }
+ bcm_kfree(temp_buff);
+ break;
+ }
+ case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
+ {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar=0;
+ /* Copy Ioctl Buffer structure */
+
+ if(copy_from_user(&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ /* Get WrmBuffer structure */
+ if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1)||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ Status = -EFAULT;
+ break;
+ }
+ Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sizeof(ULONG));
+ if(Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
+
+ case IOCTL_BCM_REGISTER_READ:
+ case IOCTL_BCM_EEPROM_REGISTER_READ:
+ {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff = NULL;
+ UINT uiTempVar = 0;
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
+ Status = -EACCES;
+ break;
+ }
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+ if(!temp_buff)
+ {
+ return STATUS_FAILURE;
+ }
+ if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ if(
+#if !defined(BCM_SHM_INTERFACE)
+ (((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+#endif
+ ((ULONG)sRdmBuffer.Register & 0x3)
+ )
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
+ (int)sRdmBuffer.Register);
+ Status = -EINVAL;
+ break;
+ }
+
+ uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
+ Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, IoBuffer.OutputLength);
+ if(Status != STATUS_SUCCESS)
+ {
+ bcm_kfree(temp_buff);
+ return Status;
+ }
+ if(copy_to_user(IoBuffer.OutputBuffer,
+ (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength))
+ {
+ Status = -EFAULT;
+ }
+ bcm_kfree(temp_buff);
+ break;
+ }
+ case IOCTL_BCM_REGISTER_WRITE:
+ case IOCTL_BCM_EEPROM_REGISTER_WRITE:
+ {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar=0;
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
+ Status = -EACCES;
+ break;
+ }
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user((PCHAR)&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ /* Get WrmBuffer structure */
+ if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if(
+#if !defined(BCM_SHM_INTERFACE)
+
+ (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+#endif
+ ((ULONG)sWrmBuffer.Register & 0x3)
+ )
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n",
+ (int)sWrmBuffer.Register);
+ Status = -EINVAL;
+ break;
+ }
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1)||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
+ if(Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ {
+ UCHAR ucResetValue[4];
+ UINT value =0;
+ UINT uiBit = 0;
+ UINT uiOperation = 0;
+
+ GPIO_INFO gpio_info = {0};
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
+ Status = -EACCES;
+ break;
+ }
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ uiBit = gpio_info.uiGpioNumber;
+ uiOperation = gpio_info.uiGpioValue;
+
+ value= (1<<uiBit);
+
+ if(IsReqGpioIsLedInNVM(Adapter,value) ==FALSE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",value);
+ Status = -EINVAL;
+ break;
+ }
+
+
+ if(uiOperation)//Set - setting 1
+ {
+ //Set the gpio output register
+ Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG ,
+ (PUINT)(&value), sizeof(UINT));
+ if(Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit);
+ break;
+ }
+ }
+ else//Unset - setting 0
+ {
+ //Set the gpio output register
+ Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG ,
+ (PUINT)(&value), sizeof(UINT));
+ if(Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit);
+ break;
+ }
+ }
+
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
+ (PUINT)ucResetValue, sizeof(UINT));
+ if (STATUS_SUCCESS != Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed");
+ break;
+ }
+ //Set the gpio mode register to output
+ *(UINT*)ucResetValue |= (1<<uiBit);
+ Status = wrmaltWithLock(Adapter,GPIO_MODE_REGISTER ,
+ (PUINT)ucResetValue, sizeof(UINT));
+ if(Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO to output Mode\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
+ break;
+ }
+ }
+ break;
+ case BCM_LED_THREAD_STATE_CHANGE_REQ:
+ {
+
+ USER_THREAD_REQ threadReq = {0};
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"User made LED thread InActive");
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
+ Status = -EACCES;
+ break;
+ }
+ Status =copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+
+ Status= copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the InputBuffer from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+ //if LED thread is running(Actively or Inactively) set it state to make inactive
+ if(Adapter->LEDInfo.led_thread_running)
+ {
+ if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req");
+ Adapter->DriverState = LED_THREAD_ACTIVE;
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req.....");
+ Adapter->DriverState = LED_THREAD_INACTIVE;
+ }
+
+ //signal thread.
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+
+ }
+ }
+ break;
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ {
+ ULONG uiBit = 0;
+ UCHAR ucRead[4];
+ GPIO_INFO gpio_info = {0};
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ Status = -EACCES;
+ break;
+ }
+ if(copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ Status = -EFAULT;
+ break;
+ }
+ if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ uiBit = gpio_info.uiGpioNumber;
+ //Set the gpio output register
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ (PUINT)ucRead, sizeof(UINT));
+ if(Status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
+ return Status;
+ }
+
+ }
+ break;
+ case IOCTL_BCM_GPIO_MULTI_REQUEST:
+ {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
+ PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
+
+ memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO));
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ Status = -EINVAL;
+ break;
+ }
+ Status = copy_from_user( (PCHAR)&IoBuffer, argp, sizeof( IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+
+ Status = copy_from_user( &gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+ if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
+ Status = -EINVAL;
+ break;
+ }
+
+ /* Set the gpio output register */
+
+ if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
+ ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand))
+ {
+ /* Set 1's in GPIO OUTPUT REGISTER */
+ *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
+
+ if( *(UINT*) ucResetValue)
+ Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG));
+
+ if( Status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
+ return Status;
+ }
+
+ /* Clear to 0's in GPIO OUTPUT REGISTER */
+ *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
+
+ if( *(UINT*) ucResetValue)
+ Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG));
+
+ if( Status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." );
+ return Status;
+ }
+ }
+
+ if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
+ {
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+
+ if(Status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed.");
+ return Status;
+ }
+
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
+ }
+
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+ }
+ break;
+ case IOCTL_BCM_GPIO_MODE_REQUEST:
+ {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
+ PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode;
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ Status = -EINVAL;
+ break;
+ }
+ Status = copy_from_user(&IoBuffer, argp, sizeof( IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+
+ Status = copy_from_user( &gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+
+ Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT));
+ if( STATUS_SUCCESS != Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed");
+ return Status;
+ }
+
+ //Validating the request
+ if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
+ Status = -EINVAL;
+ break;
+ }
+
+ if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
+ {
+ /* write all OUT's (1's) */
+ *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+ /* write all IN's (0's) */
+ *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* Currently implemented return the modes of all GPIO's
+ * else needs to bit AND with mask
+ * */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue;
+
+ Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG));
+ if( Status == STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed");
+ Status = -EFAULT;
+ break;
+ }
+ }
+ else /* if uiGPIOMask is 0 then return mode register configuration */
+ {
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue;
+ }
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
+ Status = -EFAULT;
+ break;
+ }
+ }
+ break;
+
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ {
+ PVOID pvBuffer=NULL;
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if(!pvBuffer)
+ {
+ return -ENOMEM;
+ }
+
+ if(copy_from_user(pvBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ Status = -EFAULT;
+ bcm_kfree(pvBuffer);
+ break;
+ }
+
+ down(&Adapter->LowPowerModeSync);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
+ !Adapter->bPreparingForLowPowerMode,
+ (1 * HZ));
+ if(Status == -ERESTARTSYS)
+ goto cntrlEnd;
+
+ if(Adapter->bPreparingForLowPowerMode)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n");
+ Status = STATUS_FAILURE ;
+ goto cntrlEnd ;
+ }
+ Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
+ cntrlEnd:
+ up(&Adapter->LowPowerModeSync);
+ bcm_kfree(pvBuffer);
+ break;
+ }
+#ifndef BCM_SHM_INTERFACE
+ case IOCTL_BCM_BUFFER_DOWNLOAD_START:
+ {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ;
+ if(NVMAccess)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+ if(!down_trylock(&Adapter->fw_download_sema))
+ {
+ Adapter->bBinDownloaded=FALSE;
+ Adapter->fw_download_process_pid=current->pid;
+ Adapter->bCfgDownloaded=FALSE;
+ Adapter->fw_download_done=FALSE;
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+ Status = reset_card_proc(Adapter);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "reset_card_proc Failed!\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+ mdelay(10);
+ }
+ else
+ {
+
+ Status = -EBUSY;
+
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+ case IOCTL_BCM_BUFFER_DOWNLOAD:
+ {
+ FIRMWARE_INFO *psFwInfo=NULL;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+ do{
+ if(!down_trylock(&Adapter->fw_download_sema))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n");
+ Status=-EINVAL;
+ break;
+ }
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
+ Status = -EFAULT;
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n",
+ IoBuffer.InputLength);
+ psFwInfo=kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+ if(!psFwInfo)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Failed to allocate buffer!!!!\n");
+ Status = -ENOMEM;
+ break;
+ }
+ if(copy_from_user(psFwInfo, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from_user 2 failed\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ if(!psFwInfo->pvMappedFirmwareAddress ||
+ (psFwInfo->u32FirmwareLength == 0))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
+ psFwInfo->u32FirmwareLength);
+ Status = -EINVAL;
+ break;
+ }
+ Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+ if(Status != STATUS_SUCCESS)
+ {
+ if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
+ }
+ //up(&Adapter->fw_download_sema);
+
+ if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
+ {
+ Adapter->DriverState = DRIVER_INIT;
+ Adapter->LEDInfo.bLedInitDone = FALSE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ }
+ break ;
+ }while(0);
+
+ if(Status != STATUS_SUCCESS)
+ up(&Adapter->fw_download_sema);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
+ bcm_kfree(psFwInfo);
+ break;
+ }
+ case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
+ {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if(NVMAccess)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n");
+ up(&Adapter->fw_download_sema);
+ return -EACCES;
+ }
+ if(down_trylock(&Adapter->fw_download_sema))
+ {
+ Adapter->bBinDownloaded=TRUE;
+ Adapter->bCfgDownloaded=TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ atomic_set(&Adapter->RxRollOverCount, 0);
+ Adapter->CurrNumRecvDescs=0;
+ Adapter->downloadDDR = 0;
+
+ //setting the Mips to Run
+ Status = run_card_proc(Adapter);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+ else
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n");
+ mdelay(10);
+ /* Wait for MailBox Interrupt */
+ if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
+ }
+ timeout = 5*HZ;
+ Adapter->waiting_to_fw_download_done = FALSE;
+ wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+ Adapter->waiting_to_fw_download_done, timeout);
+ Adapter->fw_download_process_pid=INVALID_PID;
+ Adapter->fw_download_done=TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ atomic_set(&Adapter->cntrlpktCnt,0);
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+
+ if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
+ {
+ Adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ if(!timeout)
+ {
+ Status = -ENODEV;
+ }
+ }
+ else
+ {
+ Status = -EINVAL;
+ }
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+#endif
+ case IOCTL_BE_BUCKET_SIZE:
+ Adapter->BEBucketSize = *(PULONG)arg;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_RTPS_BUCKET_SIZE:
+ Adapter->rtPSBucketSize = *(PULONG)arg;
+ Status = STATUS_SUCCESS;
+ break;
+ case IOCTL_CHIP_RESET:
+ {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if(NVMAccess)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+ down(&Adapter->RxAppControlQueuelock);
+ Status = reset_card_proc(Adapter);
+ flushAllAppQ();
+ up(&Adapter->RxAppControlQueuelock);
+ up(&Adapter->NVMRdmWrmLock);
+ ResetCounters(Adapter);
+ break;
+ }
+ case IOCTL_QOS_THRESHOLD:
+ {
+ USHORT uiLoopIndex;
+ for(uiLoopIndex = 0 ; uiLoopIndex < NO_OF_QUEUES ; uiLoopIndex++)
+ {
+ Adapter->PackInfo[uiLoopIndex].uiThreshold = *(PULONG)arg;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ case IOCTL_DUMP_PACKET_INFO:
+
+ DumpPackInfo(Adapter);
+ DumpPhsRules(&Adapter->stBCMPhsContext);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_GET_PACK_INFO:
+ if(copy_to_user(argp, &Adapter->PackInfo,
+ sizeof(PacketInfo)*NO_OF_QUEUES))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ case IOCTL_BCM_SWITCH_TRANSFER_MODE:
+ {
+ UINT uiData = 0;
+ if(copy_from_user(&uiData, argp, sizeof(UINT)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if(uiData) /* Allow All Packets */
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
+ Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
+ }
+ else /* Allow IP only Packets */
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ case IOCTL_BCM_GET_DRIVER_VERSION:
+ {
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if(copy_to_user(IoBuffer.OutputBuffer,
+ VER_FILEVERSION_STR, (UINT)IoBuffer.OutputLength))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_BCM_GET_CURRENT_STATUS:
+ {
+ LINK_STATE *plink_state = NULL;
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
+ Status = -EFAULT;
+ break;
+ }
+ plink_state = (LINK_STATE*)arg;
+ plink_state->bIdleMode = (UCHAR)Adapter->IdleMode;
+ plink_state->bShutdownMode = Adapter->bShutStatus;
+ plink_state->ucLinkStatus = (UCHAR)Adapter->LinkStatus;
+ if(copy_to_user(IoBuffer.OutputBuffer,
+ (PUCHAR)plink_state, (UINT)IoBuffer.OutputLength))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
+ Status = -EFAULT;
+ break;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IOCTL_BCM_SET_MAC_TRACING:
+ {
+ UINT tracing_flag;
+ /* copy ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if(copy_from_user(&tracing_flag, IoBuffer.InputBuffer,sizeof(UINT)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+ if (tracing_flag)
+ Adapter->pTarangs->MacTracingEnabled = TRUE;
+ else
+ Adapter->pTarangs->MacTracingEnabled = FALSE;
+ break;
+ }
+ case IOCTL_BCM_GET_DSX_INDICATION:
+ {
+ ULONG ulSFId=0;
+ if(copy_from_user((PCHAR)&IoBuffer, argp,
+ sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid IO buffer!!!" );
+ Status = -EFAULT;
+ break;
+ }
+ if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Mismatch req: %lx needed is =0x%zx!!!",
+ IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
+ return -EINVAL;
+ }
+ if(copy_from_user(&ulSFId, IoBuffer.InputBuffer,
+ sizeof(ulSFId)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Invalid SFID!!! %lu", ulSFId );
+ Status = -EFAULT;
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId );
+ get_dsx_sf_data_to_application(Adapter, ulSFId,
+ IoBuffer.OutputBuffer);
+ Status=STATUS_SUCCESS;
+ }
+ break;
+ case IOCTL_BCM_GET_HOST_MIBS:
+ {
+ PCHAR temp_buff;
+
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from user for IoBuff failed\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length Check failed %lu %zd\n", IoBuffer.OutputLength,
+ sizeof(S_MIBS_HOST_STATS_MIBS));
+ return -EINVAL;
+ }
+
+ temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+
+ if(!temp_buff)
+ {
+ return STATUS_FAILURE;
+ }
+
+ Status = ProcessGetHostMibs(Adapter,
+ (PUCHAR)temp_buff, IoBuffer.OutputLength);
+
+ Status = GetDroppedAppCntrlPktMibs((PVOID)temp_buff,
+ (PPER_TARANG_DATA)filp->private_data);
+
+ if(copy_to_user(IoBuffer.OutputBuffer,(PCHAR)temp_buff,
+ sizeof(S_MIBS_HOST_STATS_MIBS)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy to user failed\n");
+ bcm_kfree(temp_buff);
+ return -EFAULT;
+ }
+
+ bcm_kfree(temp_buff);
+ break;
+ }
+
+ case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
+ if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode))
+ {
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ #if 0
+ Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
+ InterfaceAbortIdlemode (Adapter, Adapter->usIdleModePattern);
+ #endif
+ }
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_BULK_WRM:
+ {
+ PBULKWRM_BUFFER pBulkBuffer;
+ UINT uiTempVar=0;
+ PCHAR pvBuffer = NULL;
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
+ Status = -EACCES;
+ break;
+ }
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if(!pvBuffer)
+ {
+ return -ENOMEM;
+ break;
+ }
+
+ /* Get WrmBuffer structure */
+ if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ {
+ bcm_kfree(pvBuffer);
+ Status = -EFAULT;
+ break;
+ }
+
+ pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
+
+ if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
+ ((ULONG)pBulkBuffer->Register & 0x3))
+ {
+ bcm_kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register);
+ Status = -EINVAL;
+ break;
+ }
+
+
+ uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
+ if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE)
+ && ((uiTempVar == EEPROM_REJECT_REG_1)||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE))
+ {
+ bcm_kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ if(pBulkBuffer->SwapEndian == FALSE)
+ Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+ else
+ Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+
+ if(Status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
+ }
+
+ bcm_kfree(pvBuffer);
+ break;
+ }
+
+ case IOCTL_BCM_GET_NVM_SIZE:
+ {
+
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ //IOLog("failed NVM first");
+ Status = -EFAULT;
+ break;
+ }
+ if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) {
+ if(copy_to_user(IoBuffer.OutputBuffer,
+ (unsigned char *)&Adapter->uiNVMDSDSize, (UINT)sizeof(UINT)))
+ {
+ Status = -EFAULT;
+ return Status;
+ }
+ }
+
+ Status = STATUS_SUCCESS ;
+ }
+ break;
+
+ case IOCTL_BCM_CAL_INIT :
+
+ {
+ UINT uiSectorSize = 0 ;
+ if(Adapter->eNVMType == NVM_FLASH)
+ {
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy From User space failed. status :%d", Status);
+ return -EFAULT;
+ }
+ uiSectorSize = *((PUINT)(IoBuffer.InputBuffer)); /* FIXME: unchecked __user access */
+ if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE))
+ {
+
+ Status = copy_to_user(IoBuffer.OutputBuffer,
+ (unsigned char *)&Adapter->uiSectorSize ,
+ (UINT)sizeof(UINT));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status);
+ return -EFAULT;
+ }
+ }
+ else
+ {
+ if(IsFlash2x(Adapter))
+ {
+ Status = copy_to_user(IoBuffer.OutputBuffer,
+ (unsigned char *)&Adapter->uiSectorSize ,
+ (UINT)sizeof(UINT));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status);
+ return -EFAULT;
+ }
+
+ }
+ else
+ {
+ if((TRUE == Adapter->bShutStatus) ||
+ (TRUE == Adapter->IdleMode))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n");
+ return -EACCES;
+ }
+
+ Adapter->uiSectorSize = uiSectorSize ;
+ BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize);
+ }
+ }
+ Status = STATUS_SUCCESS ;
+ }
+ else
+ {
+ Status = STATUS_FAILURE;
+ }
+ }
+ break;
+ case IOCTL_BCM_SET_DEBUG :
+ {
+ USER_BCM_DBG_STATE sUserDebugState;
+
+// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG );
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
+ Status = copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy from user failed\n");
+ Status = -EFAULT;
+ break;
+ }
+ Status = copy_from_user(&sUserDebugState,IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IoBuffer.InputBuffer failed");
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
+ sUserDebugState.OnOff, sUserDebugState.Type);
+ //sUserDebugState.Subtype <<= 1;
+ sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
+
+ // Update new 'DebugState' in the Adapter
+ Adapter->stDebugState.type |= sUserDebugState.Type;
+ /* Subtype: A bitmap of 32 bits for Subtype per Type.
+ * Valid indexes in 'subtype' array: 1,2,4,8
+ * corresponding to valid Type values. Hence we can use the 'Type' field
+ * as the index value, ignoring the array entries 0,3,5,6,7 !
+ */
+ if (sUserDebugState.OnOff)
+ Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
+ else
+ Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
+
+ BCM_SHOW_DEBUG_BITMAP(Adapter);
+
+ }
+ break;
+ case IOCTL_BCM_NVM_READ:
+ case IOCTL_BCM_NVM_WRITE:
+ {
+
+ NVM_READWRITE stNVMReadWrite = {};
+ PUCHAR pReadData = NULL;
+ void __user * pBuffertobeCopied = NULL;
+ ULONG ulDSDMagicNumInUsrBuff = 0 ;
+ struct timeval tv0, tv1;
+ memset(&tv0,0,sizeof(struct timeval));
+ memset(&tv1,0,sizeof(struct timeval));
+ if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0))
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ if(IsFlash2x(Adapter))
+ {
+ if((Adapter->eActiveDSD != DSD0) &&
+ (Adapter->eActiveDSD != DSD1) &&
+ (Adapter->eActiveDSD != DSD2))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked");
+ return STATUS_FAILURE ;
+ }
+ }
+
+ /* Copy Ioctl Buffer structure */
+
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copy_from_user failed\n");
+ Status = -EFAULT;
+ break;
+ }
+ if(IOCTL_BCM_NVM_READ == cmd)
+ pBuffertobeCopied = IoBuffer.OutputBuffer;
+ else
+ pBuffertobeCopied = IoBuffer.InputBuffer;
+
+ if(copy_from_user(&stNVMReadWrite, pBuffertobeCopied,sizeof(NVM_READWRITE)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ //
+ // Deny the access if the offset crosses the cal area limit.
+ //
+ if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize)
+ {
+ //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);
+ Status = STATUS_FAILURE;
+ break;
+ }
+
+ pReadData =(PCHAR)kmalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
+
+ if(!pReadData)
+ return -ENOMEM;
+
+ memset(pReadData,0,stNVMReadWrite.uiNumBytes);
+
+ if(copy_from_user(pReadData, stNVMReadWrite.pBuffer,
+ stNVMReadWrite.uiNumBytes))
+ {
+ Status = -EFAULT;
+ bcm_kfree(pReadData);
+ break;
+ }
+
+ do_gettimeofday(&tv0);
+ if(IOCTL_BCM_NVM_READ == cmd)
+ {
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadData);
+ return -EACCES;
+ }
+
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadData,
+ stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
+
+ up(&Adapter->NVMRdmWrmLock);
+
+ if(Status != STATUS_SUCCESS)
+ {
+ bcm_kfree(pReadData);
+ return Status;
+ }
+ if(copy_to_user(stNVMReadWrite.pBuffer,
+ pReadData, (UINT)stNVMReadWrite.uiNumBytes))
+ {
+ bcm_kfree(pReadData);
+ Status = -EFAULT;
+ }
+ }
+ else
+ {
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadData);
+ return -EACCES;
+ }
+
+ Adapter->bHeaderChangeAllowed = TRUE ;
+ if(IsFlash2x(Adapter))
+ {
+ /*
+ New Requirement:-
+ DSD section updation will be allowed in two case:-
+ 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
+ 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
+ corrupted then user space program first modify the DSD header with valid DSD sig so
+ that this as well as further write may be worthwhile.
+
+ This restriction has been put assuming that if DSD sig is corrupted, DSD
+ data won't be considered valid.
+
+
+ */
+ Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD);
+ if(Status != STATUS_SUCCESS)
+ {
+ if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) ||
+ (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadData);
+ return Status;
+ }
+
+ ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
+ if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadData);
+ return Status;
+ }
+ }
+ }
+ Status = BeceemNVMWrite(Adapter, (PUINT )pReadData,
+ stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
+ if(IsFlash2x(Adapter))
+ BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD);
+
+ Adapter->bHeaderChangeAllowed = FALSE ;
+
+ up(&Adapter->NVMRdmWrmLock);
+
+
+ if(Status != STATUS_SUCCESS)
+ {
+ bcm_kfree(pReadData);
+ return Status;
+ }
+ }
+ do_gettimeofday(&tv1);
+ 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);
+
+
+ bcm_kfree(pReadData);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+ case IOCTL_BCM_FLASH2X_SECTION_READ :
+ {
+
+ FLASH2X_READWRITE sFlash2xRead = {0};
+ PUCHAR pReadBuff = NULL ;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT ReadBytes = 0;
+ UINT ReadOffset = 0;
+ char __user *OutPutBuff = NULL;
+
+ if(IsFlash2x(Adapter) != TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+
+ //Reading FLASH 2.x READ structure
+ Status = copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Input Buffer failed");
+ return -EFAULT;
+ }
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify);
+
+ //This was internal to driver for raw read. now it has ben exposed to user space app.
+ if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE)
+ return STATUS_FAILURE ;
+
+ NOB = sFlash2xRead.numOfBytes;
+ if(NOB > Adapter->uiSectorSize )
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB ;
+
+ ReadOffset = sFlash2xRead.offset ;
+ OutPutBuff = IoBuffer.OutputBuffer;
+
+
+ pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
+ if(pReadBuff == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadBuff);
+ return -EACCES;
+ }
+
+ while(NOB)
+ {
+
+ if(NOB > Adapter->uiSectorSize )
+ ReadBytes = Adapter->uiSectorSize;
+ else
+ ReadBytes = NOB;
+
+
+ //Reading the data from Flash 2.x
+
+ Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status);
+ break ;
+ }
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status);
+ Status = -EFAULT;
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if(NOB)
+ {
+ ReadOffset = ReadOffset + ReadBytes ;
+ OutPutBuff = OutPutBuff + ReadBytes ;
+ }
+
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadBuff);
+
+ }
+ break ;
+ case IOCTL_BCM_FLASH2X_SECTION_WRITE :
+ {
+ FLASH2X_READWRITE sFlash2xWrite = {0};
+ PUCHAR pWriteBuff = NULL;
+ void __user *InputAddr = NULL;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT WriteOffset = 0;
+ UINT WriteBytes = 0;
+
+ if(IsFlash2x(Adapter) != TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite
+ Adapter->bAllDSDWriteAllow = FALSE;
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+
+ //Reading FLASH 2.x READ structure
+ Status = copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reading of output Buffer from IOCTL buffer fails");
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify);
+ #if 0
+ if((sFlash2xWrite.Section == ISO_IMAGE1) ||(sFlash2xWrite.Section == ISO_IMAGE2) ||
+ (sFlash2xWrite.Section == DSD0) || (sFlash2xWrite.Section == DSD1) || (sFlash2xWrite.Section == DSD2))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"ISO/DSD Image write is not allowed.... ");
+ return STATUS_FAILURE ;
+ }
+ #endif
+ if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) &&
+ (sFlash2xWrite.Section != VSA2) )
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed");
+ return -EINVAL;
+ }
+
+ if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE)
+ return STATUS_FAILURE ;
+
+ InputAddr = sFlash2xWrite.pDataBuff;
+ WriteOffset = sFlash2xWrite.offset ;
+ NOB = sFlash2xWrite.numOfBytes;
+
+ if(NOB > Adapter->uiSectorSize )
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB ;
+
+ pWriteBuff = (PCHAR)kmalloc(BuffSize, GFP_KERNEL);
+ if(pWriteBuff == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+
+ //extracting the remainder of the given offset.
+ WriteBytes = Adapter->uiSectorSize ;
+ if(WriteOffset % Adapter->uiSectorSize)
+ WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
+ if(NOB < WriteBytes)
+ WriteBytes = NOB;
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pWriteBuff);
+ return -EACCES;
+ }
+
+ BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section);
+ do
+ {
+ Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status);
+ Status = -EFAULT;
+ break ;
+ }
+ BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes);
+ //Writing the data from Flash 2.x
+ Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify);
+
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
+ break ;
+ }
+
+ NOB = NOB - WriteBytes;
+ if(NOB)
+ {
+ WriteOffset = WriteOffset + WriteBytes ;
+ InputAddr = InputAddr + WriteBytes ;
+ if(NOB > Adapter->uiSectorSize )
+ WriteBytes = Adapter->uiSectorSize;
+ else
+ WriteBytes = NOB;
+ }
+
+
+ } while(NOB > 0);
+ BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section);
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pWriteBuff);
+ }
+ break ;
+ case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP :
+ {
+
+ PFLASH2X_BITMAP psFlash2xBitMap = NULL ;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+ if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Structure size mismatch Lib :0x%lx Driver :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH2X_BITMAP));
+ break;
+ }
+
+ psFlash2xBitMap = (PFLASH2X_BITMAP)kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
+ if(psFlash2xBitMap == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available");
+ return -ENOMEM ;
+ }
+ //Reading the Flash Sectio Bit map
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(psFlash2xBitMap);
+ return -EACCES;
+ }
+
+ BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
+ up(&Adapter->NVMRdmWrmLock);
+ Status = copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x bitMap failed");
+ bcm_kfree(psFlash2xBitMap);
+ return -EFAULT;
+ }
+ bcm_kfree(psFlash2xBitMap);
+ }
+ break ;
+ case IOCTL_BCM_SET_ACTIVE_SECTION :
+ {
+ FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
+
+ if(IsFlash2x(Adapter) != TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+
+ Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return -EFAULT;
+ }
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status);
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break ;
+ case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION :
+ {
+ //Right Now we are taking care of only DSD
+ Adapter->bAllDSDWriteAllow = FALSE ;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
+
+ #if 0
+ SECTION_TYPE section = 0 ;
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION Called");
+ Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+ Status = copy_from_user((PCHAR)section,(PCHAR)&IoBuffer, sizeof(INT));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of section type failed failed");
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", section);
+ if(section == DSD)
+ Adapter->ulFlashCalStart = Adapter->uiActiveDSDOffsetAtFwDld ;
+ else
+ Status = STATUS_FAILURE ;
+ #endif
+ Status = STATUS_SUCCESS ;
+ }
+ break ;
+ case IOCTL_BCM_COPY_SECTION :
+ {
+ FLASH2X_COPY_SECTION sCopySectStrut = {0};
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
+
+ Adapter->bAllDSDWriteAllow = FALSE ;
+ if(IsFlash2x(Adapter) != TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
+ return -EFAULT;
+ }
+
+ Status = copy_from_user(&sCopySectStrut,IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
+
+
+ if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
+ return -EINVAL;
+ }
+
+ if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
+ return -EINVAL;
+ }
+
+ if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different");
+ return -EINVAL;
+ }
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2)
+ {
+ if(IsNonCDLessDevice(Adapter))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!");
+ Status = -EINVAL ;
+ }
+ else if(sCopySectStrut.numOfBytes == 0)
+ {
+ Status = BcmCopyISO(Adapter,sCopySectStrut);
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed..");
+ Status = STATUS_FAILURE ;
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ }
+
+ Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
+ sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes);
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break ;
+ case IOCTL_BCM_GET_FLASH_CS_INFO :
+ {
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ Status = -EFAULT;
+ break;
+ }
+ if(Adapter->eNVMType != NVM_FLASH)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash");
+ Status = -EINVAL;
+ break;
+ }
+ if(IsFlash2x(Adapter) == TRUE)
+ {
+
+ if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. \nRequired size :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH2X_CS_INFO));
+ Status = -EINVAL;
+ break;
+ }
+
+ Status = copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x cs info failed");
+ Status = -EFAULT;
+ break;
+ }
+ }
+ else
+ {
+ if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. Required size :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH_CS_INFO));
+ Status = -EINVAL;
+ break;
+ }
+ Status = copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash CS info failed");
+ Status = -EFAULT;
+ break;
+ }
+
+ }
+ }
+ break ;
+ case IOCTL_BCM_SELECT_DSD :
+ {
+ UINT SectOfset = 0;
+ FLASH2X_SECTION_VAL eFlash2xSectionVal;
+ eFlash2xSectionVal = NO_SECTION_VAL ;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called");
+
+ if(IsFlash2x(Adapter) != TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+ Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal);
+ if((eFlash2xSectionVal != DSD0) &&
+ (eFlash2xSectionVal != DSD1) &&
+ (eFlash2xSectionVal != DSD2) )
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal);
+ return STATUS_FAILURE ;
+ }
+
+ SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal);
+ if(SectOfset == INVALID_OFFSET)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
+ return -EINVAL;
+ }
+
+ Adapter->bAllDSDWriteAllow = TRUE ;
+
+ Adapter->ulFlashCalStart = SectOfset ;
+ Adapter->eActiveDSD = eFlash2xSectionVal;
+ }
+ Status = STATUS_SUCCESS ;
+ break;
+
+ case IOCTL_BCM_NVM_RAW_READ :
+ {
+
+ NVM_READWRITE stNVMRead = {};
+ INT NOB ;
+ INT BuffSize ;
+ INT ReadOffset = 0;
+ UINT ReadBytes = 0 ;
+ PUCHAR pReadBuff = NULL ;
+ char __user *OutPutBuff = NULL ;
+
+ if(Adapter->eNVMType != NVM_FLASH)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash ");
+ return -EINVAL ;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
+ Status = -EFAULT;
+ break;
+ }
+
+ if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE)))
+ {
+ Status = -EFAULT;
+ break;
+ }
+
+ NOB = stNVMRead.uiNumBytes;
+ //In Raw-Read max Buff size : 64MB
+
+ if(NOB > DEFAULT_BUFF_SIZE)
+ BuffSize = DEFAULT_BUFF_SIZE;
+ else
+ BuffSize = NOB ;
+
+ ReadOffset = stNVMRead.uiOffset ;
+ OutPutBuff = stNVMRead.pBuffer;
+
+
+ pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
+ if(pReadBuff == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
+ Status = -ENOMEM;
+ break;
+ }
+ down(&Adapter->NVMRdmWrmLock);
+
+ if((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus ==TRUE) ||
+ (Adapter->bPreparingForLowPowerMode ==TRUE))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
+ bcm_kfree(pReadBuff);
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Adapter->bFlashRawRead = TRUE ;
+ while(NOB)
+ {
+ if(NOB > DEFAULT_BUFF_SIZE )
+ ReadBytes = DEFAULT_BUFF_SIZE;
+ else
+ ReadBytes = NOB;
+
+ //Reading the data from Flash 2.x
+ Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
+ break;
+ }
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status);
+ Status = -EFAULT;
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if(NOB)
+ {
+ ReadOffset = ReadOffset + ReadBytes ;
+ OutPutBuff = OutPutBuff + ReadBytes ;
+ }
+
+ }
+ Adapter->bFlashRawRead = FALSE ;
+ up(&Adapter->NVMRdmWrmLock);
+ bcm_kfree(pReadBuff);
+ break ;
+ }
+
+ case IOCTL_BCM_CNTRLMSG_MASK:
+ {
+ ULONG RxCntrlMsgBitMask = 0 ;
+
+ /* Copy Ioctl Buffer structure */
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space");
+ Status = -EFAULT;
+ break;
+ }
+
+ Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space");
+ Status = -EFAULT;
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
+ pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ;
+ }
+ break;
+ case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
+ {
+ DEVICE_DRIVER_INFO DevInfo;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
+ DevInfo.u32NVMType = Adapter->eNVMType;
+ DevInfo.u32InterfaceType = BCM_USB;
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ Status = -EFAULT;
+ break;
+ }
+ if(IoBuffer.OutputLength < sizeof(DevInfo))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length is less than actural buffer size");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"user passed buffer size :0x%lX, expected size :0x%zx",IoBuffer.OutputLength, sizeof(DevInfo));
+ Status = -EINVAL;
+ break;
+ }
+ Status = copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying Dev info structure to user space buffer failed");
+ Status = -EFAULT;
+ break;
+ }
+ }
+ break ;
+
+ case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
+ {
+ ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+ struct timeval tv = {0} ;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ Status = -EFAULT;
+ break;
+ }
+ if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length:0x%lx is less than expected buff size :0x%zX",IoBuffer.OutputLength,sizeof(ST_TIME_ELAPSED));
+ Status = -EINVAL;
+ break;
+ }
+
+ //stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = Adapter->liTimeSinceLastNetEntry;
+ do_gettimeofday(&tv);
+ stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = tv.tv_sec - Adapter->liTimeSinceLastNetEntry;
+
+ Status = copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED));
+ if(Status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying ST_TIME_ELAPSED structure to user space buffer failed");
+ Status = -EFAULT;
+ break;
+ }
+
+ }
+ break;
+
+ default:
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "wrong input %x",cmd);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In default ioctl %d\n", cmd);
+ Status = STATUS_FAILURE;
+
+ break;
+ }
+ return Status;
+}
+
+
+static struct file_operations bcm_fops = {
+ .owner = THIS_MODULE,
+ .open = bcm_char_open,
+ .release = bcm_char_release,
+ .read = bcm_char_read,
+ .unlocked_ioctl = bcm_char_ioctl,
+ .llseek = no_llseek,
+};
+
+
+int register_control_device_interface(PMINI_ADAPTER Adapter)
+{
+ if(Adapter->major>0)
+ return Adapter->major;
+ Adapter->major = register_chrdev(0, "tarang", &bcm_fops);
+ if(Adapter->major < 0)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "register_chrdev:Failed to registering WiMax control char device!");
+ return Adapter->major;
+ }
+
+ bcm_class = NULL;
+ bcm_class = class_create (THIS_MODULE, "tarang");
+ if(IS_ERR (bcm_class))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unable to create class\n");
+ unregister_chrdev(Adapter->major, "tarang");
+ Adapter->major = 0;
+ return -ENODEV;
+ }
+ Adapter->pstCreatedClassDevice = device_create (bcm_class, NULL,
+ MKDEV(Adapter->major, 0),
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)
+ NULL ,
+#endif
+ "tarang");
+
+ if(IS_ERR(Adapter->pstCreatedClassDevice))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "class device did not get created : %ld", PTR_ERR(Adapter->pstCreatedClassDevice) );
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Got Major No: %d", Adapter->major);
+ return 0;
+}
+
+void unregister_control_device_interface(PMINI_ADAPTER Adapter)
+{
+ if(Adapter->major > 0)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying class device");
+ device_destroy (bcm_class, MKDEV(Adapter->major, 0));
+ }
+ if(!IS_ERR(bcm_class))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying created class ");
+ class_destroy (bcm_class);
+ bcm_class = NULL;
+ }
+ if(Adapter->major > 0)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"unregistering character interface");
+ unregister_chrdev(Adapter->major, "tarang");
+ }
+
+}