mtdram.c 5.7 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
Linus Torvalds's avatar
Linus Torvalds committed
2
 * mtdram - a test mtd device
David Woodhouse's avatar
David Woodhouse committed
3
 * $Id: mtdram.c,v 1.32 2003/05/21 15:15:07 dwmw2 Exp $
Linus Torvalds's avatar
Linus Torvalds committed
4
 * Author: Alexander Larsson <alex@cendio.se>
Linus Torvalds's avatar
Linus Torvalds committed
5 6 7 8 9 10 11 12 13
 *
 * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
 *
 * This code is GPL
 *
 */

#include <linux/config.h>
#include <linux/module.h>
Linus Torvalds's avatar
Linus Torvalds committed
14
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
15
#include <linux/ioport.h>
David Woodhouse's avatar
David Woodhouse committed
16 17
#include <linux/vmalloc.h>
#include <linux/init.h>
Linus Torvalds's avatar
Linus Torvalds committed
18 19 20
#include <linux/mtd/compatmac.h>
#include <linux/mtd/mtd.h>

Linus Torvalds's avatar
Linus Torvalds committed
21 22 23 24 25 26 27
#ifndef CONFIG_MTDRAM_ABS_POS
  #define CONFIG_MTDRAM_ABS_POS 0
#endif

#if CONFIG_MTDRAM_ABS_POS > 0
  #include <asm/io.h>
#endif
Linus Torvalds's avatar
Linus Torvalds committed
28

Linus Torvalds's avatar
Linus Torvalds committed
29 30 31 32
#ifdef MODULE
static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
MODULE_PARM(total_size,"l");
David Woodhouse's avatar
David Woodhouse committed
33
MODULE_PARM_DESC(total_size, "Total device size in KiB");
Linus Torvalds's avatar
Linus Torvalds committed
34
MODULE_PARM(erase_size,"l");
David Woodhouse's avatar
David Woodhouse committed
35
MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
Linus Torvalds's avatar
Linus Torvalds committed
36 37 38
#define MTDRAM_TOTAL_SIZE (total_size * 1024)
#define MTDRAM_ERASE_SIZE (erase_size * 1024)
#else
Linus Torvalds's avatar
Linus Torvalds committed
39 40
#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024)
Linus Torvalds's avatar
Linus Torvalds committed
41
#endif
Linus Torvalds's avatar
Linus Torvalds committed
42 43 44 45 46 47 48 49 50


// We could store these in the mtd structure, but we only support 1 device..
static struct mtd_info *mtd_info;


static int
ram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
Linus Torvalds's avatar
Linus Torvalds committed
51 52 53
  DEBUG(MTD_DEBUG_LEVEL2, "ram_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len);
  if (instr->addr + instr->len > mtd->size) {
    DEBUG(MTD_DEBUG_LEVEL1, "ram_erase() out of bounds (%ld > %ld)\n", (long)(instr->addr + instr->len), (long)mtd->size);
Linus Torvalds's avatar
Linus Torvalds committed
54
    return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
55
  }
Linus Torvalds's avatar
Linus Torvalds committed
56 57
	
  memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
Linus Torvalds's avatar
Linus Torvalds committed
58
	
Linus Torvalds's avatar
Linus Torvalds committed
59 60 61 62 63 64 65 66 67 68 69
  instr->state = MTD_ERASE_DONE;

  if (instr->callback)
    (*(instr->callback))(instr);
  return 0;
}

static int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
{
  if (from + len > mtd->size)
    return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
70
	
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73 74 75
  *mtdbuf = mtd->priv + from;
  *retlen = len;
  return 0;
}

David Woodhouse's avatar
David Woodhouse committed
76 77
static void ram_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
			 size_t len)
Linus Torvalds's avatar
Linus Torvalds committed
78
{
Linus Torvalds's avatar
Linus Torvalds committed
79
  DEBUG(MTD_DEBUG_LEVEL2, "ram_unpoint\n");
Linus Torvalds's avatar
Linus Torvalds committed
80 81 82 83 84
}

static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
	     size_t *retlen, u_char *buf)
{
Linus Torvalds's avatar
Linus Torvalds committed
85 86 87
  DEBUG(MTD_DEBUG_LEVEL2, "ram_read(pos:%ld, len:%ld)\n", (long)from, (long)len);
  if (from + len > mtd->size) {
    DEBUG(MTD_DEBUG_LEVEL1, "ram_read() out of bounds (%ld > %ld)\n", (long)(from + len), (long)mtd->size);
Linus Torvalds's avatar
Linus Torvalds committed
88
    return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
89
  }
Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93 94 95 96 97 98 99

  memcpy(buf, mtd->priv + from, len);

  *retlen=len;
  return 0;
}

