~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/mem.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/char/mem.c
  3  *
  4  *  Copyright (C) 1991, 1992  Linus Torvalds
  5  *
  6  *  Added devfs support. 
  7  *    Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
  8  *  Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
  9  */
 10 
 11 #include <linux/config.h>
 12 #include <linux/mm.h>
 13 #include <linux/miscdevice.h>
 14 #include <linux/tpqic02.h>
 15 #include <linux/ftape.h>
 16 #include <linux/malloc.h>
 17 #include <linux/vmalloc.h>
 18 #include <linux/mman.h>
 19 #include <linux/random.h>
 20 #include <linux/init.h>
 21 #include <linux/raw.h>
 22 #include <linux/capability.h>
 23 
 24 #include <asm/uaccess.h>
 25 #include <asm/io.h>
 26 #include <asm/pgalloc.h>
 27 
 28 #ifdef CONFIG_I2C
 29 extern int i2c_init_all(void);
 30 #endif
 31 #ifdef CONFIG_ISDN
 32 int isdn_init(void);
 33 #endif
 34 #ifdef CONFIG_VIDEO_DEV
 35 extern int videodev_init(void);
 36 #endif
 37 #ifdef CONFIG_FB
 38 extern void fbmem_init(void);
 39 #endif
 40 #ifdef CONFIG_PROM_CONSOLE
 41 extern void prom_con_init(void);
 42 #endif
 43 #ifdef CONFIG_MDA_CONSOLE
 44 extern void mda_console_init(void);
 45 #endif
 46 #if defined(CONFIG_ADB)
 47 extern void adbdev_init(void);
 48 #endif
 49      
 50 static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
 51                             const char * buf, size_t count, loff_t *ppos)
 52 {
 53         ssize_t written;
 54 
 55         written = 0;
 56 #if defined(__sparc__) || defined(__mc68000__)
 57         /* we don't have page 0 mapped on sparc and m68k.. */
 58         if (realp < PAGE_SIZE) {
 59                 unsigned long sz = PAGE_SIZE-realp;
 60                 if (sz > count) sz = count; 
 61                 /* Hmm. Do something? */
 62                 buf+=sz;
 63                 p+=sz;
 64                 count-=sz;
 65                 written+=sz;
 66         }
 67 #endif
 68         if (copy_from_user(p, buf, count))
 69                 return -EFAULT;
 70         written += count;
 71         *ppos += written;
 72         return written;
 73 }
 74 
 75 
 76 /*
 77  * This funcion reads the *physical* memory. The f_pos points directly to the 
 78  * memory location. 
 79  */
 80 static ssize_t read_mem(struct file * file, char * buf,
 81                         size_t count, loff_t *ppos)
 82 {
 83         unsigned long p = *ppos;
 84         unsigned long end_mem;
 85         ssize_t read;
 86         
 87         end_mem = __pa(high_memory);
 88         if (p >= end_mem)
 89                 return 0;
 90         if (count > end_mem - p)
 91                 count = end_mem - p;
 92         read = 0;
 93 #if defined(__sparc__) || defined(__mc68000__)
 94         /* we don't have page 0 mapped on sparc and m68k.. */
 95         if (p < PAGE_SIZE) {
 96                 unsigned long sz = PAGE_SIZE-p;
 97                 if (sz > count) 
 98                         sz = count; 
 99                 if (sz > 0) {
100                         if (clear_user(buf, sz))
101                                 return -EFAULT;
102                         buf += sz; 
103                         p += sz; 
104                         count -= sz; 
105                         read += sz; 
106                 }
107         }
108 #endif
109         if (copy_to_user(buf, __va(p), count))
110                 return -EFAULT;
111         read += count;
112         *ppos += read;
113         return read;
114 }
115 
116 static ssize_t write_mem(struct file * file, const char * buf, 
117                          size_t count, loff_t *ppos)
118 {
119         unsigned long p = *ppos;
120         unsigned long end_mem;
121 
122         end_mem = __pa(high_memory);
123         if (p >= end_mem)
124                 return 0;
125         if (count > end_mem - p)
126                 count = end_mem - p;
127         return do_write_mem(file, __va(p), p, buf, count, ppos);
128 }
129 
130 #ifndef pgprot_noncached
131 
132 /*
133  * This should probably be per-architecture in <asm/pgtable.h>
134  */
135 static inline pgprot_t pgprot_noncached(pgprot_t _prot)
136 {
137         unsigned long prot = pgprot_val(_prot);
138 
139 #if defined(__i386__)
140         /* On PPro and successors, PCD alone doesn't always mean 
141             uncached because of interactions with the MTRRs. PCD | PWT
142             means definitely uncached. */ 
143         if (boot_cpu_data.x86 > 3)
144                 prot |= _PAGE_PCD | _PAGE_PWT;
145 #elif defined(__powerpc__)
146         prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
147 #elif defined(__mc68000__)
148 #ifdef SUN3_PAGE_NOCACHE
149         if (MMU_IS_SUN3)
150                 prot |= SUN3_PAGE_NOCACHE;
151         else
152 #endif
153         if (MMU_IS_851 || MMU_IS_030)
154                 prot |= _PAGE_NOCACHE030;
155         /* Use no-cache mode, serialized */
156         else if (MMU_IS_040 || MMU_IS_060)
157                 prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
158 #elif defined(__mips__)
159         prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
160 #elif defined(__arm__) && defined(CONFIG_CPU_32)
161         /* Turn off caching for all I/O areas */
162         prot &= ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE);
163 #endif
164 
165         return __pgprot(prot);
166 }
167 
168 #endif /* !pgprot_noncached */
169 
170 /*
171  * Architectures vary in how they handle caching for addresses 
172  * outside of main memory.
173  */
174 static inline int noncached_address(unsigned long addr)
175 {
176 #if defined(__i386__)
177         /* 
178          * On the PPro and successors, the MTRRs are used to set
179          * memory types for physical addresses outside main memory, 
180          * so blindly setting PCD or PWT on those pages is wrong.
181          * For Pentiums and earlier, the surround logic should disable 
182          * caching for the high addresses through the KEN pin, but
183          * we maintain the tradition of paranoia in this code.
184          */
185         return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ||
186                   test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ||
187                   test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ||
188                   test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) )
189           && addr >= __pa(high_memory);
190 #else
191         return addr >= __pa(high_memory);
192 #endif
193 }
194 
195 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
196 {
197         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
198 
199         /*
200          * Accessing memory above the top the kernel knows about or
201          * through a file pointer that was marked O_SYNC will be
202          * done non-cached.
203          */
204         if (noncached_address(offset) || (file->f_flags & O_SYNC))
205                 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
206 
207         /* Don't try to swap out physical pages.. */
208         vma->vm_flags |= VM_RESERVED;
209 
210         /*
211          * Don't dump addresses that are not real memory to a core file.
212          */
213         if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
214                 vma->vm_flags |= VM_IO;
215 
216         if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
217                              vma->vm_page_prot))
218                 return -EAGAIN;
219         return 0;
220 }
221 
222 /*
223  * This function reads the *virtual* memory as seen by the kernel.
224  */
225 static ssize_t read_kmem(struct file *file, char *buf, 
226                          size_t count, loff_t *ppos)
227 {
228         unsigned long p = *ppos;
229         ssize_t read = 0;
230         ssize_t virtr = 0;
231         char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
232                 
233         if (p < (unsigned long) high_memory) {
234                 read = count;
235                 if (count > (unsigned long) high_memory - p)
236                         read = (unsigned long) high_memory - p;
237 
238 #if defined(__sparc__) || defined(__mc68000__)
239                 /* we don't have page 0 mapped on sparc and m68k.. */
240                 if (p < PAGE_SIZE && read > 0) {
241                         size_t tmp = PAGE_SIZE - p;
242                         if (tmp > read) tmp = read;
243                         if (clear_user(buf, tmp))
244                                 return -EFAULT;
245                         buf += tmp;
246                         p += tmp;
247                         read -= tmp;
248                         count -= tmp;
249                 }
250 #endif
251                 if (copy_to_user(buf, (char *)p, read))
252                         return -EFAULT;
253                 p += read;
254                 buf += read;
255                 count -= read;
256         }
257 
258         if (count > 0) {
259                 kbuf = (char *)__get_free_page(GFP_KERNEL);
260                 if (!kbuf)
261                         return -ENOMEM;
262                 while (count > 0) {
263                         int len = count;
264 
265                         if (len > PAGE_SIZE)
266                                 len = PAGE_SIZE;
267                         len = vread(kbuf, (char *)p, len);
268                         if (len && copy_to_user(buf, kbuf, len)) {
269                                 free_page((unsigned long)kbuf);
270                                 return -EFAULT;
271                         }
272                         count -= len;
273                         buf += len;
274                         virtr += len;
275                         p += len;
276                 }
277                 free_page((unsigned long)kbuf);
278         }
279         *ppos = p;
280         return virtr + read;
281 }
282 
283 /*
284  * This function writes to the *virtual* memory as seen by the kernel.
285  */
286 static ssize_t write_kmem(struct file * file, const char * buf, 
287                           size_t count, loff_t *ppos)
288 {
289         unsigned long p = *ppos;
290 
291         if (p >= (unsigned long) high_memory)
292                 return 0;
293         if (count > (unsigned long) high_memory - p)
294                 count = (unsigned long) high_memory - p;
295         return do_write_mem(file, (void*)p, p, buf, count, ppos);
296 }
297 
298 #if !defined(__mc68000__)
299 static ssize_t read_port(struct file * file, char * buf,
300                          size_t count, loff_t *ppos)
301 {
302         unsigned long i = *ppos;
303         char *tmp = buf;
304 
305         if (verify_area(VERIFY_WRITE,buf,count))
306                 return -EFAULT; 
307         while (count-- > 0 && i < 65536) {
308                 if (__put_user(inb(i),tmp) < 0) 
309                         return -EFAULT;  
310                 i++;
311                 tmp++;
312         }
313         *ppos = i;
314         return tmp-buf;
315 }
316 
317 static ssize_t write_port(struct file * file, const char * buf,
318                           size_t count, loff_t *ppos)
319 {
320         unsigned long i = *ppos;
321         const char * tmp = buf;
322 
323         if (verify_area(VERIFY_READ,buf,count))
324                 return -EFAULT;
325         while (count-- > 0 && i < 65536) {
326                 char c;
327                 if (__get_user(c, tmp)) 
328                         return -EFAULT; 
329                 outb(c,i);
330                 i++;
331                 tmp++;
332         }
333         *ppos = i;
334         return tmp-buf;
335 }
336 #endif
337 
338 static ssize_t read_null(struct file * file, char * buf,
339                          size_t count, loff_t *ppos)
340 {
341         return 0;
342 }
343 
344 static ssize_t write_null(struct file * file, const char * buf,
345                           size_t count, loff_t *ppos)
346 {
347         return count;
348 }
349 
350 /*
351  * For fun, we are using the MMU for this.
352  */
353 static inline size_t read_zero_pagealigned(char * buf, size_t size)
354 {
355         struct mm_struct *mm;
356         struct vm_area_struct * vma;
357         unsigned long addr=(unsigned long)buf;
358 
359         mm = current->mm;
360         /* Oops, this was forgotten before. -ben */
361         down(&mm->mmap_sem);
362 
363         /* For private mappings, just map in zero pages. */
364         for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
365                 unsigned long count;
366 
367                 if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
368                         goto out_up;
369                 if (vma->vm_flags & VM_SHARED)
370                         break;
371                 count = vma->vm_end - addr;
372                 if (count > size)
373                         count = size;
374 
375                 flush_cache_range(mm, addr, addr + count);
376                 zap_page_range(mm, addr, count);
377                 zeromap_page_range(addr, count, PAGE_COPY);
378                 flush_tlb_range(mm, addr, addr + count);
379 
380                 size -= count;
381                 buf += count;
382                 addr += count;
383                 if (size == 0)
384                         goto out_up;
385         }
386 
387         up(&mm->mmap_sem);
388         
389         /* The shared case is hard. Let's do the conventional zeroing. */ 
390         do {
391                 unsigned long unwritten = clear_user(buf, PAGE_SIZE);
392                 if (unwritten)
393                         return size + unwritten - PAGE_SIZE;
394                 if (current->need_resched)
395                         schedule();
396                 buf += PAGE_SIZE;
397                 size -= PAGE_SIZE;
398         } while (size);
399 
400         return size;
401 out_up:
402         up(&mm->mmap_sem);
403         return size;
404 }
405 
406 static ssize_t read_zero(struct file * file, char * buf, 
407                          size_t count, loff_t *ppos)
408 {
409         unsigned long left, unwritten, written = 0;
410 
411         if (!count)
412                 return 0;
413 
414         if (!access_ok(VERIFY_WRITE, buf, count))
415                 return -EFAULT;
416 
417         left = count;
418 
419         /* do we want to be clever? Arbitrary cut-off */
420         if (count >= PAGE_SIZE*4) {
421                 unsigned long partial;
422 
423                 /* How much left of the page? */
424                 partial = (PAGE_SIZE-1) & -(unsigned long) buf;
425                 unwritten = clear_user(buf, partial);
426                 written = partial - unwritten;
427                 if (unwritten)
428                         goto out;
429                 left -= partial;
430                 buf += partial;
431                 unwritten = read_zero_pagealigned(buf, left & PAGE_MASK);
432                 written += (left & PAGE_MASK) - unwritten;
433                 if (unwritten)
434                         goto out;
435                 buf += left & PAGE_MASK;
436                 left &= ~PAGE_MASK;
437         }
438         unwritten = clear_user(buf, left);
439         written += left - unwritten;
440 out:
441         return written ? written : -EFAULT;
442 }
443 
444 static int mmap_zero(struct file * file, struct vm_area_struct * vma)
445 {
446         if (vma->vm_flags & VM_SHARED)
447                 return shmem_zero_setup(vma);
448         if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
449                 return -EAGAIN;
450         return 0;
451 }
452 
453 static ssize_t write_full(struct file * file, const char * buf,
454                           size_t count, loff_t *ppos)
455 {
456         return -ENOSPC;
457 }
458 
459 /*
460  * Special lseek() function for /dev/null and /dev/zero.  Most notably, you
461  * can fopen() both devices with "a" now.  This was previously impossible.
462  * -- SRB.
463  */
464 
465 static loff_t null_lseek(struct file * file, loff_t offset, int orig)
466 {
467         return file->f_pos = 0;
468 }
469 
470 /*
471  * The memory devices use the full 32/64 bits of the offset, and so we cannot
472  * check against negative addresses: they are ok. The return value is weird,
473  * though, in that case (0).
474  *
475  * also note that seeking relative to the "end of file" isn't supported:
476  * it has no meaning, so it returns -EINVAL.
477  */
478 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
479 {
480         switch (orig) {
481                 case 0:
482                         file->f_pos = offset;
483                         return file->f_pos;
484                 case 1:
485                         file->f_pos += offset;
486                         return file->f_pos;
487                 default:
488                         return -EINVAL;
489         }
490 }
491 
492 static int open_port(struct inode * inode, struct file * filp)
493 {
494         return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
495 }
496 
497 #define mmap_kmem       mmap_mem
498 #define zero_lseek      null_lseek
499 #define full_lseek      null_lseek
500 #define write_zero      write_null
501 #define read_full       read_zero
502 #define open_mem        open_port
503 #define open_kmem       open_mem
504 
505 static struct file_operations mem_fops = {
506         llseek:         memory_lseek,
507         read:           read_mem,
508         write:          write_mem,
509         mmap:           mmap_mem,
510         open:           open_mem,
511 };
512 
513 static struct file_operations kmem_fops = {
514         llseek:         memory_lseek,
515         read:           read_kmem,
516         write:          write_kmem,
517         mmap:           mmap_kmem,
518         open:           open_kmem,
519 };
520 
521 static struct file_operations null_fops = {
522         llseek:         null_lseek,
523         read:           read_null,
524         write:          write_null,
525 };
526 
527 #if !defined(__mc68000__)
528 static struct file_operations port_fops = {
529         llseek:         memory_lseek,
530         read:           read_port,
531         write:          write_port,
532         open:           open_port,
533 };
534 #endif
535 
536 static struct file_operations zero_fops = {
537         llseek:         zero_lseek,
538         read:           read_zero,
539         write:          write_zero,
540         mmap:           mmap_zero,
541 };
542 
543 static struct file_operations full_fops = {
544         llseek:         full_lseek,
545         read:           read_full,
546         write:          write_full,
547 };
548 
549 static int memory_open(struct inode * inode, struct file * filp)
550 {
551         switch (MINOR(inode->i_rdev)) {
552                 case 1:
553                         filp->f_op = &mem_fops;
554                         break;
555                 case 2:
556                         filp->f_op = &kmem_fops;
557                         break;
558                 case 3:
559                         filp->f_op = &null_fops;
560                         break;
561 #if !defined(__mc68000__)
562                 case 4:
563                         filp->f_op = &port_fops;
564                         break;
565 #endif
566                 case 5:
567                         filp->f_op = &zero_fops;
568                         break;
569                 case 7:
570                         filp->f_op = &full_fops;
571                         break;
572                 case 8:
573                         filp->f_op = &random_fops;
574                         break;
575                 case 9:
576                         filp->f_op = &urandom_fops;
577                         break;
578                 default:
579                         return -ENXIO;
580         }
581         if (filp->f_op && filp->f_op->open)
582                 return filp->f_op->open(inode,filp);
583         return 0;
584 }
585 
586 void __init memory_devfs_register (void)
587 {
588     /*  These are never unregistered  */
589     static const struct {
590         unsigned short minor;
591         char *name;
592         umode_t mode;
593         struct file_operations *fops;
594     } list[] = { /* list of minor devices */
595         {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
596         {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
597         {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
598         {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
599         {5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
600         {7, "full",    S_IRUGO | S_IWUGO,           &full_fops},
601         {8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
602         {9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops}
603     };
604     int i;
605 
606     for (i=0; i<(sizeof(list)/sizeof(*list)); i++)
607         devfs_register (NULL, list[i].name, DEVFS_FL_NONE,
608                         MEM_MAJOR, list[i].minor,
609                         list[i].mode | S_IFCHR,
610                         list[i].fops, NULL);
611 }
612 
613 static struct file_operations memory_fops = {
614         open:           memory_open,    /* just a selector for the real open */
615 };
616 
617 int __init chr_dev_init(void)
618 {
619         if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops))
620                 printk("unable to get major %d for memory devs\n", MEM_MAJOR);
621         memory_devfs_register();
622         rand_initialize();
623         raw_init();
624 #ifdef CONFIG_I2C
625         i2c_init_all();
626 #endif
627 #if defined (CONFIG_FB)
628         fbmem_init();
629 #endif
630 #if defined (CONFIG_PROM_CONSOLE)
631         prom_con_init();
632 #endif
633 #if defined (CONFIG_MDA_CONSOLE)
634         mda_console_init();
635 #endif
636         tty_init();
637 #ifdef CONFIG_PRINTER
638         lp_init();
639 #endif
640 #ifdef CONFIG_M68K_PRINTER
641         lp_m68k_init();
642 #endif
643         misc_init();
644 #if CONFIG_QIC02_TAPE
645         qic02_tape_init();
646 #endif
647 #if CONFIG_ISDN
648         isdn_init();
649 #endif
650 #ifdef CONFIG_FTAPE
651         ftape_init();
652 #endif
653 #if defined(CONFIG_ADB)
654         adbdev_init();
655 #endif
656 #ifdef CONFIG_VIDEO_DEV
657         videodev_init();
658 #endif
659         return 0;
660 }
661 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.