2 ** linux/amiga/chipram.c
4 ** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
5 ** - 64-bit aligned allocations for full AGA compatibility
8 #include <linux/types.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <asm/amigahw.h>
18 long pad
; /* We suppose this makes this struct 64 bits long!! */
21 #define DP(ptr) ((struct chip_desc *)(ptr))
23 u_long amiga_chip_size
;
24 static unsigned long chipavail
;
26 unsigned long amiga_chip_avail( void )
29 printk("chip_avail : %ld bytes\n",chipavail
);
35 void __init
amiga_chip_init (void)
39 if (!AMIGAHW_PRESENT(CHIP_RAM
))
42 /* initialize start boundary */
48 dp
->length
= amiga_chip_size
- 2*sizeof(*dp
);
50 /* initialize end boundary */
51 dp
= DP(chipaddr
+ amiga_chip_size
) - 1;
55 dp
->length
= amiga_chip_size
- 2*sizeof(*dp
);
56 chipavail
= dp
->length
; /*MILAN*/
59 printk ("chipram end boundary is %p, length is %d\n", dp
,
64 void *amiga_chip_alloc (long size
)
71 size
= (size
+ 7) & ~7;
74 printk("chip_alloc: allocate %ld bytes\n", size
);
78 * get pointer to descriptor for last chunk by
79 * going backwards from end chunk
81 dp
= DP(chipaddr
+ amiga_chip_size
) - 1;
82 dp
= DP((unsigned long)dp
- dp
->length
) - 1;
84 while ((dp
->alloced
|| dp
->length
< size
)
86 dp
= DP ((unsigned long)dp
- dp
[-1].length
) - 2;
88 if (dp
->alloced
|| dp
->length
< size
) {
89 printk ("no chipmem available for %ld allocation\n", size
);
93 if (dp
->length
< (size
+ 2*sizeof(*dp
))) {
94 /* length too small to split; allocate the whole thing */
97 dp
= DP((unsigned long)ptr
+ dp
->length
);
100 printk ("chip_alloc: no split\n");
103 /* split the extent; use the end part */
104 long newsize
= dp
->length
- (2*sizeof(*dp
) + size
);
107 printk ("chip_alloc: splitting %d to %ld\n", dp
->length
,
110 dp
->length
= newsize
;
111 dp
= DP((unsigned long)(dp
+1) + newsize
);
112 dp
->first
= dp
->last
= 0;
114 dp
->length
= newsize
;
116 dp
->first
= dp
->last
= 0;
119 ptr
= (void *)(dp
+1);
120 dp
= DP((unsigned long)ptr
+ size
);
126 printk ("chip_alloc: returning %p\n", ptr
);
129 if ((unsigned long)ptr
& 7)
130 panic("chip_alloc: alignment violation\n");
132 chipavail
-= size
+ (2*sizeof(*dp
)); /*MILAN*/
137 void amiga_chip_free (void *ptr
)
139 struct chip_desc
*sdp
= DP(ptr
) - 1, *dp2
;
140 struct chip_desc
*edp
= DP((unsigned long)ptr
+ sdp
->length
);
142 chipavail
+= sdp
->length
+ (2* sizeof(sdp
)); /*MILAN*/
144 printk("chip_free: free %ld bytes at %p\n",sdp
->length
,ptr
);
146 /* deallocate the chunk */
147 sdp
->alloced
= edp
->alloced
= 0;
149 /* check if we should merge with the previous chunk */
150 if (!sdp
->first
&& !sdp
[-1].alloced
) {
151 dp2
= DP((unsigned long)sdp
- sdp
[-1].length
) - 2;
152 dp2
->length
+= sdp
->length
+ 2*sizeof(*sdp
);
153 edp
->length
= dp2
->length
;
157 /* check if we should merge with the following chunk */
158 if (!edp
->last
&& !edp
[1].alloced
) {
159 dp2
= DP((unsigned long)edp
+ edp
[1].length
) + 2;
160 dp2
->length
+= edp
->length
+ 2*sizeof(*sdp
);
161 sdp
->length
= dp2
->length
;