diff options
Diffstat (limited to 'hw/pflash_cfi02.c')
-rw-r--r-- | hw/pflash_cfi02.c | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index e7e0408fc4..ac5115e4c8 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -39,7 +39,6 @@ #include "flash.h" #include "qemu-timer.h" #include "block.h" -#include "exec-memory.h" //#define PFLASH_DEBUG #ifdef PFLASH_DEBUG @@ -70,39 +69,25 @@ struct pflash_t { uint8_t cfi_len; uint8_t cfi_table[0x52]; QEMUTimer *timer; - /* The device replicates the flash memory across its memory space. Emulate - * that by having a container (.mem) filled with an array of aliases - * (.mem_mappings) pointing to the flash memory (.orig_mem). - */ - MemoryRegion mem; - MemoryRegion *mem_mappings; /* array; one per mapping */ - MemoryRegion *orig_mem; + ram_addr_t off; + int fl_mem; int rom_mode; int read_counter; /* used for lazy switch-back to rom mode */ void *storage; }; -/* - * Set up replicated mappings of the same region. - */ -static void pflash_setup_mappings(pflash_t *pfl, MemoryRegion *mem) -{ - unsigned i; - target_phys_addr_t size = memory_region_size(mem); - - pfl->orig_mem = mem; - memory_region_init(&pfl->mem, "pflash", pfl->mappings * size); - pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings); - for (i = 0; i < pfl->mappings; ++i) { - memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias", mem, - 0, size); - memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]); - } -} - static void pflash_register_memory(pflash_t *pfl, int rom_mode) { - memory_region_rom_device_set_readable(pfl->orig_mem, rom_mode); + unsigned long phys_offset = pfl->fl_mem; + int i; + + if (rom_mode) + phys_offset |= pfl->off | IO_MEM_ROMD; + pfl->rom_mode = rom_mode; + + for (i = 0; i < pfl->mappings; i++) + cpu_register_physical_memory(pfl->base + i * pfl->chip_len, + pfl->chip_len, phys_offset); } static void pflash_timer (void *opaque) @@ -553,20 +538,28 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 4, 0); } -const MemoryRegionOps pflash_cfi02_ops_be = { - .old_mmio = { - .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, }, - .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUWriteMemoryFunc * const pflash_write_ops_be[] = { + &pflash_writeb_be, + &pflash_writew_be, + &pflash_writel_be, +}; + +static CPUReadMemoryFunc * const pflash_read_ops_be[] = { + &pflash_readb_be, + &pflash_readw_be, + &pflash_readl_be, }; -const MemoryRegionOps pflash_cfi02_ops_le = { - .old_mmio = { - .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, }, - .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUWriteMemoryFunc * const pflash_write_ops_le[] = { + &pflash_writeb_le, + &pflash_writew_le, + &pflash_writel_le, +}; + +static CPUReadMemoryFunc * const pflash_read_ops_le[] = { + &pflash_readb_le, + &pflash_readw_le, + &pflash_readl_le, }; /* Count trailing zeroes of a 32 bits quantity */ @@ -605,12 +598,13 @@ static int ctz32 (uint32_t n) return ret; } -pflash_t *pflash_cfi02_register(target_phys_addr_t base, MemoryRegion *mem, +pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, - uint16_t unlock_addr0, uint16_t unlock_addr1) + uint16_t unlock_addr0, uint16_t unlock_addr1, + int be) { pflash_t *pfl; int32_t chip_len; @@ -625,22 +619,31 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, MemoryRegion *mem, #endif pfl = g_malloc0(sizeof(pflash_t)); /* FIXME: Allocate ram ourselves. */ - pfl->storage = memory_region_get_ram_ptr(mem); + pfl->storage = qemu_get_ram_ptr(off); + if (be) { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be, + pflash_write_ops_be, + pfl, DEVICE_NATIVE_ENDIAN); + } else { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le, + pflash_write_ops_le, + pfl, DEVICE_NATIVE_ENDIAN); + } + pfl->off = off; pfl->base = base; pfl->chip_len = chip_len; pfl->mappings = nb_mappings; + pflash_register_memory(pfl, 1); pfl->bs = bs; if (pfl->bs) { /* read the initial flash content */ ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); if (ret < 0) { + cpu_unregister_io_memory(pfl->fl_mem); g_free(pfl); return NULL; } } - pflash_setup_mappings(pfl, mem); - pfl->rom_mode = 1; - memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem); #if 0 /* XXX: there should be a bit to set up read-only, * the same way the hardware does (with WP pin). */ |