/****************************************************************************** * FILE PURPOSE: Functions to OSAL related routines for running NWAL, PA, QMSS,etc ****************************************************************************** * FILE NAME: osal.c * * DESCRIPTION: Functions to initialize framework resources for running NWAL * * REVISION HISTORY: * * Copyright (c) Texas Instruments Incorporated 2010-2011 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* CSL RL includes */ #include #include #include #include #include #include #include #include "netapi_tune.h" #include "netapi_vm.h" #include "netapi_timer.h" #include #include #include #include #include #include #include #include #include "netapi_util.h" #include "tools/module/netapimod.h" #define System_printf printf uint32_t Osal_qmss_MallocCounter =0; uint32_t Osal_qmss_FreeCounter =0; uint32_t Osal_cppi_MallocCounter =0; uint32_t Osal_cppi_FreeCounter =0; void* Osal_saGetSCPhyAddr(void* vaddr); /* TODO: */ #define DNUM 0 #if 0 uint32_t globalCritkey; /* Lock to be used for critical section */ pthread_mutex_t mutex_lock; void nwalTest_osalInit() { pthread_mutex_init(&mutex_lock, NULL); return; } void nwalTest_osalshutdown() { pthread_mutex_destroy(&mutex_lock); return; } static inline void nwalTest_osalEnterCS() { #if 0 pthread_mutex_lock(&mutex_lock); #endif return; } static inline void nwalTest_osalLeaveCS() { #if 0 pthread_mutex_unlock(&mutex_lock); #endif return; } #endif //utility to convert virt2phy, phy2virt static inline void* _Osal_qmssVirtToPhy (void *ptr) { return (void *)(netapi_VM_mem_start_phy + ((uint8_t*)ptr - netapi_VM_mem_start)); } static inline void * _Osal_qmssPhyToVirt (void *ptr) { if (!ptr) return (void *) 0; //todo, see if out of range of mem_start_phy and size!! (like mmu would do) return (void *)(netapi_VM_mem_start + ((uint8_t*)ptr - netapi_VM_mem_start_phy)); } /**********USE SPACE ACCESS TO KERNEL MEMORY SERVICES*************/ static int netapi_fd; /***init **/ int netapi_utilModInit(void) { netapi_fd = open("/dev/netapi", O_RDWR); if (netapi_fd == -1) { return -1; } return netapi_fd; } /***close **/ void netapi_utilModClose(void) { close(netapi_fd); } /* return physical address of region kernel module has allocated for us */ unsigned long netapi_utilGetPhysOfBufferArea(void) { unsigned long physp; if (ioctl(netapi_fd, NETAPIMOD_IOCGETPHYS | NETAPIMOD_IOCMAGIC, &physp) == -1) { return 0; } return physp; } /* return the size of that region */ unsigned long netapi_utilGetSizeOfBufferArea(void) { unsigned long size; if (ioctl(netapi_fd, NETAPIMOD_IOCGETSIZE | NETAPIMOD_IOCMAGIC, &size) == -1) { return 0; } return size; } //*****for the actual wb, inv cache ops, call the osal_xxx version, not these directly // (so make inline) /** write back operation on block */ static inline int netapi_utilCacheWb(void *ptr, size_t size) { struct netapimod_block block; block.addr = (unsigned long)ptr; block.size = size; if (ioctl(netapi_fd, NETAPIMOD_IOCCACHEWB | NETAPIMOD_IOCMAGIC, &block) == -1) { return -1; } return 0; } /** write back & invalidate **/ static inline int _netapi_utilCacheWbInv(void *ptr, size_t size) { struct netapimod_block block; block.addr = (unsigned long)ptr; block.size = size; if (ioctl(netapi_fd, NETAPIMOD_IOCCACHEWBINV | NETAPIMOD_IOCMAGIC, &block) == -1) { return -1; } return 0; } int netapi_utilCacheWbInv(void *ptr, size_t size) {return _netapi_utilCacheWbInv(ptr,size);} /** just invalidate **/ static inline int netapi_utilCacheInv(void *ptr, size_t size) { struct netapimod_block block; block.addr = (unsigned long)ptr; block.size = size; if (ioctl(netapi_fd, NETAPIMOD_IOCCACHEINV | NETAPIMOD_IOCMAGIC, &block) == -1) { return -1; } return 0; } //***mmap the block into our user space process memory map. */ unsigned long netapi_utilGetVaOfBufferArea(unsigned int offset, unsigned int size) { void *userp; /* Map the physical address to user space */ userp = mmap(0, // Preferred start address size, // Length to be mapped PROT_WRITE | PROT_READ, // Read and write access MAP_SHARED, // Shared memory netapi_fd, // File descriptor offset); // The byte offset from fd if (userp == MAP_FAILED) { return 0; } return (unsigned long)userp; } /***************************************************************************** * FUNCTION PURPOSE: Cache Invalidation Routine ***************************************************************************** * DESCRIPTION: Cache Invalidation Routine *****************************************************************************/ static inline void Osal_invalidateCache (void *blockPtr, uint32_t size) { #if 0 //do invalidate with writeback (when actually sending or freeing) #ifdef NETAPI_TUNE_USE_CACHE_OPS if ((blockPtr netapi_VM_mem_end)) return; //netapi_utilCacheInv(blockPtr, size); netapi_utilCacheInv(Osal_saGetSCPhyAddr(blockPtr), size); #endif #endif return; } /***************************************************************************** * FUNCTION PURPOSE: Cache Writeback Routine ***************************************************************************** * DESCRIPTION: Cache Invalidation Routine *****************************************************************************/ /* stats */ static unsigned int cache_op_cycles=0; static unsigned int n_cache_op_cycles=0; void Osal_cache_op_measure_reset(void) { cache_op_cycles=0; n_cache_op_cycles=0;} unsigned int Osal_cache_op_measure(int * p_n) { *p_n = n_cache_op_cycles; return cache_op_cycles;} static inline void Osal_writeBackCache (void *blockPtr, uint32_t size) { #ifdef NETAPI_TUNE_USE_CACHE_OPS register unsigned int v1; register unsigned int v2; v1= netapi_timing_stop(); if ((blockPtr netapi_VM_mem_end)) return; //netapi_utilCacheWbInv(blockPtr, size); //printf("osal> wbiv %x %x %d ..", blockPtr, Osal_saGetSCPhyAddr(blockPtr), size); _netapi_utilCacheWbInv(_Osal_qmssVirtToPhy(blockPtr), size); v2= netapi_timing_stop(); cache_op_cycles += (v2-v1); n_cache_op_cycles+=1; //printf("done\n"); sleep(1); #endif return; } void * Osal_qmssMtCsEnter() { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return NULL; } void Osal_qmssMtCsExit(void *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_nwalCsEnter(uint32_t *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_nwalCsExit(uint32_t key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_qmssLog ( String fmt, ... ) { } void Osal_cppiCsEnter (uint32_t *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_cppiCsExit (uint32_t key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_cppiLog ( String fmt, ... ) { } void Osal_paBeginMemAccess (Ptr addr, uint32_t size) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ } void Osal_paEndMemAccess (Ptr addr, uint32_t size) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ } void Osal_paMtCsEnter (uint32_t *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ } void Osal_paMtCsExit (uint32_t key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ } void* Osal_qmssCsEnter () { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return(NULL); } void Osal_qmssCsExit (void * key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } Ptr Osal_qmssMalloc (uint32_t num_bytes) { Ptr ret; Osal_qmss_MallocCounter++; ret = malloc (num_bytes); if(ret==NULL) { System_printf("\nERROR! QMSS Malloc failed!\n"); } return ret; } void Osal_qmssFree (Ptr ptr, uint32_t size) { /* Increment the free counter. */ Osal_qmss_FreeCounter++; free(ptr); } Ptr Osal_cppiMalloc (uint32_t num_bytes) { Ptr ret; Osal_cppi_MallocCounter++; num_bytes += (CACHE_L2_LINESIZE-1); ret = malloc (num_bytes); if(ret==NULL) { System_printf("\nERROR! CPPI Malloc failed!\n"); } return ret; } void Osal_cppiFree (Ptr ptr, uint32_t size) { /* Increment the free counter. */ Osal_cppi_FreeCounter++; free(ptr); } void Osal_qmssBeginMemAccess (void *blockPtr, uint32_t size) { //Osal_invalidateCache(blockPtr,size); return; } void Osal_qmssEndMemAccess (void *blockPtr, uint32_t size) { //Osal_writeBackCache(blockPtr,size); return; } void Osal_cppiBeginMemAccess (void *blockPtr, uint32_t size) { //Osal_invalidateCache(blockPtr,size); return; } void Osal_cppiEndMemAccess (void *blockPtr, uint32_t size) { //Osal_writeBackCache(blockPtr,size); return; } void Osal_nwalInvalidateCache (void *blockPtr, uint32_t size) { //Osal_invalidateCache(blockPtr,size); return; } void Osal_nwalWriteBackCache (void *blockPtr, uint32_t size) { //Osal_writeBackCache(blockPtr,size); return; } uint32_t Osal_nwalGetCacheLineSize (void ) { /* By default assumes L2 cache line is enabled. If not return CACHE_L1D_LINESIZE */ return (CACHE_L2_LINESIZE); } /******************************************************************** * FUNCTION PURPOSE: Convert local address to global ******************************************************************** * DESCRIPTION: Returns global address ********************************************************************/ unsigned int Osal_nwalLocToGlobAddr(unsigned int x) { return x; } uint16_t Osal_nwalGetProcId (void ) { return DNUM; } uint64_t Osal_nwalGetTimeStamp(void) { /* Stub function to return timestamp */ return netapi_getTimestamp(); } uint16_t Osal_saGetProcId (void ) { return 0; } void* Osal_saGetSCPhyAddr(void* vaddr) { if(vaddr == NULL) { return NULL; } return (void *)(netapi_VM_mem_start_phy + ((uint8_t*) vaddr - netapi_VM_mem_start)); } void Osal_saBeginScAccess (void* addr, uint32_t size) { Osal_invalidateCache(addr,size); } void Osal_saEndScAccess (void* addr, uint32_t size) { Osal_writeBackCache(addr,size); } void Osal_saCsEnter (uint32_t *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ //((CSL_semAcquireDirect (SA_HW_SEM)) == 0); return; } void Osal_saCsExit (uint32_t key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_saMtCsEnter (uint32_t *key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_saMtCsExit (uint32_t key) { /* Stub Function. TBD: Would need to handle when for multi proc access * To be handled once infrastructure is available from Kernel */ return; } void Osal_saBeginMemAccess (void *blockPtr, uint32_t size) { Osal_invalidateCache(blockPtr,size); return; } void Osal_saEndMemAccess (void *blockPtr, uint32_t size) { Osal_writeBackCache(blockPtr,size); return; } void Osal_pktLibBeginMemAccess(void* ptr, uint32_t size) { //Osal_invalidateCache(ptr,size); } void Osal_pktLibEndMemAccess(void* ptr, uint32_t size) { //Osal_writeBackCache(ptr,size); } void Osal_pktLibBeginPktAccess(Pktlib_HeapHandle heapHandle, Ti_Pkt* ptrPkt, uint32_t size) { /* TODO: We should use the 'heapHandle' and compare it with what we got from the * 'create/find' HEAP API & depending upon the comparison take appropriate action. * Just for testing we are always invalidating the cache here. */ //Osal_invalidateCache(ptrPkt,size); } void Osal_pktLibEndPktAccess(Pktlib_HeapHandle heapHandle, Ti_Pkt* ptrPkt, uint32_t size) { /* TODO: We should use the 'heapHandle' and compare it with what we got from the * 'create/find' HEAP API & depending upon the comparison take appropriate action. * Just for testing we are always writing back the cache here. */ /* Writeback the contents of the cache. */ //Osal_writeBackCache(ptrPkt,size); } void* Osal_pktLibEnterCriticalSection(Pktlib_HeapHandle heapHandle) { /* TODO: We should use the 'heapHandle' and compare it with what we got from the * 'create/find' HEAP API & depending upon the comparison take appropriate action. * Implementations here could range from a MULTI-THREAD protection if the packets in * the heap are being accessed across multiple threads or MULTI-CORE if the packets * are being accessed across multiple cores and features: split and clone are used. * For NWAL layer no protection required. * * For testing we are not doing any of this so we are simply setting it to NOOP */ return NULL; } void Osal_pktLibExitCriticalSection(Pktlib_HeapHandle heapHandle, void* csHandle) { /* TODO: We should use the 'heapHandle' and compare it with what we got from the * 'create/find' HEAP API & depending upon the comparison take appropriate action. * Implementations here could range from a MULTI-THREAD protection if the packets in * the heap are being accessed across multiple threads or MULTI-CORE if the packets * are being accessed across multiple cores and features: split and clone are used. * For NWAL layer no protection required.. * * For testing we are not doing any of this so we are simply setting it to NOOP */ return; } void* Osal_qmssVirtToPhy (void *ptr) { return _Osal_qmssVirtToPhy(ptr); } void * Osal_qmssPhyToVirt (void *ptr) { return _Osal_qmssPhyToVirt(ptr); } /****************************************************************************** * Function to traverse a CPPI descriptor and convert all address references * from virtual to physical. ******************************************************************************/ //#define ASSUME_ALL_DESCRIPTOR //define this if mono and host descriptors are present, else don't //define and just host will be assumed (more efficient) void* Osal_qmssConvertDescVirtToPhy(void *descAddr) { if (!descAddr) return (void *)0; #ifdef ASSUME_ALL_DESCRIPTOR if (Cppi_getDescType((Cppi_Desc *)QMSS_DESC_PTR(descAddr)) == Cppi_DescType_HOST) #endif { Cppi_HostDesc *nextBDPtr = (Cppi_HostDesc *)QMSS_DESC_PTR(descAddr); Cppi_HostDesc *prevBDPtr = 0; while (nextBDPtr) { void *buffPtr=NULL; if (nextBDPtr->buffPtr) { buffPtr = (void *)nextBDPtr->buffPtr; nextBDPtr->buffPtr = (uint32_t)_Osal_qmssVirtToPhy((void *)(nextBDPtr->buffPtr)); if (!(nextBDPtr->buffPtr)) return (void *)0; Osal_writeBackCache(buffPtr, nextBDPtr->buffLen); } if (nextBDPtr->origBuffPtr) { nextBDPtr->origBuffPtr = (uint32_t)_Osal_qmssVirtToPhy((void *)(nextBDPtr->origBuffPtr)); if (!(nextBDPtr->origBuffPtr)) return (void *)0; } prevBDPtr = nextBDPtr; nextBDPtr = (Cppi_HostDesc *)QMSS_DESC_PTR((nextBDPtr->nextBDPtr)); if (prevBDPtr->nextBDPtr) { prevBDPtr->nextBDPtr = (uint32_t)_Osal_qmssVirtToPhy((void *)(prevBDPtr->nextBDPtr)); if (!(prevBDPtr->nextBDPtr)) return (void *)0; } if (buffPtr) Osal_writeBackCache(buffPtr, prevBDPtr->buffLen); Osal_writeBackCache(prevBDPtr, TUNE_NETAPI_DESC_SIZE); } descAddr = _Osal_qmssVirtToPhy(descAddr); if (!descAddr) return (void *)0; } #ifdef ASSUME_ALL_DESCRIPTOR else if (Cppi_getDescType((Cppi_Desc *)QMSS_DESC_PTR(descAddr)) == Cppi_DescType_MONOLITHIC) { Osal_writeBackCache(descAddr, TUNE_NETAPI_DESC_SIZE); descAddr = _Osal_qmssVirtToPhy(descAddr); if (!descAddr) return (void *)0; } #endif return descAddr; } /****************************************************************************** * Function to traverse a CPPI descriptor and convert all address references * from physical to virtual. ******************************************************************************/ void* Osal_qmssConvertDescPhyToVirt(void *descAddr) { if (!descAddr) return (void *)0; descAddr = _Osal_qmssPhyToVirt(descAddr); #ifdef ASSUME_ALL_DESCRIPTOR if (Cppi_getDescType((Cppi_Desc *)QMSS_DESC_PTR(descAddr)) == Cppi_DescType_HOST) #endif { Cppi_HostDesc *nextBDPtr = (Cppi_HostDesc *)QMSS_DESC_PTR(descAddr); while (nextBDPtr) { //Qmss_osalBeginMemAccess(nextBDPtr, TUNE_NETAPI_DESC_SIZE); if (nextBDPtr->buffPtr) { nextBDPtr->buffPtr = (uint32_t)_Osal_qmssPhyToVirt((void *)(nextBDPtr->buffPtr)); if (!(nextBDPtr->buffPtr)) return (void *)0; //Qmss_osalBeginMemAccess((void *)(nextBDPtr->buffPtr), nextBDPtr->buffLen); } if (nextBDPtr->origBuffPtr) { nextBDPtr->origBuffPtr = (uint32_t)_Osal_qmssPhyToVirt((void *)(nextBDPtr->origBuffPtr)); if (!(nextBDPtr->origBuffPtr)) return (void *)0; } if (nextBDPtr->nextBDPtr) { nextBDPtr->nextBDPtr = (uint32_t)_Osal_qmssPhyToVirt((void *)(nextBDPtr->nextBDPtr)); if (!(nextBDPtr->nextBDPtr)) return (void *)0; } nextBDPtr = (void *)QMSS_DESC_PTR((nextBDPtr->nextBDPtr)); } } #ifdef ASSUME_ALL_DESCRIPTOR else if (Cppi_getDescType((Cppi_Desc *)QMSS_DESC_PTR(descAddr)) == Cppi_DescType_MONOLITHIC) { descAddr = _Osal_qmssPhyToVirt(descAddr); if (!descAddr) return (void *)0; } #endif return descAddr; } void* Osal_stubCsEnter (void) { } void Osal_stubCsExit (void *CsHandle) { /* Release Semaphore using handle */ return; }