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. write_zero
  13. mmap_zero
  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/soundcard.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 static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  23 {
  24         return -EIO;
  25 }
  26 
  27 static int write_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 read_core(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         unsigned long p = file->f_pos;
  35         int read;
  36         int count1;
  37         char * pnt;
  38         struct user dump;
  39 
  40         memset(&dump, 0, sizeof(struct user));
  41         dump.magic = CMAGIC;
  42         dump.u_dsize = high_memory >> 12;
  43 
  44         if (count < 0)
  45                 return -EINVAL;
  46         if (p >= high_memory)
  47                 return 0;
  48         if (count > high_memory - p)
  49                 count = high_memory - p;
  50         read = 0;
  51 
  52         if (p < sizeof(struct user) && count > 0) {
  53                 count1 = count;
  54                 if (p + count1 > sizeof(struct user))
  55                         count1 = sizeof(struct user)-p;
  56                 pnt = (char *) &dump + p;
  57                 memcpy_tofs(buf,(void *) pnt, count1);
  58                 buf += count1;
  59                 p += count1;
  60                 count -= count1;
  61                 read += count1;
  62         }
  63 
  64         while (p < (4096 + 4096) && count > 0) {
  65                 put_fs_byte(0,buf);
  66                 buf++;
  67                 p++;
  68                 count--;
  69                 read++;
  70         }
  71         memcpy_tofs(buf,(void *) (p - 4096),count);
  72         read += count;
  73         file->f_pos += read;
  74         return read;
  75 }
  76 
  77 static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         unsigned long p = file->f_pos;
  80         int read;
  81 
  82         if (count < 0)
  83                 return -EINVAL;
  84         if (p >= high_memory)
  85                 return 0;
  86         if (count > high_memory - p)
  87                 count = high_memory - p;
  88         read = 0;
  89         while (p < 4096 && count > 0) {
  90                 put_fs_byte(0,buf);
  91                 buf++;
  92                 p++;
  93                 count--;
  94                 read++;
  95         }
  96         memcpy_tofs(buf,(void *) p,count);
  97         read += count;
  98         file->f_pos += read;
  99         return read;
 100 }
 101 
 102 static int write_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104         unsigned long p = file->f_pos;
 105         int written;
 106 
 107         if (count < 0)
 108                 return -EINVAL;
 109         if (p >= high_memory)
 110                 return 0;
 111         if (count > high_memory - p)
 112                 count = high_memory - p;
 113         written = 0;
 114         while (p < 4096 && count > 0) {
 115                 /* Hmm. Do something? */
 116                 buf++;
 117                 p++;
 118                 count--;
 119                 written++;
 120         }
 121         memcpy_fromfs((void *) p,buf,count);
 122         written += count;
 123         file->f_pos += written;
 124         return count;
 125 }
 126 
 127 static int mmap_mem(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 128         unsigned long addr, size_t len, int prot, unsigned long off)
 129 {
 130         if (len > high_memory || off > high_memory - len) /* avoid overflow */
 131                 return -ENXIO;
 132 
 133         if (remap_page_range(addr, off, len, prot))
 134                 return -EAGAIN;
 135         
 136         return 0;
 137 }
 138 
 139 static int read_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141         unsigned int i = file->f_pos;
 142         char * tmp = buf;
 143 
 144         while (count-- > 0 && i < 65536) {
 145                 put_fs_byte(inb(i),tmp);
 146                 i++;
 147                 tmp++;
 148         }
 149         file->f_pos = i;
 150         return tmp-buf;
 151 }
 152 
 153 static int write_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155         unsigned int i = file->f_pos;
 156         char * tmp = buf;
 157 
 158         while (count-- > 0 && i < 65536) {
 159                 outb(get_fs_byte(tmp),i);
 160                 i++;
 161                 tmp++;
 162         }
 163         file->f_pos = i;
 164         return tmp-buf;
 165 }
 166 
 167 static int read_null(struct inode * node,struct file * file,char * buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         return 0;
 170 }
 171 
 172 static int write_null(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         return count;
 175 }
 176 
 177 static int read_zero(struct inode * node,struct file * file,char * buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179         int left;
 180 
 181         for (left = count; left > 0; left--) {
 182                 put_fs_byte(0,buf);
 183                 buf++;
 184         }
 185         return count;
 186 }
 187 
 188 static int write_zero(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190         return count;
 191 }
 192 
 193 static int mmap_zero(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 194         unsigned long addr, size_t len, int prot, unsigned long off)
 195 {
 196         if (prot & PAGE_RW)
 197                 return -EINVAL;
 198         if (zeromap_page_range(addr, len, prot))
 199                 return -EAGAIN;
 200         return 0;
 201 }
 202 
 203 /*
 204  * The memory devices use the full 32 bits of the offset, and so we cannot
 205  * check against negative addresses: they are ok. The return value is weird,
 206  * though, in that case (0).
 207  *
 208  * also note that seeking relative to the "end of file" isn't supported:
 209  * it has no meaning, so it returns -EINVAL.
 210  */
 211 static int memory_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         switch (orig) {
 214                 case 0:
 215                         file->f_pos = offset;
 216                         return file->f_pos;
 217                 case 1:
 218                         file->f_pos += offset;
 219                         return file->f_pos;
 220                 default:
 221                         return -EINVAL;
 222         }
 223         if (file->f_pos < 0)
 224                 return 0;
 225         return file->f_pos;
 226 }
 227 
 228 #define read_kmem read_mem
 229 #define write_kmem write_mem
 230 #define mmap_kmem mmap_mem
 231 
 232 static struct file_operations ram_fops = {
 233         memory_lseek,
 234         read_ram,
 235         write_ram,
 236         NULL,           /* ram_readdir */
 237         NULL,           /* ram_select */
 238         NULL,           /* ram_ioctl */
 239         NULL,           /* ram_mmap */
 240         NULL,           /* no special open code */
 241         NULL            /* no special release code */
 242 };
 243 
 244 static struct file_operations mem_fops = {
 245         memory_lseek,
 246         read_mem,
 247         write_mem,
 248         NULL,           /* mem_readdir */
 249         NULL,           /* mem_select */
 250         NULL,           /* mem_ioctl */
 251         mmap_mem,
 252         NULL,           /* no special open code */
 253         NULL            /* no special release code */
 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 };
 267 
 268 static struct file_operations null_fops = {
 269         memory_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 };
 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 };
 291 
 292 static struct file_operations zero_fops = {
 293         memory_lseek,
 294         read_zero,
 295         write_zero,
 296         NULL,           /* zero_readdir */
 297         NULL,           /* zero_select */
 298         NULL,           /* zero_ioctl */
 299         mmap_zero,
 300         NULL,           /* no special open code */
 301         NULL            /* no special release code */
 302 };
 303 
 304 static struct file_operations core_fops = {
 305         memory_lseek,
 306         read_core,
 307         NULL,
 308         NULL,           /* zero_readdir */
 309         NULL,           /* zero_select */
 310         NULL,           /* zero_ioctl */
 311         NULL,           /* zero_mmap */
 312         NULL,           /* no special open code */
 313         NULL            /* no special release code */
 314 };
 315 
 316 static int memory_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318         switch (MINOR(inode->i_rdev)) {
 319                 case 0:
 320                         filp->f_op = &ram_fops;
 321                         break;
 322                 case 1:
 323                         filp->f_op = &mem_fops;
 324                         break;
 325                 case 2:
 326                         filp->f_op = &kmem_fops;
 327                         break;
 328                 case 3:
 329                         filp->f_op = &null_fops;
 330                         break;
 331                 case 4:
 332                         filp->f_op = &port_fops;
 333                         break;
 334                 case 5:
 335                         filp->f_op = &zero_fops;
 336                         break;
 337                 case 6:
 338                         filp->f_op = &core_fops;
 339                         break;
 340                 default:
 341                         return -ENODEV;
 342         }
 343         if (filp->f_op && filp->f_op->open)
 344                 return filp->f_op->open(inode,filp);
 345         return 0;
 346 }
 347 
 348 static struct file_operations memory_fops = {
 349         NULL,           /* lseek */
 350         NULL,           /* read */
 351         NULL,           /* write */
 352         NULL,           /* readdir */
 353         NULL,           /* select */
 354         NULL,           /* ioctl */
 355         NULL,           /* mmap */
 356         memory_open,    /* just a selector for the real open */
 357         NULL            /* release */
 358 };
 359 
 360 long chr_dev_init(long mem_start, long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362         if (register_chrdev(1,"mem",&memory_fops))
 363                 printk("unable to get major 1 for memory devs\n");
 364         mem_start = tty_init(mem_start);
 365         mem_start = lp_init(mem_start);
 366         mem_start = mouse_init(mem_start);
 367         mem_start = soundcard_init(mem_start);
 368         return mem_start;
 369 }

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