1
2
3
4
5
6
7
8
9
10
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/kdev_t.h>
15#include <linux/major.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/vmalloc.h>
19#include <linux/pagemap.h>
20#include <linux/bootmem.h>
21#include <linux/mount.h>
22#include <linux/blkdev.h>
23#include <linux/module.h>
24
25#include <asm/setup.h>
26#include <asm/machdep.h>
27#include <asm/page.h>
28#include <asm/pgtable.h>
29#include <asm/atarihw.h>
30#include <asm/atari_stram.h>
31#include <asm/io.h>
32
33#undef DEBUG
34
35#ifdef DEBUG
36#define DPRINTK(fmt,args...) printk( fmt, ##args )
37#else
38#define DPRINTK(fmt,args...)
39#endif
40
41#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
42
43#define DO_PROC
44#include <linux/proc_fs.h>
45#include <linux/seq_file.h>
46#endif
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74static void *stram_start, *stram_end;
75
76
77
78static int mem_init_done;
79
80
81static int kernel_in_stram;
82
83typedef struct stram_block {
84 struct stram_block *next;
85 void *start;
86 unsigned long size;
87 unsigned flags;
88 const char *owner;
89} BLOCK;
90
91
92#define BLOCK_FREE 0x01
93#define BLOCK_KMALLOCED 0x02
94#define BLOCK_GFP 0x08
95
96
97static BLOCK *alloc_list;
98
99
100
101
102
103#define N_STATIC_BLOCKS 20
104static BLOCK static_blocks[N_STATIC_BLOCKS];
105
106
107
108static BLOCK *add_region( void *addr, unsigned long size );
109static BLOCK *find_region( void *addr );
110static int remove_region( BLOCK *block );
111
112
113
114
115
116
117
118
119
120
121
122
123void __init atari_stram_init(void)
124{
125 int i;
126
127
128 for( i = 0; i < N_STATIC_BLOCKS; ++i )
129 static_blocks[i].flags = BLOCK_FREE;
130
131
132
133 stram_start = phys_to_virt(0);
134 kernel_in_stram = (stram_start == 0);
135
136 for( i = 0; i < m68k_num_memory; ++i ) {
137 if (m68k_memory[i].addr == 0) {
138
139 stram_end = stram_start + m68k_memory[i].size;
140 return;
141 }
142 }
143
144 panic( "atari_stram_init: no ST-RAM found!" );
145}
146
147
148
149
150
151
152void __init atari_stram_reserve_pages(void *start_mem)
153{
154
155
156 if (!kernel_in_stram)
157 reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
158
159}
160
161void atari_stram_mem_init_hook (void)
162{
163 mem_init_done = 1;
164}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181void *atari_stram_alloc(long size, const char *owner)
182{
183 void *addr = NULL;
184 BLOCK *block;
185 int flags;
186
187 DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
188
189 if (!mem_init_done)
190 return alloc_bootmem_low(size);
191 else {
192
193 addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
194 flags = BLOCK_GFP;
195 DPRINTK( "atari_stram_alloc: after mem_init, "
196 "get_pages=%p\n", addr );
197 }
198
199 if (addr) {
200 if (!(block = add_region( addr, size ))) {
201
202 DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
203 "freeing again\n" );
204 free_pages((unsigned long)addr, get_order(size));
205 return( NULL );
206 }
207 block->owner = owner;
208 block->flags |= flags;
209 }
210 return( addr );
211}
212EXPORT_SYMBOL(atari_stram_alloc);
213
214void atari_stram_free( void *addr )
215
216{
217 BLOCK *block;
218
219 DPRINTK( "atari_stram_free(addr=%p)\n", addr );
220
221 if (!(block = find_region( addr ))) {
222 printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
223 "from %p\n", addr, __builtin_return_address(0) );
224 return;
225 }
226 DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
227 "flags=%02x\n", block, block->size, block->owner, block->flags );
228
229 if (!(block->flags & BLOCK_GFP))
230 goto fail;
231
232 DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
233 get_order(block->size));
234 free_pages((unsigned long)addr, get_order(block->size));
235 remove_region( block );
236 return;
237
238 fail:
239 printk( KERN_ERR "atari_stram_free: cannot free block at %p "
240 "(called from %p)\n", addr, __builtin_return_address(0) );
241}
242EXPORT_SYMBOL(atari_stram_free);
243
244
245
246
247
248
249
250
251static BLOCK *add_region( void *addr, unsigned long size )
252{
253 BLOCK **p, *n = NULL;
254 int i;
255
256 for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
257 if (static_blocks[i].flags & BLOCK_FREE) {
258 n = &static_blocks[i];
259 n->flags = 0;
260 break;
261 }
262 }
263 if (!n && mem_init_done) {
264
265
266 n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
267 if (n)
268 n->flags = BLOCK_KMALLOCED;
269 }
270 if (!n) {
271 printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
272 return( NULL );
273 }
274 n->start = addr;
275 n->size = size;
276
277 for( p = &alloc_list; *p; p = &((*p)->next) )
278 if ((*p)->start > addr) break;
279 n->next = *p;
280 *p = n;
281
282 return( n );
283}
284
285
286
287static BLOCK *find_region( void *addr )
288{
289 BLOCK *p;
290
291 for( p = alloc_list; p; p = p->next ) {
292 if (p->start == addr)
293 return( p );
294 if (p->start > addr)
295 break;
296 }
297 return( NULL );
298}
299
300
301
302static int remove_region( BLOCK *block )
303{
304 BLOCK **p;
305
306 for( p = &alloc_list; *p; p = &((*p)->next) )
307 if (*p == block) break;
308 if (!*p)
309 return( 0 );
310
311 *p = block->next;
312 if (block->flags & BLOCK_KMALLOCED)
313 kfree( block );
314 else
315 block->flags |= BLOCK_FREE;
316 return( 1 );
317}
318
319
320
321
322
323
324
325#ifdef DO_PROC
326
327#define PRINT_PROC(fmt,args...) seq_printf( m, fmt, ##args )
328
329static int stram_proc_show(struct seq_file *m, void *v)
330{
331 BLOCK *p;
332
333 PRINT_PROC("Total ST-RAM: %8u kB\n",
334 (stram_end - stram_start) >> 10);
335 PRINT_PROC( "Allocated regions:\n" );
336 for( p = alloc_list; p; p = p->next ) {
337 PRINT_PROC("0x%08lx-0x%08lx: %s (",
338 virt_to_phys(p->start),
339 virt_to_phys(p->start+p->size-1),
340 p->owner);
341 if (p->flags & BLOCK_GFP)
342 PRINT_PROC( "page-alloced)\n" );
343 else
344 PRINT_PROC( "??)\n" );
345 }
346
347 return 0;
348}
349
350static int stram_proc_open(struct inode *inode, struct file *file)
351{
352 return single_open(file, stram_proc_show, NULL);
353}
354
355static const struct file_operations stram_proc_fops = {
356 .open = stram_proc_open,
357 .read = seq_read,
358 .llseek = seq_lseek,
359 .release = single_release,
360};
361
362static int __init proc_stram_init(void)
363{
364 proc_create("stram", 0, NULL, &stram_proc_fops);
365 return 0;
366}
367module_init(proc_stram_init);
368#endif
369
370
371
372
373
374
375
376
377