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

Cache object: 127e3149656c55c5465cc268a2d46a29


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