|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.