File:  [Qemu by Fabrice Bellard] / qemu / ioport.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:34:04 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0130, qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, HEAD
qemu 0.12.0

    1: /*
    2:  * QEMU System Emulator
    3:  *
    4:  * Copyright (c) 2003-2008 Fabrice Bellard
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: /*
   25:  * splitted out ioport related stuffs from vl.c.
   26:  */
   27: 
   28: #include "ioport.h"
   29: 
   30: /***********************************************************/
   31: /* IO Port */
   32: 
   33: //#define DEBUG_UNUSED_IOPORT
   34: //#define DEBUG_IOPORT
   35: 
   36: #ifdef DEBUG_UNUSED_IOPORT
   37: #  define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
   38: #else
   39: #  define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0)
   40: #endif
   41: 
   42: #ifdef DEBUG_IOPORT
   43: #  define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
   44: #else
   45: #  define LOG_IOPORT(...) do { } while (0)
   46: #endif
   47: 
   48: /* XXX: use a two level table to limit memory usage */
   49: 
   50: static void *ioport_opaque[MAX_IOPORTS];
   51: static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
   52: static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
   53: 
   54: static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
   55: static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
   56: 
   57: static uint32_t ioport_read(int index, uint32_t address)
   58: {
   59:     static IOPortReadFunc * const default_func[3] = {
   60:         default_ioport_readb,
   61:         default_ioport_readw,
   62:         default_ioport_readl
   63:     };
   64:     IOPortReadFunc *func = ioport_read_table[index][address];
   65:     if (!func)
   66:         func = default_func[index];
   67:     return func(ioport_opaque[address], address);
   68: }
   69: 
   70: static void ioport_write(int index, uint32_t address, uint32_t data)
   71: {
   72:     static IOPortWriteFunc * const default_func[3] = {
   73:         default_ioport_writeb,
   74:         default_ioport_writew,
   75:         default_ioport_writel
   76:     };
   77:     IOPortWriteFunc *func = ioport_write_table[index][address];
   78:     if (!func)
   79:         func = default_func[index];
   80:     func(ioport_opaque[address], address, data);
   81: }
   82: 
   83: static uint32_t default_ioport_readb(void *opaque, uint32_t address)
   84: {
   85:     LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address);
   86:     return 0xff;
   87: }
   88: 
   89: static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
   90: {
   91:     LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
   92:                       address, data);
   93: }
   94: 
   95: /* default is to make two byte accesses */
   96: static uint32_t default_ioport_readw(void *opaque, uint32_t address)
   97: {
   98:     uint32_t data;
   99:     data = ioport_read(0, address);
  100:     address = (address + 1) & IOPORTS_MASK;
  101:     data |= ioport_read(0, address) << 8;
  102:     return data;
  103: }
  104: 
  105: static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
  106: {
  107:     ioport_write(0, address, data & 0xff);
  108:     address = (address + 1) & IOPORTS_MASK;
  109:     ioport_write(0, address, (data >> 8) & 0xff);
  110: }
  111: 
  112: static uint32_t default_ioport_readl(void *opaque, uint32_t address)
  113: {
  114:     LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address);
  115:     return 0xffffffff;
  116: }
  117: 
  118: static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
  119: {
  120:     LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
  121:                       address, data);
  122: }
  123: 
  124: static int ioport_bsize(int size, int *bsize)
  125: {
  126:     if (size == 1) {
  127:         *bsize = 0;
  128:     } else if (size == 2) {
  129:         *bsize = 1;
  130:     } else if (size == 4) {
  131:         *bsize = 2;
  132:     } else {
  133:         return -1;
  134:     }
  135:     return 0;
  136: }
  137: 
  138: /* size is the word size in byte */
  139: int register_ioport_read(pio_addr_t start, int length, int size,
  140:                          IOPortReadFunc *func, void *opaque)
  141: {
  142:     int i, bsize;
  143: 
  144:     if (ioport_bsize(size, &bsize)) {
  145:         hw_error("register_ioport_read: invalid size");
  146:         return -1;
  147:     }
  148:     for(i = start; i < start + length; i += size) {
  149:         ioport_read_table[bsize][i] = func;
  150:         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  151:             hw_error("register_ioport_read: invalid opaque");
  152:         ioport_opaque[i] = opaque;
  153:     }
  154:     return 0;
  155: }
  156: 
  157: /* size is the word size in byte */
  158: int register_ioport_write(pio_addr_t start, int length, int size,
  159:                           IOPortWriteFunc *func, void *opaque)
  160: {
  161:     int i, bsize;
  162: 
  163:     if (ioport_bsize(size, &bsize)) {
  164:         hw_error("register_ioport_write: invalid size");
  165:         return -1;
  166:     }
  167:     for(i = start; i < start + length; i += size) {
  168:         ioport_write_table[bsize][i] = func;
  169:         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  170:             hw_error("register_ioport_write: invalid opaque");
  171:         ioport_opaque[i] = opaque;
  172:     }
  173:     return 0;
  174: }
  175: 
  176: void isa_unassign_ioport(pio_addr_t start, int length)
  177: {
  178:     int i;
  179: 
  180:     for(i = start; i < start + length; i++) {
  181:         ioport_read_table[0][i] = default_ioport_readb;
  182:         ioport_read_table[1][i] = default_ioport_readw;
  183:         ioport_read_table[2][i] = default_ioport_readl;
  184: 
  185:         ioport_write_table[0][i] = default_ioport_writeb;
  186:         ioport_write_table[1][i] = default_ioport_writew;
  187:         ioport_write_table[2][i] = default_ioport_writel;
  188: 
  189:         ioport_opaque[i] = NULL;
  190:     }
  191: }
  192: 
  193: /***********************************************************/
  194: 
  195: void cpu_outb(pio_addr_t addr, uint8_t val)
  196: {
  197:     LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
  198:     ioport_write(0, addr, val);
  199: }
  200: 
  201: void cpu_outw(pio_addr_t addr, uint16_t val)
  202: {
  203:     LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
  204:     ioport_write(1, addr, val);
  205: }
  206: 
  207: void cpu_outl(pio_addr_t addr, uint32_t val)
  208: {
  209:     LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
  210:     ioport_write(2, addr, val);
  211: }
  212: 
  213: uint8_t cpu_inb(pio_addr_t addr)
  214: {
  215:     uint8_t val;
  216:     val = ioport_read(0, addr);
  217:     LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
  218:     return val;
  219: }
  220: 
  221: uint16_t cpu_inw(pio_addr_t addr)
  222: {
  223:     uint16_t val;
  224:     val = ioport_read(1, addr);
  225:     LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
  226:     return val;
  227: }
  228: 
  229: uint32_t cpu_inl(pio_addr_t addr)
  230: {
  231:     uint32_t val;
  232:     val = ioport_read(2, addr);
  233:     LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
  234:     return val;
  235: }

unix.superglobalmegacorp.com