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