1 #include <linux/module.h>
2 #include <linux/moduleparam.h>
3 #include <linux/init.h>
5 #include <linux/kernel.h> /* printk() */
6 #include <linux/fs.h> /* everything... */
7 #include <linux/errno.h> /* error codes */
8 #include <linux/types.h> /* size_t */
9 #include <linux/vmalloc.h>
10 #include <linux/genhd.h>
11 #include <linux/blkdev.h>
12 #include <linux/hdreg.h>
14 MODULE_LICENSE("Dual BSD/GPL");
15 static char *Version = "1.4";
17 static int memdisk_major = 0;
18 module_param(memdisk_major, int, 0);
19 static int hardsect_size = 512;
20 module_param(hardsect_size, int, 0);
23 * We can tweak our hardware sector size, but the kernel talks to us
24 * in terms of small sectors, always.
26 #define KERNEL_SECTOR_SIZE 512
27 #define MEMDISK_MINORS 16
28 #define MEMDISKS_COUNT 3
30 * The internal representation of our device.
32 static struct memdisk_dev {
33 unsigned long size; /* Device size in sectors */
34 spinlock_t lock; /* For mutual exclusion */
35 u8 *data; /* The data array */
36 struct request_queue *queue; /* The device request queue */
37 struct gendisk *gd; /* The gendisk structure */
41 #define MEMDISK_SYSTEM_PHYS 0xA0000000
42 #define MEMDISK_SYSTEM_SIZE 0x12c00000 // 300M
44 #define MEMDISK_USERDATA_PHYS 0xB2E00000
45 #define MEMDISK_USERDATA_SIZE 0x9600000 // 150M
47 #define MEMDISK_CACHE_PHYS 0xBC600000
48 #define MEMDISK_CACHE_SIZE 0x3200000 // 50M
50 #define MEMDISK_SYSTEM_PHYS 0xA0000000
51 #define MEMDISK_SYSTEM_SIZE 0xD200000 // 210M
53 #define MEMDISK_USERDATA_PHYS 0xB2E00000
54 #define MEMDISK_USERDATA_SIZE 0x2800000 // 40M
56 #define MEMDISK_CACHE_PHYS 0xBC600000
57 #define MEMDISK_CACHE_SIZE 0x600000 // 6M
60 static struct memdisk_dev sprd_memdisks[] = {
62 .data = MEMDISK_SYSTEM_PHYS,
63 .size = MEMDISK_SYSTEM_SIZE,
66 .data = MEMDISK_USERDATA_PHYS,
67 .size = MEMDISK_USERDATA_SIZE,
70 .data = MEMDISK_CACHE_PHYS,
71 .size = MEMDISK_CACHE_SIZE,
76 * Handle an I/O request.
78 static void memdisk_transfer(struct memdisk_dev *dev, sector_t sector
79 , unsigned long nsect, char *buffer, int write)
81 unsigned long offset = sector * hardsect_size;
82 unsigned long nbytes = nsect * hardsect_size;
84 //printk("memdisk_transfer: %s offset:%x, %d bytes. \n", write ? "write" : "read", offset, nbytes);
85 if ((offset + nbytes) > (dev->size * hardsect_size)) {
86 printk (KERN_NOTICE "memdisk: Beyond-end write (%ld %ld)\n", offset, nbytes);
91 memcpy(dev->data + offset, buffer, nbytes);
93 memcpy(buffer, dev->data + offset, nbytes);
96 static void memdisk_request(struct request_queue *q) {
98 struct memdisk_dev *dev = q->queuedata;
100 req = blk_fetch_request(q);
101 while (req != NULL) {
102 if (req->cmd_type != REQ_TYPE_FS) {
103 printk (KERN_NOTICE "Skip non-CMD request/n");
104 __blk_end_request_all(req, -EIO);
107 memdisk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req),
108 req->buffer, rq_data_dir(req));
109 if ( ! __blk_end_request_cur(req, 0) ) {
110 req = blk_fetch_request(q);
116 * The HDIO_GETGEO ioctl is handled in blkdev_ioctl(), i
117 * calls this. We need to implement getgeo, since we can't
118 * use tools such as fdisk to partition the drive otherwise.
120 int memdisk_getgeo(struct block_device * bd, struct hd_geometry * geo)
124 printk("memdisk_getgeo. \n");
126 struct memdisk_dev *dev = bd->bd_disk->private_data;
127 size = dev->size *(hardsect_size / KERNEL_SECTOR_SIZE);
129 geo->cylinders = (size & ~0x3f) >> 6;
138 * The device operations structure.
140 static struct block_device_operations memdisk_ops = {
141 .owner = THIS_MODULE,
142 .getgeo = memdisk_getgeo
146 * Set up our internal device.
148 static void memdisk_setup_device(struct memdisk_dev *dev, int i)
150 unsigned char __iomem *base;
151 printk("memdisk_setup_device i:%d. \n", i);
153 spin_lock_init(&dev->lock);
154 base = ioremap(sprd_memdisks[i].data, sprd_memdisks[i].size);
156 printk("memdisk_setup_device ioremap error, dev[%d] data: %x, size: %x\n", i, sprd_memdisks[i].data, sprd_memdisks[i].size);
160 printk("memdisk_setup_device base: %x, start: %x, size: %x\n",base, sprd_memdisks[i].data, sprd_memdisks[i].size);
161 sprd_memdisks[i].data = base;
162 sprd_memdisks[i].size = (sprd_memdisks[i].size / hardsect_size);
164 dev->queue = blk_init_queue(memdisk_request, &dev->lock);
165 if (dev->queue == NULL) {
166 printk ("memdisk_setup_device blk_init_queue failure. \n");
170 blk_queue_logical_block_size(dev->queue, hardsect_size);
171 dev->queue->queuedata = dev;
173 * And the gendisk structure.
175 dev->gd = alloc_disk(MEMDISK_MINORS);
177 printk ("memdisk_setup_device alloc_disk failure. \n");
180 dev->gd->major = memdisk_major;
181 dev->gd->first_minor = i*MEMDISK_MINORS;
182 dev->gd->fops = &memdisk_ops;
183 dev->gd->queue = dev->queue;
184 dev->gd->private_data = dev;
186 snprintf (dev->gd->disk_name, 32, "memdisk.%d", i);
187 set_capacity(dev->gd, sprd_memdisks[i].size*(hardsect_size/KERNEL_SECTOR_SIZE));
190 printk("memdisk_setup_device i:%d success.\n", i);
194 static int __init memdisk_init(void)
201 printk("memdisk_init. \n");
202 memdisk_major = register_blkdev(memdisk_major, "memdisk");
203 if (memdisk_major <= 0) {
204 printk("memdisk: unable to get major number\n");
208 for (i = 0; i < MEMDISKS_COUNT; i++)
209 memdisk_setup_device(&sprd_memdisks[i], i);
211 printk("memdisk_init finished. \n");
215 static void __exit memdisk_exit(void)
219 printk("memdisk_exit. \n");
220 for (i = 0; i < MEMDISKS_COUNT; i++) {
221 struct memdisk_dev *dev = &sprd_memdisks[i];
224 del_gendisk(dev->gd);
228 blk_cleanup_queue(dev->queue);
231 unregister_blkdev(memdisk_major, "memdisk");
234 module_init(memdisk_init);
235 module_exit(memdisk_exit);