diff options
author | Thomas Bushnell <thomas@gnu.org> | 1997-02-25 21:28:37 +0000 |
---|---|---|
committer | Thomas Bushnell <thomas@gnu.org> | 1997-02-25 21:28:37 +0000 |
commit | f07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch) | |
tree | 12b07c7e578fc1a5f53dbfde2632408491ff2a70 /i386/i386at/iopl.c |
Initial source
Diffstat (limited to 'i386/i386at/iopl.c')
-rw-r--r-- | i386/i386at/iopl.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/i386/i386at/iopl.c b/i386/i386at/iopl.c new file mode 100644 index 0000000..ae67568 --- /dev/null +++ b/i386/i386at/iopl.c @@ -0,0 +1,287 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include <mach/vm_prot.h> +#include <mach/machine/vm_types.h> +#include <mach/machine/vm_param.h> +#include <mach/machine/eflags.h> + +#include <ipc/ipc_port.h> + +#include <device/io_req.h> + +#include <i386/io_port.h> +#include <i386/pit.h> + +/* + * IOPL device. + */ +ipc_port_t iopl_device_port = IP_NULL; +mach_device_t iopl_device = 0; + +/* + * Ports that we allow access to. + */ +io_reg_t iopl_port_list[] = { + /* timer 2 */ + 0x42, + /* speaker output */ + 0x61, + /* ATI - savage */ + 0x1ce, 0x1cf, + /* game port */ + 0x201, + /* sound board */ + 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, + 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, + /* printer */ + 0x278, 0x279, 0x27a, + 0x378, 0x379, 0x37a, + /* ega/vga */ + 0x3b0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, + 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, + 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, + 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, 0x3cd, 0x3ce, 0x3cf, + 0x3d0, 0x3d1, 0x3d2, 0x3d3, 0x3d4, 0x3d5, 0x3d6, 0x3d7, + 0x3d8, 0x3d9, 0x3da, 0x3db, 0x3dc, 0x3dd, 0x3de, 0x3df, + /* end of list */ + IO_REG_NULL, + /* patch space */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int +ioplopen(dev, flag, ior) + int dev; + int flag; + io_req_t ior; +{ + iopl_device_port = ior->io_device->port; + iopl_device = ior->io_device; + + io_port_create(iopl_device, iopl_port_list); + return (0); +} + + +/*ARGSUSED*/ +ioplclose(dev, flags) + int dev; + int flags; +{ + io_port_destroy(iopl_device); + iopl_device_port = IP_NULL; + iopl_device = 0; + return 0; +} + +/*ARGSUSED*/ +int iopl_all = 1; +ioplmmap(dev, off, prot) +int dev; +vm_offset_t off; +vm_prot_t prot; +{ + extern vm_offset_t phys_last_addr; + + if (iopl_all) { + if (off == 0) + return 0; + else if (off < 0xa0000) + return -1; + else if (off >= 0x100000 && off <= phys_last_addr) + return -1; + else + return i386_btop(off); + + } + if (off > 0x60000) + return(-1); + + /* Get page frame number for the page to be mapped. */ + + return(i386_btop(0xa0000 + off)); +} + +/* + * For DOS compatibility, it's easier to list the ports we don't + * allow access to. + */ +#define IOPL_PORTS_USED_MAX 256 +io_reg_t iopl_ports_used[IOPL_PORTS_USED_MAX] = { + IO_REG_NULL +}; + +boolean_t +iopl_port_forbidden(io_port) + int io_port; +{ + int i; + +#if 0 /* we only read from these... it should be OK */ + + if (io_port <= 0xff) + return TRUE; /* system ports. 42,61,70,71 allowed above */ + + if (io_port >= 0x130 && io_port <= 0x137) + return TRUE; /* AHA disk */ + + if (io_port >= 0x170 && io_port <= 0x177) + return TRUE; /* HD disk */ + + if (io_port >= 0x1f0 && io_port <= 0x1f7) + return TRUE; /* HD disk */ + + if (io_port >= 0x230 && io_port <= 0x237) + return TRUE; /* AHA disk */ + + if (io_port >= 0x280 && io_port <= 0x2df) + return TRUE; /* 8390 network */ + + if (io_port >= 0x300 && io_port <= 0x31f) + return TRUE; /* 8390 network */ + + if (io_port >= 0x330 && io_port <= 0x337) + return TRUE; /* AHA disk */ + + if (io_port >= 0x370 && io_port <= 0x377) + return TRUE; /* FD disk */ + + if (io_port >= 0x3f0 && io_port <= 0x3f7) + return TRUE; /* FD disk */ + +#endif + + /* + * Must be OK, as far as we know... + * Record the port in the list, for + * curiosity seekers. + */ + for (i = 0; i < IOPL_PORTS_USED_MAX; i++) { + if (iopl_ports_used[i] == io_port) + break; /* in list */ + if (iopl_ports_used[i] == IO_REG_NULL) { + iopl_ports_used[i] = io_port; + iopl_ports_used[i+1] = IO_REG_NULL; + break; + } + } + + return FALSE; +} + +/* + * Emulate certain IO instructions for the AT bus. + * + * We emulate writes to the timer control port, 43. + * Only writes to timer 2 are allowed. + * + * Temporarily, we allow reads of any IO port, + * but ONLY if the thread has the IOPL device mapped + * and is not in V86 mode. + * + * This is a HACK and MUST go away when the DOS emulator + * emulates these IO ports, or when we decide that + * the DOS world can get access to all uncommitted IO + * ports. In that case, config() should remove the IO + * ports for devices it exists from the allowable list. + */ +boolean_t +iopl_emulate(regs, opcode, io_port) + struct i386_saved_state *regs; + int opcode; + int io_port; +{ + iopb_tss_t iopb; + + iopb = current_thread()->pcb->ims.io_tss; + if (iopb == 0) + return FALSE; /* no IO mapped */ + + /* + * Handle outb to the timer control port, + * for timer 2 only. + */ + if (io_port == PITCTL_PORT) { + + int io_byte = regs->eax & 0xff; + + if (((iopb->bitmap[PITCTR2_PORT >> 3] & (1 << (PITCTR2_PORT & 0x7))) + == 0) /* allowed */ + && (opcode == 0xe6 || opcode == 0xee) /* outb */ + && (io_byte & 0xc0) == 0x80) /* timer 2 */ + { + outb(io_port, io_byte); + return TRUE; + } + return FALSE; /* invalid IO to port 42 */ + } + + /* + * If the thread has the IOPL device mapped, and + * the io port is not on the 'forbidden' list, allow + * reads from it. Reject writes. + * + * Don`t do this for V86 mode threads + * (hack for DOS emulator XXX!) + */ + if (!(regs->efl & EFL_VM) && + iopb_check_mapping(current_thread(), iopl_device) && + !iopl_port_forbidden(io_port)) + { + /* + * handle inb, inw, inl + */ + switch (opcode) { + case 0xE4: /* inb imm */ + case 0xEC: /* inb dx */ + regs->eax = (regs->eax & 0xffffff00) + | inb(io_port); + return TRUE; + + case 0x66E5: /* inw imm */ + case 0x66ED: /* inw dx */ + regs->eax = (regs->eax & 0xffff0000) + | inw(io_port); + return TRUE; + + case 0xE5: /* inl imm */ + case 0xED: /* inl dx */ + regs->eax = inl(io_port); + return TRUE; + + default: + return FALSE; /* OUT not allowed */ + } + } + + /* + * Not OK. + */ + return FALSE; +} + |