qemu/ioport.c
<<
>>
Prefs
   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
  50static void *ioport_opaque[MAX_IOPORTS];
  51static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
  52static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
  53
  54static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
  55static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
  56
  57static uint32_t ioport_read(int index, uint32_t address)
  58{
  59    static IOPortReadFunc *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
  70static void ioport_write(int index, uint32_t address, uint32_t data)
  71{
  72    static IOPortWriteFunc *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
  83static 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
  89static 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 */
  96static 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
 105static 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
 112static 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
 118static 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
 124static 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 */
 139int 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 */
 158int 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
 176void 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
 195void cpu_outb(CPUState *env, 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#ifdef CONFIG_KQEMU
 200    if (env)
 201        env->last_io_time = cpu_get_time_fast();
 202#endif
 203}
 204
 205void cpu_outw(CPUState *env, pio_addr_t addr, uint16_t val)
 206{
 207    LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
 208    ioport_write(1, addr, val);
 209#ifdef CONFIG_KQEMU
 210    if (env)
 211        env->last_io_time = cpu_get_time_fast();
 212#endif
 213}
 214
 215void cpu_outl(CPUState *env, pio_addr_t addr, uint32_t val)
 216{
 217    LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
 218    ioport_write(2, addr, val);
 219#ifdef CONFIG_KQEMU
 220    if (env)
 221        env->last_io_time = cpu_get_time_fast();
 222#endif
 223}
 224
 225uint8_t cpu_inb(CPUState *env, pio_addr_t addr)
 226{
 227    uint8_t val;
 228    val = ioport_read(0, addr);
 229    LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
 230#ifdef CONFIG_KQEMU
 231    if (env)
 232        env->last_io_time = cpu_get_time_fast();
 233#endif
 234    return val;
 235}
 236
 237uint16_t cpu_inw(CPUState *env, pio_addr_t addr)
 238{
 239    uint16_t val;
 240    val = ioport_read(1, addr);
 241    LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
 242#ifdef CONFIG_KQEMU
 243    if (env)
 244        env->last_io_time = cpu_get_time_fast();
 245#endif
 246    return val;
 247}
 248
 249uint32_t cpu_inl(CPUState *env, pio_addr_t addr)
 250{
 251    uint32_t val;
 252    val = ioport_read(2, addr);
 253    LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
 254#ifdef CONFIG_KQEMU
 255    if (env)
 256        env->last_io_time = cpu_get_time_fast();
 257#endif
 258    return val;
 259}
 260