Test mtd ram device
Alexander Larsson
alex at cendio.se
Sat Mar 4 09:52:12 EST 2000
Since I'm playing around with the MTD stuff i needed a test device that i
can use on my normal machine. I've attached a device that just vmalloc()s
some space and registers as an mtd device.
/ Alex
-------------- next part --------------
/*
* mtdram - a test mtd device
*
* Author: Alexander Larsson <alex at cendio.se>
*
* Copyright (c) 1999 Alexander Larsson <alex at cendio.se>
*
* This code is GPL
*
*/
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/mtd/mapped.h>
#if LINUX_VERSION_CODE < 0x20300
#define __exit
#endif
#define MTDRAM_TOTAL_SIZE 1024*1024*2
#define MTDRAM_ERASE_SIZE 64*1024
struct ram_mtd_info {
struct mtd_info mtd;
char *buffer;
};
// We could store these in the mtd structure, but we only support 1 device..
static struct ram_mtd_info *mtd_info;
int
ram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct ram_mtd_info *priv = (struct ram_mtd_info *)mtd;
if (instr->addr + instr->len > mtd->size)
return -EINVAL;
memset(priv->buffer + instr->addr, 0xff, instr->len);
/* This'll catch a few races. Free the thing before returning :)
* I don't feel at all ashamed. This kind of thing is possible anyway
* with flash, but unlikely.
*/
instr->state = MTD_ERASE_DONE;
if (instr->callback)
(*(instr->callback))(instr);
else
kfree(instr);
return 0;
}
int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
{
struct ram_mtd_info *priv = (struct ram_mtd_info *)mtd;
if (from + len > mtd->size)
return -EINVAL;
*mtdbuf = priv->buffer + from;
*retlen = len;
return 0;
}
void ram_unpoint (struct mtd_info *mtd, u_char *addr)
{
}
int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct ram_mtd_info *priv = (struct ram_mtd_info *)mtd;
if (from + len > mtd->size)
return -EINVAL;
memcpy (buf, priv->buffer + from, len);
*retlen=len;
return 0;
}
int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct ram_mtd_info *priv = (struct ram_mtd_info *)mtd;
if (to + len > mtd->size)
return -EINVAL;
memcpy (priv->buffer + to, buf, len);
*retlen=len;
return 0;
}
static void __exit cleanup_mtdram()
{
if (mtd_info) {
del_mtd_device(&mtd_info->mtd);
if (mtd_info->buffer)
vfree(mtd_info->buffer);
kfree(mtd_info);
}
}
static int __init init_mtdram(void)
{
// Allocate some memory
mtd_info = (struct ram_mtd_info *)kmalloc(sizeof(struct ram_mtd_info), GFP_KERNEL);
if (mtd_info == 0)
return 0;
memset(mtd_info, 0, sizeof(*mtd_info));
// Setup the MTD structure
strcpy(mtd_info->mtd.name,"mtdram test device");
mtd_info->mtd.type = MTD_RAM;
mtd_info->mtd.flags = MTD_CAP_RAM;
mtd_info->mtd.size = MTDRAM_TOTAL_SIZE;
mtd_info->mtd.erasesize = MTDRAM_ERASE_SIZE;
mtd_info->buffer = vmalloc(MTDRAM_TOTAL_SIZE);
if (mtd_info->buffer == NULL)
return -ENOMEM;
mtd_info->mtd.erase = ram_erase;
mtd_info->mtd.point = ram_point;
mtd_info->mtd.unpoint = ram_unpoint;
mtd_info->mtd.read = ram_read;
mtd_info->mtd.write = ram_write;
if (add_mtd_device(&mtd_info->mtd)) {
/* Clean up */
}
return 0;
}
module_init(init_mtdram);
module_exit(cleanup_mtdram);
More information about the linux-mtd
mailing list