Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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