root/arch/m68k/amiga/chipram.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amiga_chip_init
  2. amiga_chip_alloc
  3. amiga_chip_free

   1 /*
   2 **  linux/amiga/chipram.c
   3 **
   4 **      Modified 03-May-94 by Geert Uytterhoeven
   5 **                           (Geert.Uytterhoeven@cs.kuleuven.ac.be)
   6 **          - 64-bit aligned allocations for full AGA compatibility
   7 */
   8 
   9 #include <linux/types.h>
  10 #include <linux/kernel.h>
  11 #include <asm/bootinfo.h>
  12 #include <asm/amigahw.h>
  13 
  14 struct chip_desc {
  15         unsigned first   :  1;
  16         unsigned last    :  1;
  17         unsigned alloced :  1;
  18         unsigned length  : 24;
  19         long pad;                                       /* We suppose this makes this struct 64 bits long!! */
  20 };
  21 
  22 #define DP(ptr) ((struct chip_desc *)(ptr))
  23 
  24 static unsigned long chipsize;
  25 
  26 void amiga_chip_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28   struct chip_desc *dp;
  29 
  30   if (!AMIGAHW_PRESENT(CHIP_RAM))
  31     return;
  32 
  33   chipsize = boot_info.bi_amiga.chip_size;
  34 
  35   /* initialize start boundary */
  36 
  37   custom.color[0] = 0xfff;
  38 
  39   dp = DP(chipaddr);
  40   dp->first = 1;
  41 
  42   custom.color[0] = 0x0f00;
  43 
  44   dp->alloced = 0;
  45   dp->length = chipsize - 2*sizeof(*dp);
  46 
  47   /* initialize end boundary */
  48   dp = DP(chipaddr + chipsize) - 1;
  49   dp->last = 1;
  50   
  51   custom.color[0] = 0x00f0;
  52 
  53   dp->alloced = 0;
  54   dp->length = chipsize - 2*sizeof(*dp);
  55 
  56   custom.color[0] = 0x000f;
  57 
  58 #ifdef DEBUG
  59   printk ("chipram end boundary is %p, length is %d\n", dp,
  60           dp->length);
  61 #endif
  62 }
  63 
  64 void *amiga_chip_alloc (long size)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         /* last chunk */
  67         struct chip_desc *dp;
  68         void *ptr;
  69 
  70         /* round off */
  71         size = (size + 7) & ~7;
  72 
  73 #ifdef DEBUG
  74         printk ("chip_alloc: allocate %ld bytes\n", size);
  75 #endif
  76 
  77         /*
  78          * get pointer to descriptor for last chunk by 
  79          * going backwards from end chunk
  80          */
  81         dp = DP(chipaddr + chipsize) - 1;
  82         dp = DP((unsigned long)dp - dp->length) - 1;
  83         
  84         while ((dp->alloced || dp->length < size)
  85                && !dp->first)
  86                 dp = DP ((unsigned long)dp - dp[-1].length) - 2;
  87 
  88         if (dp->alloced || dp->length < size) {
  89                 printk ("no chipmem available for %ld allocation\n", size);
  90                 return NULL;
  91         }
  92 
  93         if (dp->length < (size + 2*sizeof(*dp))) {
  94                 /* length too small to split; allocate the whole thing */
  95                 dp->alloced = 1;
  96                 ptr = (void *)(dp+1);
  97                 dp = DP((unsigned long)ptr + dp->length);
  98                 dp->alloced = 1;
  99 #ifdef DEBUG
 100                 printk ("chip_alloc: no split\n");
 101 #endif
 102         } else {
 103                 /* split the extent; use the end part */
 104                 long newsize = dp->length - (2*sizeof(*dp) + size);
 105 
 106 #ifdef DEBUG
 107                 printk ("chip_alloc: splitting %d to %ld\n", dp->length,
 108                         newsize);
 109 #endif
 110                 dp->length = newsize;
 111                 dp = DP((unsigned long)(dp+1) + newsize);
 112                 dp->first = dp->last = 0;
 113                 dp->alloced = 0;
 114                 dp->length = newsize;
 115                 dp++;
 116                 dp->first = dp->last = 0;
 117                 dp->alloced = 1;
 118                 dp->length = size;
 119                 ptr = (void *)(dp+1);
 120                 dp = DP((unsigned long)ptr + size);
 121                 dp->alloced = 1;
 122                 dp->length = size;
 123         }
 124 
 125 #ifdef DEBUG
 126         printk ("chip_alloc: returning %p\n", ptr);
 127 #endif
 128 
 129         if ((unsigned long)ptr & 7)
 130                 panic("chip_alloc: alignment violation\n");
 131 
 132         return ptr;
 133 }
 134 
 135 void amiga_chip_free (void *ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137         struct chip_desc *sdp = DP(ptr) - 1, *dp2;
 138         struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
 139 
 140         /* deallocate the chunk */
 141         sdp->alloced = edp->alloced = 0;
 142 
 143         /* check if we should merge with the previous chunk */
 144         if (!sdp->first && !sdp[-1].alloced) {
 145                 dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
 146                 dp2->length += sdp->length + 2*sizeof(*sdp);
 147                 edp->length = dp2->length;
 148                 sdp = dp2;
 149         }
 150 
 151         /* check if we should merge with the following chunk */
 152         if (!edp->last && !edp[1].alloced) {
 153                 dp2 = DP((unsigned long)edp + edp[1].length) + 2;
 154                 dp2->length += edp->length + 2*sizeof(*sdp);
 155                 sdp->length = dp2->length;
 156                 edp = dp2;
 157         }
 158 }

/* [previous][next][first][last][top][bottom][index][help] */