~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/m68k/emu/nfblock.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php