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

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