Annotation of linux/fs/char_dev.c, revision 1.1.1.5

1.1.1.2   root        1: /*
                      2:  *  linux/fs/char_dev.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
1.1       root        7: #include <errno.h>
1.1.1.2   root        8: #include <sys/types.h>
1.1       root        9: 
                     10: #include <linux/sched.h>
                     11: #include <linux/kernel.h>
                     12: 
1.1.1.5 ! root       13: #include <checkpoint.h>
1.1.1.2   root       14: #include <asm/segment.h>
                     15: #include <asm/io.h>
                     16: 
1.1.1.4   root       17: extern int tty_read(unsigned minor,char * buf,int count,unsigned short flags);
1.1       root       18: extern int tty_write(unsigned minor,char * buf,int count);
1.1.1.5 ! root       19: extern int lp_write(unsigned minor,char *buf, int count);
1.1       root       20: 
1.1.1.4   root       21: typedef (*crw_ptr)(int,unsigned,char *,int,off_t *,unsigned short);
1.1.1.2   root       22: 
1.1.1.4   root       23: static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
1.1.1.2   root       24: {
1.1.1.4   root       25:        return ((rw==READ)?tty_read(minor,buf,count,flags):
1.1.1.2   root       26:                tty_write(minor,buf,count));
                     27: }
                     28: 
1.1.1.5 ! root       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));
        !            32: }
        !            33: 
1.1.1.4   root       34: static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos, unsigned short flags)
1.1.1.2   root       35: {
                     36:        if (current->tty<0)
                     37:                return -EPERM;
1.1.1.4   root       38:        return rw_ttyx(rw,current->tty,buf,count,pos,flags);
1.1.1.2   root       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: {
1.1.1.5 ! root       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);
1.1.1.2   root       93: }
1.1       root       94: 
1.1.1.2   root       95: static int rw_kmem(int rw,char * buf, int count, off_t * pos)
                     96: {
1.1.1.5 ! root       97:        char *p=(char *) *pos;
1.1.1.4   root       98: 
1.1.1.5 ! root       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)++, 
        !           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;
1.1.1.4   root      119:        }
1.1.1.5 ! root      120:        p -= *pos;
        !           121:        *pos += (int) p;
        !           122:        return (int) p;
1.1.1.2   root      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++);
                    132:                else
                    133:                        outb(get_fs_byte(buf++),i);
                    134:                i++;
                    135:        }
                    136:        i -= *pos;
                    137:        *pos += i;
                    138:        return i;
                    139: }
                    140: 
1.1.1.4   root      141: static int rw_memory(int rw, unsigned minor, char * buf, int count,
                    142:        off_t * pos, unsigned short flags)
1.1.1.2   root      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: }
1.1       root      159: 
                    160: #define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
                    161: 
                    162: static crw_ptr crw_table[]={
                    163:        NULL,           /* nodev */
1.1.1.2   root      164:        rw_memory,      /* /dev/mem etc */
1.1       root      165:        NULL,           /* /dev/fd */
                    166:        NULL,           /* /dev/hd */
                    167:        rw_ttyx,        /* /dev/ttyx */
                    168:        rw_tty,         /* /dev/tty */
1.1.1.5 ! root      169:        rw_lp,          /* /dev/lp */
1.1       root      170:        NULL};          /* unnamed pipes */
                    171: 
1.1.1.4   root      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)
1.1       root      187: {
1.1.1.4   root      188:        unsigned int major,minor;
1.1       root      189:        crw_ptr call_addr;
                    190: 
1.1.1.4   root      191:        major = MAJOR(inode->i_rdev);
                    192:        minor = MINOR(inode->i_rdev);
                    193:        if (major >= NRDEVS)
1.1.1.3   root      194:                return -ENODEV;
1.1.1.4   root      195:        if (!(call_addr=crw_table[major]))
1.1.1.3   root      196:                return -ENODEV;
1.1.1.4   root      197:        return call_addr(WRITE,minor,buf,count,&filp->f_pos,filp->f_flags);
1.1       root      198: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.