root/fs/char_dev.c

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

DEFINITIONS

This source file includes following definitions.
  1. tty_read
  2. tty_write
  3. lp_write
  4. put_fs_long
  5. inb
  6. get_fs_byte

   1 /*
   2  *  linux/fs/char_dev.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 
  13 #include <checkpoint.h>
  14 #include <asm/segment.h>
  15 #include <asm/io.h>
  16 
  17 extern int tty_read(unsigned minor,char * buf,int count,unsigned short flags);
  18 extern int tty_write(unsigned minor,char * buf,int count);
  19 extern int lp_write(unsigned minor,char *buf, int count);
  20 
  21 typedef (*crw_ptr)(int,unsigned,char *,int,off_t *,unsigned short);
  22 
  23 static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
  24 {
  25         return ((rw==READ)?tty_read(minor,buf,count,flags):
     /* [previous][next][first][last][top][bottom][index][help] */
  26                 tty_write(minor,buf,count));
     /* [previous][next][first][last][top][bottom][index][help] */
  27 }
  28 
  29 static int rw_lp(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
  30 {
  31         return ((rw==READ)?-EINVAL:lp_write(minor,buf,count));
     /* [previous][next][first][last][top][bottom][index][help] */
  32 }
  33 
  34 static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos, unsigned short flags)
  35 {
  36         if (current->tty<0)
  37                 return -EPERM;
  38         return rw_ttyx(rw,current->tty,buf,count,pos,flags);
  39 }
  40 
  41 static int rw_ram(int rw,char * buf, int count, off_t *pos)
  42 {
  43         return -EIO;
  44 }
  45 
  46 static int rw_mem(int rw,char * buf, int count, off_t * pos)
  47 {
  48         char *p;
  49         unsigned long pde, pte, tmp;
  50         int i = count;
  51 
  52         if (count <= 0)
  53                 return(0);
  54         /*
  55          * return EOF on nonexistant pages or pages swapped out to disk
  56          */
  57         pde = (unsigned long) pg_dir + (*pos >> 20 & 0xffc);
  58         if (((pte = *((unsigned long *) pde)) & 1) == 0)
  59                 return 0;       /* page table not present */
  60         pte &= 0xfffff000;
  61         pte += *pos >> 10 & 0xffc;
  62         if (((tmp = *((unsigned long *) pte)) & 1) == 0)
  63                 return 0;
  64         if (rw == WRITE && (tmp & 2) == 0)
  65                 un_wp_page((unsigned long *) pte);
  66         p = (char *) ((tmp & 0xfffff000) + (*pos & 0xfff));
  67         while (1) {
  68                 if (rw == WRITE)
  69                         *p++ = get_fs_byte(buf++);
  70                 else
  71                         put_fs_byte(*p++, buf++);
  72 
  73                 if (--i == 0)
  74                         break;
  75 
  76                 if (count && ((unsigned long) p & 0xfff) == 0) {
  77                         if (((pte += 4) & 0xfff) == 0) {
  78                                 if (((pde += 4) & 0xfff) == 0)
  79                                         break;
  80                                 if (((pte = *((unsigned long *) pde)) & 1) == 0)
  81                                         break;
  82                                 pte &= 0xfffff000;
  83                         }
  84                         if (((tmp = *((unsigned long *) pte)) & 1) == 0)
  85                                 break;
  86 
  87                         if (rw == WRITE && (tmp & 2) == 0)
  88                                 un_wp_page((unsigned long *) pte);
  89                         p = (char *) (tmp & 0xfffff000);
  90                 }
  91         }
  92         return(count - i);
  93 }
  94 
  95 static int rw_kmem(int rw,char * buf, int count, off_t * pos)
  96 {
  97         char *p=(char *) *pos;
  98 
  99         if ((unsigned long) *pos > HIGH_MEMORY)
 100                 return 0;
 101         if ((unsigned long) *pos + count > HIGH_MEMORY)
 102                 count = HIGH_MEMORY - *pos;
 103 
 104         switch (rw) {
 105                 case READ:
 106                         while ((count -= 4) >= 0)
 107                                 put_fs_long(*((unsigned long *) p)++, 
     /* [previous][next][first][last][top][bottom][index][help] */
 108                                             ((unsigned long *) buf)++);
 109                         count += 4;
 110                         while (--count >= 0)
 111                                 put_fs_byte(*p++, buf++);
 112                         break;
 113                 case WRITE:
 114                         while (--count >= 0)
 115                                 *p++ = get_fs_byte(buf++);
 116                         break;
 117                 default:
 118                         return -EINVAL;
 119         }
 120         p -= *pos;
 121         *pos += (int) p;
 122         return (int) p;
 123 }
 124 
 125 static int rw_port(int rw,char * buf, int count, off_t * pos)
 126 {
 127         int i=*pos;
 128 
 129         while (count-->0 && i<65536) {
 130                 if (rw==READ)
 131                         put_fs_byte(inb(i),buf++);
     /* [previous][next][first][last][top][bottom][index][help] */
 132                 else
 133                         outb(get_fs_byte(buf++),i);
     /* [previous][next][first][last][top][bottom][index][help] */
 134                 i++;
 135         }
 136         i -= *pos;
 137         *pos += i;
 138         return i;
 139 }
 140 
 141 static int rw_memory(int rw, unsigned minor, char * buf, int count,
 142         off_t * pos, unsigned short flags)
 143 {
 144         switch(minor) {
 145                 case 0:
 146                         return rw_ram(rw,buf,count,pos);
 147                 case 1:
 148                         return rw_mem(rw,buf,count,pos);
 149                 case 2:
 150                         return rw_kmem(rw,buf,count,pos);
 151                 case 3:
 152                         return (rw==READ)?0:count;      /* rw_null */
 153                 case 4:
 154                         return rw_port(rw,buf,count,pos);
 155                 default:
 156                         return -EIO;
 157         }
 158 }
 159 
 160 #define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
 161 
 162 static crw_ptr crw_table[]={
 163         NULL,           /* nodev */
 164         rw_memory,      /* /dev/mem etc */
 165         NULL,           /* /dev/fd */
 166         NULL,           /* /dev/hd */
 167         rw_ttyx,        /* /dev/ttyx */
 168         rw_tty,         /* /dev/tty */
 169         rw_lp,          /* /dev/lp */
 170         NULL};          /* unnamed pipes */
 171 
 172 int char_read(struct inode * inode, struct file * filp, char * buf, int count)
 173 {
 174         unsigned int major,minor;
 175         crw_ptr call_addr;
 176 
 177         major = MAJOR(inode->i_rdev);
 178         minor = MINOR(inode->i_rdev);
 179         if (major >= NRDEVS)
 180                 return -ENODEV;
 181         if (!(call_addr = crw_table[major]))
 182                 return -ENODEV;
 183         return call_addr(READ,minor,buf,count,&filp->f_pos,filp->f_flags);
 184 }
 185 
 186 int char_write(struct inode * inode, struct file * filp, char * buf, int count)
 187 {
 188         unsigned int major,minor;
 189         crw_ptr call_addr;
 190 
 191         major = MAJOR(inode->i_rdev);
 192         minor = MINOR(inode->i_rdev);
 193         if (major >= NRDEVS)
 194                 return -ENODEV;
 195         if (!(call_addr=crw_table[major]))
 196                 return -ENODEV;
 197         return call_addr(WRITE,minor,buf,count,&filp->f_pos,filp->f_flags);
 198 }

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