OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [char/] [mem.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 *  linux/arch/arm/drivers/char/mem.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 *
6
 *  Modifications for ARM Copyright (C) 1995, 1996 Russell King
7
 */
8
 
9
#include <linux/config.h>
10
#include <linux/types.h>
11
#include <linux/errno.h>
12
#include <linux/sched.h>
13
#include <linux/kernel.h>
14
#include <linux/major.h>
15
#include <linux/tty.h>
16
#include <linux/miscdevice.h>
17
#include <linux/tpqic02.h>
18
#include <linux/malloc.h>
19
#include <linux/mman.h>
20
#include <linux/mm.h>
21
#include <linux/random.h>
22
 
23
#include <asm/segment.h>
24
#include <asm/io.h>
25
#include <asm/pgtable.h>
26
 
27
extern int con_fb_read(char *buf, unsigned long pos, int count);
28
extern int con_fb_write(const char *buf, unsigned long pos, int count);
29
extern int con_fb_mmap(unsigned long vma_start, unsigned long vma_offset,
30
                        unsigned long vma_end, pgprot_t prot);
31
 
32
#ifdef CONFIG_SOUND
33
void soundcard_init(void);
34
#endif
35
 
36
static int read_ram(struct inode * inode, struct file * file, char * buf, int count)
37
{
38
        return -EIO;
39
}
40
 
41
static int write_ram(struct inode * inode, struct file * file, const char * buf, int count)
42
{
43
        return -EIO;
44
}
45
 
46
static int read_mem(struct inode * inode, struct file * file, char * buf, int count)
47
{
48
        unsigned long p = file->f_pos;
49
 
50
        p += PAGE_OFFSET;
51
        if (count < 0)
52
                return -EINVAL;
53
        if (MAP_NR(p) >= max_mapnr)
54
                return 0;
55
        if (count > high_memory - p)
56
                count = high_memory - p;
57
        memcpy_tofs(buf,(void *) p,count);
58
        file->f_pos += count;
59
        return count;
60
}
61
 
62
static int write_mem(struct inode * inode, struct file * file, const char * buf, int count)
63
{
64
        unsigned long p = file->f_pos;
65
 
66
        p += PAGE_OFFSET;
67
        if (count < 0)
68
                return -EINVAL;
69
        if (MAP_NR(p) >= max_mapnr)
70
                return 0;
71
        if (count > high_memory - p)
72
                count = high_memory - p;
73
        memcpy_fromfs((void *) p,buf,count);
74
        file->f_pos += count;
75
        return count;
76
}
77
 
78
static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_struct * vma)
79
{
80
#ifndef NO_MM
81
        if (vma->vm_offset & ~PAGE_MASK)
82
                return -ENXIO;
83
 
84
        /*
85
         * This disables memory caching/buffering
86
         */
87
#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
88
        if (MAP_NR(vma->vm_offset) >= max_mapnr)
89
                pgprot_val(vma->vm_page_prot) &= ~(PTE_CACHEABLE | PTE_BUFFERABLE);
90
#endif
91
 
92
        if (remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))
93
                return -EAGAIN;
94
        vma->vm_inode = inode;
95
        inode->i_count++;
96
#else
97
        vma->vm_start = file->f_pos+PAGE_OFFSET+vma->vm_offset;
98
#endif /* !NO_MM */
99
 
100
        return 0;
101
}
102
 
103
static int read_fb(struct inode * inode, struct file *file, char *buf, int count)
104
{
105
        if (count < 0)
106
                return -EINVAL;
107
        count = con_fb_read(buf, file->f_pos, count);
108
        if (count > 0)
109
                file->f_pos += count;
110
        return count;
111
}
112
 
113
static int write_fb(struct inode * inode, struct file * file, const char * buf, int count)
114
{
115
        if (count < 0)
116
                return -EINVAL;
117
        count = con_fb_write(buf, file->f_pos, count);
118
        if (count > 0)
119
                file->f_pos += count;
120
        return count;
121
}
122
 
123
static int mmap_fb(struct inode * inode, struct file * file, struct vm_area_struct * vma)
124
{
125
        int ret;
126
#ifndef NO_MM
127
 
128
        if (vma->vm_offset & ~PAGE_MASK)
129
                return -ENXIO;
130
 
131
        ret = con_fb_mmap(vma->vm_start, vma->vm_offset, vma->vm_end, vma->vm_page_prot);
132
        if (ret)
133
                return ret;
134
        vma->vm_inode = inode;
135
        inode->i_count ++;
136
#else
137
        ret = con_fb_mmap(vma->vm_start, vma->vm_offset, vma->vm_end, __pgprot(0));
138
        if (ret)
139
                return ret;
140
#endif  
141
        return 0;
142
}
143
 
