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. mem_lseek
  10. mem_read
  11. mem_write
  12. mem_readdir
  13. chr_dev_init

   1 /*
   2  *  linux/kernel/chr_drv/mem.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 #include <errno.h>
   8 #include <sys/types.h>
   9 
  10 #include <linux/sched.h>
  11 #include <linux/kernel.h>
  12 #include <linux/tty.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                 pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
  40                 if (!((pte = *((unsigned long *) pde)) & 1))
  41                         break;
  42                 pte &= 0xfffff000;
  43                 pte += (addr >> 10) & 0xffc;
  44                 if (((page = *((unsigned long *) pte)) & 1) == 0)
  45                         break;
  46 /*
  47                 if ((page & 2) == 0)
  48                         un_wp_page((unsigned long *) pte);
  49 */
  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                 pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
  77                 if (!((pte = *((unsigned long *) pde)) & 1))
  78                         break;
  79                 pte &= 0xfffff000;
  80                 pte += (addr >> 10) & 0xffc;
  81                 if (((page = *((unsigned long *) pte)) & 1) == 0)
  82                         break;
  83                 if ((page & 2) == 0)
  84                         un_wp_page((unsigned long *) pte);
  85                 page &= 0xfffff000;
  86                 page += addr & 0xfff;
  87                 i = 4096-(addr & 0xfff);
  88                 if (i > count)
  89                         i = count;
  90                 memcpy_fromfs((void *) page,tmp,i);
  91                 addr += i;
  92                 tmp += i;
  93                 count -= i;
  94         }
  95         file->f_pos = addr;
  96         return tmp-buf;
  97 }
  98 
  99 static int read_kmem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         unsigned long p = file->f_pos;
 102 
 103         if (count < 0)
 104                 return -EINVAL;
 105         if (p >= HIGH_MEMORY)
 106                 return 0;
 107         if (count > HIGH_MEMORY - p)
 108                 count = HIGH_MEMORY - p;
 109         memcpy_tofs(buf,(void *) p,count);
 110         file->f_pos += count;
 111         return count;
 112 }
 113 
 114 static int write_kmem(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         unsigned long p = file->f_pos;
 117 
 118         if (count < 0)
 119                 return -EINVAL;
 120         if (p >= HIGH_MEMORY)
 121                 return 0;
 122         if (count > HIGH_MEMORY - p)
 123                 count = HIGH_MEMORY - p;
 124         memcpy_fromfs((void *) p,buf,count);
 125         file->f_pos += count;
 126         return count;
 127 }
 128 
 129 static int read_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         unsigned int i = file->f_pos;
 132         char * tmp = buf;
 133 
 134         while (count-- > 0 && i < 65536) {
 135                 put_fs_byte(inb(i),tmp);
 136                 i++;
 137                 tmp++;
 138         }
 139         file->f_pos = i;
 140         return tmp-buf;
 141 }
 142 
 143 static int write_port(struct inode * inode,struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         unsigned int i = file->f_pos;
 146         char * tmp = buf;
 147 
 148         while (count-- > 0 && i < 65536) {
 149                 outb(get_fs_byte(tmp),i);
 150                 i++;
 151                 tmp++;
 152         }
 153         file->f_pos = i;
 154         return tmp-buf;
 155 }
 156 
 157 /*
 158  * The memory devices use the full 32 bits of the offset, and so we cannot
 159  * check against negative addresses: they are ok. The return value is weird,
 160  * though, in that case (0).
 161  *
 162  * also note that seeking relative to the "end of file" isn't supported:
 163  * it has no meaning, so it returns -EINVAL.
 164  */
 165 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167         switch (orig) {
 168                 case 0:
 169                         file->f_pos = offset;
 170                         return file->f_pos;
 171                 case 1:
 172                         file->f_pos += offset;
 173                         return file->f_pos;
 174                 default:
 175                         return -EINVAL;
 176         }
 177         if (file->f_pos < 0)
 178                 return 0;
 179         return file->f_pos;
 180 }
 181 
 182 static int mem_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184         switch (MINOR(inode->i_rdev)) {
 185                 case 0:
 186                         return read_ram(inode,file,buf,count);
 187                 case 1:
 188                         return read_mem(inode,file,buf,count);
 189                 case 2:
 190                         return read_kmem(inode,file,buf,count);
 191                 case 3:
 192                         return 0;       /* /dev/null */
 193                 case 4:
 194                         return read_port(inode,file,buf,count);
 195                 default:
 196                         return -ENODEV;
 197         }
 198 }
 199 
 200 static int mem_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         switch (MINOR(inode->i_rdev)) {
 203                 case 0:
 204                         return write_ram(inode,file,buf,count);
 205                 case 1:
 206                         return write_mem(inode,file,buf,count);
 207                 case 2:
 208                         return write_kmem(inode,file,buf,count);
 209                 case 3:
 210                         return count;   /* /dev/null */
 211                 case 4:
 212                         return write_port(inode,file,buf,count);
 213                 default:
 214                         return -ENODEV;
 215         }
 216 }
 217 
 218 static int mem_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220         return -ENOTDIR;
 221 }
 222 
 223 static struct file_operations mem_fops = {
 224         mem_lseek,
 225         mem_read,
 226         mem_write,
 227         mem_readdir,
 228         NULL,           /* mem_close */
 229         NULL,           /* mem_select */
 230         NULL            /* mem_ioctl */
 231 };
 232 
 233 void chr_dev_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         chrdev_fops[1] = &mem_fops;
 236         tty_init();
 237         lp_init();
 238 }

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