/** * \fn wlanDrvIf_Start * \brief Start driver * * Called by network stack upon opening network interface (ifconfig up). * Can also be called from user application or CLI for flight mode. * Start the driver initialization process up to OPERATIONAL state. * * \note * \param dev - The driver network-interface handle * \return 0 if succeeded, error if driver not available * \sa wlanDrvIf_Stop */ int wlanDrvIf_Start (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Start()\n"); printk("%s\n", __func__); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver not created!\n"); return -ENODEV; } if (DRV_STATE_FAILED == drv->tCommon.eDriverState) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver failed!\n"); return -ENODEV; } /* * Insert Start command in DrvMain action queue, request driver scheduling * and wait for action completion (all init process). */ os_wake_lock_timeout_enable(drv); if (TI_OK != drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_START)) { return -ENODEV; } return 0; }
/** * \fn wlanDrvIf_Open * \brief Start driver * * Called by network stack upon opening network interface (ifconfig up). * Can also be called from user application or CLI for flight mode. * Start the driver initialization process up to OPERATIONAL state. * * \note * \param dev - The driver network-interface handle * \return 0 if succeeded, error if driver not available * \sa wlanDrvIf_Release */ int wlanDrvIf_Open (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); int status = 0; WLAN_OS_REPORT(("wlanDrvIf_Open()\n")); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Open() Driver not created!\n"); return -ENODEV; } if (drv->tCommon.eDriverState == DRV_STATE_FAILED) { ti_dprintf (TIWLAN_LOG_ERROR, "Driver in FAILED state!\n"); return -EPERM; } if (drv->tCommon.eDriverState != DRV_STATE_RUNNING) { status = wlanDrvIf_Start(dev); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) drv->netdev->hard_start_xmit = wlanDrvIf_Xmit; #else drv->netdev->netdev_ops = &tiwlan_ops_pri; #endif drv->netdev->addr_len = MAC_ADDR_LEN; netif_start_queue (dev); } return status; }
/** * \fn wlanDrvIf_Open * \brief Start driver * * Called by network stack upon opening network interface (ifconfig up). * Can also be called from user application or CLI for flight mode. * Start the driver initialization process up to OPERATIONAL state. * * \note * \param dev - The driver network-interface handle * \return 0 if succeeded, error if driver not available * \sa wlanDrvIf_Release */ int wlanDrvIf_Open (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Open()\n"); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Open() Driver not created!\n"); return -ENODEV; } if (drv->tCommon.eDriverState == DRV_STATE_FAILED) { ti_dprintf (TIWLAN_LOG_ERROR, "Driver in FAILED state!\n"); return -EPERM; } if (drv->tCommon.eDriverState != DRV_STATE_RUNNING) { wlanDrvIf_Start(dev); } #ifndef AP_MODE_ENABLED netif_start_queue (dev); /* Temporal, use wlanDrvIf_Enable/DisableTx in STA mode */ #endif /* register 3430 PM hooks in our SDIO driver */ #ifdef CONFIG_PM /*sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend);*/ #endif return 0; }
int wlanDrvIf_Open (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); int status = 0; ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Open()\n"); printk("%s\n", __func__); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Open() Driver not created!\n"); return -ENODEV; } if (drv->tCommon.eDriverState == DRV_STATE_STOPPED || drv->tCommon.eDriverState == DRV_STATE_IDLE) { status = wlanDrvIf_Start(dev); } /* * Finalize network interface setup */ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) drv->netdev->hard_start_xmit = wlanDrvIf_Xmit; #else drv->netdev->netdev_ops = &tiwlan_ops_pri; #endif drv->netdev->addr_len = MAC_ADDR_LEN; netif_start_queue (dev); return status; }
/** * \fn wlanDrvIf_SetupNetif * \brief Setup driver network interface * * Called in driver creation process. * Setup driver network interface. * * \note * \param drv - The driver object handle * \return 0 - OK, else - failure * \sa */ static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv) { struct net_device *dev; int res; /* Allocate network interface structure for the driver */ dev = alloc_etherdev (0); if (dev == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n"); return -ENOMEM; } /* Setup the network interface */ ether_setup (dev); NETDEV_SET_PRIVATE(dev,drv); drv->netdev = dev; strcpy (dev->name, TIWLAN_DRV_IF_NAME); netif_carrier_off (dev); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) dev->validate_addr = NULL; #endif /* the following is required on at least BSP 23.8 and higher. Without it, the Open function of the driver will not be called when trying to 'ifconfig up' the interface */ dev->open = wlanDrvIf_Open; dev->stop = wlanDrvIf_Release; dev->hard_start_xmit = wlanDrvIf_Xmit; dev->get_stats = wlanDrvIf_NetGetStat; dev->do_ioctl = NULL; #else dev->netdev_ops = &tiwlan_ops_pri; #endif dev->tx_queue_len = 100; /* Initialize Wireless Extensions interface (WEXT) */ wlanDrvWext_Init (dev); res = register_netdev (dev); if (res != 0) { ti_dprintf (TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res); kfree (dev); return res; } /* Setup power-management callbacks */ hPlatform_SetupPm(SuspendCb, ResumeCb, pDrvStaticHandle); /* On the latest Kernel there is no more support for the below macro. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) SET_MODULE_OWNER (dev); #endif return 0; }
/** * \fn wlanDrvIf_Stop * \brief Stop driver * * Called by network stack upon closing network interface (ifconfig down). * Can also be called from user application or CLI for flight mode. * Stop the driver and turn off the device. * * \note * \param dev - The driver network-interface handle * \return 0 (OK) * \sa wlanDrvIf_Start */ int wlanDrvIf_Stop (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Stop()\n"); if (DRV_STATE_FAILED == drv->tCommon.eDriverState) { return -ENODEV; } /* * Insert Stop command in DrvMain action queue, request driver scheduling * and wait for Stop process completion. */ os_printf("%s LINE %d\n", __func__, __LINE__); os_wake_lock_timeout_enable(drv); os_printf("%s LINE %d\n", __func__, __LINE__); if (TI_OK != drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_STOP)) { return -ENODEV; } os_printf("%s\n", __func__); return 0; }
/** * \fn wlanDrvIf_NetGetStat * \brief Provides driver statistics * * Provides driver Tx and Rx statistics to network stack. * * \note * \param dev - The driver network-interface handle * \return The statistics pointer * \sa */ static struct net_device_stats *wlanDrvIf_NetGetStat (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_NetGetStat()\n"); return &drv->stats; }
TI_INT32 IPC_EventSend(TI_HANDLE hAdapter, TI_UINT8* pEvData, TI_UINT32 EvDataSize) { struct sk_buff *skb; int res; TWlanDrvIfObj *drv = (TWlanDrvIfObj *) hAdapter; TI_UINT32 realSize = 0; TI_UINT32 msgSize; struct nlmsghdr *nlh; TI_UINT8 *msg; os_wake_lock_timeout_enable(drv); /* This event is targetted to the OS process Id 0 is not a valid pId for LINUX*/ if ((( IPC_EVENT_PARAMS *) pEvData) ->uProcessID == 0) { (( IPC_EVENT_PARAMS *) pEvData) ->pfEventCallback(( IPC_EV_DATA *) pEvData); return 0; } /* set the payload size */ msgSize = (( IPC_EV_DATA *) pEvData) ->uBufferSize + offsetof(IPC_EV_DATA,uBuffer); /* add the netlink header size */ realSize = NLMSG_SPACE(msgSize); /* allocate the complete message */ skb = dev_alloc_skb(realSize); if (!skb) { printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",realSize); return -1; } /* set the netlink header params */ nlh = NLMSG_PUT(skb, 0, 0, NLMSG_DONE, realSize - sizeof(*nlh)); /* get the payload pointer */ msg = (char *)NLMSG_DATA(nlh); /* copy the data to the payload */ memcpy(msg,pEvData,msgSize); NETLINK_CB(skb).pid = 0; /* from kernel */ #define RTMGRP_LINK 1 NETLINK_CB(skb).dst_group = RTMGRP_LINK; /* send the message*/ res = netlink_unicast(drv->wl_sock, skb, (( IPC_EVENT_PARAMS *) pEvData) ->uProcessID, MSG_DONTWAIT); /* Sanity checks. As far as we're concerned this error is unrecovarable.*/ if (res >= 0) { return 0; } nlmsg_failure: ti_dprintf(TIWLAN_LOG_INFO,"IPC kernel: did not send the netlink message\n"); return -1; }
int wlanDrvIf_Release (struct net_device *dev) { ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Release()\n"); /* Disable network interface queue */ netif_stop_queue (dev); return 0; }
/** * \fn wlanDrvIf_Release * \brief Stop driver * * Called by network stack upon closing network interface (ifconfig down). * Can also be called from user application or CLI for flight mode. * Stop the driver and turn off the device. * * \note * \param dev - The driver network-interface handle * \return 0 (OK) * \sa wlanDrvIf_Open */ int wlanDrvIf_Release (struct net_device *dev) { /* TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); */ ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Release()\n"); /* Disable network interface queue */ netif_stop_queue (dev); return 0; }
/** * \fn wlanDrvIf_Start * \brief Start driver * * Called by network stack upon opening network interface (ifconfig up). * Can also be called from user application or CLI for flight mode. * Start the driver initialization process up to OPERATIONAL state. * * \note * \param dev - The driver network-interface handle * \return 0 if succeeded, error if driver not available * \sa wlanDrvIf_Stop */ int wlanDrvIf_Start (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Start()\n"); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver not created!\n"); return -ENODEV; } /* * Insert Start command in DrvMain action queue, request driver scheduling * and wait for action completion (all init process). */ drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_START); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) /* * Finalize network interface setup */ netif_start_queue (dev); #ifdef AP_MODE_ENABLED netif_carrier_on (dev); #endif /* register 3430 PM hooks in our SDIO driver */ #if defined HOST_PLATFORM_OMAP3430 || defined HOST_PLATFORM_ZOOM2 || defined HOST_PLATFORM_ZOOM1 || defined HOST_PLATFORM_MX25 /*sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend);*/ #endif #endif return 0; }
/** * \fn wlanDrvIf_Start * \brief Start driver * * Called by network stack upon opening network interface (ifconfig up). * Can also be called from user application or CLI for flight mode. * Start the driver initialization process up to OPERATIONAL state. * * \note * \param dev - The driver network-interface handle * \return 0 if succeeded, error if driver not available * \sa wlanDrvIf_Stop */ int wlanDrvIf_Start (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Start()\n"); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver not created!\n"); return -ENODEV; } /*before inserting an action - check driver state*/ if (DRV_STATE_FAILED == drv->tCommon.eDriverState) { return -ENODEV; } os_wake_lock_timeout_enable(drv); drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_START); return 0; }
/** * \fn wlanDrvIf_UpdateDriverState * \brief Update the driver state * * The DrvMain uses this function to update the OAL with the driver steady state * that is relevant for the driver users. * * \note * \param hOs - The driver object handle * \param eDriverState - The new driver state * \return void * \sa */ void wlanDrvIf_UpdateDriverState (TI_HANDLE hOs, EDriverSteadyState eDriverState) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; ti_dprintf(TIWLAN_LOG_OTHER, "wlanDrvIf_UpdateDriverState(): State = %d\n", eDriverState); /* Save the new state */ drv->tCommon.eDriverState = eDriverState; /* If the new state is not RUNNING, replace the Tx handler to a dummy one. */ if (eDriverState != DRV_STATE_RUNNING) { drv->netdev->hard_start_xmit = wlanDrvIf_XmitDummy; } }
/** * \fn wlanDrvIf_Stop * \brief Stop driver * * Called by network stack upon closing network interface (ifconfig down). * Can also be called from user application or CLI for flight mode. * Stop the driver and turn off the device. * * \note * \param dev - The driver network-interface handle * \return 0 (OK) * \sa wlanDrvIf_Start */ int wlanDrvIf_Stop (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Stop()\n"); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) /* Disable network interface queue */ netif_stop_queue (dev); #endif /* * Insert Stop command in DrvMain action queue, request driver scheduling * and wait for Stop process completion. */ drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_STOP); return 0; }
/** * \fn wlanDrvIf_UpdateDriverState * \brief Update the driver state * * The DrvMain uses this function to update the OAL with the driver steady state * that is relevant for the driver users. * * \note * \param hOs - The driver object handle * \param eDriverState - The new driver state * \return void * \sa */ void wlanDrvIf_UpdateDriverState (TI_HANDLE hOs, EDriverSteadyState eDriverState) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; ti_dprintf(TIWLAN_LOG_OTHER, "wlanDrvIf_UpdateDriverState(): State = %d\n", eDriverState); /* Save the new state */ drv->tCommon.eDriverState = eDriverState; /* If the new state is not RUNNING, replace the Tx handler to a dummy one. */ if (eDriverState != DRV_STATE_RUNNING) { #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) drv->netdev->hard_start_xmit = wlanDrvIf_XmitDummy; #else drv->netdev->netdev_ops = &tiwlan_ops_dummy; #endif } }
int wlanDrvIf_Open (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); WLAN_OS_REPORT(("wlanDrvIf_Open()\n")); if (!drv->tCommon.hDrvMain) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Open() Driver not created!\n"); return -ENODEV; } wlanDrvIf_Start(dev); /* * Finalize network interface setup */ drv->netdev->hard_start_xmit = wlanDrvIf_Xmit; drv->netdev->addr_len = MAC_ADDR_LEN; netif_start_queue (dev); return 0; }
/** * \fn wlanDrvIf_Stop * \brief Stop driver * * Called by network stack upon closing network interface (ifconfig down). * Can also be called from user application or CLI for flight mode. * Stop the driver and turn off the device. * * \note * \param dev - The driver network-interface handle * \return 0 (OK) * \sa wlanDrvIf_Start */ int wlanDrvIf_Stop (struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Stop()\n"); /* Disable network interface queue */ netif_stop_queue (dev); /*before inserting an action - check driver state*/ if (DRV_STATE_FAILED == drv->tCommon.eDriverState) { return -ENODEV; } /* * Insert Stop command in DrvMain action queue, request driver scheduling * and wait for Stop process completion. */ if (TI_OK != drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_STOP)) { return -ENODEV; } return 0; }
/** * \fn wlanDrvIf_Create * \brief Create the driver instance * * Allocate driver object. * Initialize driver OS resources (IRQ, workqueue, events socket) * Setup driver network interface. * Create and link all driver modules. * * \note * \param void * \return 0 - OK, else - failure * \sa wlanDrvIf_Destroy */ static int wlanDrvIf_Create (void) { TWlanDrvIfObj *drv; int rc; /* Allocate driver's structure */ drv = kmalloc (sizeof(TWlanDrvIfObj), GFP_KERNEL); if (!drv) { return -ENOMEM; } #ifdef TI_DBG tb_init(TB_OPTION_NONE); #endif pDrvStaticHandle = drv; /* save for module destroy */ #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(TWlanDrvIfObj), GFP_KERNEL, sizeof(TWlanDrvIfObj)); #endif memset (drv, 0, sizeof(TWlanDrvIfObj)); /* #if defined HOST_PLATFORM_OMAP3430 || defined HOST_PLATFORM_ZOOM2 || defined HOST_PLATFORM_ZOOM1 if(g_external_board) { WLAN_OS_REPORT(("\nZoom2 use external board")); drv->irq = (OMAP_GPIO_IRQ(IRQ_GPIO_EXT)); } else { drv->irq = (OMAP_GPIO_IRQ(IRQ_GPIO)); } #endif */ drv->irq = tiwlan_ext_int_init(); drv->tCommon.eDriverState = DRV_STATE_IDLE; #ifdef AP_MODE_ENABLED /* for STA role, need to allocate another driver and to set STA role */ drv->tCommon.eIfRole = IF_ROLE_TYPE_AP; #endif drv->pWorkQueue = create_singlethread_workqueue (TIWLAN_DRV_NAME); if (!drv->pWorkQueue) { return -ENOMEM; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask, (void *)drv); #else INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask); #endif spin_lock_init (&drv->lock); /* Setup driver network interface. */ rc = wlanDrvIf_SetupNetif (drv); if (rc) { kfree (drv); return rc; } /* Create the events socket interface */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, THIS_MODULE ); #else drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE ); #endif if (drv->wl_sock == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); return -EINVAL; } /* Create all driver modules and link their handles */ drvMain_Create (drv, &drv->tCommon.hDrvMain, &drv->tCommon.hCmdHndlr, &drv->tCommon.hContext, &drv->tCommon.hTxDataQ, &drv->tCommon.hTxMgmtQ, &drv->tCommon.hTxCtrl, &drv->tCommon.hTWD, &drv->tCommon.hEvHandler, &drv->tCommon.hCmdDispatch, &drv->tCommon.hReport); /* * Initialize interrupts (or polling mode for debug): */ #ifdef PRIODIC_INTERRUPT /* Debug mode: Polling (the timer is started by HwInit process) */ drv->hPollTimer = os_timerCreate ((TI_HANDLE)drv, wlanDrvIf_PollIrqHandler, (TI_HANDLE)drv); #else /* Normal mode: Interrupts (the default mode) */ rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt); if (rc) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); return rc; } #ifdef HOST_PLATFORM_OMAP2430 set_irq_type (drv->irq, IRQT_FALLING); #endif #endif /* PRIODIC_INTERRUPT */ return 0; }
/** * \fn wlanDrvIf_SetupNetif * \brief Setup driver network interface * * Called in driver creation process. * Setup driver network interface. * * \note * \param drv - The driver object handle * \return 0 - OK, else - failure * \sa */ static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv) { struct net_device *dev; int res; /* Allocate network interface structure for the driver */ dev = alloc_etherdev (0); if (dev == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n"); return -ENOMEM; } /* Setup the network interface */ ether_setup (dev); /* the following is required on at least BSP 23.8 and higher. Without it, the Open function of the driver will not be called when trying to 'ifconfig up' the interface */ //#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) // dev->validate_addr = NULL; //#endif NETDEV_SET_PRIVATE(dev,drv); drv->netdev = dev; strcpy (dev->name, TIWLAN_DRV_IF_NAME); netif_carrier_off (dev); /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) dev->open = wlanDrvIf_Start; dev->stop = wlanDrvIf_Stop; #else dev->open = wlanDrvIf_Open; dev->stop = wlanDrvIf_Release; #endif */ /*dev->hard_start_xmit = wlanDrvIf_XmitDummy;*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &tiwlan_netdev_ops; #else dev->open = wlanDrvIf_Start; dev->stop = wlanDrvIf_Stop; dev->hard_start_xmit = wlanDrvIf_Xmit; dev->addr_len = MAC_ADDR_LEN; dev->get_stats = wlanDrvIf_NetGetStat; dev->tx_queue_len = 100; dev->do_ioctl = NULL; #endif /* Initialize Wireless Extensions interface (WEXT) */ wlanDrvWext_Init (dev); res = register_netdev (dev); if (res != 0) { ti_dprintf (TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res); kfree (dev); return res; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) #if defined HOST_PLATFORM_OMAP3430 || defined HOST_PLATFORM_ZOOM2 || defined HOST_PLATFORM_ZOOM1 || defined HOST_PLATFORM_MX25 sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend); #endif #else #ifdef CONFIG_PM sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend); #endif #endif /* On the latest Kernel there is no more support for the below macro. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) SET_MODULE_OWNER (dev); #endif return 0; }
/** * \fn wlanDrvIf_GetFile * \brief Provides access to a requested init file * * Provide the requested file information and call the requester callback. * Note that in Linux the files were previously loaded to driver memory * by the loader (see wlanDrvIf_LoadFiles). * * \note * \param hOs - The driver object handle * \param pFileInfo - The requested file's properties * \return TI_OK * \sa wlanDrvIf_LoadFiles */ int wlanDrvIf_GetFile (TI_HANDLE hOs, TFileInfo *pFileInfo) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; if (drv == NULL || pFileInfo == NULL) { ti_dprintf(TIWLAN_LOG_ERROR, "wlanDrv_GetFile: ERROR: Null File Handler, Exiting"); return TI_NOK; } /* Future option for getting the FW image part by part */ pFileInfo->hOsFileDesc = NULL; /* Fill the file's location and size in the file's info structure */ switch (pFileInfo->eFileType) { case FILE_TYPE_INI: pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tIniFile.pImage; pFileInfo->uLength = drv->tCommon.tIniFile.uSize; break; case FILE_TYPE_NVS: pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tNvsImage.pImage; pFileInfo->uLength = drv->tCommon.tNvsImage.uSize; break; case FILE_TYPE_FW: pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tFwImage.pImage; pFileInfo->bLast = TI_FALSE; pFileInfo->uLength = 0; pFileInfo->uOffset = 0; pFileInfo->uChunkBytesLeft = 0; pFileInfo->uChunksLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); /* check uChunksLeft's Validity */ if (( pFileInfo->uChunksLeft == 0 ) || ( pFileInfo->uChunksLeft > MAX_CHUNKS_IN_FILE )) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() Read Invalid Chunks Left: %d!\n",pFileInfo->uChunksLeft); return TI_NOK; } pFileInfo->pBuffer += DRV_ADDRESS_SIZE; /* FALL THROUGH */ case FILE_TYPE_FW_NEXT: /* check dec. validity */ if ( pFileInfo->uChunkBytesLeft >= pFileInfo->uLength ) { pFileInfo->uChunkBytesLeft -= pFileInfo->uLength; } /* invalid Dec. */ else { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() No. of Bytes Left < File Length\n"); return TI_NOK; } pFileInfo->pBuffer += pFileInfo->uLength; /* Finished reading all Previous Chunk */ if ( pFileInfo->uChunkBytesLeft == 0 ) { /* check dec. validity */ if ( pFileInfo->uChunksLeft > 0 ) { pFileInfo->uChunksLeft--; } /* invalid Dec. */ else { ti_dprintf (TIWLAN_LOG_ERROR, "No. of Bytes Left = 0 and Chunks Left <= 0\n"); return TI_NOK; } /* read Chunk's address */ pFileInfo->uAddress = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); pFileInfo->pBuffer += DRV_ADDRESS_SIZE; /* read Portion's length */ pFileInfo->uChunkBytesLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); pFileInfo->pBuffer += DRV_ADDRESS_SIZE; } /* Reading Chunk is NOT complete */ else { pFileInfo->uAddress += pFileInfo->uLength; } if ( pFileInfo->uChunkBytesLeft < OS_SPECIFIC_RAM_ALLOC_LIMIT ) { pFileInfo->uLength = pFileInfo->uChunkBytesLeft; } else { pFileInfo->uLength = OS_SPECIFIC_RAM_ALLOC_LIMIT; } /* If last chunk to download */ if (( pFileInfo->uChunksLeft == 0 ) && ( pFileInfo->uLength == pFileInfo->uChunkBytesLeft )) { pFileInfo->bLast = TI_TRUE; } break; } /* Call the requester callback */ if (pFileInfo->fCbFunc) { pFileInfo->fCbFunc (pFileInfo->hCbHndl); } return TI_OK; }
/** * \fn wlanDrvIf_LoadFiles * \brief Load init files from loader * * This function is called from the loader context right after the driver * is created (in IDLE state). * It copies the following files to the driver's memory: * - Ini-File - The driver's default parameters values * - NVS-File - The NVS data for FW usage * - FW-Image - The FW program image * * \note * \param drv - The driver object handle * \return void * \sa wlanDrvIf_GetFile */ int wlanDrvIf_LoadFiles (TWlanDrvIfObj *drv, TLoaderFilesData *pInitFiles) { if (!pInitFiles) { ti_dprintf (TIWLAN_LOG_ERROR, "No Init Files!\n"); return -EINVAL; } if (drv->tCommon.eDriverState != DRV_STATE_IDLE) { ti_dprintf (TIWLAN_LOG_ERROR, "Trying to load files not in IDLE state!\n"); return -EINVAL; } if (pInitFiles->uIniFileLength) { drv->tCommon.tIniFile.uSize = pInitFiles->uIniFileLength; drv->tCommon.tIniFile.pImage = kmalloc (pInitFiles->uIniFileLength, GFP_KERNEL); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, pInitFiles->uIniFileLength, GFP_KERNEL, pInitFiles->uIniFileLength); #endif if (!drv->tCommon.tIniFile.pImage) { ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for Ini-File!\n"); return -ENOMEM; } memcpy (drv->tCommon.tIniFile.pImage, &pInitFiles->data[pInitFiles->uNvsFileLength + pInitFiles->uFwFileLength], drv->tCommon.tIniFile.uSize); } if (pInitFiles->uNvsFileLength) { drv->tCommon.tNvsImage.uSize = pInitFiles->uNvsFileLength; drv->tCommon.tNvsImage.pImage = kmalloc (drv->tCommon.tNvsImage.uSize, GFP_KERNEL); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->tCommon.tNvsImage.uSize, GFP_KERNEL, drv->tCommon.tNvsImage.uSize); #endif if (!drv->tCommon.tNvsImage.pImage) { ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for NVS image\n"); return -ENOMEM; } memcpy (drv->tCommon.tNvsImage.pImage, &pInitFiles->data[0], drv->tCommon.tNvsImage.uSize ); } drv->tCommon.tFwImage.uSize = pInitFiles->uFwFileLength; if (!drv->tCommon.tFwImage.uSize) { ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n"); return -EINVAL; } drv->tCommon.tFwImage.pImage = os_memoryAlloc (drv, drv->tCommon.tFwImage.uSize); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->tCommon.tFwImage.uSize, GFP_KERNEL, drv->tCommon.tFwImage.uSize); #endif if (!drv->tCommon.tFwImage.pImage) { ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n"); return -ENOMEM; } memcpy (drv->tCommon.tFwImage.pImage, &pInitFiles->data[pInitFiles->uNvsFileLength], drv->tCommon.tFwImage.uSize); ti_dprintf(TIWLAN_LOG_OTHER, "--------- Eeeprom=%p(%lu), Firmware=%p(%lu), IniFile=%p(%lu)\n", drv->tCommon.tNvsImage.pImage, drv->tCommon.tNvsImage.uSize, drv->tCommon.tFwImage.pImage, drv->tCommon.tFwImage.uSize, drv->tCommon.tIniFile.pImage, drv->tCommon.tIniFile.uSize); return 0; }
/** * \fn wlanDrvIf_Create * \brief Create the driver instance * * Allocate driver object. * Initialize driver OS resources (IRQ, workqueue, events socket) * Setup driver network interface. * Create and link all driver modules. * * \note * \param void * \return 0 - OK, else - failure * \sa wlanDrvIf_Destroy */ static int wlanDrvIf_Create (void) { TWlanDrvIfObj *drv; /* Dm: Failure is not cleaned properly !!! */ int rc; /* Allocate driver's structure */ drv = kmalloc (sizeof(TWlanDrvIfObj), GFP_KERNEL); if (!drv) { return -ENOMEM; } #ifdef TI_DBG tb_init(TB_OPTION_NONE); #endif pDrvStaticHandle = drv; /* save for module destroy */ #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(TWlanDrvIfObj), GFP_KERNEL, sizeof(TWlanDrvIfObj)); #endif memset (drv, 0, sizeof(TWlanDrvIfObj)); /* Dm: drv->irq = TNETW_IRQ; */ drv->tCommon.eDriverState = DRV_STATE_IDLE; drv->tiwlan_wq = create_freezeable_workqueue(DRIVERWQ_NAME); if (!drv->tiwlan_wq) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to create workQ!\n"); rc = -EINVAL; goto drv_create_end_1; } drv->wl_packet = 0; drv->wl_count = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&drv->wl_wifi, WAKE_LOCK_SUSPEND, "wifi_wake"); wake_lock_init(&drv->wl_rxwake, WAKE_LOCK_SUSPEND, "wifi_rx_wake"); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask, (void *)drv); #else INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask); #endif spin_lock_init (&drv->lock); /* Setup driver network interface. */ rc = wlanDrvIf_SetupNetif (drv); if (rc) { goto drv_create_end_2; } /* Create the events socket interface */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, THIS_MODULE ); #else drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE ); #endif if (drv->wl_sock == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); rc = -EINVAL; goto drv_create_end_3; } /* Create all driver modules and link their handles */ rc = drvMain_Create (drv, &drv->tCommon.hDrvMain, &drv->tCommon.hCmdHndlr, &drv->tCommon.hContext, &drv->tCommon.hTxDataQ, &drv->tCommon.hTxMgmtQ, &drv->tCommon.hTxCtrl, &drv->tCommon.hTWD, &drv->tCommon.hEvHandler, &drv->tCommon.hCmdDispatch, &drv->tCommon.hReport); if (rc != TI_OK) { ti_dprintf (TIWLAN_LOG_ERROR, "%s: Failed to dvrMain_Create!\n", __func__); rc = -EINVAL; goto drv_create_end_4; } /* * Initialize interrupts (or polling mode for debug): */ #ifdef PRIODIC_INTERRUPT /* Debug mode: Polling (the timer is started by HwInit process) */ drv->hPollTimer = os_timerCreate ((TI_HANDLE)drv, wlanDrvIf_PollIrqHandler, (TI_HANDLE)drv); #else /* Normal mode: Interrupts (the default mode) */ rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt); #if 1 //wait to debug if (rc) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); goto drv_create_end_5; } #endif #endif /* PRIODIC_INTERRUPT */ return 0; #if 1 //wait to debug drv_create_end_5: /* Destroy all driver modules */ if (drv->tCommon.hDrvMain) { drvMain_Destroy (drv->tCommon.hDrvMain); } #endif drv_create_end_4: if (drv->wl_sock) { sock_release (drv->wl_sock->sk_socket); } drv_create_end_3: /* Release the driver network interface */ if (drv->netdev) { unregister_netdev (drv->netdev); free_netdev (drv->netdev); } drv_create_end_2: #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&drv->wl_wifi); wake_lock_destroy(&drv->wl_rxwake); #endif if (drv->tiwlan_wq) destroy_workqueue(drv->tiwlan_wq); drv_create_end_1: kfree(drv); printk("%s: Fail\n", __func__); return rc; }
/** * \fn wlanDrvIf_Create * \brief Create the driver instance * * Allocate driver object. * Initialize driver OS resources (IRQ, workqueue, events socket) * Setup driver network interface. * Create and link all driver modules. * * \note * \param void * \return 0 - OK, else - failure * \sa wlanDrvIf_Destroy */ static int wlanDrvIf_Create (void) { TWlanDrvIfObj *drv; int rc; /* Allocate driver's structure */ drv = kmalloc (sizeof(TWlanDrvIfObj), GFP_KERNEL); if (!drv) { return -ENOMEM; } #ifdef TI_DBG tb_init(TB_OPTION_NONE); #endif pDrvStaticHandle = drv; /* save for module destroy */ #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(TWlanDrvIfObj), GFP_KERNEL, sizeof(TWlanDrvIfObj)); #endif memset (drv, 0, sizeof(TWlanDrvIfObj)); drv->tCommon.eDriverState = DRV_STATE_IDLE; drv->pWorkQueue = create_singlethread_workqueue(TIWLAN_WQ_NAME); if (!drv->pWorkQueue) { return -ENOMEM; } drv->wl_packet = 0; drv->wl_count = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&drv->wl_wifi, WAKE_LOCK_SUSPEND, "wifi_wake"); wake_lock_init(&drv->wl_rxwake, WAKE_LOCK_SUSPEND, "wifi_rx_wake"); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask, (void *)drv); #else INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask); #endif spin_lock_init (&drv->lock); /* Setup driver network interface. */ rc = wlanDrvIf_SetupNetif (drv); if (rc) { kfree (drv); return rc; } /* Create the events socket interface */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, THIS_MODULE ); #else drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE ); #endif if (drv->wl_sock == NULL) { ti_dprintf (TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); return -EINVAL; } /* Create all driver modules and link their handles */ drvMain_Create (drv, &drv->tCommon.hDrvMain, &drv->tCommon.hCmdHndlr, &drv->tCommon.hContext, &drv->tCommon.hTxDataQ, &drv->tCommon.hTxMgmtQ, &drv->tCommon.hTxCtrl, &drv->tCommon.hTWD, &drv->tCommon.hEvHandler, &drv->tCommon.hCmdDispatch, &drv->tCommon.hReport); /* * Initialize interrupts (or polling mode for debug): */ #ifdef PRIODIC_INTERRUPT /* Debug mode: Polling (the timer is started by HwInit process) */ drv->hPollTimer = os_timerCreate ((TI_HANDLE)drv, wlanDrvIf_PollIrqHandler, (TI_HANDLE)drv); #else /* Normal mode: Interrupts (the default mode) */ rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt); if (rc) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); return rc; } #endif /* PRIODIC_INTERRUPT */ #ifdef CONFIG_PM /* register PM hooks in our SDIO driver */ sdioDrv_register_pm(wlanDrvIf_Resume, wlanDrvIf_Suspend); #endif return 0; }
static void wlanDrvIf_DriverTask (void *hDrv) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hDrv; #else static void wlanDrvIf_DriverTask(struct work_struct *work) { #ifdef STACK_PROFILE register unsigned long sp asm ("sp"); unsigned long local_sp = sp; #endif TWlanDrvIfObj *drv = container_of(work, TWlanDrvIfObj, tWork); #endif #ifdef STACK_PROFILE unsigned long curr1, base1; unsigned long curr2, base2; static unsigned long maximum_stack = 0; #endif os_profile (drv, 0, 0); #ifdef STACK_PROFILE curr1 = check_stack_start(&base1, local_sp + 4, 0); #endif /* Call the driver main task */ context_DriverTask (drv->tCommon.hContext); os_profile (drv, 1, 0); os_wake_lock_timeout(drv); os_wake_unlock(drv); #ifdef STACK_PROFILE curr2 = check_stack_stop(&base2, 0); if (base2 == base1) { /* if the current measurement is bigger then the maximum store it and print*/ if ((curr1 - curr2) > maximum_stack) { printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n"); printk("current operation stack use=%lu \n",(curr1 - curr2)); printk("total stack use=%lu \n",8192 - curr2 + base2); printk("total stack usage=%lu percent \n",100 * (8192 - curr2 + base2) / 8192); maximum_stack = curr1 - curr2; } } #endif } /** * \fn wlanDrvIf_LoadFiles * \brief Load init files from loader * * This function is called from the loader context right after the driver * is created (in IDLE state). * It copies the following files to the driver's memory: * - Ini-File - The driver's default parameters values * - NVS-File - The NVS data for FW usage * - FW-Image - The FW program image * * \note * \param drv - The driver object handle * \return void * \sa wlanDrvIf_GetFile */ int wlanDrvIf_LoadFiles (TWlanDrvIfObj *drv, TLoaderFilesData *pInitFiles) { if (!pInitFiles) { ti_dprintf (TIWLAN_LOG_ERROR, "No Init Files!\n"); return -EINVAL; } if (drv->tCommon.eDriverState != DRV_STATE_IDLE) { ti_dprintf (TIWLAN_LOG_ERROR, "Trying to load files not in IDLE state!\n"); return -EINVAL; } if (pInitFiles->uIniFileLength) { drv->tCommon.tIniFile.uSize = pInitFiles->uIniFileLength; drv->tCommon.tIniFile.pImage = kmalloc (pInitFiles->uIniFileLength, GFP_KERNEL); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, pInitFiles->uIniFileLength, GFP_KERNEL, pInitFiles->uIniFileLength); #endif if (!drv->tCommon.tIniFile.pImage) { ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for Ini-File!\n"); return -ENOMEM; } memcpy (drv->tCommon.tIniFile.pImage, &pInitFiles->data[pInitFiles->uNvsFileLength + pInitFiles->uFwFileLength], drv->tCommon.tIniFile.uSize); } if (pInitFiles->uNvsFileLength) { drv->tCommon.tNvsImage.uSize = pInitFiles->uNvsFileLength; drv->tCommon.tNvsImage.pImage = kmalloc (drv->tCommon.tNvsImage.uSize, GFP_KERNEL); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->tCommon.tNvsImage.uSize, GFP_KERNEL, drv->tCommon.tNvsImage.uSize); #endif if (!drv->tCommon.tNvsImage.pImage) { ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for NVS image\n"); return -ENOMEM; } memcpy (drv->tCommon.tNvsImage.pImage, &pInitFiles->data[0], drv->tCommon.tNvsImage.uSize ); } drv->tCommon.tFwImage.uSize = pInitFiles->uFwFileLength; if (!drv->tCommon.tFwImage.uSize) { ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n"); return -EINVAL; } drv->tCommon.tFwImage.pImage = os_memoryAlloc (drv, drv->tCommon.tFwImage.uSize); #ifdef TI_MEM_ALLOC_TRACE os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->tCommon.tFwImage.uSize, GFP_KERNEL, drv->tCommon.tFwImage.uSize); #endif if (!drv->tCommon.tFwImage.pImage) { ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n"); return -ENOMEM; } memcpy (drv->tCommon.tFwImage.pImage, &pInitFiles->data[pInitFiles->uNvsFileLength], drv->tCommon.tFwImage.uSize); ti_dprintf(TIWLAN_LOG_OTHER, "--------- Eeeprom=%p(%lu), Firmware=%p(%lu), IniFile=%p(%lu)\n", drv->tCommon.tNvsImage.pImage, drv->tCommon.tNvsImage.uSize, drv->tCommon.tFwImage.pImage, drv->tCommon.tFwImage.uSize, drv->tCommon.tIniFile.pImage, drv->tCommon.tIniFile.uSize); return 0; } /** * \fn wlanDrvIf_GetFile * \brief Provides access to a requested init file * * Provide the requested file information and call the requester callback. * Note that in Linux the files were previously loaded to driver memory * by the loader (see wlanDrvIf_LoadFiles). * * \note * \param hOs - The driver object handle * \param pFileInfo - The requested file's properties * \return TI_OK * \sa wlanDrvIf_LoadFiles */ int wlanDrvIf_GetFile (TI_HANDLE hOs, TFileInfo *pFileInfo) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; if (drv == NULL || pFileInfo == NULL) { ti_dprintf(TIWLAN_LOG_ERROR, "wlanDrv_GetFile: ERROR: Null File Handler, Exiting"); return TI_NOK; } /* Future option for getting the FW image part by part */ pFileInfo->hOsFileDesc = NULL; /* Fill the file's location and size in the file's info structure */ switch (pFileInfo->eFileType) { case FILE_TYPE_INI: pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tIniFile.pImage; pFileInfo->uLength = drv->tCommon.tIniFile.uSize; break; case FILE_TYPE_NVS: pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tNvsImage.pImage; pFileInfo->uLength = drv->tCommon.tNvsImage.uSize; break; case FILE_TYPE_FW: if (drv->tCommon.tFwImage.pImage == NULL) { ti_dprintf(TIWLAN_LOG_ERROR, "wlanDrv_GetFile: ERROR: no Firmware image, exiting\n"); return TI_NOK; } pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tFwImage.pImage; pFileInfo->bLast = TI_FALSE; pFileInfo->uLength = 0; pFileInfo->uOffset = 0; pFileInfo->uChunkBytesLeft = 0; pFileInfo->uChunksLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); /* check uChunksLeft's Validity */ if (( pFileInfo->uChunksLeft == 0 ) || ( pFileInfo->uChunksLeft > MAX_CHUNKS_IN_FILE )) { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() Read Invalid Chunks Left: %d!\n",pFileInfo->uChunksLeft); return TI_NOK; } pFileInfo->pBuffer += DRV_ADDRESS_SIZE; /* FALL THROUGH */ case FILE_TYPE_FW_NEXT: /* check dec. validity */ if ( pFileInfo->uChunkBytesLeft >= pFileInfo->uLength ) { pFileInfo->uChunkBytesLeft -= pFileInfo->uLength; } /* invalid Dec. */ else { ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() No. of Bytes Left < File Length\n"); return TI_NOK; } pFileInfo->pBuffer += pFileInfo->uLength; /* Finished reading all Previous Chunk */ if ( pFileInfo->uChunkBytesLeft == 0 ) { /* check dec. validity */ if ( pFileInfo->uChunksLeft > 0 ) { pFileInfo->uChunksLeft--; } /* invalid Dec. */ else { ti_dprintf (TIWLAN_LOG_ERROR, "No. of Bytes Left = 0 and Chunks Left <= 0\n"); return TI_NOK; } /* read Chunk's address */ pFileInfo->uAddress = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); pFileInfo->pBuffer += DRV_ADDRESS_SIZE; /* read Portion's length */ pFileInfo->uChunkBytesLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); pFileInfo->pBuffer += DRV_ADDRESS_SIZE; } /* Reading Chunk is NOT complete */ else { pFileInfo->uAddress += pFileInfo->uLength; } if ( pFileInfo->uChunkBytesLeft < OS_SPECIFIC_RAM_ALLOC_LIMIT ) { pFileInfo->uLength = pFileInfo->uChunkBytesLeft; } else { pFileInfo->uLength = OS_SPECIFIC_RAM_ALLOC_LIMIT; } /* If last chunk to download */ if (( pFileInfo->uChunksLeft == 0 ) && ( pFileInfo->uLength == pFileInfo->uChunkBytesLeft )) { pFileInfo->bLast = TI_TRUE; } break; } /* Call the requester callback */ if (pFileInfo->fCbFunc) { pFileInfo->fCbFunc (pFileInfo->hCbHndl); } return TI_OK; }