USB: mct_u232: add sanity checking in probe
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / memdisk / memdisk.c
1 #include <linux/module.h>
2 #include <linux/moduleparam.h>
3 #include <linux/init.h>
4
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>
13
14 MODULE_LICENSE("Dual BSD/GPL");
15 static char *Version = "1.4";
16
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);
21
22 /*
23  * We can tweak our hardware sector size, but the kernel talks to us
24  * in terms of small sectors, always.
25  */
26 #define KERNEL_SECTOR_SIZE 512
27 #define MEMDISK_MINORS  16
28 #define MEMDISKS_COUNT 3
29 /*
30  * The internal representation of our device.
31  */
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 */
38 } memdisk_device;
39
40 #if 1 //1G
41 #define MEMDISK_SYSTEM_PHYS    0xA0000000
42 #define MEMDISK_SYSTEM_SIZE    0x12c00000 // 300M
43
44 #define MEMDISK_USERDATA_PHYS  0xB2E00000
45 #define MEMDISK_USERDATA_SIZE  0x9600000  // 150M
46
47 #define MEMDISK_CACHE_PHYS     0xBC600000
48 #define MEMDISK_CACHE_SIZE     0x3200000  // 50M
49 #else //512M
50 #define MEMDISK_SYSTEM_PHYS    0xA0000000
51 #define MEMDISK_SYSTEM_SIZE    0xD200000  // 210M
52
53 #define MEMDISK_USERDATA_PHYS  0xB2E00000
54 #define MEMDISK_USERDATA_SIZE  0x2800000  // 40M
55
56 #define MEMDISK_CACHE_PHYS     0xBC600000
57 #define MEMDISK_CACHE_SIZE     0x600000   // 6M
58 #endif
59
60 static struct memdisk_dev sprd_memdisks[] = {
61         [0] = {
62             .data    = MEMDISK_SYSTEM_PHYS,
63             .size    = MEMDISK_SYSTEM_SIZE,
64         },
65         [1] = {
66             .data    = MEMDISK_USERDATA_PHYS,
67             .size    = MEMDISK_USERDATA_SIZE,
68         },
69         [2] = {
70             .data    = MEMDISK_CACHE_PHYS,
71             .size    = MEMDISK_CACHE_SIZE,
72         },
73 };
74
75 /*
76  * Handle an I/O request.
77  */
78 static void memdisk_transfer(struct memdisk_dev *dev, sector_t sector
79                                          , unsigned long nsect, char *buffer, int write)
80 {
81     unsigned long offset = sector * hardsect_size;
82     unsigned long nbytes = nsect * hardsect_size;
83
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);
87         return;
88     }
89
90     if (write)
91         memcpy(dev->data + offset, buffer, nbytes);
92     else
93         memcpy(buffer, dev->data + offset, nbytes);
94 }
95
96 static void memdisk_request(struct request_queue *q) {
97     struct request *req;
98     struct memdisk_dev *dev = q->queuedata;
99
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);
105             continue;
106         }
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);
111         }
112     }
113 }
114
115 /*
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.
119  */
120 int memdisk_getgeo(struct block_device * bd, struct hd_geometry * geo)
121 {
122         long size;
123
124     printk("memdisk_getgeo. \n");
125
126     struct memdisk_dev *dev = bd->bd_disk->private_data;
127     size = dev->size *(hardsect_size / KERNEL_SECTOR_SIZE);
128
129     geo->cylinders = (size & ~0x3f) >> 6;
130     geo->heads = 4;
131     geo->sectors = 16;
132     geo->start = 4;
133
134     return 0;
135 }
136
137 /*
138  * The device operations structure.
139  */
140 static struct block_device_operations memdisk_ops = {
141         .owner  = THIS_MODULE,
142         .getgeo = memdisk_getgeo
143 };
144
145 /*
146  * Set up our internal device.
147  */
148 static void memdisk_setup_device(struct memdisk_dev *dev, int i)
149 {
150     unsigned char __iomem  *base;
151     printk("memdisk_setup_device i:%d. \n", i);
152
153     spin_lock_init(&dev->lock);
154     base = ioremap(sprd_memdisks[i].data, sprd_memdisks[i].size);
155     if(!base) {
156         printk("memdisk_setup_device ioremap error, dev[%d] data: %x, size: %x\n", i, sprd_memdisks[i].data, sprd_memdisks[i].size);
157         return;
158     }
159
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);
163
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");
167         return;
168     }
169
170     blk_queue_logical_block_size(dev->queue, hardsect_size);
171     dev->queue->queuedata = dev;
172     /*
173      * And the gendisk structure.
174      */
175     dev->gd = alloc_disk(MEMDISK_MINORS);
176     if (! dev->gd) {
177         printk ("memdisk_setup_device alloc_disk failure. \n");
178         return;
179     }
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;
185
186     snprintf (dev->gd->disk_name, 32, "memdisk.%d", i);
187     set_capacity(dev->gd, sprd_memdisks[i].size*(hardsect_size/KERNEL_SECTOR_SIZE));
188     add_disk(dev->gd);
189
190     printk("memdisk_setup_device i:%d success.\n", i);
191     return;
192 }
193
194 static int __init memdisk_init(void)
195 {
196     int i;
197
198     /*
199      * Get registered.
200      */
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");
205         return -EBUSY;
206     }
207
208     for (i = 0; i < MEMDISKS_COUNT; i++)
209          memdisk_setup_device(&sprd_memdisks[i], i);
210
211     printk("memdisk_init finished. \n");
212     return 0;
213 }
214
215 static void __exit memdisk_exit(void)
216 {
217         int i;
218
219         printk("memdisk_exit. \n");
220         for (i = 0; i < MEMDISKS_COUNT; i++) {
221                 struct memdisk_dev *dev = &sprd_memdisks[i];
222
223                 if (dev->gd) {
224                         del_gendisk(dev->gd);
225                         put_disk(dev->gd);
226                 }
227                 if (dev->queue) {
228                     blk_cleanup_queue(dev->queue);
229                 }
230         }
231         unregister_blkdev(memdisk_major, "memdisk");
232 }
233
234 module_init(memdisk_init);
235 module_exit(memdisk_exit);