144
static int read_kmem(struct inode *inode, struct file *file, char *buf, int count)
145
{
146
        int read1, read2;
147
 
148
        read1 = read_mem(inode, file, buf, count);
149
        if (read1 < 0)
150
                return read1;
151
        read2 = vread(buf + read1, (char *) ((unsigned long) file->f_pos), count - read1);
152
        if (read2 < 0)
153
                return read2;
154
        file->f_pos += read2;
155
        return read1 + read2;
156
}
157
 
158
static int read_port(struct inode * inode, struct file * file,char * buf, int count)
159
{
160
        unsigned int i = file->f_pos;
161
        char * tmp = buf;
162
 
163
        while (count-- > 0 && (i < 65536 || (i > 0x80000000 && i < 0x84000000))) {
164
                put_user(inb(i),tmp);
165
                i++;
166
                tmp++;
167
        }
168
        file->f_pos = i;
169
        return tmp-buf;
170
}
171
 
172
static int write_port(struct inode * inode, struct file * file, const char * buf, int count)
173
{
174
        unsigned int i = file->f_pos;
175
        const char * tmp = buf;
176
 
177
        while (count-- > 0 && (i < 65536 || (i > 0x80000000 && i < 0x84000000))) {
178
                outb(get_user(tmp),i);
179
                i++;
180
                tmp++;
181
        }
182
        file->f_pos = i;
183
        return tmp-buf;
184
}
185
 
186
static int read_null(struct inode * node, struct file * file, char * buf, int count)
187
{
188
        return 0;
189
}
190
 
191
static int write_null(struct inode * inode, struct file * file, const char * buf, int count)
192
{
193
        return count;
194
}
195
 
196
static int read_zero(struct inode * node, struct file * file, char * buf, int count)
197
{
198
        int left;
199
 
200
        for (left = count; left > 0; left--) {
201
                put_user(0,buf);
202
                buf++;
203
                if (need_resched)
204
                        schedule();
205
        }
206
        return count;
207
}
208
 
209
static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_struct * vma)
210
{
211
#ifndef NO_MM
212
        if (vma->vm_flags & VM_SHARED)
213
                return -EINVAL;
214
        if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
215
                return -EAGAIN;
216
        return 0;
217
#else /* !NO_MM */
218
        /* FIXME: trivial calloc() implementation is feasible */
219
        return -ENOSYS;
220
#endif /* !NO_MM */
221
 
222
}
223
 
224
static int read_full(struct inode * node, struct file * file, char * buf,int count)
225
{
226
        file->f_pos += count;
227
        return count;
228
}
229
 
230
static int write_full(struct inode * inode, struct file * file, const char * buf, int count)
231
{
232
        return -ENOSPC;
233
}
234
 
235
/*
236
 * Special lseek() function for /dev/null and /dev/zero.  Most notably, you can fopen()
237
 * both devices with "a" now.  This was previously impossible.  SRB.
238
 */
239
 
240
static int null_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
241
{
242
        return file->f_pos=0;
243
}
244
/*
245
 * The memory devices use the full 32/64 bits of the offset, and so we cannot
246
 * check against negative addresses: they are ok. The return value is weird,
247
 * though, in that case (0).
248
 *
249
 * also note that seeking relative to the "end of file" isn't supported:
250
 * it has no meaning, so it returns -EINVAL.
251
 */
252
static int memory_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
253
{
254
        switch (orig) {
255
                case 0:
256
                        file->f_pos = offset;
257
                        return file->f_pos;
258
                case 1:
259
                        file->f_pos += offset;
260
                        return file->f_pos;
261
                default:
262
                        return -EINVAL;
263
        }
264
        if (file->f_pos < 0)
265
                return 0;
266
        return file->f_pos;
267
}
268
 
269
#define write_kmem      write_mem
270
#define mmap_kmem       mmap_mem
271
#define zero_lseek      null_lseek
272
#define write_zero      write_null
273
 
274
static struct file_operations ram_fops = {
275
        memory_lseek,
276
        read_ram,
277
        write_ram,
278
        NULL,           /* ram_readdir */
279
        NULL,           /* ram_select */
280
        NULL,           /* ram_ioctl */
281
        NULL,           /* ram_mmap */
282
        NULL,           /* no special open code */
283
        NULL,           /* no special release code */
284
        NULL            /* fsync */
285
};
286
 
287
static struct file_operations mem_fops = {
288
        memory_lseek,
289
        read_mem,
290
        write_mem,
291
        NULL,           /* mem_readdir */
292
        NULL,           /* mem_select */
293
        NULL,           /* mem_ioctl */
294
        mmap_mem,
295
        NULL,           /* no special open code */
296
        NULL,           /* no special release code */
297
        NULL            /* fsync */
298
};
299
 
