]> git.proxmox.com Git - qemu.git/commitdiff
hw: move block devices to hw/block/, configure via default-configs/
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 5 Feb 2013 11:55:04 +0000 (12:55 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 8 Apr 2013 16:13:13 +0000 (18:13 +0200)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15 files changed:
default-configs/arm-softmmu.mak
default-configs/i386-softmmu.mak
default-configs/sh4-softmmu.mak
default-configs/sh4eb-softmmu.mak
default-configs/x86_64-softmmu.mak
hw/arm/Makefile.objs
hw/block/Makefile.objs
hw/block/onenand.c [new file with mode: 0644]
hw/block/pc_sysfw.c [new file with mode: 0644]
hw/block/tc58128.c [new file with mode: 0644]
hw/i386/Makefile.objs
hw/onenand.c [deleted file]
hw/pc_sysfw.c [deleted file]
hw/sh4/Makefile.objs
hw/tc58128.c [deleted file]

index cd353bd1fc23eea6a22d82be4a284ceacf83da12..7717ea66725c995314f760830dc8481ca8743483 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_PL310=y
 CONFIG_PL330=y
 CONFIG_CADENCE=y
 CONFIG_XGMAC=y
+CONFIG_ONENAND=y
 
 CONFIG_VERSATILE_PCI=y
 CONFIG_VERSATILE_I2C=y
index 2ddf670030c2e12624eceaecbd3bb9fc3d19bfd5..4f0b3f346f0f9dd6d78c2c8cf712f4051d69ecd0 100644 (file)
@@ -31,3 +31,4 @@ CONFIG_TPM_PASSTHROUGH=y
 CONFIG_PCI_HOTPLUG=y
 CONFIG_MC146818RTC=y
 CONFIG_WDT_IB700=y
+CONFIG_PC_SYSFW=y
index bcafc27ff83eeec535227259e1a31cf6ee616465..20a05f9f35c396e347573acebf312ccf18a9a87b 100644 (file)
@@ -6,4 +6,5 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_ISA_MMIO=y
+CONFIG_SH4=y
 CONFIG_IDE_MMIO=y
index 8372b0d0660f6d557d166baf551987e84216133a..875e7e62c2e329ad325bb76c2cfc652353feee8c 100644 (file)
@@ -6,4 +6,5 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_ISA_MMIO=y
+CONFIG_SH4=y
 CONFIG_IDE_MMIO=y
index 72f9bc72afc3d266c70aa95b59d10bffccbdd79d..6fba70ff7386696e5953558f04476e6d1920a4aa 100644 (file)
@@ -31,3 +31,4 @@ CONFIG_TPM_PASSTHROUGH=y
 CONFIG_PCI_HOTPLUG=y
 CONFIG_MC146818RTC=y
 CONFIG_WDT_IB700=y
+CONFIG_PC_SYSFW=y
index b14beb86efb25fc1e0cb0829a4ef8de763b686cc..ede019da02e09623618362b2d7bcc050379c514b 100644 (file)
@@ -17,7 +17,7 @@ obj-y += omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
 obj-y += omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
                 omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 obj-y += tsc210x.o
-obj-y += blizzard.o onenand.o cbus.o tusb6010.o
+obj-y += blizzard.o cbus.o tusb6010.o
 obj-y += mst_fpga.o
 obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 obj-y += framebuffer.o
index 856915eb6a37f99d24056dd1d78be83b1dbeb3c9..e4329a08a9b8bd68b2d8ef29bb11205edaf554c7 100644 (file)
@@ -6,6 +6,10 @@ common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
 common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
 common-obj-$(CONFIG_XEN_BACKEND) += xen_disk.o
 common-obj-$(CONFIG_ECC) += ecc.o
+common-obj-$(CONFIG_ONENAND) += onenand.o
+common-obj-$(CONFIG_PC_SYSFW) += pc_sysfw.o
+
+obj-$(CONFIG_SH4) += tc58128.o
 
 obj-$(CONFIG_VIRTIO) += virtio-blk.o
 obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += dataplane/
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
new file mode 100644 (file)
index 0000000..8b511a7
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ * OneNAND flash memories emulation.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu-common.h"
+#include "hw/hw.h"
+#include "hw/block/flash.h"
+#include "hw/irq.h"
+#include "sysemu/blockdev.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "qemu/error-report.h"
+
+/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
+#define PAGE_SHIFT     11
+
+/* Fixed */
+#define BLOCK_SHIFT    (PAGE_SHIFT + 6)
+
+typedef struct {
+    SysBusDevice busdev;
+    struct {
+        uint16_t man;
+        uint16_t dev;
+        uint16_t ver;
+    } id;
+    int shift;
+    hwaddr base;
+    qemu_irq intr;
+    qemu_irq rdy;
+    BlockDriverState *bdrv;
+    BlockDriverState *bdrv_cur;
+    uint8_t *image;
+    uint8_t *otp;
+    uint8_t *current;
+    MemoryRegion ram;
+    MemoryRegion mapped_ram;
+    uint8_t current_direction;
+    uint8_t *boot[2];
+    uint8_t *data[2][2];
+    MemoryRegion iomem;
+    MemoryRegion container;
+    int cycle;
+    int otpmode;
+
+    uint16_t addr[8];
+    uint16_t unladdr[8];
+    int bufaddr;
+    int count;
+    uint16_t command;
+    uint16_t config[2];
+    uint16_t status;
+    uint16_t intstatus;
+    uint16_t wpstatus;
+
+    ECCState ecc;
+
+    int density_mask;
+    int secs;
+    int secs_cur;
+    int blocks;
+    uint8_t *blockwp;
+} OneNANDState;
+
+enum {
+    ONEN_BUF_BLOCK = 0,
+    ONEN_BUF_BLOCK2 = 1,
+    ONEN_BUF_DEST_BLOCK = 2,
+    ONEN_BUF_DEST_PAGE = 3,
+    ONEN_BUF_PAGE = 7,
+};
+
+enum {
+    ONEN_ERR_CMD = 1 << 10,
+    ONEN_ERR_ERASE = 1 << 11,
+    ONEN_ERR_PROG = 1 << 12,
+    ONEN_ERR_LOAD = 1 << 13,
+};
+
+enum {
+    ONEN_INT_RESET = 1 << 4,
+    ONEN_INT_ERASE = 1 << 5,
+    ONEN_INT_PROG = 1 << 6,
+    ONEN_INT_LOAD = 1 << 7,
+    ONEN_INT = 1 << 15,
+};
+
+enum {
+    ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
+    ONEN_LOCK_LOCKED = 1 << 1,
+    ONEN_LOCK_UNLOCKED = 1 << 2,
+};
+
+static void onenand_mem_setup(OneNANDState *s)
+{
+    /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
+     * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
+     * write boot commands.  Also take note of the BWPS bit.  */
+    memory_region_init(&s->container, "onenand", 0x10000 << s->shift);
+    memory_region_add_subregion(&s->container, 0, &s->iomem);
+    memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram",
+                             &s->ram, 0x0200 << s->shift,
+                             0xbe00 << s->shift);
+    memory_region_add_subregion_overlap(&s->container,
+                                        0x0200 << s->shift,
+                                        &s->mapped_ram,
+                                        1);
+}
+
+static void onenand_intr_update(OneNANDState *s)
+{
+    qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
+}
+
+static void onenand_pre_save(void *opaque)
+{
+    OneNANDState *s = opaque;
+    if (s->current == s->otp) {
+        s->current_direction = 1;
+    } else if (s->current == s->image) {
+        s->current_direction = 2;
+    } else {
+        s->current_direction = 0;
+    }
+}
+
+static int onenand_post_load(void *opaque, int version_id)
+{
+    OneNANDState *s = opaque;
+    switch (s->current_direction) {
+    case 0:
+        break;
+    case 1:
+        s->current = s->otp;
+        break;
+    case 2:
+        s->current = s->image;
+        break;
+    default:
+        return -1;
+    }
+    onenand_intr_update(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_onenand = {
+    .name = "onenand",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = onenand_pre_save,
+    .post_load = onenand_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(current_direction, OneNANDState),
+        VMSTATE_INT32(cycle, OneNANDState),
+        VMSTATE_INT32(otpmode, OneNANDState),
+        VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
+        VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
+        VMSTATE_INT32(bufaddr, OneNANDState),
+        VMSTATE_INT32(count, OneNANDState),
+        VMSTATE_UINT16(command, OneNANDState),
+        VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
+        VMSTATE_UINT16(status, OneNANDState),
+        VMSTATE_UINT16(intstatus, OneNANDState),
+        VMSTATE_UINT16(wpstatus, OneNANDState),
+        VMSTATE_INT32(secs_cur, OneNANDState),
+        VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
+        VMSTATE_UINT8(ecc.cp, OneNANDState),
+        VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
+        VMSTATE_UINT16(ecc.count, OneNANDState),
+        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
+            ((64 + 2) << PAGE_SHIFT)),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
+static void onenand_reset(OneNANDState *s, int cold)
+{
+    memset(&s->addr, 0, sizeof(s->addr));
+    s->command = 0;
+    s->count = 1;
+    s->bufaddr = 0;
+    s->config[0] = 0x40c0;
+    s->config[1] = 0x0000;
+    onenand_intr_update(s);
+    qemu_irq_raise(s->rdy);
+    s->status = 0x0000;
+    s->intstatus = cold ? 0x8080 : 0x8010;
+    s->unladdr[0] = 0;
+    s->unladdr[1] = 0;
+    s->wpstatus = 0x0002;
+    s->cycle = 0;
+    s->otpmode = 0;
+    s->bdrv_cur = s->bdrv;
+    s->current = s->image;
+    s->secs_cur = s->secs;
+
+    if (cold) {
+        /* Lock the whole flash */
+        memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
+
+        if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
+            hw_error("%s: Loading the BootRAM failed.\n", __func__);
+        }
+    }
+}
+
+static void onenand_system_reset(DeviceState *dev)
+{
+    onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
+}
+
+static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
+                void *dest)
+{
+    if (s->bdrv_cur)
+        return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
+    else if (sec + secn > s->secs_cur)
+        return 1;
+
+    memcpy(dest, s->current + (sec << 9), secn << 9);
+
+    return 0;
+}
+
+static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
+                void *src)
+{
+    int result = 0;
+
+    if (secn > 0) {
+        uint32_t size = (uint32_t)secn * 512;
+        const uint8_t *sp = (const uint8_t *)src;
+        uint8_t *dp = 0;
+        if (s->bdrv_cur) {
+            dp = g_malloc(size);
+            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
+                result = 1;
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dp = (uint8_t *)s->current + (sec << 9);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < size; i++) {
+                dp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
+            }
+        }
+        if (dp && s->bdrv_cur) {
+            g_free(dp);
+        }
+    }
+
+    return result;
+}
+
+static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
+                void *dest)
+{
+    uint8_t buf[512];
+
+    if (s->bdrv_cur) {
+        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
+            return 1;
+        memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
+    } else if (sec + secn > s->secs_cur)
+        return 1;
+    else
+        memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
+    return 0;
+}
+
+static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
+                void *src)
+{
+    int result = 0;
+    if (secn > 0) {
+        const uint8_t *sp = (const uint8_t *)src;
+        uint8_t *dp = 0, *dpp = 0;
+        if (s->bdrv_cur) {
+            dp = g_malloc(512);
+            if (!dp || bdrv_read(s->bdrv_cur,
+                                 s->secs_cur + (sec >> 5),
+                                 dp, 1) < 0) {
+                result = 1;
+            } else {
+                dpp = dp + ((sec & 31) << 4);
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < (secn << 4); i++) {
+                dpp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
+                                    dp, 1) < 0;
+            }
+        }
+        if (dp) {
+            g_free(dp);
+        }
+    }
+    return result;
+}
+
+static inline int onenand_erase(OneNANDState *s, int sec, int num)
+{
+    uint8_t *blankbuf, *tmpbuf;
+    blankbuf = g_malloc(512);
+    if (!blankbuf) {
+        return 1;
+    }
+    tmpbuf = g_malloc(512);
+    if (!tmpbuf) {
+        g_free(blankbuf);
+        return 1;
+    }
+    memset(blankbuf, 0xff, 512);
+    for (; num > 0; num--, sec++) {
+        if (s->bdrv_cur) {
+            int erasesec = s->secs_cur + (sec >> 5);
+            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
+                goto fail;
+            }
+            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
+            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+        } else {
+            if (sec + 1 > s->secs_cur) {
+                goto fail;
+            }
+            memcpy(s->current + (sec << 9), blankbuf, 512);
+            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
+                   blankbuf, 1 << 4);
+        }
+    }
+
+    g_free(tmpbuf);
+    g_free(blankbuf);
+    return 0;
+
+fail:
+    g_free(tmpbuf);
+    g_free(blankbuf);
+    return 1;
+}
+
+static void onenand_command(OneNANDState *s)
+{
+    int b;
+    int sec;
+    void *buf;
+#define SETADDR(block, page)                   \
+    sec = (s->addr[page] & 3) +                        \
+            ((((s->addr[page] >> 2) & 0x3f) +  \
+              (((s->addr[block] & 0xfff) |     \
+                (s->addr[block] >> 15 ?                \
+                 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
+#define SETBUF_M()                             \
+    buf = (s->bufaddr & 8) ?                   \
+            s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];    \
+    buf += (s->bufaddr & 3) << 9;
+#define SETBUF_S()                             \
+    buf = (s->bufaddr & 8) ?                   \
+            s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];    \
+    buf += (s->bufaddr & 3) << 4;
+
+    switch (s->command) {
+    case 0x00: /* Load single/multiple sector data unit into buffer */
+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+
+        SETBUF_M()
+        if (onenand_load_main(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
+
+#if 0
+        SETBUF_S()
+        if (onenand_load_spare(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
+#endif
+
+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
+         * then we need two split the read/write into two chunks.
+         */
+        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
+        break;
+    case 0x13: /* Load single/multiple spare sector into buffer */
+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+
+        SETBUF_S()
+        if (onenand_load_spare(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
+
+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
+         * then we need two split the read/write into two chunks.
+         */
+        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
+        break;
+    case 0x80: /* Program single/multiple sector data unit from buffer */
+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+
+        SETBUF_M()
+        if (onenand_prog_main(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
+
+#if 0
+        SETBUF_S()
+        if (onenand_prog_spare(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
+#endif
+
+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
+         * then we need two split the read/write into two chunks.
+         */
+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
+        break;
+    case 0x1a: /* Program single/multiple spare area sector from buffer */
+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+
+        SETBUF_S()
+        if (onenand_prog_spare(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
+
+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
+         * then we need two split the read/write into two chunks.
+         */
+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
+        break;
+    case 0x1b: /* Copy-back program */
+        SETBUF_S()
+
+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+        if (onenand_load_main(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
+
+        SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
+        if (onenand_prog_main(s, sec, s->count, buf))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
+
+        /* TODO: spare areas */
+
+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
+        break;
+
+    case 0x23: /* Unlock NAND array block(s) */
+        s->intstatus |= ONEN_INT;
+
+        /* XXX the previous (?) area should be locked automatically */
+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
+            if (b >= s->blocks) {
+                s->status |= ONEN_ERR_CMD;
+                break;
+            }
+            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
+                break;
+
+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
+        }
+        break;
+    case 0x27: /* Unlock All NAND array blocks */
+        s->intstatus |= ONEN_INT;
+
+        for (b = 0; b < s->blocks; b ++) {
+            if (b >= s->blocks) {
+                s->status |= ONEN_ERR_CMD;
+                break;
+            }
+            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
+                break;
+
+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
+        }
+        break;
+
+    case 0x2a: /* Lock NAND array block(s) */
+        s->intstatus |= ONEN_INT;
+
+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
+            if (b >= s->blocks) {
+                s->status |= ONEN_ERR_CMD;
+                break;
+            }
+            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
+                break;
+
+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
+        }
+        break;
+    case 0x2c: /* Lock-tight NAND array block(s) */
+        s->intstatus |= ONEN_INT;
+
+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
+            if (b >= s->blocks) {
+                s->status |= ONEN_ERR_CMD;
+                break;
+            }
+            if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
+                continue;
+
+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
+        }
+        break;
+
+    case 0x71: /* Erase-Verify-Read */
+        s->intstatus |= ONEN_INT;
+        break;
+    case 0x95: /* Multi-block erase */
+        qemu_irq_pulse(s->intr);
+        /* Fall through.  */
+    case 0x94: /* Block erase */
+        sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
+                        (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
+                << (BLOCK_SHIFT - 9);
+        if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
+            s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
+
+        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
+        break;
+    case 0xb0: /* Erase suspend */
+        break;
+    case 0x30: /* Erase resume */
+        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
+        break;
+
+    case 0xf0: /* Reset NAND Flash core */
+        onenand_reset(s, 0);
+        break;
+    case 0xf3: /* Reset OneNAND */
+        onenand_reset(s, 0);
+        break;
+
+    case 0x65: /* OTP Access */
+        s->intstatus |= ONEN_INT;
+        s->bdrv_cur = NULL;
+        s->current = s->otp;
+        s->secs_cur = 1 << (BLOCK_SHIFT - 9);
+        s->addr[ONEN_BUF_BLOCK] = 0;
+        s->otpmode = 1;
+        break;
+
+    default:
+        s->status |= ONEN_ERR_CMD;
+        s->intstatus |= ONEN_INT;
+        fprintf(stderr, "%s: unknown OneNAND command %x\n",
+                        __func__, s->command);
+    }
+
+    onenand_intr_update(s);
+}
+
+static uint64_t onenand_read(void *opaque, hwaddr addr,
+                             unsigned size)
+{
+    OneNANDState *s = (OneNANDState *) opaque;
+    int offset = addr >> s->shift;
+
+    switch (offset) {
+    case 0x0000 ... 0xc000:
+        return lduw_le_p(s->boot[0] + addr);
+
+    case 0xf000:       /* Manufacturer ID */
+        return s->id.man;
+    case 0xf001:       /* Device ID */
+        return s->id.dev;
+    case 0xf002:       /* Version ID */
+        return s->id.ver;
+    /* TODO: get the following values from a real chip!  */
+    case 0xf003:       /* Data Buffer size */
+        return 1 << PAGE_SHIFT;
+    case 0xf004:       /* Boot Buffer size */
+        return 0x200;
+    case 0xf005:       /* Amount of buffers */
+        return 1 | (2 << 8);
+    case 0xf006:       /* Technology */
+        return 0;
+
+    case 0xf100 ... 0xf107:    /* Start addresses */
+        return s->addr[offset - 0xf100];
+
+    case 0xf200:       /* Start buffer */
+        return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
+
+    case 0xf220:       /* Command */
+        return s->command;
+    case 0xf221:       /* System Configuration 1 */
+        return s->config[0] & 0xffe0;
+    case 0xf222:       /* System Configuration 2 */
+        return s->config[1];
+
+    case 0xf240:       /* Controller Status */
+        return s->status;
+    case 0xf241:       /* Interrupt */
+        return s->intstatus;
+    case 0xf24c:       /* Unlock Start Block Address */
+        return s->unladdr[0];
+    case 0xf24d:       /* Unlock End Block Address */
+        return s->unladdr[1];
+    case 0xf24e:       /* Write Protection Status */
+        return s->wpstatus;
+
+    case 0xff00:       /* ECC Status */
+        return 0x00;
+    case 0xff01:       /* ECC Result of main area data */
+    case 0xff02:       /* ECC Result of spare area data */
+    case 0xff03:       /* ECC Result of main area data */
+    case 0xff04:       /* ECC Result of spare area data */
+        hw_error("%s: imeplement ECC\n", __FUNCTION__);
+        return 0x0000;
+    }
+
+    fprintf(stderr, "%s: unknown OneNAND register %x\n",
+                    __FUNCTION__, offset);
+    return 0;
+}
+
+static void onenand_write(void *opaque, hwaddr addr,
+                          uint64_t value, unsigned size)
+{
+    OneNANDState *s = (OneNANDState *) opaque;
+    int offset = addr >> s->shift;
+    int sec;
+
+    switch (offset) {
+    case 0x0000 ... 0x01ff:
+    case 0x8000 ... 0x800f:
+        if (s->cycle) {
+            s->cycle = 0;
+
+            if (value == 0x0000) {
+                SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
+                onenand_load_main(s, sec,
+                                1 << (PAGE_SHIFT - 9), s->data[0][0]);
+                s->addr[ONEN_BUF_PAGE] += 4;
+                s->addr[ONEN_BUF_PAGE] &= 0xff;
+            }
+            break;
+        }
+
+        switch (value) {
+        case 0x00f0:   /* Reset OneNAND */
+            onenand_reset(s, 0);
+            break;
+
+        case 0x00e0:   /* Load Data into Buffer */
+            s->cycle = 1;
+            break;
+
+        case 0x0090:   /* Read Identification Data */
+            memset(s->boot[0], 0, 3 << s->shift);
+            s->boot[0][0 << s->shift] = s->id.man & 0xff;
+            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
+            s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
+            break;
+
+        default:
+            fprintf(stderr, "%s: unknown OneNAND boot command %"PRIx64"\n",
+                            __FUNCTION__, value);
+        }
+        break;
+
+    case 0xf100 ... 0xf107:    /* Start addresses */
+        s->addr[offset - 0xf100] = value;
+        break;
+
+    case 0xf200:       /* Start buffer */
+        s->bufaddr = (value >> 8) & 0xf;
+        if (PAGE_SHIFT == 11)
+            s->count = (value & 3) ?: 4;
+        else if (PAGE_SHIFT == 10)
+            s->count = (value & 1) ?: 2;
+        break;
+
+    case 0xf220:       /* Command */
+        if (s->intstatus & (1 << 15))
+            break;
+        s->command = value;
+        onenand_command(s);
+        break;
+    case 0xf221:       /* System Configuration 1 */
+        s->config[0] = value;
+        onenand_intr_update(s);
+        qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
+        break;
+    case 0xf222:       /* System Configuration 2 */
+        s->config[1] = value;
+        break;
+
+    case 0xf241:       /* Interrupt */
+        s->intstatus &= value;
+        if ((1 << 15) & ~s->intstatus)
+            s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
+                            ONEN_ERR_PROG | ONEN_ERR_LOAD);
+        onenand_intr_update(s);
+        break;
+    case 0xf24c:       /* Unlock Start Block Address */
+        s->unladdr[0] = value & (s->blocks - 1);
+        /* For some reason we have to set the end address to by default
+         * be same as start because the software forgets to write anything
+         * in there.  */
+        s->unladdr[1] = value & (s->blocks - 1);
+        break;
+    case 0xf24d:       /* Unlock End Block Address */
+        s->unladdr[1] = value & (s->blocks - 1);
+        break;
+
+    default:
+        fprintf(stderr, "%s: unknown OneNAND register %x\n",
+                        __FUNCTION__, offset);
+    }
+}
+
+static const MemoryRegionOps onenand_ops = {
+    .read = onenand_read,
+    .write = onenand_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int onenand_initfn(SysBusDevice *dev)
+{
+    OneNANDState *s = (OneNANDState *)dev;
+    uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
+    void *ram;
+    s->base = (hwaddr)-1;
+    s->rdy = NULL;
+    s->blocks = size >> BLOCK_SHIFT;
+    s->secs = size >> 9;
+    s->blockwp = g_malloc(s->blocks);
+    s->density_mask = (s->id.dev & 0x08)
+        ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
+    memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand",
+                          0x10000 << s->shift);
+    if (!s->bdrv) {
+        s->image = memset(g_malloc(size + (size >> 5)),
+                          0xff, size + (size >> 5));
+    } else {
+        if (bdrv_is_read_only(s->bdrv)) {
+            error_report("Can't use a read-only drive");
+            return -1;
+        }
+        s->bdrv_cur = s->bdrv;
+    }
+    s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
+                    0xff, (64 + 2) << PAGE_SHIFT);
+    memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift);
+    vmstate_register_ram_global(&s->ram);
+    ram = memory_region_get_ram_ptr(&s->ram);
+    s->boot[0] = ram + (0x0000 << s->shift);
+    s->boot[1] = ram + (0x8000 << s->shift);
+    s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
+    s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
+    s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
+    s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
+    onenand_mem_setup(s);
+    sysbus_init_irq(dev, &s->intr);
+    sysbus_init_mmio(dev, &s->container);
+    vmstate_register(&dev->qdev,
+                     ((s->shift & 0x7f) << 24)
+                     | ((s->id.man & 0xff) << 16)
+                     | ((s->id.dev & 0xff) << 8)
+                     | (s->id.ver & 0xff),
+                     &vmstate_onenand, s);
+    return 0;
+}
+
+static Property onenand_properties[] = {
+    DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
+    DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
+    DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
+    DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
+    DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void onenand_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = onenand_initfn;
+    dc->reset = onenand_system_reset;
+    dc->props = onenand_properties;
+}
+
+static const TypeInfo onenand_info = {
+    .name          = "onenand",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(OneNANDState),
+    .class_init    = onenand_class_init,
+};
+
+static void onenand_register_types(void)
+{
+    type_register_static(&onenand_info);
+}
+
+void *onenand_raw_otp(DeviceState *onenand_device)
+{
+    return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
+}
+
+type_init(onenand_register_types)
diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c
new file mode 100644 (file)
index 0000000..0d95c8a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * QEMU PC System Firmware
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2011-2012 Intel Corporation
+ *
+ * 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 "sysemu/blockdev.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "sysemu/sysemu.h"
+#include "hw/block/flash.h"
+#include "sysemu/kvm.h"
+
+#define BIOS_FILENAME "bios.bin"
+
+typedef struct PcSysFwDevice {
+    SysBusDevice busdev;
+    uint8_t rom_only;
+} PcSysFwDevice;
+
+static void pc_isa_bios_init(MemoryRegion *rom_memory,
+                             MemoryRegion *flash_mem,
+                             int ram_size)
+{
+    int isa_bios_size;
+    MemoryRegion *isa_bios;
+    uint64_t flash_size;
+    void *flash_ptr, *isa_bios_ptr;
+
+    flash_size = memory_region_size(flash_mem);
+
+    /* map the last 128KB of the BIOS in ISA space */
+    isa_bios_size = flash_size;
+    if (isa_bios_size > (128 * 1024)) {
+        isa_bios_size = 128 * 1024;
+    }
+    isa_bios = g_malloc(sizeof(*isa_bios));
+    memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size);
+    vmstate_register_ram_global(isa_bios);
+    memory_region_add_subregion_overlap(rom_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+
+    /* copy ISA rom image from top of flash memory */
+    flash_ptr = memory_region_get_ram_ptr(flash_mem);
+    isa_bios_ptr = memory_region_get_ram_ptr(isa_bios);
+    memcpy(isa_bios_ptr,
+           ((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
+           isa_bios_size);
+
+    memory_region_set_readonly(isa_bios, true);
+}
+
+static void pc_fw_add_pflash_drv(void)
+{
+    QemuOpts *opts;
+    QEMUMachine *machine;
+    char *filename;
+
+    if (bios_name == NULL) {
+        bios_name = BIOS_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (!filename) {
+        error_report("Can't open BIOS image %s", bios_name);
+        exit(1);
+    }
+
+    opts = drive_add(IF_PFLASH, -1, filename, "readonly=on");
+
+    g_free(filename);
+
+    if (opts == NULL) {
+      return;
+    }
+
+    machine = find_default_machine();
+    if (machine == NULL) {
+      return;
+    }
+
+    if (!drive_init(opts, machine->block_default_type)) {
+        qemu_opts_del(opts);
+    }
+}
+
+static void pc_system_flash_init(MemoryRegion *rom_memory,
+                                 DriveInfo *pflash_drv)
+{
+    BlockDriverState *bdrv;
+    int64_t size;
+    hwaddr phys_addr;
+    int sector_bits, sector_size;
+    pflash_t *system_flash;
+    MemoryRegion *flash_mem;
+
+    bdrv = pflash_drv->bdrv;
+    size = bdrv_getlength(pflash_drv->bdrv);
+    sector_bits = 12;
+    sector_size = 1 << sector_bits;
+
+    if ((size % sector_size) != 0) {
+        fprintf(stderr,
+                "qemu: PC system firmware (pflash) must be a multiple of 0x%x\n",
+                sector_size);
+        exit(1);
+    }
+
+    phys_addr = 0x100000000ULL - size;
+    system_flash = pflash_cfi01_register(phys_addr, NULL, "system.flash", size,
+                                         bdrv, sector_size, size >> sector_bits,
+                                         1, 0x0000, 0x0000, 0x0000, 0x0000, 0);
+    flash_mem = pflash_cfi01_get_memory(system_flash);
+
+    pc_isa_bios_init(rom_memory, flash_mem, size);
+}
+
+static void old_pc_system_rom_init(MemoryRegion *rom_memory)
+{
+    char *filename;
+    MemoryRegion *bios, *isa_bios;
+    int bios_size, isa_bios_size;
+    int ret;
+
+    /* BIOS load */
+    if (bios_name == NULL) {
+        bios_name = BIOS_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = get_image_size(filename);
+    } else {
+        bios_size = -1;
+    }
+    if (bios_size <= 0 ||
+        (bios_size % 65536) != 0) {
+        goto bios_error;
+    }
+    bios = g_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, "pc.bios", bios_size);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
+    if (ret != 0) {
+    bios_error:
+        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
+        exit(1);
+    }
+    if (filename) {
+        g_free(filename);
+    }
+
+    /* map the last 128KB of the BIOS in ISA space */
+    isa_bios_size = bios_size;
+    if (isa_bios_size > (128 * 1024)) {
+        isa_bios_size = 128 * 1024;
+    }
+    isa_bios = g_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(rom_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    /* map all the bios at the top of memory */
+    memory_region_add_subregion(rom_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
+}
+
+void pc_system_firmware_init(MemoryRegion *rom_memory)
+{
+    DriveInfo *pflash_drv;
+    PcSysFwDevice *sysfw_dev;
+
+    sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
+
+    qdev_init_nofail(DEVICE(sysfw_dev));
+
+    if (sysfw_dev->rom_only) {
+        old_pc_system_rom_init(rom_memory);
+        return;
+    }
+
+    pflash_drv = drive_get(IF_PFLASH, 0, 0);
+
+    /* Currently KVM cannot execute from device memory.
+       Use old rom based firmware initialization for KVM. */
+    if (kvm_enabled()) {
+        if (pflash_drv != NULL) {
+            fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n");
+            exit(1);
+        } else {
+            sysfw_dev->rom_only = 1;
+            old_pc_system_rom_init(rom_memory);
+            return;
+        }
+    }
+
+    /* If a pflash drive is not found, then create one using
+       the bios filename. */
+    if (pflash_drv == NULL) {
+        pc_fw_add_pflash_drv();
+        pflash_drv = drive_get(IF_PFLASH, 0, 0);
+    }
+
+    if (pflash_drv != NULL) {
+        pc_system_flash_init(rom_memory, pflash_drv);
+    } else {
+        fprintf(stderr, "qemu: PC system firmware (pflash) not available\n");
+        exit(1);
+    }
+}
+
+static Property pcsysfw_properties[] = {
+    DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int pcsysfw_init(DeviceState *dev)
+{
+    return 0;
+}
+
+static void pcsysfw_class_init (ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS (klass);
+
+    dc->desc = "PC System Firmware";
+    dc->init = pcsysfw_init;
+    dc->props = pcsysfw_properties;
+}
+
+static const TypeInfo pcsysfw_info = {
+    .name          = "pc-sysfw",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof (PcSysFwDevice),
+    .class_init    = pcsysfw_class_init,
+};
+
+static void pcsysfw_register (void)
+{
+    type_register_static (&pcsysfw_info);
+}
+
+type_init (pcsysfw_register);
+
diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c
new file mode 100644 (file)
index 0000000..a3929d4
--- /dev/null
@@ -0,0 +1,178 @@
+#include "hw/hw.h"
+#include "hw/sh4/sh.h"
+#include "hw/loader.h"
+
+#define CE1  0x0100
+#define CE2  0x0200
+#define RE   0x0400
+#define WE   0x0800
+#define ALE  0x1000
+#define CLE  0x2000
+#define RDY1 0x4000
+#define RDY2 0x8000
+#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
+
+typedef enum { WAIT, READ1, READ2, READ3 } state_t;
+
+typedef struct {
+    uint8_t *flash_contents;
+    state_t state;
+    uint32_t address;
+    uint8_t address_cycle;
+} tc58128_dev;
+
+static tc58128_dev tc58128_devs[2];
+
+#define FLASH_SIZE (16*1024*1024)
+
+static void init_dev(tc58128_dev * dev, const char *filename)
+{
+    int ret, blocks;
+
+    dev->state = WAIT;
+    dev->flash_contents = g_malloc(FLASH_SIZE);
+    memset(dev->flash_contents, 0xff, FLASH_SIZE);
+    if (filename) {
+       /* Load flash image skipping the first block */
+       ret = load_image(filename, dev->flash_contents + 528 * 32);
+       if (ret < 0) {
+           fprintf(stderr, "ret=%d\n", ret);
+           fprintf(stderr, "qemu: could not load flash image %s\n",
+                   filename);
+           exit(1);
+       } else {
+           /* Build first block with number of blocks */
+           blocks = (ret + 528 * 32 - 1) / (528 * 32);
+           dev->flash_contents[0] = blocks & 0xff;
+           dev->flash_contents[1] = (blocks >> 8) & 0xff;
+           dev->flash_contents[2] = (blocks >> 16) & 0xff;
+           dev->flash_contents[3] = (blocks >> 24) & 0xff;
+           fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
+                   filename);
+       }
+    }
+}
+
+static void handle_command(tc58128_dev * dev, uint8_t command)
+{
+    switch (command) {
+    case 0xff:
+       fprintf(stderr, "reset flash device\n");
+       dev->state = WAIT;
+       break;
+    case 0x00:
+       fprintf(stderr, "read mode 1\n");
+       dev->state = READ1;
+       dev->address_cycle = 0;
+       break;
+    case 0x01:
+       fprintf(stderr, "read mode 2\n");
+       dev->state = READ2;
+       dev->address_cycle = 0;
+       break;
+    case 0x50:
+       fprintf(stderr, "read mode 3\n");
+       dev->state = READ3;
+       dev->address_cycle = 0;
+       break;
+    default:
+       fprintf(stderr, "unknown flash command 0x%02x\n", command);
+        abort();
+    }
+}
+
+static void handle_address(tc58128_dev * dev, uint8_t data)
+{
+    switch (dev->state) {
+    case READ1:
+    case READ2:
+    case READ3:
+       switch (dev->address_cycle) {
+       case 0:
+           dev->address = data;
+           if (dev->state == READ2)
+               dev->address |= 0x100;
+           else if (dev->state == READ3)
+               dev->address |= 0x200;
+           break;
+       case 1:
+           dev->address += data * 528 * 0x100;
+           break;
+       case 2:
+           dev->address += data * 528;
+           fprintf(stderr, "address pointer in flash: 0x%08x\n",
+                   dev->address);
+           break;
+       default:
+           /* Invalid data */
+            abort();
+       }
+       dev->address_cycle++;
+       break;
+    default:
+        abort();
+    }
+}
+
+static uint8_t handle_read(tc58128_dev * dev)
+{
+#if 0
+    if (dev->address % 0x100000 == 0)
+       fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
+#endif
+    return dev->flash_contents[dev->address++];
+}
+
+/* We never mark the device as busy, so interrupts cannot be triggered
+   XXXXX */
+
+static int tc58128_cb(uint16_t porta, uint16_t portb,
+                      uint16_t * periph_pdtra, uint16_t * periph_portadir,
+                      uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
+{
+    int dev;
+
+    if ((porta & CE1) == 0)
+       dev = 0;
+    else if ((porta & CE2) == 0)
+       dev = 1;
+    else
+       return 0;               /* No device selected */
+
+    if ((porta & RE) && (porta & WE)) {
+       /* Nothing to do, assert ready and return to input state */
+       *periph_portadir &= 0xff00;
+       *periph_portadir |= RDY(dev);
+       *periph_pdtra |= RDY(dev);
+       return 1;
+    }
+
+    if (porta & CLE) {
+       /* Command */
+       assert((porta & WE) == 0);
+       handle_command(&tc58128_devs[dev], porta & 0x00ff);
+    } else if (porta & ALE) {
+       assert((porta & WE) == 0);
+       handle_address(&tc58128_devs[dev], porta & 0x00ff);
+    } else if ((porta & RE) == 0) {
+       *periph_portadir |= 0x00ff;
+       *periph_pdtra &= 0xff00;
+       *periph_pdtra |= handle_read(&tc58128_devs[dev]);
+    } else {
+        abort();
+    }
+    return 1;
+}
+
+static sh7750_io_device tc58128 = {
+    RE | WE,                   /* Port A triggers */
+    0,                         /* Port B triggers */
+    tc58128_cb                 /* Callback */
+};
+
+int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
+{
+    init_dev(&tc58128_devs[0], zone1);
+    init_dev(&tc58128_devs[1], zone2);
+    return sh7750_register_io_device(s, &tc58128);
+}
index 80132d8f40cb3e45757f1a68941f3352524f9461..6df5fd9196baa4e0215849fb70f8ff65b18cb891 100644 (file)
@@ -2,7 +2,6 @@ obj-y += apic_common.o apic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
 obj-y += debugcon.o debugexit.o
-obj-y += pc_sysfw.o
 obj-y += lpc_ich9.o q35.o
 obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
diff --git a/hw/onenand.c b/hw/onenand.c
deleted file mode 100644 (file)
index 8b511a7..0000000
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * OneNAND flash memories emulation.
- *
- * Copyright (C) 2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu-common.h"
-#include "hw/hw.h"
-#include "hw/block/flash.h"
-#include "hw/irq.h"
-#include "sysemu/blockdev.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "hw/sysbus.h"
-#include "qemu/error-report.h"
-
-/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
-#define PAGE_SHIFT     11
-
-/* Fixed */
-#define BLOCK_SHIFT    (PAGE_SHIFT + 6)
-
-typedef struct {
-    SysBusDevice busdev;
-    struct {
-        uint16_t man;
-        uint16_t dev;
-        uint16_t ver;
-    } id;
-    int shift;
-    hwaddr base;
-    qemu_irq intr;
-    qemu_irq rdy;
-    BlockDriverState *bdrv;
-    BlockDriverState *bdrv_cur;
-    uint8_t *image;
-    uint8_t *otp;
-    uint8_t *current;
-    MemoryRegion ram;
-    MemoryRegion mapped_ram;
-    uint8_t current_direction;
-    uint8_t *boot[2];
-    uint8_t *data[2][2];
-    MemoryRegion iomem;
-    MemoryRegion container;
-    int cycle;
-    int otpmode;
-
-    uint16_t addr[8];
-    uint16_t unladdr[8];
-    int bufaddr;
-    int count;
-    uint16_t command;
-    uint16_t config[2];
-    uint16_t status;
-    uint16_t intstatus;
-    uint16_t wpstatus;
-
-    ECCState ecc;
-
-    int density_mask;
-    int secs;
-    int secs_cur;
-    int blocks;
-    uint8_t *blockwp;
-} OneNANDState;
-
-enum {
-    ONEN_BUF_BLOCK = 0,
-    ONEN_BUF_BLOCK2 = 1,
-    ONEN_BUF_DEST_BLOCK = 2,
-    ONEN_BUF_DEST_PAGE = 3,
-    ONEN_BUF_PAGE = 7,
-};
-
-enum {
-    ONEN_ERR_CMD = 1 << 10,
-    ONEN_ERR_ERASE = 1 << 11,
-    ONEN_ERR_PROG = 1 << 12,
-    ONEN_ERR_LOAD = 1 << 13,
-};
-
-enum {
-    ONEN_INT_RESET = 1 << 4,
-    ONEN_INT_ERASE = 1 << 5,
-    ONEN_INT_PROG = 1 << 6,
-    ONEN_INT_LOAD = 1 << 7,
-    ONEN_INT = 1 << 15,
-};
-
-enum {
-    ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
-    ONEN_LOCK_LOCKED = 1 << 1,
-    ONEN_LOCK_UNLOCKED = 1 << 2,
-};
-
-static void onenand_mem_setup(OneNANDState *s)
-{
-    /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
-     * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
-     * write boot commands.  Also take note of the BWPS bit.  */
-    memory_region_init(&s->container, "onenand", 0x10000 << s->shift);
-    memory_region_add_subregion(&s->container, 0, &s->iomem);
-    memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram",
-                             &s->ram, 0x0200 << s->shift,
-                             0xbe00 << s->shift);
-    memory_region_add_subregion_overlap(&s->container,
-                                        0x0200 << s->shift,
-                                        &s->mapped_ram,
-                                        1);
-}
-
-static void onenand_intr_update(OneNANDState *s)
-{
-    qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
-}
-
-static void onenand_pre_save(void *opaque)
-{
-    OneNANDState *s = opaque;
-    if (s->current == s->otp) {
-        s->current_direction = 1;
-    } else if (s->current == s->image) {
-        s->current_direction = 2;
-    } else {
-        s->current_direction = 0;
-    }
-}
-
-static int onenand_post_load(void *opaque, int version_id)
-{
-    OneNANDState *s = opaque;
-    switch (s->current_direction) {
-    case 0:
-        break;
-    case 1:
-        s->current = s->otp;
-        break;
-    case 2:
-        s->current = s->image;
-        break;
-    default:
-        return -1;
-    }
-    onenand_intr_update(s);
-    return 0;
-}
-
-static const VMStateDescription vmstate_onenand = {
-    .name = "onenand",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .pre_save = onenand_pre_save,
-    .post_load = onenand_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT8(current_direction, OneNANDState),
-        VMSTATE_INT32(cycle, OneNANDState),
-        VMSTATE_INT32(otpmode, OneNANDState),
-        VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
-        VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
-        VMSTATE_INT32(bufaddr, OneNANDState),
-        VMSTATE_INT32(count, OneNANDState),
-        VMSTATE_UINT16(command, OneNANDState),
-        VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
-        VMSTATE_UINT16(status, OneNANDState),
-        VMSTATE_UINT16(intstatus, OneNANDState),
-        VMSTATE_UINT16(wpstatus, OneNANDState),
-        VMSTATE_INT32(secs_cur, OneNANDState),
-        VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
-        VMSTATE_UINT8(ecc.cp, OneNANDState),
-        VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
-        VMSTATE_UINT16(ecc.count, OneNANDState),
-        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
-            ((64 + 2) << PAGE_SHIFT)),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
-static void onenand_reset(OneNANDState *s, int cold)
-{
-    memset(&s->addr, 0, sizeof(s->addr));
-    s->command = 0;
-    s->count = 1;
-    s->bufaddr = 0;
-    s->config[0] = 0x40c0;
-    s->config[1] = 0x0000;
-    onenand_intr_update(s);
-    qemu_irq_raise(s->rdy);
-    s->status = 0x0000;
-    s->intstatus = cold ? 0x8080 : 0x8010;
-    s->unladdr[0] = 0;
-    s->unladdr[1] = 0;
-    s->wpstatus = 0x0002;
-    s->cycle = 0;
-    s->otpmode = 0;
-    s->bdrv_cur = s->bdrv;
-    s->current = s->image;
-    s->secs_cur = s->secs;
-
-    if (cold) {
-        /* Lock the whole flash */
-        memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
-
-        if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
-            hw_error("%s: Loading the BootRAM failed.\n", __func__);
-        }
-    }
-}
-
-static void onenand_system_reset(DeviceState *dev)
-{
-    onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
-}
-
-static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
-                void *dest)
-{
-    if (s->bdrv_cur)
-        return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
-    else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(dest, s->current + (sec << 9), secn << 9);
-
-    return 0;
-}
-
-static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
-                void *src)
-{
-    int result = 0;
-
-    if (secn > 0) {
-        uint32_t size = (uint32_t)secn * 512;
-        const uint8_t *sp = (const uint8_t *)src;
-        uint8_t *dp = 0;
-        if (s->bdrv_cur) {
-            dp = g_malloc(size);
-            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
-                result = 1;
-            }
-        } else {
-            if (sec + secn > s->secs_cur) {
-                result = 1;
-            } else {
-                dp = (uint8_t *)s->current + (sec << 9);
-            }
-        }
-        if (!result) {
-            uint32_t i;
-            for (i = 0; i < size; i++) {
-                dp[i] &= sp[i];
-            }
-            if (s->bdrv_cur) {
-                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
-            }
-        }
-        if (dp && s->bdrv_cur) {
-            g_free(dp);
-        }
-    }
-
-    return result;
-}
-
-static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
-                void *dest)
-{
-    uint8_t buf[512];
-
-    if (s->bdrv_cur) {
-        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-            return 1;
-        memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
-    } else if (sec + secn > s->secs_cur)
-        return 1;
-    else
-        memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
-    return 0;
-}
-
-static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
-                void *src)
-{
-    int result = 0;
-    if (secn > 0) {
-        const uint8_t *sp = (const uint8_t *)src;
-        uint8_t *dp = 0, *dpp = 0;
-        if (s->bdrv_cur) {
-            dp = g_malloc(512);
-            if (!dp || bdrv_read(s->bdrv_cur,
-                                 s->secs_cur + (sec >> 5),
-                                 dp, 1) < 0) {
-                result = 1;
-            } else {
-                dpp = dp + ((sec & 31) << 4);
-            }
-        } else {
-            if (sec + secn > s->secs_cur) {
-                result = 1;
-            } else {
-                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
-            }
-        }
-        if (!result) {
-            uint32_t i;
-            for (i = 0; i < (secn << 4); i++) {
-                dpp[i] &= sp[i];
-            }
-            if (s->bdrv_cur) {
-                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
-                                    dp, 1) < 0;
-            }
-        }
-        if (dp) {
-            g_free(dp);
-        }
-    }
-    return result;
-}
-
-static inline int onenand_erase(OneNANDState *s, int sec, int num)
-{
-    uint8_t *blankbuf, *tmpbuf;
-    blankbuf = g_malloc(512);
-    if (!blankbuf) {
-        return 1;
-    }
-    tmpbuf = g_malloc(512);
-    if (!tmpbuf) {
-        g_free(blankbuf);
-        return 1;
-    }
-    memset(blankbuf, 0xff, 512);
-    for (; num > 0; num--, sec++) {
-        if (s->bdrv_cur) {
-            int erasesec = s->secs_cur + (sec >> 5);
-            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
-                goto fail;
-            }
-            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
-                goto fail;
-            }
-            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
-            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
-                goto fail;
-            }
-        } else {
-            if (sec + 1 > s->secs_cur) {
-                goto fail;
-            }
-            memcpy(s->current + (sec << 9), blankbuf, 512);
-            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
-                   blankbuf, 1 << 4);
-        }
-    }
-
-    g_free(tmpbuf);
-    g_free(blankbuf);
-    return 0;
-
-fail:
-    g_free(tmpbuf);
-    g_free(blankbuf);
-    return 1;
-}
-
-static void onenand_command(OneNANDState *s)
-{
-    int b;
-    int sec;
-    void *buf;
-#define SETADDR(block, page)                   \
-    sec = (s->addr[page] & 3) +                        \
-            ((((s->addr[page] >> 2) & 0x3f) +  \
-              (((s->addr[block] & 0xfff) |     \
-                (s->addr[block] >> 15 ?                \
-                 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
-#define SETBUF_M()                             \
-    buf = (s->bufaddr & 8) ?                   \
-            s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];    \
-    buf += (s->bufaddr & 3) << 9;
-#define SETBUF_S()                             \
-    buf = (s->bufaddr & 8) ?                   \
-            s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];    \
-    buf += (s->bufaddr & 3) << 4;
-
-    switch (s->command) {
-    case 0x00: /* Load single/multiple sector data unit into buffer */
-        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-
-        SETBUF_M()
-        if (onenand_load_main(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-
-#if 0
-        SETBUF_S()
-        if (onenand_load_spare(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-#endif
-
-        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-         * then we need two split the read/write into two chunks.
-         */
-        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
-        break;
-    case 0x13: /* Load single/multiple spare sector into buffer */
-        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-
-        SETBUF_S()
-        if (onenand_load_spare(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-
-        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-         * then we need two split the read/write into two chunks.
-         */
-        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
-        break;
-    case 0x80: /* Program single/multiple sector data unit from buffer */
-        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-
-        SETBUF_M()
-        if (onenand_prog_main(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-
-#if 0
-        SETBUF_S()
-        if (onenand_prog_spare(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-#endif
-
-        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-         * then we need two split the read/write into two chunks.
-         */
-        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-        break;
-    case 0x1a: /* Program single/multiple spare area sector from buffer */
-        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-
-        SETBUF_S()
-        if (onenand_prog_spare(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-
-        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-         * then we need two split the read/write into two chunks.
-         */
-        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-        break;
-    case 0x1b: /* Copy-back program */
-        SETBUF_S()
-
-        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-        if (onenand_load_main(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-
-        SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
-        if (onenand_prog_main(s, sec, s->count, buf))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-
-        /* TODO: spare areas */
-
-        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-        break;
-
-    case 0x23: /* Unlock NAND array block(s) */
-        s->intstatus |= ONEN_INT;
-
-        /* XXX the previous (?) area should be locked automatically */
-        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-            if (b >= s->blocks) {
-                s->status |= ONEN_ERR_CMD;
-                break;
-            }
-            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
-                break;
-
-            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
-        }
-        break;
-    case 0x27: /* Unlock All NAND array blocks */
-        s->intstatus |= ONEN_INT;
-
-        for (b = 0; b < s->blocks; b ++) {
-            if (b >= s->blocks) {
-                s->status |= ONEN_ERR_CMD;
-                break;
-            }
-            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
-                break;
-
-            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
-        }
-        break;
-
-    case 0x2a: /* Lock NAND array block(s) */
-        s->intstatus |= ONEN_INT;
-
-        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-            if (b >= s->blocks) {
-                s->status |= ONEN_ERR_CMD;
-                break;
-            }
-            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
-                break;
-
-            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
-        }
-        break;
-    case 0x2c: /* Lock-tight NAND array block(s) */
-        s->intstatus |= ONEN_INT;
-
-        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-            if (b >= s->blocks) {
-                s->status |= ONEN_ERR_CMD;
-                break;
-            }
-            if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
-                continue;
-
-            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
-        }
-        break;
-
-    case 0x71: /* Erase-Verify-Read */
-        s->intstatus |= ONEN_INT;
-        break;
-    case 0x95: /* Multi-block erase */
-        qemu_irq_pulse(s->intr);
-        /* Fall through.  */
-    case 0x94: /* Block erase */
-        sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
-                        (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
-                << (BLOCK_SHIFT - 9);
-        if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
-            s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
-
-        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
-        break;
-    case 0xb0: /* Erase suspend */
-        break;
-    case 0x30: /* Erase resume */
-        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
-        break;
-
-    case 0xf0: /* Reset NAND Flash core */
-        onenand_reset(s, 0);
-        break;
-    case 0xf3: /* Reset OneNAND */
-        onenand_reset(s, 0);
-        break;
-
-    case 0x65: /* OTP Access */
-        s->intstatus |= ONEN_INT;
-        s->bdrv_cur = NULL;
-        s->current = s->otp;
-        s->secs_cur = 1 << (BLOCK_SHIFT - 9);
-        s->addr[ONEN_BUF_BLOCK] = 0;
-        s->otpmode = 1;
-        break;
-
-    default:
-        s->status |= ONEN_ERR_CMD;
-        s->intstatus |= ONEN_INT;
-        fprintf(stderr, "%s: unknown OneNAND command %x\n",
-                        __func__, s->command);
-    }
-
-    onenand_intr_update(s);
-}
-
-static uint64_t onenand_read(void *opaque, hwaddr addr,
-                             unsigned size)
-{
-    OneNANDState *s = (OneNANDState *) opaque;
-    int offset = addr >> s->shift;
-
-    switch (offset) {
-    case 0x0000 ... 0xc000:
-        return lduw_le_p(s->boot[0] + addr);
-
-    case 0xf000:       /* Manufacturer ID */
-        return s->id.man;
-    case 0xf001:       /* Device ID */
-        return s->id.dev;
-    case 0xf002:       /* Version ID */
-        return s->id.ver;
-    /* TODO: get the following values from a real chip!  */
-    case 0xf003:       /* Data Buffer size */
-        return 1 << PAGE_SHIFT;
-    case 0xf004:       /* Boot Buffer size */
-        return 0x200;
-    case 0xf005:       /* Amount of buffers */
-        return 1 | (2 << 8);
-    case 0xf006:       /* Technology */
-        return 0;
-
-    case 0xf100 ... 0xf107:    /* Start addresses */
-        return s->addr[offset - 0xf100];
-
-    case 0xf200:       /* Start buffer */
-        return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
-
-    case 0xf220:       /* Command */
-        return s->command;
-    case 0xf221:       /* System Configuration 1 */
-        return s->config[0] & 0xffe0;
-    case 0xf222:       /* System Configuration 2 */
-        return s->config[1];
-
-    case 0xf240:       /* Controller Status */
-        return s->status;
-    case 0xf241:       /* Interrupt */
-        return s->intstatus;
-    case 0xf24c:       /* Unlock Start Block Address */
-        return s->unladdr[0];
-    case 0xf24d:       /* Unlock End Block Address */
-        return s->unladdr[1];
-    case 0xf24e:       /* Write Protection Status */
-        return s->wpstatus;
-
-    case 0xff00:       /* ECC Status */
-        return 0x00;
-    case 0xff01:       /* ECC Result of main area data */
-    case 0xff02:       /* ECC Result of spare area data */
-    case 0xff03:       /* ECC Result of main area data */
-    case 0xff04:       /* ECC Result of spare area data */
-        hw_error("%s: imeplement ECC\n", __FUNCTION__);
-        return 0x0000;
-    }
-
-    fprintf(stderr, "%s: unknown OneNAND register %x\n",
-                    __FUNCTION__, offset);
-    return 0;
-}
-
-static void onenand_write(void *opaque, hwaddr addr,
-                          uint64_t value, unsigned size)
-{
-    OneNANDState *s = (OneNANDState *) opaque;
-    int offset = addr >> s->shift;
-    int sec;
-
-    switch (offset) {
-    case 0x0000 ... 0x01ff:
-    case 0x8000 ... 0x800f:
-        if (s->cycle) {
-            s->cycle = 0;
-
-            if (value == 0x0000) {
-                SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-                onenand_load_main(s, sec,
-                                1 << (PAGE_SHIFT - 9), s->data[0][0]);
-                s->addr[ONEN_BUF_PAGE] += 4;
-                s->addr[ONEN_BUF_PAGE] &= 0xff;
-            }
-            break;
-        }
-
-        switch (value) {
-        case 0x00f0:   /* Reset OneNAND */
-            onenand_reset(s, 0);
-            break;
-
-        case 0x00e0:   /* Load Data into Buffer */
-            s->cycle = 1;
-            break;
-
-        case 0x0090:   /* Read Identification Data */
-            memset(s->boot[0], 0, 3 << s->shift);
-            s->boot[0][0 << s->shift] = s->id.man & 0xff;
-            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
-            s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
-            break;
-
-        default:
-            fprintf(stderr, "%s: unknown OneNAND boot command %"PRIx64"\n",
-                            __FUNCTION__, value);
-        }
-        break;
-
-    case 0xf100 ... 0xf107:    /* Start addresses */
-        s->addr[offset - 0xf100] = value;
-        break;
-
-    case 0xf200:       /* Start buffer */
-        s->bufaddr = (value >> 8) & 0xf;
-        if (PAGE_SHIFT == 11)
-            s->count = (value & 3) ?: 4;
-        else if (PAGE_SHIFT == 10)
-            s->count = (value & 1) ?: 2;
-        break;
-
-    case 0xf220:       /* Command */
-        if (s->intstatus & (1 << 15))
-            break;
-        s->command = value;
-        onenand_command(s);
-        break;
-    case 0xf221:       /* System Configuration 1 */
-        s->config[0] = value;
-        onenand_intr_update(s);
-        qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
-        break;
-    case 0xf222:       /* System Configuration 2 */
-        s->config[1] = value;
-        break;
-
-    case 0xf241:       /* Interrupt */
-        s->intstatus &= value;
-        if ((1 << 15) & ~s->intstatus)
-            s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
-                            ONEN_ERR_PROG | ONEN_ERR_LOAD);
-        onenand_intr_update(s);
-        break;
-    case 0xf24c:       /* Unlock Start Block Address */
-        s->unladdr[0] = value & (s->blocks - 1);
-        /* For some reason we have to set the end address to by default
-         * be same as start because the software forgets to write anything
-         * in there.  */
-        s->unladdr[1] = value & (s->blocks - 1);
-        break;
-    case 0xf24d:       /* Unlock End Block Address */
-        s->unladdr[1] = value & (s->blocks - 1);
-        break;
-
-    default:
-        fprintf(stderr, "%s: unknown OneNAND register %x\n",
-                        __FUNCTION__, offset);
-    }
-}
-
-static const MemoryRegionOps onenand_ops = {
-    .read = onenand_read,
-    .write = onenand_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int onenand_initfn(SysBusDevice *dev)
-{
-    OneNANDState *s = (OneNANDState *)dev;
-    uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
-    void *ram;
-    s->base = (hwaddr)-1;
-    s->rdy = NULL;
-    s->blocks = size >> BLOCK_SHIFT;
-    s->secs = size >> 9;
-    s->blockwp = g_malloc(s->blocks);
-    s->density_mask = (s->id.dev & 0x08)
-        ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
-    memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand",
-                          0x10000 << s->shift);
-    if (!s->bdrv) {
-        s->image = memset(g_malloc(size + (size >> 5)),
-                          0xff, size + (size >> 5));
-    } else {
-        if (bdrv_is_read_only(s->bdrv)) {
-            error_report("Can't use a read-only drive");
-            return -1;
-        }
-        s->bdrv_cur = s->bdrv;
-    }
-    s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
-                    0xff, (64 + 2) << PAGE_SHIFT);
-    memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift);
-    vmstate_register_ram_global(&s->ram);
-    ram = memory_region_get_ram_ptr(&s->ram);
-    s->boot[0] = ram + (0x0000 << s->shift);
-    s->boot[1] = ram + (0x8000 << s->shift);
-    s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
-    s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
-    s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
-    s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
-    onenand_mem_setup(s);
-    sysbus_init_irq(dev, &s->intr);
-    sysbus_init_mmio(dev, &s->container);
-    vmstate_register(&dev->qdev,
-                     ((s->shift & 0x7f) << 24)
-                     | ((s->id.man & 0xff) << 16)
-                     | ((s->id.dev & 0xff) << 8)
-                     | (s->id.ver & 0xff),
-                     &vmstate_onenand, s);
-    return 0;
-}
-
-static Property onenand_properties[] = {
-    DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
-    DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
-    DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
-    DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
-    DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void onenand_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = onenand_initfn;
-    dc->reset = onenand_system_reset;
-    dc->props = onenand_properties;
-}
-
-static const TypeInfo onenand_info = {
-    .name          = "onenand",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(OneNANDState),
-    .class_init    = onenand_class_init,
-};
-
-static void onenand_register_types(void)
-{
-    type_register_static(&onenand_info);
-}
-
-void *onenand_raw_otp(DeviceState *onenand_device)
-{
-    return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
-}
-
-type_init(onenand_register_types)
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
deleted file mode 100644 (file)
index 0d95c8a..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * QEMU PC System Firmware
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2011-2012 Intel Corporation
- *
- * 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 "sysemu/blockdev.h"
-#include "qemu/error-report.h"
-#include "hw/sysbus.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "sysemu/sysemu.h"
-#include "hw/block/flash.h"
-#include "sysemu/kvm.h"
-
-#define BIOS_FILENAME "bios.bin"
-
-typedef struct PcSysFwDevice {
-    SysBusDevice busdev;
-    uint8_t rom_only;
-} PcSysFwDevice;
-
-static void pc_isa_bios_init(MemoryRegion *rom_memory,
-                             MemoryRegion *flash_mem,
-                             int ram_size)
-{
-    int isa_bios_size;
-    MemoryRegion *isa_bios;
-    uint64_t flash_size;
-    void *flash_ptr, *isa_bios_ptr;
-
-    flash_size = memory_region_size(flash_mem);
-
-    /* map the last 128KB of the BIOS in ISA space */
-    isa_bios_size = flash_size;
-    if (isa_bios_size > (128 * 1024)) {
-        isa_bios_size = 128 * 1024;
-    }
-    isa_bios = g_malloc(sizeof(*isa_bios));
-    memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size);
-    vmstate_register_ram_global(isa_bios);
-    memory_region_add_subregion_overlap(rom_memory,
-                                        0x100000 - isa_bios_size,
-                                        isa_bios,
-                                        1);
-
-    /* copy ISA rom image from top of flash memory */
-    flash_ptr = memory_region_get_ram_ptr(flash_mem);
-    isa_bios_ptr = memory_region_get_ram_ptr(isa_bios);
-    memcpy(isa_bios_ptr,
-           ((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
-           isa_bios_size);
-
-    memory_region_set_readonly(isa_bios, true);
-}
-
-static void pc_fw_add_pflash_drv(void)
-{
-    QemuOpts *opts;
-    QEMUMachine *machine;
-    char *filename;
-
-    if (bios_name == NULL) {
-        bios_name = BIOS_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (!filename) {
-        error_report("Can't open BIOS image %s", bios_name);
-        exit(1);
-    }
-
-    opts = drive_add(IF_PFLASH, -1, filename, "readonly=on");
-
-    g_free(filename);
-
-    if (opts == NULL) {
-      return;
-    }
-
-    machine = find_default_machine();
-    if (machine == NULL) {
-      return;
-    }
-
-    if (!drive_init(opts, machine->block_default_type)) {
-        qemu_opts_del(opts);
-    }
-}
-
-static void pc_system_flash_init(MemoryRegion *rom_memory,
-                                 DriveInfo *pflash_drv)
-{
-    BlockDriverState *bdrv;
-    int64_t size;
-    hwaddr phys_addr;
-    int sector_bits, sector_size;
-    pflash_t *system_flash;
-    MemoryRegion *flash_mem;
-
-    bdrv = pflash_drv->bdrv;
-    size = bdrv_getlength(pflash_drv->bdrv);
-    sector_bits = 12;
-    sector_size = 1 << sector_bits;
-
-    if ((size % sector_size) != 0) {
-        fprintf(stderr,
-                "qemu: PC system firmware (pflash) must be a multiple of 0x%x\n",
-                sector_size);
-        exit(1);
-    }
-
-    phys_addr = 0x100000000ULL - size;
-    system_flash = pflash_cfi01_register(phys_addr, NULL, "system.flash", size,
-                                         bdrv, sector_size, size >> sector_bits,
-                                         1, 0x0000, 0x0000, 0x0000, 0x0000, 0);
-    flash_mem = pflash_cfi01_get_memory(system_flash);
-
-    pc_isa_bios_init(rom_memory, flash_mem, size);
-}
-
-static void old_pc_system_rom_init(MemoryRegion *rom_memory)
-{
-    char *filename;
-    MemoryRegion *bios, *isa_bios;
-    int bios_size, isa_bios_size;
-    int ret;
-
-    /* BIOS load */
-    if (bios_name == NULL) {
-        bios_name = BIOS_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = get_image_size(filename);
-    } else {
-        bios_size = -1;
-    }
-    if (bios_size <= 0 ||
-        (bios_size % 65536) != 0) {
-        goto bios_error;
-    }
-    bios = g_malloc(sizeof(*bios));
-    memory_region_init_ram(bios, "pc.bios", bios_size);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
-    if (ret != 0) {
-    bios_error:
-        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
-        exit(1);
-    }
-    if (filename) {
-        g_free(filename);
-    }
-
-    /* map the last 128KB of the BIOS in ISA space */
-    isa_bios_size = bios_size;
-    if (isa_bios_size > (128 * 1024)) {
-        isa_bios_size = 128 * 1024;
-    }
-    isa_bios = g_malloc(sizeof(*isa_bios));
-    memory_region_init_alias(isa_bios, "isa-bios", bios,
-                             bios_size - isa_bios_size, isa_bios_size);
-    memory_region_add_subregion_overlap(rom_memory,
-                                        0x100000 - isa_bios_size,
-                                        isa_bios,
-                                        1);
-    memory_region_set_readonly(isa_bios, true);
-
-    /* map all the bios at the top of memory */
-    memory_region_add_subregion(rom_memory,
-                                (uint32_t)(-bios_size),
-                                bios);
-}
-
-void pc_system_firmware_init(MemoryRegion *rom_memory)
-{
-    DriveInfo *pflash_drv;
-    PcSysFwDevice *sysfw_dev;
-
-    sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
-
-    qdev_init_nofail(DEVICE(sysfw_dev));
-
-    if (sysfw_dev->rom_only) {
-        old_pc_system_rom_init(rom_memory);
-        return;
-    }
-
-    pflash_drv = drive_get(IF_PFLASH, 0, 0);
-
-    /* Currently KVM cannot execute from device memory.
-       Use old rom based firmware initialization for KVM. */
-    if (kvm_enabled()) {
-        if (pflash_drv != NULL) {
-            fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n");
-            exit(1);
-        } else {
-            sysfw_dev->rom_only = 1;
-            old_pc_system_rom_init(rom_memory);
-            return;
-        }
-    }
-
-    /* If a pflash drive is not found, then create one using
-       the bios filename. */
-    if (pflash_drv == NULL) {
-        pc_fw_add_pflash_drv();
-        pflash_drv = drive_get(IF_PFLASH, 0, 0);
-    }
-
-    if (pflash_drv != NULL) {
-        pc_system_flash_init(rom_memory, pflash_drv);
-    } else {
-        fprintf(stderr, "qemu: PC system firmware (pflash) not available\n");
-        exit(1);
-    }
-}
-
-static Property pcsysfw_properties[] = {
-    DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static int pcsysfw_init(DeviceState *dev)
-{
-    return 0;
-}
-
-static void pcsysfw_class_init (ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS (klass);
-
-    dc->desc = "PC System Firmware";
-    dc->init = pcsysfw_init;
-    dc->props = pcsysfw_properties;
-}
-
-static const TypeInfo pcsysfw_info = {
-    .name          = "pc-sysfw",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof (PcSysFwDevice),
-    .class_init    = pcsysfw_class_init,
-};
-
-static void pcsysfw_register (void)
-{
-    type_register_static (&pcsysfw_info);
-}
-
-type_init (pcsysfw_register);
-
index 4f2ac2a6ced7934fd4248b13e8b9c5ef5f4b811d..efbb9ebef1a42a9c03b0514ecb3bd8404cb812dd 100644 (file)
@@ -1,4 +1,3 @@
-obj-y = tc58128.o
 obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/tc58128.c b/hw/tc58128.c
deleted file mode 100644 (file)
index a3929d4..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-#include "hw/hw.h"
-#include "hw/sh4/sh.h"
-#include "hw/loader.h"
-
-#define CE1  0x0100
-#define CE2  0x0200
-#define RE   0x0400
-#define WE   0x0800
-#define ALE  0x1000
-#define CLE  0x2000
-#define RDY1 0x4000
-#define RDY2 0x8000
-#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
-
-typedef enum { WAIT, READ1, READ2, READ3 } state_t;
-
-typedef struct {
-    uint8_t *flash_contents;
-    state_t state;
-    uint32_t address;
-    uint8_t address_cycle;
-} tc58128_dev;
-
-static tc58128_dev tc58128_devs[2];
-
-#define FLASH_SIZE (16*1024*1024)
-
-static void init_dev(tc58128_dev * dev, const char *filename)
-{
-    int ret, blocks;
-
-    dev->state = WAIT;
-    dev->flash_contents = g_malloc(FLASH_SIZE);
-    memset(dev->flash_contents, 0xff, FLASH_SIZE);
-    if (filename) {
-       /* Load flash image skipping the first block */
-       ret = load_image(filename, dev->flash_contents + 528 * 32);
-       if (ret < 0) {
-           fprintf(stderr, "ret=%d\n", ret);
-           fprintf(stderr, "qemu: could not load flash image %s\n",
-                   filename);
-           exit(1);
-       } else {
-           /* Build first block with number of blocks */
-           blocks = (ret + 528 * 32 - 1) / (528 * 32);
-           dev->flash_contents[0] = blocks & 0xff;
-           dev->flash_contents[1] = (blocks >> 8) & 0xff;
-           dev->flash_contents[2] = (blocks >> 16) & 0xff;
-           dev->flash_contents[3] = (blocks >> 24) & 0xff;
-           fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
-                   filename);
-       }
-    }
-}
-
-static void handle_command(tc58128_dev * dev, uint8_t command)
-{
-    switch (command) {
-    case 0xff:
-       fprintf(stderr, "reset flash device\n");
-       dev->state = WAIT;
-       break;
-    case 0x00:
-       fprintf(stderr, "read mode 1\n");
-       dev->state = READ1;
-       dev->address_cycle = 0;
-       break;
-    case 0x01:
-       fprintf(stderr, "read mode 2\n");
-       dev->state = READ2;
-       dev->address_cycle = 0;
-       break;
-    case 0x50:
-       fprintf(stderr, "read mode 3\n");
-       dev->state = READ3;
-       dev->address_cycle = 0;
-       break;
-    default:
-       fprintf(stderr, "unknown flash command 0x%02x\n", command);
-        abort();
-    }
-}
-
-static void handle_address(tc58128_dev * dev, uint8_t data)
-{
-    switch (dev->state) {
-    case READ1:
-    case READ2:
-    case READ3:
-       switch (dev->address_cycle) {
-       case 0:
-           dev->address = data;
-           if (dev->state == READ2)
-               dev->address |= 0x100;
-           else if (dev->state == READ3)
-               dev->address |= 0x200;
-           break;
-       case 1:
-           dev->address += data * 528 * 0x100;
-           break;
-       case 2:
-           dev->address += data * 528;
-           fprintf(stderr, "address pointer in flash: 0x%08x\n",
-                   dev->address);
-           break;
-       default:
-           /* Invalid data */
-            abort();
-       }
-       dev->address_cycle++;
-       break;
-    default:
-        abort();
-    }
-}
-
-static uint8_t handle_read(tc58128_dev * dev)
-{
-#if 0
-    if (dev->address % 0x100000 == 0)
-       fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
-#endif
-    return dev->flash_contents[dev->address++];
-}
-
-/* We never mark the device as busy, so interrupts cannot be triggered
-   XXXXX */
-
-static int tc58128_cb(uint16_t porta, uint16_t portb,
-                      uint16_t * periph_pdtra, uint16_t * periph_portadir,
-                      uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
-{
-    int dev;
-
-    if ((porta & CE1) == 0)
-       dev = 0;
-    else if ((porta & CE2) == 0)
-       dev = 1;
-    else
-       return 0;               /* No device selected */
-
-    if ((porta & RE) && (porta & WE)) {
-       /* Nothing to do, assert ready and return to input state */
-       *periph_portadir &= 0xff00;
-       *periph_portadir |= RDY(dev);
-       *periph_pdtra |= RDY(dev);
-       return 1;
-    }
-
-    if (porta & CLE) {
-       /* Command */
-       assert((porta & WE) == 0);
-       handle_command(&tc58128_devs[dev], porta & 0x00ff);
-    } else if (porta & ALE) {
-       assert((porta & WE) == 0);
-       handle_address(&tc58128_devs[dev], porta & 0x00ff);
-    } else if ((porta & RE) == 0) {
-       *periph_portadir |= 0x00ff;
-       *periph_pdtra &= 0xff00;
-       *periph_pdtra |= handle_read(&tc58128_devs[dev]);
-    } else {
-        abort();
-    }
-    return 1;
-}
-
-static sh7750_io_device tc58128 = {
-    RE | WE,                   /* Port A triggers */
-    0,                         /* Port B triggers */
-    tc58128_cb                 /* Callback */
-};
-
-int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
-{
-    init_dev(&tc58128_devs[0], zone1);
-    init_dev(&tc58128_devs[1], zone2);
-    return sh7750_register_io_device(s, &tc58128);
-}