Annotation of qemu/ioport.c, revision 1.1.1.3

1.1       root        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"
1.1.1.3 ! root       29: #include "trace.h"
1.1       root       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: {
1.1.1.2   root       60:     static IOPortReadFunc * const default_func[3] = {
1.1       root       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: {
1.1.1.2   root       73:     static IOPortWriteFunc * const default_func[3] = {
1.1       root       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: 
1.1.1.3 ! root      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: 
1.1       root      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: 
1.1.1.2   root      260: void cpu_outb(pio_addr_t addr, uint8_t val)
1.1       root      261: {
                    262:     LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
1.1.1.3 ! root      263:     trace_cpu_out(addr, val);
1.1       root      264:     ioport_write(0, addr, val);
                    265: }
                    266: 
1.1.1.2   root      267: void cpu_outw(pio_addr_t addr, uint16_t val)
1.1       root      268: {
                    269:     LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
1.1.1.3 ! root      270:     trace_cpu_out(addr, val);
1.1       root      271:     ioport_write(1, addr, val);
                    272: }
                    273: 
1.1.1.2   root      274: void cpu_outl(pio_addr_t addr, uint32_t val)
1.1       root      275: {
                    276:     LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
1.1.1.3 ! root      277:     trace_cpu_out(addr, val);
1.1       root      278:     ioport_write(2, addr, val);
                    279: }
                    280: 
1.1.1.2   root      281: uint8_t cpu_inb(pio_addr_t addr)
1.1       root      282: {
                    283:     uint8_t val;
                    284:     val = ioport_read(0, addr);
1.1.1.3 ! root      285:     trace_cpu_in(addr, val);
1.1       root      286:     LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
                    287:     return val;
                    288: }
                    289: 
1.1.1.2   root      290: uint16_t cpu_inw(pio_addr_t addr)
1.1       root      291: {
                    292:     uint16_t val;
                    293:     val = ioport_read(1, addr);
1.1.1.3 ! root      294:     trace_cpu_in(addr, val);
1.1       root      295:     LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
                    296:     return val;
                    297: }
                    298: 
1.1.1.2   root      299: uint32_t cpu_inl(pio_addr_t addr)
1.1       root      300: {
                    301:     uint32_t val;
                    302:     val = ioport_read(2, addr);
1.1.1.3 ! root      303:     trace_cpu_in(addr, val);
1.1       root      304:     LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
                    305:     return val;
                    306: }

unix.superglobalmegacorp.com