root/drivers/mtd/devices/mtdram.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_offs_len
  2. ram_erase
  3. ram_point
  4. ram_unpoint
  5. ram_read
  6. ram_write
  7. cleanup_mtdram
  8. mtdram_init_device
  9. init_mtdram

   1 /*
   2  * mtdram - a test mtd device
   3  * Author: Alexander Larsson <alex@cendio.se>
   4  *
   5  * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
   6  * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de>
   7  *
   8  * This code is GPL
   9  *
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/slab.h>
  14 #include <linux/ioport.h>
  15 #include <linux/vmalloc.h>
  16 #include <linux/mm.h>
  17 #include <linux/init.h>
  18 #include <linux/mtd/mtd.h>
  19 #include <linux/mtd/mtdram.h>
  20 
  21 static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
  22 static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
  23 static unsigned long writebuf_size = 64;
  24 #define MTDRAM_TOTAL_SIZE (total_size * 1024)
  25 #define MTDRAM_ERASE_SIZE (erase_size * 1024)
  26 
  27 module_param(total_size, ulong, 0);
  28 MODULE_PARM_DESC(total_size, "Total device size in KiB");
  29 module_param(erase_size, ulong, 0);
  30 MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
  31 module_param(writebuf_size, ulong, 0);
  32 MODULE_PARM_DESC(writebuf_size, "Device write buf size in Bytes (Default: 64)");
  33 
  34 // We could store these in the mtd structure, but we only support 1 device..
  35 static struct mtd_info *mtd_info;
  36 
  37 static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len)
  38 {
  39         int ret = 0;
  40 
  41         /* Start address must align on block boundary */
  42         if (mtd_mod_by_eb(ofs, mtd)) {
  43                 pr_debug("%s: unaligned address\n", __func__);
  44                 ret = -EINVAL;
  45         }
  46 
  47         /* Length must align on block boundary */
  48         if (mtd_mod_by_eb(len, mtd)) {
  49                 pr_debug("%s: length not block aligned\n", __func__);
  50                 ret = -EINVAL;
  51         }
  52 
  53         return ret;
  54 }
  55 
  56 static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
  57 {
  58         if (check_offs_len(mtd, instr->addr, instr->len))
  59                 return -EINVAL;
  60         memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
  61 
  62         return 0;
  63 }
  64 
  65 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
  66                 size_t *retlen, void **virt, resource_size_t *phys)
  67 {
  68         *virt = mtd->priv + from;
  69         *retlen = len;
  70 
  71         if (phys) {
  72                 /* limit retlen to the number of contiguous physical pages */
  73                 unsigned long page_ofs = offset_in_page(*virt);
  74                 void *addr = *virt - page_ofs;
  75                 unsigned long pfn1, pfn0 = vmalloc_to_pfn(addr);
  76 
  77                 *phys = __pfn_to_phys(pfn0) + page_ofs;
  78                 len += page_ofs;
  79                 while (len > PAGE_SIZE) {
  80                         len -= PAGE_SIZE;
  81                         addr += PAGE_SIZE;
  82                         pfn0++;
  83                         pfn1 = vmalloc_to_pfn(addr);
  84                         if (pfn1 != pfn0) {
  85                                 *retlen = addr - *virt;
  86                                 break;
  87                         }
  88                 }
  89         }
  90 
  91         return 0;
  92 }
  93 
  94 static int ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
  95 {
  96         return 0;
  97 }
  98 
  99 static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
 100                 size_t *retlen, u_char *buf)
 101 {
 102         memcpy(buf, mtd->priv + from, len);
 103         *retlen = len;
 104         return 0;
 105 }
 106 
 107 static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
 108                 size_t *retlen, const u_char *buf)
 109 {
 110         memcpy((char *)mtd->priv + to, buf, len);
 111         *retlen = len;
 112         return 0;
 113 }
 114 
 115 static void __exit cleanup_mtdram(void)
 116 {
 117         if (mtd_info) {
 118                 mtd_device_unregister(mtd_info);
 119                 vfree(mtd_info->priv);
 120                 kfree(mtd_info);
 121         }
 122 }
 123 
 124 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
 125                 unsigned long size, const char *name)
 126 {
 127         memset(mtd, 0, sizeof(*mtd));
 128 
 129         /* Setup the MTD structure */
 130         mtd->name = name;
 131         mtd->type = MTD_RAM;
 132         mtd->flags = MTD_CAP_RAM;
 133         mtd->size = size;
 134         mtd->writesize = 1;
 135         mtd->writebufsize = writebuf_size;
 136         mtd->erasesize = MTDRAM_ERASE_SIZE;
 137         mtd->priv = mapped_address;
 138 
 139         mtd->owner = THIS_MODULE;
 140         mtd->_erase = ram_erase;
 141         mtd->_point = ram_point;
 142         mtd->_unpoint = ram_unpoint;
 143         mtd->_read = ram_read;
 144         mtd->_write = ram_write;
 145 
 146         if (mtd_device_register(mtd, NULL, 0))
 147                 return -EIO;
 148 
 149         return 0;
 150 }
 151 
 152 static int __init init_mtdram(void)
 153 {
 154         void *addr;
 155         int err;
 156 
 157         if (!total_size)
 158                 return -EINVAL;
 159 
 160         /* Allocate some memory */
 161         mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
 162         if (!mtd_info)
 163                 return -ENOMEM;
 164 
 165         addr = vmalloc(MTDRAM_TOTAL_SIZE);
 166         if (!addr) {
 167                 kfree(mtd_info);
 168                 mtd_info = NULL;
 169                 return -ENOMEM;
 170         }
 171         err = mtdram_init_device(mtd_info, addr, MTDRAM_TOTAL_SIZE, "mtdram test device");
 172         if (err) {
 173                 vfree(addr);
 174                 kfree(mtd_info);
 175                 mtd_info = NULL;
 176                 return err;
 177         }
 178         memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
 179         return err;
 180 }
 181 
 182 module_init(init_mtdram);
 183 module_exit(cleanup_mtdram);
 184 
 185 MODULE_LICENSE("GPL");
 186 MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
 187 MODULE_DESCRIPTION("Simulated MTD driver for testing");

/* [<][>][^][v][top][bottom][index][help] */