summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/drivers/mtd/mtdblock_ro.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.4.x/drivers/mtd/mtdblock_ro.c')
-rw-r--r--linux-2.4.x/drivers/mtd/mtdblock_ro.c348
1 files changed, 51 insertions, 297 deletions
diff --git a/linux-2.4.x/drivers/mtd/mtdblock_ro.c b/linux-2.4.x/drivers/mtd/mtdblock_ro.c
index a66b852..0c830ba 100644
--- a/linux-2.4.x/drivers/mtd/mtdblock_ro.c
+++ b/linux-2.4.x/drivers/mtd/mtdblock_ro.c
@@ -1,333 +1,87 @@
/*
- * $Id: mtdblock_ro.c,v 1.12 2001/11/20 11:42:33 dwmw2 Exp $
+ * $Id: mtdblock_ro.c,v 1.19 2004/11/16 18:28:59 dwmw2 Exp $
*
- * Read-only version of the mtdblock device, without the
- * read/erase/modify/writeback stuff
+ * (C) 2003 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Simple read-only (writable only for RAM) mtdblock driver
*/
-#ifdef MTDBLOCK_DEBUG
-#define DEBUGLVL debug
-#endif
-
-
-#include <linux/module.h>
-#include <linux/types.h>
-
+#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
-
-#define MAJOR_NR MTD_BLOCK_MAJOR
-#define DEVICE_NAME "mtdblock"
-#define DEVICE_REQUEST mtdblock_request
-#define DEVICE_NR(device) (device)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-#define DEVICE_NO_RANDOM
-#include <linux/blk.h>
-
-#if LINUX_VERSION_CODE < 0x20300
-#define RQFUNC_ARG void
-#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0)
-#else
-#define RQFUNC_ARG request_queue_t *q
-#endif
-
-#ifdef MTDBLOCK_DEBUG
-static int debug = MTDBLOCK_DEBUG;
-MODULE_PARM(debug, "i");
-#endif
+#include <linux/mtd/blktrans.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
-#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
-#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
-#else
-#define BLK_INC_USE_COUNT do {} while(0)
-#define BLK_DEC_USE_COUNT do {} while(0)
-#endif
-
-static int mtd_sizes[MAX_MTD_DEVICES];
-
-
-static int mtdblock_open(struct inode *inode, struct file *file)
+static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
+ unsigned long block, char *buf)
{
- struct mtd_info *mtd = NULL;
-
- int dev;
-
- DEBUG(1,"mtdblock_open\n");
-
- if (inode == 0)
- return -EINVAL;
-
- dev = MINOR(inode->i_rdev);
-
- mtd = get_mtd_device(NULL, dev);
- if (!mtd)
- return -EINVAL;
- if (MTD_ABSENT == mtd->type) {
- put_mtd_device(mtd);
- return -EINVAL;
- }
-
- BLK_INC_USE_COUNT;
-
- mtd_sizes[dev] = mtd->size>>9;
-
- DEBUG(1, "ok\n");
+ size_t retlen;
+ if (dev->mtd->read(dev->mtd, (block * 512), 512, &retlen, buf))
+ return 1;
return 0;
}
-static release_t mtdblock_release(struct inode *inode, struct file *file)
-{
- int dev;
- struct mtd_info *mtd;
-
- DEBUG(1, "mtdblock_release\n");
-
- if (inode == NULL)
- release_return(-ENODEV);
-
- dev = MINOR(inode->i_rdev);
- mtd = __get_mtd_device(NULL, dev);
-
- if (!mtd) {
- printk(KERN_WARNING "MTD device is absent on mtd_release!\n");
- BLK_DEC_USE_COUNT;
- release_return(-ENODEV);
- }
-
- if (mtd->sync)
- mtd->sync(mtd);
-
- put_mtd_device(mtd);
-
- DEBUG(1, "ok\n");
-
- BLK_DEC_USE_COUNT;
- release_return(0);
-}
-
-
-static void mtdblock_request(RQFUNC_ARG)
+static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
+ unsigned long block, char *buf)
{
- struct request *current_request;
- unsigned int res = 0;
- struct mtd_info *mtd;
-
- while (1)
- {
- /* Grab the Request and unlink it from the request list, INIT_REQUEST
- will execute a return if we are done. */
- INIT_REQUEST;
- current_request = CURRENT;
-
- if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES)
- {
- printk("mtd: Unsupported device!\n");
- end_request(0);
- continue;
- }
-
- // Grab our MTD structure
+ size_t retlen;
- mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev));
- if (!mtd) {
- printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV);
- end_request(0);
- }
-
- if (current_request->sector << 9 > mtd->size ||
- (current_request->sector + current_request->nr_sectors) << 9 > mtd->size)
- {
- printk("mtd: Attempt to read past end of device!\n");
- printk("size: %x, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors);
- end_request(0);
- continue;
- }
-
- /* Remove the request we are handling from the request list so nobody messes
- with it */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- /* Now drop the lock that the ll_rw_blk functions grabbed for us
- and process the request. This is necessary due to the extreme time
- we spend processing it. */
- spin_unlock_irq(&io_request_lock);
-#endif
-
- // Handle the request
- switch (current_request->cmd)
- {
- size_t retlen;
-
- case READ:
- if (MTD_READ(mtd,current_request->sector<<9,
- current_request->nr_sectors << 9,
- &retlen, current_request->buffer) == 0)
- res = 1;
- else
- res = 0;
- break;
-
- case WRITE:
-
- /* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector,
- current_request->nr_sectors);
- */
-
- // Read only device
- if ((mtd->flags & MTD_CAP_RAM) == 0)
- {
- res = 0;
- break;
- }
-
- // Do the write
- if (MTD_WRITE(mtd,current_request->sector<<9,
- current_request->nr_sectors << 9,
- &retlen, current_request->buffer) == 0)
- res = 1;
- else
- res = 0;
- break;
-
- // Shouldn't happen
- default:
- printk("mtd: unknown request\n");
- break;
- }
-
- // Grab the lock and re-thread the item onto the linked list
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- spin_lock_irq(&io_request_lock);
-#endif
- end_request(res);
- }
+ if (dev->mtd->write(dev->mtd, (block * 512), 512, &retlen, buf))
+ return 1;
+ return 0;
}
-
-
-static int mtdblock_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
- struct mtd_info *mtd;
+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
- mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev));
+ if (!dev)
+ return;
- if (!mtd) return -EINVAL;
+ memset(dev, 0, sizeof(*dev));
- switch (cmd) {
- case BLKGETSIZE: /* Return device size */
- return put_user((mtd->size >> 9), (unsigned long *) arg);
+ dev->mtd = mtd;
+ dev->devnum = mtd->index;
+ dev->blksize = 512;
+ dev->size = mtd->size >> 9;
+ dev->tr = tr;
+ if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) !=
+ (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE))
+ dev->readonly = 1;
-#ifdef BLKGETSIZE64
- case BLKGETSIZE64:
- return put_user((u64)mtd->size, (u64 *)arg);
-#endif
-
- case BLKFLSBUF:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if(!capable(CAP_SYS_ADMIN)) return -EACCES;
-#endif
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- if (mtd->sync)
- mtd->sync(mtd);
- return 0;
-
- default:
- return -ENOTTY;
- }
+ add_mtd_blktrans_dev(dev);
}
-
-#ifdef MAGIC_ROM_PTR
-static int
-mtdblock_romptr(kdev_t dev, struct vm_area_struct * vma)
+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
{
- struct mtd_info *mtd;
- u_char *ptr;
- size_t len;
-
- mtd = __get_mtd_device(NULL, MINOR(dev));
-
- if (!mtd->point)
- return -ENOSYS; /* Can't do it, No function to point to correct addr */
-
- if ((*mtd->point)(mtd,vma->vm_offset,vma->vm_end-vma->vm_start,&len,&ptr) != 0)
- return -ENOSYS;
-
- vma->vm_start = (unsigned long) ptr;
- vma->vm_end = vma->vm_start + len;
- return 0;
+ del_mtd_blktrans_dev(dev);
+ kfree(dev);
}
-#endif
-
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations mtd_fops =
-{
- open: mtdblock_open,
- ioctl: mtdblock_ioctl,
- release: mtdblock_release,
- read: block_read,
-#ifdef MAGIC_ROM_PTR
- romptr: mtdblock_romptr,
-#endif
- write: block_write
-};
-#else
-static struct block_device_operations mtd_fops =
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
- owner: THIS_MODULE,
-#endif
- open: mtdblock_open,
- release: mtdblock_release,
-#ifdef MAGIC_ROM_PTR
- romptr: mtdblock_romptr,
-#endif
- ioctl: mtdblock_ioctl
+static struct mtd_blktrans_ops mtdblock_tr = {
+ .name = "mtdblock",
+ .major = 31,
+ .part_bits = 0,
+ .readsect = mtdblock_readsect,
+ .writesect = mtdblock_writesect,
+ .add_mtd = mtdblock_add_mtd,
+ .remove_dev = mtdblock_remove_dev,
+ .owner = THIS_MODULE,
};
-#endif
-int __init init_mtdblock(void)
+static int __init mtdblock_init(void)
{
- int i;
-
- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
- MTD_BLOCK_MAJOR);
- return -EAGAIN;
- }
- DEBUG(MTD_DEBUG_LEVEL3,
- "init_mtdblock: allocated major number %d (read only).\n",
- MTD_BLOCK_MAJOR);
-
- /* We fill it in at open() time. */
- for (i=0; i< MAX_MTD_DEVICES; i++) {
- mtd_sizes[i] = 0;
- }
-
- /* Allow the block size to default to BLOCK_SIZE. */
- blksize_size[MAJOR_NR] = NULL;
- blk_size[MAJOR_NR] = mtd_sizes;
-
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
- return 0;
+ return register_mtd_blktrans(&mtdblock_tr);
}
-static void __exit cleanup_mtdblock(void)
+static void __exit mtdblock_exit(void)
{
- unregister_blkdev(MAJOR_NR,DEVICE_NAME);
- blksize_size[MAJOR_NR] = NULL;
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ deregister_mtd_blktrans(&mtdblock_tr);
}
-module_init(init_mtdblock);
-module_exit(cleanup_mtdblock);
-
+module_init(mtdblock_init);
+module_exit(mtdblock_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Erwin Authried <eauth@softsys.co.at> et al.");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Simple read-only block device emulation access to MTD devices");