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_mem
  4. write_mem
  5. read_kmem
  6. write_kmem
  7. read_port
  8. write_port
  9. read_zero
  10. mem_lseek
  11. mem_read
  12. mem_write
  13. 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 <asm/segment.h>
  15 #include <asm/io.h>
  16 
  17 static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  18 {
  19         return -EIO;
  20 }
  21 
  22 static int write_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 read_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         unsigned long addr;
  30         char *tmp;
  31         unsigned long pde, pte, page;
  32         int i;
  33 
  34         if (count < 0)
  35                 return -EINVAL;
  36         addr = file->f_pos;
  37         tmp = buf;
  38         while (count > 0) {
  39                 if (current->signal & ~current->blocked)
  40                         break;
  41                 pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
  42                 pte = *(unsigned long *) pde;
  43                 if (!(pte & PAGE_PRESENT))
  44                         break;
  45                 pte &= 0xfffff000;
  46                 pte += (addr >> 10) & 0xffc;
  47                 page = *(unsigned long *) pte;
  48                 if (!(page & 1))
  49                         break;
  50                 page &= 0xfffff000;
  51                 page += addr & 0xfff;
  52                 i = 4096-(addr & 0xfff);
  53                 if (i > count)
  54                         i = count;
  55                 memcpy_tofs(tmp,(void *) page,i);
  56                 addr += i;
  57                 tmp += i;
  58                 count -= i;
  59         }
  60         file->f_pos = addr;
  61         return tmp-buf;
  62 }
  63 
  64 static int write_mem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         unsigned long addr;
  67         char *tmp;
  68         unsigned long pde, pte, page;
  69         int i;
  70 
  71         if (count < 0)
  72                 return -EINVAL;
  73         addr = file->f_pos;
  74         tmp = buf;
  75         while (count > 0) {
  76                 if (current->signal & ~current->blocked)
  77                         break;
  78                 pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
  79                 pte = *(unsigned long *) pde;
  80                 if (!(pte & PAGE_PRESENT))
  81                         break;
  82                 pte &= 0xfffff000;
  83                 pte += (addr >> 10) & 0xffc;
  84                 page = *(unsigned long *) pte;
  85                 if (!(page & PAGE_PRESENT))
  86                         break;
  87                 if (!(page & 2)) {
  88                         do_wp_page(0,addr,current,0);
  89                         continue;
  90                 }
  91                 page &= 0xfffff000;
  92                 page += addr & 0xfff;
  93                 i = 4096-(addr & 0xfff);
  94                 if (i > count)
  95                         i = count;
  96                 memcpy_fromfs((void *) page,tmp,i);
  97                 addr += i;
  98                 tmp += i;
  99                 count -= i;
 100         }
 101         file->f_pos = addr;
 102         if (tmp != buf)
 103                 return tmp-buf;
 104         if (current->signal & ~current->blocked)
 105                 return -ERESTARTSYS;
 106         return 0;
 107 }
 108 
 109 static int read_kmem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         unsigned long p = file->f_pos;
 112 
 113         if (count < 0)
 114                 return -EINVAL;
 115         if (p >= high_memory)
 116                 return 0;
 117         if (count > high_memory - p)
 118                 count = high_memory - p;
 119         memcpy_tofs(buf,(void *) p,count);
 120         file->f_pos += count;
 121         return count;
 122 }
 123 
 124 static int write_kmem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         unsigned long p = file->f_pos;
 127 
 128         if (count < 0)
 129                 return -EINVAL;
 130         if (p >= high_memory)
 131                 return 0;
 132         if (count > high_memory - p)
 133                 count = high_memory - p;
 134         memcpy_fromfs((void *) p,buf,count);
 135         file->f_pos += count;
 136         return count;
 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_zero(struct inode *node,struct file *file,char *buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         int left;
 170 
 171         for (left = count; left > 0; left--) {
 172                 put_fs_byte(0,buf);
 173                 buf++;
 174         }
 175         return count;
 176 }
 177 
 178 /*
 179  * The memory devices use the full 32 bits of the offset, and so we cannot
 180  * check against negative addresses: they are ok. The return value is weird,
 181  * though, in that case (0).
 182  *
 183  * also note that seeking relative to the "end of file" isn't supported:
 184  * it has no meaning, so it returns -EINVAL.
 185  */
 186 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         switch (orig) {
 189                 case 0:
 190                         file->f_pos = offset;
 191                         return file->f_pos;
 192                 case 1:
 193                         file->f_pos += offset;
 194                         return file->f_pos;
 195                 default:
 196                         return -EINVAL;
 197         }
 198         if (file->f_pos < 0)
 199                 return 0;
 200         return file->f_pos;
 201 }
 202 
 203 static int mem_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205         switch (MINOR(inode->i_rdev)) {
 206                 case 0:
 207                         return read_ram(inode,file,buf,count);
 208                 case 1:
 209                         return read_mem(inode,file,buf,count);
 210                 case 2:
 211                         return read_kmem(inode,file,buf,count);
 212                 case 3:
 213                         return 0;       /* /dev/null */
 214                 case 4:
 215                         return read_port(inode,file,buf,count);
 216                 case 5:
 217                         return read_zero(inode,file,buf,count);
 218                 default:
 219                         return -ENODEV;
 220         }
 221 }
 222 
 223 static int mem_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         switch (MINOR(inode->i_rdev)) {
 226                 case 0:
 227                         return write_ram(inode,file,buf,count);
 228                 case 1:
 229                         return write_mem(inode,file,buf,count);
 230                 case 2:
 231                         return write_kmem(inode,file,buf,count);
 232                 case 3:
 233                         return count;   /* /dev/null */
 234                 case 4:
 235                         return write_port(inode,file,buf,count);
 236                 case 5:
 237                         return count; /* /dev/zero */
 238                 default:
 239                         return -ENODEV;
 240         }
 241 }
 242 
 243 static struct file_operations mem_fops = {
 244         mem_lseek,
 245         mem_read,
 246         mem_write,
 247         NULL,           /* mem_readdir */
 248         NULL,           /* mem_select */
 249         NULL,           /* mem_ioctl */
 250         NULL,           /* no special open code */
 251         NULL            /* no special release code */
 252 };
 253 
 254 long chr_dev_init(long mem_start, long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         chrdev_fops[1] = &mem_fops;
 257         mem_start = tty_init(mem_start);
 258         mem_start = lp_init(mem_start);
 259         mem_start = mouse_init(mem_start);
 260         return mem_start;
 261 }

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