diff options
author | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-04-16 23:45:36 +0000 |
---|---|---|
committer | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-04-16 23:45:36 +0000 |
commit | 4fbd24ba35ce80b23253002116d5a90df6d25b2c (patch) | |
tree | 4109e93fdd15090405dee9c090663209385fd6dd /hw/pflash_cfi02.c | |
parent | 6725070d8dba75fefb9f852c64239a988ef42caa (diff) | |
download | qemu-4fbd24ba35ce80b23253002116d5a90df6d25b2c.zip qemu-4fbd24ba35ce80b23253002116d5a90df6d25b2c.tar.gz qemu-4fbd24ba35ce80b23253002116d5a90df6d25b2c.tar.bz2 |
Emulate address wrap in CFI02 chips mapping (Jan Kiszka).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4219 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/pflash_cfi02.c')
-rw-r--r-- | hw/pflash_cfi02.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index d4d5a9f..075f50f 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -55,7 +55,8 @@ struct pflash_t { BlockDriverState *bs; target_phys_addr_t base; uint32_t sector_len; - uint32_t total_len; + uint32_t chip_len; + int mappings; int width; int wcycle; /* if 0, the flash is read normally */ int bypass; @@ -72,6 +73,19 @@ struct pflash_t { void *storage; }; +static void pflash_register_memory(pflash_t *pfl, int rom_mode) +{ + unsigned long phys_offset = pfl->fl_mem; + int i; + + if (rom_mode) + phys_offset |= pfl->off | IO_MEM_ROMD; + + 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) { pflash_t *pfl = opaque; @@ -82,8 +96,7 @@ static void pflash_timer (void *opaque) if (pfl->bypass) { pfl->wcycle = 2; } else { - cpu_register_physical_memory(pfl->base, pfl->total_len, - pfl->off | IO_MEM_ROMD | pfl->fl_mem); + pflash_register_memory(pfl, 1); pfl->wcycle = 0; } pfl->cmd = 0; @@ -98,6 +111,7 @@ static uint32_t pflash_read (pflash_t *pfl, uint32_t offset, int width) DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset); ret = -1; offset -= pfl->base; + offset &= pfl->chip_len - 1; boff = offset & 0xFF; if (pfl->width == 2) boff = boff >> 1; @@ -226,11 +240,10 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, offset -= (uint32_t)(long)pfl->storage; else offset -= pfl->base; + offset &= pfl->chip_len - 1; DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__, offset, value, width); - /* Set the device in I/O access mode */ - cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem); boff = offset & (pfl->sector_len - 1); if (pfl->width == 2) boff = boff >> 1; @@ -238,6 +251,8 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, boff = boff >> 2; switch (pfl->wcycle) { case 0: + /* Set the device in I/O access mode */ + pflash_register_memory(pfl, 0); /* We're in read mode */ check_unlock0: if (boff == 0x55 && cmd == 0x98) { @@ -369,9 +384,9 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, } /* Chip erase */ DPRINTF("%s: start chip erase\n", __func__); - memset(pfl->storage, 0xFF, pfl->total_len); + memset(pfl->storage, 0xFF, pfl->chip_len); pfl->status = 0x00; - pflash_update(pfl, 0, pfl->total_len); + pflash_update(pfl, 0, pfl->chip_len); /* Let's wait 5 seconds before chip erase is done */ qemu_mod_timer(pfl->timer, qemu_get_clock(vm_clock) + (ticks_per_sec * 5)); @@ -424,8 +439,7 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, /* Reset flash */ reset_flash: - cpu_register_physical_memory(pfl->base, pfl->total_len, - pfl->off | IO_MEM_ROMD | pfl->fl_mem); + pflash_register_memory(pfl, 1); pfl->bypass = 0; pfl->wcycle = 0; pfl->cmd = 0; @@ -527,15 +541,15 @@ static int ctz32 (uint32_t n) pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, - int nb_blocs, int width, + 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) { pflash_t *pfl; - int32_t total_len; + int32_t chip_len; - total_len = sector_len * nb_blocs; + chip_len = sector_len * nb_blocs; /* XXX: to be fixed */ #if 0 if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && @@ -549,12 +563,14 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, pfl); pfl->off = off; - cpu_register_physical_memory(base, total_len, - off | pfl->fl_mem | IO_MEM_ROMD); + 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 */ - bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); + bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); } #if 0 /* XXX: there should be a bit to set up read-only, * the same way the hardware does (with WP pin). @@ -564,9 +580,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, pfl->ro = 0; #endif pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl); - pfl->base = base; pfl->sector_len = sector_len; - pfl->total_len = total_len; pfl->width = width; pfl->wcycle = 0; pfl->cmd = 0; @@ -620,7 +634,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, /* Max timeout for chip erase */ pfl->cfi_table[0x26] = 0x0D; /* Device size */ - pfl->cfi_table[0x27] = ctz32(total_len) + 1; + pfl->cfi_table[0x27] = ctz32(chip_len) + 1; /* Flash device interface (8 & 16 bits) */ pfl->cfi_table[0x28] = 0x02; pfl->cfi_table[0x29] = 0x00; |