|
|
1.1 root 1: /*
2: * linux/kernel/chr_drv/mem.c
3: *
1.1.1.4 ! root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1 root 5: */
6:
1.1.1.4 ! root 7: #include <linux/types.h>
! 8: #include <linux/errno.h>
1.1 root 9: #include <linux/sched.h>
10: #include <linux/kernel.h>
11: #include <linux/tty.h>
1.1.1.4 ! root 12: #include <linux/mouse.h>
1.1 root 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)
18: {
19: return -EIO;
20: }
21:
22: static int write_ram(struct inode * inode, struct file * file,char * buf, int count)
23: {
24: return -EIO;
25: }
26:
27: static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
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) {
1.1.1.4 ! root 39: if (current->signal & ~current->blocked)
! 40: break;
1.1 root 41: pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
1.1.1.4 ! root 42: pte = *(unsigned long *) pde;
! 43: if (!(pte & PAGE_PRESENT))
1.1 root 44: break;
45: pte &= 0xfffff000;
46: pte += (addr >> 10) & 0xffc;
1.1.1.4 ! root 47: page = *(unsigned long *) pte;
! 48: if (!(page & 1))
1.1 root 49: break;
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)
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) {
1.1.1.4 ! root 76: if (current->signal & ~current->blocked)
! 77: break;
1.1 root 78: pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
1.1.1.4 ! root 79: pte = *(unsigned long *) pde;
! 80: if (!(pte & PAGE_PRESENT))
1.1 root 81: break;
82: pte &= 0xfffff000;
83: pte += (addr >> 10) & 0xffc;
1.1.1.4 ! root 84: page = *(unsigned long *) pte;
! 85: if (!(page & PAGE_PRESENT))
1.1 root 86: break;
1.1.1.4 ! root 87: if (!(page & 2)) {
! 88: do_wp_page(0,addr,current,0);
! 89: continue;
! 90: }
1.1 root 91: page &= 0xfffff000;
92: page += addr & 0xfff;
93: i = 4096-(addr & 0xfff);
94: if (i > count)
95: i = count;
96: memcpy_fromfs((void *) page,tmp,i);
97: addr += i;
98: tmp += i;
99: count -= i;
100: }
101: file->f_pos = addr;
1.1.1.4 ! root 102: if (tmp != buf)
! 103: return tmp-buf;
! 104: if (current->signal & ~current->blocked)
! 105: return -ERESTARTSYS;
! 106: return 0;
1.1 root 107: }
108:
109: static int read_kmem(struct inode * inode, struct file * file,char * buf, int count)
110: {
111: unsigned long p = file->f_pos;
112:
113: if (count < 0)
114: return -EINVAL;
1.1.1.4 ! root 115: if (p >= high_memory)
1.1 root 116: return 0;
1.1.1.4 ! root 117: if (count > high_memory - p)
! 118: count = high_memory - p;
1.1 root 119: memcpy_tofs(buf,(void *) p,count);
120: file->f_pos += count;
121: return count;
122: }
123:
124: static int write_kmem(struct inode * inode, struct file * file,char * buf, int count)
125: {
126: unsigned long p = file->f_pos;
127:
128: if (count < 0)
129: return -EINVAL;
1.1.1.4 ! root 130: if (p >= high_memory)
1.1 root 131: return 0;
1.1.1.4 ! root 132: if (count > high_memory - p)
! 133: count = high_memory - p;
1.1 root 134: memcpy_fromfs((void *) p,buf,count);
135: file->f_pos += count;
136: return count;
137: }
138:
139: static int read_port(struct inode * inode,struct file * file,char * buf, int count)
140: {
141: unsigned int i = file->f_pos;
142: char * tmp = buf;
143:
144: while (count-- > 0 && i < 65536) {
145: put_fs_byte(inb(i),tmp);
146: i++;
147: tmp++;
148: }
149: file->f_pos = i;
150: return tmp-buf;
151: }
152:
153: static int write_port(struct inode * inode,struct file * file,char * buf, int count)
154: {
155: unsigned int i = file->f_pos;
156: char * tmp = buf;
157:
158: while (count-- > 0 && i < 65536) {
159: outb(get_fs_byte(tmp),i);
160: i++;
161: tmp++;
162: }
163: file->f_pos = i;
164: return tmp-buf;
165: }
166:
1.1.1.2 root 167: static int read_zero(struct inode *node,struct file *file,char *buf,int count)
168: {
169: int left;
170:
171: for (left = count; left > 0; left--) {
172: put_fs_byte(0,buf);
173: buf++;
174: }
175: return count;
176: }
177:
1.1 root 178: /*
179: * The memory devices use the full 32 bits of the offset, and so we cannot
180: * check against negative addresses: they are ok. The return value is weird,
181: * though, in that case (0).
182: *
183: * also note that seeking relative to the "end of file" isn't supported:
184: * it has no meaning, so it returns -EINVAL.
185: */
186: static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
187: {
188: switch (orig) {
189: case 0:
190: file->f_pos = offset;
191: return file->f_pos;
192: case 1:
193: file->f_pos += offset;
194: return file->f_pos;
195: default:
196: return -EINVAL;
197: }
198: if (file->f_pos < 0)
199: return 0;
200: return file->f_pos;
201: }
202:
203: static int mem_read(struct inode * inode, struct file * file, char * buf, int count)
204: {
205: switch (MINOR(inode->i_rdev)) {
206: case 0:
207: return read_ram(inode,file,buf,count);
208: case 1:
209: return read_mem(inode,file,buf,count);
210: case 2:
211: return read_kmem(inode,file,buf,count);
212: case 3:
213: return 0; /* /dev/null */
214: case 4:
215: return read_port(inode,file,buf,count);
1.1.1.2 root 216: case 5:
217: return read_zero(inode,file,buf,count);
1.1 root 218: default:
219: return -ENODEV;
220: }
221: }
222:
223: static int mem_write(struct inode * inode, struct file * file, char * buf, int count)
224: {
225: switch (MINOR(inode->i_rdev)) {
226: case 0:
227: return write_ram(inode,file,buf,count);
228: case 1:
229: return write_mem(inode,file,buf,count);
230: case 2:
231: return write_kmem(inode,file,buf,count);
232: case 3:
233: return count; /* /dev/null */
234: case 4:
235: return write_port(inode,file,buf,count);
1.1.1.2 root 236: case 5:
237: return count; /* /dev/zero */
1.1 root 238: default:
239: return -ENODEV;
240: }
241: }
242:
243: static struct file_operations mem_fops = {
244: mem_lseek,
245: mem_read,
246: mem_write,
247: NULL, /* mem_readdir */
248: NULL, /* mem_select */
249: NULL, /* mem_ioctl */
250: NULL, /* no special open code */
251: NULL /* no special release code */
252: };
253:
1.1.1.3 root 254: long chr_dev_init(long mem_start, long mem_end)
1.1 root 255: {
256: chrdev_fops[1] = &mem_fops;
1.1.1.3 root 257: mem_start = tty_init(mem_start);
258: mem_start = lp_init(mem_start);
1.1.1.4 ! root 259: mem_start = mouse_init(mem_start);
1.1.1.3 root 260: return mem_start;
1.1 root 261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.