2 * ARAnyM block device driver
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
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/init.h>
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>
21 #include <asm/natfeat.h>
26 /* emulation entry points */
28 NFHD_GET_CAPACITY
= 14,
30 /* skip ACSI devices */
34 static inline s32
nfhd_read_write(u32 major
, u32 minor
, u32 rwflag
, u32 recno
,
37 return nf_call(nfhd_id
+ NFHD_READ_WRITE
, major
, minor
, rwflag
, recno
,
41 static inline s32
nfhd_get_capacity(u32 major
, u32 minor
, u32
*blocks
,
44 return nf_call(nfhd_id
+ NFHD_GET_CAPACITY
, major
, minor
, blocks
,
48 static LIST_HEAD(nfhd_list
);
51 module_param(major_num
, int, 0);
54 struct list_head list
;
58 struct request_queue
*queue
;
62 static void nfhd_make_request(struct request_queue
*queue
, struct bio
*bio
)
64 struct nfhd_device
*dev
= queue
->queuedata
;
66 int i
, dir
, len
, shift
;
67 sector_t sec
= bio
->bi_sector
;
69 dir
= bio_data_dir(bio
);
71 bio_for_each_segment(bvec
, bio
, i
) {
74 nfhd_read_write(dev
->id
, 0, dir
, sec
>> shift
, len
>> shift
,
81 static int nfhd_getgeo(struct block_device
*bdev
, struct hd_geometry
*geo
)
83 struct nfhd_device
*dev
= bdev
->bd_disk
->private_data
;
85 geo
->cylinders
= dev
->blocks
>> (6 - dev
->bshift
);
92 static const struct block_device_operations nfhd_ops
= {
94 .getgeo
= nfhd_getgeo
,
97 static int __init
nfhd_init_one(int id
, u32 blocks
, u32 bsize
)
99 struct nfhd_device
*dev
;
100 int dev_id
= id
- NFHD_DEV_OFFSET
;
102 pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id
,
105 if (bsize
< 512 || (bsize
& (bsize
- 1))) {
106 pr_warn("nfhd%u: invalid block size\n", dev_id
);
110 dev
= kmalloc(sizeof(struct nfhd_device
), GFP_KERNEL
);
115 dev
->blocks
= blocks
;
117 dev
->bshift
= ffs(bsize
) - 10;
119 dev
->queue
= blk_alloc_queue(GFP_KERNEL
);
120 if (dev
->queue
== NULL
)
123 dev
->queue
->queuedata
= dev
;
124 blk_queue_make_request(dev
->queue
, nfhd_make_request
);
125 blk_queue_logical_block_size(dev
->queue
, bsize
);
127 dev
->disk
= alloc_disk(16);
131 dev
->disk
->major
= major_num
;
132 dev
->disk
->first_minor
= dev_id
* 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 dev
->disk
->queue
= dev
->queue
;
141 list_add_tail(&dev
->list
, &nfhd_list
);
146 blk_cleanup_queue(dev
->queue
);
153 static int __init
nfhd_init(void)
158 nfhd_id
= nf_get_id("XHDI");
162 major_num
= register_blkdev(major_num
, "nfhd");
163 if (major_num
<= 0) {
164 pr_warn("nfhd: unable to get major number\n");
168 for (i
= NFHD_DEV_OFFSET
; i
< 24; i
++) {
169 if (nfhd_get_capacity(i
, 0, &blocks
, &bsize
))
171 nfhd_init_one(i
, blocks
, bsize
);
177 static void __exit
nfhd_exit(void)
179 struct nfhd_device
*dev
, *next
;
181 list_for_each_entry_safe(dev
, next
, &nfhd_list
, list
) {
182 list_del(&dev
->list
);
183 del_gendisk(dev
->disk
);
185 blk_cleanup_queue(dev
->queue
);
188 unregister_blkdev(major_num
, "nfhd");
191 module_init(nfhd_init
);
192 module_exit(nfhd_exit
);
194 MODULE_LICENSE("GPL");