iomem.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <stddef.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include "iomem.h"
  6. #include "printf.h"
  7. #include "atomic.h"
  8. #define IOMEM_BLOCK_SIZE 256
  9. typedef struct _iomem_malloc_t
  10. {
  11. void (*init)();
  12. uint32_t (*unused)();
  13. uint8_t *membase;
  14. uint32_t memsize;
  15. uint32_t memtblsize;
  16. uint16_t *memmap;
  17. uint8_t memrdy;
  18. _lock_t *lock;
  19. } iomem_malloc_t;
  20. static _lock_t iomem_lock;
  21. static void iomem_init();
  22. static uint32_t k_unused();
  23. extern char *_ioheap_line;
  24. extern char *_heap_line;
  25. extern char _heap_start[];
  26. extern char *_heap_cur;
  27. iomem_malloc_t malloc_cortol =
  28. {
  29. iomem_init,
  30. k_unused,
  31. NULL,
  32. 0,
  33. 0,
  34. NULL,
  35. 0,
  36. &iomem_lock
  37. };
  38. static void iomem_set(void *s, uint8_t c, uint32_t num)
  39. {
  40. uint8_t *xs = s;
  41. while(num--)
  42. *xs++=c;
  43. }
  44. static void iomem_init()
  45. {
  46. malloc_cortol.membase = (uint8_t *)((uintptr_t)_heap_line-0x40000000);
  47. malloc_cortol.memsize = (uint32_t)_ioheap_line - (uint32_t)malloc_cortol.membase;
  48. malloc_cortol.memtblsize = malloc_cortol.memsize / IOMEM_BLOCK_SIZE;
  49. malloc_cortol.memmap = (uint16_t *)malloc(malloc_cortol.memtblsize * 2);
  50. mb();
  51. malloc_cortol.membase = (uint8_t *)((uintptr_t)_heap_line-0x40000000);
  52. malloc_cortol.memsize = (uint32_t)_ioheap_line - (uint32_t)malloc_cortol.membase;
  53. malloc_cortol.memtblsize = malloc_cortol.memsize / IOMEM_BLOCK_SIZE;
  54. iomem_set(malloc_cortol.memmap, 0, malloc_cortol.memtblsize * 2);
  55. iomem_set(malloc_cortol.membase, 0, malloc_cortol.memsize);
  56. malloc_cortol.memrdy = 1;
  57. }
  58. static uint32_t k_unused()
  59. {
  60. uint32_t unused=0;
  61. unused = (uintptr_t)_ioheap_line + 0x40000000 - (uintptr_t)_heap_line;
  62. return unused;
  63. }
  64. static uint32_t k_malloc(uint32_t size)
  65. {
  66. signed long offset = 0;
  67. uint32_t xmemb;
  68. uint32_t kmemb = 0;
  69. if(!malloc_cortol.memrdy)
  70. malloc_cortol.init();
  71. if(size==0)
  72. return 0XFFFFFFFF;
  73. xmemb=size / IOMEM_BLOCK_SIZE;
  74. if(size % IOMEM_BLOCK_SIZE)
  75. xmemb++;
  76. for(offset=malloc_cortol.memtblsize-1; offset>=0; offset--)
  77. {
  78. if(!malloc_cortol.memmap[offset])
  79. {
  80. kmemb++;
  81. }
  82. else
  83. {
  84. offset = offset - malloc_cortol.memmap[offset] + 1;
  85. kmemb=0;
  86. }
  87. if(kmemb==xmemb)
  88. {
  89. malloc_cortol.memmap[offset] = xmemb;
  90. malloc_cortol.memmap[offset+xmemb-1] = xmemb;
  91. return (offset * IOMEM_BLOCK_SIZE);
  92. }
  93. }
  94. return 0XFFFFFFFF;
  95. }
  96. static uint8_t k_free(uint32_t offset)
  97. {
  98. if(!malloc_cortol.memrdy)
  99. {
  100. malloc_cortol.init();
  101. return 1;
  102. }
  103. if(offset < malloc_cortol.memsize)
  104. {
  105. int index=offset / IOMEM_BLOCK_SIZE;
  106. int nmemb=malloc_cortol.memmap[index];
  107. malloc_cortol.memmap[index] = 0;
  108. malloc_cortol.memmap[index+nmemb-1] = 0;
  109. if((uintptr_t)_ioheap_line == (uintptr_t)malloc_cortol.membase + offset)
  110. {
  111. _ioheap_line = (char *)((uintptr_t)_ioheap_line + nmemb * IOMEM_BLOCK_SIZE);
  112. }
  113. return 0;
  114. }
  115. else
  116. return 2;
  117. }
  118. void iomem_free(void *paddr)
  119. {
  120. uint32_t offset;
  121. if(paddr == NULL)
  122. return;
  123. _lock_acquire_recursive(malloc_cortol.lock);
  124. offset=(uintptr_t)paddr - (uintptr_t)malloc_cortol.membase;
  125. k_free(offset);
  126. _lock_release_recursive(malloc_cortol.lock);
  127. }
  128. void *iomem_malloc(uint32_t size)
  129. {
  130. _lock_acquire_recursive(malloc_cortol.lock);
  131. uint32_t offset;
  132. offset=k_malloc(size);
  133. if(offset == 0XFFFFFFFF)
  134. {
  135. printk("IOMEM malloc OUT of MEMORY!\r\n");
  136. _lock_release_recursive(malloc_cortol.lock);
  137. return NULL;
  138. }
  139. else
  140. {
  141. if((uintptr_t)_ioheap_line > (uintptr_t)malloc_cortol.membase + offset)
  142. {
  143. _ioheap_line = (char *)((uintptr_t)malloc_cortol.membase + offset);
  144. if((uintptr_t)_ioheap_line < (uintptr_t)_heap_line-0x40000000)
  145. {
  146. printk("Error: OUT of MEMORY!\r\n");
  147. printk("_heap_line = %p\r\n", _heap_line);
  148. printk("_ioheap_line = %p\r\n", _ioheap_line);
  149. while(1)
  150. ;
  151. }
  152. };
  153. _lock_release_recursive(malloc_cortol.lock);
  154. return (void*)((uintptr_t)malloc_cortol.membase + offset);
  155. }
  156. }
  157. uint32_t iomem_unused()
  158. {
  159. return malloc_cortol.unused();
  160. }