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 "exec/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