18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 48c2ecf20Sopenharmony_ci * of PCI-SCSI IO processors. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This driver is derived from the Linux sym53c8xx driver. 98c2ecf20Sopenharmony_ci * Copyright (C) 1998-2000 Gerard Roudier 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 128c2ecf20Sopenharmony_ci * a port of the FreeBSD ncr driver to Linux-1.2.13. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * The original ncr driver has been written for 386bsd and FreeBSD by 158c2ecf20Sopenharmony_ci * Wolfgang Stanglmeier <wolf@cologne.de> 168c2ecf20Sopenharmony_ci * Stefan Esser <se@mi.Uni-Koeln.de> 178c2ecf20Sopenharmony_ci * Copyright (C) 1994 Wolfgang Stanglmeier 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Other major contributions: 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * NVRAM detection and reading. 228c2ecf20Sopenharmony_ci * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci *----------------------------------------------------------------------------- 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include "sym_glue.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Simple power of two buddy-like generic allocator. 318c2ecf20Sopenharmony_ci * Provides naturally aligned memory chunks. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * This simple code is not intended to be fast, but to 348c2ecf20Sopenharmony_ci * provide power of 2 aligned memory allocations. 358c2ecf20Sopenharmony_ci * Since the SCRIPTS processor only supplies 8 bit arithmetic, 368c2ecf20Sopenharmony_ci * this allocator allows simple and fast address calculations 378c2ecf20Sopenharmony_ci * from the SCRIPTS code. In addition, cache line alignment 388c2ecf20Sopenharmony_ci * is guaranteed for power of 2 cache line size. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * This allocator has been developed for the Linux sym53c8xx 418c2ecf20Sopenharmony_ci * driver, since this O/S does not provide naturally aligned 428c2ecf20Sopenharmony_ci * allocations. 438c2ecf20Sopenharmony_ci * It has the advantage of allowing the driver to use private 448c2ecf20Sopenharmony_ci * pages of memory that will be useful if we ever need to deal 458c2ecf20Sopenharmony_ci * with IO MMUs for PCI. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_cistatic void *___sym_malloc(m_pool_p mp, int size) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci int i = 0; 508c2ecf20Sopenharmony_ci int s = (1 << SYM_MEM_SHIFT); 518c2ecf20Sopenharmony_ci int j; 528c2ecf20Sopenharmony_ci void *a; 538c2ecf20Sopenharmony_ci m_link_p h = mp->h; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (size > SYM_MEM_CLUSTER_SIZE) 568c2ecf20Sopenharmony_ci return NULL; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci while (size > s) { 598c2ecf20Sopenharmony_ci s <<= 1; 608c2ecf20Sopenharmony_ci ++i; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci j = i; 648c2ecf20Sopenharmony_ci while (!h[j].next) { 658c2ecf20Sopenharmony_ci if (s == SYM_MEM_CLUSTER_SIZE) { 668c2ecf20Sopenharmony_ci h[j].next = (m_link_p) M_GET_MEM_CLUSTER(); 678c2ecf20Sopenharmony_ci if (h[j].next) 688c2ecf20Sopenharmony_ci h[j].next->next = NULL; 698c2ecf20Sopenharmony_ci break; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci ++j; 728c2ecf20Sopenharmony_ci s <<= 1; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci a = h[j].next; 758c2ecf20Sopenharmony_ci if (a) { 768c2ecf20Sopenharmony_ci h[j].next = h[j].next->next; 778c2ecf20Sopenharmony_ci while (j > i) { 788c2ecf20Sopenharmony_ci j -= 1; 798c2ecf20Sopenharmony_ci s >>= 1; 808c2ecf20Sopenharmony_ci h[j].next = (m_link_p) (a+s); 818c2ecf20Sopenharmony_ci h[j].next->next = NULL; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci#ifdef DEBUG 858c2ecf20Sopenharmony_ci printf("___sym_malloc(%d) = %p\n", size, (void *) a); 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ci return a; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * Counter-part of the generic allocator. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_cistatic void ___sym_mfree(m_pool_p mp, void *ptr, int size) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci int i = 0; 968c2ecf20Sopenharmony_ci int s = (1 << SYM_MEM_SHIFT); 978c2ecf20Sopenharmony_ci m_link_p q; 988c2ecf20Sopenharmony_ci unsigned long a, b; 998c2ecf20Sopenharmony_ci m_link_p h = mp->h; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#ifdef DEBUG 1028c2ecf20Sopenharmony_ci printf("___sym_mfree(%p, %d)\n", ptr, size); 1038c2ecf20Sopenharmony_ci#endif 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (size > SYM_MEM_CLUSTER_SIZE) 1068c2ecf20Sopenharmony_ci return; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci while (size > s) { 1098c2ecf20Sopenharmony_ci s <<= 1; 1108c2ecf20Sopenharmony_ci ++i; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci a = (unsigned long)ptr; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci while (1) { 1168c2ecf20Sopenharmony_ci if (s == SYM_MEM_CLUSTER_SIZE) { 1178c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 1188c2ecf20Sopenharmony_ci M_FREE_MEM_CLUSTER((void *)a); 1198c2ecf20Sopenharmony_ci#else 1208c2ecf20Sopenharmony_ci ((m_link_p) a)->next = h[i].next; 1218c2ecf20Sopenharmony_ci h[i].next = (m_link_p) a; 1228c2ecf20Sopenharmony_ci#endif 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci b = a ^ s; 1268c2ecf20Sopenharmony_ci q = &h[i]; 1278c2ecf20Sopenharmony_ci while (q->next && q->next != (m_link_p) b) { 1288c2ecf20Sopenharmony_ci q = q->next; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci if (!q->next) { 1318c2ecf20Sopenharmony_ci ((m_link_p) a)->next = h[i].next; 1328c2ecf20Sopenharmony_ci h[i].next = (m_link_p) a; 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci q->next = q->next->next; 1368c2ecf20Sopenharmony_ci a = a & b; 1378c2ecf20Sopenharmony_ci s <<= 1; 1388c2ecf20Sopenharmony_ci ++i; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* 1438c2ecf20Sopenharmony_ci * Verbose and zeroing allocator that wrapps to the generic allocator. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_cistatic void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci void *p; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci p = ___sym_malloc(mp, size); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (DEBUG_FLAGS & DEBUG_ALLOC) { 1528c2ecf20Sopenharmony_ci printf ("new %-10s[%4d] @%p.\n", name, size, p); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (p) 1568c2ecf20Sopenharmony_ci memset(p, 0, size); 1578c2ecf20Sopenharmony_ci else if (uflags & SYM_MEM_WARN) 1588c2ecf20Sopenharmony_ci printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size); 1598c2ecf20Sopenharmony_ci return p; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci#define __sym_calloc(mp, s, n) __sym_calloc2(mp, s, n, SYM_MEM_WARN) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* 1648c2ecf20Sopenharmony_ci * Its counter-part. 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_cistatic void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci if (DEBUG_FLAGS & DEBUG_ALLOC) 1698c2ecf20Sopenharmony_ci printf ("freeing %-10s[%4d] @%p.\n", name, size, ptr); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci ___sym_mfree(mp, ptr, size); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/* 1758c2ecf20Sopenharmony_ci * Default memory pool we donnot need to involve in DMA. 1768c2ecf20Sopenharmony_ci * 1778c2ecf20Sopenharmony_ci * With DMA abstraction, we use functions (methods), to 1788c2ecf20Sopenharmony_ci * distinguish between non DMAable memory and DMAable memory. 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_cistatic void *___mp0_get_mem_cluster(m_pool_p mp) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci void *m = sym_get_mem_cluster(); 1838c2ecf20Sopenharmony_ci if (m) 1848c2ecf20Sopenharmony_ci ++mp->nump; 1858c2ecf20Sopenharmony_ci return m; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 1898c2ecf20Sopenharmony_cistatic void ___mp0_free_mem_cluster(m_pool_p mp, void *m) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci sym_free_mem_cluster(m); 1928c2ecf20Sopenharmony_ci --mp->nump; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci#else 1958c2ecf20Sopenharmony_ci#define ___mp0_free_mem_cluster NULL 1968c2ecf20Sopenharmony_ci#endif 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic struct sym_m_pool mp0 = { 1998c2ecf20Sopenharmony_ci NULL, 2008c2ecf20Sopenharmony_ci ___mp0_get_mem_cluster, 2018c2ecf20Sopenharmony_ci ___mp0_free_mem_cluster 2028c2ecf20Sopenharmony_ci}; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci/* 2058c2ecf20Sopenharmony_ci * Methods that maintains DMAable pools according to user allocations. 2068c2ecf20Sopenharmony_ci * New pools are created on the fly when a new pool id is provided. 2078c2ecf20Sopenharmony_ci * They are deleted on the fly when they get emptied. 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci/* Get a memory cluster that matches the DMA constraints of a given pool */ 2108c2ecf20Sopenharmony_cistatic void * ___get_dma_mem_cluster(m_pool_p mp) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci m_vtob_p vbp; 2138c2ecf20Sopenharmony_ci void *vaddr; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB"); 2168c2ecf20Sopenharmony_ci if (!vbp) 2178c2ecf20Sopenharmony_ci goto out_err; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci vaddr = sym_m_get_dma_mem_cluster(mp, vbp); 2208c2ecf20Sopenharmony_ci if (vaddr) { 2218c2ecf20Sopenharmony_ci int hc = VTOB_HASH_CODE(vaddr); 2228c2ecf20Sopenharmony_ci vbp->next = mp->vtob[hc]; 2238c2ecf20Sopenharmony_ci mp->vtob[hc] = vbp; 2248c2ecf20Sopenharmony_ci ++mp->nump; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci return vaddr; 2278c2ecf20Sopenharmony_ciout_err: 2288c2ecf20Sopenharmony_ci return NULL; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 2328c2ecf20Sopenharmony_ci/* Free a memory cluster and associated resources for DMA */ 2338c2ecf20Sopenharmony_cistatic void ___free_dma_mem_cluster(m_pool_p mp, void *m) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci m_vtob_p *vbpp, vbp; 2368c2ecf20Sopenharmony_ci int hc = VTOB_HASH_CODE(m); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci vbpp = &mp->vtob[hc]; 2398c2ecf20Sopenharmony_ci while (*vbpp && (*vbpp)->vaddr != m) 2408c2ecf20Sopenharmony_ci vbpp = &(*vbpp)->next; 2418c2ecf20Sopenharmony_ci if (*vbpp) { 2428c2ecf20Sopenharmony_ci vbp = *vbpp; 2438c2ecf20Sopenharmony_ci *vbpp = (*vbpp)->next; 2448c2ecf20Sopenharmony_ci sym_m_free_dma_mem_cluster(mp, vbp); 2458c2ecf20Sopenharmony_ci __sym_mfree(&mp0, vbp, sizeof(*vbp), "VTOB"); 2468c2ecf20Sopenharmony_ci --mp->nump; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci#endif 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* Fetch the memory pool for a given pool id (i.e. DMA constraints) */ 2528c2ecf20Sopenharmony_cistatic inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci m_pool_p mp; 2558c2ecf20Sopenharmony_ci for (mp = mp0.next; 2568c2ecf20Sopenharmony_ci mp && !sym_m_pool_match(mp->dev_dmat, dev_dmat); 2578c2ecf20Sopenharmony_ci mp = mp->next); 2588c2ecf20Sopenharmony_ci return mp; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/* Create a new memory DMAable pool (when fetch failed) */ 2628c2ecf20Sopenharmony_cistatic m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci m_pool_p mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL"); 2658c2ecf20Sopenharmony_ci if (mp) { 2668c2ecf20Sopenharmony_ci mp->dev_dmat = dev_dmat; 2678c2ecf20Sopenharmony_ci mp->get_mem_cluster = ___get_dma_mem_cluster; 2688c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 2698c2ecf20Sopenharmony_ci mp->free_mem_cluster = ___free_dma_mem_cluster; 2708c2ecf20Sopenharmony_ci#endif 2718c2ecf20Sopenharmony_ci mp->next = mp0.next; 2728c2ecf20Sopenharmony_ci mp0.next = mp; 2738c2ecf20Sopenharmony_ci return mp; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci return NULL; 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 2798c2ecf20Sopenharmony_ci/* Destroy a DMAable memory pool (when got emptied) */ 2808c2ecf20Sopenharmony_cistatic void ___del_dma_pool(m_pool_p p) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci m_pool_p *pp = &mp0.next; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci while (*pp && *pp != p) 2858c2ecf20Sopenharmony_ci pp = &(*pp)->next; 2868c2ecf20Sopenharmony_ci if (*pp) { 2878c2ecf20Sopenharmony_ci *pp = (*pp)->next; 2888c2ecf20Sopenharmony_ci __sym_mfree(&mp0, p, sizeof(*p), "MPOOL"); 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci#endif 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* This lock protects only the memory allocation/free. */ 2948c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(sym53c8xx_lock); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci/* 2978c2ecf20Sopenharmony_ci * Actual allocator for DMAable memory. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_civoid *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci unsigned long flags; 3028c2ecf20Sopenharmony_ci m_pool_p mp; 3038c2ecf20Sopenharmony_ci void *m = NULL; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci spin_lock_irqsave(&sym53c8xx_lock, flags); 3068c2ecf20Sopenharmony_ci mp = ___get_dma_pool(dev_dmat); 3078c2ecf20Sopenharmony_ci if (!mp) 3088c2ecf20Sopenharmony_ci mp = ___cre_dma_pool(dev_dmat); 3098c2ecf20Sopenharmony_ci if (!mp) 3108c2ecf20Sopenharmony_ci goto out; 3118c2ecf20Sopenharmony_ci m = __sym_calloc(mp, size, name); 3128c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 3138c2ecf20Sopenharmony_ci if (!mp->nump) 3148c2ecf20Sopenharmony_ci ___del_dma_pool(mp); 3158c2ecf20Sopenharmony_ci#endif 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci out: 3188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sym53c8xx_lock, flags); 3198c2ecf20Sopenharmony_ci return m; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_civoid __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci unsigned long flags; 3258c2ecf20Sopenharmony_ci m_pool_p mp; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci spin_lock_irqsave(&sym53c8xx_lock, flags); 3288c2ecf20Sopenharmony_ci mp = ___get_dma_pool(dev_dmat); 3298c2ecf20Sopenharmony_ci if (!mp) 3308c2ecf20Sopenharmony_ci goto out; 3318c2ecf20Sopenharmony_ci __sym_mfree(mp, m, size, name); 3328c2ecf20Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 3338c2ecf20Sopenharmony_ci if (!mp->nump) 3348c2ecf20Sopenharmony_ci ___del_dma_pool(mp); 3358c2ecf20Sopenharmony_ci#endif 3368c2ecf20Sopenharmony_ci out: 3378c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sym53c8xx_lock, flags); 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci/* 3418c2ecf20Sopenharmony_ci * Actual virtual to bus physical address translator 3428c2ecf20Sopenharmony_ci * for 32 bit addressable DMAable memory. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_cidma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci unsigned long flags; 3478c2ecf20Sopenharmony_ci m_pool_p mp; 3488c2ecf20Sopenharmony_ci int hc = VTOB_HASH_CODE(m); 3498c2ecf20Sopenharmony_ci m_vtob_p vp = NULL; 3508c2ecf20Sopenharmony_ci void *a = (void *)((unsigned long)m & ~SYM_MEM_CLUSTER_MASK); 3518c2ecf20Sopenharmony_ci dma_addr_t b; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci spin_lock_irqsave(&sym53c8xx_lock, flags); 3548c2ecf20Sopenharmony_ci mp = ___get_dma_pool(dev_dmat); 3558c2ecf20Sopenharmony_ci if (mp) { 3568c2ecf20Sopenharmony_ci vp = mp->vtob[hc]; 3578c2ecf20Sopenharmony_ci while (vp && vp->vaddr != a) 3588c2ecf20Sopenharmony_ci vp = vp->next; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci if (!vp) 3618c2ecf20Sopenharmony_ci panic("sym: VTOBUS FAILED!\n"); 3628c2ecf20Sopenharmony_ci b = vp->baddr + (m - a); 3638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sym53c8xx_lock, flags); 3648c2ecf20Sopenharmony_ci return b; 3658c2ecf20Sopenharmony_ci} 366