mtdram.c revision 783ed81ff39d3f938a6b2efd09fbad96e41e5c1f
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mtdram - a test mtd device 3c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel * $Id: mtdram.c,v 1.37 2005/04/21 03:42:11 joern Exp $ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Alexander Larsson <alex@cendio.se> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1999 Alexander Larsson <alex@cendio.se> 7c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is GPL 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/compatmac.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_TOTAL_SIZE (total_size * 1024) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_ERASE_SIZE (erase_size * 1024) 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel#ifdef MODULE 28c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelmodule_param(total_size, ulong, 0); 29c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern EngelMODULE_PARM_DESC(total_size, "Total device size in KiB"); 30c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelmodule_param(erase_size, ulong, 0); 31c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern EngelMODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); 32c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel#endif 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// We could store these in the mtd structure, but we only support 1 device.. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *mtd_info; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic int ram_erase(struct mtd_info *mtd, struct erase_info *instr) 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 39c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (instr->addr + instr->len > mtd->size) 40c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EINVAL; 41c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 42c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel memset((char *)mtd->priv + instr->addr, 0xff, instr->len); 43c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 44c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel instr->state = MTD_ERASE_DONE; 45c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd_erase_callback(instr); 46c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 47c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return 0; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 50c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic int ram_point(struct mtd_info *mtd, loff_t from, size_t len, 51c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel size_t *retlen, u_char **mtdbuf) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 53c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (from + len > mtd->size) 54c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EINVAL; 55c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 56c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel *mtdbuf = mtd->priv + from; 57c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel *retlen = len; 58c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return 0; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from, 62c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel size_t len) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_read(struct mtd_info *mtd, loff_t from, size_t len, 67c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel size_t *retlen, u_char *buf) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 69c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (from + len > mtd->size) 70c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EINVAL; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel memcpy(buf, mtd->priv + from, len); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel *retlen = len; 75c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return 0; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_write(struct mtd_info *mtd, loff_t to, size_t len, 79c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel size_t *retlen, const u_char *buf) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 81c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (to + len > mtd->size) 82c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EINVAL; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 84c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel memcpy((char *)mtd->priv + to, buf, len); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 86c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel *retlen = len; 87c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return 0; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit cleanup_mtdram(void) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 92c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (mtd_info) { 93c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel del_mtd_device(mtd_info); 94f9101210e7aa72daf92722d451a2f7e3af5f781fJesper Juhl vfree(mtd_info->priv); 95c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel kfree(mtd_info); 96c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel } 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelint mtdram_init_device(struct mtd_info *mtd, void *mapped_address, 100c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel unsigned long size, char *name) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 102c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel memset(mtd, 0, sizeof(*mtd)); 103c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 104c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel /* Setup the MTD structure */ 105c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->name = name; 10692cbfdcc3661d7670b01b92b89811cd3a2412297Joern Engel mtd->type = MTD_GENERIC_TYPE; 107c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->flags = MTD_CAP_RAM; 108c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->size = size; 109783ed81ff39d3f938a6b2efd09fbad96e41e5c1fArtem B. Bityutskiy mtd->writesize = 1; 110c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->erasesize = MTDRAM_ERASE_SIZE; 111c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->priv = mapped_address; 112c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 113c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->owner = THIS_MODULE; 114c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->erase = ram_erase; 115c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->point = ram_point; 116c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->unpoint = ram_unpoint; 117c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->read = ram_read; 118c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd->write = ram_write; 119c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 120c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (add_mtd_device(mtd)) { 121c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EIO; 122c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel } 123c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 124c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return 0; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_mtdram(void) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 129c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel void *addr; 130c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel int err; 131c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 132c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (!total_size) 133c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -EINVAL; 134c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 135c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel /* Allocate some memory */ 136c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 137c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (!mtd_info) 138c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -ENOMEM; 139c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel 140c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel addr = vmalloc(MTDRAM_TOTAL_SIZE); 141c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (!addr) { 142c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel kfree(mtd_info); 143c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd_info = NULL; 144c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return -ENOMEM; 145c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel } 146c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel err = mtdram_init_device(mtd_info, addr, MTDRAM_TOTAL_SIZE, "mtdram test device"); 147c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel if (err) { 148c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel vfree(addr); 149c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel kfree(mtd_info); 150c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel mtd_info = NULL; 151c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return err; 152c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel } 153c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE); 154c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel return err; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_mtdram); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cleanup_mtdram); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>"); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Simulated MTD driver for testing"); 163