static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
	      size_t *retlen, const u_char *buf)
{
Linus Torvalds's avatar
Linus Torvalds committed
100 101 102
  DEBUG(MTD_DEBUG_LEVEL2, "ram_write(pos:%ld, len:%ld)\n", (long)to, (long)len);
  if (to + len > mtd->size) {
    DEBUG(MTD_DEBUG_LEVEL1, "ram_write() out of bounds (%ld > %ld)\n", (long)(to + len), (long)mtd->size);
Linus Torvalds's avatar
Linus Torvalds committed
103
    return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
104 105
  }

Linus Torvalds's avatar
Linus Torvalds committed
106 107 108 109 110 111
  memcpy ((char *)mtd->priv + to, buf, len);

  *retlen=len;
  return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
112
static void __exit cleanup_mtdram(void)
Linus Torvalds's avatar
Linus Torvalds committed
113 114 115
{
  if (mtd_info) {
    del_mtd_device(mtd_info);
David Woodhouse's avatar
David Woodhouse committed
116
#if CONFIG_MTDRAM_TOTAL_SIZE > 0
Linus Torvalds's avatar
Linus Torvalds committed
117
    if (mtd_info->priv)
Linus Torvalds's avatar
Linus Torvalds committed
118 119 120
#if CONFIG_MTDRAM_ABS_POS > 0
      iounmap(mtd_info->priv);
#else
Linus Torvalds's avatar
Linus Torvalds committed
121
      vfree(mtd_info->priv);
Linus Torvalds's avatar
Linus Torvalds committed
122
#endif	
David Woodhouse's avatar
David Woodhouse committed
123
#endif
Linus Torvalds's avatar
Linus Torvalds committed
124 125 126 127
    kfree(mtd_info);
  }
}

David Woodhouse's avatar
David Woodhouse committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, 
                       unsigned long size, char *name)
{
   memset(mtd, 0, sizeof(*mtd));

   /* Setup the MTD structure */
   mtd->name = name;
   mtd->type = MTD_RAM;
   mtd->flags = MTD_CAP_RAM;
   mtd->size = size;
   mtd->erasesize = MTDRAM_ERASE_SIZE;
   mtd->priv = mapped_address;

   mtd->owner = THIS_MODULE;
   mtd->erase = ram_erase;
   mtd->point = ram_point;
   mtd->unpoint = ram_unpoint;
   mtd->read = ram_read;
   mtd->write = ram_write;

   if (add_mtd_device(mtd)) {
     return -EIO;
   }
   
   return 0;
}

#if CONFIG_MTDRAM_TOTAL_SIZE > 0
#if CONFIG_MTDRAM_ABS_POS > 0
Linus Torvalds's avatar
Linus Torvalds committed
157
int __init init_mtdram(void)
Linus Torvalds's avatar
Linus Torvalds committed
158
{
David Woodhouse's avatar
David Woodhouse committed
159 160 161
  void *addr;
  int err;
  /* Allocate some memory */
Linus Torvalds's avatar
Linus Torvalds committed
162
   mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
163
   if (!mtd_info)
David Woodhouse's avatar
David Woodhouse committed
164
     return -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
165
   
David Woodhouse's avatar
David Woodhouse committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
  addr = ioremap(CONFIG_MTDRAM_ABS_POS, MTDRAM_TOTAL_SIZE);
  if (!addr) {
    DEBUG(MTD_DEBUG_LEVEL1, 
          "Failed to ioremap) memory region of size %ld at ABS_POS:%ld\n", 
          (long)MTDRAM_TOTAL_SIZE, (long)CONFIG_MTDRAM_ABS_POS);
    kfree(mtd_info);
    mtd_info = NULL;
    return -ENOMEM;
  }
  err = mtdram_init_device(mtd_info, addr, 
                           MTDRAM_TOTAL_SIZE, "mtdram test device");
  if (err) 
  {
    iounmap(addr);
    kfree(mtd_info);
    mtd_info = NULL;
    return err;
  }
  memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
  return err;
}
Linus Torvalds's avatar
Linus Torvalds committed
187

David Woodhouse's avatar
David Woodhouse committed
188 189 190 191 192 193 194 195 196
#else /* CONFIG_MTDRAM_ABS_POS > 0 */

int __init init_mtdram(void)
{
  void *addr;
  int err;
  /* Allocate some memory */
   mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
   if (!mtd_info)
Linus Torvalds's avatar
Linus Torvalds committed
197
     return -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
198

David Woodhouse's avatar
David Woodhouse committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  addr = vmalloc(MTDRAM_TOTAL_SIZE);
  if (!addr) {
    DEBUG(MTD_DEBUG_LEVEL1, 
          "Failed to vmalloc memory region of size %ld\n", 
          (long)MTDRAM_TOTAL_SIZE);
    kfree(mtd_info);
    mtd_info = NULL;
    return -ENOMEM;
  }
  err = mtdram_init_device(mtd_info, addr, 
                           MTDRAM_TOTAL_SIZE, "mtdram test device");
  if (err) 
  {
    vfree(addr);
    kfree(mtd_info);
    mtd_info = NULL;
    return err;
  }
  memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
  return err;
}
#endif /* !(CONFIG_MTDRAM_ABS_POS > 0) */
Linus Torvalds's avatar
Linus Torvalds committed
221

David Woodhouse's avatar
David Woodhouse committed
222 223 224 225 226
#else /* CONFIG_MTDRAM_TOTAL_SIZE > 0 */

int __init init_mtdram(void)
{
  return 0;
Linus Torvalds's avatar
Linus Torvalds committed
227
}
David Woodhouse's avatar
David Woodhouse committed
228
#endif /* !(CONFIG_MTDRAM_TOTAL_SIZE > 0) */
Linus Torvalds's avatar
Linus Torvalds committed
229 230 231

module_init(init_mtdram);
module_exit(cleanup_mtdram);
Linus Torvalds's avatar
Linus Torvalds committed
232 233 234 235 236

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
MODULE_DESCRIPTION("Simulated MTD driver for testing");