static void wlanDrvIf_DriverTask (void *hDrv) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hDrv; #else static void wlanDrvIf_DriverTask(struct work_struct *work) { TWlanDrvIfObj *drv = container_of(work, TWlanDrvIfObj, tWork); #endif #ifdef STACK_PROFILE unsigned int curr1,base1; unsigned int curr2,base2; static unsigned int maximum_stack = 0; #endif TI_BOOL bShouldLock; os_profile (drv, 0, 0); #ifdef STACK_PROFILE curr1 = check_stack_start(&base1); #endif /* we must read the value first here */ bShouldLock = ! context_IsSuspending(pDrvStaticHandle->tCommon.hContext); /* Call the driver main task */ context_DriverTask (drv->tCommon.hContext); if (bShouldLock) { os_wake_lock_timeout(drv); os_wake_unlock(drv); } #ifdef STACK_PROFILE curr2 = check_stack_stop(&base2); 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 =%d \n",(curr1 - curr2)); printk("total stack use=%d \n",8192 - curr2 + base2); printk("total stack usage= %d percent \n",100 * (8192 - curr2 + base2) / 8192); maximum_stack = curr1 - curr2; } } #endif os_profile (drv, 1, 0); }
/**************************************************************************************** * os_memoryFree() **************************************************************************************** DESCRIPTION: This function releases a block of memory previously allocated with the os_memoryAlloc function. ARGUMENTS: OsContext - our adapter context. pMemPtr - Pointer to the base virtual address of the allocated memory. This address was returned by the os_memoryAlloc function. Size - Specifies the size, in bytes, of the memory block to be released. This parameter must be identical to the Length that was passed to os_memoryAlloc. RETURN: None NOTES: *****************************************************************************************/ void os_memoryFree( TI_HANDLE OsContext, void* pMemPtr, TI_UINT32 Size ) { struct os_mem_block *blk; if (!pMemPtr) { printk("%s: NULL\n",__func__); return; } blk = (struct os_mem_block *)((char *)pMemPtr - sizeof(struct os_mem_block)); if (blk->signature != MEM_BLOCK_START) { printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n", __FUNCTION__, blk->signature); return; } *(char *)(&blk->signature) = '~'; if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block)) != MEM_BLOCK_END) { printk("\n\n%s: memory block corruption. Size=%u\n\n\n", __FUNCTION__, blk->size); } os_profile (OsContext, 5, blk->size + sizeof(struct os_mem_block) + sizeof(__u32)); blk->f_free(blk); }
/**************************************************************************************** * os_memoryFree() **************************************************************************************** DESCRIPTION: This function releases a block of memory previously allocated with the os_memoryAlloc function. ARGUMENTS: OsContext - our adapter context. pMemPtr - Pointer to the base virtual address of the allocated memory. This address was returned by the os_memoryAlloc function. Size - Specifies the size, in bytes, of the memory block to be released. This parameter must be identical to the Length that was passed to os_memoryAlloc. RETURN: None NOTES: *****************************************************************************************/ VOID os_memoryFree( TI_HANDLE OsContext, PVOID pMemPtr, UINT32 Size ) { struct os_mem_block *blk = (struct os_mem_block *)((char *)pMemPtr - sizeof(struct os_mem_block)); #ifdef TI_MEM_ALLOC_TRACE os_printf("MTT:%s:%d ::os_memoryFree(0x%p, 0x%p, %lu) : %d\n",__FUNCTION__,__LINE__,OsContext,pMemPtr,Size,-Size); #endif if (blk->signature != MEM_BLOCK_START) { printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n", __FUNCTION__, blk->signature); return; } *(char *)(&blk->signature) = '~'; if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block)) != MEM_BLOCK_END) { printk("\n\n%s: memory block corruption. Size=%u\n\n\n", __FUNCTION__, blk->size); } os_profile (OsContext, 5, blk->size + sizeof(struct os_mem_block) + sizeof(__u32)); blk->f_free(blk); }
/**************************************************************************************** * os_memoryPreAlloc() **************************************************************************************** DESCRIPTION: Gets system-space memory preallocated by kernel. ARGUMENTS: OsContext - our adapter context. section - section number Size - Specifies the size, in bytes, to be allocated. RETURN: Pointer to the allocated memory. NULL if there is insufficient memory available. *****************************************************************************************/ PVOID os_memoryPreAlloc( TI_HANDLE OsContext, int section, UINT32 Size ) { struct os_mem_block *blk; __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); #ifdef TI_MEM_ALLOC_TRACE os_printf("MTT:%s:%d ::os_memoryPreAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size); #endif if( total_size < Size ) { /* Dm: Security fix */ return NULL; } blk = (struct os_mem_block *)wifi_kernel_prealloc( section, total_size ); if( !blk ) { return os_memoryAlloc(OsContext, Size); } blk->f_free = (os_free)os_memoryPreFree; os_profile (OsContext, 4, total_size); /*list_add(&blk->blk_list, &drv->mem_blocks);*/ blk->size = Size; blk->signature = MEM_BLOCK_START; *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; return (PVOID)((char *)blk + sizeof(struct os_mem_block)); }
void* _os_memoryAlloc( TI_HANDLE OsContext, TI_UINT32 Size, TI_UINT32 FileNbr, TI_UINT32 LineNbr ) { struct os_mem_block *blk; __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; #ifdef TI_MEM_ALLOC_TRACE os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",FileNbr, LineNbr ,OsContext,Size,total_size); #endif /* Memory optimization issue. Allocate up to 2 pages (8k) from the SLAB allocator (2^n), otherwise allocate from virtual pool. If full Async mode is used, allow up to 6 pages (24k) for DMA-able memory, so the TxCtrlBlk table can be transacted over DMA. */ #ifdef FULL_ASYNC_MODE if (total_size < 6 * 4096) #else if (total_size < 2 * 4096) #endif { blk = kmalloc(total_size, flags); if (!blk) { printk(KERN_ERR "%s: NULL from kmalloc\n",__func__); return NULL; } blk->f_free = (os_free)kfree; } else { /* We expect that the big allocations should be made outside the interrupt, otherwise fail */ if (in_interrupt()) { printk(KERN_ERR "%s: in_interrupt(), returning NULL\n",__func__); return NULL; } blk = vmalloc(total_size); if (!blk) { printk(KERN_ERR "%s: NULL from vmalloc\n",__func__); return NULL; } blk->f_free = (os_free)vfree; } os_profile (OsContext, 4, total_size); /*list_add(&blk->blk_list, &drv->mem_blocks);*/ blk->size = Size; blk->signature = MEM_BLOCK_START; blk->allocFile = FileNbr; blk->allocLine = LineNbr; *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; return (void *)((char *)blk + sizeof(struct os_mem_block)); }
/**************************************************************************************** * os_memoryAlloc() **************************************************************************************** DESCRIPTION: Allocates resident (nonpaged) system-space memory. ARGUMENTS: OsContext - our adapter context. Size - Specifies the size, in bytes, to be allocated. RETURN: Pointer to the allocated memory. NULL if there is insufficient memory available. NOTES: With the call to vmalloc it is assumed that this function will never be called in an interrupt context. vmalloc has the potential to sleep the caller while waiting for memory to become available. *****************************************************************************************/ void* os_memoryAlloc( TI_HANDLE OsContext, TI_UINT32 Size ) { struct os_mem_block *blk; __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); /* Memory optimization issue. Allocate up to 2 pages (8k) from the SLAB allocator (2^n), otherwise allocate from virtual pool. If full Async mode is used, allow up to 6 pages (24k) for DMA-able memory, so the TxCtrlBlk table can be transacted over DMA. */ #ifdef FULL_ASYNC_MODE if (total_size < 6 * 4096) #else if (total_size < 2 * 4096) #endif { if (in_atomic()) { blk = kmalloc(total_size, GFP_ATOMIC); } else { blk = kmalloc(total_size, GFP_KERNEL); } if (!blk) { printk("%s: NULL\n",__func__); return NULL; } blk->f_free = (os_free)kfree; } else { /* We expect that the big allocations should be made outside the interrupt, otherwise fail */ if (in_interrupt()) return NULL; blk = vmalloc(total_size); if (!blk) return NULL; blk->f_free = (os_free)vfree; } os_profile (OsContext, 4, total_size); /*list_add(&blk->blk_list, &drv->mem_blocks);*/ blk->size = Size; blk->signature = MEM_BLOCK_START; *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; return (void*)((char *)blk + sizeof(struct os_mem_block)); }
/** * \fn wlanDrvIf_Xmit * \brief Packets transmission * * The network stack calls this function in order to transmit a packet * through the WLAN interface. * The packet is inserted to the drver Tx queues and its handling is continued * after switching to the driver context. * * \note * \param skb - The Linux packet buffer structure * \param dev - The driver network-interface handle * \return 0 (= OK) * \sa */ static int wlanDrvIf_Xmit (struct sk_buff *skb, struct net_device *dev) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); TTxCtrlBlk * pPktCtrlBlk; int status; CL_TRACE_START_L1(); os_profile (drv, 0, 0); drv->stats.tx_packets++; drv->stats.tx_bytes += skb->len; /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */ pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD); pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */ pPktCtrlBlk->tTxDescriptor.length = skb->len; pPktCtrlBlk->tTxPktParams.pInputPkt = skb; /* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */ pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data; pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[2] = 0; /* Send the packet to the driver for transmission. */ status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority); /* If failed (queue full or driver not running), drop the packet. */ if (status != TI_OK) { drv->stats.tx_errors++; } os_profile (drv, 1, 0); CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); return 0; }
/**************************************************************************************** * os_memoryAlloc() **************************************************************************************** DESCRIPTION: Allocates resident (nonpaged) system-space memory. ARGUMENTS: OsContext - our adapter context. Size - Specifies the size, in bytes, to be allocated. RETURN: Pointer to the allocated memory. NULL if there is insufficient memory available. NOTES: With the call to vmalloc it is assumed that this function will never be called in an interrupt context. vmalloc has the potential to sleep the caller while waiting for memory to become available. *****************************************************************************************/ PVOID os_memoryAlloc( TI_HANDLE OsContext, UINT32 Size ) { struct os_mem_block *blk; __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32); #ifdef TI_MEM_ALLOC_TRACE os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size); #endif if( total_size < Size ) { /* Dm: Security fix */ return NULL; } /* memory optimization issue. Allocate 8 kB and less from the SLAB allocator (2^n) otherwise allocate from virtual pool. */ /* 2 pages */ if (total_size < 2 * 4096) { if (in_atomic()) blk = kmalloc(total_size, GFP_ATOMIC); else blk = kmalloc(total_size, GFP_KERNEL); if (!blk) return NULL; blk->f_free = (os_free)kfree; } else { /* We expect that the big allocations should be made outside the interrupt, otherwise fail */ if (in_atomic()) return NULL; blk = vmalloc(total_size); if (!blk) return NULL; blk->f_free = (os_free)vfree; } os_profile (OsContext, 4, total_size); /*list_add(&blk->blk_list, &drv->mem_blocks);*/ blk->size = Size; blk->signature = MEM_BLOCK_START; *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END; return (PVOID)((char *)blk + sizeof(struct os_mem_block)); }
static int xmit_Bridge (struct sk_buff *skb, struct net_device *dev, TIntraBssBridge *pBssBridgeParam) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); TTxCtrlBlk * pPktCtrlBlk; TEthernetHeader *pEthHead = (TEthernetHeader *)(skb->data); int status; CL_TRACE_START_L1(); os_profile (drv, 0, 0); drv->stats.tx_packets++; drv->stats.tx_bytes += skb->len; /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */ pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD); if (pPktCtrlBlk == NULL) { drv->stats.tx_errors++; os_profile (drv, 1, 0); CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); return 0; } /* Set interface type according to net device interface number */ if (drv->tCommon.eIfRole == IF_ROLE_TYPE_AP) SET_PKT_TYPE_IF_ROLE_AP(pPktCtrlBlk); else SET_PKT_TYPE_IF_ROLE_STA(pPktCtrlBlk); pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */ pPktCtrlBlk->tTxDescriptor.length = skb->len; pPktCtrlBlk->tTxPktParams.pInputPkt = skb; /* Check MGMT packet from hostapd, forward it to the Mgmt-Queue and exit without ethernet header */ if (HTOWLANS(pEthHead->type) == AP_MGMT_ETH_TYPE) { /* Copy WLAN header into aPktHdr - format for MGMT packets */ memcpy (pPktCtrlBlk->aPktHdr, skb->data + ETHERNET_HDR_LEN , WLAN_HDR_LEN ); /* Skip ethernet header, send as management frame */ pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_MGMT; pPktCtrlBlk->tTxnStruct.aBuf[0] = (TI_UINT8 *)pPktCtrlBlk->aPktHdr; pPktCtrlBlk->tTxnStruct.aLen[0] = WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN + WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN - WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[2] = 0; pPktCtrlBlk->tTxPktParams.uInputPktLen = skb->len; pPktCtrlBlk->tTxDescriptor.length = (TI_UINT16)((pPktCtrlBlk->tTxnStruct.aLen[0]) + (pPktCtrlBlk->tTxnStruct.aLen[1])); status = txMgmtQ_Xmit (drv->tCommon.hTxMgmtQ, pPktCtrlBlk, TI_TRUE); } else { /* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */ pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data; pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[2] = 0; /* Send the packet to the driver for transmission. */ status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority, pBssBridgeParam); } /* If failed (queue full or driver not running), drop the packet. */ if (status != TI_OK) { drv->stats.tx_errors++; } os_profile (drv, 1, 0); CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); 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; }