root/arch/m68k/emu/nfblock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfhd_read_write
  2. nfhd_get_capacity
  3. nfhd_make_request
  4. nfhd_getgeo
  5. nfhd_init_one
  6. nfhd_init
  7. nfhd_exit

   1 /*
   2  * ARAnyM block device driver
   3  *
   4  * This file is subject to the terms and conditions of the GNU General Public
   5  * License.  See the file COPYING in the main directory of this archive
   6  * for more details.
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/moduleparam.h>
  11 #include <linux/init.h>
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/errno.h>
  15 #include <linux/types.h>
  16 #include <linux/genhd.h>
  17 #include <linux/blkdev.h>
  18 #include <linux/hdreg.h>
  19 #include <linux/slab.h>
  20 
  21 #include <asm/natfeat.h>
  22 
  23 static long nfhd_id;
  24 
  25 enum {
  26         /* emulation entry points */
  27         NFHD_READ_WRITE = 10,
  28         NFHD_GET_CAPACITY = 14,
  29 
  30         /* skip ACSI devices */
  31         NFHD_DEV_OFFSET = 8,
  32 };
  33 
  34 static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno,
  35                                   u32 count, u32 buf)
  36 {
  37         return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno,
  38                        count, buf);
  39 }
  40 
  41 static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks,
  42                                     u32 *blocksize)
  43 {
  44         return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor,
  45                        virt_to_phys(blocks), virt_to_phys(blocksize));
  46 }
  47 
  48 static LIST_HEAD(nfhd_list);
  49 
  50 static int major_num;
  51 module_param(major_num, int, 0);
  52 
  53 struct nfhd_device {
  54         struct list_head list;
  55         int id;
  56         u32 blocks, bsize;
  57         int bshift;
  58         struct request_queue *queue;
  59         struct gendisk *disk;
  60 };
  61 
  62 static blk_qc_t nfhd_make_request(struct request_queue *queue, struct bio *bio)
  63 {
  64         struct nfhd_device *dev = queue->queuedata;
  65         struct bio_vec bvec;
  66         struct bvec_iter iter;
  67         int dir, len, shift;
  68         sector_t sec = bio->bi_iter.bi_sector;
  69 
  70         dir = bio_data_dir(bio);
  71         shift = dev->bshift;
  72         bio_for_each_segment(bvec, bio, iter) {
  73                 len = bvec.bv_len;
  74                 len >>= 9;
  75                 nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
  76                                 page_to_phys(bvec.bv_page) + bvec.bv_offset);
  77                 sec += len;
  78         }
  79         bio_endio(bio);
  80         return BLK_QC_T_NONE;
  81 }
  82 
  83 static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
  84 {
  85         struct nfhd_device *dev = bdev->bd_disk->private_data;
  86 
  87         geo->cylinders = dev->blocks >> (6 - dev->bshift);
  88         geo->heads = 4;
  89         geo->sectors = 16;
  90 
  91         return 0;
  92 }
  93 
  94 static const struct block_device_operations nfhd_ops = {
  95         .owner  = THIS_MODULE,
  96         .getgeo = nfhd_getgeo,
  97 };
  98 
  99 static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
 100 {
 101         struct nfhd_device *dev;
 102         int dev_id = id - NFHD_DEV_OFFSET;
 103 
 104         pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id,
 105                 blocks, bsize);
 106 
 107         if (bsize < 512 || (bsize & (bsize - 1))) {
 108                 pr_warn("nfhd%u: invalid block size\n", dev_id);
 109                 return -EINVAL;
 110         }
 111 
 112         dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL);
 113         if (!dev)
 114                 goto out;
 115 
 116         dev->id = id;
 117         dev->blocks = blocks;
 118         dev->bsize = bsize;
 119         dev->bshift = ffs(bsize) - 10;
 120 
 121         dev->queue = blk_alloc_queue(GFP_KERNEL);
 122         if (dev->queue == NULL)
 123                 goto free_dev;
 124 
 125         dev->queue->queuedata = dev;
 126         blk_queue_make_request(dev->queue, nfhd_make_request);
 127         blk_queue_logical_block_size(dev->queue, bsize);
 128 
 129         dev->disk = alloc_disk(16);
 130         if (!dev->disk)
 131                 goto free_queue;
 132 
 133         dev->disk->major = major_num;
 134         dev->disk->first_minor = dev_id * 16;
 135         dev->disk->fops = &nfhd_ops;
 136         dev->disk->private_data = dev;
 137         sprintf(dev->disk->disk_name, "nfhd%u", dev_id);
 138         set_capacity(dev->disk, (sector_t)blocks * (bsize / 512));
 139         dev->disk->queue = dev->queue;
 140 
 141         add_disk(dev->disk);
 142 
 143         list_add_tail(&dev->list, &nfhd_list);
 144 
 145         return 0;
 146 
 147 free_queue:
 148         blk_cleanup_queue(dev->queue);
 149 free_dev:
 150         kfree(dev);
 151 out:
 152         return -ENOMEM;
 153 }
 154 
 155 static int __init nfhd_init(void)
 156 {
 157         u32 blocks, bsize;
 158         int ret;
 159         int i;
 160 
 161         nfhd_id = nf_get_id("XHDI");
 162         if (!nfhd_id)
 163                 return -ENODEV;
 164 
 165         ret = register_blkdev(major_num, "nfhd");
 166         if (ret < 0) {
 167                 pr_warn("nfhd: unable to get major number\n");
 168                 return ret;
 169         }
 170 
 171         if (!major_num)
 172                 major_num = ret;
 173 
 174         for (i = NFHD_DEV_OFFSET; i < 24; i++) {
 175                 if (nfhd_get_capacity(i, 0, &blocks, &bsize))
 176                         continue;
 177                 nfhd_init_one(i, blocks, bsize);
 178         }
 179 
 180         return 0;
 181 }
 182 
 183 static void __exit nfhd_exit(void)
 184 {
 185         struct nfhd_device *dev, *next;
 186 
 187         list_for_each_entry_safe(dev, next, &nfhd_list, list) {
 188                 list_del(&dev->list);
 189                 del_gendisk(dev->disk);
 190                 put_disk(dev->disk);
 191                 blk_cleanup_queue(dev->queue);
 192                 kfree(dev);
 193         }
 194         unregister_blkdev(major_num, "nfhd");
 195 }
 196 
 197 module_init(nfhd_init);
 198 module_exit(nfhd_exit);
 199 
 200 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */