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_cfi02.c */
 | 
				
			||||||
pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 | 
					pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 | 
				
			||||||
                                BlockDriverState *bs, uint32_t sector_len,
 | 
					                                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 id0, uint16_t id1,
 | 
				
			||||||
                                uint16_t id2, uint16_t id3,
 | 
					                                uint16_t id2, uint16_t id3,
 | 
				
			||||||
                                uint16_t unlock_addr0, uint16_t unlock_addr1);
 | 
					                                uint16_t unlock_addr0, uint16_t unlock_addr1);
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,8 @@ struct pflash_t {
 | 
				
			|||||||
    BlockDriverState *bs;
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
    target_phys_addr_t base;
 | 
					    target_phys_addr_t base;
 | 
				
			||||||
    uint32_t sector_len;
 | 
					    uint32_t sector_len;
 | 
				
			||||||
    uint32_t total_len;
 | 
					    uint32_t chip_len;
 | 
				
			||||||
 | 
					    int mappings;
 | 
				
			||||||
    int width;
 | 
					    int width;
 | 
				
			||||||
    int wcycle; /* if 0, the flash is read normally */
 | 
					    int wcycle; /* if 0, the flash is read normally */
 | 
				
			||||||
    int bypass;
 | 
					    int bypass;
 | 
				
			||||||
@ -72,6 +73,19 @@ struct pflash_t {
 | 
				
			|||||||
    void *storage;
 | 
					    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)
 | 
					static void pflash_timer (void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    pflash_t *pfl = opaque;
 | 
					    pflash_t *pfl = opaque;
 | 
				
			||||||
@ -82,8 +96,7 @@ static void pflash_timer (void *opaque)
 | 
				
			|||||||
    if (pfl->bypass) {
 | 
					    if (pfl->bypass) {
 | 
				
			||||||
        pfl->wcycle = 2;
 | 
					        pfl->wcycle = 2;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        cpu_register_physical_memory(pfl->base, pfl->total_len,
 | 
					        pflash_register_memory(pfl, 1);
 | 
				
			||||||
                                     pfl->off | IO_MEM_ROMD | pfl->fl_mem);
 | 
					 | 
				
			||||||
        pfl->wcycle = 0;
 | 
					        pfl->wcycle = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pfl->cmd = 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);
 | 
					    DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset);
 | 
				
			||||||
    ret = -1;
 | 
					    ret = -1;
 | 
				
			||||||
    offset -= pfl->base;
 | 
					    offset -= pfl->base;
 | 
				
			||||||
 | 
					    offset &= pfl->chip_len - 1;
 | 
				
			||||||
    boff = offset & 0xFF;
 | 
					    boff = offset & 0xFF;
 | 
				
			||||||
    if (pfl->width == 2)
 | 
					    if (pfl->width == 2)
 | 
				
			||||||
        boff = boff >> 1;
 | 
					        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;
 | 
					        offset -= (uint32_t)(long)pfl->storage;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        offset -= pfl->base;
 | 
					        offset -= pfl->base;
 | 
				
			||||||
 | 
					    offset &= pfl->chip_len - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
 | 
					    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
 | 
				
			||||||
            offset, value, width);
 | 
					            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);
 | 
					    boff = offset & (pfl->sector_len - 1);
 | 
				
			||||||
    if (pfl->width == 2)
 | 
					    if (pfl->width == 2)
 | 
				
			||||||
        boff = boff >> 1;
 | 
					        boff = boff >> 1;
 | 
				
			||||||
@ -238,6 +251,8 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value,
 | 
				
			|||||||
        boff = boff >> 2;
 | 
					        boff = boff >> 2;
 | 
				
			||||||
    switch (pfl->wcycle) {
 | 
					    switch (pfl->wcycle) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
 | 
					        /* Set the device in I/O access mode */
 | 
				
			||||||
 | 
					        pflash_register_memory(pfl, 0);
 | 
				
			||||||
        /* We're in read mode */
 | 
					        /* We're in read mode */
 | 
				
			||||||
    check_unlock0:
 | 
					    check_unlock0:
 | 
				
			||||||
        if (boff == 0x55 && cmd == 0x98) {
 | 
					        if (boff == 0x55 && cmd == 0x98) {
 | 
				
			||||||
@ -369,9 +384,9 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value,
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            /* Chip erase */
 | 
					            /* Chip erase */
 | 
				
			||||||
            DPRINTF("%s: start chip erase\n", __func__);
 | 
					            DPRINTF("%s: start chip erase\n", __func__);
 | 
				
			||||||
            memset(pfl->storage, 0xFF, pfl->total_len);
 | 
					            memset(pfl->storage, 0xFF, pfl->chip_len);
 | 
				
			||||||
            pfl->status = 0x00;
 | 
					            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 */
 | 
					            /* Let's wait 5 seconds before chip erase is done */
 | 
				
			||||||
            qemu_mod_timer(pfl->timer,
 | 
					            qemu_mod_timer(pfl->timer,
 | 
				
			||||||
                           qemu_get_clock(vm_clock) + (ticks_per_sec * 5));
 | 
					                           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 */
 | 
				
			||||||
 reset_flash:
 | 
					 reset_flash:
 | 
				
			||||||
    cpu_register_physical_memory(pfl->base, pfl->total_len,
 | 
					    pflash_register_memory(pfl, 1);
 | 
				
			||||||
                                 pfl->off | IO_MEM_ROMD | pfl->fl_mem);
 | 
					 | 
				
			||||||
    pfl->bypass = 0;
 | 
					    pfl->bypass = 0;
 | 
				
			||||||
    pfl->wcycle = 0;
 | 
					    pfl->wcycle = 0;
 | 
				
			||||||
    pfl->cmd = 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,
 | 
					pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 | 
				
			||||||
                                BlockDriverState *bs, uint32_t sector_len,
 | 
					                                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 id0, uint16_t id1,
 | 
				
			||||||
                                uint16_t id2, uint16_t id3,
 | 
					                                uint16_t id2, uint16_t id3,
 | 
				
			||||||
                                uint16_t unlock_addr0, uint16_t unlock_addr1)
 | 
					                                uint16_t unlock_addr0, uint16_t unlock_addr1)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    pflash_t *pfl;
 | 
					    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 */
 | 
					    /* XXX: to be fixed */
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
    if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
 | 
					    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->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops,
 | 
				
			||||||
                                         pfl);
 | 
					                                         pfl);
 | 
				
			||||||
    pfl->off = off;
 | 
					    pfl->off = off;
 | 
				
			||||||
    cpu_register_physical_memory(base, total_len,
 | 
					    pfl->base = base;
 | 
				
			||||||
                                 off | pfl->fl_mem | IO_MEM_ROMD);
 | 
					    pfl->chip_len = chip_len;
 | 
				
			||||||
 | 
					    pfl->mappings = nb_mappings;
 | 
				
			||||||
 | 
					    pflash_register_memory(pfl, 1);
 | 
				
			||||||
    pfl->bs = bs;
 | 
					    pfl->bs = bs;
 | 
				
			||||||
    if (pfl->bs) {
 | 
					    if (pfl->bs) {
 | 
				
			||||||
        /* read the initial flash content */
 | 
					        /* 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,
 | 
					#if 0 /* XXX: there should be a bit to set up read-only,
 | 
				
			||||||
       *      the same way the hardware does (with WP pin).
 | 
					       *      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;
 | 
					    pfl->ro = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
 | 
					    pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
 | 
				
			||||||
    pfl->base = base;
 | 
					 | 
				
			||||||
    pfl->sector_len = sector_len;
 | 
					    pfl->sector_len = sector_len;
 | 
				
			||||||
    pfl->total_len = total_len;
 | 
					 | 
				
			||||||
    pfl->width = width;
 | 
					    pfl->width = width;
 | 
				
			||||||
    pfl->wcycle = 0;
 | 
					    pfl->wcycle = 0;
 | 
				
			||||||
    pfl->cmd = 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 */
 | 
					    /* Max timeout for chip erase */
 | 
				
			||||||
    pfl->cfi_table[0x26] = 0x0D;
 | 
					    pfl->cfi_table[0x26] = 0x0D;
 | 
				
			||||||
    /* Device size */
 | 
					    /* Device size */
 | 
				
			||||||
    pfl->cfi_table[0x27] = ctz32(total_len) + 1;
 | 
					    pfl->cfi_table[0x27] = ctz32(chip_len) + 1;
 | 
				
			||||||
    /* Flash device interface (8 & 16 bits) */
 | 
					    /* Flash device interface (8 & 16 bits) */
 | 
				
			||||||
    pfl->cfi_table[0x28] = 0x02;
 | 
					    pfl->cfi_table[0x28] = 0x02;
 | 
				
			||||||
    pfl->cfi_table[0x29] = 0x00;
 | 
					    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);
 | 
					               bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
 | 
					        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
 | 
				
			||||||
                              drives_table[index].bdrv, 65536, fl_sectors, 2,
 | 
					                              drives_table[index].bdrv, 65536, fl_sectors, 1,
 | 
				
			||||||
                              0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
					                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
				
			||||||
        fl_idx++;
 | 
					        fl_idx++;
 | 
				
			||||||
    } else
 | 
					    } else
 | 
				
			||||||
#endif
 | 
					#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);
 | 
					               bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
 | 
					        pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
 | 
				
			||||||
                              drives_table[index].bdrv, 65536, fl_sectors, 4,
 | 
					                              drives_table[index].bdrv, 65536, fl_sectors, 1,
 | 
				
			||||||
                              0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
					                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
				
			||||||
        fl_idx++;
 | 
					        fl_idx++;
 | 
				
			||||||
    } else
 | 
					    } else
 | 
				
			||||||
#endif
 | 
					#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));
 | 
					               bdrv_get_device_name(drives_table[index].bdrv));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        pflash_cfi02_register(0xfc000000, bios_offset,
 | 
					        pflash_cfi02_register(0xfc000000, bios_offset,
 | 
				
			||||||
                              drives_table[index].bdrv, 65536, fl_sectors, 4,
 | 
					                              drives_table[index].bdrv, 65536, fl_sectors, 1,
 | 
				
			||||||
                              0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
					                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
 | 
				
			||||||
        fl_idx++;
 | 
					        fl_idx++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Register CLPD & LCD display */
 | 
					    /* Register CLPD & LCD display */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user