OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [amiga/] [chipram.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
**  linux/amiga/chipram.c
**  linux/amiga/chipram.c
**
**
**      Modified 03-May-94 by Geert Uytterhoeven
**      Modified 03-May-94 by Geert Uytterhoeven
**                           (Geert.Uytterhoeven@cs.kuleuven.ac.be)
**                           (Geert.Uytterhoeven@cs.kuleuven.ac.be)
**          - 64-bit aligned allocations for full AGA compatibility
**          - 64-bit aligned allocations for full AGA compatibility
*/
*/
 
 
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo.h>
#include <asm/amigahw.h>
#include <asm/amigahw.h>
 
 
struct chip_desc {
struct chip_desc {
        unsigned first   :  1;
        unsigned first   :  1;
        unsigned last    :  1;
        unsigned last    :  1;
        unsigned alloced :  1;
        unsigned alloced :  1;
        unsigned length  : 24;
        unsigned length  : 24;
        long pad;                                       /* We suppose this makes this struct 64 bits long!! */
        long pad;                                       /* We suppose this makes this struct 64 bits long!! */
};
};
 
 
#define DP(ptr) ((struct chip_desc *)(ptr))
#define DP(ptr) ((struct chip_desc *)(ptr))
 
 
static unsigned long chipsize;
static unsigned long chipsize;
 
 
void amiga_chip_init (void)
void amiga_chip_init (void)
{
{
  struct chip_desc *dp;
  struct chip_desc *dp;
 
 
  if (!AMIGAHW_PRESENT(CHIP_RAM))
  if (!AMIGAHW_PRESENT(CHIP_RAM))
    return;
    return;
 
 
  chipsize = boot_info.bi_amiga.chip_size;
  chipsize = boot_info.bi_amiga.chip_size;
 
 
  /* initialize start boundary */
  /* initialize start boundary */
 
 
  dp = DP(chipaddr);
  dp = DP(chipaddr);
  dp->first = 1;
  dp->first = 1;
 
 
  dp->alloced = 0;
  dp->alloced = 0;
  dp->length = chipsize - 2*sizeof(*dp);
  dp->length = chipsize - 2*sizeof(*dp);
 
 
  /* initialize end boundary */
  /* initialize end boundary */
  dp = DP(chipaddr + chipsize) - 1;
  dp = DP(chipaddr + chipsize) - 1;
  dp->last = 1;
  dp->last = 1;
 
 
  dp->alloced = 0;
  dp->alloced = 0;
  dp->length = chipsize - 2*sizeof(*dp);
  dp->length = chipsize - 2*sizeof(*dp);
 
 
#ifdef DEBUG
#ifdef DEBUG
  printk ("chipram end boundary is %p, length is %d\n", dp,
  printk ("chipram end boundary is %p, length is %d\n", dp,
          dp->length);
          dp->length);
#endif
#endif
}
}
 
 
void *amiga_chip_alloc (long size)
void *amiga_chip_alloc (long size)
{
{
        /* last chunk */
        /* last chunk */
        struct chip_desc *dp;
        struct chip_desc *dp;
        void *ptr;
        void *ptr;
 
 
        /* round off */
        /* round off */
        size = (size + 7) & ~7;
        size = (size + 7) & ~7;
 
 
#ifdef DEBUG
#ifdef DEBUG
        printk ("chip_alloc: allocate %ld bytes\n", size);
        printk ("chip_alloc: allocate %ld bytes\n", size);
#endif
#endif
 
 
        /*
        /*
         * get pointer to descriptor for last chunk by
         * get pointer to descriptor for last chunk by
         * going backwards from end chunk
         * going backwards from end chunk
         */
         */
        dp = DP(chipaddr + chipsize) - 1;
        dp = DP(chipaddr + chipsize) - 1;
        dp = DP((unsigned long)dp - dp->length) - 1;
        dp = DP((unsigned long)dp - dp->length) - 1;
 
 
        while ((dp->alloced || dp->length < size)
        while ((dp->alloced || dp->length < size)
               && !dp->first)
               && !dp->first)
                dp = DP ((unsigned long)dp - dp[-1].length) - 2;
                dp = DP ((unsigned long)dp - dp[-1].length) - 2;
 
 
        if (dp->alloced || dp->length < size) {
        if (dp->alloced || dp->length < size) {
                printk ("no chipmem available for %ld allocation\n", size);
                printk ("no chipmem available for %ld allocation\n", size);
                return NULL;
                return NULL;
        }
        }
 
 
        if (dp->length < (size + 2*sizeof(*dp))) {
        if (dp->length < (size + 2*sizeof(*dp))) {
                /* length too small to split; allocate the whole thing */
                /* length too small to split; allocate the whole thing */
                dp->alloced = 1;
                dp->alloced = 1;
                ptr = (void *)(dp+1);
                ptr = (void *)(dp+1);
                dp = DP((unsigned long)ptr + dp->length);
                dp = DP((unsigned long)ptr + dp->length);
                dp->alloced = 1;
                dp->alloced = 1;
#ifdef DEBUG
#ifdef DEBUG
                printk ("chip_alloc: no split\n");
                printk ("chip_alloc: no split\n");
#endif
#endif
        } else {
        } else {
                /* split the extent; use the end part */
                /* split the extent; use the end part */
                long newsize = dp->length - (2*sizeof(*dp) + size);
                long newsize = dp->length - (2*sizeof(*dp) + size);
 
 
#ifdef DEBUG
#ifdef DEBUG
                printk ("chip_alloc: splitting %d to %ld\n", dp->length,
                printk ("chip_alloc: splitting %d to %ld\n", dp->length,
                        newsize);
                        newsize);
#endif
#endif
                dp->length = newsize;
                dp->length = newsize;
                dp = DP((unsigned long)(dp+1) + newsize);
                dp = DP((unsigned long)(dp+1) + newsize);
                dp->first = dp->last = 0;
                dp->first = dp->last = 0;
                dp->alloced = 0;
                dp->alloced = 0;
                dp->length = newsize;
                dp->length = newsize;
                dp++;
                dp++;
                dp->first = dp->last = 0;
                dp->first = dp->last = 0;
                dp->alloced = 1;
                dp->alloced = 1;
                dp->length = size;
                dp->length = size;
                ptr = (void *)(dp+1);
                ptr = (void *)(dp+1);
                dp = DP((unsigned long)ptr + size);
                dp = DP((unsigned long)ptr + size);
                dp->alloced = 1;
                dp->alloced = 1;
                dp->length = size;
                dp->length = size;
        }
        }
 
 
#ifdef DEBUG
#ifdef DEBUG
        printk ("chip_alloc: returning %p\n", ptr);
        printk ("chip_alloc: returning %p\n", ptr);
#endif
#endif
 
 
        if ((unsigned long)ptr & 7)
        if ((unsigned long)ptr & 7)
                panic("chip_alloc: alignment violation\n");
                panic("chip_alloc: alignment violation\n");
 
 
        return ptr;
        return ptr;
}
}
 
 
void amiga_chip_free (void *ptr)
void amiga_chip_free (void *ptr)
{
{
        struct chip_desc *sdp = DP(ptr) - 1, *dp2;
        struct chip_desc *sdp = DP(ptr) - 1, *dp2;
        struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
        struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
 
 
        /* deallocate the chunk */
        /* deallocate the chunk */
        sdp->alloced = edp->alloced = 0;
        sdp->alloced = edp->alloced = 0;
 
 
        /* check if we should merge with the previous chunk */
        /* check if we should merge with the previous chunk */
        if (!sdp->first && !sdp[-1].alloced) {
        if (!sdp->first && !sdp[-1].alloced) {
                dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
                dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
                dp2->length += sdp->length + 2*sizeof(*sdp);
                dp2->length += sdp->length + 2*sizeof(*sdp);
                edp->length = dp2->length;
                edp->length = dp2->length;
                sdp = dp2;
                sdp = dp2;
        }
        }
 
 
        /* check if we should merge with the following chunk */
        /* check if we should merge with the following chunk */
        if (!edp->last && !edp[1].alloced) {
        if (!edp->last && !edp[1].alloced) {
                dp2 = DP((unsigned long)edp + edp[1].length) + 2;
                dp2 = DP((unsigned long)edp + edp[1].length) + 2;
                dp2->length += edp->length + 2*sizeof(*sdp);
                dp2->length += edp->length + 2*sizeof(*sdp);
                sdp->length = dp2->length;
                sdp->length = dp2->length;
                edp = dp2;
                edp = dp2;
        }
        }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.