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