]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blob - ti/runtime/hplib/src/hplib_vm.c
96003e0e9ac04f12165ed9b868888e9fd3cda6bd
[keystone-rtos/netapi.git] / ti / runtime / hplib / src / hplib_vm.c
1 /******************************************************************************
2  * FILE PURPOSE:  Main Routines for HPLIB Virtual Memory Allocator
3  ******************************************************************************
4  * FILE NAME:   hplib_vm.c
5  *
6  * DESCRIPTION: The virtual memory APIs provide the following functionality:
7  *       Maps peripheral registers into user space for LLDs. 
8  *          QMSS
9  *          CPPI
10  *          SRIO
11 .*          PASS
12  *          Timer64 (Appleton)
13  *      Memory allocation routines.
14  *      Routines to perform address translations (physical to virtual, virtual to physical)
16  *
17  * REVISION HISTORY:
18  *
19  *  Copyright (c) Texas Instruments Incorporated 2010-2012
20  * 
21  *  Redistribution and use in source and binary forms, with or without 
22  *  modification, are permitted provided that the following conditions 
23  *  are met:
24  *
25  *    Redistributions of source code must retain the above copyright 
26  *    notice, this list of conditions and the following disclaimer.
27  *
28  *    Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the 
30  *    documentation and/or other materials provided with the   
31  *    distribution.
32  *
33  *    Neither the name of Texas Instruments Incorporated nor the names of
34  *    its contributors may be used to endorse or promote products derived
35  *    from this software without specific prior written permission.
36  *
37  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
38  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
39  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
41  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
42  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
43  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
47  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  *
49  */
51 #include <stdint.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <fcntl.h>
57 #include <sys/mman.h>
58 #include <errno.h>
59 #include <unistd.h>
60 #include <sys/ioctl.h>
61 #include "hplibmod.h"
62 #include "hplib.h"
63 #include "ti/csl/cslr_device.h"
65 extern void* Osal_hplibCsEnter(void);
66 extern void Osal_hplibCsExit (void *CsHandle);
68 /***********************RAW MEMORY ALLOCATION & TRANSLATION*************************/
69 /* Macro to align x to y */
70 #define align(x,y)   ((x + y) & (~(y-1)))
72 #define HPLIB_VM_BM_ALLOC_PAGE_SIZE 256
74 hplib_virtualMemPoolAddr_T memPoolAddr[HPLIB_MAX_MEM_POOLS];
75 uint8_t *hplib_VM_mem_start_phy = (uint8_t*)0;
76 uint8_t *hplib_VM_mem_start = (uint8_t*)0;
77 uint8_t *hplib_VM_mem_end = (uint8_t*)0;
78 uint8_t *hplib_VM_mem_end_phy = (uint8_t*)0;
79 static uint8_t *hplib_VM_mem_alloc_ptr = (uint8_t*)0;
80 static uint32_t hplib_VM_mem_size = 0;
81 uint32_t hplib_VM_virt_to_phy_mapping;
82 uint32_t hplib_VM_phy_to_virt_mapping;
84 /* File descriptor for /dev/mem */ 
85 static int dev_mem_fd;
87 /**************************************************************************
88  *  FUNCTION PURPOSE:   Maps the give physical address to virtual memory space
89  **************************************************************************/
90 void *hplib_VM_MemMap
91 (
92     void        *addr, /* Physical address */
93     uint32_t    size   /* Size of block */
94 )
95 {
96     void            *map_base,*virt_addr;
97     uint32_t        page_sz;
98     long            retval;
100     retval = sysconf(_SC_PAGE_SIZE);
101     if (retval == -1)
102     {
103         hplib_Log("hplib_VM_MemMap: Failed to get page size err=%s\n",
104                strerror(errno));
105         return (void *)0;
106     }
108     page_sz = (uint32_t)retval;
110     if (size%page_sz)
111     {
112         hplib_Log("hplib_VM_MemMap: error: block size not aligned to page size\n");
113         return (void *)0;
114     }
116     if ((uint32_t)addr%page_sz)
117     {
118         hplib_Log("hplib_VM_MemMap: error: addr not aligned to page size\n");
119         return (void *)0;
120     }
122     map_base = mmap(0, size, (PROT_READ|PROT_WRITE), MAP_SHARED, dev_mem_fd, (off_t)addr);
123     if(map_base == (void *) -1) 
124     {
125         hplib_Log("hplib_VM_MemMap: Failed to mmap \"dev/mem\" err=%s\n",
126                strerror(errno));
127         return (void *)0;
128     }
129     virt_addr = map_base;
131     return(virt_addr);
134 unsigned long peek(unsigned long * p)
136   return *p;
139 /**************************************************************************
140  *  FUNCTION PURPOSE:   Initialize the allocated memory pool area 
141  **************************************************************************/
142 HPLIB_BOOL_T hplib_VM_MemAllocInit
144     uint8_t     *addr,      /* Physical address */
145     uint32_t    size,        /* Size of block */
146     uint8_t i      /* pool id */
149     void *map_base = NULL;
150     uint32_t mapSize = 0;
151     uint32_t virtPoolHdrSize = sizeof(hplib_VirtMemPoolheader_T);
153     /* Set up memory mapping for un-cached  memory, this requires physical  address and size of memory region to map*/
154     if ((addr != NULL ) && size)
155     {
156         map_base = hplib_VM_MemMap((void *)addr, size);
157         if (!map_base)
158         {
159             hplib_Log("hplib_VM_MemAllocInit(): Failed to memory map for uncached memory, addr (0x%x)", 
160                         (uint32_t)addr);
161             return HPLIB_FALSE;
162         }
164         memPoolAddr[i].memPoolHdr = (hplib_VirtMemPoolheader_T*)map_base;
165         memPoolAddr[i].memStart = (uint8_t*)map_base + virtPoolHdrSize;
167         memPoolAddr[i].memSize = size;
168         memPoolAddr[i].memEnd = (uint8_t*)map_base + size;
169         memPoolAddr[i].memStartPhy = addr + virtPoolHdrSize;
170         memPoolAddr[i].memEndPhy = addr + size;
171         mapSize = memPoolAddr[i].memSize / (HPLIB_VM_BM_ALLOC_PAGE_SIZE*32);
173         memPoolAddr[i].memAllocPtr = memPoolAddr[i].memStart +
174                                                     mapSize +
175                                                     virtPoolHdrSize;
176         memPoolAddr[i].memAllocPtr =
177              (uint8_t*)align((uint32_t)memPoolAddr[i].memAllocPtr,
178                             HPLIB_VM_BM_ALLOC_PAGE_SIZE);
179         memPoolAddr[i].virtMapInfo =
180               (uint8_t*)bmAllocInit(memPoolAddr[i].memAllocPtr,
181                memPoolAddr[i].memSize - mapSize - virtPoolHdrSize,
182                (uint32_t*)&memPoolAddr[i].memPoolHdr->bmap,
183                HPLIB_VM_BM_ALLOC_PAGE_SIZE);
184     }
185     else if (addr == NULL)
186     {
187         addr=  ( uint8_t *) hplib_utilGetPhysOfBufferArea();
188         size = hplib_utilGetSizeOfBufferArea();
189         map_base = (void *) hplib_utilGetVaOfBufferArea(HPLIBMOD_MMAP_DMA_MEM_OFFSET,
190                                                         size); //mmap into our space, return va
191         memPoolAddr[i].memPoolHdr = (hplib_VirtMemPoolheader_T*)map_base;
192         memPoolAddr[i].memStart = (uint8_t*)map_base;
193         memPoolAddr[i].memSize =size;
194         memPoolAddr[i].memEnd = (uint8_t*)map_base + size;
195         memPoolAddr[i].memStartPhy = addr;
196         memPoolAddr[i].memEndPhy = addr + size;
197         mapSize = memPoolAddr[i].memSize / (HPLIB_VM_BM_ALLOC_PAGE_SIZE*32);
199         memPoolAddr[i].memAllocPtr = memPoolAddr[i].memStart +
200                                                     mapSize +
201                                                     virtPoolHdrSize;
203          memPoolAddr[i].memAllocPtr =
204              (uint8_t*)align((uint32_t)memPoolAddr[i].memAllocPtr,
205                             HPLIB_VM_BM_ALLOC_PAGE_SIZE);
207         memPoolAddr[i].virtMapInfo=
208               (uint8_t*)bmAllocInit(memPoolAddr[i].memAllocPtr,
209                memPoolAddr[i].memSize - mapSize - virtPoolHdrSize,
210                (uint32_t*)&memPoolAddr[i].memPoolHdr->bmap,
211                HPLIB_VM_BM_ALLOC_PAGE_SIZE);
212     }
213     else
214     {
215         return HPLIB_FALSE;
216     }
217     if (i== 0)
218     {
219         hplib_VM_mem_size = size;
220         hplib_VM_mem_alloc_ptr = hplib_VM_mem_start = map_base +
221                                                       mapSize +
222                                                       virtPoolHdrSize;
223         hplib_VM_mem_end = map_base + hplib_VM_mem_size;
224         hplib_VM_mem_start_phy = addr + mapSize + virtPoolHdrSize;
225         hplib_VM_mem_end_phy = addr + hplib_VM_mem_size;
226         hplib_VM_virt_to_phy_mapping = (uint32_t) hplib_VM_mem_start_phy - (uint32_t)hplib_VM_mem_start;
227         hplib_VM_phy_to_virt_mapping = (uint32_t)hplib_VM_mem_start - (uint32_t)hplib_VM_mem_start_phy;
228     }
229     return HPLIB_TRUE;
234 /**************************************************************************
235  *  FUNCTION PURPOSE:   Returns the free amount of buffer/descriptor area
236  *  for the memory pool specified.
237  **************************************************************************/
239 uint32_t  hplib_vmGetMemPoolRemainder(int pool_id)
241     hplib_VirtMemPoolheader_T *poolHdr;
242     uint32_t remainder;
243     void* key;
244     uint32_t virtPoolHdrSize;
245     uint32_t mapSize;
247     if (pool_id > (HPLIB_MAX_MEM_POOLS -1))
248         return 0;
249     Osal_hplibCsEnter();
251     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
253     mapSize = memPoolAddr[pool_id].memSize / (HPLIB_VM_BM_ALLOC_PAGE_SIZE*32);
254     virtPoolHdrSize = sizeof(hplib_VirtMemPoolheader_T);
255     Osal_hplibCsExit(key);
257     return (memPoolAddr[pool_id].memEnd -
258                 memPoolAddr[pool_id].memStart -
259                 mapSize -
260                 virtPoolHdrSize -
261                 poolHdr->totalAllocated);
265 /*****************************************************************************
266  * FUNCTION PURPOSE: Free memory for Buffer/Descriptors from memory pool
267  *                   specified
268  *****************************************************************************/
269 void hplib_vmMemFree
271     void        *ptr,
272     uint32_t    size,
273     int         pool_id
276     void* key = NULL;
277     hplib_VirtMemPoolheader_T *poolHdr;
279     if ((pool_id > (HPLIB_MAX_MEM_POOLS -1)) || (ptr == NULL))
280         return;
281     Osal_hplibCsEnter();
283     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
285     bmFree(memPoolAddr[pool_id].virtMapInfo,(unsigned char*)ptr, size);
286     poolHdr->totalAllocated -=size;
288     Osal_hplibCsExit(key);
289     return;
291 /*****************************************************************************
292  * FUNCTION PURPOSE: Allocates memory for Buffer/Descriptors from memory pool specified 
293  *****************************************************************************/
294 void* hplib_vmMemAlloc
296     uint32_t    size,
297     uint32_t    alignment,
298     int         pool_id
302     void* key = NULL;
303     hplib_VirtMemPoolheader_T *poolHdr;
304     void *pMalloc = NULL;
306     if (pool_id > (HPLIB_MAX_MEM_POOLS -1))
307     {
308         return NULL;
309     }
310     
311     Osal_hplibCsEnter();
312     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
314     pMalloc = bmAlloc(memPoolAddr[pool_id].virtMapInfo,size);
315     if (pMalloc)
316         poolHdr->totalAllocated += size;
318     Osal_hplibCsExit(key);
319     return pMalloc;
323 /********************************************************************
324  *FUNCTION PURPOSE: The function API is used to release/unmap continuous 
325  *  block of memory allocated via  hplib_VM_MemorySetup function, 
326  *  remove mapping of virtual memory for peripherals.
327  ********************************************************************/
328 void hplib_vmTeardown(void)
330     hplib_utilModClose();
331     close(dev_mem_fd);
334 hplib_RetValue hplib_checkMallocArea(int pool_id)
336     hplib_VirtMemPoolheader_T *poolHdr;
337     if (pool_id > (HPLIB_MAX_MEM_POOLS-1))
338     {
339         return hplib_FAILURE;
340     }
341     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
342     if(poolHdr->ref_count)
343         return hplib_OK;
344     else
345         return hplib_FAILURE;
348 hplib_RetValue hplib_resetMallocArea(int pool_id)
350     hplib_VirtMemPoolheader_T *poolHdr;
351     if (pool_id > (HPLIB_MAX_MEM_POOLS-1))
352     {
353         return hplib_FAILURE;
354     }
355     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
357     bmAllocClose(memPoolAddr[pool_id].virtMapInfo);
359     memset(poolHdr,
360            0,
361            memPoolAddr[pool_id].memAllocPtr - memPoolAddr[pool_id].memStart);
363     return hplib_OK;
366 hplib_RetValue hplib_initMallocArea(int pool_id)
368     hplib_VirtMemPoolheader_T *poolHdr;
370     if (pool_id > (HPLIB_MAX_MEM_POOLS -1))
371     {
372         return hplib_FAILURE;
373     }
375     poolHdr = (hplib_VirtMemPoolheader_T*) memPoolAddr[pool_id].memStart;
377     poolHdr->ref_count++;
378     poolHdr->totalAllocated = 0;
380     return hplib_OK;
383 /********************************************************************
384  * FUNCTION PURPOSE: Allocate continuous block of cached memory via CMA and
385  * optionally un-cached memory if specified, maps virtual memory for peripheral registers.
386  ********************************************************************/
387 hplib_RetValue hplib_vmInit(hplib_virtualAddrInfo_T *hplib_vmaddr,
388                             int num_pools,
389                             hplib_memPoolAttr_T *mempool_attr)
391     int i;
392     
393     if (num_pools == 0)
394     {
395         hplib_Log("hplib_vmInit(): Error, invalid number of pools\n");
396         return -1;
397     }
400     /*Open dev/mem, since we need for QM, CPPI, etc */
401     if((dev_mem_fd = open("/dev/mem", (O_RDWR | O_SYNC))) == -1)
402     {
403         hplib_Log("hplib_vmInit: Failed to open \"dev/mem\" err=%s\n",
404                strerror(errno));
405         return HPLIB_FALSE;
406     }
408     /* Open kernel module since we need it for PA to VA mappings */
409     if (hplib_utilModOpen() == -1)
410     {
411         hplib_Log("hplib_vmInit:: failed to open /dev/netapi: '%s'\n", strerror(errno));
412         return HPLIB_FALSE;
413     }
414     for (i=0;i < num_pools; i++)
415     {
416         /* Initialize memory which was allocated from DDR via hplibmod CMA*/
417         if (mempool_attr[i].attr == HPLIB_ATTR_KM_CACHED0) {
418             if (hplib_VM_MemAllocInit( NULL, 0, i) == HPLIB_FALSE)
419             {
420                 hplib_Log("hplib_vmInit: hplib_VM_MemAllocInit from DDR/CMA failed\n");
421                 return hplib_ERR_NOMEM;
422             }
423         }
424         /* Intialize memory for un-cached memory, make sure size and phys_addr passed in and have valid values */
425         if ((mempool_attr[i].attr == HPLIB_ATTR_UN_CACHED) && mempool_attr[i].size && mempool_attr[i].phys_addr)
426         {
427             if (hplib_VM_MemAllocInit((uint8_t*)mempool_attr[i].phys_addr,
428                                                             mempool_attr[i].size, i) == HPLIB_FALSE)
429             {
430                 hplib_Log(" hplib_vmInit: hplib_VM_MemAllocInit from un-cached memory failed\n");
431                 return hplib_ERR_NOMEM;
432             }
433         }
434     }
436     /* Create virtual memory maps for peripherals */
437     /* QMSS CFG Regs */
438     hplib_vmaddr->qmssCfgVaddr =
439         hplib_VM_MemMap((void*)CSL_QMSS_CFG_BASE, QMSS_CFG_BLK_SZ);
440     if (!hplib_vmaddr->qmssCfgVaddr)
441     {
442         hplib_Log("hplib_vmInit: Failed to map QMSS CFG registers\n");
443         return hplib_FAILURE;
444     }
446     /*QMSS DATA Regs */
447     hplib_vmaddr->qmssDataVaddr =
448         (void *) hplib_utilGetVaOfBufferArea(HPLIBMOD_MMAP_QM_DATA_REG_MEM_OFFSET,
449                                              QMSS_DATA_BLK_SZ);
451     if (!hplib_vmaddr->qmssDataVaddr)
452     {
453         hplib_Log("hplib_vmInit(): Failed to map QMSS DATA registers\n");
454         return hplib_FAILURE;
455     }
458     /* PASS CFG Regs */
459     hplib_vmaddr->passCfgVaddr =
460             hplib_VM_MemMap((void*)CSL_NETCP_CFG_REGS,
461                                    //p_device_cfg->netcpCfgBlkSz
462                                    PASS_CFG_BLK_SZ);
464     if (!hplib_vmaddr->passCfgVaddr)
465     {
466         hplib_Log("hplib_vmInit(): Failed to map PASS CFG registers\n");
467         return hplib_FAILURE;
468     }
470 #ifdef CORTEX_A8
471     /* (2f) Timer */
472     t64_memmap(dev_mem_fd);
473 #endif
475     return hplib_OK;