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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [amiga/] [chipram.c] - Blame information for rev 1623

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
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)
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
  dp = DP(chipaddr);
38
  dp->first = 1;
39
 
40
  dp->alloced = 0;
41
  dp->length = chipsize - 2*sizeof(*dp);
42
 
43
  /* initialize end boundary */
44
  dp = DP(chipaddr + chipsize) - 1;
45
  dp->last = 1;
46
 
47
  dp->alloced = 0;
48
  dp->length = chipsize - 2*sizeof(*dp);
49
 
50
#ifdef DEBUG
51
  printk ("chipram end boundary is %p, length is %d\n", dp,
52
          dp->length);
53
#endif
54
}
55
 
56
void *amiga_chip_alloc (long size)
57
{
58
        /* last chunk */
59
        struct chip_desc *dp;
60
        void *ptr;
61
 
62
        /* round off */
63
        size = (size + 7) & ~7;
64
 
65
#ifdef DEBUG
66
        printk ("chip_alloc: allocate %ld bytes\n", size);
67
#endif
68
 
69
        /*
70
         * get pointer to descriptor for last chunk by
71
         * going backwards from end chunk
72
         */
73
        dp = DP(chipaddr + chipsize) - 1;
74
        dp = DP((unsigned long)dp - dp->length) - 1;
75
 
76
        while ((dp->alloced || dp->length < size)
77
               && !dp->first)
78
                dp = DP ((unsigned long)dp - dp[-1].length) - 2;
79
 
80
        if (dp->alloced || dp->length < size) {
81
                printk ("no chipmem available for %ld allocation\n", size);
82
                return NULL;
83
        }
84
 
85
        if (dp->length < (size + 2*sizeof(*dp))) {
86
                /* length too small to split; allocate the whole thing */
87
                dp->alloced = 1;
88
                ptr = (void *)(dp+1);
89
                dp = DP((unsigned long)ptr + dp->length);
90
                dp->alloced = 1;
91
#ifdef DEBUG
92
                printk ("chip_alloc: no split\n");
93
#endif
94
        } else {
95
                /* split the extent; use the end part */
96
                long newsize = dp->length - (2*sizeof(*dp) + size);
97
 
98
#ifdef DEBUG
99
                printk ("chip_alloc: splitting %d to %ld\n", dp->length,
100
                        newsize);
101
#endif
102
                dp->length = newsize;
103
                dp = DP((unsigned long)(dp+1) + newsize);
104
                dp->first = dp->last = 0;
105
                dp->alloced = 0;
106
                dp->length = newsize;
107
                dp++;
108
                dp->first = dp->last = 0;
109
                dp->alloced = 1;
110
                dp->length = size;
111
                ptr = (void *)(dp+1);
112
                dp = DP((unsigned long)ptr + size);
113
                dp->alloced = 1;
114
                dp->length = size;
115
        }
116
 
117
#ifdef DEBUG
118
        printk ("chip_alloc: returning %p\n", ptr);
119
#endif
120
 
121
        if ((unsigned long)ptr & 7)
122
                panic("chip_alloc: alignment violation\n");
123
 
124
        return ptr;
125
}
126
 
127
void amiga_chip_free (void *ptr)
128
{
129
        struct chip_desc *sdp = DP(ptr) - 1, *dp2;
130
        struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
131
 
132
        /* deallocate the chunk */
133
        sdp->alloced = edp->alloced = 0;
134
 
135
        /* check if we should merge with the previous chunk */
136
        if (!sdp->first && !sdp[-1].alloced) {
137
                dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
138
                dp2->length += sdp->length + 2*sizeof(*sdp);
139
                edp->length = dp2->length;
140
                sdp = dp2;
141
        }
142
 
143
        /* check if we should merge with the following chunk */
144
        if (!edp->last && !edp[1].alloced) {
145
                dp2 = DP((unsigned long)edp + edp[1].length) + 2;
146
                dp2->length += edp->length + 2*sizeof(*sdp);
147
                sdp->length = dp2->length;
148
                edp = dp2;
149
        }
150
}

powered by: WebSVN 2.1.0

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