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 
  14 #include <linux/user.h>
  15 #include <linux/a.out.h>
  16 #include <linux/string.h>
  17 
  18 #include <asm/segment.h>
  19 #include <asm/io.h>
  20 
  21 extern long soundcard_init(long mem_start);
  22 
  23 static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         return -EIO;
  26 }
  27 
  28 static int write_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 read_core(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35         unsigned long p = file->f_pos;
  36         int read;
  37         int count1;
  38         char * pnt;
  39         struct user dump;
  40 
  41         memset(&dump, 0, sizeof(struct user));
  42         dump.magic = CMAGIC;
  43         dump.u_dsize = high_memory >> 12;
  44 
  45         if (count < 0)
  46                 return -EINVAL;
  47         if (p >= high_memory)
  48                 return 0;
  49         if (count > high_memory - p)
  50                 count = high_memory - p;
  51         read = 0;
  52 
  53         if (p < sizeof(struct user) && count > 0) {
  54                 count1 = count;
  55                 if (p + count1 > sizeof(struct user))
  56                         count1 = sizeof(struct user)-p;
  57                 pnt = (char *) &dump + p;
  58                 memcpy_tofs(buf,(void *) pnt, count1);
  59                 buf += count1;
  60                 p += count1;
  61                 count -= count1;
  62                 read += count1;
  63         }
  64 
  65         while (p < (4096 + 4096) && count > 0) {
  66                 put_fs_byte(0,buf);
  67                 buf++;
  68                 p++;
  69                 count--;
  70                 read++;
  71         }
  72         memcpy_tofs(buf,(void *) (p - 4096),count);
  73         read += count;
  74         file->f_pos += read;
  75         return read;
  76 }
  77 
  78 static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         unsigned long p = file->f_pos;
  81         int read;
  82 
  83         if (count < 0)
  84                 return -EINVAL;
  85         if (p >= high_memory)
  86                 return 0;
  87         if (count > high_memory - p)
  88                 count = high_memory - p;
  89         read = 0;
  90         while (p < 4096 && count > 0) {
  91                 put_fs_byte(0,buf);
  92                 buf++;
  93                 p++;
  94                 count--;
  95                 read++;
  96         }
  97         memcpy_tofs(buf,(void *) p,count);
  98         read += count;
  99         file->f_pos += read;
 100         return read;
 101 }
 102 
 103 static int write_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         unsigned long p = file->f_pos;
 106         int written;
 107 
 108         if (count < 0)
 109                 return -EINVAL;
 110         if (p >= high_memory)
 111                 return 0;
 112         if (count > high_memory - p)
 113                 count = high_memory - p;
 114         written = 0;
 115         while (p < 4096 && count > 0) {
 116                 /* Hmm. Do something? */
 117                 buf++;
 118                 p++;
 119                 count--;
 120                 written++;
 121         }
 122         memcpy_fromfs((void *) p,buf,count);
 123         written += count;
 124         file->f_pos += written;
 125         return count;
 126 }
 127 
 128 static int mmap_mem(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 129         unsigned long addr, size_t len, int prot, unsigned long off)
 130 {
 131         if (len > high_memory || off > high_memory - len) /* avoid overflow */
 132                 return -ENXIO;
 133 
 134         if (remap_page_range(addr, off, len, prot))
 135                 return -EAGAIN;
 136         
 137         return 0;
 138 }
 139 
 140 static int read_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142         unsigned int i = file->f_pos;
 143         char * tmp = buf;
 144 
 145         while (count-- > 0 && i < 65536) {
 146                 put_fs_byte(inb(i),tmp);
 147                 i++;
 148                 tmp++;
 149         }
 150         file->f_pos = i;
 151         return tmp-buf;
 152 }
 153 
 154 static int write_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156         unsigned int i = file->f_pos;
 157         char * tmp = buf;
 158 
 159         while (count-- > 0 && i < 65536) {
 160                 outb(get_fs_byte(tmp),i);
 161                 i++;
 162                 tmp++;
 163         }
 164         file->f_pos = i;
 165         return tmp-buf;
 166 }
 167 
 168 static int read_null(struct inode * node,struct file * file,char * buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170         return 0;
 171 }
 172 
 173 static int write_null(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175         return count;
 176 }
 177 
 178 static int read_zero(struct inode * node,struct file * file,char * buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         int left;
 181 
 182         for (left = count; left > 0; left--) {
 183                 put_fs_byte(0,buf);
 184                 buf++;
 185         }
 186         return count;
 187 }
 188 
 189 static int write_zero(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         return count;
 192 }
 193 
 194 static int mmap_zero(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 195         unsigned long addr, size_t len, int prot, unsigned long off)
 196 {
 197         if (prot & PAGE_RW)
 198                 return -EINVAL;
 199         if (zeromap_page_range(addr, len, prot))
 200                 return -EAGAIN;
 201         return 0;
 202 }
 203 
 204 /*
 205  * The memory devices use the full 32 bits of the offset, and so we cannot
 206  * check against negative addresses: they are ok. The return value is weird,
 207  * though, in that case (0).
 208  *
 209  * also note that seeking relative to the "end of file" isn't supported:
 210  * it has no meaning, so it returns -EINVAL.
 211  */
 212 static int memory_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         switch (orig) {
 215                 case 0:
 216                         file->f_pos = offset;
 217                         return file->f_pos;
 218                 case 1:
 219                         file->f_pos += offset;
 220                         return file->f_pos;
 221                 default:
 222                         return -EINVAL;
 223         }
 224         if (file->f_pos < 0)
 225                 return 0;
 226         return file->f_pos;
 227 }
 228 
 229 #define read_kmem read_mem
 230 #define write_kmem write_mem
 231 #define mmap_kmem mmap_mem
 232 
 233 static struct file_operations ram_fops = {
 234         memory_lseek,
 235         read_ram,
 236         write_ram,
 237         NULL,           /* ram_readdir */
 238         NULL,           /* ram_select */
 239         NULL,           /* ram_ioctl */
 240         NULL,           /* ram_mmap */
 241         NULL,           /* no special open code */
 242         NULL            /* no special release code */
 243 };
 244 
 245 static struct file_operations mem_fops = {
 246         memory_lseek,
 247         read_mem,
 248         write_mem,
 249         NULL,           /* mem_readdir */
 250         NULL,           /* mem_select */
 251         NULL,           /* mem_ioctl */
 252         mmap_mem,
 253         NULL,           /* no special open code */
 254         NULL            /* no special release code */
 255 };
 256 
 257 static struct file_operations kmem_fops = {
 258         memory_lseek,
 259         read_kmem,
 260         write_kmem,
 261         NULL,           /* kmem_readdir */
 262         NULL,           /* kmem_select */
 263         NULL,           /* kmem_ioctl */
 264         mmap_kmem,
 265         NULL,           /* no special open code */
 266         NULL            /* no special release code */
 267 };
 268 
 269 static struct file_operations null_fops = {
 270         memory_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 };
 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 };
 292 
 293 static struct file_operations zero_fops = {
 294         memory_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 core_fops = {
 306         memory_lseek,
 307         read_core,
 308         NULL,
 309         NULL,           /* zero_readdir */
 310         NULL,           /* zero_select */
 311         NULL,           /* zero_ioctl */
 312         NULL,           /* zero_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 6:
 339                         filp->f_op = &core_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 };
 360 
 361 long chr_dev_init(long mem_start, long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 362 {
 363         if (register_chrdev(1,"mem",&memory_fops))
 364                 printk("unable to get major 1 for memory devs\n");
 365         mem_start = tty_init(mem_start);
 366         mem_start = lp_init(mem_start);
 367         mem_start = mouse_init(mem_start);
 368         mem_start = soundcard_init(mem_start);
 369         return mem_start;
 370 }

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