1 /*======================================================================
2
3 $Id: slram.c,v 1.10 2000/07/03 10:01:38 dwmw2 Exp $
4
5 ======================================================================*/
6
7
8 #include <linux/module.h>
9 #include <asm/uaccess.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/ptrace.h>
14 #include <linux/malloc.h>
15 #include <linux/string.h>
16 #include <linux/timer.h>
17 #include <linux/major.h>
18 #include <linux/fs.h>
19 #include <linux/ioctl.h>
20 #include <linux/init.h>
21 #include <asm/io.h>
22 #include <asm/system.h>
23 #include <asm/segment.h>
24 #include <stdarg.h>
25
26 #include <linux/mtd/mtd.h>
27
28 struct mypriv {
29 u_char *start;
30 u_char *end;
31 };
32
33 int physmem_erase (struct mtd_info *mtd, struct erase_info *instr);
34 int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
35 void physmem_unpoint (struct mtd_info *mtd, u_char *addr);
36 int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
37 int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
38
39
40 int physmem_erase (struct mtd_info *mtd, struct erase_info *instr)
41 {
42 struct mypriv *priv = mtd->priv;
43
44 if (instr->addr + instr->len > mtd->size)
45 return -EINVAL;
46
47 memset(priv->start + instr->addr, 0xff, instr->len);
48
49 /* This'll catch a few races. Free the thing before returning :)
50 * I don't feel at all ashamed. This kind of thing is possible anyway
51 * with flash, but unlikely.
52 */
53
54 instr->state = MTD_ERASE_DONE;
55
56 if (instr->callback)
57 (*(instr->callback))(instr);
58 else
59 kfree(instr);
60
61 return 0;
62 }
63
64
65 int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
66 {
67 struct mypriv *priv = (struct mypriv *)mtd->priv;
68
69 *mtdbuf = priv->start + from;
70 *retlen = len;
71 return 0;
72 }
73
74 void physmem_unpoint (struct mtd_info *mtd, u_char *addr)
75 {
76 }
77
78 int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
79 {
80 struct mypriv *priv = (struct mypriv *)mtd->priv;
81
82 memcpy (buf, priv->start + from, len);
83
84 *retlen=len;
85 return 0;
86 }
87
88 int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
89 {
90 struct mypriv *priv = (struct mypriv *)mtd->priv;
91
92 memcpy (priv->start + to, buf, len);
93
94 *retlen=len;
95 return 0;
96 }
97
98
99
100
101 /*====================================================================*/
102
103 /* Place your defaults here */
104
105 static u_long start = 100663296;
106 static u_long length = 33554432;
107 static u_long end = 0;
108
109 #if LINUX_VERSION_CODE < 0x20300
110 #ifdef MODULE
111 #define init_slram init_module
112 #define cleanup_slram cleanup_module
113 #endif
114 #define __exit
115 #endif
116
117 #ifdef MODULE
118 MODULE_PARM(start,"l");
119 MODULE_PARM(length,"l");
120 MODULE_PARM(end,"l");
121 #endif
122
123 struct mtd_info *mymtd;
124
125 void __init mtd_slram_setup(char *str, int *ints)
126 {
127 if (ints[0] > 0)
128 start=ints[1];
129 if (ints[0] > 1)
130 length=ints[2];
131 }
132
133 int init_slram(void)
134 {
135 if (!start)
136 {
137 printk(KERN_NOTICE "physmem: No start address for memory device.\n");
138 return -EINVAL;
139 }
140
141 if (!length && !end)
142 {
143 printk(KERN_NOTICE "physmem: No length or endpointer given.\n");
144 return -EINVAL;
145 }
146
147 if (!end)
148 end = start + length;
149
150 if (!length)
151 length = end - start;
152
153 if (start + length != end)
154 {
155 printk(KERN_NOTICE "physmem: start(%lx) + length(%lx) != end(%lx) !\n",
156 start, length, end);
157 return -EINVAL;
158 }
159
160 mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
161
162 memset(mymtd, 0, sizeof(*mymtd));
163
164 if (mymtd)
165 {
166 memset((char *)mymtd, 0, sizeof(struct mtd_info));
167 mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL);
168 if (!mymtd->priv)
169 {
170 kfree(mymtd);
171 mymtd = NULL;
172 }
173 memset(mymtd->priv, 0, sizeof(struct mypriv));
174 }
175
176 if (!mymtd)
177 {
178 printk(KERN_NOTICE "physmem: Cannot allocate new MTD device.\n");
179 return -ENOMEM;
180 }
181
182
183 ((struct mypriv *)mymtd->priv)->start = ioremap(start, length);
184 ((struct mypriv *)mymtd->priv)->end = ((struct mypriv *)mymtd->priv)->start + length;
185
186
187 mymtd->name = "Raw memory";
188
189 mymtd->size = length;
190 mymtd->flags = MTD_CLEAR_BITS | MTD_SET_BITS | MTD_WRITEB_WRITEABLE | MTD_VOLATILE;
191 mymtd->erase = physmem_erase;
192 mymtd->point = physmem_point;
193 mymtd->unpoint = physmem_unpoint;
194 mymtd->read = physmem_read;
195 mymtd->write = physmem_write;
196 mymtd->module = THIS_MODULE;
197 mymtd->type = MTD_RAM;
198 mymtd->erasesize = 0x10000;
199
200 if (add_mtd_device(mymtd))
201 {
202 printk("Failed to register new device\n");
203 kfree(mymtd->priv);
204 kfree(mymtd);
205 return -EAGAIN;
206 }
207 printk("Registered physmem device from %dKb to %dKb\n",
208 (int)(start / 1024), (int)(end / 1024));
209 printk("Mapped from 0x%p to 0x%p\n",((struct mypriv *)mymtd->priv)->start,
210 ((struct mypriv *)mymtd->priv)->end);
211
212 return 0;
213 }
214
215 static void __exit cleanup_slram(void)
216 {
217 iounmap(((struct mypriv *)mymtd->priv)->start);
218 kfree (mymtd->priv);
219 del_mtd_device(mymtd);
220 kfree(mymtd);
221 }
222
223 #if LINUX_VERSION_CODE > 0x20300
224 module_init(init_slram);
225 module_exit(cleanup_slram);
226 #endif
227
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.