File:  [Qemu by Fabrice Bellard] / qemu / ioport.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:33:34 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.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: #include "trace.h"
   30: 
   31: /***********************************************************/
   32: /* IO Port */
   33: 
   34: //#define DEBUG_UNUSED_IOPORT
   35: //#define DEBUG_IOPORT
   36: 
   37: #ifdef DEBUG_UNUSED_IOPORT
   38: #  define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
   39: #else
   40: #  define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0)
   41: #endif
   42: 
   43: #ifdef DEBUG_IOPORT
   44: #  define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
   45: #else
   46: #  define LOG_IOPORT(...) do { } while (0)
   47: #endif
   48: 
   49: /* XXX: use a two level table to limit memory usage */
   50: 
   51: static void *ioport_opaque[MAX_IOPORTS];
   52: static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
   53: static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
   54: 
   55: static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
   56: static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
   57: 
   58: static uint32_t ioport_read(int index, uint32_t address)
   59: {
   60:     static IOPortReadFunc * const default_func[3] = {
   61:         default_ioport_readb,
   62:         default_ioport_readw,
   63:         default_ioport_readl
   64:     };
   65:     IOPortReadFunc *func = ioport_read_table[index][address];
   66:     if (!func)
   67:         func = default_func[index];
   68:     return func(ioport_opaque[address], address);
   69: }
   70: 
   71: static void ioport_write(int index, uint32_t address, uint32_t data)
   72: {
   73:     static IOPortWriteFunc * const default_func[3] = {
   74:         default_ioport_writeb,
   75:         default_ioport_writew,
   76:         default_ioport_writel
   77:     };
   78:     IOPortWriteFunc *func = ioport_write_table[index][address];
   79:     if (!func)
   80:         func = default_func[index];
   81:     func(ioport_opaque[address], address, data);
   82: }
   83: 
   84: static uint32_t default_ioport_readb(void *opaque, uint32_t address)
   85: {
   86:     LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address);
   87:     return 0xff;
   88: }
   89: 
   90: static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
   91: {
   92:     LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
   93:                       address, data);
   94: }
   95: 
   96: /* default is to make two byte accesses */
   97: static uint32_t default_ioport_readw(void *opaque, uint32_t address)
   98: {
   99:     uint32_t data;
  100:     data = ioport_read(0, address);
  101:     address = (address + 1) & IOPORTS_MASK;
  102:     data |= ioport_read(0, address) << 8;
  103:     return data;
  104: }
  105: 
  106: static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
  107: {
  108:     ioport_write(0, address, data & 0xff);
  109:     address = (address + 1) & IOPORTS_MASK;
  110:     ioport_write(0, address, (data >> 8) & 0xff);
  111: }
  112: 
  113: static uint32_t default_ioport_readl(void *opaque, uint32_t address)
  114: {
  115:     LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address);
  116:     return 0xffffffff;
  117: }
  118: 
  119: static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
  120: {
  121:     LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
  122:                       address, data);
  123: }
  124: 
  125: static int ioport_bsize(int size, int *bsize)
  126: {
  127:     if (size == 1) {
  128:         *bsize = 0;
  129:     } else if (size == 2) {
  130:         *bsize = 1;
  131:     } else if (size == 4) {
  132:         *bsize = 2;
  133:     } else {
  134:         return -1;
  135:     }
  136:     return 0;
  137: }
  138: 
  139: /* size is the word size in byte */
  140: int register_ioport_read(pio_addr_t start, int length, int size,
  141:                          IOPortReadFunc *func, void *opaque)
  142: {
  143:     int i, bsize;
  144: 
  145:     if (ioport_bsize(size, &bsize)) {
  146:         hw_error("register_ioport_read: invalid size");
  147:         return -1;
  148:     }
  149:     for(i = start; i < start + length; i += size) {
  150:         ioport_read_table[bsize][i] = func;
  151:         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  152:             hw_error("register_ioport_read: invalid opaque");
  153:         ioport_opaque[i] = opaque;
  154:     }
  155:     return 0;
  156: }
  157: 
  158: /* size is the word size in byte */
  159: int register_ioport_write(pio_addr_t start, int length, int size,
  160:                           IOPortWriteFunc *func, void *opaque)
  161: {
  162:     int i, bsize;
  163: 
  164:     if (ioport_bsize(size, &bsize)) {
  165:         hw_error("register_ioport_write: invalid size");
  166:         return -1;
  167:     }
  168:     for(i = start; i < start + length; i += size) {
  169:         ioport_write_table[bsize][i] = func;
  170:         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  171:             hw_error("register_ioport_write: invalid opaque");
  172:         ioport_opaque[i] = opaque;
  173:     }
  174:     return 0;
  175: }
  176: 
  177: static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr)
  178: {
  179:     IORange *ioport = opaque;
  180:     uint64_t data;
  181: 
  182:     ioport->ops->read(ioport, addr - ioport->base, 1, &data);
  183:     return data;
  184: }
  185: 
  186: static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr)
  187: {
  188:     IORange *ioport = opaque;
  189:     uint64_t data;
  190: 
  191:     ioport->ops->read(ioport, addr - ioport->base, 2, &data);
  192:     return data;
  193: }
  194: 
  195: static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr)
  196: {
  197:     IORange *ioport = opaque;
  198:     uint64_t data;
  199: 
  200:     ioport->ops->read(ioport, addr - ioport->base, 4, &data);
  201:     return data;
  202: }
  203: 
  204: static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data)
  205: {
  206:     IORange *ioport = opaque;
  207: 
  208:     ioport->ops->write(ioport, addr - ioport->base, 1, data);
  209: }
  210: 
  211: static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data)
  212: {
  213:     IORange *ioport = opaque;
  214: 
  215:     ioport->ops->write(ioport, addr - ioport->base, 2, data);
  216: }
  217: 
  218: static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
  219: {
  220:     IORange *ioport = opaque;
  221: 
  222:     ioport->ops->write(ioport, addr - ioport->base, 4, data);
  223: }
  224: 
  225: void ioport_register(IORange *ioport)
  226: {
  227:     register_ioport_read(ioport->base, ioport->len, 1,
  228:                          ioport_readb_thunk, ioport);
  229:     register_ioport_read(ioport->base, ioport->len, 2,
  230:                          ioport_readw_thunk, ioport);
  231:     register_ioport_read(ioport->base, ioport->len, 4,
  232:                          ioport_readl_thunk, ioport);
  233:     register_ioport_write(ioport->base, ioport->len, 1,
  234:                           ioport_writeb_thunk, ioport);
  235:     register_ioport_write(ioport->base, ioport->len, 2,
  236:                           ioport_writew_thunk, ioport);
  237:     register_ioport_write(ioport->base, ioport->len, 4,
  238:                           ioport_writel_thunk, ioport);
  239: }
  240: 
  241: void isa_unassign_ioport(pio_addr_t start, int length)
  242: {
  243:     int i;
  244: 
  245:     for(i = start; i < start + length; i++) {
  246:         ioport_read_table[0][i] = default_ioport_readb;
  247:         ioport_read_table[1][i] = default_ioport_readw;
  248:         ioport_read_table[2][i] = default_ioport_readl;
  249: 
  250:         ioport_write_table[0][i] = default_ioport_writeb;
  251:         ioport_write_table[1][i] = default_ioport_writew;
  252:         ioport_write_table[2][i] = default_ioport_writel;
  253: 
  254:         ioport_opaque[i] = NULL;
  255:     }
  256: }
  257: 
  258: /***********************************************************/
  259: 
  260: void cpu_outb(pio_addr_t addr, uint8_t val)
  261: {
  262:     LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
  263:     trace_cpu_out(addr, val);
  264:     ioport_write(0, addr, val);
  265: }
  266: 
  267: void cpu_outw(pio_addr_t addr, uint16_t val)
  268: {
  269:     LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
  270:     trace_cpu_out(addr, val);
  271:     ioport_write(1, addr, val);
  272: }
  273: 
  274: void cpu_outl(pio_addr_t addr, uint32_t val)
  275: {
  276:     LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
  277:     trace_cpu_out(addr, val);
  278:     ioport_write(2, addr, val);
  279: }
  280: 
  281: uint8_t cpu_inb(pio_addr_t addr)
  282: {
  283:     uint8_t val;
  284:     val = ioport_read(0, addr);
  285:     trace_cpu_in(addr, val);
  286:     LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
  287:     return val;
  288: }
  289: 
  290: uint16_t cpu_inw(pio_addr_t addr)
  291: {
  292:     uint16_t val;
  293:     val = ioport_read(1, addr);
  294:     trace_cpu_in(addr, val);
  295:     LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
  296:     return val;
  297: }
  298: 
  299: uint32_t cpu_inl(pio_addr_t addr)
  300: {
  301:     uint32_t val;
  302:     val = ioport_read(2, addr);
  303:     trace_cpu_in(addr, val);
  304:     LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
  305:     return val;
  306: }

unix.superglobalmegacorp.com