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

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