pflash_cfi01/pflash_cfi02: convert to memory API

cfi02 is annoying in that is ignores some address bits; we probably
want explicit support in the memory API for that.

In order to get the correct opaque into the MemoryRegion object, the
allocation scheme is changed so that the flash emulation code allocates
memory, instead of the caller.  This clears a FIXME in the flash code.

Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Avi Kivity 2011-08-04 15:55:30 +03:00
parent ccbecf6237
commit cfe5f01104
18 changed files with 187 additions and 181 deletions

View File

@ -26,7 +26,6 @@ static void collie_init(ram_addr_t ram_size,
{
StrongARMState *s;
DriveInfo *dinfo;
ram_addr_t phys_flash;
if (!cpu_model) {
cpu_model = "sa1110";
@ -34,15 +33,13 @@ static void collie_init(ram_addr_t ram_size,
s = sa1110_init(collie_binfo.ram_size, cpu_model);
phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(SA_CS0, phys_flash,
pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
512, 4, 0x00, 0x00, 0x00, 0x00, 0);
phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
dinfo = drive_get(IF_PFLASH, 0, 1);
pflash_cfi01_register(SA_CS1, phys_flash,
pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
512, 4, 0x00, 0x00, 0x00, 0x00, 0);

View File

@ -1,15 +1,22 @@
/* NOR flash devices */
#include "memory.h"
typedef struct pflash_t pflash_t;
/* pflash_cfi01.c */
pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
pflash_t *pflash_cfi01_register(target_phys_addr_t base,
DeviceState *qdev, const char *name,
target_phys_addr_t size,
BlockDriverState *bs,
uint32_t sector_len, int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3, int be);
/* 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,
DeviceState *qdev, const char *name,
target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
@ -17,6 +24,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
uint16_t unlock_addr0, uint16_t unlock_addr1,
int be);
MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
/* nand.c */
DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,

View File

@ -67,8 +67,7 @@ static void connex_init(ram_addr_t ram_size,
#else
be = 0;
#endif
if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
connex_rom),
if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
dinfo->bdrv, sector_len, connex_rom / sector_len,
2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
@ -106,8 +105,7 @@ static void verdex_init(ram_addr_t ram_size,
#else
be = 0;
#endif
if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
verdex_rom),
if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
dinfo->bdrv, sector_len, verdex_rom / sector_len,
2, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");

View File

@ -77,7 +77,6 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
CPUState *env;
DriveInfo *dinfo;
ram_addr_t phys_ram;
ram_addr_t phys_flash;
qemu_irq *cpu_irq, irq[32];
ResetInfo *reset_info;
int i;
@ -108,10 +107,9 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used,
phys_ram = qemu_ram_alloc(NULL, "lm32_evr.sdram", ram_size);
cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "lm32_evr.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Spansion S29NS128P */
pflash_cfi02_register(flash_base, phys_flash,
pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 1, 2,
0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
@ -165,7 +163,6 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
CPUState *env;
DriveInfo *dinfo;
ram_addr_t phys_ram;
ram_addr_t phys_flash;
qemu_irq *cpu_irq, irq[32];
HWSetup *hw;
ResetInfo *reset_info;
@ -203,10 +200,9 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
phys_ram = qemu_ram_alloc(NULL, "lm32_uclinux.sdram", ram_size);
cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "lm32_uclinux.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Spansion S29NS128P */
pflash_cfi02_register(flash_base, phys_flash,
pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 1, 2,
0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);

View File

@ -126,10 +126,9 @@ static void mainstone_common_init(ram_addr_t ram_size,
exit(1);
}
if (!pflash_cfi01_register(mainstone_flash_base[i],
qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
"mainstone.flash0",
MAINSTONE_FLASH),
if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
i ? "mainstone.flash1" : "mainstone.flash0",
MAINSTONE_FLASH,
dinfo->bdrv, sector_len,
MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
be)) {

View File

@ -82,7 +82,6 @@ milkymist_init(ram_addr_t ram_size_not_used,
int kernel_size;
DriveInfo *dinfo;
ram_addr_t phys_sdram;
ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
int i;
char *bios_filename;
@ -113,10 +112,9 @@ milkymist_init(ram_addr_t ram_size_not_used,
cpu_register_physical_memory(sdram_base, sdram_size,
phys_sdram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "milkymist.flash", flash_size);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* Numonyx JS28F256J3F105 */
pflash_cfi01_register(flash_base, phys_flash,
pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
dinfo ? dinfo->bdrv : NULL, flash_sector_size,
flash_size / flash_sector_size, 2,
0x00, 0x89, 0x00, 0x1d, 1);

View File

@ -46,6 +46,7 @@
#include "elf.h"
#include "mc146818rtc.h"
#include "blockdev.h"
#include "exec-memory.h"
//#define DEBUG_BOARD_INIT
@ -761,8 +762,10 @@ void mips_malta_init (ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model)
{
char *filename;
pflash_t *fl;
ram_addr_t ram_offset;
ram_addr_t bios_offset;
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
target_long bios_size;
int64_t kernel_entry;
PCIBus *pci_bus;
@ -811,17 +814,9 @@ void mips_malta_init (ram_addr_t ram_size,
exit(1);
}
ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
/* Map the bios at two physical locations, as on the real board. */
cpu_register_physical_memory(0x1e000000LL,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_register_physical_memory(0x1fc00000LL,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
#else
@ -833,12 +828,19 @@ void mips_malta_init (ram_addr_t ram_size,
/* Load firmware in flash / BIOS unless we boot directly into a kernel. */
if (kernel_filename) {
/* Write a small bootloader to the flash location. */
bios = g_new(MemoryRegion, 1);
memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
memory_region_set_readonly(bios, true);
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
/* Map the bios at two physical locations, as on the real board. */
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
loaderparams.ram_size = ram_size;
loaderparams.kernel_filename = kernel_filename;
loaderparams.kernel_cmdline = kernel_cmdline;
loaderparams.initrd_filename = initrd_filename;
kernel_entry = load_kernel();
write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
} else {
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
if (dinfo) {
@ -847,15 +849,31 @@ void mips_malta_init (ram_addr_t ram_size,
fl_sectors = bios_size >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
"offset %08lx addr %08llx '%s' %x\n",
fl_idx, bios_size, bios_offset, 0x1e000000LL,
"addr %08llx '%s' %x\n",
fl_idx, bios_size, 0x1e000000LL,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
pflash_cfi01_register(0x1e000000LL, bios_offset,
dinfo->bdrv, 65536, fl_sectors,
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
fl_idx++;
fl = pflash_cfi01_register(0x1e000000LL,
NULL, "mips_malta.bios", BIOS_SIZE,
dinfo->bdrv, 65536, fl_sectors,
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
bios = pflash_cfi01_get_memory(fl);
/* Map the bios at two physical locations, as on the real board. */
memory_region_init_alias(bios_alias, "bios.1fc",
bios, 0, BIOS_SIZE);
memory_region_add_subregion(system_memory, 0x1fc00000LL,
bios_alias);
fl_idx++;
} else {
bios = g_new(MemoryRegion, 1);
memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
memory_region_set_readonly(bios, true);
memory_region_init_alias(bios_alias, "bios.1fc",
bios, 0, BIOS_SIZE);
/* Map the bios at two physical locations, as on the real board. */
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
memory_region_add_subregion(system_memory, 0x1fc00000LL,
bios_alias);
/* Load a BIOS image. */
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
@ -878,7 +896,7 @@ void mips_malta_init (ram_addr_t ram_size,
a neat trick which allows bi-endian firmware. */
#ifndef TARGET_WORDS_BIGENDIAN
{
uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
uint32_t *addr = memory_region_get_ram_ptr(bios);
uint32_t *end = addr + bios_size;
while (addr < end) {
bswap32s(addr);
@ -890,7 +908,7 @@ void mips_malta_init (ram_addr_t ram_size,
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_irq_init_cpu(env);

View File

@ -23,6 +23,7 @@
#include "elf.h"
#include "mc146818rtc.h"
#include "blockdev.h"
#include "exec-memory.h"
#define MAX_IDE_BUS 2
@ -163,7 +164,7 @@ void mips_r4k_init (ram_addr_t ram_size,
{
char *filename;
ram_addr_t ram_offset;
ram_addr_t bios_offset;
MemoryRegion *bios;
int bios_size;
CPUState *env;
ResetData *reset_info;
@ -227,15 +228,15 @@ void mips_r4k_init (ram_addr_t ram_size,
be = 0;
#endif
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
bios_offset | IO_MEM_ROM);
bios = g_new(MemoryRegion, 1);
memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE);
memory_region_set_readonly(bios, true);
memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
} else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
uint32_t mips_rom = 0x00400000;
bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
if (!pflash_cfi01_register(0x1fc00000, bios_offset,
if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
dinfo->bdrv, sector_len,
mips_rom / sector_len,
4, 0, 0, 0, 0, be)) {

View File

@ -1565,16 +1565,16 @@ static void musicpal_init(ram_addr_t ram_size,
* image is smaller than 32 MB.
*/
#ifdef TARGET_WORDS_BIGENDIAN
pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
"musicpal.flash", flash_size),
pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
"musicpal.flash", flash_size,
dinfo->bdrv, 0x10000,
(flash_size + 0xffff) >> 16,
MP_FLASH_SIZE_MAX / flash_size,
2, 0x00BF, 0x236D, 0x0000, 0x0000,
0x5555, 0x2AAA, 1);
#else
pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
"musicpal.flash", flash_size),
pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
"musicpal.flash", flash_size,
dinfo->bdrv, 0x10000,
(flash_size + 0xffff) >> 16,
MP_FLASH_SIZE_MAX / flash_size,

View File

@ -161,8 +161,8 @@ static void sx1_init(ram_addr_t ram_size,
#endif
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
"omap_sx1.flash0-1", flash_size),
if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
"omap_sx1.flash0-1", flash_size,
dinfo->bdrv, sector_size,
flash_size / sector_size,
4, 0, 0, 0, 0, be)) {
@ -182,8 +182,8 @@ static void sx1_init(ram_addr_t ram_size,
cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
OMAP_CS1_SIZE - flash1_size, io);
if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
"omap_sx1.flash1-1", flash1_size),
if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
"omap_sx1.flash1-1", flash1_size,
dinfo->bdrv, sector_size,
flash1_size / sector_size,
4, 0, 0, 0, 0, be)) {

View File

@ -149,7 +149,6 @@ petalogix_ml605_init(ram_addr_t ram_size,
target_phys_addr_t ddr_base = MEMORY_BASEADDR;
ram_addr_t phys_lmb_bram;
ram_addr_t phys_ram;
ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
/* init CPUs */
@ -169,11 +168,11 @@ petalogix_ml605_init(ram_addr_t ram_size,
phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size);
cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
/* 5th parameter 2 means bank-width
* 10th paremeter 0 means little-endian */
pflash_cfi01_register(FLASH_BASEADDR, phys_flash,
pflash_cfi01_register(FLASH_BASEADDR,
NULL, "petalogix_ml605.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
2, 0x89, 0x18, 0x0000, 0x0, 0);

View File

@ -127,7 +127,6 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
target_phys_addr_t ddr_base = 0x90000000;
ram_addr_t phys_lmb_bram;
ram_addr_t phys_ram;
ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
/* init CPUs */
@ -148,9 +147,9 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(0xa0000000, phys_flash,
pflash_cfi01_register(0xa0000000,
NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
1, 0x89, 0x18, 0x0000, 0x0, 1);

View File

@ -40,6 +40,7 @@
#include "flash.h"
#include "block.h"
#include "qemu-timer.h"
#include "exec-memory.h"
#define PFLASH_BUG(fmt, ...) \
do { \
@ -74,8 +75,7 @@ struct pflash_t {
target_phys_addr_t counter;
unsigned int writeblock_size;
QEMUTimer *timer;
ram_addr_t off;
int fl_mem;
MemoryRegion mem;
void *storage;
};
@ -89,8 +89,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);
memory_region_rom_device_set_readable(&pfl->mem, true);
pfl->wcycle = 0;
}
pfl->cmd = 0;
@ -263,7 +262,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
if (!pfl->wcycle) {
/* Set the device in I/O access mode */
cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
memory_region_rom_device_set_readable(&pfl->mem, false);
}
switch (pfl->wcycle) {
@ -422,8 +421,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
__func__, offset, pfl->wcycle, pfl->cmd, value);
reset_flash:
cpu_register_physical_memory(pfl->base, pfl->total_len,
pfl->off | IO_MEM_ROMD | pfl->fl_mem);
memory_region_rom_device_set_readable(&pfl->mem, true);
pfl->bypass = 0;
pfl->wcycle = 0;
@ -514,28 +512,20 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr,
pflash_write(pfl, addr, value, 4, 0);
}
static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
&pflash_writeb_be,
&pflash_writew_be,
&pflash_writel_be,
static const MemoryRegionOps pflash_cfi01_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 CPUReadMemoryFunc * const pflash_read_ops_be[] = {
&pflash_readb_be,
&pflash_readw_be,
&pflash_readl_be,
};
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,
static const MemoryRegionOps pflash_cfi01_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,
};
/* Count trailing zeroes of a 32 bits quantity */
@ -574,12 +564,13 @@ static int ctz32 (uint32_t n)
return ret;
}
pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
pflash_t *pflash_cfi01_register(target_phys_addr_t base,
DeviceState *qdev, const char *name,
target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3,
int be)
uint16_t id2, uint16_t id3, int be)
{
pflash_t *pfl;
target_phys_addr_t total_len;
@ -596,27 +587,19 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
pfl = g_malloc0(sizeof(pflash_t));
/* FIXME: Allocate ram ourselves. */
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;
cpu_register_physical_memory(base, total_len,
off | pfl->fl_mem | IO_MEM_ROMD);
memory_region_init_rom_device(
&pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
qdev, name, size);
pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
if (ret < 0) {
cpu_unregister_io_memory(pfl->fl_mem);
memory_region_del_subregion(get_system_memory(), &pfl->mem);
memory_region_destroy(&pfl->mem);
g_free(pfl);
return NULL;
}
@ -724,3 +707,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
return pfl;
}
MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
{
return &fl->mem;
}

View File

@ -39,6 +39,7 @@
#include "flash.h"
#include "qemu-timer.h"
#include "block.h"
#include "exec-memory.h"
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
@ -69,25 +70,38 @@ struct pflash_t {
uint8_t cfi_len;
uint8_t cfi_table[0x52];
QEMUTimer *timer;
ram_addr_t off;
int fl_mem;
/* 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;
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)
{
unsigned i;
target_phys_addr_t size = memory_region_size(&pfl->orig_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",
&pfl->orig_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)
{
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);
memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
}
static void pflash_timer (void *opaque)
@ -538,28 +552,20 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr,
pflash_write(pfl, addr, value, 4, 0);
}
static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
&pflash_writeb_be,
&pflash_writew_be,
&pflash_writel_be,
static 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 CPUReadMemoryFunc * const pflash_read_ops_be[] = {
&pflash_readb_be,
&pflash_readw_be,
&pflash_readl_be,
};
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,
static 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,
};
/* Count trailing zeroes of a 32 bits quantity */
@ -598,7 +604,9 @@ static int ctz32 (uint32_t n)
return ret;
}
pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
pflash_t *pflash_cfi02_register(target_phys_addr_t base,
DeviceState *qdev, const char *name,
target_phys_addr_t size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
@ -618,32 +626,25 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
return NULL;
#endif
pfl = g_malloc0(sizeof(pflash_t));
/* FIXME: Allocate ram ourselves. */
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;
memory_region_init_rom_device(
&pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
qdev, name, size);
pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
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);
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).
*/

View File

@ -32,6 +32,7 @@
#include "qemu-log.h"
#include "loader.h"
#include "blockdev.h"
#include "exec-memory.h"
#define BIOS_FILENAME "ppc405_rom.bin"
#define BIOS_SIZE (2048 * 1024)
@ -181,7 +182,8 @@ static void ref405ep_init (ram_addr_t ram_size,
ppc4xx_bd_info_t bd;
CPUPPCState *env;
qemu_irq *pic;
ram_addr_t sram_offset, bios_offset, bdloc;
MemoryRegion *bios;
ram_addr_t sram_offset, bdloc;
MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
target_phys_addr_t ram_bases[2], ram_sizes[2];
target_ulong sram_size;
@ -224,15 +226,15 @@ static void ref405ep_init (ram_addr_t ram_size,
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
if (dinfo) {
bios_size = bdrv_getlength(dinfo->bdrv);
bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
fl_sectors = (bios_size + 65535) >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
" at offset %08lx addr %lx '%s' %d\n",
fl_idx, bios_size, bios_offset, -bios_size,
" at addr %lx '%s' %d\n",
fl_idx, bios_size, -bios_size,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
pflash_cfi02_register((uint32_t)(-bios_size),
NULL, "ef405ep.bios", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);
@ -243,12 +245,13 @@ static void ref405ep_init (ram_addr_t ram_size,
#ifdef DEBUG_BOARD_INIT
printf("Load BIOS from file\n");
#endif
bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
bios = g_new(MemoryRegion, 1);
memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
} else {
bios_size = -1;
@ -259,8 +262,9 @@ static void ref405ep_init (ram_addr_t ram_size,
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
memory_region_set_readonly(bios, true);
memory_region_add_subregion(get_system_memory(),
(uint32_t)(-bios_size), bios);
}
/* Register FPGA */
#ifdef DEBUG_BOARD_INIT
@ -507,7 +511,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
{
char *filename;
qemu_irq *pic;
ram_addr_t bios_offset;
MemoryRegion *bios;
MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
target_phys_addr_t ram_bases[2], ram_sizes[2];
long bios_size;
@ -544,14 +548,14 @@ static void taihu_405ep_init(ram_addr_t ram_size,
/* XXX: should check that size is 2MB */
// bios_size = 2 * 1024 * 1024;
fl_sectors = (bios_size + 65535) >> 16;
bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
" at offset %08lx addr %lx '%s' %d\n",
fl_idx, bios_size, bios_offset, -bios_size,
" at addr %lx '%s' %d\n",
fl_idx, bios_size, -bios_size,
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
#endif
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
pflash_cfi02_register((uint32_t)(-bios_size),
NULL, "taihu_405ep.bios", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);
@ -564,10 +568,11 @@ static void taihu_405ep_init(ram_addr_t ram_size,
#endif
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
bios = g_new(MemoryRegion, 1);
memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
} else {
bios_size = -1;
@ -578,8 +583,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
memory_region_set_readonly(bios, true);
memory_region_add_subregion(get_system_memory(), (uint32_t)(-bios_size),
bios);
}
/* Register Linux flash */
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
@ -590,12 +596,11 @@ static void taihu_405ep_init(ram_addr_t ram_size,
fl_sectors = (bios_size + 65535) >> 16;
#ifdef DEBUG_BOARD_INIT
printf("Register parallel flash %d size %lx"
" at offset %08lx addr " TARGET_FMT_lx " '%s'\n",
fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
" at addr " TARGET_FMT_lx " '%s'\n",
fl_idx, bios_size, (target_ulong)0xfc000000,
bdrv_get_device_name(dinfo->bdrv));
#endif
bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
pflash_cfi02_register(0xfc000000, bios_offset,
pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
dinfo->bdrv, 65536, fl_sectors, 1,
4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
1);

View File

@ -267,7 +267,7 @@ static void r2d_init(ram_addr_t ram_size,
/* onboard flash memory */
dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (16 * 1024),
FLASH_SIZE >> 16,
1, 4, 0x0000, 0x0000, 0x0000, 0x0000,

View File

@ -196,7 +196,6 @@ static void virtex_init(ram_addr_t ram_size,
target_phys_addr_t ram_base = 0;
DriveInfo *dinfo;
ram_addr_t phys_ram;
ram_addr_t phys_flash;
qemu_irq irq[32], *cpu_irq;
clk_setup_t clk_setup[7];
int kernel_size;
@ -215,9 +214,8 @@ static void virtex_init(ram_addr_t ram_size,
phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(0xfc000000, phys_flash,
pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
dinfo ? dinfo->bdrv : NULL, (64 * 1024),
FLASH_SIZE >> 16,
1, 0x89, 0x18, 0x0000, 0x0, 1);

View File

@ -305,7 +305,7 @@ static void z2_init(ram_addr_t ram_size,
}
if (!pflash_cfi01_register(Z2_FLASH_BASE,
qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE),
NULL, "z2.flash0", Z2_FLASH_SIZE,
dinfo->bdrv, sector_len,
Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
be)) {