Home | History | Annotate | Download | only in qemu
      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 }
    236