From c8b153d79493e83113f1eb3055de5f31f104f4c5 Mon Sep 17 00:00:00 2001 From: ths Date: Fri, 4 Jan 2008 19:11:32 +0000 Subject: [PATCH] Malta flash support. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3887 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile.target | 1 + hw/mips_malta.c | 81 +++++++++++++++++++++++++++++------------------ hw/pflash_cfi01.c | 37 +++++++++++++--------- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Makefile.target b/Makefile.target index 629f09da9a..cc8facb7ea 100644 --- a/Makefile.target +++ b/Makefile.target @@ -470,6 +470,7 @@ VL_OBJS+= jazz_led.o VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o VL_OBJS+= piix_pci.o parallel.o cirrus_vga.o $(SOUND_HW) VL_OBJS+= mipsnet.o +VL_OBJS+= pflash_cfi01.o CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), cris) diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 6af5e52dc4..1ab594098e 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -28,6 +28,8 @@ #include "net.h" #include "boards.h" #include "smbus.h" +#include "block.h" +#include "flash.h" #include "mips.h" #include "pci.h" #include "qemu-char.h" @@ -35,6 +37,8 @@ #include "audio/audio.h" #include "boards.h" +//#define DEBUG_BOARD_INIT + #ifdef TARGET_WORDS_BIGENDIAN #define BIOS_FILENAME "mips_bios.bin" #else @@ -766,13 +770,13 @@ void mips_malta_init (int ram_size, int vga_ram_size, { char buf[1024]; unsigned long bios_offset; + target_long bios_size; int64_t kernel_entry; PCIBus *pci_bus; CPUState *env; RTCState *rtc_state; fdctrl_t *floppy_controller; MaltaFPGAState *malta_fpga; - int ret; qemu_irq *i8259; int piix4_devfn; uint8_t *eeprom_buf; @@ -781,6 +785,8 @@ void mips_malta_init (int ram_size, int vga_ram_size, int index; BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; + int fl_idx = 0; + int fl_sectors = 0; /* init CPUs */ if (cpu_model == NULL) { @@ -801,7 +807,7 @@ void mips_malta_init (int ram_size, int vga_ram_size, /* allocate RAM */ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); - /* Map the bios at two physical locations, as on the real board */ + /* Map the bios at two physical locations, as on the real board. */ bios_offset = ram_size + vga_ram_size; cpu_register_physical_memory(0x1e000000LL, BIOS_SIZE, bios_offset | IO_MEM_ROM); @@ -811,35 +817,9 @@ void mips_malta_init (int ram_size, int vga_ram_size, /* FPGA */ malta_fpga = malta_fpga_init(0x1f000000LL, env); - /* Load a BIOS image unless a kernel image has been specified. */ - if (!kernel_filename) { - if (bios_name == NULL) - bios_name = BIOS_FILENAME; - snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); - ret = load_image(buf, phys_ram_base + bios_offset); - if (ret < 0 || ret > BIOS_SIZE) { - fprintf(stderr, - "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", - buf); - exit(1); - } - /* In little endian mode the 32bit words in the bios are swapped, - a neat trick which allows bi-endian firmware. */ -#ifndef TARGET_WORDS_BIGENDIAN - { - uint32_t *addr; - for (addr = (uint32_t *)(phys_ram_base + bios_offset); - addr < (uint32_t *)(phys_ram_base + bios_offset + ret); - addr++) { - *addr = bswap32(*addr); - } - } -#endif - } - - /* If a kernel image has been specified, write a small bootloader - to the flash location. */ + /* Load firmware in flash / BIOS unless we boot directly into a kernel. */ if (kernel_filename) { + /* Write a small bootloader to the flash location. */ loaderparams.ram_size = ram_size; loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; @@ -847,6 +827,47 @@ void mips_malta_init (int ram_size, int vga_ram_size, kernel_entry = load_kernel(env); env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); write_bootloader(env, bios_offset, kernel_entry); + } else { + index = drive_get_index(IF_PFLASH, 0, fl_idx); + if (index != -1) { + /* Load firmware from flash. */ + bios_size = 0x400000; + 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, + bdrv_get_device_name(drives_table[index].bdrv), fl_sectors); +#endif + pflash_cfi01_register(0x1e000000LL, bios_offset, + drives_table[index].bdrv, 65536, fl_sectors, + 4, 0x0000, 0x0000, 0x0000, 0x0000); + fl_idx++; + } else { + /* Load a BIOS image. */ + if (bios_name == NULL) + bios_name = BIOS_FILENAME; + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); + bios_size = load_image(buf, phys_ram_base + bios_offset); + if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + fprintf(stderr, + "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", + buf); + exit(1); + } + } + /* In little endian mode the 32bit words in the bios are swapped, + a neat trick which allows bi-endian firmware. */ +#ifndef TARGET_WORDS_BIGENDIAN + { + uint32_t *addr; + for (addr = (uint32_t *)(phys_ram_base + bios_offset); + addr < (uint32_t *)(phys_ram_base + bios_offset + bios_size); + addr++) { + *addr = bswap32(*addr); + } + } +#endif } /* Board ID = 0x420 (Malta Board with CoreLV) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 745f5e57c5..b3a8a8e3fb 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -111,8 +111,8 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width) else if (pfl->width == 4) boff = boff >> 2; - DPRINTF("%s: reading offset %08x under cmd %02x\n", - __func__, boff, pfl->cmd); + DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x\n", + __func__, boff, pfl->cmd); switch (pfl->cmd) { case 0x00: @@ -121,7 +121,8 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width) switch (width) { case 1: ret = p[offset]; - DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret); + DPRINTF("%s: data offset " TARGET_FMT_lx " %02x\n", + __func__, offset, ret); break; case 2: #if defined(TARGET_WORDS_BIGENDIAN) @@ -131,7 +132,8 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width) ret = p[offset]; ret |= p[offset + 1] << 8; #endif - DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret); + DPRINTF("%s: data offset " TARGET_FMT_lx " %04x\n", + __func__, offset, ret); break; case 4: #if defined(TARGET_WORDS_BIGENDIAN) @@ -146,7 +148,8 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width) ret |= p[offset + 2] << 16; ret |= p[offset + 3] << 24; #endif - DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret); + DPRINTF("%s: data offset " TARGET_FMT_lx " %08x\n", + __func__, offset, ret); break; default: DPRINTF("BUG in %s\n", __func__); @@ -208,8 +211,8 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, else offset -= pfl->base; - DPRINTF("%s: offset %08x %08x %d wcycle 0x%x\n", - __func__, offset, value, width, pfl->wcycle); + DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d wcycle 0x%x\n", + __func__, offset, value, width, pfl->wcycle); /* Set the device in I/O access mode */ cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem); @@ -230,8 +233,9 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, p = pfl->storage; offset &= ~(pfl->sector_len - 1); - DPRINTF("%s: block erase at 0x%x bytes 0x%x\n", __func__, - offset, pfl->sector_len); + DPRINTF("%s: block erase at " TARGET_FMT_lx " bytes " + TARGET_FMT_lx "\n", + __func__, offset, pfl->sector_len); memset(p + offset, 0xff, pfl->sector_len); pflash_update(pfl, offset, pfl->sector_len); @@ -278,7 +282,7 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, break; case 0xe8: - DPRINTF("%s: block write of 0x%x bytes\n", __func__, cmd); + DPRINTF("%s: block write of %x bytes\n", __func__, cmd); pfl->counter = cmd; pfl->wcycle++; break; @@ -311,8 +315,9 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, switch (pfl->cmd) { case 0xe8: /* Block write */ p = pfl->storage; - DPRINTF("%s: block write offset 0x%x value 0x%x counter 0x%x\n", - __func__, offset, value, pfl->counter); + DPRINTF("%s: block write offset " TARGET_FMT_lx + " value %x counter " TARGET_FMT_lx "\n", + __func__, offset, value, pfl->counter); switch (width) { case 1: p[offset] = value; @@ -382,8 +387,8 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, error_flash: printf("%s: Unimplemented flash cmd sequence " - "(offset 0x%x, wcycle 0x%x cmd 0x%x value 0x%x\n", - __func__, offset, pfl->wcycle, pfl->cmd, value); + "(offset " TARGET_FMT_lx ", wcycle 0x%x cmd 0x%x value 0x%x\n", + __func__, offset, pfl->wcycle, pfl->cmd, value); reset_flash: cpu_register_physical_memory(pfl->base, pfl->total_len, @@ -484,7 +489,7 @@ static int ctz32 (uint32_t n) } pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off, - BlockDriverState *bs, target_ulong sector_len, + BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3) @@ -495,9 +500,11 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off, total_len = sector_len * nb_blocs; /* XXX: to be fixed */ +#if 0 if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) return NULL; +#endif pfl = qemu_mallocz(sizeof(pflash_t));