root/drivers/char/mem.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_ram
  2. write_ram
  3. read_mem
  4. write_mem
  5. mmap_mem
  6. read_kmem
  7. read_port
  8. write_port
  9. read_null
  10. write_null
  11. read_zero
  12. mmap_zero
  13. read_full
  14. write_full
  15. null_lseek
  16. memory_lseek
  17. memory_open
  18. chr_dev_init

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

/* [previous][next][first][last][top][bottom][index][help] */