|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: ! 27: #include <mach/vm_prot.h> ! 28: #include <mach/machine/vm_types.h> ! 29: #include <mach/machine/vm_param.h> ! 30: #include <mach/machine/eflags.h> ! 31: ! 32: #include <ipc/ipc_port.h> ! 33: ! 34: #include <device/io_req.h> ! 35: ! 36: #include <i386/io_port.h> ! 37: #include <i386/pit.h> ! 38: ! 39: /* ! 40: * IOPL device. ! 41: */ ! 42: ipc_port_t iopl_device_port = IP_NULL; ! 43: mach_device_t iopl_device = 0; ! 44: ! 45: /* ! 46: * Ports that we allow access to. ! 47: */ ! 48: io_reg_t iopl_port_list[] = { ! 49: /* timer 2 */ ! 50: 0x42, ! 51: /* speaker output */ ! 52: 0x61, ! 53: /* ATI - savage */ ! 54: 0x1ce, 0x1cf, ! 55: /* game port */ ! 56: 0x201, ! 57: /* sound board */ ! 58: 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, ! 59: 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, ! 60: /* printer */ ! 61: 0x278, 0x279, 0x27a, ! 62: 0x378, 0x379, 0x37a, ! 63: /* ega/vga */ ! 64: 0x3b0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, ! 65: 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, ! 66: 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, ! 67: 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, 0x3cd, 0x3ce, 0x3cf, ! 68: 0x3d0, 0x3d1, 0x3d2, 0x3d3, 0x3d4, 0x3d5, 0x3d6, 0x3d7, ! 69: 0x3d8, 0x3d9, 0x3da, 0x3db, 0x3dc, 0x3dd, 0x3de, 0x3df, ! 70: /* end of list */ ! 71: IO_REG_NULL, ! 72: /* patch space */ ! 73: 0, 0, 0, 0, 0, 0, 0, 0, ! 74: 0, 0, 0, 0, 0, 0, 0, 0 ! 75: }; ! 76: ! 77: int ! 78: ioplopen(dev, flag, ior) ! 79: int dev; ! 80: int flag; ! 81: io_req_t ior; ! 82: { ! 83: iopl_device_port = ior->io_device->port; ! 84: iopl_device = ior->io_device; ! 85: ! 86: io_port_create(iopl_device, iopl_port_list); ! 87: return (0); ! 88: } ! 89: ! 90: ! 91: /*ARGSUSED*/ ! 92: ioplclose(dev, flags) ! 93: int dev; ! 94: int flags; ! 95: { ! 96: io_port_destroy(iopl_device); ! 97: iopl_device_port = IP_NULL; ! 98: iopl_device = 0; ! 99: return 0; ! 100: } ! 101: ! 102: /*ARGSUSED*/ ! 103: int iopl_all = 1; ! 104: ioplmmap(dev, off, prot) ! 105: int dev; ! 106: vm_offset_t off; ! 107: vm_prot_t prot; ! 108: { ! 109: extern vm_offset_t phys_last_addr; ! 110: ! 111: if (iopl_all) { ! 112: if (off == 0) ! 113: return 0; ! 114: else if (off < 0xa0000) ! 115: return -1; ! 116: else if (off >= 0x100000 && off <= phys_last_addr) ! 117: return -1; ! 118: else ! 119: return i386_btop(off); ! 120: ! 121: } ! 122: if (off > 0x60000) ! 123: return(-1); ! 124: ! 125: /* Get page frame number for the page to be mapped. */ ! 126: ! 127: return(i386_btop(0xa0000 + off)); ! 128: } ! 129: ! 130: /* ! 131: * For DOS compatibility, it's easier to list the ports we don't ! 132: * allow access to. ! 133: */ ! 134: #define IOPL_PORTS_USED_MAX 256 ! 135: io_reg_t iopl_ports_used[IOPL_PORTS_USED_MAX] = { ! 136: IO_REG_NULL ! 137: }; ! 138: ! 139: boolean_t ! 140: iopl_port_forbidden(io_port) ! 141: int io_port; ! 142: { ! 143: int i; ! 144: ! 145: #if 0 /* we only read from these... it should be OK */ ! 146: ! 147: if (io_port <= 0xff) ! 148: return TRUE; /* system ports. 42,61,70,71 allowed above */ ! 149: ! 150: if (io_port >= 0x130 && io_port <= 0x137) ! 151: return TRUE; /* AHA disk */ ! 152: ! 153: if (io_port >= 0x170 && io_port <= 0x177) ! 154: return TRUE; /* HD disk */ ! 155: ! 156: if (io_port >= 0x1f0 && io_port <= 0x1f7) ! 157: return TRUE; /* HD disk */ ! 158: ! 159: if (io_port >= 0x230 && io_port <= 0x237) ! 160: return TRUE; /* AHA disk */ ! 161: ! 162: if (io_port >= 0x280 && io_port <= 0x2df) ! 163: return TRUE; /* 8390 network */ ! 164: ! 165: if (io_port >= 0x300 && io_port <= 0x31f) ! 166: return TRUE; /* 8390 network */ ! 167: ! 168: if (io_port >= 0x330 && io_port <= 0x337) ! 169: return TRUE; /* AHA disk */ ! 170: ! 171: if (io_port >= 0x370 && io_port <= 0x377) ! 172: return TRUE; /* FD disk */ ! 173: ! 174: if (io_port >= 0x3f0 && io_port <= 0x3f7) ! 175: return TRUE; /* FD disk */ ! 176: ! 177: #endif ! 178: ! 179: /* ! 180: * Must be OK, as far as we know... ! 181: * Record the port in the list, for ! 182: * curiosity seekers. ! 183: */ ! 184: for (i = 0; i < IOPL_PORTS_USED_MAX; i++) { ! 185: if (iopl_ports_used[i] == io_port) ! 186: break; /* in list */ ! 187: if (iopl_ports_used[i] == IO_REG_NULL) { ! 188: iopl_ports_used[i] = io_port; ! 189: iopl_ports_used[i+1] = IO_REG_NULL; ! 190: break; ! 191: } ! 192: } ! 193: ! 194: return FALSE; ! 195: } ! 196: ! 197: /* ! 198: * Emulate certain IO instructions for the AT bus. ! 199: * ! 200: * We emulate writes to the timer control port, 43. ! 201: * Only writes to timer 2 are allowed. ! 202: * ! 203: * Temporarily, we allow reads of any IO port, ! 204: * but ONLY if the thread has the IOPL device mapped ! 205: * and is not in V86 mode. ! 206: * ! 207: * This is a HACK and MUST go away when the DOS emulator ! 208: * emulates these IO ports, or when we decide that ! 209: * the DOS world can get access to all uncommitted IO ! 210: * ports. In that case, config() should remove the IO ! 211: * ports for devices it exists from the allowable list. ! 212: */ ! 213: boolean_t ! 214: iopl_emulate(regs, opcode, io_port) ! 215: struct i386_saved_state *regs; ! 216: int opcode; ! 217: int io_port; ! 218: { ! 219: iopb_tss_t iopb; ! 220: ! 221: iopb = current_thread()->pcb->ims.io_tss; ! 222: if (iopb == 0) ! 223: return FALSE; /* no IO mapped */ ! 224: ! 225: /* ! 226: * Handle outb to the timer control port, ! 227: * for timer 2 only. ! 228: */ ! 229: if (io_port == PITCTL_PORT) { ! 230: ! 231: int io_byte = regs->eax & 0xff; ! 232: ! 233: if (((iopb->bitmap[PITCTR2_PORT >> 3] & (1 << (PITCTR2_PORT & 0x7))) ! 234: == 0) /* allowed */ ! 235: && (opcode == 0xe6 || opcode == 0xee) /* outb */ ! 236: && (io_byte & 0xc0) == 0x80) /* timer 2 */ ! 237: { ! 238: outb(io_port, io_byte); ! 239: return TRUE; ! 240: } ! 241: return FALSE; /* invalid IO to port 42 */ ! 242: } ! 243: ! 244: /* ! 245: * If the thread has the IOPL device mapped, and ! 246: * the io port is not on the 'forbidden' list, allow ! 247: * reads from it. Reject writes. ! 248: * ! 249: * Don`t do this for V86 mode threads ! 250: * (hack for DOS emulator XXX!) ! 251: */ ! 252: if (!(regs->efl & EFL_VM) && ! 253: iopb_check_mapping(current_thread(), iopl_device) && ! 254: !iopl_port_forbidden(io_port)) ! 255: { ! 256: /* ! 257: * handle inb, inw, inl ! 258: */ ! 259: switch (opcode) { ! 260: case 0xE4: /* inb imm */ ! 261: case 0xEC: /* inb dx */ ! 262: regs->eax = (regs->eax & 0xffffff00) ! 263: | inb(io_port); ! 264: return TRUE; ! 265: ! 266: case 0x66E5: /* inw imm */ ! 267: case 0x66ED: /* inw dx */ ! 268: regs->eax = (regs->eax & 0xffff0000) ! 269: | inw(io_port); ! 270: return TRUE; ! 271: ! 272: case 0xE5: /* inl imm */ ! 273: case 0xED: /* inl dx */ ! 274: regs->eax = inl(io_port); ! 275: return TRUE; ! 276: ! 277: default: ! 278: return FALSE; /* OUT not allowed */ ! 279: } ! 280: } ! 281: ! 282: /* ! 283: * Not OK. ! 284: */ ! 285: return FALSE; ! 286: } ! 287:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.