linux/drivers/block/z2ram.c
<<
>>
Prefs
   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/blk-mq.h>
  35#include <linux/bitops.h>
  36#include <linux/mutex.h>
  37#include <linux/slab.h>
  38#include <linux/pgtable.h>
  39
  40#include <asm/setup.h>
  41#include <asm/amigahw.h>
  42
  43#include <linux/zorro.h>
  44
  45#define Z2MINOR_COMBINED      (0)
  46#define Z2MINOR_Z2ONLY        (1)
  47#define Z2MINOR_CHIPONLY      (2)
  48#define Z2MINOR_MEMLIST1      (4)
  49#define Z2MINOR_MEMLIST2      (5)
  50#define Z2MINOR_MEMLIST3      (6)
  51#define Z2MINOR_MEMLIST4      (7)
  52#define Z2MINOR_COUNT         (8)       /* Move this down when adding a new minor */
  53
  54#define Z2RAM_CHUNK1024       ( Z2RAM_CHUNKSIZE >> 10 )
  55
  56static DEFINE_MUTEX(z2ram_mutex);
  57static u_long *z2ram_map = NULL;
  58static u_long z2ram_size = 0;
  59static int z2_count = 0;
  60static int chip_count = 0;
  61static int list_count = 0;
  62static int current_device = -1;
  63
  64static DEFINE_SPINLOCK(z2ram_lock);
  65
  66static struct gendisk *z2ram_gendisk[Z2MINOR_COUNT];
  67
  68static blk_status_t z2_queue_rq(struct blk_mq_hw_ctx *hctx,
  69                                const struct blk_mq_queue_data *bd)
  70{
  71        struct request *req = bd->rq;
  72        unsigned long start = blk_rq_pos(req) << 9;
  73        unsigned long len = blk_rq_cur_bytes(req);
  74
  75        blk_mq_start_request(req);
  76
  77        if (start + len > z2ram_size) {
  78                pr_err(DEVICE_NAME ": bad access: block=%llu, "
  79                       "count=%u\n",
  80                       (unsigned long long)blk_rq_pos(req),
  81                       blk_rq_cur_sectors(req));
  82                return BLK_STS_IOERR;
  83        }
  84
  85        spin_lock_irq(&z2ram_lock);
  86
  87        while (len) {
  88                unsigned long addr = start & Z2RAM_CHUNKMASK;
  89                unsigned long size = Z2RAM_CHUNKSIZE - addr;
  90                void *buffer = bio_data(req->bio);
  91
  92                if (len < size)
  93                        size = len;
  94                addr += z2ram_map[start >> Z2RAM_CHUNKSHIFT];
  95                if (rq_data_dir(req) == READ)
  96                        memcpy(buffer, (char *)addr, size);
  97                else
  98                        memcpy((char *)addr, buffer, size);
  99                start += size;
 100                len -= size;
 101        }
 102
 103        spin_unlock_irq(&z2ram_lock);
 104        blk_mq_end_request(req, BLK_STS_OK);
 105        return BLK_STS_OK;
 106}
 107
 108static void get_z2ram(void)
 109{
 110        int i;
 111
 112        for (i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++) {
 113                if (test_bit(i, zorro_unused_z2ram)) {
 114                        z2_count++;
 115                        z2ram_map[z2ram_size++] =
 116                            (unsigned long)ZTWO_VADDR(Z2RAM_START) +
 117                            (i << Z2RAM_CHUNKSHIFT);
 118                        clear_bit(i, zorro_unused_z2ram);
 119                }
 120        }
 121
 122        return;
 123}
 124
 125static void get_chipram(void)
 126{
 127
 128        while (amiga_chip_avail() > (Z2RAM_CHUNKSIZE * 4)) {
 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                        break;
 135                }
 136
 137                z2ram_size++;
 138        }
 139
 140        return;
 141}
 142
 143static int z2_open(struct block_device *bdev, fmode_t mode)
 144{
 145        int device;
 146        int max_z2_map = (Z2RAM_SIZE / Z2RAM_CHUNKSIZE) * sizeof(z2ram_map[0]);
 147        int max_chip_map = (amiga_chip_size / Z2RAM_CHUNKSIZE) *
 148            sizeof(z2ram_map[0]);
 149        int rc = -ENOMEM;
 150
 151        device = MINOR(bdev->bd_dev);
 152
 153        mutex_lock(&z2ram_mutex);
 154        if (current_device != -1 && current_device != device) {
 155                rc = -EBUSY;
 156                goto err_out;
 157        }
 158
 159        if (current_device == -1) {
 160                z2_count = 0;
 161                chip_count = 0;
 162                list_count = 0;
 163                z2ram_size = 0;
 164
 165                /* Use a specific list entry. */
 166                if (device >= Z2MINOR_MEMLIST1 && device <= Z2MINOR_MEMLIST4) {
 167                        int index = device - Z2MINOR_MEMLIST1 + 1;
 168                        unsigned long size, paddr, vaddr;
 169
 170                        if (index >= m68k_realnum_memory) {
 171                                printk(KERN_ERR DEVICE_NAME
 172                                       ": no such entry in z2ram_map\n");
 173                                goto err_out;
 174                        }
 175
 176                        paddr = m68k_memory[index].addr;
 177                        size = m68k_memory[index].size & ~(Z2RAM_CHUNKSIZE - 1);
 178
 179#ifdef __powerpc__
 180                        /* FIXME: ioremap doesn't build correct memory tables. */
 181                        {
 182                                vfree(vmalloc(size));
 183                        }
 184
 185                        vaddr = (unsigned long)ioremap_wt(paddr, size);
 186
 187#else
 188                        vaddr =
 189                            (unsigned long)z_remap_nocache_nonser(paddr, size);
 190#endif
 191                        z2ram_map =
 192                            kmalloc_array(size / Z2RAM_CHUNKSIZE,
 193                                          sizeof(z2ram_map[0]), GFP_KERNEL);
 194                        if (z2ram_map == NULL) {
 195                                printk(KERN_ERR DEVICE_NAME
 196                                       ": cannot get mem for z2ram_map\n");
 197                                goto err_out;
 198                        }
 199
 200                        while (size) {
 201                                z2ram_map[z2ram_size++] = vaddr;
 202                                size -= Z2RAM_CHUNKSIZE;
 203                                vaddr += Z2RAM_CHUNKSIZE;
 204                                list_count++;
 205                        }
 206
 207                        if (z2ram_size != 0)
 208                                printk(KERN_INFO DEVICE_NAME
 209                                       ": using %iK List Entry %d Memory\n",
 210                                       list_count * Z2RAM_CHUNK1024, index);
 211                } else
 212                        switch (device) {
 213                        case Z2MINOR_COMBINED:
 214
 215                                z2ram_map =
 216                                    kmalloc(max_z2_map + max_chip_map,
 217                                            GFP_KERNEL);
 218                                if (z2ram_map == NULL) {
 219                                        printk(KERN_ERR DEVICE_NAME
 220                                               ": cannot get mem for z2ram_map\n");
 221                                        goto err_out;
 222                                }
 223
 224                                get_z2ram();
 225                                get_chipram();
 226
 227                                if (z2ram_size != 0)
 228                                        printk(KERN_INFO DEVICE_NAME
 229                                               ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n",
 230                                               z2_count * Z2RAM_CHUNK1024,
 231                                               chip_count * Z2RAM_CHUNK1024,
 232                                               (z2_count +
 233                                                chip_count) * Z2RAM_CHUNK1024);
 234
 235                                break;
 236
 237                        case Z2MINOR_Z2ONLY:
 238                                z2ram_map = kmalloc(max_z2_map, GFP_KERNEL);
 239                                if (!z2ram_map)
 240                                        goto err_out;
 241
 242                                get_z2ram();
 243
 244                                if (z2ram_size != 0)
 245                                        printk(KERN_INFO DEVICE_NAME
 246                                               ": using %iK of Zorro II RAM\n",
 247                                               z2_count * Z2RAM_CHUNK1024);
 248
 249                                break;
 250
 251                        case Z2MINOR_CHIPONLY:
 252                                z2ram_map = kmalloc(max_chip_map, GFP_KERNEL);
 253                                if (!z2ram_map)
 254                                        goto err_out;
 255
 256                                get_chipram();
 257
 258                                if (z2ram_size != 0)
 259                                        printk(KERN_INFO DEVICE_NAME
 260                                               ": using %iK Chip RAM\n",
 261                                               chip_count * Z2RAM_CHUNK1024);
 262
 263                                break;
 264
 265                        default:
 266                                rc = -ENODEV;
 267                                goto err_out;
 268
 269                                break;
 270                        }
 271
 272                if (z2ram_size == 0) {
 273                        printk(KERN_NOTICE DEVICE_NAME
 274                               ": no unused ZII/Chip RAM found\n");
 275                        goto err_out_kfree;
 276                }
 277
 278                current_device = device;
 279                z2ram_size <<= Z2RAM_CHUNKSHIFT;
 280                set_capacity(z2ram_gendisk[device], z2ram_size >> 9);
 281        }
 282
 283        mutex_unlock(&z2ram_mutex);
 284        return 0;
 285
 286err_out_kfree:
 287        kfree(z2ram_map);
 288err_out:
 289        mutex_unlock(&z2ram_mutex);
 290        return rc;
 291}
 292
 293static void z2_release(struct gendisk *disk, fmode_t mode)
 294{
 295        mutex_lock(&z2ram_mutex);
 296        if (current_device == -1) {
 297                mutex_unlock(&z2ram_mutex);
 298                return;
 299        }
 300        mutex_unlock(&z2ram_mutex);
 301        /*
 302         * FIXME: unmap memory
 303         */
 304}
 305
 306static const struct block_device_operations z2_fops = {
 307        .owner = THIS_MODULE,
 308        .open = z2_open,
 309        .release = z2_release,
 310};
 311
 312static struct blk_mq_tag_set tag_set;
 313
 314static const struct blk_mq_ops z2_mq_ops = {
 315        .queue_rq = z2_queue_rq,
 316};
 317
 318static int z2ram_register_disk(int minor)
 319{
 320        struct gendisk *disk;
 321
 322        disk = blk_mq_alloc_disk(&tag_set, NULL);
 323        if (IS_ERR(disk))
 324                return PTR_ERR(disk);
 325
 326        disk->major = Z2RAM_MAJOR;
 327        disk->first_minor = minor;
 328        disk->minors = 1;
 329        disk->fops = &z2_fops;
 330        if (minor)
 331                sprintf(disk->disk_name, "z2ram%d", minor);
 332        else
 333                sprintf(disk->disk_name, "z2ram");
 334
 335        z2ram_gendisk[minor] = disk;
 336        add_disk(disk);
 337        return 0;
 338}
 339
 340static int __init z2_init(void)
 341{
 342        int ret, i;
 343
 344        if (!MACH_IS_AMIGA)
 345                return -ENODEV;
 346
 347        if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
 348                return -EBUSY;
 349
 350        tag_set.ops = &z2_mq_ops;
 351        tag_set.nr_hw_queues = 1;
 352        tag_set.nr_maps = 1;
 353        tag_set.queue_depth = 16;
 354        tag_set.numa_node = NUMA_NO_NODE;
 355        tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
 356        ret = blk_mq_alloc_tag_set(&tag_set);
 357        if (ret)
 358                goto out_unregister_blkdev;
 359
 360        for (i = 0; i < Z2MINOR_COUNT; i++) {
 361                ret = z2ram_register_disk(i);
 362                if (ret && i == 0)
 363                        goto out_free_tagset;
 364        }
 365
 366        return 0;
 367
 368out_free_tagset:
 369        blk_mq_free_tag_set(&tag_set);
 370out_unregister_blkdev:
 371        unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 372        return ret;
 373}
 374
 375static void __exit z2_exit(void)
 376{
 377        int i, j;
 378
 379        unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 380
 381        for (i = 0; i < Z2MINOR_COUNT; i++) {
 382                del_gendisk(z2ram_gendisk[i]);
 383                blk_cleanup_queue(z2ram_gendisk[i]->queue);
 384                put_disk(z2ram_gendisk[i]);
 385        }
 386        blk_mq_free_tag_set(&tag_set);
 387
 388        if (current_device != -1) {
 389                i = 0;
 390
 391                for (j = 0; j < z2_count; j++) {
 392                        set_bit(i++, zorro_unused_z2ram);
 393                }
 394
 395                for (j = 0; j < chip_count; j++) {
 396                        if (z2ram_map[i]) {
 397                                amiga_chip_free((void *)z2ram_map[i++]);
 398                        }
 399                }
 400
 401                if (z2ram_map != NULL) {
 402                        kfree(z2ram_map);
 403                }
 404        }
 405
 406        return;
 407}
 408
 409module_init(z2_init);
 410module_exit(z2_exit);
 411MODULE_LICENSE("GPL");
 412