// SPDX-License-Identifier: GPL-2.0-or-later /* * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier * * The sym53c8xx driver is derived from the ncr53c8xx driver that had been * a port of the FreeBSD ncr driver to Linux-1.2.13. * * The original ncr driver has been written for 386bsd and FreeBSD by * Wolfgang Stanglmeier <wolf@cologne.de> * Stefan Esser <se@mi.Uni-Koeln.de> * Copyright (C) 1994 Wolfgang Stanglmeier * * Other major contributions: * * NVRAM detection and reading. * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> * *-----------------------------------------------------------------------------
*/
#include"sym_glue.h"
/* * Simple power of two buddy-like generic allocator. * Provides naturally aligned memory chunks. * * This simple code is not intended to be fast, but to * provide power of 2 aligned memory allocations. * Since the SCRIPTS processor only supplies 8 bit arithmetic, * this allocator allows simple and fast address calculations * from the SCRIPTS code. In addition, cache line alignment * is guaranteed for power of 2 cache line size. * * This allocator has been developed for the Linux sym53c8xx * driver, since this O/S does not provide naturally aligned * allocations. * It has the advantage of allowing the driver to use private * pages of memory that will be useful if we ever need to deal * with IO MMUs for PCI.
*/ staticvoid *___sym_malloc(m_pool_p mp, int size)
{ int i = 0; int s = (1 << SYM_MEM_SHIFT); int j; void *a;
m_link_p h = mp->h;
if (size > SYM_MEM_CLUSTER_SIZE) return NULL;
while (size > s) {
s <<= 1;
++i;
}
j = i; while (!h[j].next) { if (s == SYM_MEM_CLUSTER_SIZE) {
h[j].next = (m_link_p) M_GET_MEM_CLUSTER(); if (h[j].next)
h[j].next->next = NULL; break;
}
++j;
s <<= 1;
}
a = h[j].next; if (a) {
h[j].next = h[j].next->next; while (j > i) {
j -= 1;
s >>= 1;
h[j].next = (m_link_p) (a+s);
h[j].next->next = NULL;
}
} #ifdef DEBUG
printf("___sym_malloc(%d) = %p\n", size, (void *) a); #endif return a;
}
/* * Counter-part of the generic allocator.
*/ staticvoid ___sym_mfree(m_pool_p mp, void *ptr, int size)
{ int i = 0; int s = (1 << SYM_MEM_SHIFT);
m_link_p q; unsignedlong a, b;
m_link_p h = mp->h;
while (1) { if (s == SYM_MEM_CLUSTER_SIZE) { #ifdef SYM_MEM_FREE_UNUSED
M_FREE_MEM_CLUSTER((void *)a); #else
((m_link_p) a)->next = h[i].next;
h[i].next = (m_link_p) a; #endif break;
}
b = a ^ s;
q = &h[i]; while (q->next && q->next != (m_link_p) b) {
q = q->next;
} if (!q->next) {
((m_link_p) a)->next = h[i].next;
h[i].next = (m_link_p) a; break;
}
q->next = q->next->next;
a = a & b;
s <<= 1;
++i;
}
}
/* * Verbose and zeroing allocator that wrapps to the generic allocator.
*/ staticvoid *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
{ void *p;
if (p)
memset(p, 0, size); elseif (uflags & SYM_MEM_WARN)
printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size); return p;
} #define __sym_calloc(mp, s, n) __sym_calloc2(mp, s, n, SYM_MEM_WARN)
/* * Its counter-part.
*/ staticvoid __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
{ if (DEBUG_FLAGS & DEBUG_ALLOC)
printf ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
___sym_mfree(mp, ptr, size);
}
/* * Default memory pool we donnot need to involve in DMA. * * With DMA abstraction, we use functions (methods), to * distinguish between non DMAable memory and DMAable memory.
*/ staticvoid *___mp0_get_mem_cluster(m_pool_p mp)
{ void *m = sym_get_mem_cluster(); if (m)
++mp->nump; return m;
}
/* * Methods that maintains DMAable pools according to user allocations. * New pools are created on the fly when a new pool id is provided. * They are deleted on the fly when they get emptied.
*/ /* Get a memory cluster that matches the DMA constraints of a given pool */ staticvoid * ___get_dma_mem_cluster(m_pool_p mp)
{
m_vtob_p vbp; void *vaddr;
vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB"); if (!vbp) goto out_err;
vaddr = sym_m_get_dma_mem_cluster(mp, vbp); if (vaddr) { int hc = VTOB_HASH_CODE(vaddr);
vbp->next = mp->vtob[hc];
mp->vtob[hc] = vbp;
++mp->nump;
} return vaddr;
out_err: return NULL;
}
#ifdef SYM_MEM_FREE_UNUSED /* Free a memory cluster and associated resources for DMA */ staticvoid ___free_dma_mem_cluster(m_pool_p mp, void *m)
{
m_vtob_p *vbpp, vbp; int hc = VTOB_HASH_CODE(m);
/* Fetch the memory pool for a given pool id (i.e. DMA constraints) */ staticinline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
{
m_pool_p mp; for (mp = mp0.next;
mp && !sym_m_pool_match(mp->dev_dmat, dev_dmat);
mp = mp->next); return mp;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.