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 == NULL) {
 240                                        printk(KERN_ERR DEVICE_NAME
 241                                               ": cannot get mem for z2ram_map\n");
 242                                        goto err_out;
 243                                }
 244
 245                                get_z2ram();
 246
 247                                if (z2ram_size != 0)
 248                                        printk(KERN_INFO DEVICE_NAME
 249                                               ": using %iK of Zorro II RAM\n",
 250                                               z2_count * Z2RAM_CHUNK1024);
 251
 252                                break;
 253
 254                        case Z2MINOR_CHIPONLY:
 255                                z2ram_map = kmalloc(max_chip_map, GFP_KERNEL);
 256                                if (z2ram_map == NULL) {
 257                                        printk(KERN_ERR DEVICE_NAME
 258                                               ": cannot get mem for z2ram_map\n");
 259                                        goto err_out;
 260                                }
 261
 262                                get_chipram();
 263
 264                                if (z2ram_size != 0)
 265                                        printk(KERN_INFO DEVICE_NAME
 266                                               ": using %iK Chip RAM\n",
 267                                               chip_count * Z2RAM_CHUNK1024);
 268
 269                                break;
 270
 271                        default:
 272                                rc = -ENODEV;
 273                                goto err_out;
 274
 275                                break;
 276                        }
 277
 278                if (z2ram_size == 0) {
 279                        printk(KERN_NOTICE DEVICE_NAME
 280                               ": no unused ZII/Chip RAM found\n");
 281                        goto err_out_kfree;
 282                }
 283
 284                current_device = device;
 285                z2ram_size <<= Z2RAM_CHUNKSHIFT;
 286                set_capacity(z2ram_gendisk[device], z2ram_size >> 9);
 287        }
 288
 289        mutex_unlock(&z2ram_mutex);
 290        return 0;
 291
 292err_out_kfree:
 293        kfree(z2ram_map);
 294err_out:
 295        mutex_unlock(&z2ram_mutex);
 296        return rc;
 297}
 298
 299static void z2_release(struct gendisk *disk, fmode_t mode)
 300{
 301        mutex_lock(&z2ram_mutex);
 302        if (current_device == -1) {
 303                mutex_unlock(&z2ram_mutex);
 304                return;
 305        }
 306        mutex_unlock(&z2ram_mutex);
 307        /*
 308         * FIXME: unmap memory
 309         */
 310}
 311
 312static const struct block_device_operations z2_fops = {
 313        .owner = THIS_MODULE,
 314        .open = z2_open,
 315        .release = z2_release,
 316};
 317
 318static struct blk_mq_tag_set tag_set;
 319
 320static const struct blk_mq_ops z2_mq_ops = {
 321        .queue_rq = z2_queue_rq,
 322};
 323
 324static int z2ram_register_disk(int minor)
 325{
 326        struct request_queue *q;
 327        struct gendisk *disk;
 328
 329        disk = alloc_disk(1);
 330        if (!disk)
 331                return -ENOMEM;
 332
 333        q = blk_mq_init_queue(&tag_set);
 334        if (IS_ERR(q)) {
 335                put_disk(disk);
 336                return PTR_ERR(q);
 337        }
 338
 339        disk->major = Z2RAM_MAJOR;
 340        disk->first_minor = minor;
 341        disk->fops = &z2_fops;
 342        if (minor)
 343                sprintf(disk->disk_name, "z2ram%d", minor);
 344        else
 345                sprintf(disk->disk_name, "z2ram");
 346        disk->queue = q;
 347
 348        z2ram_gendisk[minor] = disk;
 349        add_disk(disk);
 350        return 0;
 351}
 352
 353static int __init z2_init(void)
 354{
 355        int ret, i;
 356
 357        if (!MACH_IS_AMIGA)
 358                return -ENODEV;
 359
 360        if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
 361                return -EBUSY;
 362
 363        tag_set.ops = &z2_mq_ops;
 364        tag_set.nr_hw_queues = 1;
 365        tag_set.nr_maps = 1;
 366        tag_set.queue_depth = 16;
 367        tag_set.numa_node = NUMA_NO_NODE;
 368        tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
 369        ret = blk_mq_alloc_tag_set(&tag_set);
 370        if (ret)
 371                goto out_unregister_blkdev;
 372
 373        for (i = 0; i < Z2MINOR_COUNT; i++) {
 374                ret = z2ram_register_disk(i);
 375                if (ret && i == 0)
 376                        goto out_free_tagset;
 377        }
 378
 379        return 0;
 380
 381out_free_tagset:
 382        blk_mq_free_tag_set(&tag_set);
 383out_unregister_blkdev:
 384        unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 385        return ret;
 386}
 387
 388static void __exit z2_exit(void)
 389{
 390        int i, j;
 391
 392        unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 393
 394        for (i = 0; i < Z2MINOR_COUNT; i++) {
 395                del_gendisk(z2ram_gendisk[i]);
 396                blk_cleanup_queue(z2ram_gendisk[i]->queue);
 397                put_disk(z2ram_gendisk[i]);
 398        }
 399        blk_mq_free_tag_set(&tag_set);
 400
 401        if (current_device != -1) {
 402                i = 0;
 403
 404                for (j = 0; j < z2_count; j++) {
 405                        set_bit(i++, zorro_unused_z2ram);
 406                }
 407
 408                for (j = 0; j < chip_count; j++) {
 409                        if (z2ram_map[i]) {
 410                                amiga_chip_free((void *)z2ram_map[i++]);
 411                        }
 412                }
 413
 414                if (z2ram_map != NULL) {
 415                        kfree(z2ram_map);
 416                }
 417        }
 418
 419        return;
 420}
 421
 422module_init(z2_init);
 423module_exit(z2_exit);
 424MODULE_LICENSE("GPL");
 425