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 * 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 70static 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 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(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 201void 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 207void 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 213uint8_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 221uint16_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 229uint32_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