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
This commit is contained in:
parent
6725070d8d
commit
4fbd24ba35
@ -11,7 +11,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
|
||||
/* pflash_cfi02.c */
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -235,8 +235,8 @@ static void ref405ep_init (int ram_size, int vga_ram_size,
|
||||
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
|
||||
#endif
|
||||
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 2,
|
||||
0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 1,
|
||||
2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
fl_idx++;
|
||||
} else
|
||||
#endif
|
||||
@ -552,8 +552,8 @@ static void taihu_405ep_init(int ram_size, int vga_ram_size,
|
||||
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
|
||||
#endif
|
||||
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 4,
|
||||
0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 1,
|
||||
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
fl_idx++;
|
||||
} else
|
||||
#endif
|
||||
@ -588,8 +588,8 @@ static void taihu_405ep_init(int ram_size, int vga_ram_size,
|
||||
bdrv_get_device_name(drives_table[index].bdrv));
|
||||
#endif
|
||||
pflash_cfi02_register(0xfc000000, bios_offset,
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 4,
|
||||
0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
drives_table[index].bdrv, 65536, fl_sectors, 1,
|
||||
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
|
||||
fl_idx++;
|
||||
}
|
||||
/* Register CLPD & LCD display */
|
||||
|
Loading…
Reference in New Issue
Block a user