The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386at/iopl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  Software.Distribution@CS.CMU.EDU
   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  * HISTORY
   28  * $Log:        iopl.c,v $
   29  * Revision 2.11  93/09/01  11:32:49  mrt
   30  *      For X11R5, allow any old address to be mmapped.
   31  *      [93/08/19            rvb]
   32  * 
   33  * Revision 2.10  93/03/09  11:18:43  danner
   34  *      And printer at 0x278
   35  *      [93/03/04  11:16:17  rvb]
   36  * 
   37  *      Added two ports for ATI graphics card from Savage.
   38  *      [93/03/03            rvb]
   39  * 
   40  * Revision 2.9  92/04/03  12:09:07  rpd
   41  *      Change mapping of mmap function to map 0x0, 0xa0000..0xfffff
   42  *      directly.
   43  *      [92/03/16            rvb]
   44  * 
   45  * Revision 2.8  92/01/03  20:11:01  dbg
   46  *      Add 'forbidden' list.  For DOS compatibility, allow any port not
   47  *      on this list.
   48  *      [92/01/02            dbg]
   49  * 
   50  *      Add ports 70 and 71 for DOS programs (XXX).
   51  *      [91/12/18            dbg]
   52  * 
   53  *      Use io_port sets.
   54  *      [91/11/09            dbg]
   55  * 
   56  * Revision 2.7  91/05/14  16:26:21  mrt
   57  *      Correcting copyright
   58  * 
   59  * Revision 2.6  91/02/05  17:18:43  mrt
   60  *      Changed to new Mach copyright
   61  *      [91/02/01  17:44:59  mrt]
   62  * 
   63  * Revision 2.5  90/11/26  14:50:15  rvb
   64  *      jsb bet me to XMK34, sigh ...
   65  *      [90/11/26            rvb]
   66  *      Synched 2.5 & 3.0 at I386q (r2.1.1.3) & XMK35 (r2.5)
   67  *      [90/11/15            rvb]
   68  * 
   69  * Revision 2.1.1.2  90/03/28  08:30:58  rvb
   70  *      Add ioplmmap to map 0x0a0000 - 0x100000
   71  *      [90/03/25            rvb]
   72  * 
   73  * Revision 2.1.1.1  90/02/01  13:36:55  rvb
   74  *      Allow io privileges to the process.
   75  *      [90/02/01            rvb]
   76  * 
   77  */
   78  
   79 #include <mach/vm_prot.h>
   80 #include <mach/i386/vm_types.h>
   81 #include <mach/i386/vm_param.h>
   82 
   83 #include <ipc/ipc_port.h>
   84 
   85 #include <device/io_req.h>
   86 
   87 #include <i386/io_port.h>
   88 #include <i386/eflags.h>
   89 #include <i386/pit.h>
   90 
   91 /*
   92  * IOPL device.
   93  */
   94 ipc_port_t      iopl_device_port = IP_NULL;
   95 device_t        iopl_device = 0;
   96 
   97 /*
   98  * Ports that we allow access to.
   99  */
  100 io_reg_t iopl_port_list[] = {
  101         /* timer 2 */
  102         0x42,
  103         /* speaker output */
  104         0x61,
  105         /* configuration RAM */
  106         0x70, 0x71,                     /* XXX should not need! */
  107         /* ATI - savage */
  108         0x1ce, 0x1cf,
  109         /* game port */
  110         0x201,
  111         /* sound board */
  112         0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227,
  113         0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e, 0x22f,
  114         /* printer */
  115         0x278, 0x279, 0x27a,
  116         0x378, 0x379, 0x37a,
  117         /* ega/vga */
  118         0x3b0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7,
  119         0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf,
  120         0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7,
  121         0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, 0x3cd, 0x3ce, 0x3cf,
  122         0x3d0, 0x3d1, 0x3d2, 0x3d3, 0x3d4, 0x3d5, 0x3d6, 0x3d7,
  123         0x3d8, 0x3d9, 0x3da, 0x3db, 0x3dc, 0x3dd, 0x3de, 0x3df,
  124         /* end of list */
  125         IO_REG_NULL
  126 };
  127 
  128 int
  129 ioplopen(dev, flag, ior)
  130         int     dev;
  131         int     flag;
  132         io_req_t ior;
  133 {
  134         iopl_device_port = ior->io_device->port;
  135         iopl_device = ior->io_device;
  136 
  137         io_port_create(iopl_device, iopl_port_list);
  138         return (0);
  139 }
  140 
  141 
  142 /*ARGSUSED*/
  143 ioplclose(dev, flags)
  144         int     dev;
  145         int flags;
  146 {
  147         io_port_destroy(iopl_device);
  148         iopl_device_port = IP_NULL;
  149         iopl_device = 0;
  150         return 0;
  151 }
  152 
  153 /*ARGSUSED*/
  154 int iopl_all = 1;
  155 ioplmmap(dev, off, prot)
  156 int             dev;
  157 vm_offset_t     off;
  158 vm_prot_t       prot;
  159 {
  160     extern vm_offset_t last_addr;
  161 
  162     if (iopl_all) {
  163         if (off == 0)
  164                 return 0;
  165         else if (off < 0xa0000)
  166                 return -1;
  167         else if (off >= 0x100000 && off <= last_addr)
  168                 return -1;
  169         else
  170                 return i386_btop(off);
  171 
  172     }
  173         if (off > 0x60000)
  174                 return(-1);
  175 
  176         /* Get page frame number for the page to be mapped. */
  177 
  178         return(i386_btop(0xa0000 + off));
  179 }
  180 
  181 /*
  182  * For DOS compatibility, it's easier to list the ports we don't
  183  * allow access to.
  184  */
  185 #define IOPL_PORTS_USED_MAX     256
  186 io_reg_t iopl_ports_used[IOPL_PORTS_USED_MAX] = {
  187         IO_REG_NULL
  188 };
  189 
  190 boolean_t
  191 iopl_port_forbidden(io_port)
  192         int     io_port;
  193 {
  194         int     i;
  195 
  196 #if 0   /* we only read from these... it should be OK */
  197 
  198         if (io_port <= 0xff)
  199             return TRUE;        /* system ports.  42,61,70,71 allowed above */
  200 
  201         if (io_port >= 0x130 && io_port <= 0x137)
  202             return TRUE;        /* AHA disk */
  203 
  204         if (io_port >= 0x170 && io_port <= 0x177)
  205             return TRUE;        /* HD disk */
  206 
  207         if (io_port >= 0x1f0 && io_port <= 0x1f7)
  208             return TRUE;        /* HD disk */
  209 
  210         if (io_port >= 0x230 && io_port <= 0x237)
  211             return TRUE;        /* AHA disk */
  212 
  213         if (io_port >= 0x280 && io_port <= 0x2df)
  214             return TRUE;        /* 8390 network */
  215 
  216         if (io_port >= 0x300 && io_port <= 0x31f)
  217             return TRUE;        /* 8390 network */
  218 
  219         if (io_port >= 0x330 && io_port <= 0x337)
  220             return TRUE;        /* AHA disk */
  221 
  222         if (io_port >= 0x370 && io_port <= 0x377)
  223             return TRUE;        /* FD disk */
  224 
  225         if (io_port >= 0x3f0 && io_port <= 0x3f7)
  226             return TRUE;        /* FD disk */
  227 
  228 #endif
  229 
  230         /*
  231          * Must be OK, as far as we know...
  232          * Record the port in the list, for
  233          * curiosity seekers.
  234          */
  235         for (i = 0; i < IOPL_PORTS_USED_MAX; i++) {
  236             if (iopl_ports_used[i] == io_port)
  237                 break;                  /* in list */
  238             if (iopl_ports_used[i] == IO_REG_NULL) {
  239                 iopl_ports_used[i] = io_port;
  240                 iopl_ports_used[i+1] = IO_REG_NULL;
  241                 break;
  242             }
  243         }
  244 
  245         return FALSE;
  246 }
  247 
  248 /*
  249  * Emulate certain IO instructions for the AT bus.
  250  *
  251  * We emulate writes to the timer control port, 43.
  252  * Only writes to timer 2 are allowed.
  253  *
  254  * Temporarily, we allow reads of any IO port,
  255  * but ONLY if the thread has the IOPL device mapped
  256  * and is not in V86 mode.
  257  *
  258  * This is a HACK and MUST go away when the DOS emulator
  259  * emulates these IO ports, or when we decide that
  260  * the DOS world can get access to all uncommitted IO
  261  * ports.  In that case, config() should remove the IO
  262  * ports for devices it exists from the allowable list.
  263  */
  264 boolean_t
  265 iopl_emulate(regs, opcode, io_port)
  266         struct i386_saved_state *regs;
  267         int     opcode;
  268         int     io_port;
  269 {
  270         iopb_tss_t      iopb;
  271 
  272         iopb = current_thread()->pcb->ims.io_tss;
  273         if (iopb == 0)
  274             return FALSE;               /* no IO mapped */
  275 
  276         /*
  277          * Handle outb to the timer control port,
  278          * for timer 2 only.
  279          */
  280         if (io_port == PITCTL_PORT) {
  281 
  282             int io_byte = regs->eax & 0xff;
  283 
  284             if (((iopb->bitmap[PITCTR2_PORT >> 3] & (1 << (PITCTR2_PORT & 0x7)))
  285                 == 0)   /* allowed */
  286              && (opcode == 0xe6 || opcode == 0xee)      /* outb */
  287              && (io_byte & 0xc0) == 0x80)               /* timer 2 */
  288             {
  289                 outb(io_port, io_byte);
  290                 return TRUE;
  291             }
  292             return FALSE;       /* invalid IO to port 42 */
  293         }
  294 
  295         /*
  296          * If the thread has the IOPL device mapped, and
  297          * the io port is not on the 'forbidden' list, allow
  298          * reads from it.  Reject writes.
  299          *
  300          * Don`t do this for V86 mode threads
  301          * (hack for DOS emulator XXX!)
  302          */
  303         if (!(regs->efl & EFL_VM) &&
  304             iopb_check_mapping(current_thread(), iopl_device) &&
  305             !iopl_port_forbidden(io_port))
  306         {
  307             /*
  308              * handle inb, inw, inl
  309              */
  310             switch (opcode) {
  311                 case 0xE4:              /* inb imm */
  312                 case 0xEC:              /* inb dx */
  313                     regs->eax = (regs->eax & 0xffffff00)
  314                                 | inb(io_port);
  315                     return TRUE;
  316 
  317                 case 0x66E5:            /* inw imm */
  318                 case 0x66ED:            /* inw dx */
  319                     regs->eax = (regs->eax & 0xffff0000)
  320                                 | inw(io_port);
  321                     return TRUE;
  322 
  323                 case 0xE5:              /* inl imm */
  324                 case 0xED:              /* inl dx */
  325                     regs->eax = inl(io_port);
  326                     return TRUE;
  327 
  328                 default:
  329                     return FALSE;       /* OUT not allowed */
  330             }
  331         }
  332 
  333         /*
  334          * Not OK.
  335          */
  336         return FALSE;
  337 }
  338 

Cache object: 124efdd99506d1ac2bb11e50549c9fa3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.