root/kernel/chr_drv/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_core
  4. read_mem
  5. write_mem
  6. mmap_mem
  7. read_port
  8. write_port
  9. read_null
  10. write_null
  11. read_zero
  12. mmap_zero
  13. null_lseek
  14. memory_lseek
  15. memory_open
  16. chr_dev_init

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

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