|
|
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.