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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [mem.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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