This source file includes following definitions.
- tty_read
- tty_write
- lp_write
- put_fs_long
- inb
- get_fs_byte
1
2
3
4
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):
26 tty_write(minor,buf,count));
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));
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
56
57 pde = (unsigned long) pg_dir + (*pos >> 20 & 0xffc);
58 if (((pte = *((unsigned long *) pde)) & 1) == 0)
59 return 0;
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)++,
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++);
132 else
133 outb(get_fs_byte(buf++),i);
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;
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,
164 rw_memory,
165 NULL,
166 NULL,
167 rw_ttyx,
168 rw_tty,
169 rw_lp,
170 NULL};
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 }