300
static struct file_operations fb_fops = {
301
        memory_lseek,
302
        read_fb,
303
        write_fb,
304
        NULL,           /* mem_readdir */
305
        NULL,           /* mem_select */
306
        NULL,           /* mem_ioctl */
307
        mmap_fb,
308
        NULL,           /* no special open code */
309
        NULL,           /* no special release code */
310
        NULL            /* fsync */
311
};
312
 
313
static struct file_operations kmem_fops = {
314
        memory_lseek,
315
        read_kmem,
316
        write_kmem,
317
        NULL,           /* kmem_readdir */
318
        NULL,           /* kmem_select */
319
        NULL,           /* kmem_ioctl */
320
        mmap_kmem,
321
        NULL,           /* no special open code */
322
        NULL,           /* no special release code */
323
        NULL            /* fsync */
324
};
325
 
326
static struct file_operations null_fops = {
327
        null_lseek,
328
        read_null,
329
        write_null,
330
        NULL,           /* null_readdir */
331
        NULL,           /* null_select */
332
        NULL,           /* null_ioctl */
333
        NULL,           /* null_mmap */
334
        NULL,           /* no special open code */
335
        NULL,           /* no special release code */
336
        NULL            /* fsync */
337
};
338
 
339
static struct file_operations port_fops = {
340
        memory_lseek,
341
        read_port,
342
        write_port,
343
        NULL,           /* port_readdir */
344
        NULL,           /* port_select */
345
        NULL,           /* port_ioctl */
346
        NULL,           /* port_mmap */
347
        NULL,           /* no special open code */
348
        NULL,           /* no special release code */
349
        NULL            /* fsync */
350
};
351
 
352
static struct file_operations zero_fops = {
353
        zero_lseek,
354
        read_zero,
355
        write_zero,
356
        NULL,           /* zero_readdir */
357
        NULL,           /* zero_select */
358
        NULL,           /* zero_ioctl */
359
        mmap_zero,
360
        NULL,           /* no special open code */
361
        NULL            /* no special release code */
362
};
363
 
364
static struct file_operations full_fops = {
365
        memory_lseek,
366
        read_full,
367
        write_full,
368
        NULL,           /* full_readdir */
369
        NULL,           /* full_select */
370
        NULL,           /* full_ioctl */
371
        NULL,           /* full_mmap */
372
        NULL,           /* no special open code */
373
        NULL            /* no special release code */
374
};
375
 
376
static int memory_open(struct inode * inode, struct file * filp)
377
{
378
        switch (MINOR(inode->i_rdev)) {
379
                case 0:
380
                        filp->f_op = &ram_fops;
381
                        break;
382
                case 1:
383
                        filp->f_op = &mem_fops;
384
                        break;
385
                case 2:
386
                        filp->f_op = &kmem_fops;
387
                        break;
388
                case 3:
389
                        filp->f_op = &null_fops;
390
                        break;
391
                case 4:
392
                        filp->f_op = &port_fops;
393
                        break;
394
                case 5:
395
                        filp->f_op = &zero_fops;
396
                        break;
397
                case 7:
398
                        filp->f_op = &full_fops;
399
                        break;
400
                case 8:
401
                        filp->f_op = &random_fops;
402
                        break;
403
                case 9:
404
                        filp->f_op = &urandom_fops;
405
                        break;
406
                case 128:
407
                        filp->f_op = &fb_fops;
408
                        break;
409
                default:
410
                        return -ENXIO;
411
        }
412
        if (filp->f_op && filp->f_op->open)
413
                return filp->f_op->open(inode,filp);
414
        return 0;
415
}
416
 
417
static struct file_operations memory_fops = {
418
        NULL,           /* lseek */
419
        NULL,           /* read */
420
        NULL,           /* write */
421
        NULL,           /* readdir */
422
        NULL,           /* select */
423
        NULL,           /* ioctl */
424
        NULL,           /* mmap */
425
        memory_open,    /* just a selector for the real open */
426
        NULL,           /* release */
427
        NULL            /* fsync */
428
};
429
 
430
int chr_dev_init(void)
431
{
432
        if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
433
                printk("unable to get major %d for memory devs\n", MEM_MAJOR);
434
        rand_initialize();
435
        tty_init();
436
 
437
#ifdef CONFIG_PRINTER
438
        lp_init();
439
#endif
440
#if defined(CONFIG_MOUSE) || defined(CONFIG_SOFT_WATCHDOG)
441
        misc_init();
442
#endif
443
#ifdef CONFIG_SOUND
444
        soundcard_init();
445
#endif
446
        return 0;
447
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.