r3627 - in trunk/src/host/qemu-neo1973: . hw linux-user linux-user/ppc target-arm target-i386 target-m68k target-mips target-ppc target-sparc
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Mon Dec 10 18:51:53 CET 2007
Author: andrew
Date: 2007-12-10 18:51:36 +0100 (Mon, 10 Dec 2007)
New Revision: 3627
Added:
trunk/src/host/qemu-neo1973/hw/eccmemctl.c
Modified:
trunk/src/host/qemu-neo1973/Makefile
trunk/src/host/qemu-neo1973/Makefile.target
trunk/src/host/qemu-neo1973/configure
trunk/src/host/qemu-neo1973/cpu-defs.h
trunk/src/host/qemu-neo1973/exec.c
trunk/src/host/qemu-neo1973/hw/esp.c
trunk/src/host/qemu-neo1973/hw/flash.h
trunk/src/host/qemu-neo1973/hw/gumstix.c
trunk/src/host/qemu-neo1973/hw/ide.c
trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
trunk/src/host/qemu-neo1973/hw/mainstone.c
trunk/src/host/qemu-neo1973/hw/mainstone.h
trunk/src/host/qemu-neo1973/hw/mips_r4k.c
trunk/src/host/qemu-neo1973/hw/omap.c
trunk/src/host/qemu-neo1973/hw/omap.h
trunk/src/host/qemu-neo1973/hw/pci.c
trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c
trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
trunk/src/host/qemu-neo1973/hw/piix_pci.c
trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
trunk/src/host/qemu-neo1973/hw/scsi-disk.c
trunk/src/host/qemu-neo1973/hw/scsi-disk.h
trunk/src/host/qemu-neo1973/hw/sun4m.c
trunk/src/host/qemu-neo1973/hw/sun4m.h
trunk/src/host/qemu-neo1973/hw/usb-msd.c
trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/socket.h
trunk/src/host/qemu-neo1973/linux-user/syscall.c
trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
trunk/src/host/qemu-neo1973/target-arm/helper.c
trunk/src/host/qemu-neo1973/target-i386/exec.h
trunk/src/host/qemu-neo1973/target-i386/helper.c
trunk/src/host/qemu-neo1973/target-i386/helper2.c
trunk/src/host/qemu-neo1973/target-i386/op.c
trunk/src/host/qemu-neo1973/target-i386/translate.c
trunk/src/host/qemu-neo1973/target-m68k/helper.c
trunk/src/host/qemu-neo1973/target-mips/translate.c
trunk/src/host/qemu-neo1973/target-ppc/cpu.h
trunk/src/host/qemu-neo1973/target-ppc/helper.c
trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
trunk/src/host/qemu-neo1973/target-sparc/translate.c
Log:
Weekly sync with cvs.savannah.nongnu.org.
Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/Makefile 2007-12-10 17:51:36 UTC (rev 3627)
@@ -264,6 +264,7 @@
$(bindir)/qemu-system-arm \
$(bindir)/qemu-system-m68k \
$(bindir)/qemu-system-sh4 \
+ $(bindir)/qemu-system-sh4eb \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-armeb \
@@ -279,6 +280,7 @@
$(bindir)/qemu-alpha \
$(bindir)/qemu-m68k \
$(bindir)/qemu-sh4 \
+ $(bindir)/qemu-sh4eb \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/Makefile.target 2007-12-10 17:51:36 UTC (rev 3627)
@@ -490,7 +490,7 @@
else
VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
-VL_OBJS+= cs4231.o ptimer.o
+VL_OBJS+= cs4231.o ptimer.o eccmemctl.o
endif
endif
ifeq ($(TARGET_BASE_ARCH), arm)
Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/configure 2007-12-10 17:51:36 UTC (rev 3627)
@@ -526,11 +526,11 @@
if test -z "$target_list" ; then
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
- target_list="i386-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc-softmmu ppcemb-softmmu ppc64-softmmu m68k-softmmu sh4-softmmu cris-softmmu"
+ target_list="i386-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc-softmmu ppcemb-softmmu ppc64-softmmu m68k-softmmu sh4-softmmu sh4eb-softmmu cris-softmmu"
fi
# the following are Linux specific
if [ "$linux_user" = "yes" ] ; then
- target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user sparc64-linux-user sparc32plus-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user sh4-linux-user ppc-linux-user ppc64-linux-user ppc64abi32-linux-user x86_64-linux-user cris-linux-user $target_list"
+ target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user sparc64-linux-user sparc32plus-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user sh4-linux-user sh4eb-linux-user ppc-linux-user ppc64-linux-user ppc64abi32-linux-user x86_64-linux-user cris-linux-user $target_list"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -146,6 +146,8 @@
void *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
/* user data */ \
- void *opaque;
+ void *opaque; \
+ \
+ const char *cpu_model_str;
#endif
Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/exec.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -1317,9 +1317,7 @@
CPUState *cpu_copy(CPUState *env)
{
-#if 0
- /* XXX: broken, must be handled by each CPU */
- CPUState *new_env = cpu_init();
+ CPUState *new_env = cpu_init(env->cpu_model_str);
/* preserve chaining and index */
CPUState *next_cpu = new_env->next_cpu;
int cpu_index = new_env->cpu_index;
@@ -1327,9 +1325,6 @@
new_env->next_cpu = next_cpu;
new_env->cpu_index = cpu_index;
return new_env;
-#else
- return NULL;
-#endif
}
#if !defined(CONFIG_USER_ONLY)
Added: trunk/src/host/qemu-neo1973/hw/eccmemctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eccmemctl.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/eccmemctl.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -0,0 +1,266 @@
+/*
+ * QEMU Sparc Sun4m ECC memory controller emulation
+ *
+ * Copyright (c) 2007 Robert Reif
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "sun4m.h"
+#include "sysemu.h"
+
+//#define DEBUG_ECC
+
+#ifdef DEBUG_ECC
+#define DPRINTF(fmt, args...) \
+ do { printf("ECC: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+/* There are 3 versions of this chip used in SMP sun4m systems:
+ * MCC (version 0, implementation 0) SS-600MP
+ * EMC (version 0, implementation 1) SS-10
+ * SMC (version 0, implementation 2) SS-10SX and SS-20
+ */
+
+/* Register offsets */
+#define ECC_FCR_REG 0
+#define ECC_FSR_REG 8
+#define ECC_FAR0_REG 16
+#define ECC_FAR1_REG 20
+#define ECC_DIAG_REG 24
+
+/* ECC fault control register */
+#define ECC_FCR_EE 0x00000001 /* Enable ECC checking */
+#define ECC_FCR_EI 0x00000010 /* Enable Interrupts on correctable errors */
+#define ECC_FCR_VER 0x0f000000 /* Version */
+#define ECC_FCR_IMPL 0xf0000000 /* Implementation */
+
+/* ECC fault status register */
+#define ECC_FSR_CE 0x00000001 /* Correctable error */
+#define ECC_FSR_BS 0x00000002 /* C2 graphics bad slot access */
+#define ECC_FSR_TO 0x00000004 /* Timeout on write */
+#define ECC_FSR_UE 0x00000008 /* Uncorrectable error */
+#define ECC_FSR_DW 0x000000f0 /* Index of double word in block */
+#define ECC_FSR_SYND 0x0000ff00 /* Syndrome for correctable error */
+#define ECC_FSR_ME 0x00010000 /* Multiple errors */
+#define ECC_FSR_C2ERR 0x00020000 /* C2 graphics error */
+
+/* ECC fault address register 0 */
+#define ECC_FAR0_PADDR 0x0000000f /* PA[32-35] */
+#define ECC_FAR0_TYPE 0x000000f0 /* Transaction type */
+#define ECC_FAR0_SIZE 0x00000700 /* Transaction size */
+#define ECC_FAR0_CACHE 0x00000800 /* Mapped cacheable */
+#define ECC_FAR0_LOCK 0x00001000 /* Error occurred in attomic cycle */
+#define ECC_FAR0_BMODE 0x00002000 /* Boot mode */
+#define ECC_FAR0_VADDR 0x003fc000 /* VA[12-19] (superset bits) */
+#define ECC_FAR0_S 0x08000000 /* Supervisor mode */
+#define ECC_FARO_MID 0xf0000000 /* Module ID */
+
+/* ECC diagnostic register */
+#define ECC_DIAG_CBX 0x00000001
+#define ECC_DIAG_CB0 0x00000002
+#define ECC_DIAG_CB1 0x00000004
+#define ECC_DIAG_CB2 0x00000008
+#define ECC_DIAG_CB4 0x00000010
+#define ECC_DIAG_CB8 0x00000020
+#define ECC_DIAG_CB16 0x00000040
+#define ECC_DIAG_CB32 0x00000080
+#define ECC_DIAG_DMODE 0x00000c00
+
+#define ECC_NREGS 8
+#define ECC_SIZE (ECC_NREGS * sizeof(uint32_t))
+#define ECC_ADDR_MASK (ECC_SIZE - 1)
+
+typedef struct ECCState {
+ uint32_t regs[ECC_NREGS];
+} ECCState;
+
+static void ecc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ printf("ECC: Unsupported write 0x" TARGET_FMT_plx " %02x\n",
+ addr, val & 0xff);
+}
+
+static uint32_t ecc_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ printf("ECC: Unsupported read 0x" TARGET_FMT_plx " 00\n", addr);
+ return 0;
+}
+
+static void ecc_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ printf("ECC: Unsupported write 0x" TARGET_FMT_plx " %04x\n",
+ addr, val & 0xffff);
+}
+
+static uint32_t ecc_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ printf("ECC: Unsupported read 0x" TARGET_FMT_plx " 0000\n", addr);
+ return 0;
+}
+
+static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ ECCState *s = opaque;
+
+ switch (addr & ECC_ADDR_MASK) {
+ case ECC_FCR_REG:
+ s->regs[0] = (s->regs[0] & (ECC_FCR_VER | ECC_FCR_IMPL)) |
+ (val & ~(ECC_FCR_VER | ECC_FCR_IMPL));
+ DPRINTF("Write fault control %08x\n", val);
+ break;
+ case 4:
+ s->regs[1] = val;
+ DPRINTF("Write reg[1] %08x\n", val);
+ break;
+ case ECC_FSR_REG:
+ s->regs[2] = val;
+ DPRINTF("Write fault status %08x\n", val);
+ break;
+ case 12:
+ s->regs[3] = val;
+ DPRINTF("Write reg[3] %08x\n", val);
+ break;
+ case ECC_FAR0_REG:
+ s->regs[4] = val;
+ DPRINTF("Write fault address 0 %08x\n", val);
+ break;
+ case ECC_FAR1_REG:
+ s->regs[5] = val;
+ DPRINTF("Write fault address 1 %08x\n", val);
+ break;
+ case ECC_DIAG_REG:
+ s->regs[6] = val;
+ DPRINTF("Write diag %08x\n", val);
+ break;
+ case 28:
+ s->regs[7] = val;
+ DPRINTF("Write reg[7] %08x\n", val);
+ break;
+ }
+}
+
+static uint32_t ecc_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ ECCState *s = opaque;
+ uint32_t ret = 0;
+
+ switch (addr & ECC_ADDR_MASK) {
+ case ECC_FCR_REG:
+ ret = s->regs[0];
+ DPRINTF("Read enable %08x\n", ret);
+ break;
+ case 4:
+ ret = s->regs[1];
+ DPRINTF("Read register[1] %08x\n", ret);
+ break;
+ case ECC_FSR_REG:
+ ret = s->regs[2];
+ DPRINTF("Read fault status %08x\n", ret);
+ break;
+ case 12:
+ ret = s->regs[3];
+ DPRINTF("Read reg[3] %08x\n", ret);
+ break;
+ case ECC_FAR0_REG:
+ ret = s->regs[4];
+ DPRINTF("Read fault address 0 %08x\n", ret);
+ break;
+ case ECC_FAR1_REG:
+ ret = s->regs[5];
+ DPRINTF("Read fault address 1 %08x\n", ret);
+ break;
+ case ECC_DIAG_REG:
+ ret = s->regs[6];
+ DPRINTF("Read diag %08x\n", ret);
+ break;
+ case 28:
+ ret = s->regs[7];
+ DPRINTF("Read reg[7] %08x\n", ret);
+ break;
+ }
+ return ret;
+}
+
+static CPUReadMemoryFunc *ecc_mem_read[3] = {
+ ecc_mem_readb,
+ ecc_mem_readw,
+ ecc_mem_readl,
+};
+
+static CPUWriteMemoryFunc *ecc_mem_write[3] = {
+ ecc_mem_writeb,
+ ecc_mem_writew,
+ ecc_mem_writel,
+};
+
+static int ecc_load(QEMUFile *f, void *opaque, int version_id)
+{
+ ECCState *s = opaque;
+ int i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ for (i = 0; i < ECC_NREGS; i++)
+ qemu_get_be32s(f, &s->regs[i]);
+
+ return 0;
+}
+
+static void ecc_save(QEMUFile *f, void *opaque)
+{
+ ECCState *s = opaque;
+ int i;
+
+ for (i = 0; i < ECC_NREGS; i++)
+ qemu_put_be32s(f, &s->regs[i]);
+}
+
+static void ecc_reset(void *opaque)
+{
+ ECCState *s = opaque;
+ int i;
+
+ s->regs[ECC_FCR_REG] &= (ECC_FCR_VER | ECC_FCR_IMPL);
+
+ for (i = 1; i < ECC_NREGS; i++)
+ s->regs[i] = 0;
+}
+
+void * ecc_init(target_phys_addr_t base, uint32_t version)
+{
+ int ecc_io_memory;
+ ECCState *s;
+
+ s = qemu_mallocz(sizeof(ECCState));
+ if (!s)
+ return NULL;
+
+ s->regs[0] = version;
+
+ ecc_io_memory = cpu_register_io_memory(0, ecc_mem_read, ecc_mem_write, s);
+ cpu_register_physical_memory(base, ECC_SIZE, ecc_io_memory);
+ register_savevm("ECC", base, 1, ecc_save, ecc_load, s);
+ qemu_register_reset(ecc_reset, s);
+ ecc_reset(s);
+ return s;
+}
Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/esp.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -165,7 +165,7 @@
if (s->current_dev) {
/* Started a new command before the old one finished. Cancel it. */
- scsi_cancel_io(s->current_dev, 0);
+ s->current_dev->cancel_io(s->current_dev, 0);
s->async_len = 0;
}
@@ -188,7 +188,7 @@
DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
lun = buf[0] & 7;
- datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
+ datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
s->ti_size = datalen;
if (datalen != 0) {
s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC;
@@ -196,10 +196,10 @@
s->dma_counter = 0;
if (datalen > 0) {
s->rregs[ESP_RSTAT] |= STAT_DI;
- scsi_read_data(s->current_dev, 0);
+ s->current_dev->read_data(s->current_dev, 0);
} else {
s->rregs[ESP_RSTAT] |= STAT_DO;
- scsi_write_data(s->current_dev, 0);
+ s->current_dev->write_data(s->current_dev, 0);
}
}
s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
@@ -298,9 +298,9 @@
if (s->async_len == 0) {
if (to_device) {
// ti_size is negative
- scsi_write_data(s->current_dev, 0);
+ s->current_dev->write_data(s->current_dev, 0);
} else {
- scsi_read_data(s->current_dev, 0);
+ s->current_dev->read_data(s->current_dev, 0);
/* If there is still data to be read from the device then
complete the DMA operation immeriately. Otherwise defer
until the scsi layer has completed. */
@@ -335,7 +335,7 @@
} else {
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
s->async_len = arg;
- s->async_buf = scsi_get_buf(s->current_dev, 0);
+ s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
if (s->dma_left) {
esp_do_dma(s);
} else if (s->dma_counter != 0 && s->ti_size <= 0) {
@@ -611,7 +611,7 @@
}
if (s->scsi_dev[id]) {
DPRINTF("Destroying device %d\n", id);
- scsi_disk_destroy(s->scsi_dev[id]);
+ s->scsi_dev[id]->destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
/* Command queueing is not implemented. */
Modified: trunk/src/host/qemu-neo1973/hw/flash.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/flash.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/flash.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -1,12 +1,20 @@
/* NOR flash devices */
typedef struct pflash_t pflash_t;
-pflash_t *pflash_register (target_phys_addr_t base, ram_addr_t off,
- BlockDriverState *bs,
- uint32_t sector_len, int nb_blocs, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3);
+/* pflash_cfi01.c */
+pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+ BlockDriverState *bs,
+ uint32_t sector_len, int nb_blocs, int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3);
+/* 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,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3);
+
/* nand.c */
struct nand_flash_s;
struct nand_flash_s *nand_init(int manf_id, int chip_id);
@@ -37,4 +45,3 @@
void ecc_reset(struct ecc_state_s *s);
void ecc_put(QEMUFile *f, struct ecc_state_s *s);
void ecc_get(QEMUFile *f, struct ecc_state_s *s);
-
Modified: trunk/src/host/qemu-neo1973/hw/gumstix.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/gumstix.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/gumstix.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -67,7 +67,7 @@
exit(1);
}
- if (!pflash_register(0x00000000, qemu_ram_alloc(connex_rom),
+ if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(connex_rom),
drives_table[index].bdrv, sector_len, connex_rom / sector_len,
2, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -107,7 +107,7 @@
exit(1);
}
- if (!pflash_register(0x00000000, qemu_ram_alloc(verdex_rom),
+ if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(verdex_rom),
drives_table[index].bdrv, sector_len, verdex_rom / sector_len,
2, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/ide.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -1361,7 +1361,7 @@
buf[8] = 0x2a;
buf[9] = 0x12;
- buf[10] = 0x08;
+ buf[10] = 0x00;
buf[11] = 0x00;
buf[12] = 0x70;
Modified: trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/lsi53c895a.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/lsi53c895a.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -187,6 +187,7 @@
/* The tag is a combination of the device ID and the SCSI tag. */
uint32_t current_tag;
uint32_t current_dma_len;
+ int command_complete;
uint8_t *dma_buf;
lsi_queue *queue;
int queue_len;
@@ -465,7 +466,8 @@
s->dbc -= count;
if (s->dma_buf == NULL) {
- s->dma_buf = scsi_get_buf(s->current_dev, s->current_tag);
+ s->dma_buf = s->current_dev->get_buf(s->current_dev,
+ s->current_tag);
}
/* ??? Set SFBR to first data byte. */
@@ -479,10 +481,10 @@
s->dma_buf = NULL;
if (out) {
/* Write the data. */
- scsi_write_data(s->current_dev, s->current_tag);
+ s->current_dev->write_data(s->current_dev, s->current_tag);
} else {
/* Request any remaining data. */
- scsi_read_data(s->current_dev, s->current_tag);
+ s->current_dev->read_data(s->current_dev, s->current_tag);
}
} else {
s->dma_buf += count;
@@ -596,6 +598,7 @@
if (reason == SCSI_REASON_DONE) {
DPRINTF("Command complete sense=%d\n", (int)arg);
s->sense = arg;
+ s->command_complete = 2;
if (s->waiting && s->dbc != 0) {
/* Raise phase mismatch for short transfers. */
lsi_bad_phase(s, out, PHASE_ST);
@@ -612,6 +615,7 @@
}
DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
s->current_dma_len = arg;
+ s->command_complete = 1;
if (!s->waiting)
return;
if (s->waiting == 1 || s->dbc == 0) {
@@ -631,21 +635,30 @@
s->dbc = 16;
cpu_physical_memory_read(s->dnad, buf, s->dbc);
s->sfbr = buf[0];
- n = scsi_send_command(s->current_dev, s->current_tag, buf, s->current_lun);
+ s->command_complete = 0;
+ n = s->current_dev->send_command(s->current_dev, s->current_tag, buf,
+ s->current_lun);
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
- scsi_read_data(s->current_dev, s->current_tag);
+ s->current_dev->read_data(s->current_dev, s->current_tag);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
- scsi_write_data(s->current_dev, s->current_tag);
+ s->current_dev->write_data(s->current_dev, s->current_tag);
}
- if (n && s->current_dma_len == 0) {
- /* Command did not complete immediately so disconnect. */
- lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
- lsi_add_msg_byte(s, 4); /* DISCONNECT */
- lsi_set_phase(s, PHASE_MI);
- s->msg_action = 1;
- lsi_queue_command(s);
+
+ if (!s->command_complete) {
+ if (n) {
+ /* Command did not complete immediately so disconnect. */
+ lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
+ lsi_add_msg_byte(s, 4); /* DISCONNECT */
+ /* wait data */
+ lsi_set_phase(s, PHASE_MI);
+ s->msg_action = 1;
+ lsi_queue_command(s);
+ } else {
+ /* wait command complete */
+ lsi_set_phase(s, PHASE_DI);
+ }
}
}
@@ -1822,7 +1835,7 @@
}
if (s->scsi_dev[id]) {
DPRINTF("Destroying device %d\n", id);
- scsi_disk_destroy(s->scsi_dev[id]);
+ s->scsi_dev[id]->destroy(s->scsi_dev[id]);
}
DPRINTF("Attaching block device %d\n", id);
s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
Modified: trunk/src/host/qemu-neo1973/hw/mainstone.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mainstone.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/mainstone.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -55,7 +55,8 @@
"'pflash' parameter\n");
exit(1);
}
- if (!pflash_register(MST_FLASH_0, mainstone_ram + PXA2XX_INTERNAL_SIZE,
+ if (!pflash_cfi01_register(MST_FLASH_0,
+ mainstone_ram + PXA2XX_INTERNAL_SIZE,
drives_table[index].bdrv,
256 * 1024, 128, 4, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -68,7 +69,8 @@
"'pflash' parameter\n");
exit(1);
}
- if (!pflash_register(MST_FLASH_1, mainstone_ram + PXA2XX_INTERNAL_SIZE,
+ if (!pflash_cfi01_register(MST_FLASH_1,
+ mainstone_ram + PXA2XX_INTERNAL_SIZE,
drives_table[index].bdrv,
256 * 1024, 128, 4, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -76,6 +78,10 @@
}
mst_irq = mst_irq_init(cpu, MST_FPGA_PHYS, PXA2XX_PIC_GPIO_0);
+
+ /* MMC/SD host */
+ pxa2xx_mmci_handlers(cpu->mmc, NULL, mst_irq[MMC_IRQ]);
+
smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline,
Modified: trunk/src/host/qemu-neo1973/hw/mainstone.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mainstone.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/mainstone.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -17,7 +17,20 @@
#define MST_FLASH_1 0x04000000
/* IRQ definitions */
-#define ETHERNET_IRQ 3
+#define MMC_IRQ 0
+#define USIM_IRQ 1
+#define USBC_IRQ 2
+#define ETHERNET_IRQ 3
+#define AC97_IRQ 4
+#define PEN_IRQ 5
+#define MSINS_IRQ 6
+#define EXBRD_IRQ 7
+#define S0_CD_IRQ 9
+#define S0_STSCHG_IRQ 10
+#define S0_IRQ 11
+#define S1_CD_IRQ 13
+#define S1_STSCHG_IRQ 14
+#define S1_IRQ 15
extern qemu_irq
*mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq);
Modified: trunk/src/host/qemu-neo1973/hw/mips_r4k.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_r4k.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/mips_r4k.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -38,7 +38,7 @@
static PITState *pit; /* PIT i8254 */
-/*i8254 PIT is attached to the IRQ0 at PIC i8259 */
+/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
static struct _loaderparams {
int ram_size;
@@ -268,7 +268,6 @@
hd[MAX_IDE_DEVS * i + 1]);
i8042_init(i8259[1], i8259[12], 0x60);
- ds1225y_init(0x9000, "nvram");
}
QEMUMachine mips_machine = {
Modified: trunk/src/host/qemu-neo1973/hw/omap.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/omap.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -402,38 +402,53 @@
}
/* OMAP1 DMA module */
-typedef enum {
- constant = 0,
- post_incremented,
- single_index,
- double_index,
-} omap_dma_addressing_t;
-
struct omap_dma_channel_s {
+ /* transfer data */
int burst[2];
int pack[2];
enum omap_dma_port port[2];
target_phys_addr_t addr[2];
omap_dma_addressing_t mode[2];
+ uint16_t elements;
+ uint16_t frames;
+ int16_t frame_index[2];
+ int16_t element_index[2];
int data_type;
+
+ /* transfer type */
+ int transparent_copy;
+ int constant_fill;
+ uint32_t color;
+
+ /* auto init and linked channel data */
int end_prog;
int repeat;
int auto_init;
- int priority;
- int fs;
- int sync;
- int running;
+ int link_enabled;
+ int link_next_ch;
+
+ /* interruption data */
int interrupts;
int status;
- int signalled;
- int post_sync;
- int transfer;
- uint16_t elements;
- uint16_t frames;
- uint16_t frame_index;
- uint16_t element_index;
+
+ /* state data */
+ int active;
+ int enable;
+ int sync;
+ int pending_request;
+ int waiting_end_prog;
uint16_t cpc;
+ /* sync type */
+ int fs;
+ int bs;
+
+ /* compatibility */
+ int omap_3_1_compatible_disable;
+
+ qemu_irq irq;
+ struct omap_dma_channel_s *sibling;
+
struct omap_dma_reg_set_s {
target_phys_addr_t src, dest;
int frame;
@@ -443,16 +458,22 @@
int frames;
int elements;
} active_set;
+
+ /* unused parameters */
+ int priority;
+ int interleave_disabled;
+ int type;
};
struct omap_dma_s {
- qemu_irq *ih;
QEMUTimer *tm;
struct omap_mpu_state_s *mpu;
target_phys_addr_t base;
omap_clk clk;
int64_t delay;
uint32_t drq;
+ enum omap_dma_model model;
+ int omap_3_1_mapping_disabled;
uint16_t gcr;
int run_count;
@@ -462,223 +483,302 @@
struct omap_dma_lcd_channel_s lcd_ch;
};
+/* Interrupts */
+#define TIMEOUT_INTR (1 << 0)
+#define EVENT_DROP_INTR (1 << 1)
+#define HALF_FRAME_INTR (1 << 2)
+#define END_FRAME_INTR (1 << 3)
+#define LAST_FRAME_INTR (1 << 4)
+#define END_BLOCK_INTR (1 << 5)
+#define SYNC (1 << 6)
+
static void omap_dma_interrupts_update(struct omap_dma_s *s)
{
- /* First three interrupts are shared between two channels each. */
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH0_6],
- (s->ch[0].status | s->ch[6].status) & 0x3f);
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH1_7],
- (s->ch[1].status | s->ch[7].status) & 0x3f);
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH2_8],
- (s->ch[2].status | s->ch[8].status) & 0x3f);
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH3],
- (s->ch[3].status) & 0x3f);
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH4],
- (s->ch[4].status) & 0x3f);
- qemu_set_irq(s->ih[OMAP_INT_DMA_CH5],
- (s->ch[5].status) & 0x3f);
+ struct omap_dma_channel_s *ch = s->ch;
+ int i;
+
+ if (s->omap_3_1_mapping_disabled) {
+ for (i = 0; i < s->chans; i ++, ch ++)
+ if (ch->status)
+ qemu_irq_raise(ch->irq);
+ } else {
+ /* First three interrupts are shared between two channels each. */
+ for (i = 0; i < 6; i ++, ch ++) {
+ if (ch->status || (ch->sibling && ch->sibling->status))
+ qemu_irq_raise(ch->irq);
+ }
+ }
}
-static void omap_dma_channel_load(struct omap_dma_s *s, int ch)
+static void omap_dma_channel_load(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
{
- struct omap_dma_reg_set_s *a = &s->ch[ch].active_set;
+ struct omap_dma_reg_set_s *a = &ch->active_set;
int i;
+ int omap_3_1 = !ch->omap_3_1_compatible_disable;
/*
* TODO: verify address ranges and alignment
* TODO: port endianness
*/
- a->src = s->ch[ch].addr[0];
- a->dest = s->ch[ch].addr[1];
- a->frames = s->ch[ch].frames;
- a->elements = s->ch[ch].elements;
+ a->src = ch->addr[0];
+ a->dest = ch->addr[1];
+ a->frames = ch->frames;
+ a->elements = ch->elements;
a->frame = 0;
a->element = 0;
- if (unlikely(!s->ch[ch].elements || !s->ch[ch].frames)) {
+ if (unlikely(!ch->elements || !ch->frames)) {
printf("%s: bad DMA request\n", __FUNCTION__);
return;
}
for (i = 0; i < 2; i ++)
- switch (s->ch[ch].mode[i]) {
+ switch (ch->mode[i]) {
case constant:
a->elem_delta[i] = 0;
a->frame_delta[i] = 0;
break;
case post_incremented:
- a->elem_delta[i] = s->ch[ch].data_type;
+ a->elem_delta[i] = ch->data_type;
a->frame_delta[i] = 0;
break;
case single_index:
- a->elem_delta[i] = s->ch[ch].data_type +
- s->ch[ch].element_index - 1;
- if (s->ch[ch].element_index > 0x7fff)
- a->elem_delta[i] -= 0x10000;
+ a->elem_delta[i] = ch->data_type +
+ ch->element_index[omap_3_1 ? 0 : i] - 1;
a->frame_delta[i] = 0;
break;
case double_index:
- a->elem_delta[i] = s->ch[ch].data_type +
- s->ch[ch].element_index - 1;
- if (s->ch[ch].element_index > 0x7fff)
- a->elem_delta[i] -= 0x10000;
- a->frame_delta[i] = s->ch[ch].frame_index -
- s->ch[ch].element_index;
- if (s->ch[ch].frame_index > 0x7fff)
- a->frame_delta[i] -= 0x10000;
+ a->elem_delta[i] = ch->data_type +
+ ch->element_index[omap_3_1 ? 0 : i] - 1;
+ a->frame_delta[i] = ch->frame_index[omap_3_1 ? 0 : i] -
+ ch->element_index[omap_3_1 ? 0 : i];
break;
default:
break;
}
}
-static inline void omap_dma_request_run(struct omap_dma_s *s,
- int channel, int request)
+static void omap_dma_activate_channel(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
{
-next_channel:
- if (request > 0)
- for (; channel < 9; channel ++)
- if (s->ch[channel].sync == request && s->ch[channel].running)
- break;
- if (channel >= 9)
+ if (!ch->active) {
+ ch->active = 1;
+ if (ch->sync)
+ ch->status |= SYNC;
+ s->run_count ++;
+ }
+
+ if (s->delay && !qemu_timer_pending(s->tm))
+ qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
+}
+
+static void omap_dma_deactivate_channel(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
+{
+ /* Update cpc */
+ ch->cpc = ch->active_set.dest & 0xffff;
+
+ if (ch->pending_request && !ch->waiting_end_prog) {
+ /* Don't deactivate the channel */
+ ch->pending_request = 0;
return;
+ }
- if (s->ch[channel].transfer) {
- if (request > 0) {
- s->ch[channel ++].post_sync = request;
- goto next_channel;
- }
- s->ch[channel].status |= 0x02; /* Synchronisation drop */
- omap_dma_interrupts_update(s);
+ /* Don't deactive the channel if it is synchronized and the DMA request is
+ active */
+ if (ch->sync && (s->drq & (1 << ch->sync)))
return;
+
+ if (ch->active) {
+ ch->active = 0;
+ ch->status &= ~SYNC;
+ s->run_count --;
}
- if (!s->ch[channel].signalled)
- s->run_count ++;
- s->ch[channel].signalled = 1;
+ if (!s->run_count)
+ qemu_del_timer(s->tm);
+}
- if (request > 0)
- s->ch[channel].status |= 0x40; /* External request */
+static void omap_dma_enable_channel(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
+{
+ if (!ch->enable) {
+ ch->enable = 1;
+ ch->waiting_end_prog = 0;
+ omap_dma_channel_load(s, ch);
+ if ((!ch->sync) || (s->drq & (1 << ch->sync)))
+ omap_dma_activate_channel(s, ch);
+ }
+}
- if (s->delay && !qemu_timer_pending(s->tm))
- qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
+static void omap_dma_disable_channel(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
+{
+ if (ch->enable) {
+ ch->enable = 0;
+ /* Discard any pending request */
+ ch->pending_request = 0;
+ omap_dma_deactivate_channel(s, ch);
+ }
+}
- if (request > 0) {
- channel ++;
- goto next_channel;
+static void omap_dma_channel_end_prog(struct omap_dma_s *s,
+ struct omap_dma_channel_s *ch)
+{
+ if (ch->waiting_end_prog) {
+ ch->waiting_end_prog = 0;
+ if (!ch->sync || ch->pending_request) {
+ ch->pending_request = 0;
+ omap_dma_activate_channel(s, ch);
+ }
}
}
-static inline void omap_dma_request_stop(struct omap_dma_s *s, int channel)
+static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
{
- if (s->ch[channel].signalled)
- s->run_count --;
- s->ch[channel].signalled = 0;
+ s->omap_3_1_mapping_disabled = 0;
+ s->chans = 9;
+}
- if (!s->run_count)
- qemu_del_timer(s->tm);
+static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
+{
+ s->omap_3_1_mapping_disabled = 1;
+ s->chans = 16;
}
+static void omap_dma_process_request(struct omap_dma_s *s, int request)
+{
+ int channel;
+ int drop_event = 0;
+ struct omap_dma_channel_s *ch = s->ch;
+
+ for (channel = 0; channel < s->chans; channel ++, ch ++) {
+ if (ch->enable && ch->sync == request) {
+ if (!ch->active)
+ omap_dma_activate_channel(s, ch);
+ else if (!ch->pending_request)
+ ch->pending_request = 1;
+ else {
+ /* Request collision */
+ /* Second request received while processing other request */
+ ch->status |= EVENT_DROP_INTR;
+ drop_event = 1;
+ }
+ }
+ }
+
+ if (drop_event)
+ omap_dma_interrupts_update(s);
+}
+
static void omap_dma_channel_run(struct omap_dma_s *s)
{
- int ch;
+ int n = s->chans;
uint16_t status;
uint8_t value[4];
struct omap_dma_port_if_s *src_p, *dest_p;
struct omap_dma_reg_set_s *a;
+ struct omap_dma_channel_s *ch;
- for (ch = 0; ch < 9; ch ++) {
- a = &s->ch[ch].active_set;
+ for (ch = s->ch; n; n --, ch ++) {
+ if (!ch->active)
+ continue;
- src_p = &s->mpu->port[s->ch[ch].port[0]];
- dest_p = &s->mpu->port[s->ch[ch].port[1]];
- if (s->ch[ch].signalled && (!src_p->addr_valid(s->mpu, a->src) ||
- !dest_p->addr_valid(s->mpu, a->dest))) {
+ a = &ch->active_set;
+
+ src_p = &s->mpu->port[ch->port[0]];
+ dest_p = &s->mpu->port[ch->port[1]];
+ if ((!ch->constant_fill && !src_p->addr_valid(s->mpu, a->src)) ||
+ (!dest_p->addr_valid(s->mpu, a->dest))) {
#if 0
/* Bus time-out */
- if (s->ch[ch].interrupts & 0x01)
- s->ch[ch].status |= 0x01;
- omap_dma_request_stop(s, ch);
+ if (ch->interrupts & TIMEOUT_INTR)
+ ch->status |= TIMEOUT_INTR;
+ omap_dma_deactivate_channel(s, ch);
continue;
#endif
- printf("%s: Bus time-out in DMA%i operation\n", __FUNCTION__, ch);
+ printf("%s: Bus time-out in DMA%i operation\n",
+ __FUNCTION__, s->chans - n);
}
- status = s->ch[ch].status;
- while (status == s->ch[ch].status && s->ch[ch].signalled) {
+ status = ch->status;
+ while (status == ch->status && ch->active) {
/* Transfer a single element */
- s->ch[ch].transfer = 1;
- cpu_physical_memory_read(a->src, value, s->ch[ch].data_type);
- cpu_physical_memory_write(a->dest, value, s->ch[ch].data_type);
- s->ch[ch].transfer = 0;
+ /* FIXME: check the endianness */
+ if (!ch->constant_fill)
+ cpu_physical_memory_read(a->src, value, ch->data_type);
+ else
+ *(uint32_t *) value = ch->color;
+ if (!ch->transparent_copy ||
+ *(uint32_t *) value != ch->color)
+ cpu_physical_memory_write(a->dest, value, ch->data_type);
+
a->src += a->elem_delta[0];
a->dest += a->elem_delta[1];
a->element ++;
- /* Check interrupt conditions */
+ /* If the channel is element synchronized, deactivate it */
+ if (ch->sync && !ch->fs && !ch->bs)
+ omap_dma_deactivate_channel(s, ch);
+
+ /* If it is the last frame, set the LAST_FRAME interrupt */
+ if (a->element == 1 && a->frame == a->frames - 1)
+ if (ch->interrupts & LAST_FRAME_INTR)
+ ch->status |= LAST_FRAME_INTR;
+
+ /* If the half of the frame was reached, set the HALF_FRAME
+ interrupt */
+ if (a->element == (a->elements >> 1))
+ if (ch->interrupts & HALF_FRAME_INTR)
+ ch->status |= HALF_FRAME_INTR;
+
if (a->element == a->elements) {
+ /* End of Frame */
a->element = 0;
a->src += a->frame_delta[0];
a->dest += a->frame_delta[1];
a->frame ++;
- if (a->frame == a->frames) {
- if (!s->ch[ch].repeat || !s->ch[ch].auto_init)
- s->ch[ch].running = 0;
+ /* If the channel is frame synchronized, deactivate it */
+ if (ch->sync && ch->fs)
+ omap_dma_deactivate_channel(s, ch);
- if (s->ch[ch].auto_init &&
- (s->ch[ch].repeat ||
- s->ch[ch].end_prog))
- omap_dma_channel_load(s, ch);
+ /* If the channel is async, update cpc */
+ if (!ch->sync)
+ ch->cpc = a->dest & 0xffff;
- if (s->ch[ch].interrupts & 0x20)
- s->ch[ch].status |= 0x20;
+ /* Set the END_FRAME interrupt */
+ if (ch->interrupts & END_FRAME_INTR)
+ ch->status |= END_FRAME_INTR;
- if (!s->ch[ch].sync)
- omap_dma_request_stop(s, ch);
- }
+ if (a->frame == a->frames) {
+ /* End of Block */
+ /* Disable the channel */
- if (s->ch[ch].interrupts & 0x08)
- s->ch[ch].status |= 0x08;
+ if (ch->omap_3_1_compatible_disable) {
+ omap_dma_disable_channel(s, ch);
+ if (ch->link_enabled)
+ omap_dma_enable_channel(s,
+ &s->ch[ch->link_next_ch]);
+ } else {
+ if (!ch->auto_init)
+ omap_dma_disable_channel(s, ch);
+ else if (ch->repeat || ch->end_prog)
+ omap_dma_channel_load(s, ch);
+ else {
+ ch->waiting_end_prog = 1;
+ omap_dma_deactivate_channel(s, ch);
+ }
+ }
- if (s->ch[ch].sync && s->ch[ch].fs &&
- !(s->drq & (1 << s->ch[ch].sync))) {
- s->ch[ch].status &= ~0x40;
- omap_dma_request_stop(s, ch);
+ if (ch->interrupts & END_BLOCK_INTR)
+ ch->status |= END_BLOCK_INTR;
}
}
-
- if (a->element == 1 && a->frame == a->frames - 1)
- if (s->ch[ch].interrupts & 0x10)
- s->ch[ch].status |= 0x10;
-
- if (a->element == (a->elements >> 1))
- if (s->ch[ch].interrupts & 0x04)
- s->ch[ch].status |= 0x04;
-
- if (s->ch[ch].sync && !s->ch[ch].fs &&
- !(s->drq & (1 << s->ch[ch].sync))) {
- s->ch[ch].status &= ~0x40;
- omap_dma_request_stop(s, ch);
- }
-
- /*
- * Process requests made while the element was
- * being transferred.
- */
- if (s->ch[ch].post_sync) {
- omap_dma_request_run(s, 0, s->ch[ch].post_sync);
- s->ch[ch].post_sync = 0;
- }
-
-#if 0
- break;
-#endif
}
-
- s->ch[ch].cpc = a->dest & 0x0000ffff;
}
omap_dma_interrupts_update(s);
@@ -686,77 +786,176 @@
qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
}
+static void omap_dma_reset(struct omap_dma_s *s)
+{
+ int i;
+
+ qemu_del_timer(s->tm);
+ s->gcr = 0x0004;
+ s->drq = 0x00000000;
+ s->run_count = 0;
+ s->lcd_ch.src = emiff;
+ s->lcd_ch.condition = 0;
+ s->lcd_ch.interrupts = 0;
+ s->lcd_ch.dual = 0;
+ omap_dma_enable_3_1_mapping(s);
+ for (i = 0; i < s->chans; i ++) {
+ memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst));
+ memset(&s->ch[i].port, 0, sizeof(s->ch[i].port));
+ memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode));
+ memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements));
+ memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames));
+ memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index));
+ memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index));
+ memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type));
+ memset(&s->ch[i].transparent_copy, 0,
+ sizeof(s->ch[i].transparent_copy));
+ memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill));
+ memset(&s->ch[i].color, 0, sizeof(s->ch[i].color));
+ memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog));
+ memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat));
+ memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init));
+ memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled));
+ memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch));
+ s->ch[i].interrupts = 0x0003;
+ memset(&s->ch[i].status, 0, sizeof(s->ch[i].status));
+ memset(&s->ch[i].active, 0, sizeof(s->ch[i].active));
+ memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable));
+ memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync));
+ memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request));
+ memset(&s->ch[i].waiting_end_prog, 0,
+ sizeof(s->ch[i].waiting_end_prog));
+ memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc));
+ memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs));
+ memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs));
+ memset(&s->ch[i].omap_3_1_compatible_disable, 0,
+ sizeof(s->ch[i].omap_3_1_compatible_disable));
+ memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set));
+ memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority));
+ memset(&s->ch[i].interleave_disabled, 0,
+ sizeof(s->ch[i].interleave_disabled));
+ memset(&s->ch[i].type, 0, sizeof(s->ch[i].type));
+ }
+}
+
static int omap_dma_ch_reg_read(struct omap_dma_s *s,
- int ch, int reg, uint16_t *value) {
+ struct omap_dma_channel_s *ch, int reg, uint16_t *value)
+{
switch (reg) {
case 0x00: /* SYS_DMA_CSDP_CH0 */
- *value = (s->ch[ch].burst[1] << 14) |
- (s->ch[ch].pack[1] << 13) |
- (s->ch[ch].port[1] << 9) |
- (s->ch[ch].burst[0] << 7) |
- (s->ch[ch].pack[0] << 6) |
- (s->ch[ch].port[0] << 2) |
- (s->ch[ch].data_type >> 1);
+ *value = (ch->burst[1] << 14) |
+ (ch->pack[1] << 13) |
+ (ch->port[1] << 9) |
+ (ch->burst[0] << 7) |
+ (ch->pack[0] << 6) |
+ (ch->port[0] << 2) |
+ (ch->data_type >> 1);
break;
case 0x02: /* SYS_DMA_CCR_CH0 */
- *value = (s->ch[ch].mode[1] << 14) |
- (s->ch[ch].mode[0] << 12) |
- (s->ch[ch].end_prog << 11) |
- (s->ch[ch].repeat << 9) |
- (s->ch[ch].auto_init << 8) |
- (s->ch[ch].running << 7) |
- (s->ch[ch].priority << 6) |
- (s->ch[ch].fs << 5) | s->ch[ch].sync;
+ if (s->model == omap_dma_3_1)
+ *value = 0 << 10; /* FIFO_FLUSH reads as 0 */
+ else
+ *value = ch->omap_3_1_compatible_disable << 10;
+ *value |= (ch->mode[1] << 14) |
+ (ch->mode[0] << 12) |
+ (ch->end_prog << 11) |
+ (ch->repeat << 9) |
+ (ch->auto_init << 8) |
+ (ch->enable << 7) |
+ (ch->priority << 6) |
+ (ch->fs << 5) | ch->sync;
break;
case 0x04: /* SYS_DMA_CICR_CH0 */
- *value = s->ch[ch].interrupts;
+ *value = ch->interrupts;
break;
case 0x06: /* SYS_DMA_CSR_CH0 */
- /* FIXME: shared CSR for channels sharing the interrupts */
- *value = s->ch[ch].status;
- s->ch[ch].status &= 0x40;
- omap_dma_interrupts_update(s);
+ *value = ch->status;
+ ch->status &= SYNC;
+ if (!ch->omap_3_1_compatible_disable && ch->sibling) {
+ *value |= (ch->sibling->status & 0x3f) << 6;
+ ch->sibling->status &= SYNC;
+ }
+ qemu_irq_lower(ch->irq);
break;
case 0x08: /* SYS_DMA_CSSA_L_CH0 */
- *value = s->ch[ch].addr[0] & 0x0000ffff;
+ *value = ch->addr[0] & 0x0000ffff;
break;
case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
- *value = s->ch[ch].addr[0] >> 16;
+ *value = ch->addr[0] >> 16;
break;
case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
- *value = s->ch[ch].addr[1] & 0x0000ffff;
+ *value = ch->addr[1] & 0x0000ffff;
break;
case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
- *value = s->ch[ch].addr[1] >> 16;
+ *value = ch->addr[1] >> 16;
break;
case 0x10: /* SYS_DMA_CEN_CH0 */
- *value = s->ch[ch].elements;
+ *value = ch->elements;
break;
case 0x12: /* SYS_DMA_CFN_CH0 */
- *value = s->ch[ch].frames;
+ *value = ch->frames;
break;
case 0x14: /* SYS_DMA_CFI_CH0 */
- *value = s->ch[ch].frame_index;
+ *value = ch->frame_index[0];
break;
case 0x16: /* SYS_DMA_CEI_CH0 */
- *value = s->ch[ch].element_index;
+ *value = ch->element_index[0];
break;
- case 0x18: /* SYS_DMA_CPC_CH0 */
- *value = s->ch[ch].cpc;
+ case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
+ if (ch->omap_3_1_compatible_disable)
+ *value = ch->active_set.src & 0xffff; /* CSAC */
+ else
+ *value = ch->cpc;
break;
+ case 0x1a: /* DMA_CDAC */
+ *value = ch->active_set.dest & 0xffff; /* CDAC */
+ break;
+
+ case 0x1c: /* DMA_CDEI */
+ *value = ch->element_index[1];
+ break;
+
+ case 0x1e: /* DMA_CDFI */
+ *value = ch->frame_index[1];
+ break;
+
+ case 0x20: /* DMA_COLOR_L */
+ *value = ch->color & 0xffff;
+ break;
+
+ case 0x22: /* DMA_COLOR_U */
+ *value = ch->color >> 16;
+ break;
+
+ case 0x24: /* DMA_CCR2 */
+ *value = (ch->bs << 2) |
+ (ch->transparent_copy << 1) |
+ ch->constant_fill;
+ break;
+
+ case 0x28: /* DMA_CLNK_CTRL */
+ *value = (ch->link_enabled << 15) |
+ (ch->link_next_ch & 0xf);
+ break;
+
+ case 0x2a: /* DMA_LCH_CTRL */
+ *value = (ch->interleave_disabled << 15) |
+ ch->type;
+ break;
+
default:
return 1;
}
@@ -764,228 +963,690 @@
}
static int omap_dma_ch_reg_write(struct omap_dma_s *s,
- int ch, int reg, uint16_t value) {
+ struct omap_dma_channel_s *ch, int reg, uint16_t value)
+{
switch (reg) {
case 0x00: /* SYS_DMA_CSDP_CH0 */
- s->ch[ch].burst[1] = (value & 0xc000) >> 14;
- s->ch[ch].pack[1] = (value & 0x2000) >> 13;
- s->ch[ch].port[1] = (enum omap_dma_port) ((value & 0x1e00) >> 9);
- s->ch[ch].burst[0] = (value & 0x0180) >> 7;
- s->ch[ch].pack[0] = (value & 0x0040) >> 6;
- s->ch[ch].port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
- s->ch[ch].data_type = (1 << (value & 3));
- if (s->ch[ch].port[0] >= omap_dma_port_last)
+ ch->burst[1] = (value & 0xc000) >> 14;
+ ch->pack[1] = (value & 0x2000) >> 13;
+ ch->port[1] = (enum omap_dma_port) ((value & 0x1e00) >> 9);
+ ch->burst[0] = (value & 0x0180) >> 7;
+ ch->pack[0] = (value & 0x0040) >> 6;
+ ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
+ ch->data_type = (1 << (value & 3));
+ if (ch->port[0] >= omap_dma_port_last)
printf("%s: invalid DMA port %i\n", __FUNCTION__,
- s->ch[ch].port[0]);
- if (s->ch[ch].port[1] >= omap_dma_port_last)
+ ch->port[0]);
+ if (ch->port[1] >= omap_dma_port_last)
printf("%s: invalid DMA port %i\n", __FUNCTION__,
- s->ch[ch].port[1]);
+ ch->port[1]);
if ((value & 3) == 3)
- printf("%s: bad data_type for DMA channel %i\n", __FUNCTION__, ch);
+ printf("%s: bad data_type for DMA channel\n", __FUNCTION__);
break;
case 0x02: /* SYS_DMA_CCR_CH0 */
- s->ch[ch].mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
- s->ch[ch].mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
- s->ch[ch].end_prog = (value & 0x0800) >> 11;
- s->ch[ch].repeat = (value & 0x0200) >> 9;
- s->ch[ch].auto_init = (value & 0x0100) >> 8;
- s->ch[ch].priority = (value & 0x0040) >> 6;
- s->ch[ch].fs = (value & 0x0020) >> 5;
- s->ch[ch].sync = value & 0x001f;
- if (value & 0x0080) {
- if (s->ch[ch].running) {
- if (!s->ch[ch].signalled &&
- s->ch[ch].auto_init && s->ch[ch].end_prog)
- omap_dma_channel_load(s, ch);
- } else {
- s->ch[ch].running = 1;
- omap_dma_channel_load(s, ch);
- }
- if (!s->ch[ch].sync || (s->drq & (1 << s->ch[ch].sync)))
- omap_dma_request_run(s, ch, 0);
- } else {
- s->ch[ch].running = 0;
- omap_dma_request_stop(s, ch);
- }
+ ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
+ ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
+ ch->end_prog = (value & 0x0800) >> 11;
+ if (s->model > omap_dma_3_1)
+ ch->omap_3_1_compatible_disable = (value >> 10) & 0x1;
+ ch->repeat = (value & 0x0200) >> 9;
+ ch->auto_init = (value & 0x0100) >> 8;
+ ch->priority = (value & 0x0040) >> 6;
+ ch->fs = (value & 0x0020) >> 5;
+ ch->sync = value & 0x001f;
+
+ if (value & 0x0080)
+ omap_dma_enable_channel(s, ch);
+ else
+ omap_dma_disable_channel(s, ch);
+
+ if (ch->end_prog)
+ omap_dma_channel_end_prog(s, ch);
+
break;
case 0x04: /* SYS_DMA_CICR_CH0 */
- s->ch[ch].interrupts = value & 0x003f;
+ ch->interrupts = value;
break;
case 0x06: /* SYS_DMA_CSR_CH0 */
- return 1;
+ OMAP_RO_REG((target_phys_addr_t) reg);
+ break;
case 0x08: /* SYS_DMA_CSSA_L_CH0 */
- s->ch[ch].addr[0] &= 0xffff0000;
- s->ch[ch].addr[0] |= value;
+ ch->addr[0] &= 0xffff0000;
+ ch->addr[0] |= value;
break;
case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
- s->ch[ch].addr[0] &= 0x0000ffff;
- s->ch[ch].addr[0] |= (uint32_t) value << 16;
+ ch->addr[0] &= 0x0000ffff;
+ ch->addr[0] |= (uint32_t) value << 16;
break;
case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
- s->ch[ch].addr[1] &= 0xffff0000;
- s->ch[ch].addr[1] |= value;
+ ch->addr[1] &= 0xffff0000;
+ ch->addr[1] |= value;
break;
case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
- s->ch[ch].addr[1] &= 0x0000ffff;
- s->ch[ch].addr[1] |= (uint32_t) value << 16;
+ ch->addr[1] &= 0x0000ffff;
+ ch->addr[1] |= (uint32_t) value << 16;
break;
case 0x10: /* SYS_DMA_CEN_CH0 */
- s->ch[ch].elements = value & 0xffff;
+ ch->elements = value;
break;
case 0x12: /* SYS_DMA_CFN_CH0 */
- s->ch[ch].frames = value & 0xffff;
+ ch->frames = value;
break;
case 0x14: /* SYS_DMA_CFI_CH0 */
- s->ch[ch].frame_index = value & 0xffff;
+ ch->frame_index[0] = (int16_t) value;
break;
case 0x16: /* SYS_DMA_CEI_CH0 */
- s->ch[ch].element_index = value & 0xffff;
+ ch->element_index[0] = (int16_t) value;
break;
- case 0x18: /* SYS_DMA_CPC_CH0 */
+ case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */
+ OMAP_RO_REG((target_phys_addr_t) reg);
+ break;
+
+ case 0x1c: /* DMA_CDEI */
+ ch->element_index[1] = (int16_t) value;
+ break;
+
+ case 0x1e: /* DMA_CDFI */
+ ch->frame_index[1] = (int16_t) value;
+ break;
+
+ case 0x20: /* DMA_COLOR_L */
+ ch->color &= 0xffff0000;
+ ch->color |= value;
+ break;
+
+ case 0x22: /* DMA_COLOR_U */
+ ch->color &= 0xffff;
+ ch->color |= value << 16;
+ break;
+
+ case 0x24: /* DMA_CCR2 */
+ ch->bs = (value >> 2) & 0x1;
+ ch->transparent_copy = (value >> 1) & 0x1;
+ ch->constant_fill = value & 0x1;
+ break;
+
+ case 0x28: /* DMA_CLNK_CTRL */
+ ch->link_enabled = (value >> 15) & 0x1;
+ if (value & (1 << 14)) { /* Stop_Lnk */
+ ch->link_enabled = 0;
+ omap_dma_disable_channel(s, ch);
+ }
+ ch->link_next_ch = value & 0x1f;
+ break;
+
+ case 0x2a: /* DMA_LCH_CTRL */
+ ch->interleave_disabled = (value >> 15) & 0x1;
+ ch->type = value & 0xf;
+ break;
+
+ default:
return 1;
+ }
+ return 0;
+}
+static int omap_dma_3_2_lcd_write(struct omap_dma_lcd_channel_s *s, int offset,
+ uint16_t value)
+{
+ switch (offset) {
+ case 0xbc0: /* DMA_LCD_CSDP */
+ s->brust_f2 = (value >> 14) & 0x3;
+ s->pack_f2 = (value >> 13) & 0x1;
+ s->data_type_f2 = (1 << ((value >> 11) & 0x3));
+ s->brust_f1 = (value >> 7) & 0x3;
+ s->pack_f1 = (value >> 6) & 0x1;
+ s->data_type_f1 = (1 << ((value >> 0) & 0x3));
+ break;
+
+ case 0xbc2: /* DMA_LCD_CCR */
+ s->mode_f2 = (value >> 14) & 0x3;
+ s->mode_f1 = (value >> 12) & 0x3;
+ s->end_prog = (value >> 11) & 0x1;
+ s->omap_3_1_compatible_disable = (value >> 10) & 0x1;
+ s->repeat = (value >> 9) & 0x1;
+ s->auto_init = (value >> 8) & 0x1;
+ s->running = (value >> 7) & 0x1;
+ s->priority = (value >> 6) & 0x1;
+ s->bs = (value >> 4) & 0x1;
+ break;
+
+ case 0xbc4: /* DMA_LCD_CTRL */
+ s->dst = (value >> 8) & 0x1;
+ s->src = ((value >> 6) & 0x3) << 1;
+ s->condition = 0;
+ /* Assume no bus errors and thus no BUS_ERROR irq bits. */
+ s->interrupts = (value >> 1) & 1;
+ s->dual = value & 1;
+ break;
+
+ case 0xbc8: /* TOP_B1_L */
+ s->src_f1_top &= 0xffff0000;
+ s->src_f1_top |= 0x0000ffff & value;
+ break;
+
+ case 0xbca: /* TOP_B1_U */
+ s->src_f1_top &= 0x0000ffff;
+ s->src_f1_top |= value << 16;
+ break;
+
+ case 0xbcc: /* BOT_B1_L */
+ s->src_f1_bottom &= 0xffff0000;
+ s->src_f1_bottom |= 0x0000ffff & value;
+ break;
+
+ case 0xbce: /* BOT_B1_U */
+ s->src_f1_bottom &= 0x0000ffff;
+ s->src_f1_bottom |= (uint32_t) value << 16;
+ break;
+
+ case 0xbd0: /* TOP_B2_L */
+ s->src_f2_top &= 0xffff0000;
+ s->src_f2_top |= 0x0000ffff & value;
+ break;
+
+ case 0xbd2: /* TOP_B2_U */
+ s->src_f2_top &= 0x0000ffff;
+ s->src_f2_top |= (uint32_t) value << 16;
+ break;
+
+ case 0xbd4: /* BOT_B2_L */
+ s->src_f2_bottom &= 0xffff0000;
+ s->src_f2_bottom |= 0x0000ffff & value;
+ break;
+
+ case 0xbd6: /* BOT_B2_U */
+ s->src_f2_bottom &= 0x0000ffff;
+ s->src_f2_bottom |= (uint32_t) value << 16;
+ break;
+
+ case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
+ s->element_index_f1 = value;
+ break;
+
+ case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
+ s->frame_index_f1 &= 0xffff0000;
+ s->frame_index_f1 |= 0x0000ffff & value;
+ break;
+
+ case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
+ s->frame_index_f1 &= 0x0000ffff;
+ s->frame_index_f1 |= (uint32_t) value << 16;
+ break;
+
+ case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
+ s->element_index_f2 = value;
+ break;
+
+ case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
+ s->frame_index_f2 &= 0xffff0000;
+ s->frame_index_f2 |= 0x0000ffff & value;
+ break;
+
+ case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
+ s->frame_index_f2 &= 0x0000ffff;
+ s->frame_index_f2 |= (uint32_t) value << 16;
+ break;
+
+ case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
+ s->elements_f1 = value;
+ break;
+
+ case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
+ s->frames_f1 = value;
+ break;
+
+ case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
+ s->elements_f2 = value;
+ break;
+
+ case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
+ s->frames_f2 = value;
+ break;
+
+ case 0xbea: /* DMA_LCD_LCH_CTRL */
+ s->lch_type = value & 0xf;
+ break;
+
default:
- OMAP_BAD_REG((target_phys_addr_t) reg);
+ return 1;
}
return 0;
}
-static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
+static int omap_dma_3_2_lcd_read(struct omap_dma_lcd_channel_s *s, int offset,
+ uint16_t *ret)
{
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
- int i, reg, ch, offset = addr - s->base;
- uint16_t ret;
+ switch (offset) {
+ case 0xbc0: /* DMA_LCD_CSDP */
+ *ret = (s->brust_f2 << 14) |
+ (s->pack_f2 << 13) |
+ ((s->data_type_f2 >> 1) << 11) |
+ (s->brust_f1 << 7) |
+ (s->pack_f1 << 6) |
+ ((s->data_type_f1 >> 1) << 0);
+ break;
+ case 0xbc2: /* DMA_LCD_CCR */
+ *ret = (s->mode_f2 << 14) |
+ (s->mode_f1 << 12) |
+ (s->end_prog << 11) |
+ (s->omap_3_1_compatible_disable << 10) |
+ (s->repeat << 9) |
+ (s->auto_init << 8) |
+ (s->running << 7) |
+ (s->priority << 6) |
+ (s->bs << 4);
+ break;
+
+ case 0xbc4: /* DMA_LCD_CTRL */
+ qemu_irq_lower(s->irq);
+ *ret = (s->dst << 8) |
+ ((s->src & 0x6) << 5) |
+ (s->condition << 3) |
+ (s->interrupts << 1) |
+ s->dual;
+ break;
+
+ case 0xbc8: /* TOP_B1_L */
+ *ret = s->src_f1_top & 0xffff;
+ break;
+
+ case 0xbca: /* TOP_B1_U */
+ *ret = s->src_f1_top >> 16;
+ break;
+
+ case 0xbcc: /* BOT_B1_L */
+ *ret = s->src_f1_bottom & 0xffff;
+ break;
+
+ case 0xbce: /* BOT_B1_U */
+ *ret = s->src_f1_bottom >> 16;
+ break;
+
+ case 0xbd0: /* TOP_B2_L */
+ *ret = s->src_f2_top & 0xffff;
+ break;
+
+ case 0xbd2: /* TOP_B2_U */
+ *ret = s->src_f2_top >> 16;
+ break;
+
+ case 0xbd4: /* BOT_B2_L */
+ *ret = s->src_f2_bottom & 0xffff;
+ break;
+
+ case 0xbd6: /* BOT_B2_U */
+ *ret = s->src_f2_bottom >> 16;
+ break;
+
+ case 0xbd8: /* DMA_LCD_SRC_EI_B1 */
+ *ret = s->element_index_f1;
+ break;
+
+ case 0xbda: /* DMA_LCD_SRC_FI_B1_L */
+ *ret = s->frame_index_f1 & 0xffff;
+ break;
+
+ case 0xbf4: /* DMA_LCD_SRC_FI_B1_U */
+ *ret = s->frame_index_f1 >> 16;
+ break;
+
+ case 0xbdc: /* DMA_LCD_SRC_EI_B2 */
+ *ret = s->element_index_f2;
+ break;
+
+ case 0xbde: /* DMA_LCD_SRC_FI_B2_L */
+ *ret = s->frame_index_f2 & 0xffff;
+ break;
+
+ case 0xbf6: /* DMA_LCD_SRC_FI_B2_U */
+ *ret = s->frame_index_f2 >> 16;
+ break;
+
+ case 0xbe0: /* DMA_LCD_SRC_EN_B1 */
+ *ret = s->elements_f1;
+ break;
+
+ case 0xbe4: /* DMA_LCD_SRC_FN_B1 */
+ *ret = s->frames_f1;
+ break;
+
+ case 0xbe2: /* DMA_LCD_SRC_EN_B2 */
+ *ret = s->elements_f2;
+ break;
+
+ case 0xbe6: /* DMA_LCD_SRC_FN_B2 */
+ *ret = s->frames_f2;
+ break;
+
+ case 0xbea: /* DMA_LCD_LCH_CTRL */
+ *ret = s->lch_type;
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset,
+ uint16_t value)
+{
switch (offset) {
- case 0x000 ... 0x2fe:
- reg = offset & 0x3f;
- ch = (offset >> 6) & 0x0f;
- if (omap_dma_ch_reg_read(s, ch, reg, &ret))
- break;
- return ret;
-
case 0x300: /* SYS_DMA_LCD_CTRL */
- i = s->lcd_ch.condition;
- s->lcd_ch.condition = 0;
- qemu_irq_lower(s->lcd_ch.irq);
- return ((s->lcd_ch.src == imif) << 6) | (i << 3) |
- (s->lcd_ch.interrupts << 1) | s->lcd_ch.dual;
+ s->src = (value & 0x40) ? imif : emiff;
+ s->condition = 0;
+ /* Assume no bus errors and thus no BUS_ERROR irq bits. */
+ s->interrupts = (value >> 1) & 1;
+ s->dual = value & 1;
+ break;
case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
- return s->lcd_ch.src_f1_top & 0xffff;
+ s->src_f1_top &= 0xffff0000;
+ s->src_f1_top |= 0x0000ffff & value;
+ break;
case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
- return s->lcd_ch.src_f1_top >> 16;
+ s->src_f1_top &= 0x0000ffff;
+ s->src_f1_top |= value << 16;
+ break;
case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
- return s->lcd_ch.src_f1_bottom & 0xffff;
+ s->src_f1_bottom &= 0xffff0000;
+ s->src_f1_bottom |= 0x0000ffff & value;
+ break;
case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
- return s->lcd_ch.src_f1_bottom >> 16;
+ s->src_f1_bottom &= 0x0000ffff;
+ s->src_f1_bottom |= value << 16;
+ break;
case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
- return s->lcd_ch.src_f2_top & 0xffff;
+ s->src_f2_top &= 0xffff0000;
+ s->src_f2_top |= 0x0000ffff & value;
+ break;
case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
- return s->lcd_ch.src_f2_top >> 16;
+ s->src_f2_top &= 0x0000ffff;
+ s->src_f2_top |= value << 16;
+ break;
case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
- return s->lcd_ch.src_f2_bottom & 0xffff;
+ s->src_f2_bottom &= 0xffff0000;
+ s->src_f2_bottom |= 0x0000ffff & value;
+ break;
case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
- return s->lcd_ch.src_f2_bottom >> 16;
+ s->src_f2_bottom &= 0x0000ffff;
+ s->src_f2_bottom |= value << 16;
+ break;
- case 0x400: /* SYS_DMA_GCR */
- return s->gcr;
+ default:
+ return 1;
}
-
- OMAP_BAD_REG(addr);
return 0;
}
-static void omap_dma_write(void *opaque, target_phys_addr_t addr,
- uint32_t value)
+static int omap_dma_3_1_lcd_read(struct omap_dma_lcd_channel_s *s, int offset,
+ uint16_t *ret)
{
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
- int reg, ch, offset = addr - s->base;
+ int i;
switch (offset) {
- case 0x000 ... 0x2fe:
- reg = offset & 0x3f;
- ch = (offset >> 6) & 0x0f;
- if (omap_dma_ch_reg_write(s, ch, reg, value))
- OMAP_RO_REG(addr);
- break;
-
case 0x300: /* SYS_DMA_LCD_CTRL */
- s->lcd_ch.src = (value & 0x40) ? imif : emiff;
- s->lcd_ch.condition = 0;
- /* Assume no bus errors and thus no BUS_ERROR irq bits. */
- s->lcd_ch.interrupts = (value >> 1) & 1;
- s->lcd_ch.dual = value & 1;
+ i = s->condition;
+ s->condition = 0;
+ qemu_irq_lower(s->irq);
+ *ret = ((s->src == imif) << 6) | (i << 3) |
+ (s->interrupts << 1) | s->dual;
break;
case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
- s->lcd_ch.src_f1_top &= 0xffff0000;
- s->lcd_ch.src_f1_top |= 0x0000ffff & value;
+ *ret = s->src_f1_top & 0xffff;
break;
case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
- s->lcd_ch.src_f1_top &= 0x0000ffff;
- s->lcd_ch.src_f1_top |= value << 16;
+ *ret = s->src_f1_top >> 16;
break;
case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
- s->lcd_ch.src_f1_bottom &= 0xffff0000;
- s->lcd_ch.src_f1_bottom |= 0x0000ffff & value;
+ *ret = s->src_f1_bottom & 0xffff;
break;
case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
- s->lcd_ch.src_f1_bottom &= 0x0000ffff;
- s->lcd_ch.src_f1_bottom |= value << 16;
+ *ret = s->src_f1_bottom >> 16;
break;
case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
- s->lcd_ch.src_f2_top &= 0xffff0000;
- s->lcd_ch.src_f2_top |= 0x0000ffff & value;
+ *ret = s->src_f2_top & 0xffff;
break;
case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
- s->lcd_ch.src_f2_top &= 0x0000ffff;
- s->lcd_ch.src_f2_top |= value << 16;
+ *ret = s->src_f2_top >> 16;
break;
case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
- s->lcd_ch.src_f2_bottom &= 0xffff0000;
- s->lcd_ch.src_f2_bottom |= 0x0000ffff & value;
+ *ret = s->src_f2_bottom & 0xffff;
break;
case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
- s->lcd_ch.src_f2_bottom &= 0x0000ffff;
- s->lcd_ch.src_f2_bottom |= value << 16;
+ *ret = s->src_f2_bottom >> 16;
break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static int omap_dma_sys_write(struct omap_dma_s *s, int offset, uint16_t value)
+{
+ switch (offset) {
case 0x400: /* SYS_DMA_GCR */
- s->gcr = value & 0x000c;
+ s->gcr = value;
break;
+ case 0x404: /* DMA_GSCR */
+ if (value & 0x8)
+ omap_dma_disable_3_1_mapping(s);
+ else
+ omap_dma_enable_3_1_mapping(s);
+ break;
+
+ case 0x408: /* DMA_GRST */
+ if (value & 0x1)
+ omap_dma_reset(s);
+ break;
+
default:
- OMAP_BAD_REG(addr);
+ return 1;
}
+ return 0;
}
+static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
+ uint16_t *ret)
+{
+ switch (offset) {
+ case 0x400: /* SYS_DMA_GCR */
+ *ret = s->gcr;
+ break;
+
+ case 0x404: /* DMA_GSCR */
+ *ret = s->omap_3_1_mapping_disabled << 3;
+ break;
+
+ case 0x408: /* DMA_GRST */
+ *ret = 0;
+ break;
+
+ case 0x442: /* DMA_HW_ID */
+ case 0x444: /* DMA_PCh2_ID */
+ case 0x446: /* DMA_PCh0_ID */
+ case 0x448: /* DMA_PCh1_ID */
+ case 0x44a: /* DMA_PChG_ID */
+ case 0x44c: /* DMA_PChD_ID */
+ *ret = 1;
+ break;
+
+ case 0x44e: /* DMA_CAPS_0_U */
+ *ret = (1 << 3) | /* Constant Fill Capacity */
+ (1 << 2); /* Transparent BLT Capacity */
+ break;
+
+ case 0x450: /* DMA_CAPS_0_L */
+ case 0x452: /* DMA_CAPS_1_U */
+ *ret = 0;
+ break;
+
+ case 0x454: /* DMA_CAPS_1_L */
+ *ret = (1 << 1); /* 1-bit palletized capability */
+ break;
+
+ case 0x456: /* DMA_CAPS_2 */
+ *ret = (1 << 8) | /* SSDIC */
+ (1 << 7) | /* DDIAC */
+ (1 << 6) | /* DSIAC */
+ (1 << 5) | /* DPIAC */
+ (1 << 4) | /* DCAC */
+ (1 << 3) | /* SDIAC */
+ (1 << 2) | /* SSIAC */
+ (1 << 1) | /* SPIAC */
+ 1; /* SCAC */
+ break;
+
+ case 0x458: /* DMA_CAPS_3 */
+ *ret = (1 << 5) | /* CCC */
+ (1 << 4) | /* IC */
+ (1 << 3) | /* ARC */
+ (1 << 2) | /* AEC */
+ (1 << 1) | /* FSC */
+ 1; /* ESC */
+ break;
+
+ case 0x45a: /* DMA_CAPS_4 */
+ *ret = (1 << 6) | /* SSC */
+ (1 << 5) | /* BIC */
+ (1 << 4) | /* LFIC */
+ (1 << 3) | /* FIC */
+ (1 << 2) | /* HFIC */
+ (1 << 1) | /* EDIC */
+ 1; /* TOIC */
+ break;
+
+ case 0x460: /* DMA_PCh2_SR */
+ case 0x480: /* DMA_PCh0_SR */
+ case 0x482: /* DMA_PCh1_SR */
+ case 0x4c0: /* DMA_PChD_SR_0 */
+ printf("%s: Physical Channel Status Registers not implemented.\n",
+ __FUNCTION__);
+ *ret = 0xff;
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
+{
+ struct omap_dma_s *s = (struct omap_dma_s *) opaque;
+ int reg, ch, offset = addr - s->base;
+ uint16_t ret;
+
+ switch (offset) {
+ case 0x300 ... 0x3fe:
+ if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
+ if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret))
+ break;
+ return ret;
+ }
+ /* Fall through. */
+ case 0x000 ... 0x2fe:
+ reg = offset & 0x3f;
+ ch = (offset >> 6) & 0x0f;
+ if (omap_dma_ch_reg_read(s, &s->ch[ch], reg, &ret))
+ break;
+ return ret;
+
+ case 0x404 ... 0x4fe:
+ if (s->model == omap_dma_3_1)
+ break;
+ /* Fall through. */
+ case 0x400:
+ if (omap_dma_sys_read(s, offset, &ret))
+ break;
+ return ret;
+
+ case 0xb00 ... 0xbfe:
+ if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
+ if (omap_dma_3_2_lcd_read(&s->lcd_ch, offset, &ret))
+ break;
+ return ret;
+ }
+ break;
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_dma_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_dma_s *s = (struct omap_dma_s *) opaque;
+ int reg, ch, offset = addr - s->base;
+
+ switch (offset) {
+ case 0x300 ... 0x3fe:
+ if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
+ if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value))
+ break;
+ return;
+ }
+ /* Fall through. */
+ case 0x000 ... 0x2fe:
+ reg = offset & 0x3f;
+ ch = (offset >> 6) & 0x0f;
+ if (omap_dma_ch_reg_write(s, &s->ch[ch], reg, value))
+ break;
+ return;
+
+ case 0x404 ... 0x4fe:
+ if (s->model == omap_dma_3_1)
+ break;
+ case 0x400:
+ /* Fall through. */
+ if (omap_dma_sys_write(s, offset, value))
+ break;
+ return;
+
+ case 0xb00 ... 0xbfe:
+ if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) {
+ if (omap_dma_3_2_lcd_write(&s->lcd_ch, offset, value))
+ break;
+ return;
+ }
+ break;
+ }
+
+ OMAP_BAD_REG(addr);
+}
+
static CPUReadMemoryFunc *omap_dma_readfn[] = {
omap_badwidth_read16,
omap_dma_read,
@@ -1005,7 +1666,7 @@
if (req) {
if (~s->drq & (1 << drq)) {
s->drq |= 1 << drq;
- omap_dma_request_run(s, 0, drq);
+ omap_dma_process_request(s, drq);
}
} else
s->drq &= ~(1 << drq);
@@ -1026,37 +1687,33 @@
}
}
-static void omap_dma_reset(struct omap_dma_s *s)
+struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+ qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
+ enum omap_dma_model model)
{
- int i;
-
- qemu_del_timer(s->tm);
- s->gcr = 0x0004;
- s->drq = 0x00000000;
- s->run_count = 0;
- s->lcd_ch.src = emiff;
- s->lcd_ch.condition = 0;
- s->lcd_ch.interrupts = 0;
- s->lcd_ch.dual = 0;
- memset(s->ch, 0, sizeof(s->ch));
- for (i = 0; i < s->chans; i ++)
- s->ch[i].interrupts = 0x0003;
-}
-
-struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
- qemu_irq pic[], struct omap_mpu_state_s *mpu, omap_clk clk)
-{
- int iomemtype;
+ int iomemtype, num_irqs, memsize, i;
struct omap_dma_s *s = (struct omap_dma_s *)
qemu_mallocz(sizeof(struct omap_dma_s));
- s->ih = pic;
+ if (model == omap_dma_3_1) {
+ num_irqs = 6;
+ memsize = 0x800;
+ } else {
+ num_irqs = 16;
+ memsize = 0xc00;
+ }
s->base = base;
- s->chans = 9;
+ s->model = model;
s->mpu = mpu;
s->clk = clk;
- s->lcd_ch.irq = pic[OMAP_INT_DMA_LCD];
+ s->lcd_ch.irq = lcd_irq;
s->lcd_ch.mpu = mpu;
+ while (num_irqs --)
+ s->ch[num_irqs].irq = irqs[num_irqs];
+ for (i = 0; i < 3; i ++) {
+ s->ch[i].sibling = &s->ch[i + 6];
+ s->ch[i + 6].sibling = &s->ch[i];
+ }
s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32);
@@ -1065,7 +1722,7 @@
iomemtype = cpu_register_io_memory(0, omap_dma_readfn,
omap_dma_writefn, s);
- cpu_register_physical_memory(s->base, 0x800, iomemtype);
+ cpu_register_physical_memory(s->base, memsize, iomemtype);
return s;
}
@@ -2919,8 +3576,8 @@
if (*row & cols)
rows |= i;
- qemu_set_irq(s->kbd_irq, rows && ~s->kbd_mask && s->clk);
- s->row_latch = rows ^ 0x1f;
+ qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
+ s->row_latch = ~rows;
}
static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
@@ -2952,7 +3609,7 @@
return s->edge;
case 0x20: /* KBD_INT */
- return (s->row_latch != 0x1f) && !s->kbd_mask;
+ return (~s->row_latch & 0x1f) && !s->kbd_mask;
case 0x24: /* GPIO_INT */
ret = s->ints;
@@ -4919,13 +5576,39 @@
cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
}
+struct dma_irq_map {
+ int ih;
+ int intr;
+};
+
+static const struct dma_irq_map omap_dma_irq_map[] = {
+ { 0, OMAP_INT_DMA_CH0_6 },
+ { 0, OMAP_INT_DMA_CH1_7 },
+ { 0, OMAP_INT_DMA_CH2_8 },
+ { 0, OMAP_INT_DMA_CH3 },
+ { 0, OMAP_INT_DMA_CH4 },
+ { 0, OMAP_INT_DMA_CH5 },
+ { 1, OMAP_INT_1610_DMA_CH6 },
+ { 1, OMAP_INT_1610_DMA_CH7 },
+ { 1, OMAP_INT_1610_DMA_CH8 },
+ { 1, OMAP_INT_1610_DMA_CH9 },
+ { 1, OMAP_INT_1610_DMA_CH10 },
+ { 1, OMAP_INT_1610_DMA_CH11 },
+ { 1, OMAP_INT_1610_DMA_CH12 },
+ { 1, OMAP_INT_1610_DMA_CH13 },
+ { 1, OMAP_INT_1610_DMA_CH14 },
+ { 1, OMAP_INT_1610_DMA_CH15 }
+};
+
struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
DisplayState *ds, const char *core)
{
+ int i;
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
qemu_mallocz(sizeof(struct omap_mpu_state_s));
ram_addr_t imif_base, emiff_base;
qemu_irq *cpu_irq;
+ qemu_irq dma_irqs[6];
int sdindex;
if (!core)
@@ -4964,8 +5647,11 @@
s->irq[0] = s->ih[0]->pins;
s->irq[1] = s->ih[1]->pins;
- s->dma = omap_dma_init(0xfffed800, s->irq[0], s,
- omap_findclk(s, "dma_ck"));
+ for (i = 0; i < 6; i ++)
+ dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
+ s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
+ s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
+
s->port[emiff ].addr_valid = omap_validate_emiff_addr;
s->port[emifs ].addr_valid = omap_validate_emifs_addr;
s->port[imif ].addr_valid = omap_validate_imif_addr;
Modified: trunk/src/host/qemu-neo1973/hw/omap.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/omap.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -336,26 +336,68 @@
# define OMAP_INT_243X_HS_USB_DMA 93
# define OMAP_INT_243X_CARKIT 94
+enum omap_dma_model {
+ omap_dma_3_1 = 0,
+ omap_dma_3_2
+};
+
struct omap_dma_s;
-struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
- qemu_irq pic[], struct omap_mpu_state_s *mpu, omap_clk clk);
+struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
+ qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
+ enum omap_dma_model model);
enum omap_dma_port {
emiff = 0,
emifs,
- imif,
+ imif, /* omap16xx: ocp_t1 */
tipb,
- local,
+ local, /* omap16xx: ocp_t2 */
tipb_mpui,
omap_dma_port_last,
};
+typedef enum {
+ constant = 0,
+ post_incremented,
+ single_index,
+ double_index,
+} omap_dma_addressing_t;
+
struct omap_dma_lcd_channel_s {
enum omap_dma_port src;
target_phys_addr_t src_f1_top;
target_phys_addr_t src_f1_bottom;
target_phys_addr_t src_f2_top;
target_phys_addr_t src_f2_bottom;
+
+ /* Used in OMAP DMA 3.2 gigacell */
+ unsigned char brust_f1;
+ unsigned char pack_f1;
+ unsigned char data_type_f1;
+ unsigned char brust_f2;
+ unsigned char pack_f2;
+ unsigned char data_type_f2;
+ unsigned char end_prog;
+ unsigned char repeat;
+ unsigned char auto_init;
+ unsigned char priority;
+ unsigned char fs;
+ unsigned char running;
+ unsigned char bs;
+ unsigned char omap_3_1_compatible_disable;
+ unsigned char dst;
+ unsigned char lch_type;
+ int16_t element_index_f1;
+ int16_t element_index_f2;
+ int32_t frame_index_f1;
+ int32_t frame_index_f2;
+ uint16_t elements_f1;
+ uint16_t frames_f1;
+ uint16_t elements_f2;
+ uint16_t frames_f2;
+ omap_dma_addressing_t mode_f1;
+ omap_dma_addressing_t mode_f2;
+
/* Destination port is fixed. */
int interrupts;
int condition;
Modified: trunk/src/host/qemu-neo1973/hw/pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pci.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/pci.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -42,6 +42,7 @@
PCIBus *next;
/* The bus IRQ state is the logical OR of the connected devices.
Keep a count of the number of devices with raised IRQs. */
+ int nirq;
int irq_count[];
};
@@ -52,16 +53,51 @@
static int pci_irq_index;
static PCIBus *first_bus;
+static void pcibus_save(QEMUFile *f, void *opaque)
+{
+ PCIBus *bus = (PCIBus *)opaque;
+ int i;
+
+ qemu_put_be32(f, bus->nirq);
+ for (i = 0; i < bus->nirq; i++)
+ qemu_put_be32(f, bus->irq_count[i]);
+}
+
+static int pcibus_load(QEMUFile *f, void *opaque, int version_id)
+{
+ PCIBus *bus = (PCIBus *)opaque;
+ int i, nirq;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ nirq = qemu_get_be32(f);
+ if (bus->nirq != nirq) {
+ fprintf(stderr, "pcibus_load: nirq mismatch: src=%d dst=%d\n",
+ nirq, bus->nirq);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nirq; i++)
+ bus->irq_count[i] = qemu_get_be32(f);
+
+ return 0;
+}
+
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
qemu_irq *pic, int devfn_min, int nirq)
{
PCIBus *bus;
+ static int nbus = 0;
+
bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
bus->set_irq = set_irq;
bus->map_irq = map_irq;
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
+ bus->nirq = nirq;
first_bus = bus;
+ register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
return bus;
}
@@ -83,18 +119,29 @@
void pci_device_save(PCIDevice *s, QEMUFile *f)
{
- qemu_put_be32(f, 1); /* PCI device version */
+ int i;
+
+ qemu_put_be32(f, 2); /* PCI device version */
qemu_put_buffer(f, s->config, 256);
+ for (i = 0; i < 4; i++)
+ qemu_put_be32(f, s->irq_state[i]);
}
int pci_device_load(PCIDevice *s, QEMUFile *f)
{
uint32_t version_id;
+ int i;
+
version_id = qemu_get_be32(f);
- if (version_id != 1)
+ if (version_id > 2)
return -EINVAL;
qemu_get_buffer(f, s->config, 256);
pci_update_mappings(s);
+
+ if (version_id >= 2)
+ for (i = 0; i < 4; i ++)
+ s->irq_state[i] = qemu_get_be32(f);
+
return 0;
}
Modified: trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -483,11 +483,11 @@
return ret;
}
-pflash_t *pflash_register (target_phys_addr_t base, ram_addr_t off,
- BlockDriverState *bs,
- target_ulong sector_len, int nb_blocs, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3)
+pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
+ BlockDriverState *bs, target_ulong sector_len,
+ int nb_blocs, int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3)
{
pflash_t *pfl;
target_long total_len;
Modified: trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -524,11 +524,11 @@
return ret;
}
-pflash_t *pflash_register (target_phys_addr_t base, ram_addr_t off,
- BlockDriverState *bs,
- uint32_t sector_len, int nb_blocs, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3)
+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,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3)
{
pflash_t *pfl;
int32_t total_len;
Modified: trunk/src/host/qemu-neo1973/hw/piix_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/piix_pci.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/piix_pci.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -57,6 +57,7 @@
static uint32_t isa_page_descs[384 / 4];
static uint8_t smm_enabled;
+static int pci_irq_levels[4];
static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r)
{
@@ -139,22 +140,32 @@
static void i440fx_save(QEMUFile* f, void *opaque)
{
PCIDevice *d = opaque;
+ int i;
+
pci_device_save(d, f);
qemu_put_8s(f, &smm_enabled);
+
+ for (i = 0; i < 4; i++)
+ qemu_put_be32(f, pci_irq_levels[i]);
}
static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
{
PCIDevice *d = opaque;
- int ret;
+ int ret, i;
- if (version_id != 1)
+ if (version_id > 2)
return -EINVAL;
ret = pci_device_load(d, f);
if (ret < 0)
return ret;
i440fx_update_memory_mappings(d);
qemu_get_8s(f, &smm_enabled);
+
+ if (version_id >= 2)
+ for (i = 0; i < 4; i++)
+ pci_irq_levels[i] = qemu_get_be32(f);
+
return 0;
}
@@ -192,7 +203,7 @@
d->config[0x72] = 0x02; /* SMRAM */
- register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
+ register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
*pi440fx_state = d;
return b;
}
@@ -205,8 +216,6 @@
/* just used for simpler irq handling. */
#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
-static int pci_irq_levels[4];
-
static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
{
int i, pic_irq, pic_level;
@@ -314,31 +323,6 @@
return pci_device_load(d, f);
}
-static int piix_init(PCIBus *bus, int devfn)
-{
- PCIDevice *d;
- uint8_t *pci_conf;
-
- d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
- devfn, NULL, NULL);
- register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
-
- piix3_dev = d;
- pci_conf = d->config;
-
- pci_conf[0x00] = 0x86; // Intel
- pci_conf[0x01] = 0x80;
- pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
- pci_conf[0x03] = 0x12;
- pci_conf[0x08] = 0x02; // Step A1
- pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
- pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
- pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
-
- piix3_reset(d);
- return d->devfn;
-}
-
int piix3_init(PCIBus *bus, int devfn)
{
PCIDevice *d;
Modified: trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_boards.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_boards.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -234,9 +234,9 @@
fl_idx, bios_size, bios_offset, -bios_size,
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
#endif
- pflash_register((uint32_t)(-bios_size), bios_offset,
- drives_table[index].bdrv, 65536, fl_sectors, 2,
- 0x0001, 0x22DA, 0x0000, 0x0000);
+ pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+ drives_table[index].bdrv, 65536, fl_sectors, 2,
+ 0x0001, 0x22DA, 0x0000, 0x0000);
fl_idx++;
} else
#endif
@@ -551,9 +551,9 @@
fl_idx, bios_size, bios_offset, -bios_size,
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
#endif
- pflash_register((uint32_t)(-bios_size), bios_offset,
- drives_table[index].bdrv, 65536, fl_sectors, 4,
- 0x0001, 0x22DA, 0x0000, 0x0000);
+ pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
+ drives_table[index].bdrv, 65536, fl_sectors, 4,
+ 0x0001, 0x22DA, 0x0000, 0x0000);
fl_idx++;
} else
#endif
@@ -587,9 +587,9 @@
fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
bdrv_get_device_name(drives_table[index].bdrv));
#endif
- pflash_register(0xfc000000, bios_offset, drives_table[index].bdrv,
- 65536, fl_sectors, 4,
- 0x0001, 0x22DA, 0x0000, 0x0000);
+ pflash_cfi02_register(0xfc000000, bios_offset,
+ drives_table[index].bdrv, 65536, fl_sectors, 4,
+ 0x0001, 0x22DA, 0x0000, 0x0000);
fl_idx++;
}
/* Register CLPD & LCD display */
Modified: trunk/src/host/qemu-neo1973/hw/scsi-disk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-disk.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/scsi-disk.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -37,7 +37,7 @@
#define SCSI_DMA_BUF_SIZE 65536
typedef struct SCSIRequest {
- SCSIDevice *dev;
+ SCSIDeviceState *dev;
uint32_t tag;
/* ??? We should probably keep track of whether the data trasfer is
a read or a write. Currently we rely on the host getting it right. */
@@ -51,7 +51,7 @@
struct SCSIRequest *next;
} SCSIRequest;
-struct SCSIDevice
+struct SCSIDeviceState
{
BlockDriverState *bdrv;
SCSIRequest *requests;
@@ -69,7 +69,7 @@
/* Global pool of SCSIRequest structures. */
static SCSIRequest *free_requests = NULL;
-static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
+static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
{
SCSIRequest *r;
@@ -93,7 +93,7 @@
static void scsi_remove_request(SCSIRequest *r)
{
SCSIRequest *last;
- SCSIDevice *s = r->dev;
+ SCSIDeviceState *s = r->dev;
if (s->requests == r) {
s->requests = r->next;
@@ -111,7 +111,7 @@
free_requests = r;
}
-static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag)
+static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
{
SCSIRequest *r;
@@ -125,7 +125,7 @@
/* Helper function for command completion. */
static void scsi_command_complete(SCSIRequest *r, int sense)
{
- SCSIDevice *s = r->dev;
+ SCSIDeviceState *s = r->dev;
uint32_t tag;
DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
s->sense = sense;
@@ -135,8 +135,9 @@
}
/* Cancel a pending data transfer. */
-void scsi_cancel_io(SCSIDevice *s, uint32_t tag)
+static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
DPRINTF("Cancel tag=0x%x\n", tag);
r = scsi_find_request(s, tag);
@@ -151,7 +152,7 @@
static void scsi_read_complete(void * opaque, int ret)
{
SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIDevice *s = r->dev;
+ SCSIDeviceState *s = r->dev;
if (ret) {
DPRINTF("IO error\n");
@@ -164,8 +165,9 @@
}
/* Read more data from scsi device into buffer. */
-void scsi_read_data(SCSIDevice *s, uint32_t tag)
+static void scsi_read_data(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
uint32_t n;
@@ -204,7 +206,7 @@
static void scsi_write_complete(void * opaque, int ret)
{
SCSIRequest *r = (SCSIRequest *)opaque;
- SCSIDevice *s = r->dev;
+ SCSIDeviceState *s = r->dev;
uint32_t len;
if (ret) {
@@ -228,8 +230,9 @@
/* Write data to a scsi device. Returns nonzero on failure.
The transfer may complete asynchronously. */
-int scsi_write_data(SCSIDevice *s, uint32_t tag)
+static int scsi_write_data(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
uint32_t n;
@@ -259,8 +262,9 @@
}
/* Return a pointer to the data buffer. */
-uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag)
+static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
{
+ SCSIDeviceState *s = d->state;
SCSIRequest *r;
r = scsi_find_request(s, tag);
@@ -276,8 +280,10 @@
(eg. disk reads), negative for transfers to the device (eg. disk writes),
and zero if the command does not transfer any data. */
-int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
+static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
+ uint8_t *buf, int lun)
{
+ SCSIDeviceState *s = d->state;
int64_t nb_sectors;
uint32_t lba;
uint32_t len;
@@ -291,7 +297,7 @@
r = scsi_find_request(s, tag);
if (r) {
BADF("Tag 0x%x already in use\n", tag);
- scsi_cancel_io(s, tag);
+ scsi_cancel_io(d, tag);
}
/* ??? Tags are not unique for different luns. We only implement a
single lun, so this should not matter. */
@@ -576,19 +582,19 @@
}
}
-void scsi_disk_destroy(SCSIDevice *s)
+static void scsi_destroy(SCSIDevice *d)
{
- qemu_free(s);
+ qemu_free(d->state);
+ qemu_free(d);
}
-SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
- int tcq,
- scsi_completionfn completion,
- void *opaque)
+SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
+ scsi_completionfn completion, void *opaque)
{
- SCSIDevice *s;
+ SCSIDevice *d;
+ SCSIDeviceState *s;
- s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+ s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
s->bdrv = bdrv;
s->tcq = tcq;
s->completion = completion;
@@ -599,6 +605,14 @@
s->cluster_size = 1;
}
- return s;
+ d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+ d->state = s;
+ d->destroy = scsi_destroy;
+ d->send_command = scsi_send_command;
+ d->read_data = scsi_read_data;
+ d->write_data = scsi_write_data;
+ d->cancel_io = scsi_cancel_io;
+ d->get_buf = scsi_get_buf;
+
+ return d;
}
-
Modified: trunk/src/host/qemu-neo1973/hw/scsi-disk.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-disk.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/scsi-disk.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -7,24 +7,25 @@
SCSI_REASON_DATA /* Transfer complete, more data required. */
};
+typedef struct SCSIDeviceState SCSIDeviceState;
typedef struct SCSIDevice SCSIDevice;
typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag,
uint32_t arg);
-SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
- int tcq,
- scsi_completionfn completion,
- void *opaque);
-void scsi_disk_destroy(SCSIDevice *s);
+struct SCSIDevice
+{
+ SCSIDeviceState *state;
+ void (*destroy)(SCSIDevice *s);
+ int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf,
+ int lun);
+ void (*read_data)(SCSIDevice *s, uint32_t tag);
+ int (*write_data)(SCSIDevice *s, uint32_t tag);
+ void (*cancel_io)(SCSIDevice *s, uint32_t tag);
+ uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag);
+};
-int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun);
-/* SCSI data transfers are asynchrnonous. However, unlike the block IO
- layer the completion routine may be called directly by
- scsi_{read,write}_data. */
-void scsi_read_data(SCSIDevice *s, uint32_t tag);
-int scsi_write_data(SCSIDevice *s, uint32_t tag);
-void scsi_cancel_io(SCSIDevice *s, uint32_t tag);
-uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag);
+SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
+ scsi_completionfn completion, void *opaque);
/* cdrom.c */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -72,6 +72,8 @@
target_phys_addr_t serial_base, fd_base;
target_phys_addr_t dma_base, esp_base, le_base;
target_phys_addr_t tcx_base, cs_base, power_base;
+ target_phys_addr_t ecc_base;
+ uint32_t ecc_version;
long vram_size, nvram_size;
// IRQ numbers are not PIL ones, but master interrupt controller register
// bit numbers
@@ -479,6 +481,9 @@
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
boot_device, RAM_size, kernel_size, graphic_width,
graphic_height, graphic_depth, hwdef->machine_id);
+
+ if (hwdef->ecc_base != (target_phys_addr_t)-1)
+ ecc_init(hwdef->ecc_base, hwdef->ecc_version);
}
static const struct hwdef hwdefs[] = {
@@ -498,6 +503,7 @@
.esp_base = 0x78800000,
.le_base = 0x78c00000,
.power_base = 0x7a000000,
+ .ecc_base = -1,
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -534,6 +540,8 @@
.esp_base = 0xef0800000ULL,
.le_base = 0xef0c00000ULL,
.power_base = 0xefa000000ULL,
+ .ecc_base = 0xf00000000ULL,
+ .ecc_version = 0x10000000, // version 0, implementation 1
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -570,6 +578,8 @@
.esp_base = 0xef0080000ULL,
.le_base = 0xef0060000ULL,
.power_base = 0xefa000000ULL,
+ .ecc_base = 0xf00000000ULL,
+ .ecc_version = 0x00000000, // version 0, implementation 0
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -72,4 +72,7 @@
void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
qemu_irq irq, qemu_irq *reset);
+/* eccmemctl.c */
+void *ecc_init(target_phys_addr_t base, uint32_t version);
+
#endif
Modified: trunk/src/host/qemu-neo1973/hw/usb-msd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-msd.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/hw/usb-msd.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -149,9 +149,9 @@
s->data_len -= len;
if (s->scsi_len == 0) {
if (s->mode == USB_MSDM_DATAIN) {
- scsi_read_data(s->scsi_dev, s->tag);
+ s->scsi_dev->read_data(s->scsi_dev, s->tag);
} else if (s->mode == USB_MSDM_DATAOUT) {
- scsi_write_data(s->scsi_dev, s->tag);
+ s->scsi_dev->write_data(s->scsi_dev, s->tag);
}
}
}
@@ -204,7 +204,7 @@
return;
}
s->scsi_len = arg;
- s->scsi_buf = scsi_get_buf(s->scsi_dev, tag);
+ s->scsi_buf = s->scsi_dev->get_buf(s->scsi_dev, tag);
if (p) {
usb_msd_copy_data(s);
if (s->usb_len == 0) {
@@ -342,7 +342,7 @@
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
{
MSDState *s = opaque;
- scsi_cancel_io(s->scsi_dev, s->tag);
+ s->scsi_dev->cancel_io(s->scsi_dev, s->tag);
s->packet = NULL;
s->scsi_len = 0;
}
@@ -390,14 +390,14 @@
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
s->tag, cbw.flags, cbw.cmd_len, s->data_len);
s->residue = 0;
- scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
+ s->scsi_dev->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
/* ??? Should check that USB and SCSI data transfer
directions match. */
if (s->residue == 0) {
if (s->mode == USB_MSDM_DATAIN) {
- scsi_read_data(s->scsi_dev, s->tag);
+ s->scsi_dev->read_data(s->scsi_dev, s->tag);
} else if (s->mode == USB_MSDM_DATAOUT) {
- scsi_write_data(s->scsi_dev, s->tag);
+ s->scsi_dev->write_data(s->scsi_dev, s->tag);
}
}
ret = len;
@@ -508,7 +508,7 @@
{
MSDState *s = (MSDState *)dev;
- scsi_disk_destroy(s->scsi_dev);
+ s->scsi_dev->destroy(s->scsi_dev);
bdrv_delete(s->bs);
qemu_free(s);
}
Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -26,20 +26,24 @@
#define __USER_DS (1)
struct target_pt_regs {
- unsigned long gpr[32];
- unsigned long nip;
- unsigned long msr;
- unsigned long orig_gpr3; /* Used for restarting system calls */
- unsigned long ctr;
- unsigned long link;
- unsigned long xer;
- unsigned long ccr;
- unsigned long mq; /* 601 only (not used at present) */
+ abi_ulong gpr[32];
+ abi_ulong nip;
+ abi_ulong msr;
+ abi_ulong orig_gpr3; /* Used for restarting system calls */
+ abi_ulong ctr;
+ abi_ulong link;
+ abi_ulong xer;
+ abi_ulong ccr;
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+ abi_ulong softe;
+#else
+ abi_ulong mq; /* 601 only (not used at present) */
+#endif
/* Used on APUS to hold IPL value. */
- unsigned long trap; /* Reason for being here */
- unsigned long dar; /* Fault registers */
- unsigned long dsisr;
- unsigned long result; /* Result of a system call */
+ abi_ulong trap; /* Reason for being here */
+ abi_ulong dar; /* Fault registers */
+ abi_ulong dsisr;
+ abi_ulong result; /* Result of a system call */
};
/* ioctls */
Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -7,7 +7,7 @@
typedef struct target_sigaltstack {
abi_ulong ss_sp;
- abi_long ss_flags;
+ int ss_flags;
abi_ulong ss_size;
} target_stack_t;
Modified: trunk/src/host/qemu-neo1973/linux-user/socket.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/socket.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/linux-user/socket.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -109,12 +109,21 @@
#define TARGET_SO_LINGER 13
#define TARGET_SO_BSDCOMPAT 14
/* To add :#define TARGET_SO_REUSEPORT 15 */
+#if defined(TARGET_PPC)
+ #define TARGET_SO_RCVLOWAT 16
+ #define TARGET_SO_SNDLOWAT 17
+ #define TARGET_SO_RCVTIMEO 18
+ #define TARGET_SO_SNDTIMEO 19
+ #define TARGET_SO_PASSCRED 20
+ #define TARGET_SO_PEERCRED 21
+#else
#define TARGET_SO_PASSCRED 16
#define TARGET_SO_PEERCRED 17
#define TARGET_SO_RCVLOWAT 18
#define TARGET_SO_SNDLOWAT 19
#define TARGET_SO_RCVTIMEO 20
#define TARGET_SO_SNDTIMEO 21
+#endif
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define TARGET_SO_SECURITY_AUTHENTICATION 22
Modified: trunk/src/host/qemu-neo1973/linux-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -443,50 +443,66 @@
}
}
-static inline fd_set *target_to_host_fds(fd_set *fds,
- abi_long *target_fds, int n)
+static inline abi_long copy_from_user_fdset(fd_set *fds,
+ abi_ulong target_fds_addr,
+ int n)
{
-#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
- return (fd_set *)target_fds;
-#else
- int i, b;
- if (target_fds) {
- FD_ZERO(fds);
- for(i = 0;i < n; i++) {
- b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >>
- (i & (TARGET_ABI_BITS - 1))) & 1;
- if (b)
- FD_SET(i, fds);
+ int i, nw, j, k;
+ abi_ulong b, *target_fds;
+
+ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+ if (!(target_fds = lock_user(VERIFY_READ,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 1)))
+ return -TARGET_EFAULT;
+
+ FD_ZERO(fds);
+ k = 0;
+ for (i = 0; i < nw; i++) {
+ /* grab the abi_ulong */
+ __get_user(b, &target_fds[i]);
+ for (j = 0; j < TARGET_ABI_BITS; j++) {
+ /* check the bit inside the abi_ulong */
+ if ((b >> j) & 1)
+ FD_SET(k, fds);
+ k++;
}
- return fds;
- } else {
- return NULL;
}
-#endif
+
+ unlock_user(target_fds, target_fds_addr, 0);
+
+ return 0;
}
-static inline void host_to_target_fds(abi_long *target_fds,
- fd_set *fds, int n)
+static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
+ const fd_set *fds,
+ int n)
{
-#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
- /* nothing to do */
-#else
int i, nw, j, k;
abi_long v;
+ abi_ulong *target_fds;
- if (target_fds) {
- nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
- k = 0;
- for(i = 0;i < nw; i++) {
- v = 0;
- for(j = 0; j < TARGET_ABI_BITS; j++) {
- v |= ((FD_ISSET(k, fds) != 0) << j);
- k++;
- }
- target_fds[i] = tswapl(v);
+ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+ if (!(target_fds = lock_user(VERIFY_WRITE,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 0)))
+ return -TARGET_EFAULT;
+
+ k = 0;
+ for (i = 0; i < nw; i++) {
+ v = 0;
+ for (j = 0; j < TARGET_ABI_BITS; j++) {
+ v |= ((FD_ISSET(k, fds) != 0) << j);
+ k++;
}
+ __put_user(v, &target_fds[i]);
}
-#endif
+
+ unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
+
+ return 0;
}
#if defined(__alpha__)
@@ -534,105 +550,93 @@
return 0;
}
-static inline abi_long target_to_host_timeval(struct timeval *tv,
- abi_ulong target_addr)
+static inline abi_long copy_from_user_timeval(struct timeval *tv,
+ abi_ulong target_tv_addr)
{
struct target_timeval *target_tv;
- if (!lock_user_struct(VERIFY_READ, target_tv, target_addr, 1))
+ if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
return -TARGET_EFAULT;
- tv->tv_sec = tswapl(target_tv->tv_sec);
- tv->tv_usec = tswapl(target_tv->tv_usec);
- unlock_user_struct(target_tv, target_addr, 0);
+ __get_user(tv->tv_sec, &target_tv->tv_sec);
+ __get_user(tv->tv_usec, &target_tv->tv_usec);
+
+ unlock_user_struct(target_tv, target_tv_addr, 0);
+
return 0;
}
-static inline abi_long host_to_target_timeval(abi_ulong target_addr,
- const struct timeval *tv)
+static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
+ const struct timeval *tv)
{
struct target_timeval *target_tv;
- if (!lock_user_struct(VERIFY_WRITE, target_tv, target_addr, 0))
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
return -TARGET_EFAULT;
- target_tv->tv_sec = tswapl(tv->tv_sec);
- target_tv->tv_usec = tswapl(tv->tv_usec);
- unlock_user_struct(target_tv, target_addr, 1);
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
+ __put_user(tv->tv_usec, &target_tv->tv_usec);
+
+ unlock_user_struct(target_tv, target_tv_addr, 1);
+
return 0;
}
/* do_select() must return target values and target errnos. */
static abi_long do_select(int n,
- abi_ulong rfd_p, abi_ulong wfd_p,
- abi_ulong efd_p, abi_ulong target_tv)
+ abi_ulong rfd_addr, abi_ulong wfd_addr,
+ abi_ulong efd_addr, abi_ulong target_tv_addr)
{
fd_set rfds, wfds, efds;
fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
- abi_long *target_rfds, *target_wfds, *target_efds;
struct timeval tv, *tv_ptr;
abi_long ret;
- int ok;
- if (rfd_p) {
- target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);
- if (!target_rfds) {
- ret = -TARGET_EFAULT;
- goto end;
- }
- rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
+ if (rfd_addr) {
+ if (copy_from_user_fdset(&rfds, rfd_addr, n))
+ return -TARGET_EFAULT;
+ rfds_ptr = &rfds;
} else {
- target_rfds = NULL;
rfds_ptr = NULL;
}
- if (wfd_p) {
- target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);
- if (!target_wfds) {
- ret = -TARGET_EFAULT;
- goto end;
- }
- wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
+ if (wfd_addr) {
+ if (copy_from_user_fdset(&wfds, wfd_addr, n))
+ return -TARGET_EFAULT;
+ wfds_ptr = &wfds;
} else {
- target_wfds = NULL;
wfds_ptr = NULL;
}
- if (efd_p) {
- target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1);
- if (!target_efds) {
- ret = -TARGET_EFAULT;
- goto end;
- }
- efds_ptr = target_to_host_fds(&efds, target_efds, n);
+ if (efd_addr) {
+ if (copy_from_user_fdset(&efds, efd_addr, n))
+ return -TARGET_EFAULT;
+ efds_ptr = &efds;
} else {
- target_efds = NULL;
efds_ptr = NULL;
}
- if (target_tv) {
- target_to_host_timeval(&tv, target_tv);
+ if (target_tv_addr) {
+ if (copy_from_user_timeval(&tv, target_tv_addr))
+ return -TARGET_EFAULT;
tv_ptr = &tv;
} else {
tv_ptr = NULL;
}
+
ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
- ok = !is_error(ret);
- if (ok) {
- host_to_target_fds(target_rfds, rfds_ptr, n);
- host_to_target_fds(target_wfds, wfds_ptr, n);
- host_to_target_fds(target_efds, efds_ptr, n);
+ if (!is_error(ret)) {
+ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
+ return -TARGET_EFAULT;
+ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
+ return -TARGET_EFAULT;
+ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
+ return -TARGET_EFAULT;
- if (target_tv) {
- host_to_target_timeval(target_tv, &tv);
- }
+ if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
+ return -TARGET_EFAULT;
}
-end:
- unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
- unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
- unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
-
return ret;
}
@@ -3186,7 +3190,7 @@
argc = 0;
guest_argp = arg2;
- for (gp = guest_argp; ; gp++) {
+ for (gp = guest_argp; ; gp += sizeof(abi_ulong)) {
if (get_user_ual(addr, gp))
goto efault;
if (!addr)
@@ -3195,7 +3199,7 @@
}
envc = 0;
guest_envp = arg3;
- for (gp = guest_envp; ; gp++) {
+ for (gp = guest_envp; ; gp += sizeof(abi_ulong)) {
if (get_user_ual(addr, gp))
goto efault;
if (!addr)
@@ -3391,9 +3395,10 @@
{
struct timeval *tvp, tv[2];
if (arg2) {
- target_to_host_timeval(&tv[0], arg2);
- target_to_host_timeval(&tv[1],
- arg2 + sizeof (struct target_timeval));
+ if (copy_from_user_timeval(&tv[0], arg2)
+ || copy_from_user_timeval(&tv[1],
+ arg2 + sizeof(struct target_timeval)))
+ goto efault;
tvp = tv;
} else {
tvp = NULL;
@@ -3932,14 +3937,16 @@
struct timeval tv;
ret = get_errno(gettimeofday(&tv, NULL));
if (!is_error(ret)) {
- host_to_target_timeval(arg1, &tv);
+ if (copy_to_user_timeval(arg1, &tv))
+ goto efault;
}
}
break;
case TARGET_NR_settimeofday:
{
struct timeval tv;
- target_to_host_timeval(&tv, arg1);
+ if (copy_from_user_timeval(&tv, arg1))
+ goto efault;
ret = get_errno(settimeofday(&tv, NULL));
}
break;
@@ -4314,19 +4321,20 @@
if (arg2) {
pvalue = &value;
- target_to_host_timeval(&pvalue->it_interval,
- arg2);
- target_to_host_timeval(&pvalue->it_value,
- arg2 + sizeof(struct target_timeval));
+ if (copy_from_user_timeval(&pvalue->it_interval, arg2)
+ || copy_from_user_timeval(&pvalue->it_value,
+ arg2 + sizeof(struct target_timeval)))
+ goto efault;
} else {
pvalue = NULL;
}
ret = get_errno(setitimer(arg1, pvalue, &ovalue));
if (!is_error(ret) && arg3) {
- host_to_target_timeval(arg3,
- &ovalue.it_interval);
- host_to_target_timeval(arg3 + sizeof(struct target_timeval),
- &ovalue.it_value);
+ if (copy_to_user_timeval(arg3,
+ &ovalue.it_interval)
+ || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
+ &ovalue.it_value))
+ goto efault;
}
}
break;
@@ -4336,10 +4344,11 @@
ret = get_errno(getitimer(arg1, &value));
if (!is_error(ret) && arg2) {
- host_to_target_timeval(arg2,
- &value.it_interval);
- host_to_target_timeval(arg2 + sizeof(struct target_timeval),
- &value.it_value);
+ if (copy_to_user_timeval(arg2,
+ &value.it_interval)
+ || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
+ &value.it_value))
+ goto efault;
}
}
break;
Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -1086,10 +1086,10 @@
#elif defined(TARGET_PPC)
struct target_stat {
- unsigned short st_dev;
+ abi_ulong st_dev;
abi_ulong st_ino;
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
- unsigned short st_nlink;
+ abi_ulong st_nlink;
unsigned int st_mode;
#else
unsigned int st_mode;
@@ -1097,16 +1097,16 @@
#endif
unsigned int st_uid;
unsigned int st_gid;
- unsigned short st_rdev;
+ abi_ulong st_rdev;
abi_ulong st_size;
abi_ulong st_blksize;
abi_ulong st_blocks;
abi_ulong target_st_atime;
- abi_ulong __unused1;
+ abi_ulong target_st_atime_nsec;
abi_ulong target_st_mtime;
- abi_ulong __unused2;
+ abi_ulong target_st_mtime_nsec;
abi_ulong target_st_ctime;
- abi_ulong __unused3;
+ abi_ulong target_st_ctime_nsec;
abi_ulong __unused4;
abi_ulong __unused5;
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
@@ -1122,19 +1122,18 @@
unsigned int st_uid;
unsigned int st_gid;
unsigned long long st_rdev;
- long long pad0;
- long long st_size;
- abi_ulong st_blksize;
- abi_ulong pad1;
- long long st_blocks; /* Number 512-byte blocks allocated. */
- abi_ulong target_st_atime;
- abi_ulong target_st_atime_nsec;
- abi_ulong target_st_mtime;
- abi_ulong target_st_mtime_nsec;
- abi_ulong target_st_ctime;
- abi_ulong target_st_ctime_nsec;
- abi_ulong __unused4;
- abi_ulong __unused5;
+ unsigned short pad0;
+ long long st_size;
+ int st_blksize;
+ long long st_blocks; /* Number 512-byte blocks allocated. */
+ int target_st_atime;
+ unsigned int target_st_atime_nsec;
+ int target_st_mtime;
+ unsigned int target_st_mtime_nsec;
+ int target_st_ctime;
+ unsigned int target_st_ctime_nsec;
+ unsigned int __unused4;
+ unsigned int __unused5;
};
#elif defined(TARGET_M68K)
Modified: trunk/src/host/qemu-neo1973/target-arm/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/helper.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-arm/helper.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -187,6 +187,7 @@
if (!env)
return NULL;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
env->cp15.c0_cpuid = id;
cpu_reset(env);
return env;
Modified: trunk/src/host/qemu-neo1973/target-i386/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/exec.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-i386/exec.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -199,6 +199,7 @@
void helper_syscall(int next_eip_addend);
void helper_sysret(int dflag);
void helper_rdtsc(void);
+void helper_rdpmc(void);
void helper_rdmsr(void);
void helper_wrmsr(void);
void helper_lsl(void);
Modified: trunk/src/host/qemu-neo1973/target-i386/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-i386/helper.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -2743,6 +2743,18 @@
EDX = (uint32_t)(val >> 32);
}
+void helper_rdpmc(void)
+{
+ if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
+ raise_exception(EXCP0D_GPF);
+ }
+
+ if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) {
+ /* currently unimplemented */
+ raise_exception_err(EXCP06_ILLOP, 0);
+ }
+}
+
#if defined(CONFIG_USER_ONLY)
void helper_wrmsr(void)
{
@@ -4250,7 +4262,8 @@
uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
uint16_t port = (uint16_t) (param >> 16);
- if(ldub_phys(addr + port / 8) & (1 << (port % 8)))
+ uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
+ if(lduw_phys(addr + port / 8) & (mask << (port & 7)))
vmexit(type, param);
}
break;
Modified: trunk/src/host/qemu-neo1973/target-i386/helper2.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper2.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-i386/helper2.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -99,6 +99,7 @@
if (!env)
return NULL;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
/* init various static tables */
if (!inited) {
@@ -255,7 +256,7 @@
}
x86_cpu_def->stepping = stepping;
} else {
- fprintf(stderr, "unregnized feature %s\n", featurestr);
+ fprintf(stderr, "unrecognized feature %s\n", featurestr);
x86_cpu_def = 0;
goto error;
}
Modified: trunk/src/host/qemu-neo1973/target-i386/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/op.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-i386/op.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -953,6 +953,11 @@
helper_rdtsc();
}
+void OPPROTO op_rdpmc(void)
+{
+ helper_rdpmc();
+}
+
void OPPROTO op_cpuid(void)
{
helper_cpuid();
Modified: trunk/src/host/qemu-neo1973/target-i386/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-i386/translate.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -5658,6 +5658,10 @@
gen_jmp_im(pc_start - s->cs_base);
gen_op_rdtsc();
break;
+ case 0x133: /* rdpmc */
+ gen_jmp_im(pc_start - s->cs_base);
+ gen_op_rdpmc();
+ break;
case 0x134: /* sysenter */
if (CODE64(s))
goto illegal_op;
Modified: trunk/src/host/qemu-neo1973/target-m68k/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/helper.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-m68k/helper.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -126,11 +126,13 @@
return NULL;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
+
if (cpu_m68k_set_model(env, cpu_model) < 0) {
cpu_m68k_close(env);
return NULL;
}
-
+
cpu_reset(env);
return env;
}
Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -6786,6 +6786,7 @@
env->cpu_model = def;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
cpu_reset(env);
return env;
}
Modified: trunk/src/host/qemu-neo1973/target-ppc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/cpu.h 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-ppc/cpu.h 2007-12-10 17:51:36 UTC (rev 3627)
@@ -28,7 +28,6 @@
#if defined (TARGET_PPC64)
/* PowerPC 64 definitions */
typedef uint64_t ppc_gpr_t;
-#define TARGET_GPR_BITS 64
#define TARGET_LONG_BITS 64
#define TARGET_PAGE_BITS 12
@@ -41,10 +40,8 @@
* the compiler to do unuseful masking in the micro-ops.
*/
typedef uint64_t ppc_gpr_t;
-#define TARGET_GPR_BITS 64
#else /* (HOST_LONG_BITS >= 64) */
typedef uint32_t ppc_gpr_t;
-#define TARGET_GPR_BITS 32
#endif /* (HOST_LONG_BITS >= 64) */
#define TARGET_LONG_BITS 32
@@ -1235,7 +1232,7 @@
#define SPR_40x_EVPR (0x3D6)
#define SPR_L3PM (0x3D7)
#define SPR_403_CDBCR (0x3D7)
-#define SPR_L3OHCR (0x3D8)
+#define SPR_L3ITCR0 (0x3D8)
#define SPR_TCR (0x3D8)
#define SPR_40x_TSR (0x3D8)
#define SPR_IBR (0x3DA)
@@ -1248,7 +1245,7 @@
#define SPR_40x_SRR2 (0x3DE)
#define SPR_SER (0x3DF)
#define SPR_40x_SRR3 (0x3DF)
-#define SPR_L3ITCR0 (0x3E8)
+#define SPR_L3OHCR (0x3E8)
#define SPR_L3ITCR1 (0x3E9)
#define SPR_L3ITCR2 (0x3EA)
#define SPR_L3ITCR3 (0x3EB)
@@ -1277,6 +1274,7 @@
#define SPR_MSSCR0 (0x3F6)
#define SPR_970_HID5 (0x3F6)
#define SPR_MSSSR0 (0x3F7)
+#define SPR_MSSCR1 (0x3F7)
#define SPR_DABRX (0x3F7)
#define SPR_40x_DAC2 (0x3F7)
#define SPR_MMUCFG (0x3F7)
Modified: trunk/src/host/qemu-neo1973/target-ppc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -2976,6 +2976,7 @@
if (!env)
return NULL;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
cpu_ppc_register_internal(env, def);
cpu_ppc_reset(env);
return env;
Modified: trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate_init.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate_init.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -1149,11 +1149,6 @@
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UBAMR, "UBAMR",
- &spr_read_ureg, SPR_NOACCESS,
- &spr_read_ureg, SPR_NOACCESS,
- 0x00000000);
- /* XXX : not implemented */
spr_register(env, SPR_MSSCR0, "MSSCR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@@ -1195,30 +1190,6 @@
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* L3ITCR1 */
- /* XXX : not implemented */
- spr_register(env, SPR_L3ITCR1, "L3ITCR1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* L3ITCR2 */
- /* XXX : not implemented */
- spr_register(env, SPR_L3ITCR2, "L3ITCR2",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* L3ITCR3 */
- /* XXX : not implemented */
- spr_register(env, SPR_L3ITCR3, "L3ITCR3",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* L3OHCR */
- /* XXX : not implemented */
- spr_register(env, SPR_L3OHCR, "L3OHCR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
/* L3PM */
/* XXX : not implemented */
spr_register(env, SPR_L3PM, "L3PM",
@@ -3052,6 +3023,14 @@
return 0;
}
+static int check_pow_hid0_74xx (CPUPPCState *env)
+{
+ if (env->spr[SPR_HID0] & 0x00600000)
+ return 1;
+
+ return 0;
+}
+
/*****************************************************************************/
/* PowerPC implementations definitions */
@@ -4829,6 +4808,7 @@
ppc6xx_irq_init(env);
}
+/* PowerPC 750CX */
#define POWERPC_INSNS_750cx (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | \
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | \
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX | \
@@ -4876,9 +4856,8 @@
0x00000000);
/* Memory management */
gen_low_BATs(env);
- /* XXX: high BATs are also present but are known to be bugged on
- * die version 1.x
- */
+ /* PowerPC 750cx has 8 DBATs and 8 IBATs */
+ gen_high_BATs(env);
init_excp_750cx(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -5147,7 +5126,7 @@
#define POWERPC_FLAG_7400 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7400 check_pow_hid0
+#define check_pow_7400 check_pow_hid0_74xx
static void init_proc_7400 (CPUPPCState *env)
{
@@ -5157,6 +5136,17 @@
gen_tbl(env);
/* 74xx specific SPR */
gen_spr_74xx(env);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UBAMR, "UBAMR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ /* XXX: this seems not implemented on all revisions. */
+ /* XXX : not implemented */
+ spr_register(env, SPR_MSSCR1, "MSSCR1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
/* Thermal management */
gen_spr_thrm(env);
/* Memory management */
@@ -5188,7 +5178,7 @@
#define POWERPC_FLAG_7410 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7410 check_pow_hid0
+#define check_pow_7410 check_pow_hid0_74xx
static void init_proc_7410 (CPUPPCState *env)
{
@@ -5198,6 +5188,11 @@
gen_tbl(env);
/* 74xx specific SPR */
gen_spr_74xx(env);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UBAMR, "UBAMR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
/* Thermal management */
gen_spr_thrm(env);
/* L2PMCR */
@@ -5241,7 +5236,7 @@
#define POWERPC_FLAG_7440 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7440 check_pow_hid0
+#define check_pow_7440 check_pow_hid0_74xx
__attribute__ (( unused ))
static void init_proc_7440 (CPUPPCState *env)
@@ -5252,6 +5247,11 @@
gen_tbl(env);
/* 74xx specific SPR */
gen_spr_74xx(env);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UBAMR, "UBAMR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
/* LDSTCR */
/* XXX : not implemented */
spr_register(env, SPR_LDSTCR, "LDSTCR",
@@ -5321,7 +5321,7 @@
#define POWERPC_FLAG_7450 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7450 check_pow_hid0
+#define check_pow_7450 check_pow_hid0_74xx
__attribute__ (( unused ))
static void init_proc_7450 (CPUPPCState *env)
@@ -5334,6 +5334,35 @@
gen_spr_74xx(env);
/* Level 3 cache control */
gen_l3_ctrl(env);
+ /* L3ITCR1 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR1, "L3ITCR1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3ITCR2 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR2, "L3ITCR2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3ITCR3 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR3, "L3ITCR3",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3OHCR */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3OHCR, "L3OHCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UBAMR, "UBAMR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
/* LDSTCR */
/* XXX : not implemented */
spr_register(env, SPR_LDSTCR, "LDSTCR",
@@ -5403,7 +5432,7 @@
#define POWERPC_FLAG_7445 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7445 check_pow_hid0
+#define check_pow_7445 check_pow_hid0_74xx
__attribute__ (( unused ))
static void init_proc_7445 (CPUPPCState *env)
@@ -5517,7 +5546,7 @@
#define POWERPC_FLAG_7455 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
POWERPC_FLAG_BUS_CLK)
-#define check_pow_7455 check_pow_hid0
+#define check_pow_7455 check_pow_hid0_74xx
__attribute__ (( unused ))
static void init_proc_7455 (CPUPPCState *env)
@@ -5613,6 +5642,146 @@
ppc6xx_irq_init(env);
}
+/* PowerPC 7457 (aka G4) */
+#define POWERPC_INSNS_7457 (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | \
+ PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | \
+ PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | \
+ PPC_FLOAT_STFIWX | \
+ PPC_CACHE | PPC_CACHE_ICBI | \
+ PPC_CACHE_DCBA | PPC_CACHE_DCBZ | \
+ PPC_MEM_SYNC | PPC_MEM_EIEIO | \
+ PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
+ PPC_MEM_TLBIA | PPC_74xx_TLB | \
+ PPC_SEGMENT | PPC_EXTERN | \
+ PPC_ALTIVEC)
+#define POWERPC_MSRM_7457 (0x000000000205FF77ULL)
+#define POWERPC_MMU_7457 (POWERPC_MMU_SOFT_74xx)
+#define POWERPC_EXCP_7457 (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7457 (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7457 (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7457 (POWERPC_FLAG_VRE | POWERPC_FLAG_SE | \
+ POWERPC_FLAG_BE | POWERPC_FLAG_PMM | \
+ POWERPC_FLAG_BUS_CLK)
+#define check_pow_7457 check_pow_hid0_74xx
+
+__attribute__ (( unused ))
+static void init_proc_7457 (CPUPPCState *env)
+{
+ gen_spr_ne_601(env);
+ gen_spr_7xx(env);
+ /* Time base */
+ gen_tbl(env);
+ /* 74xx specific SPR */
+ gen_spr_74xx(env);
+ /* Level 3 cache control */
+ gen_l3_ctrl(env);
+ /* L3ITCR1 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR1, "L3ITCR1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3ITCR2 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR2, "L3ITCR2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3ITCR3 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3ITCR3, "L3ITCR3",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* L3OHCR */
+ /* XXX : not implemented */
+ spr_register(env, SPR_L3OHCR, "L3OHCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* LDSTCR */
+ /* XXX : not implemented */
+ spr_register(env, SPR_LDSTCR, "LDSTCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* ICTRL */
+ /* XXX : not implemented */
+ spr_register(env, SPR_ICTRL, "ICTRL",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* MSSSR0 */
+ /* XXX : not implemented */
+ spr_register(env, SPR_MSSSR0, "MSSSR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* PMC */
+ /* XXX : not implemented */
+ spr_register(env, SPR_PMC5, "PMC5",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UPMC5, "UPMC5",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_PMC6, "PMC6",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_UPMC6, "UPMC6",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ /* SPRGs */
+ spr_register(env, SPR_SPRG4, "SPRG4",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_USPRG4, "USPRG4",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ spr_register(env, SPR_SPRG5, "SPRG5",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_USPRG5, "USPRG5",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ spr_register(env, SPR_SPRG6, "SPRG6",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_USPRG6, "USPRG6",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ spr_register(env, SPR_SPRG7, "SPRG7",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_USPRG7, "USPRG7",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+ /* Memory management */
+ gen_low_BATs(env);
+ gen_high_BATs(env);
+ gen_74xx_soft_tlb(env, 128, 2);
+ init_excp_7450(env);
+ env->dcache_line_size = 32;
+ env->icache_line_size = 32;
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
+}
+
#if defined (TARGET_PPC64)
/* PowerPC 970 */
#define POWERPC_INSNS_970 (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | \
@@ -6651,6 +6820,7 @@
CPU_POWERPC_7400_v10 = 0x000C0100,
CPU_POWERPC_7400_v11 = 0x000C0101,
CPU_POWERPC_7400_v20 = 0x000C0200,
+ CPU_POWERPC_7400_v21 = 0x000C0201,
CPU_POWERPC_7400_v22 = 0x000C0202,
CPU_POWERPC_7400_v26 = 0x000C0206,
CPU_POWERPC_7400_v27 = 0x000C0207,
@@ -6671,10 +6841,12 @@
CPU_POWERPC_7450_v10 = 0x80000100,
CPU_POWERPC_7450_v11 = 0x80000101,
CPU_POWERPC_7450_v12 = 0x80000102,
- CPU_POWERPC_7450_v20 = 0x80000200, /* aka D: 2.04 */
+ CPU_POWERPC_7450_v20 = 0x80000200, /* aka A, B, C, D: 2.04 */
CPU_POWERPC_7450_v21 = 0x80000201, /* aka E */
- CPU_POWERPC_74x1 = 0x80000203,
- CPU_POWERPC_74x1G = 0x80000210, /* aka G: 2.3 */
+#define CPU_POWERPC_74x1 CPU_POWERPC_74x1_v23
+ CPU_POWERPC_74x1_v23 = 0x80000203, /* aka G: 2.3 */
+ /* XXX: this entry might be a bug in some documentation */
+ CPU_POWERPC_74x1_v210 = 0x80000210, /* aka G: 2.3 ? */
#define CPU_POWERPC_74x5 CPU_POWERPC_74x5_v32
CPU_POWERPC_74x5_v10 = 0x80010100,
/* XXX: missing 0x80010200 */
@@ -8300,6 +8472,8 @@
POWERPC_DEF("7400_v1.1", CPU_POWERPC_7400_v11, 7400),
/* PowerPC 7400 v2.0 (G4) */
POWERPC_DEF("7400_v2.0", CPU_POWERPC_7400_v20, 7400),
+ /* PowerPC 7400 v2.1 (G4) */
+ POWERPC_DEF("7400_v2.1", CPU_POWERPC_7400_v21, 7400),
/* PowerPC 7400 v2.2 (G4) */
POWERPC_DEF("7400_v2.2", CPU_POWERPC_7400_v22, 7400),
/* PowerPC 7400 v2.6 (G4) */
@@ -8352,10 +8526,16 @@
POWERPC_DEF("7441", CPU_POWERPC_74x1, 7440),
/* PowerPC 7451 (G4) */
POWERPC_DEF("7451", CPU_POWERPC_74x1, 7450),
- /* PowerPC 7441g (G4) */
- POWERPC_DEF("7441g", CPU_POWERPC_74x1G, 7440),
- /* PowerPC 7451g (G4) */
- POWERPC_DEF("7451g", CPU_POWERPC_74x1G, 7450),
+ /* PowerPC 7441 v2.1 (G4) */
+ POWERPC_DEF("7441_v2.1", CPU_POWERPC_7450_v21, 7440),
+ /* PowerPC 7441 v2.3 (G4) */
+ POWERPC_DEF("7441_v2.3", CPU_POWERPC_74x1_v23, 7440),
+ /* PowerPC 7451 v2.3 (G4) */
+ POWERPC_DEF("7451_v2.3", CPU_POWERPC_74x1_v23, 7450),
+ /* PowerPC 7441 v2.10 (G4) */
+ POWERPC_DEF("7441_v2.10", CPU_POWERPC_74x1_v210, 7440),
+ /* PowerPC 7451 v2.10 (G4) */
+ POWERPC_DEF("7451_v2.10", CPU_POWERPC_74x1_v210, 7450),
/* PowerPC 7445 (G4) */
POWERPC_DEF("7445", CPU_POWERPC_74x5, 7445),
/* PowerPC 7455 (G4) */
@@ -8396,8 +8576,6 @@
POWERPC_DEF("7447_v1.1", CPU_POWERPC_74x7_v11, 7445),
/* PowerPC 7457 v1.1 (G4) */
POWERPC_DEF("7457_v1.1", CPU_POWERPC_74x7_v11, 7455),
- /* PowerPC 7447 v1.2 (G4) */
- POWERPC_DEF("7447_v1.2", CPU_POWERPC_74x7_v12, 7445),
/* PowerPC 7457 v1.2 (G4) */
POWERPC_DEF("7457_v1.2", CPU_POWERPC_74x7_v12, 7455),
/* PowerPC 7447A (G4) */
Modified: trunk/src/host/qemu-neo1973/target-sparc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/translate.c 2007-12-10 17:40:35 UTC (rev 3626)
+++ trunk/src/host/qemu-neo1973/target-sparc/translate.c 2007-12-10 17:51:36 UTC (rev 3627)
@@ -3792,6 +3792,7 @@
if (!env)
return NULL;
cpu_exec_init(env);
+ env->cpu_model_str = cpu_model;
env->version = def->iu_version;
env->fsr = def->fpu_version;
#if !defined(TARGET_SPARC64)
More information about the commitlog
mailing list