1/* 2 * Functions for ST-RAM allocations 3 * 4 * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 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#include <linux/ioport.h> 25 26#include <asm/setup.h> 27#include <asm/machdep.h> 28#include <asm/page.h> 29#include <asm/pgtable.h> 30#include <asm/atarihw.h> 31#include <asm/atari_stram.h> 32#include <asm/io.h> 33 34 35/* 36 * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of 37 * configurable size, set aside on ST-RAM init. 38 * As long as this pool is not exhausted, allocation of real ST-RAM can be 39 * guaranteed. 40 */ 41 42/* set if kernel is in ST-RAM */ 43static int kernel_in_stram; 44 45static struct resource stram_pool = { 46 .name = "ST-RAM Pool" 47}; 48 49static unsigned long pool_size = 1024*1024; 50 51static unsigned long stram_virt_offset; 52 53static int __init atari_stram_setup(char *arg) 54{ 55 if (!MACH_IS_ATARI) 56 return 0; 57 58 pool_size = memparse(arg, NULL); 59 return 0; 60} 61 62early_param("stram_pool", atari_stram_setup); 63 64 65/* 66 * This init function is called very early by atari/config.c 67 * It initializes some internal variables needed for stram_alloc() 68 */ 69void __init atari_stram_init(void) 70{ 71 int i; 72 73 /* 74 * determine whether kernel code resides in ST-RAM 75 * (then ST-RAM is the first memory block at virtual 0x0) 76 */ 77 kernel_in_stram = (m68k_memory[0].addr == 0); 78 79 for (i = 0; i < m68k_num_memory; ++i) { 80 if (m68k_memory[i].addr == 0) { 81 return; 82 } 83 } 84 85 /* Should never come here! (There is always ST-Ram!) */ 86 panic("atari_stram_init: no ST-RAM found!"); 87} 88 89 90/* 91 * This function is called from setup_arch() to reserve the pages needed for 92 * ST-RAM management, if the kernel resides in ST-RAM. 93 */ 94void __init atari_stram_reserve_pages(void *start_mem) 95{ 96 if (kernel_in_stram) { 97 pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n"); 98 stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size); 99 stram_pool.end = stram_pool.start + pool_size - 1; 100 request_resource(&iomem_resource, &stram_pool); 101 stram_virt_offset = 0; 102 pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n", 103 pool_size, &stram_pool); 104 pr_debug("atari_stram pool: stram_virt_offset = %lx\n", 105 stram_virt_offset); 106 } 107} 108 109 110/* 111 * This function is called as arch initcall to reserve the pages needed for 112 * ST-RAM management, if the kernel does not reside in ST-RAM. 113 */ 114int __init atari_stram_map_pages(void) 115{ 116 if (!kernel_in_stram) { 117 /* 118 * Skip page 0, as the fhe first 2 KiB are supervisor-only! 119 */ 120 pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n"); 121 stram_pool.start = PAGE_SIZE; 122 stram_pool.end = stram_pool.start + pool_size - 1; 123 request_resource(&iomem_resource, &stram_pool); 124 stram_virt_offset = (unsigned long) ioremap(stram_pool.start, 125 resource_size(&stram_pool)) - stram_pool.start; 126 pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n", 127 pool_size, &stram_pool); 128 pr_debug("atari_stram pool: stram_virt_offset = %lx\n", 129 stram_virt_offset); 130 } 131 return 0; 132} 133arch_initcall(atari_stram_map_pages); 134 135 136void *atari_stram_to_virt(unsigned long phys) 137{ 138 return (void *)(phys + stram_virt_offset); 139} 140EXPORT_SYMBOL(atari_stram_to_virt); 141 142 143unsigned long atari_stram_to_phys(void *virt) 144{ 145 return (unsigned long)(virt - stram_virt_offset); 146} 147EXPORT_SYMBOL(atari_stram_to_phys); 148 149 150void *atari_stram_alloc(unsigned long size, const char *owner) 151{ 152 struct resource *res; 153 int error; 154 155 pr_debug("atari_stram_alloc: allocate %lu bytes\n", size); 156 157 /* round up */ 158 size = PAGE_ALIGN(size); 159 160 res = kzalloc(sizeof(struct resource), GFP_KERNEL); 161 if (!res) 162 return NULL; 163 164 res->name = owner; 165 error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX, 166 PAGE_SIZE, NULL, NULL); 167 if (error < 0) { 168 pr_err("atari_stram_alloc: allocate_resource() failed %d!\n", 169 error); 170 kfree(res); 171 return NULL; 172 } 173 174 pr_debug("atari_stram_alloc: returning %pR\n", res); 175 return atari_stram_to_virt(res->start); 176} 177EXPORT_SYMBOL(atari_stram_alloc); 178 179 180void atari_stram_free(void *addr) 181{ 182 unsigned long start = atari_stram_to_phys(addr); 183 struct resource *res; 184 unsigned long size; 185 186 res = lookup_resource(&stram_pool, start); 187 if (!res) { 188 pr_err("atari_stram_free: trying to free nonexistent region " 189 "at %p\n", addr); 190 return; 191 } 192 193 size = resource_size(res); 194 pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr); 195 release_resource(res); 196 kfree(res); 197} 198EXPORT_SYMBOL(atari_stram_free); 199