summaryrefslogtreecommitdiffstats
path: root/drivers/block/z2ram.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /drivers/block/z2ram.c
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'drivers/block/z2ram.c')
-rw-r--r--drivers/block/z2ram.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
new file mode 100644
index 000000000..0f556752d
--- /dev/null
+++ b/drivers/block/z2ram.c
@@ -0,0 +1,354 @@
+/*
+** z2ram - Amiga pseudo-driver to access 16bit-RAM in ZorroII space
+** as a block device, to be used as a RAM disk or swap space
+**
+** Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
+**
+** ++Geert: support for zorro_unused_z2ram, better range checking
+** ++roman: translate accesses via an array
+** ++Milan: support for ChipRAM usage
+** ++yambo: converted to 2.0 kernel
+** ++yambo: modularized and support added for 3 minor devices including:
+** MAJOR MINOR DESCRIPTION
+** ----- ----- ----------------------------------------------
+** 37 0 Use Zorro II and Chip ram
+** 37 1 Use only Zorro II ram
+** 37 2 Use only Chip ram
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#define MAJOR_NR Z2RAM_MAJOR
+
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+
+#if defined(MODULE)
+#include <linux/module.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/bitops.h>
+#include <asm/amigahw.h>
+#include <linux/zorro.h>
+
+#define TRUE (1)
+#define FALSE (0)
+
+#define Z2MINOR_COMBINED (0)
+#define Z2MINOR_Z2ONLY (1)
+#define Z2MINOR_CHIPONLY (2)
+
+#define Z2RAM_CHUNK1024 ( Z2RAM_CHUNKSIZE >> 10 )
+
+static u_long *z2ram_map = NULL;
+static u_long z2ram_size = 0;
+static int z2_blocksizes[3] = { 1024, 1024, 1024 };
+static int z2_sizes[3] = { 0, 0, 0 };
+static int z2_count = 0;
+static int chip_count = 0;
+static int current_device = -1;
+
+static void
+do_z2_request( void )
+{
+ u_long start, len, addr, size;
+
+ while ( TRUE )
+ {
+ INIT_REQUEST;
+
+ start = CURRENT->sector << 9;
+ len = CURRENT->current_nr_sectors << 9;
+
+ if ( ( start + len ) > z2ram_size )
+ {
+ printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld\n",
+ CURRENT->sector,
+ CURRENT->current_nr_sectors);
+ end_request( FALSE );
+ continue;
+ }
+
+ if ( ( CURRENT->cmd != READ ) && ( CURRENT->cmd != WRITE ) )
+ {
+ printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd );
+ end_request( FALSE );
+ continue;
+ }
+
+ while ( len )
+ {
+ addr = start & Z2RAM_CHUNKMASK;
+ size = Z2RAM_CHUNKSIZE - addr;
+ if ( len < size )
+ size = len;
+
+ addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
+
+ if ( CURRENT->cmd == READ )
+ memcpy( CURRENT->buffer, (char *)addr, size );
+ else
+ memcpy( (char *)addr, CURRENT->buffer, size );
+
+ start += size;
+ len -= size;
+ }
+
+ end_request( TRUE );
+ }
+}
+
+static void
+get_z2ram( void )
+{
+ int i;
+
+ for ( i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++ )
+ {
+ if ( test_bit( i, zorro_unused_z2ram ) )
+ {
+ z2_count++;
+ z2ram_map[ z2ram_size++ ] =
+ ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT );
+ clear_bit( i, zorro_unused_z2ram );
+ }
+ }
+
+ return;
+}
+
+static void
+get_chipram( void )
+{
+
+ while ( amiga_chip_avail() > ( Z2RAM_CHUNKSIZE * 4 ) )
+ {
+ chip_count++;
+ z2ram_map[ z2ram_size ] =
+ (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE );
+
+ if ( z2ram_map[ z2ram_size ] == 0 )
+ {
+ break;
+ }
+
+ z2ram_size++;
+ }
+
+ return;
+}
+
+static int
+z2_open( struct inode *inode, struct file *filp )
+{
+ int device;
+ int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) *
+ sizeof( z2ram_map[0] );
+ int max_chip_map = ( amiga_chip_size / Z2RAM_CHUNKSIZE ) *
+ sizeof( z2ram_map[0] );
+
+ device = DEVICE_NR( inode->i_rdev );
+
+ if ( current_device != -1 && current_device != device )
+ {
+ return -EBUSY;
+ }
+
+ if ( current_device == -1 )
+ {
+ z2_count = 0;
+ chip_count = 0;
+ z2ram_size = 0;
+
+ switch ( device )
+ {
+ case Z2MINOR_COMBINED:
+
+ z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL );
+ if ( z2ram_map == NULL )
+ {
+ printk( KERN_ERR DEVICE_NAME
+ ": cannot get mem for z2ram_map\n" );
+ return -ENOMEM;
+ }
+
+ get_z2ram();
+ get_chipram();
+
+ if ( z2ram_size != 0 )
+ printk( KERN_INFO DEVICE_NAME
+ ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n",
+ z2_count * Z2RAM_CHUNK1024,
+ chip_count * Z2RAM_CHUNK1024,
+ ( z2_count + chip_count ) * Z2RAM_CHUNK1024 );
+
+ break;
+
+ case Z2MINOR_Z2ONLY:
+ z2ram_map = kmalloc( max_z2_map, GFP_KERNEL );
+ if ( z2ram_map == NULL )
+ {
+ printk( KERN_ERR DEVICE_NAME
+ ": cannot get mem for z2ram_map\n" );
+ return -ENOMEM;
+ }
+
+ get_z2ram();
+
+ if ( z2ram_size != 0 )
+ printk( KERN_INFO DEVICE_NAME
+ ": using %iK of Zorro II RAM\n",
+ z2_count * Z2RAM_CHUNK1024 );
+
+ break;
+
+ case Z2MINOR_CHIPONLY:
+ z2ram_map = kmalloc( max_chip_map, GFP_KERNEL );
+ if ( z2ram_map == NULL )
+ {
+ printk( KERN_ERR DEVICE_NAME
+ ": cannot get mem for z2ram_map\n" );
+ return -ENOMEM;
+ }
+
+ get_chipram();
+
+ if ( z2ram_size != 0 )
+ printk( KERN_INFO DEVICE_NAME
+ ": using %iK Chip RAM\n",
+ chip_count * Z2RAM_CHUNK1024 );
+
+ break;
+
+ default:
+ return -ENODEV;
+ }
+
+ if ( z2ram_size == 0 )
+ {
+ kfree( z2ram_map );
+ printk( KERN_NOTICE DEVICE_NAME
+ ": no unused ZII/Chip RAM found\n" );
+ return -ENOMEM;
+ }
+
+ current_device = device;
+ z2ram_size <<= Z2RAM_CHUNKSHIFT;
+ z2_sizes[ device ] = z2ram_size >> 10;
+ blk_size[ MAJOR_NR ] = z2_sizes;
+ }
+
+#if defined(MODULE)
+ MOD_INC_USE_COUNT;
+#endif
+
+ return 0;
+}
+
+static void
+z2_release( struct inode *inode, struct file *filp )
+{
+
+ if ( current_device == -1 )
+ return;
+
+ sync_dev( inode->i_rdev );
+
+#if defined(MODULE)
+ MOD_DEC_USE_COUNT;
+#endif
+
+ return;
+}
+
+static struct file_operations z2_fops =
+{
+ NULL, /* lseek - default */
+ block_read, /* read - general block-dev read */
+ block_write, /* write - general block-dev write */
+ NULL, /* readdir - bad */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ z2_open, /* open */
+ z2_release, /* release */
+ block_fsync /* fsync */
+};
+
+int
+z2_init( void )
+{
+
+ if ( !MACH_IS_AMIGA )
+ return -ENXIO;
+
+ if ( register_blkdev( MAJOR_NR, DEVICE_NAME, &z2_fops ) )
+ {
+ printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
+ MAJOR_NR );
+ return -EBUSY;
+ }
+
+ blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
+ blksize_size[ MAJOR_NR ] = z2_blocksizes;
+ blk_size[ MAJOR_NR ] = z2_sizes;
+
+ return 0;
+}
+
+#if defined(MODULE)
+int
+init_module( void )
+{
+ int error;
+
+ error = z2_init();
+ if ( error == 0 )
+ {
+ printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
+ }
+
+ return error;
+}
+
+void
+cleanup_module( void )
+{
+ int i, j;
+
+ if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 )
+ printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
+
+ if ( current_device != -1 )
+ {
+ i = 0;
+
+ for ( j = 0 ; j < z2_count; j++ )
+ {
+ set_bit( i++, zorro_unused_z2ram );
+ }
+
+ for ( j = 0 ; j < chip_count; j++ )
+ {
+ if ( z2ram_map[ i ] )
+ {
+ amiga_chip_free( (void *) z2ram_map[ i++ ] );
+ }
+ }
+
+ if ( z2ram_map != NULL )
+ {
+ kfree( z2ram_map );
+ }
+ }
+
+ return;
+}
+#endif