Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.33-rc4 410 lines 9.1 kB view raw
1/* 2** z2ram - Amiga pseudo-driver to access 16bit-RAM in ZorroII space 3** as a block device, to be used as a RAM disk or swap space 4** 5** Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) 6** 7** ++Geert: support for zorro_unused_z2ram, better range checking 8** ++roman: translate accesses via an array 9** ++Milan: support for ChipRAM usage 10** ++yambo: converted to 2.0 kernel 11** ++yambo: modularized and support added for 3 minor devices including: 12** MAJOR MINOR DESCRIPTION 13** ----- ----- ---------------------------------------------- 14** 37 0 Use Zorro II and Chip ram 15** 37 1 Use only Zorro II ram 16** 37 2 Use only Chip ram 17** 37 4-7 Use memory list entry 1-4 (first is 0) 18** ++jskov: support for 1-4th memory list entry. 19** 20** Permission to use, copy, modify, and distribute this software and its 21** documentation for any purpose and without fee is hereby granted, provided 22** that the above copyright notice appear in all copies and that both that 23** copyright notice and this permission notice appear in supporting 24** documentation. This software is provided "as is" without express or 25** implied warranty. 26*/ 27 28#define DEVICE_NAME "Z2RAM" 29 30#include <linux/major.h> 31#include <linux/vmalloc.h> 32#include <linux/init.h> 33#include <linux/module.h> 34#include <linux/blkdev.h> 35#include <linux/bitops.h> 36 37#include <asm/setup.h> 38#include <asm/amigahw.h> 39#include <asm/pgtable.h> 40 41#include <linux/zorro.h> 42 43 44extern int m68k_realnum_memory; 45extern struct mem_info m68k_memory[NUM_MEMINFO]; 46 47#define Z2MINOR_COMBINED (0) 48#define Z2MINOR_Z2ONLY (1) 49#define Z2MINOR_CHIPONLY (2) 50#define Z2MINOR_MEMLIST1 (4) 51#define Z2MINOR_MEMLIST2 (5) 52#define Z2MINOR_MEMLIST3 (6) 53#define Z2MINOR_MEMLIST4 (7) 54#define Z2MINOR_COUNT (8) /* Move this down when adding a new minor */ 55 56#define Z2RAM_CHUNK1024 ( Z2RAM_CHUNKSIZE >> 10 ) 57 58static u_long *z2ram_map = NULL; 59static u_long z2ram_size = 0; 60static int z2_count = 0; 61static int chip_count = 0; 62static int list_count = 0; 63static int current_device = -1; 64 65static DEFINE_SPINLOCK(z2ram_lock); 66 67static struct gendisk *z2ram_gendisk; 68 69static void do_z2_request(struct request_queue *q) 70{ 71 struct request *req; 72 73 req = blk_fetch_request(q); 74 while (req) { 75 unsigned long start = blk_rq_pos(req) << 9; 76 unsigned long len = blk_rq_cur_bytes(req); 77 int err = 0; 78 79 if (start + len > z2ram_size) { 80 printk( KERN_ERR DEVICE_NAME ": bad access: block=%lu, count=%u\n", 81 blk_rq_pos(req), blk_rq_cur_sectors(req)); 82 err = -EIO; 83 goto done; 84 } 85 while (len) { 86 unsigned long addr = start & Z2RAM_CHUNKMASK; 87 unsigned long size = Z2RAM_CHUNKSIZE - addr; 88 if (len < size) 89 size = len; 90 addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ]; 91 if (rq_data_dir(req) == READ) 92 memcpy(req->buffer, (char *)addr, size); 93 else 94 memcpy((char *)addr, req->buffer, size); 95 start += size; 96 len -= size; 97 } 98 done: 99 if (!__blk_end_request_cur(req, err)) 100 req = blk_fetch_request(q); 101 } 102} 103 104static void 105get_z2ram( void ) 106{ 107 int i; 108 109 for ( i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++ ) 110 { 111 if ( test_bit( i, zorro_unused_z2ram ) ) 112 { 113 z2_count++; 114 z2ram_map[ z2ram_size++ ] = 115 ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT ); 116 clear_bit( i, zorro_unused_z2ram ); 117 } 118 } 119 120 return; 121} 122 123static void 124get_chipram( void ) 125{ 126 127 while ( amiga_chip_avail() > ( Z2RAM_CHUNKSIZE * 4 ) ) 128 { 129 chip_count++; 130 z2ram_map[ z2ram_size ] = 131 (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE, "z2ram" ); 132 133 if ( z2ram_map[ z2ram_size ] == 0 ) 134 { 135 break; 136 } 137 138 z2ram_size++; 139 } 140 141 return; 142} 143 144static int z2_open(struct block_device *bdev, fmode_t mode) 145{ 146 int device; 147 int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) * 148 sizeof( z2ram_map[0] ); 149 int max_chip_map = ( amiga_chip_size / Z2RAM_CHUNKSIZE ) * 150 sizeof( z2ram_map[0] ); 151 int rc = -ENOMEM; 152 153 device = MINOR(bdev->bd_dev); 154 155 if ( current_device != -1 && current_device != device ) 156 { 157 rc = -EBUSY; 158 goto err_out; 159 } 160 161 if ( current_device == -1 ) 162 { 163 z2_count = 0; 164 chip_count = 0; 165 list_count = 0; 166 z2ram_size = 0; 167 168 /* Use a specific list entry. */ 169 if (device >= Z2MINOR_MEMLIST1 && device <= Z2MINOR_MEMLIST4) { 170 int index = device - Z2MINOR_MEMLIST1 + 1; 171 unsigned long size, paddr, vaddr; 172 173 if (index >= m68k_realnum_memory) { 174 printk( KERN_ERR DEVICE_NAME 175 ": no such entry in z2ram_map\n" ); 176 goto err_out; 177 } 178 179 paddr = m68k_memory[index].addr; 180 size = m68k_memory[index].size & ~(Z2RAM_CHUNKSIZE-1); 181 182#ifdef __powerpc__ 183 /* FIXME: ioremap doesn't build correct memory tables. */ 184 { 185 vfree(vmalloc (size)); 186 } 187 188 vaddr = (unsigned long) __ioremap (paddr, size, 189 _PAGE_WRITETHRU); 190 191#else 192 vaddr = (unsigned long)z_remap_nocache_nonser(paddr, size); 193#endif 194 z2ram_map = 195 kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]), 196 GFP_KERNEL); 197 if ( z2ram_map == NULL ) 198 { 199 printk( KERN_ERR DEVICE_NAME 200 ": cannot get mem for z2ram_map\n" ); 201 goto err_out; 202 } 203 204 while (size) { 205 z2ram_map[ z2ram_size++ ] = vaddr; 206 size -= Z2RAM_CHUNKSIZE; 207 vaddr += Z2RAM_CHUNKSIZE; 208 list_count++; 209 } 210 211 if ( z2ram_size != 0 ) 212 printk( KERN_INFO DEVICE_NAME 213 ": using %iK List Entry %d Memory\n", 214 list_count * Z2RAM_CHUNK1024, index ); 215 } else 216 217 switch ( device ) 218 { 219 case Z2MINOR_COMBINED: 220 221 z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL ); 222 if ( z2ram_map == NULL ) 223 { 224 printk( KERN_ERR DEVICE_NAME 225 ": cannot get mem for z2ram_map\n" ); 226 goto err_out; 227 } 228 229 get_z2ram(); 230 get_chipram(); 231 232 if ( z2ram_size != 0 ) 233 printk( KERN_INFO DEVICE_NAME 234 ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n", 235 z2_count * Z2RAM_CHUNK1024, 236 chip_count * Z2RAM_CHUNK1024, 237 ( z2_count + chip_count ) * Z2RAM_CHUNK1024 ); 238 239 break; 240 241 case Z2MINOR_Z2ONLY: 242 z2ram_map = kmalloc( max_z2_map, GFP_KERNEL ); 243 if ( z2ram_map == NULL ) 244 { 245 printk( KERN_ERR DEVICE_NAME 246 ": cannot get mem for z2ram_map\n" ); 247 goto err_out; 248 } 249 250 get_z2ram(); 251 252 if ( z2ram_size != 0 ) 253 printk( KERN_INFO DEVICE_NAME 254 ": using %iK of Zorro II RAM\n", 255 z2_count * Z2RAM_CHUNK1024 ); 256 257 break; 258 259 case Z2MINOR_CHIPONLY: 260 z2ram_map = kmalloc( max_chip_map, GFP_KERNEL ); 261 if ( z2ram_map == NULL ) 262 { 263 printk( KERN_ERR DEVICE_NAME 264 ": cannot get mem for z2ram_map\n" ); 265 goto err_out; 266 } 267 268 get_chipram(); 269 270 if ( z2ram_size != 0 ) 271 printk( KERN_INFO DEVICE_NAME 272 ": using %iK Chip RAM\n", 273 chip_count * Z2RAM_CHUNK1024 ); 274 275 break; 276 277 default: 278 rc = -ENODEV; 279 goto err_out; 280 281 break; 282 } 283 284 if ( z2ram_size == 0 ) 285 { 286 printk( KERN_NOTICE DEVICE_NAME 287 ": no unused ZII/Chip RAM found\n" ); 288 goto err_out_kfree; 289 } 290 291 current_device = device; 292 z2ram_size <<= Z2RAM_CHUNKSHIFT; 293 set_capacity(z2ram_gendisk, z2ram_size >> 9); 294 } 295 296 return 0; 297 298err_out_kfree: 299 kfree(z2ram_map); 300err_out: 301 return rc; 302} 303 304static int 305z2_release(struct gendisk *disk, fmode_t mode) 306{ 307 if ( current_device == -1 ) 308 return 0; 309 310 /* 311 * FIXME: unmap memory 312 */ 313 314 return 0; 315} 316 317static const struct block_device_operations z2_fops = 318{ 319 .owner = THIS_MODULE, 320 .open = z2_open, 321 .release = z2_release, 322}; 323 324static struct kobject *z2_find(dev_t dev, int *part, void *data) 325{ 326 *part = 0; 327 return get_disk(z2ram_gendisk); 328} 329 330static struct request_queue *z2_queue; 331 332static int __init 333z2_init(void) 334{ 335 int ret; 336 337 if (!MACH_IS_AMIGA) 338 return -ENODEV; 339 340 ret = -EBUSY; 341 if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME)) 342 goto err; 343 344 ret = -ENOMEM; 345 z2ram_gendisk = alloc_disk(1); 346 if (!z2ram_gendisk) 347 goto out_disk; 348 349 z2_queue = blk_init_queue(do_z2_request, &z2ram_lock); 350 if (!z2_queue) 351 goto out_queue; 352 353 z2ram_gendisk->major = Z2RAM_MAJOR; 354 z2ram_gendisk->first_minor = 0; 355 z2ram_gendisk->fops = &z2_fops; 356 sprintf(z2ram_gendisk->disk_name, "z2ram"); 357 358 z2ram_gendisk->queue = z2_queue; 359 add_disk(z2ram_gendisk); 360 blk_register_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT, THIS_MODULE, 361 z2_find, NULL, NULL); 362 363 return 0; 364 365out_queue: 366 put_disk(z2ram_gendisk); 367out_disk: 368 unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); 369err: 370 return ret; 371} 372 373static void __exit z2_exit(void) 374{ 375 int i, j; 376 blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT); 377 unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); 378 del_gendisk(z2ram_gendisk); 379 put_disk(z2ram_gendisk); 380 blk_cleanup_queue(z2_queue); 381 382 if ( current_device != -1 ) 383 { 384 i = 0; 385 386 for ( j = 0 ; j < z2_count; j++ ) 387 { 388 set_bit( i++, zorro_unused_z2ram ); 389 } 390 391 for ( j = 0 ; j < chip_count; j++ ) 392 { 393 if ( z2ram_map[ i ] ) 394 { 395 amiga_chip_free( (void *) z2ram_map[ i++ ] ); 396 } 397 } 398 399 if ( z2ram_map != NULL ) 400 { 401 kfree( z2ram_map ); 402 } 403 } 404 405 return; 406} 407 408module_init(z2_init); 409module_exit(z2_exit); 410MODULE_LICENSE("GPL");