sym_malloc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 
  3.  * of PCI-SCSI IO processors.
  4.  *
  5.  * Copyright (C) 1999-2001  Gerard Roudier <groudier@free.fr>
  6.  *
  7.  * This driver is derived from the Linux sym53c8xx driver.
  8.  * Copyright (C) 1998-2000  Gerard Roudier
  9.  *
  10.  * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 
  11.  * a port of the FreeBSD ncr driver to Linux-1.2.13.
  12.  *
  13.  * The original ncr driver has been written for 386bsd and FreeBSD by
  14.  *         Wolfgang Stanglmeier        <wolf@cologne.de>
  15.  *         Stefan Esser                <se@mi.Uni-Koeln.de>
  16.  * Copyright (C) 1994  Wolfgang Stanglmeier
  17.  *
  18.  * Other major contributions:
  19.  *
  20.  * NVRAM detection and reading.
  21.  * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
  22.  *
  23.  *-----------------------------------------------------------------------------
  24.  *
  25.  * Redistribution and use in source and binary forms, with or without
  26.  * modification, are permitted provided that the following conditions
  27.  * are met:
  28.  * 1. Redistributions of source code must retain the above copyright
  29.  *    notice, this list of conditions and the following disclaimer.
  30.  * 2. The name of the author may not be used to endorse or promote products
  31.  *    derived from this software without specific prior written permission.
  32.  *
  33.  * Where this Software is combined with software released under the terms of 
  34.  * the GNU Public License ("GPL") and the terms of the GPL would require the 
  35.  * combined work to also be released under the terms of the GPL, the terms
  36.  * and conditions of this License will apply in addition to those of the
  37.  * GPL with the exception of any terms or conditions of this License that
  38.  * conflict with, or are expressly prohibited by, the GPL.
  39.  *
  40.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  41.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43.  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  44.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50.  * SUCH DAMAGE.
  51.  */
  52. #ifdef __FreeBSD__
  53. #include <dev/sym/sym_glue.h>
  54. #else
  55. #include "sym_glue.h"
  56. #endif
  57. /*
  58.  *  Simple power of two buddy-like generic allocator.
  59.  *  Provides naturally aligned memory chunks.
  60.  *
  61.  *  This simple code is not intended to be fast, but to 
  62.  *  provide power of 2 aligned memory allocations.
  63.  *  Since the SCRIPTS processor only supplies 8 bit arithmetic, 
  64.  *  this allocator allows simple and fast address calculations  
  65.  *  from the SCRIPTS code. In addition, cache line alignment 
  66.  *  is guaranteed for power of 2 cache line size.
  67.  *
  68.  *  This allocator has been developped for the Linux sym53c8xx  
  69.  *  driver, since this O/S does not provide naturally aligned 
  70.  *  allocations.
  71.  *  It has the advantage of allowing the driver to use private 
  72.  *  pages of memory that will be useful if we ever need to deal 
  73.  *  with IO MMUs for PCI.
  74.  */
  75. static void *___sym_malloc(m_pool_p mp, int size)
  76. {
  77. int i = 0;
  78. int s = (1 << SYM_MEM_SHIFT);
  79. int j;
  80. m_addr_t a;
  81. m_link_p h = mp->h;
  82. if (size > SYM_MEM_CLUSTER_SIZE)
  83. return 0;
  84. while (size > s) {
  85. s <<= 1;
  86. ++i;
  87. }
  88. j = i;
  89. while (!h[j].next) {
  90. if (s == SYM_MEM_CLUSTER_SIZE) {
  91. h[j].next = (m_link_p) M_GET_MEM_CLUSTER();
  92. if (h[j].next)
  93. h[j].next->next = 0;
  94. break;
  95. }
  96. ++j;
  97. s <<= 1;
  98. }
  99. a = (m_addr_t) h[j].next;
  100. if (a) {
  101. h[j].next = h[j].next->next;
  102. while (j > i) {
  103. j -= 1;
  104. s >>= 1;
  105. h[j].next = (m_link_p) (a+s);
  106. h[j].next->next = 0;
  107. }
  108. }
  109. #ifdef DEBUG
  110. printf("___sym_malloc(%d) = %pn", size, (void *) a);
  111. #endif
  112. return (void *) a;
  113. }
  114. /*
  115.  *  Counter-part of the generic allocator.
  116.  */
  117. static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
  118. {
  119. int i = 0;
  120. int s = (1 << SYM_MEM_SHIFT);
  121. m_link_p q;
  122. m_addr_t a, b;
  123. m_link_p h = mp->h;
  124. #ifdef DEBUG
  125. printf("___sym_mfree(%p, %d)n", ptr, size);
  126. #endif
  127. if (size > SYM_MEM_CLUSTER_SIZE)
  128. return;
  129. while (size > s) {
  130. s <<= 1;
  131. ++i;
  132. }
  133. a = (m_addr_t) ptr;
  134. while (1) {
  135. #ifdef SYM_MEM_FREE_UNUSED
  136. if (s == SYM_MEM_CLUSTER_SIZE) {
  137. M_FREE_MEM_CLUSTER(a);
  138. break;
  139. }
  140. #endif
  141. b = a ^ s;
  142. q = &h[i];
  143. while (q->next && q->next != (m_link_p) b) {
  144. q = q->next;
  145. }
  146. if (!q->next) {
  147. ((m_link_p) a)->next = h[i].next;
  148. h[i].next = (m_link_p) a;
  149. break;
  150. }
  151. q->next = q->next->next;
  152. a = a & b;
  153. s <<= 1;
  154. ++i;
  155. }
  156. }
  157. /*
  158.  *  Verbose and zeroing allocator that wrapps to the generic allocator.
  159.  */
  160. static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
  161. {
  162. void *p;
  163. p = ___sym_malloc(mp, size);
  164. if (DEBUG_FLAGS & DEBUG_ALLOC) {
  165. printf ("new %-10s[%4d] @%p.n", name, size, p);
  166. }
  167. if (p)
  168. bzero(p, size);
  169. else if (uflags & SYM_MEM_WARN)
  170. printf ("__sym_calloc2: failed to allocate %s[%d]n", name, size);
  171. return p;
  172. }
  173. #define __sym_calloc(mp, s, n) __sym_calloc2(mp, s, n, SYM_MEM_WARN)
  174. /*
  175.  *  Its counter-part.
  176.  */
  177. static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
  178. {
  179. if (DEBUG_FLAGS & DEBUG_ALLOC)
  180. printf ("freeing %-10s[%4d] @%p.n", name, size, ptr);
  181. ___sym_mfree(mp, ptr, size);
  182. }
  183. /*
  184.  *  Default memory pool we donnot need to involve in DMA.
  185.  *
  186.  *  If DMA abtraction is not needed, the generic allocator 
  187.  *  calls directly some kernel allocator.
  188.  *
  189.  *  With DMA abstraction, we use functions (methods), to 
  190.  *  distinguish between non DMAable memory and DMAable memory.
  191.  */
  192. #ifndef SYM_OPT_BUS_DMA_ABSTRACTION
  193. static struct sym_m_pool mp0;
  194. #else
  195. static m_addr_t ___mp0_get_mem_cluster(m_pool_p mp)
  196. {
  197. m_addr_t m = (m_addr_t) sym_get_mem_cluster();
  198. if (m)
  199. ++mp->nump;
  200. return m;
  201. }
  202. #ifdef SYM_MEM_FREE_UNUSED
  203. static void ___mp0_free_mem_cluster(m_pool_p mp, m_addr_t m)
  204. {
  205. sym_free_mem_cluster(m);
  206. --mp->nump;
  207. }
  208. #endif
  209. #ifdef SYM_MEM_FREE_UNUSED
  210. static struct sym_m_pool mp0 =
  211. {0, ___mp0_get_mem_cluster, ___mp0_free_mem_cluster};
  212. #else
  213. static struct sym_m_pool mp0 =
  214. {0, ___mp0_get_mem_cluster};
  215. #endif
  216. #endif /* SYM_OPT_BUS_DMA_ABSTRACTION */
  217. /*
  218.  * Actual memory allocation routine for non-DMAed memory.
  219.  */
  220. void *sym_calloc_unlocked(int size, char *name)
  221. {
  222. void *m;
  223. m = __sym_calloc(&mp0, size, name);
  224. return m;
  225. }
  226. /*
  227.  *  Its counter-part.
  228.  */
  229. void sym_mfree_unlocked(void *ptr, int size, char *name)
  230. {
  231. __sym_mfree(&mp0, ptr, size, name);
  232. }
  233. #ifdef SYM_OPT_BUS_DMA_ABSTRACTION
  234. /*
  235.  *  Methods that maintains DMAable pools according to user allocations.
  236.  *  New pools are created on the fly when a new pool id is provided.
  237.  *  They are deleted on the fly when they get emptied.
  238.  */
  239. /* Get a memory cluster that matches the DMA contraints of a given pool */
  240. static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
  241. {
  242. m_vtob_p vbp;
  243. m_addr_t vaddr;
  244. vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB");
  245. if (!vbp)
  246. goto out_err;
  247. vaddr = sym_m_get_dma_mem_cluster(mp, vbp);
  248. if (vaddr) {
  249. int hc = VTOB_HASH_CODE(vaddr);
  250. vbp->next = mp->vtob[hc];
  251. mp->vtob[hc] = vbp;
  252. ++mp->nump;
  253. return (m_addr_t) vaddr;
  254. }
  255. return vaddr;
  256. out_err:
  257. return 0;
  258. }
  259. #ifdef SYM_MEM_FREE_UNUSED
  260. /* Free a memory cluster and associated resources for DMA */
  261. static void ___free_dma_mem_cluster(m_pool_p mp, m_addr_t m)
  262. {
  263. m_vtob_p *vbpp, vbp;
  264. int hc = VTOB_HASH_CODE(m);
  265. vbpp = &mp->vtob[hc];
  266. while (*vbpp && (*vbpp)->vaddr != m)
  267. vbpp = &(*vbpp)->next;
  268. if (*vbpp) {
  269. vbp = *vbpp;
  270. *vbpp = (*vbpp)->next;
  271. sym_m_free_dma_mem_cluster(mp, vbp);
  272. __sym_mfree(&mp0, vbp, sizeof(*vbp), "VTOB");
  273. --mp->nump;
  274. }
  275. }
  276. #endif
  277. /* Fetch the memory pool for a given pool id (i.e. DMA constraints) */
  278. static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
  279. {
  280. m_pool_p mp;
  281. for (mp = mp0.next;
  282. mp && !sym_m_pool_match(mp->dev_dmat, dev_dmat);
  283. mp = mp->next);
  284. return mp;
  285. }
  286. /* Create a new memory DMAable pool (when fetch failed) */
  287. static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat)
  288. {
  289. m_pool_p mp = 0;
  290. mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
  291. if (mp) {
  292. mp->dev_dmat = dev_dmat;
  293. if (!sym_m_create_dma_mem_tag(mp)) {
  294. mp->get_mem_cluster = ___get_dma_mem_cluster;
  295. #ifdef SYM_MEM_FREE_UNUSED
  296. mp->free_mem_cluster = ___free_dma_mem_cluster;
  297. #endif
  298. mp->next = mp0.next;
  299. mp0.next = mp;
  300. return mp;
  301. }
  302. }
  303. if (mp)
  304. __sym_mfree(&mp0, mp, sizeof(*mp), "MPOOL");
  305. return 0;
  306. }
  307. #ifdef SYM_MEM_FREE_UNUSED
  308. /* Destroy a DMAable memory pool (when got emptied) */
  309. static void ___del_dma_pool(m_pool_p p)
  310. {
  311. m_pool_p *pp = &mp0.next;
  312. while (*pp && *pp != p)
  313. pp = &(*pp)->next;
  314. if (*pp) {
  315. *pp = (*pp)->next;
  316. sym_m_delete_dma_mem_tag(p);
  317. __sym_mfree(&mp0, p, sizeof(*p), "MPOOL");
  318. }
  319. }
  320. #endif
  321. /*
  322.  *  Actual allocator for DMAable memory.
  323.  */
  324. void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name)
  325. {
  326. m_pool_p mp;
  327. void *m = 0;
  328. mp = ___get_dma_pool(dev_dmat);
  329. if (!mp)
  330. mp = ___cre_dma_pool(dev_dmat);
  331. if (mp)
  332. m = __sym_calloc(mp, size, name);
  333. #ifdef SYM_MEM_FREE_UNUSED
  334. if (mp && !mp->nump)
  335. ___del_dma_pool(mp);
  336. #endif
  337. return m;
  338. }
  339. /*
  340.  *  Its counter-part.
  341.  */
  342. void 
  343. __sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m, int size, char *name)
  344. {
  345. m_pool_p mp;
  346. mp = ___get_dma_pool(dev_dmat);
  347. if (mp)
  348. __sym_mfree(mp, m, size, name);
  349. #ifdef SYM_MEM_FREE_UNUSED
  350. if (mp && !mp->nump)
  351. ___del_dma_pool(mp);
  352. #endif
  353. }
  354. /*
  355.  *  Actual virtual to bus physical address translator 
  356.  *  for 32 bit addressable DMAable memory.
  357.  */
  358. u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m)
  359. {
  360. m_pool_p mp;
  361. int hc = VTOB_HASH_CODE(m);
  362. m_vtob_p vp = 0;
  363. m_addr_t a = ((m_addr_t) m) & ~SYM_MEM_CLUSTER_MASK;
  364. mp = ___get_dma_pool(dev_dmat);
  365. if (mp) {
  366. vp = mp->vtob[hc];
  367. while (vp && (m_addr_t) vp->vaddr != a)
  368. vp = vp->next;
  369. }
  370. if (!vp)
  371. panic("sym: VTOBUS FAILED!n");
  372. return (u32)(vp ? vp->baddr + (((m_addr_t) m) - a) : 0);
  373. }
  374. #endif /* SYM_OPT_BUS_DMA_ABSTRACTION */