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