diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/virtio-9p-debug.c (renamed from hw/virtio-9p-debug.c) | 0 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-debug.h (renamed from hw/virtio-9p-debug.h) | 0 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-local.c (renamed from hw/virtio-9p-local.c) | 2 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-posix-acl.c (renamed from hw/virtio-9p-posix-acl.c) | 17 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-xattr-user.c (renamed from hw/virtio-9p-xattr-user.c) | 2 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-xattr.c (renamed from hw/virtio-9p-xattr.c) | 2 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-xattr.h (renamed from hw/virtio-9p-xattr.h) | 0 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.c (renamed from hw/virtio-9p.c) | 14 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.h (renamed from hw/virtio-9p.h) | 4 | ||||
-rw-r--r-- | hw/adb.c | 83 | ||||
-rw-r--r-- | hw/ads7846.c | 41 | ||||
-rw-r--r-- | hw/an5206.c | 1 | ||||
-rw-r--r-- | hw/arm_boot.c | 2 | ||||
-rw-r--r-- | hw/arm_timer.c | 66 | ||||
-rw-r--r-- | hw/armv7m.c | 1 | ||||
-rw-r--r-- | hw/armv7m_nvic.c | 39 | ||||
-rw-r--r-- | hw/axis_dev88.c | 1 | ||||
-rw-r--r-- | hw/blizzard.c | 1 | ||||
-rw-r--r-- | hw/bt-hci-csr.c | 1 | ||||
-rw-r--r-- | hw/collie.c | 69 | ||||
-rw-r--r-- | hw/cris-boot.c | 1 | ||||
-rw-r--r-- | hw/cuda.c | 116 | ||||
-rw-r--r-- | hw/dummy_m68k.c | 1 | ||||
-rw-r--r-- | hw/e1000.c | 2 | ||||
-rw-r--r-- | hw/eepro100.c | 2 | ||||
-rw-r--r-- | hw/empty_slot.c | 21 | ||||
-rw-r--r-- | hw/etraxfs.c | 1 | ||||
-rw-r--r-- | hw/file-op-9p.h | 107 | ||||
-rw-r--r-- | hw/flash.h | 4 | ||||
-rw-r--r-- | hw/grlib_apbuart.c | 2 | ||||
-rw-r--r-- | hw/grlib_gptimer.c | 29 | ||||
-rw-r--r-- | hw/grlib_irqmp.c | 4 | ||||
-rw-r--r-- | hw/gumstix.c | 1 | ||||
-rw-r--r-- | hw/heathrow_pic.c | 62 | ||||
-rw-r--r-- | hw/hw.h | 17 | ||||
-rw-r--r-- | hw/ide/atapi.c | 1138 | ||||
-rw-r--r-- | hw/ide/core.c | 1067 | ||||
-rw-r--r-- | hw/ide/ich.c | 1 | ||||
-rw-r--r-- | hw/ide/internal.h | 10 | ||||
-rw-r--r-- | hw/ide/isa.c | 1 | ||||
-rw-r--r-- | hw/ide/macio.c | 1 | ||||
-rw-r--r-- | hw/ide/microdrive.c | 1 | ||||
-rw-r--r-- | hw/ide/mmio.c | 1 | ||||
-rw-r--r-- | hw/ide/pci.c | 1 | ||||
-rw-r--r-- | hw/integratorcp.c | 1 | ||||
-rw-r--r-- | hw/ioapic.c | 5 | ||||
-rw-r--r-- | hw/isa-bus.c | 1 | ||||
-rw-r--r-- | hw/kvmclock.c | 6 | ||||
-rw-r--r-- | hw/lm32_boards.c | 1 | ||||
-rw-r--r-- | hw/m48t59.c | 36 | ||||
-rw-r--r-- | hw/mac_dbdma.c | 83 | ||||
-rw-r--r-- | hw/mac_nvram.c | 32 | ||||
-rw-r--r-- | hw/mainstone.c | 1 | ||||
-rw-r--r-- | hw/max111x.c | 51 | ||||
-rw-r--r-- | hw/milkymist-hw.h | 20 | ||||
-rw-r--r-- | hw/milkymist-minimac2.c (renamed from hw/milkymist-minimac.c) | 297 | ||||
-rw-r--r-- | hw/milkymist-sysctl.c | 26 | ||||
-rw-r--r-- | hw/milkymist-vgafb.c | 3 | ||||
-rw-r--r-- | hw/milkymist.c | 2 | ||||
-rw-r--r-- | hw/mipsnet.c | 53 | ||||
-rw-r--r-- | hw/nand.c | 79 | ||||
-rw-r--r-- | hw/ne2000.c | 2 | ||||
-rw-r--r-- | hw/omap_sx1.c | 1 | ||||
-rw-r--r-- | hw/pcie.c | 3 | ||||
-rw-r--r-- | hw/pcnet-pci.c | 2 | ||||
-rw-r--r-- | hw/pflash_cfi02.c | 12 | ||||
-rw-r--r-- | hw/piix4.c | 44 | ||||
-rw-r--r-- | hw/pl011.c | 76 | ||||
-rw-r--r-- | hw/pl022.c | 84 | ||||
-rw-r--r-- | hw/ppc440_bamboo.c | 1 | ||||
-rw-r--r-- | hw/ppc4xx_devs.c | 1 | ||||
-rw-r--r-- | hw/ppc4xx_pci.c | 80 | ||||
-rw-r--r-- | hw/ppce500_pci.c | 87 | ||||
-rw-r--r-- | hw/ptimer.c | 59 | ||||
-rw-r--r-- | hw/pxa2xx.c | 158 | ||||
-rw-r--r-- | hw/pxa2xx_keypad.c | 53 | ||||
-rw-r--r-- | hw/pxa2xx_lcd.c | 138 | ||||
-rw-r--r-- | hw/qdev-properties.c | 4 | ||||
-rw-r--r-- | hw/rtl8139.c | 440 | ||||
-rw-r--r-- | hw/s390-virtio-bus.c | 10 | ||||
-rw-r--r-- | hw/s390-virtio.c | 21 | ||||
-rw-r--r-- | hw/stellaris.c | 324 | ||||
-rw-r--r-- | hw/stellaris_input.c | 50 | ||||
-rw-r--r-- | hw/strongarm.c | 1598 | ||||
-rw-r--r-- | hw/strongarm.h | 64 | ||||
-rw-r--r-- | hw/syborg.c | 1 | ||||
-rw-r--r-- | hw/syborg_keyboard.c | 57 | ||||
-rw-r--r-- | hw/syborg_pointer.c | 73 | ||||
-rw-r--r-- | hw/syborg_rtc.c | 34 | ||||
-rw-r--r-- | hw/syborg_serial.c | 60 | ||||
-rw-r--r-- | hw/syborg_timer.c | 46 | ||||
-rw-r--r-- | hw/syborg_virtio.c | 1 | ||||
-rw-r--r-- | hw/sysbus.c | 1 | ||||
-rw-r--r-- | hw/tc58128.c | 1 | ||||
-rw-r--r-- | hw/tosa.c | 1 | ||||
-rw-r--r-- | hw/twl92230.c | 1 | ||||
-rw-r--r-- | hw/usb-hid.c | 2 | ||||
-rw-r--r-- | hw/usb-msd.c | 4 | ||||
-rw-r--r-- | hw/virtio-balloon.c | 1 | ||||
-rw-r--r-- | hw/virtio-console.c | 18 | ||||
-rw-r--r-- | hw/virtio-pci.c | 2 | ||||
-rw-r--r-- | hw/virtio-serial-bus.c | 23 | ||||
-rw-r--r-- | hw/virtio.c | 1 | ||||
-rw-r--r-- | hw/vmport.c | 1 | ||||
-rw-r--r-- | hw/xen_console.c | 1 | ||||
-rw-r--r-- | hw/xen_domainbuild.c | 1 | ||||
-rw-r--r-- | hw/xen_machine_pv.c | 1 | ||||
-rw-r--r-- | hw/xenfb.c | 1 | ||||
-rw-r--r-- | hw/xilinx_timer.c | 1 |
109 files changed, 4280 insertions, 2999 deletions
diff --git a/hw/virtio-9p-debug.c b/hw/9pfs/virtio-9p-debug.c index 6b18842fd..6b18842fd 100644 --- a/hw/virtio-9p-debug.c +++ b/hw/9pfs/virtio-9p-debug.c diff --git a/hw/virtio-9p-debug.h b/hw/9pfs/virtio-9p-debug.h index d9a249118..d9a249118 100644 --- a/hw/virtio-9p-debug.h +++ b/hw/9pfs/virtio-9p-debug.h diff --git a/hw/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index a8e7525bf..0a015de9a 100644 --- a/hw/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -370,7 +370,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, return fd; } /* Write the oldpath (target) to the file. */ - oldpath_size = strlen(oldpath) + 1; + oldpath_size = strlen(oldpath); do { write_size = write(fd, (void *)oldpath, oldpath_size); } while (write_size == -1 && errno == EINTR); diff --git a/hw/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c index 3978d0cf7..575abe86b 100644 --- a/hw/virtio-9p-posix-acl.c +++ b/hw/9pfs/virtio-9p-posix-acl.c @@ -15,7 +15,7 @@ #include <attr/xattr.h> #include "virtio.h" #include "virtio-9p.h" -#include "file-op-9p.h" +#include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access" @@ -60,7 +60,7 @@ static int mp_pacl_removexattr(FsContext *ctx, ret = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS); if (ret == -1 && errno == ENODATA) { /* - * We don't get ENODATA error when trying to remote a + * We don't get ENODATA error when trying to remove a * posix acl that is not present. So don't throw the error * even in case of mapped security model */ @@ -103,7 +103,18 @@ static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name, static int mp_dacl_removexattr(FsContext *ctx, const char *path, const char *name) { - return lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT); + int ret; + ret = lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT); + if (ret == -1 && errno == ENODATA) { + /* + * We don't get ENODATA error when trying to remove a + * posix acl that is not present. So don't throw the error + * even in case of mapped security model + */ + errno = 0; + ret = 0; + } + return ret; } diff --git a/hw/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c index faa02a191..bba13ce64 100644 --- a/hw/virtio-9p-xattr-user.c +++ b/hw/9pfs/virtio-9p-xattr-user.c @@ -14,7 +14,7 @@ #include <sys/types.h> #include "virtio.h" #include "virtio-9p.h" -#include "file-op-9p.h" +#include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" diff --git a/hw/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c index 1aab081de..03c3d3f6b 100644 --- a/hw/virtio-9p-xattr.c +++ b/hw/9pfs/virtio-9p-xattr.c @@ -13,7 +13,7 @@ #include "virtio.h" #include "virtio-9p.h" -#include "file-op-9p.h" +#include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" diff --git a/hw/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h index 2bbae2dcb..2bbae2dcb 100644 --- a/hw/virtio-9p-xattr.h +++ b/hw/9pfs/virtio-9p-xattr.h diff --git a/hw/virtio-9p.c b/hw/9pfs/virtio-9p.c index 7e2953567..b5fc52b3e 100644 --- a/hw/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -596,7 +596,10 @@ static V9fsPDU *alloc_pdu(V9fsState *s) static void free_pdu(V9fsState *s, V9fsPDU *pdu) { if (pdu) { - QLIST_INSERT_HEAD(&s->free_list, pdu, next); + if (debug_9p_pdu) { + pprint_pdu(pdu); + } + QLIST_INSERT_HEAD(&s->free_list, pdu, next); } } @@ -1479,7 +1482,7 @@ static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) { complete_pdu(s, vs->pdu, err); - if (vs->nwnames) { + if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) { v9fs_string_free(&vs->wnames[vs->name_idx]); } @@ -1575,7 +1578,7 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu) vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid, &newfid, &vs->nwnames); - if (vs->nwnames) { + if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames); vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames); @@ -1584,6 +1587,9 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu) vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s", &vs->wnames[i]); } + } else if (vs->nwnames > P9_MAXWELEM) { + err = -EINVAL; + goto out; } vs->fidp = lookup_fid(s, fid); @@ -1768,7 +1774,7 @@ static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err) v9fs_string_copy(&vs->fidp->path, &vs->fullname); stat_to_qid(&vs->stbuf, &vs->qid); vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, - &vs->iounit); + vs->iounit); err = vs->offset; } else { vs->fidp->fid_type = P9_FID_NONE; diff --git a/hw/virtio-9p.h b/hw/9pfs/virtio-9p.h index 2ae4ce718..622928fce 100644 --- a/hw/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -6,7 +6,7 @@ #include <sys/time.h> #include <utime.h> -#include "file-op-9p.h" +#include "fsdev/file-op-9p.h" /* The feature bitmap for virtio 9P */ /* The mount point is specified in a config variable */ @@ -282,7 +282,7 @@ typedef struct V9fsStatStateDotl { typedef struct V9fsWalkState { V9fsPDU *pdu; size_t offset; - int16_t nwnames; + uint16_t nwnames; int name_idx; V9fsQID *qids; V9fsFidState *fidp; @@ -261,30 +261,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, return olen; } -static void adb_kbd_save(QEMUFile *f, void *opaque) -{ - KBDState *s = (KBDState *)opaque; - - qemu_put_buffer(f, s->data, sizeof(s->data)); - qemu_put_sbe32s(f, &s->rptr); - qemu_put_sbe32s(f, &s->wptr); - qemu_put_sbe32s(f, &s->count); -} - -static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id) -{ - KBDState *s = (KBDState *)opaque; - - if (version_id != 1) - return -EINVAL; - - qemu_get_buffer(f, s->data, sizeof(s->data)); - qemu_get_sbe32s(f, &s->rptr); - qemu_get_sbe32s(f, &s->wptr); - qemu_get_sbe32s(f, &s->count); - - return 0; -} +static const VMStateDescription vmstate_adb_kbd = { + .name = "adb_kbd", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_BUFFER(data, KBDState), + VMSTATE_INT32(rptr, KBDState), + VMSTATE_INT32(wptr, KBDState), + VMSTATE_INT32(count, KBDState), + VMSTATE_END_OF_LIST() + } +}; static int adb_kbd_reset(ADBDevice *d) { @@ -305,8 +294,7 @@ void adb_kbd_init(ADBBusState *bus) d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, adb_kbd_reset, s); qemu_add_kbd_event_handler(adb_kbd_put_keycode, d); - register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save, - adb_kbd_load, s); + vmstate_register(NULL, -1, &vmstate_adb_kbd, s); } /***************************************************************/ @@ -439,32 +427,20 @@ static int adb_mouse_reset(ADBDevice *d) return 0; } -static void adb_mouse_save(QEMUFile *f, void *opaque) -{ - MouseState *s = (MouseState *)opaque; - - qemu_put_sbe32s(f, &s->buttons_state); - qemu_put_sbe32s(f, &s->last_buttons_state); - qemu_put_sbe32s(f, &s->dx); - qemu_put_sbe32s(f, &s->dy); - qemu_put_sbe32s(f, &s->dz); -} - -static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id) -{ - MouseState *s = (MouseState *)opaque; - - if (version_id != 1) - return -EINVAL; - - qemu_get_sbe32s(f, &s->buttons_state); - qemu_get_sbe32s(f, &s->last_buttons_state); - qemu_get_sbe32s(f, &s->dx); - qemu_get_sbe32s(f, &s->dy); - qemu_get_sbe32s(f, &s->dz); - - return 0; -} +static const VMStateDescription vmstate_adb_mouse = { + .name = "adb_mouse", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32(buttons_state, MouseState), + VMSTATE_INT32(last_buttons_state, MouseState), + VMSTATE_INT32(dx, MouseState), + VMSTATE_INT32(dy, MouseState), + VMSTATE_INT32(dz, MouseState), + VMSTATE_END_OF_LIST() + } +}; void adb_mouse_init(ADBBusState *bus) { @@ -475,6 +451,5 @@ void adb_mouse_init(ADBBusState *bus) d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, adb_mouse_reset, s); qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse"); - register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save, - adb_mouse_load, s); + vmstate_register(NULL, -1, &vmstate_adb_mouse, s); } diff --git a/hw/ads7846.c b/hw/ads7846.c index b3bbeaf68..9c58a5f59 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -105,35 +105,30 @@ static void ads7846_ts_event(void *opaque, } } -static void ads7846_save(QEMUFile *f, void *opaque) +static int ads7856_post_load(void *opaque, int version_id) { - ADS7846State *s = (ADS7846State *) opaque; - int i; - - for (i = 0; i < 8; i ++) - qemu_put_be32(f, s->input[i]); - qemu_put_be32(f, s->noise); - qemu_put_be32(f, s->cycle); - qemu_put_be32(f, s->output); -} - -static int ads7846_load(QEMUFile *f, void *opaque, int version_id) -{ - ADS7846State *s = (ADS7846State *) opaque; - int i; - - for (i = 0; i < 8; i ++) - s->input[i] = qemu_get_be32(f); - s->noise = qemu_get_be32(f); - s->cycle = qemu_get_be32(f); - s->output = qemu_get_be32(f); + ADS7846State *s = opaque; s->pressure = 0; ads7846_int_update(s); - return 0; } +static const VMStateDescription vmstate_ads7846 = { + .name = "ads7846", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .post_load = ads7856_post_load, + .fields = (VMStateField[]) { + VMSTATE_INT32_ARRAY(input, ADS7846State, 8), + VMSTATE_INT32(noise, ADS7846State), + VMSTATE_INT32(cycle, ADS7846State), + VMSTATE_INT32(output, ADS7846State), + VMSTATE_END_OF_LIST() + } +}; + static int ads7846_init(SSISlave *dev) { ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); @@ -151,7 +146,7 @@ static int ads7846_init(SSISlave *dev) ads7846_int_update(s); - register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s); + vmstate_register(NULL, -1, &vmstate_ads7846, s); return 0; } diff --git a/hw/an5206.c b/hw/an5206.c index b9f19a994..42a0163fb 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -9,7 +9,6 @@ #include "hw.h" #include "pc.h" #include "mcf.h" -#include "sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" diff --git a/hw/arm_boot.c b/hw/arm_boot.c index 41e99d133..bfac982e6 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -15,7 +15,7 @@ #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 -#define INITRD_LOAD_ADDR 0x00800000 +#define INITRD_LOAD_ADDR 0x00d00000 /* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ static uint32_t bootloader[] = { diff --git a/hw/arm_timer.c b/hw/arm_timer.c index 82f05dec8..dac9e7075 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -140,28 +140,19 @@ static void arm_timer_tick(void *opaque) arm_timer_update(s); } -static void arm_timer_save(QEMUFile *f, void *opaque) -{ - arm_timer_state *s = (arm_timer_state *)opaque; - qemu_put_be32(f, s->control); - qemu_put_be32(f, s->limit); - qemu_put_be32(f, s->int_level); - qemu_put_ptimer(f, s->timer); -} - -static int arm_timer_load(QEMUFile *f, void *opaque, int version_id) -{ - arm_timer_state *s = (arm_timer_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->control = qemu_get_be32(f); - s->limit = qemu_get_be32(f); - s->int_level = qemu_get_be32(f); - qemu_get_ptimer(f, s->timer); - return 0; -} +static const VMStateDescription vmstate_arm_timer = { + .name = "arm_timer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(control, arm_timer_state), + VMSTATE_UINT32(limit, arm_timer_state), + VMSTATE_INT32(int_level, arm_timer_state), + VMSTATE_PTIMER(timer, arm_timer_state), + VMSTATE_END_OF_LIST() + } +}; static arm_timer_state *arm_timer_init(uint32_t freq) { @@ -174,7 +165,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq) bh = qemu_bh_new(arm_timer_tick, s); s->timer = ptimer_init(bh); - register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s); + vmstate_register(NULL, -1, &vmstate_arm_timer, s); return s; } @@ -235,24 +226,17 @@ static CPUWriteMemoryFunc * const sp804_writefn[] = { sp804_write }; -static void sp804_save(QEMUFile *f, void *opaque) -{ - sp804_state *s = (sp804_state *)opaque; - qemu_put_be32(f, s->level[0]); - qemu_put_be32(f, s->level[1]); -} - -static int sp804_load(QEMUFile *f, void *opaque, int version_id) -{ - sp804_state *s = (sp804_state *)opaque; - if (version_id != 1) - return -EINVAL; - - s->level[0] = qemu_get_be32(f); - s->level[1] = qemu_get_be32(f); - return 0; -} +static const VMStateDescription vmstate_sp804 = { + .name = "sp804", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32_ARRAY(level, sp804_state, 2), + VMSTATE_END_OF_LIST() + } +}; static int sp804_init(SysBusDevice *dev) { @@ -271,7 +255,7 @@ static int sp804_init(SysBusDevice *dev) iomemtype = cpu_register_io_memory(sp804_readfn, sp804_writefn, s, DEVICE_NATIVE_ENDIAN); sysbus_init_mmio(dev, 0x1000, iomemtype); - register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_sp804, s); return 0; } diff --git a/hw/armv7m.c b/hw/armv7m.c index 304cd34bc..72d010a63 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -9,7 +9,6 @@ #include "sysbus.h" #include "arm-misc.h" -#include "sysemu.h" #include "loader.h" #include "elf.h" diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index ffe16b8a6..d06eec9b3 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -365,30 +365,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) } } -static void nvic_save(QEMUFile *f, void *opaque) -{ - nvic_state *s = (nvic_state *)opaque; - - qemu_put_be32(f, s->systick.control); - qemu_put_be32(f, s->systick.reload); - qemu_put_be64(f, s->systick.tick); - qemu_put_timer(f, s->systick.timer); -} - -static int nvic_load(QEMUFile *f, void *opaque, int version_id) -{ - nvic_state *s = (nvic_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->systick.control = qemu_get_be32(f); - s->systick.reload = qemu_get_be32(f); - s->systick.tick = qemu_get_be64(f); - qemu_get_timer(f, s->systick.timer); - - return 0; -} +static const VMStateDescription vmstate_nvic = { + .name = "armv7m_nvic", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(systick.control, nvic_state), + VMSTATE_UINT32(systick.reload, nvic_state), + VMSTATE_INT64(systick.tick, nvic_state), + VMSTATE_TIMER(systick.timer, nvic_state), + VMSTATE_END_OF_LIST() + } +}; static int armv7m_nvic_init(SysBusDevice *dev) { @@ -397,7 +386,7 @@ static int armv7m_nvic_init(SysBusDevice *dev) gic_init(&s->gic); cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype); s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s); - register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_nvic, s); return 0; } diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index 57b5e2f04..0e2135afd 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -26,7 +26,6 @@ #include "net.h" #include "flash.h" #include "boards.h" -#include "sysemu.h" #include "etraxfs.h" #include "loader.h" #include "elf.h" diff --git a/hw/blizzard.c b/hw/blizzard.c index 5f329ad13..c5245504a 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -19,7 +19,6 @@ */ #include "qemu-common.h" -#include "sysemu.h" #include "console.h" #include "devices.h" #include "vga_int.h" diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c index 65ffa37fd..d135ef479 100644 --- a/hw/bt-hci-csr.c +++ b/hw/bt-hci-csr.c @@ -22,7 +22,6 @@ #include "qemu-char.h" #include "qemu-timer.h" #include "irq.h" -#include "sysemu.h" #include "net.h" #include "bt.h" diff --git a/hw/collie.c b/hw/collie.c new file mode 100644 index 000000000..156404d9f --- /dev/null +++ b/hw/collie.c @@ -0,0 +1,69 @@ +/* + * SA-1110-based Sharp Zaurus SL-5500 platform. + * + * Copyright (C) 2011 Dmitry Eremin-Solenikov + * + * This code is licensed under GNU GPL v2. + */ +#include "hw.h" +#include "sysbus.h" +#include "boards.h" +#include "devices.h" +#include "strongarm.h" +#include "arm-misc.h" +#include "flash.h" +#include "blockdev.h" + +static struct arm_boot_info collie_binfo = { + .loader_start = SA_SDCS0, + .ram_size = 0x20000000, +}; + +static void collie_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + StrongARMState *s; + DriveInfo *dinfo; + ram_addr_t phys_flash; + + if (!cpu_model) { + cpu_model = "sa1110"; + } + + s = sa1110_init(collie_binfo.ram_size, cpu_model); + + phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000); + dinfo = drive_get(IF_PFLASH, 0, 0); + pflash_cfi01_register(SA_CS0, phys_flash, + dinfo ? dinfo->bdrv : NULL, (64 * 1024), + 512, 4, 0x00, 0x00, 0x00, 0x00, 0); + + phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000); + dinfo = drive_get(IF_PFLASH, 0, 1); + pflash_cfi01_register(SA_CS1, phys_flash, + dinfo ? dinfo->bdrv : NULL, (64 * 1024), + 512, 4, 0x00, 0x00, 0x00, 0x00, 0); + + sysbus_create_simple("scoop", 0x40800000, NULL); + + collie_binfo.kernel_filename = kernel_filename; + collie_binfo.kernel_cmdline = kernel_cmdline; + collie_binfo.initrd_filename = initrd_filename; + collie_binfo.board_id = 0x208; + arm_load_kernel(s->env, &collie_binfo); +} + +static QEMUMachine collie_machine = { + .name = "collie", + .desc = "Collie PDA (SA-1110)", + .init = collie_init, +}; + +static void collie_machine_init(void) +{ + qemu_register_machine(&collie_machine); +} + +machine_init(collie_machine_init) diff --git a/hw/cris-boot.c b/hw/cris-boot.c index 2ef17f606..37894f8b5 100644 --- a/hw/cris-boot.c +++ b/hw/cris-boot.c @@ -23,7 +23,6 @@ */ #include "hw.h" -#include "sysemu.h" #include "loader.h" #include "elf.h" #include "cris-boot.h" @@ -644,80 +644,56 @@ static CPUReadMemoryFunc * const cuda_read[] = { &cuda_readl, }; -static void cuda_save_timer(QEMUFile *f, CUDATimer *s) +static bool cuda_timer_exist(void *opaque, int version_id) { - qemu_put_be16s(f, &s->latch); - qemu_put_be16s(f, &s->counter_value); - qemu_put_sbe64s(f, &s->load_time); - qemu_put_sbe64s(f, &s->next_irq_time); - if (s->timer) - qemu_put_timer(f, s->timer); -} - -static void cuda_save(QEMUFile *f, void *opaque) -{ - CUDAState *s = (CUDAState *)opaque; - - qemu_put_ubyte(f, s->b); - qemu_put_ubyte(f, s->a); - qemu_put_ubyte(f, s->dirb); - qemu_put_ubyte(f, s->dira); - qemu_put_ubyte(f, s->sr); - qemu_put_ubyte(f, s->acr); - qemu_put_ubyte(f, s->pcr); - qemu_put_ubyte(f, s->ifr); - qemu_put_ubyte(f, s->ier); - qemu_put_ubyte(f, s->anh); - qemu_put_sbe32s(f, &s->data_in_size); - qemu_put_sbe32s(f, &s->data_in_index); - qemu_put_sbe32s(f, &s->data_out_index); - qemu_put_ubyte(f, s->autopoll); - qemu_put_buffer(f, s->data_in, sizeof(s->data_in)); - qemu_put_buffer(f, s->data_out, sizeof(s->data_out)); - qemu_put_be32s(f, &s->tick_offset); - cuda_save_timer(f, &s->timers[0]); - cuda_save_timer(f, &s->timers[1]); -} + CUDATimer *s = opaque; -static void cuda_load_timer(QEMUFile *f, CUDATimer *s) -{ - qemu_get_be16s(f, &s->latch); - qemu_get_be16s(f, &s->counter_value); - qemu_get_sbe64s(f, &s->load_time); - qemu_get_sbe64s(f, &s->next_irq_time); - if (s->timer) - qemu_get_timer(f, s->timer); + return s->timer != NULL; } -static int cuda_load(QEMUFile *f, void *opaque, int version_id) -{ - CUDAState *s = (CUDAState *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->b = qemu_get_ubyte(f); - s->a = qemu_get_ubyte(f); - s->dirb = qemu_get_ubyte(f); - s->dira = qemu_get_ubyte(f); - s->sr = qemu_get_ubyte(f); - s->acr = qemu_get_ubyte(f); - s->pcr = qemu_get_ubyte(f); - s->ifr = qemu_get_ubyte(f); - s->ier = qemu_get_ubyte(f); - s->anh = qemu_get_ubyte(f); - qemu_get_sbe32s(f, &s->data_in_size); - qemu_get_sbe32s(f, &s->data_in_index); - qemu_get_sbe32s(f, &s->data_out_index); - s->autopoll = qemu_get_ubyte(f); - qemu_get_buffer(f, s->data_in, sizeof(s->data_in)); - qemu_get_buffer(f, s->data_out, sizeof(s->data_out)); - qemu_get_be32s(f, &s->tick_offset); - cuda_load_timer(f, &s->timers[0]); - cuda_load_timer(f, &s->timers[1]); +static const VMStateDescription vmstate_cuda_timer = { + .name = "cuda_timer", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT16(latch, CUDATimer), + VMSTATE_UINT16(counter_value, CUDATimer), + VMSTATE_INT64(load_time, CUDATimer), + VMSTATE_INT64(next_irq_time, CUDATimer), + VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist), + VMSTATE_END_OF_LIST() + } +}; - return 0; -} +static const VMStateDescription vmstate_cuda = { + .name = "cuda", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(a, CUDAState), + VMSTATE_UINT8(b, CUDAState), + VMSTATE_UINT8(dira, CUDAState), + VMSTATE_UINT8(dirb, CUDAState), + VMSTATE_UINT8(sr, CUDAState), + VMSTATE_UINT8(acr, CUDAState), + VMSTATE_UINT8(pcr, CUDAState), + VMSTATE_UINT8(ifr, CUDAState), + VMSTATE_UINT8(ier, CUDAState), + VMSTATE_UINT8(anh, CUDAState), + VMSTATE_INT32(data_in_size, CUDAState), + VMSTATE_INT32(data_in_index, CUDAState), + VMSTATE_INT32(data_out_index, CUDAState), + VMSTATE_UINT8(autopoll, CUDAState), + VMSTATE_BUFFER(data_in, CUDAState), + VMSTATE_BUFFER(data_out, CUDAState), + VMSTATE_UINT32(tick_offset, CUDAState), + VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1, + vmstate_cuda_timer, CUDATimer), + VMSTATE_END_OF_LIST() + } +}; static void cuda_reset(void *opaque) { @@ -764,6 +740,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq) s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s); *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s, DEVICE_NATIVE_ENDIAN); - register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s); + vmstate_register(NULL, -1, &vmstate_cuda, s); qemu_register_reset(cuda_reset, s); } diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index 61efb3989..cec1cc8e8 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -7,7 +7,6 @@ */ #include "hw.h" -#include "sysemu.h" #include "boards.h" #include "loader.h" #include "elf.h" diff --git a/hw/e1000.c b/hw/e1000.c index fe3e81261..f160bfc2a 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -1220,7 +1220,7 @@ static PCIDeviceInfo e1000_info = { .qdev.vmsd = &vmstate_e1000, .init = pci_e1000_init, .exit = pci_e1000_uninit, - .romfile = "pxe-e1000.bin", + .romfile = "pxe-e1000.rom", .qdev.props = (Property[]) { DEFINE_NIC_PROPERTIES(E1000State, conf), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/eepro100.c b/hw/eepro100.c index edf48f61d..369ad7f84 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -2054,7 +2054,7 @@ static void eepro100_register_devices(void) PCIDeviceInfo *pci_dev = &e100_devices[i].pci; /* We use the same rom file for all device ids. QEMU fixes the device id during rom load. */ - pci_dev->romfile = "gpxe-eepro100-80861209.rom"; + pci_dev->romfile = "pxe-eepro100.rom"; pci_dev->init = e100_nic_init; pci_dev->exit = pci_nic_uninit; pci_dev->qdev.props = e100_properties; diff --git a/hw/empty_slot.c b/hw/empty_slot.c index 664b8d9c4..da8adc4d0 100644 --- a/hw/empty_slot.c +++ b/hw/empty_slot.c @@ -53,18 +53,21 @@ static CPUWriteMemoryFunc * const empty_slot_write[3] = { void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size) { - DeviceState *dev; - SysBusDevice *s; - EmptySlot *e; + if (slot_size > 0) { + /* Only empty slots larger than 0 byte need handling. */ + DeviceState *dev; + SysBusDevice *s; + EmptySlot *e; - dev = qdev_create(NULL, "empty_slot"); - s = sysbus_from_qdev(dev); - e = FROM_SYSBUS(EmptySlot, s); - e->size = slot_size; + dev = qdev_create(NULL, "empty_slot"); + s = sysbus_from_qdev(dev); + e = FROM_SYSBUS(EmptySlot, s); + e->size = slot_size; - qdev_init_nofail(dev); + qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, addr); + sysbus_mmio_map(s, 0, addr); + } } static int empty_slot_init1(SysBusDevice *dev) diff --git a/hw/etraxfs.c b/hw/etraxfs.c index 5ee5f979a..b84d74a11 100644 --- a/hw/etraxfs.c +++ b/hw/etraxfs.c @@ -24,7 +24,6 @@ #include "sysbus.h" #include "boards.h" -#include "sysemu.h" #include "net.h" #include "flash.h" #include "etraxfs.h" diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h deleted file mode 100644 index 126e60e27..000000000 --- a/hw/file-op-9p.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Virtio 9p - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ -#ifndef _FILEOP_H -#define _FILEOP_H -#include <sys/types.h> -#include <dirent.h> -#include <sys/time.h> -#include <utime.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <sys/vfs.h> -#define SM_LOCAL_MODE_BITS 0600 -#define SM_LOCAL_DIR_MODE_BITS 0700 - -typedef enum -{ - /* - * Server will try to set uid/gid. - * On failure ignore the error. - */ - SM_NONE = 0, - /* - * uid/gid set on fileserver files - */ - SM_PASSTHROUGH = 1, - /* - * uid/gid part of xattr - */ - SM_MAPPED, -} SecModel; - -typedef struct FsCred -{ - uid_t fc_uid; - gid_t fc_gid; - mode_t fc_mode; - dev_t fc_rdev; -} FsCred; - -struct xattr_operations; - -typedef struct FsContext -{ - char *fs_root; - SecModel fs_sm; - uid_t uid; - struct xattr_operations **xops; -} FsContext; - -void cred_init(FsCred *); - -typedef struct FileOperations -{ - int (*lstat)(FsContext *, const char *, struct stat *); - ssize_t (*readlink)(FsContext *, const char *, char *, size_t); - int (*chmod)(FsContext *, const char *, FsCred *); - int (*chown)(FsContext *, const char *, FsCred *); - int (*mknod)(FsContext *, const char *, FsCred *); - int (*utimensat)(FsContext *, const char *, const struct timespec *); - int (*remove)(FsContext *, const char *); - int (*symlink)(FsContext *, const char *, const char *, FsCred *); - int (*link)(FsContext *, const char *, const char *); - int (*setuid)(FsContext *, uid_t); - int (*close)(FsContext *, int); - int (*closedir)(FsContext *, DIR *); - DIR *(*opendir)(FsContext *, const char *); - int (*open)(FsContext *, const char *, int); - int (*open2)(FsContext *, const char *, int, FsCred *); - void (*rewinddir)(FsContext *, DIR *); - off_t (*telldir)(FsContext *, DIR *); - struct dirent *(*readdir)(FsContext *, DIR *); - void (*seekdir)(FsContext *, DIR *, off_t); - ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t); - ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t); - int (*mkdir)(FsContext *, const char *, FsCred *); - int (*fstat)(FsContext *, int, struct stat *); - int (*rename)(FsContext *, const char *, const char *); - int (*truncate)(FsContext *, const char *, off_t); - int (*fsync)(FsContext *, int, int); - int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf); - ssize_t (*lgetxattr)(FsContext *, const char *, - const char *, void *, size_t); - ssize_t (*llistxattr)(FsContext *, const char *, void *, size_t); - int (*lsetxattr)(FsContext *, const char *, - const char *, void *, size_t, int); - int (*lremovexattr)(FsContext *, const char *, const char *); - void *opaque; -} FileOperations; - -static inline const char *rpath(FsContext *ctx, const char *path) -{ - /* FIXME: so wrong... */ - static char buffer[4096]; - snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path); - return buffer; -} -#endif diff --git a/hw/flash.h b/hw/flash.h index d7d103e66..c22e1a922 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -21,8 +21,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, typedef struct NANDFlashState NANDFlashState; NANDFlashState *nand_init(int manf_id, int chip_id); void nand_done(NANDFlashState *s); -void nand_setpins(NANDFlashState *s, - int cle, int ale, int ce, int wp, int gnd); +void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, + uint8_t ce, uint8_t wp, uint8_t gnd); void nand_getpins(NANDFlashState *s, int *rb); void nand_setio(NANDFlashState *s, uint8_t value); uint8_t nand_getio(NANDFlashState *s); diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c index 101b150aa..169a56eb1 100644 --- a/hw/grlib_apbuart.c +++ b/hw/grlib_apbuart.c @@ -133,7 +133,7 @@ grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value) break; } - trace_grlib_apbuart_unknown_register("write", addr); + trace_grlib_apbuart_writel_unknown(addr, value); } static CPUReadMemoryFunc * const grlib_apbuart_read[] = { diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c index 596a9000a..99e90336b 100644 --- a/hw/grlib_gptimer.c +++ b/hw/grlib_gptimer.c @@ -165,15 +165,15 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr) /* Unit registers */ switch (addr) { case SCALER_OFFSET: - trace_grlib_gptimer_readl(-1, "scaler:", unit->scaler); + trace_grlib_gptimer_readl(-1, addr, unit->scaler); return unit->scaler; case SCALER_RELOAD_OFFSET: - trace_grlib_gptimer_readl(-1, "reload:", unit->reload); + trace_grlib_gptimer_readl(-1, addr, unit->reload); return unit->reload; case CONFIG_OFFSET: - trace_grlib_gptimer_readl(-1, "config:", unit->config); + trace_grlib_gptimer_readl(-1, addr, unit->config); return unit->config; default: @@ -189,17 +189,16 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr) switch (timer_addr) { case COUNTER_OFFSET: value = ptimer_get_count(unit->timers[id].ptimer); - trace_grlib_gptimer_readl(id, "counter value:", value); + trace_grlib_gptimer_readl(id, addr, value); return value; case COUNTER_RELOAD_OFFSET: value = unit->timers[id].reload; - trace_grlib_gptimer_readl(id, "reload value:", value); + trace_grlib_gptimer_readl(id, addr, value); return value; case CONFIG_OFFSET: - trace_grlib_gptimer_readl(id, "scaler value:", - unit->timers[id].config); + trace_grlib_gptimer_readl(id, addr, unit->timers[id].config); return unit->timers[id].config; default: @@ -208,7 +207,7 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr) } - trace_grlib_gptimer_unknown_register("read", addr); + trace_grlib_gptimer_readl(-1, addr, 0); return 0; } @@ -226,19 +225,19 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value) case SCALER_OFFSET: value &= 0xFFFF; /* clean up the value */ unit->scaler = value; - trace_grlib_gptimer_writel(-1, "scaler:", unit->scaler); + trace_grlib_gptimer_writel(-1, addr, unit->scaler); return; case SCALER_RELOAD_OFFSET: value &= 0xFFFF; /* clean up the value */ unit->reload = value; - trace_grlib_gptimer_writel(-1, "reload:", unit->reload); + trace_grlib_gptimer_writel(-1, addr, unit->reload); grlib_gptimer_set_scaler(unit, value); return; case CONFIG_OFFSET: /* Read Only (disable timer freeze not supported) */ - trace_grlib_gptimer_writel(-1, "config (Read Only):", 0); + trace_grlib_gptimer_writel(-1, addr, 0); return; default: @@ -253,18 +252,18 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value) /* GPTimer registers */ switch (timer_addr) { case COUNTER_OFFSET: - trace_grlib_gptimer_writel(id, "counter:", value); + trace_grlib_gptimer_writel(id, addr, value); unit->timers[id].counter = value; grlib_gptimer_enable(&unit->timers[id]); return; case COUNTER_RELOAD_OFFSET: - trace_grlib_gptimer_writel(id, "reload:", value); + trace_grlib_gptimer_writel(id, addr, value); unit->timers[id].reload = value; return; case CONFIG_OFFSET: - trace_grlib_gptimer_writel(id, "config:", value); + trace_grlib_gptimer_writel(id, addr, value); if (value & GPTIMER_INT_PENDING) { /* clear pending bit */ @@ -297,7 +296,7 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value) } - trace_grlib_gptimer_unknown_register("write", addr); + trace_grlib_gptimer_writel(-1, addr, value); } static CPUReadMemoryFunc * const grlib_gptimer_read[] = { diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c index f47c491a4..b8738fc04 100644 --- a/hw/grlib_irqmp.c +++ b/hw/grlib_irqmp.c @@ -220,7 +220,7 @@ static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr) return state->extended[cpu]; } - trace_grlib_irqmp_unknown_register("read", addr); + trace_grlib_irqmp_readl_unknown(addr); return 0; } @@ -308,7 +308,7 @@ grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value) return; } - trace_grlib_irqmp_unknown_register("write", addr); + trace_grlib_irqmp_writel_unknown(addr, value); } static CPUReadMemoryFunc * const grlib_irqmp_read[] = { diff --git a/hw/gumstix.c b/hw/gumstix.c index ee63f634c..853f7e1ee 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -35,7 +35,6 @@ #include "pxa.h" #include "net.h" #include "flash.h" -#include "sysemu.h" #include "devices.h" #include "boards.h" #include "blockdev.h" diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c index b19b754b3..5fd71a0f7 100644 --- a/hw/heathrow_pic.c +++ b/hw/heathrow_pic.c @@ -159,42 +159,31 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level) heathrow_pic_update(s); } -static void heathrow_pic_save_one(QEMUFile *f, HeathrowPIC *s) -{ - qemu_put_be32s(f, &s->events); - qemu_put_be32s(f, &s->mask); - qemu_put_be32s(f, &s->levels); - qemu_put_be32s(f, &s->level_triggered); -} - -static void heathrow_pic_save(QEMUFile *f, void *opaque) -{ - HeathrowPICS *s = (HeathrowPICS *)opaque; - - heathrow_pic_save_one(f, &s->pics[0]); - heathrow_pic_save_one(f, &s->pics[1]); -} - -static void heathrow_pic_load_one(QEMUFile *f, HeathrowPIC *s) -{ - qemu_get_be32s(f, &s->events); - qemu_get_be32s(f, &s->mask); - qemu_get_be32s(f, &s->levels); - qemu_get_be32s(f, &s->level_triggered); -} - -static int heathrow_pic_load(QEMUFile *f, void *opaque, int version_id) -{ - HeathrowPICS *s = (HeathrowPICS *)opaque; - - if (version_id != 1) - return -EINVAL; - - heathrow_pic_load_one(f, &s->pics[0]); - heathrow_pic_load_one(f, &s->pics[1]); +static const VMStateDescription vmstate_heathrow_pic_one = { + .name = "heathrow_pic_one", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(events, HeathrowPIC), + VMSTATE_UINT32(mask, HeathrowPIC), + VMSTATE_UINT32(levels, HeathrowPIC), + VMSTATE_UINT32(level_triggered, HeathrowPIC), + VMSTATE_END_OF_LIST() + } +}; - return 0; -} +static const VMStateDescription vmstate_heathrow_pic = { + .name = "heathrow_pic", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1, + vmstate_heathrow_pic_one, HeathrowPIC), + VMSTATE_END_OF_LIST() + } +}; static void heathrow_pic_reset_one(HeathrowPIC *s) { @@ -223,8 +212,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index, *pmem_index = cpu_register_io_memory(pic_read, pic_write, s, DEVICE_LITTLE_ENDIAN); - register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save, - heathrow_pic_load, s); + vmstate_register(NULL, -1, &vmstate_heathrow_pic, s); qemu_register_reset(heathrow_pic_reset, s); return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64); } @@ -693,6 +693,17 @@ extern const VMStateDescription vmstate_usb_device; .offset = vmstate_offset_macaddr(_state, _field), \ } +extern const VMStateDescription vmstate_ptimer; + +#define VMSTATE_PTIMER(_field, _state) { \ + .name = (stringify(_field)), \ + .version_id = (1), \ + .vmsd = &vmstate_ptimer, \ + .size = sizeof(ptimer_state *), \ + .flags = VMS_STRUCT|VMS_POINTER, \ + .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \ +} + /* _f : field name _f_n : num of elements field_name _n : num of elements @@ -797,12 +808,6 @@ extern const VMStateDescription vmstate_usb_device; #define VMSTATE_TIMER_ARRAY(_f, _s, _n) \ VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *) -#define VMSTATE_PTIMER_V(_f, _s, _v) \ - VMSTATE_POINTER(_f, _s, _v, vmstate_info_ptimer, ptimer_state *) - -#define VMSTATE_PTIMER(_f, _s) \ - VMSTATE_PTIMER_V(_f, _s, 0) - #define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v) \ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool) diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c new file mode 100644 index 000000000..fe2fb0b80 --- /dev/null +++ b/hw/ide/atapi.c @@ -0,0 +1,1138 @@ +/* + * QEMU ATAPI Emulation + * + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Openedhand Ltd. + * + * 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/ide/internal.h" +#include "hw/scsi.h" + +static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); + +static void padstr8(uint8_t *buf, int buf_size, const char *src) +{ + int i; + for(i = 0; i < buf_size; i++) { + if (*src) + buf[i] = *src++; + else + buf[i] = ' '; + } +} + +static inline void cpu_to_ube16(uint8_t *buf, int val) +{ + buf[0] = val >> 8; + buf[1] = val & 0xff; +} + +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val & 0xff; +} + +static inline int ube16_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 8) | buf[1]; +} + +static inline int ube32_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +static void lba_to_msf(uint8_t *buf, int lba) +{ + lba += 150; + buf[0] = (lba / 75) / 60; + buf[1] = (lba / 75) % 60; + buf[2] = lba % 75; +} + +static inline int media_present(IDEState *s) +{ + return (s->nb_sectors > 0); +} + +/* XXX: DVDs that could fit on a CD will be reported as a CD */ +static inline int media_is_dvd(IDEState *s) +{ + return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS); +} + +static inline int media_is_cd(IDEState *s) +{ + return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS); +} + +static void cd_data_to_raw(uint8_t *buf, int lba) +{ + /* sync bytes */ + buf[0] = 0x00; + memset(buf + 1, 0xff, 10); + buf[11] = 0x00; + buf += 12; + /* MSF */ + lba_to_msf(buf, lba); + buf[3] = 0x01; /* mode 1 data */ + buf += 4; + /* data */ + buf += 2048; + /* XXX: ECC not computed */ + memset(buf, 0, 288); +} + +static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, + int sector_size) +{ + int ret; + + switch(sector_size) { + case 2048: + ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); + break; + case 2352: + ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); + if (ret < 0) + return ret; + cd_data_to_raw(buf, lba); + break; + default: + ret = -EIO; + break; + } + return ret; +} + +void ide_atapi_cmd_ok(IDEState *s) +{ + s->error = 0; + s->status = READY_STAT | SEEK_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s->bus); +} + +void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc) +{ +#ifdef DEBUG_IDE_ATAPI + printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); +#endif + s->error = sense_key << 4; + s->status = READY_STAT | ERR_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + s->sense_key = sense_key; + s->asc = asc; + ide_set_irq(s->bus); +} + +void ide_atapi_io_error(IDEState *s, int ret) +{ + /* XXX: handle more errors */ + if (ret == -ENOMEDIUM) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } else { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + } +} + +/* The whole ATAPI transfer logic is handled in this function */ +void ide_atapi_cmd_reply_end(IDEState *s) +{ + int byte_count_limit, size, ret; +#ifdef DEBUG_IDE_ATAPI + printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", + s->packet_transfer_size, + s->elementary_transfer_size, + s->io_buffer_index); +#endif + if (s->packet_transfer_size <= 0) { + /* end of transfer */ + ide_transfer_stop(s); + s->status = READY_STAT | SEEK_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s->bus); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } else { + /* see if a new sector must be read */ + if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { + ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + if (ret < 0) { + ide_transfer_stop(s); + ide_atapi_io_error(s, ret); + return; + } + s->lba++; + s->io_buffer_index = 0; + } + if (s->elementary_transfer_size > 0) { + /* there are some data left to transmit in this elementary + transfer */ + size = s->cd_sector_size - s->io_buffer_index; + if (size > s->elementary_transfer_size) + size = s->elementary_transfer_size; + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size, + size, ide_atapi_cmd_reply_end); + } else { + /* a new transfer is needed */ + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; + byte_count_limit = s->lcyl | (s->hcyl << 8); +#ifdef DEBUG_IDE_ATAPI + printf("byte_count_limit=%d\n", byte_count_limit); +#endif + if (byte_count_limit == 0xffff) + byte_count_limit--; + size = s->packet_transfer_size; + if (size > byte_count_limit) { + /* byte count limit must be even if this case */ + if (byte_count_limit & 1) + byte_count_limit--; + size = byte_count_limit; + } + s->lcyl = size; + s->hcyl = size >> 8; + s->elementary_transfer_size = size; + /* we cannot transmit more than one sector at a time */ + if (s->lba != -1) { + if (size > (s->cd_sector_size - s->io_buffer_index)) + size = (s->cd_sector_size - s->io_buffer_index); + } + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size, + size, ide_atapi_cmd_reply_end); + ide_set_irq(s->bus); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } + } +} + +/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ +static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) +{ + if (size > max_size) + size = max_size; + s->lba = -1; /* no sector read */ + s->packet_transfer_size = size; + s->io_buffer_size = size; /* dma: send the reply data as one chunk */ + s->elementary_transfer_size = 0; + s->io_buffer_index = 0; + + if (s->atapi_dma) { + s->status = READY_STAT | SEEK_STAT | DRQ_STAT; + s->bus->dma->ops->start_dma(s->bus->dma, s, + ide_atapi_cmd_read_dma_cb); + } else { + s->status = READY_STAT | SEEK_STAT; + ide_atapi_cmd_reply_end(s); + } +} + +/* start a CD-CDROM read command */ +static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->elementary_transfer_size = 0; + s->io_buffer_index = sector_size; + s->cd_sector_size = sector_size; + + s->status = READY_STAT | SEEK_STAT; + ide_atapi_cmd_reply_end(s); +} + +static void ide_atapi_cmd_check_status(IDEState *s) +{ +#ifdef DEBUG_IDE_ATAPI + printf("atapi_cmd_check_status\n"); +#endif + s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4); + s->status = ERR_STAT; + s->nsector = 0; + ide_set_irq(s->bus); +} +/* ATAPI DMA support */ + +/* XXX: handle read errors */ +static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) +{ + IDEState *s = opaque; + int data_offset, n; + + if (ret < 0) { + ide_atapi_io_error(s, ret); + goto eot; + } + + if (s->io_buffer_size > 0) { + /* + * For a cdrom read sector command (s->lba != -1), + * adjust the lba for the next s->io_buffer_size chunk + * and dma the current chunk. + * For a command != read (s->lba == -1), just transfer + * the reply data. + */ + if (s->lba != -1) { + if (s->cd_sector_size == 2352) { + n = 1; + cd_data_to_raw(s->io_buffer, s->lba); + } else { + n = s->io_buffer_size >> 11; + } + s->lba += n; + } + s->packet_transfer_size -= s->io_buffer_size; + if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0) + goto eot; + } + + if (s->packet_transfer_size <= 0) { + s->status = READY_STAT | SEEK_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s->bus); + eot: + s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); + ide_set_inactive(s); + return; + } + + s->io_buffer_index = 0; + if (s->cd_sector_size == 2352) { + n = 1; + s->io_buffer_size = s->cd_sector_size; + data_offset = 16; + } else { + n = s->packet_transfer_size >> 11; + if (n > (IDE_DMA_BUF_SECTORS / 4)) + n = (IDE_DMA_BUF_SECTORS / 4); + s->io_buffer_size = n * 2048; + data_offset = 0; + } +#ifdef DEBUG_AIO + printf("aio_read_cd: lba=%u n=%d\n", s->lba, n); +#endif + s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset); + s->bus->dma->iov.iov_len = n * 4 * 512; + qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1); + s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, + &s->bus->dma->qiov, n * 4, + ide_atapi_cmd_read_dma_cb, s); + if (!s->bus->dma->aiocb) { + /* Note: media not present is the most likely case */ + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + goto eot; + } +} + +/* start a CD-CDROM read command with DMA */ +/* XXX: test if DMA is available */ +static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->io_buffer_index = 0; + s->io_buffer_size = 0; + s->cd_sector_size = sector_size; + + /* XXX: check if BUSY_STAT should be set */ + s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; + s->bus->dma->ops->start_dma(s->bus->dma, s, + ide_atapi_cmd_read_dma_cb); +} + +static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ +#ifdef DEBUG_IDE_ATAPI + printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio", + lba, nb_sectors); +#endif + if (s->atapi_dma) { + ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size); + } else { + ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size); + } +} + +static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index, + uint16_t profile) +{ + uint8_t *buf_profile = buf + 12; /* start of profiles */ + + buf_profile += ((*index) * 4); /* start of indexed profile */ + cpu_to_ube16 (buf_profile, profile); + buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7])); + + /* each profile adds 4 bytes to the response */ + (*index)++; + buf[11] += 4; /* Additional Length */ + + return 4; +} + +static int ide_dvd_read_structure(IDEState *s, int format, + const uint8_t *packet, uint8_t *buf) +{ + switch (format) { + case 0x0: /* Physical format information */ + { + int layer = packet[6]; + uint64_t total_sectors; + + if (layer != 0) + return -ASC_INV_FIELD_IN_CMD_PACKET; + + total_sectors = s->nb_sectors >> 2; + if (total_sectors == 0) { + return -ASC_MEDIUM_NOT_PRESENT; + } + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + cpu_to_ube32(buf + 8, 0); /* start sector */ + cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */ + cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */ + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 2048 + 2); + + /* 2k data + 4 byte header */ + return (2048 + 4); + } + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 4 + 2); + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + return -ASC_INV_FIELD_IN_CMD_PACKET; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 2048 + 2); + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4); + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4); + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4); + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4); + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 16 + 2); + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + return -ASC_INV_FIELD_IN_CMD_PACKET; + } +} + +static unsigned int event_status_media(IDEState *s, + uint8_t *buf) +{ + enum media_event_code { + MEC_NO_CHANGE = 0, /* Status unchanged */ + MEC_EJECT_REQUESTED, /* received a request from user to eject */ + MEC_NEW_MEDIA, /* new media inserted and ready for access */ + MEC_MEDIA_REMOVAL, /* only for media changers */ + MEC_MEDIA_CHANGED, /* only for media changers */ + MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */ + MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */ + }; + enum media_status { + MS_TRAY_OPEN = 1, + MS_MEDIA_PRESENT = 2, + }; + uint8_t event_code, media_status; + + media_status = 0; + if (s->bs->tray_open) { + media_status = MS_TRAY_OPEN; + } else if (bdrv_is_inserted(s->bs)) { + media_status = MS_MEDIA_PRESENT; + } + + /* Event notification descriptor */ + event_code = MEC_NO_CHANGE; + if (media_status != MS_TRAY_OPEN && s->events.new_media) { + event_code = MEC_NEW_MEDIA; + s->events.new_media = false; + } + + buf[4] = event_code; + buf[5] = media_status; + + /* These fields are reserved, just clear them. */ + buf[6] = 0; + buf[7] = 0; + + return 8; /* We wrote to 4 extra bytes from the header */ +} + +static void cmd_get_event_status_notification(IDEState *s, + uint8_t *buf) +{ + const uint8_t *packet = buf; + + struct { + uint8_t opcode; + uint8_t polled; /* lsb bit is polled; others are reserved */ + uint8_t reserved2[2]; + uint8_t class; + uint8_t reserved3[2]; + uint16_t len; + uint8_t control; + } __attribute__((packed)) *gesn_cdb; + + struct { + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; + } __attribute((packed)) *gesn_event_header; + + enum notification_class_request_type { + NCR_RESERVED1 = 1 << 0, + NCR_OPERATIONAL_CHANGE = 1 << 1, + NCR_POWER_MANAGEMENT = 1 << 2, + NCR_EXTERNAL_REQUEST = 1 << 3, + NCR_MEDIA = 1 << 4, + NCR_MULTI_HOST = 1 << 5, + NCR_DEVICE_BUSY = 1 << 6, + NCR_RESERVED2 = 1 << 7, + }; + enum event_notification_class_field { + ENC_NO_EVENTS = 0, + ENC_OPERATIONAL_CHANGE, + ENC_POWER_MANAGEMENT, + ENC_EXTERNAL_REQUEST, + ENC_MEDIA, + ENC_MULTIPLE_HOSTS, + ENC_DEVICE_BUSY, + ENC_RESERVED, + }; + unsigned int max_len, used_len; + + gesn_cdb = (void *)packet; + gesn_event_header = (void *)buf; + + max_len = be16_to_cpu(gesn_cdb->len); + + /* It is fine by the MMC spec to not support async mode operations */ + if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + return; + } + + /* polling mode operation */ + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + */ + gesn_event_header->supported_events = NCR_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->class & NCR_MEDIA) { + gesn_event_header->notification_class |= ENC_MEDIA; + used_len = event_status_media(s, buf); + } else { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = cpu_to_be16(used_len + - sizeof(*gesn_event_header)); + ide_atapi_cmd_reply(s, used_len, max_len); +} + +static void cmd_request_sense(IDEState *s, uint8_t *buf) +{ + int max_len = buf[4]; + + memset(buf, 0, 18); + buf[0] = 0x70 | (1 << 7); + buf[2] = s->sense_key; + buf[7] = 10; + buf[12] = s->asc; + + if (s->sense_key == SENSE_UNIT_ATTENTION) { + s->sense_key = SENSE_NONE; + } + + ide_atapi_cmd_reply(s, 18, max_len); +} + +static void cmd_inquiry(IDEState *s, uint8_t *buf) +{ + int max_len = buf[4]; + + buf[0] = 0x05; /* CD-ROM */ + buf[1] = 0x80; /* removable */ + buf[2] = 0x00; /* ISO */ + buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */ + buf[4] = 31; /* additional length */ + buf[5] = 0; /* reserved */ + buf[6] = 0; /* reserved */ + buf[7] = 0; /* reserved */ + padstr8(buf + 8, 8, "QEMU"); + padstr8(buf + 16, 16, "QEMU DVD-ROM"); + padstr8(buf + 32, 4, s->version); + ide_atapi_cmd_reply(s, 36, max_len); +} + +static void cmd_get_configuration(IDEState *s, uint8_t *buf) +{ + uint32_t len; + uint8_t index = 0; + int max_len; + + /* only feature 0 is supported */ + if (buf[2] != 0 || buf[3] != 0) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + return; + } + + /* XXX: could result in alignment problems in some architectures */ + max_len = ube16_to_cpu(buf + 7); + + /* + * XXX: avoid overflow for io_buffer if max_len is bigger than + * the size of that buffer (dimensioned to max number of + * sectors to transfer at once) + * + * Only a problem if the feature/profiles grow. + */ + if (max_len > 512) { + /* XXX: assume 1 sector */ + max_len = 512; + } + + memset(buf, 0, max_len); + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (media_is_dvd(s)) { + cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); + } else if (media_is_cd(s)) { + cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); + } + + buf[10] = 0x02 | 0x01; /* persistent and current */ + len = 12; /* headers: 8 + 4 */ + len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM); + len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM); + cpu_to_ube32(buf, len - 4); /* data length */ + + ide_atapi_cmd_reply(s, len, max_len); +} + +static void cmd_mode_sense(IDEState *s, uint8_t *buf) +{ + int action, code; + int max_len; + + if (buf[0] == GPCMD_MODE_SENSE_10) { + max_len = ube16_to_cpu(buf + 7); + } else { + max_len = buf[4]; + } + + action = buf[2] >> 6; + code = buf[2] & 0x3f; + + switch(action) { + case 0: /* current values */ + switch(code) { + case GPMODE_R_W_ERROR_PAGE: /* error recovery */ + cpu_to_ube16(&buf[0], 16 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x01; + buf[9] = 0x06; + buf[10] = 0x00; + buf[11] = 0x05; + buf[12] = 0x00; + buf[13] = 0x00; + buf[14] = 0x00; + buf[15] = 0x00; + ide_atapi_cmd_reply(s, 16, max_len); + break; + case GPMODE_AUDIO_CTL_PAGE: + cpu_to_ube16(&buf[0], 24 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + /* Fill with CDROM audio volume */ + buf[17] = 0; + buf[19] = 0; + buf[21] = 0; + buf[23] = 0; + + ide_atapi_cmd_reply(s, 24, max_len); + break; + case GPMODE_CAPABILITIES_PAGE: + cpu_to_ube16(&buf[0], 28 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x2a; + buf[9] = 0x12; + buf[10] = 0x00; + buf[11] = 0x00; + + /* Claim PLAY_AUDIO capability (0x01) since some Linux + code checks for this to automount media. */ + buf[12] = 0x71; + buf[13] = 3 << 5; + buf[14] = (1 << 0) | (1 << 3) | (1 << 5); + if (bdrv_is_locked(s->bs)) + buf[6] |= 1 << 1; + buf[15] = 0x00; + cpu_to_ube16(&buf[16], 706); + buf[18] = 0; + buf[19] = 2; + cpu_to_ube16(&buf[20], 512); + cpu_to_ube16(&buf[22], 706); + buf[24] = 0; + buf[25] = 0; + buf[26] = 0; + buf[27] = 0; + ide_atapi_cmd_reply(s, 28, max_len); + break; + default: + goto error_cmd; + } + break; + case 1: /* changeable values */ + goto error_cmd; + case 2: /* default values */ + goto error_cmd; + default: + case 3: /* saved values */ + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_SAVING_PARAMETERS_NOT_SUPPORTED); + break; + } + return; + +error_cmd: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); +} + +static void cmd_test_unit_ready(IDEState *s, uint8_t *buf) +{ + /* Not Ready Conditions are already handled in ide_atapi_cmd(), so if we + * come here, we know that it's ready. */ + ide_atapi_cmd_ok(s); +} + +static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf) +{ + bdrv_set_locked(s->bs, buf[4] & 1); + ide_atapi_cmd_ok(s); +} + +static void cmd_read(IDEState *s, uint8_t* buf) +{ + int nb_sectors, lba; + + if (buf[0] == GPCMD_READ_10) { + nb_sectors = ube16_to_cpu(buf + 7); + } else { + nb_sectors = ube32_to_cpu(buf + 6); + } + + lba = ube32_to_cpu(buf + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + return; + } + + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); +} + +static void cmd_read_cd(IDEState *s, uint8_t* buf) +{ + int nb_sectors, lba, transfer_request; + + nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8]; + lba = ube32_to_cpu(buf + 2); + + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + return; + } + + transfer_request = buf[9]; + switch(transfer_request & 0xf8) { + case 0x00: + /* nothing */ + ide_atapi_cmd_ok(s); + break; + case 0x10: + /* normal read */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + break; + case 0xf8: + /* read all data */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2352); + break; + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } +} + +static void cmd_seek(IDEState *s, uint8_t* buf) +{ + unsigned int lba; + uint64_t total_sectors = s->nb_sectors >> 2; + + lba = ube32_to_cpu(buf + 2); + if (lba >= total_sectors) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); + return; + } + + ide_atapi_cmd_ok(s); +} + +static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) +{ + int start, eject, sense, err = 0; + start = buf[4] & 1; + eject = (buf[4] >> 1) & 1; + + if (eject) { + err = bdrv_eject(s->bs, !start); + } + + switch (err) { + case 0: + ide_atapi_cmd_ok(s); + break; + case -EBUSY: + sense = SENSE_NOT_READY; + if (bdrv_is_inserted(s->bs)) { + sense = SENSE_ILLEGAL_REQUEST; + } + ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); + break; + default: + ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + break; + } +} + +static void cmd_mechanism_status(IDEState *s, uint8_t* buf) +{ + int max_len = ube16_to_cpu(buf + 8); + + cpu_to_ube16(buf, 0); + /* no current LBA */ + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = 1; + cpu_to_ube16(buf + 6, 0); + ide_atapi_cmd_reply(s, 8, max_len); +} + +static void cmd_read_toc_pma_atip(IDEState *s, uint8_t* buf) +{ + int format, msf, start_track, len; + int max_len; + uint64_t total_sectors = s->nb_sectors >> 2; + + max_len = ube16_to_cpu(buf + 7); + format = buf[9] >> 6; + msf = (buf[1] >> 1) & 1; + start_track = buf[6]; + + switch(format) { + case 0: + len = cdrom_read_toc(total_sectors, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + case 1: + /* multi session : only a single session defined */ + memset(buf, 0, 12); + buf[1] = 0x0a; + buf[2] = 0x01; + buf[3] = 0x01; + ide_atapi_cmd_reply(s, 12, max_len); + break; + case 2: + len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + default: + error_cmd: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + } +} + +static void cmd_read_cdvd_capacity(IDEState *s, uint8_t* buf) +{ + uint64_t total_sectors = s->nb_sectors >> 2; + + /* NOTE: it is really the number of sectors minus 1 */ + cpu_to_ube32(buf, total_sectors - 1); + cpu_to_ube32(buf + 4, 2048); + ide_atapi_cmd_reply(s, 8, 8); +} + +static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf) +{ + int max_len; + int media = buf[1]; + int format = buf[7]; + int ret; + + max_len = ube16_to_cpu(buf + 8); + + if (format < 0xff) { + if (media_is_cd(s)) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INCOMPATIBLE_FORMAT); + return; + } else if (!media_present(s)) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + return; + } + } + + memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ? + IDE_DMA_BUF_SECTORS * 512 + 4 : max_len); + + switch (format) { + case 0x00 ... 0x7f: + case 0xff: + if (media == 0) { + ret = ide_dvd_read_structure(s, format, buf, buf); + + if (ret < 0) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret); + } else { + ide_atapi_cmd_reply(s, ret, max_len); + } + + break; + } + /* TODO: BD support, fall through for now */ + + /* Generic disk structures */ + case 0x80: /* TODO: AACS volume identifier */ + case 0x81: /* TODO: AACS media serial number */ + case 0x82: /* TODO: AACS media identifier */ + case 0x83: /* TODO: AACS media key block */ + case 0x90: /* TODO: List of recognized format layers */ + case 0xc0: /* TODO: Write protection status */ + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } +} + +static void cmd_set_speed(IDEState *s, uint8_t* buf) +{ + ide_atapi_cmd_ok(s); +} + +enum { + /* + * Only commands flagged as ALLOW_UA are allowed to run under a + * unit attention condition. (See MMC-5, section 4.1.6.1) + */ + ALLOW_UA = 0x01, + + /* + * Commands flagged with CHECK_READY can only execute if a medium is present. + * Otherwise they report the Not Ready Condition. (See MMC-5, section + * 4.1.8) + */ + CHECK_READY = 0x02, +}; + +static const struct { + void (*handler)(IDEState *s, uint8_t *buf); + int flags; +} atapi_cmd_table[0x100] = { + [ 0x00 ] = { cmd_test_unit_ready, CHECK_READY }, + [ 0x03 ] = { cmd_request_sense, ALLOW_UA }, + [ 0x12 ] = { cmd_inquiry, ALLOW_UA }, + [ 0x1a ] = { cmd_mode_sense, /* (6) */ 0 }, + [ 0x1b ] = { cmd_start_stop_unit, 0 }, + [ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 }, + [ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY }, + [ 0x28 ] = { cmd_read, /* (10) */ 0 }, + [ 0x2b ] = { cmd_seek, CHECK_READY }, + [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY }, + [ 0x46 ] = { cmd_get_configuration, ALLOW_UA }, + [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA }, + [ 0x5a ] = { cmd_mode_sense, /* (10) */ 0 }, + [ 0xa8 ] = { cmd_read, /* (12) */ 0 }, + [ 0xad ] = { cmd_read_dvd_structure, 0 }, + [ 0xbb ] = { cmd_set_speed, 0 }, + [ 0xbd ] = { cmd_mechanism_status, 0 }, + [ 0xbe ] = { cmd_read_cd, 0 }, +}; + +void ide_atapi_cmd(IDEState *s) +{ + uint8_t *buf; + + buf = s->io_buffer; +#ifdef DEBUG_IDE_ATAPI + { + int i; + printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8)); + for(i = 0; i < ATAPI_PACKET_SIZE; i++) { + printf(" %02x", buf[i]); + } + printf("\n"); + } +#endif + /* + * If there's a UNIT_ATTENTION condition pending, only command flagged with + * ALLOW_UA are allowed to complete. with other commands getting a CHECK + * condition response unless a higher priority status, defined by the drive + * here, is pending. + */ + if (s->sense_key == SENSE_UNIT_ATTENTION && + !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) { + ide_atapi_cmd_check_status(s); + return; + } + /* + * When a CD gets changed, we have to report an ejected state and + * then a loaded state to guests so that they detect tray + * open/close and media change events. Guests that do not use + * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close + * states rely on this behavior. + */ + if (bdrv_is_inserted(s->bs) && s->cdrom_changed) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + + s->cdrom_changed = 0; + s->sense_key = SENSE_UNIT_ATTENTION; + s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED; + return; + } + + /* Report a Not Ready condition if appropriate for the command */ + if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) && + (!media_present(s) || !bdrv_is_inserted(s->bs))) + { + ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + return; + } + + /* Execute the command */ + if (atapi_cmd_table[s->io_buffer[0]].handler) { + atapi_cmd_table[s->io_buffer[0]].handler(s, buf); + return; + } + + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE); +} diff --git a/hw/ide/core.c b/hw/ide/core.c index f028ddb49..90f553b69 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -25,7 +25,6 @@ #include <hw/hw.h> #include <hw/pc.h> #include <hw/pci.h> -#include <hw/scsi.h> #include "qemu-error.h" #include "qemu-timer.h" #include "sysemu.h" @@ -56,23 +55,6 @@ static const int smart_attributes[][12] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -/* XXX: DVDs that could fit on a CD will be reported as a CD */ -static inline int media_present(IDEState *s) -{ - return (s->nb_sectors > 0); -} - -static inline int media_is_dvd(IDEState *s) -{ - return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS); -} - -static inline int media_is_cd(IDEState *s) -{ - return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS); -} - -static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); static int ide_handle_rw_error(IDEState *s, int error, int op); static void padstr(char *str, const char *src, int len) @@ -87,17 +69,6 @@ static void padstr(char *str, const char *src, int len) } } -static void padstr8(uint8_t *buf, int buf_size, const char *src) -{ - int i; - for(i = 0; i < buf_size; i++) { - if (*src) - buf[i] = *src++; - else - buf[i] = ' '; - } -} - static void put_le16(uint16_t *p, unsigned int v) { *p = cpu_to_le16(v); @@ -335,8 +306,8 @@ static inline void ide_abort_command(IDEState *s) } /* prepare data transfer and tell what to do after */ -static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, - EndTransferFunc *end_transfer_func) +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func) { s->end_transfer_func = end_transfer_func; s->data_ptr = buf; @@ -347,7 +318,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, s->bus->dma->ops->start_transfer(s->bus->dma); } -static void ide_transfer_stop(IDEState *s) +void ide_transfer_stop(IDEState *s) { s->end_transfer_func = ide_transfer_stop; s->data_ptr = s->io_buffer; @@ -447,7 +418,7 @@ static void dma_buf_commit(IDEState *s, int is_write) qemu_sglist_destroy(&s->sg); } -static void ide_set_inactive(IDEState *s) +void ide_set_inactive(IDEState *s) { s->bus->dma->aiocb = NULL; s->bus->dma->ops->set_inactive(s->bus->dma); @@ -617,38 +588,6 @@ void ide_sector_write(IDEState *s) } } -void ide_atapi_cmd_ok(IDEState *s) -{ - s->error = 0; - s->status = READY_STAT | SEEK_STAT; - s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; - ide_set_irq(s->bus); -} - -void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc) -{ -#ifdef DEBUG_IDE_ATAPI - printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); -#endif - s->error = sense_key << 4; - s->status = READY_STAT | ERR_STAT; - s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; - s->sense_key = sense_key; - s->asc = asc; - ide_set_irq(s->bus); -} - -static void ide_atapi_cmd_check_status(IDEState *s) -{ -#ifdef DEBUG_IDE_ATAPI - printf("atapi_cmd_check_status\n"); -#endif - s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4); - s->status = ERR_STAT; - s->nsector = 0; - ide_set_irq(s->bus); -} - static void ide_flush_cb(void *opaque, int ret) { IDEState *s = opaque; @@ -679,995 +618,6 @@ void ide_flush_cache(IDEState *s) } } -static inline void cpu_to_ube16(uint8_t *buf, int val) -{ - buf[0] = val >> 8; - buf[1] = val & 0xff; -} - -static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) -{ - buf[0] = val >> 24; - buf[1] = val >> 16; - buf[2] = val >> 8; - buf[3] = val & 0xff; -} - -static inline int ube16_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 8) | buf[1]; -} - -static inline int ube32_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - -static void lba_to_msf(uint8_t *buf, int lba) -{ - lba += 150; - buf[0] = (lba / 75) / 60; - buf[1] = (lba / 75) % 60; - buf[2] = lba % 75; -} - -static void cd_data_to_raw(uint8_t *buf, int lba) -{ - /* sync bytes */ - buf[0] = 0x00; - memset(buf + 1, 0xff, 10); - buf[11] = 0x00; - buf += 12; - /* MSF */ - lba_to_msf(buf, lba); - buf[3] = 0x01; /* mode 1 data */ - buf += 4; - /* data */ - buf += 2048; - /* XXX: ECC not computed */ - memset(buf, 0, 288); -} - -static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, - int sector_size) -{ - int ret; - - switch(sector_size) { - case 2048: - ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); - break; - case 2352: - ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); - if (ret < 0) - return ret; - cd_data_to_raw(buf, lba); - break; - default: - ret = -EIO; - break; - } - return ret; -} - -void ide_atapi_io_error(IDEState *s, int ret) -{ - /* XXX: handle more errors */ - if (ret == -ENOMEDIUM) { - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - } else { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_LOGICAL_BLOCK_OOR); - } -} - -/* The whole ATAPI transfer logic is handled in this function */ -static void ide_atapi_cmd_reply_end(IDEState *s) -{ - int byte_count_limit, size, ret; -#ifdef DEBUG_IDE_ATAPI - printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", - s->packet_transfer_size, - s->elementary_transfer_size, - s->io_buffer_index); -#endif - if (s->packet_transfer_size <= 0) { - /* end of transfer */ - ide_transfer_stop(s); - s->status = READY_STAT | SEEK_STAT; - s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; - ide_set_irq(s->bus); -#ifdef DEBUG_IDE_ATAPI - printf("status=0x%x\n", s->status); -#endif - } else { - /* see if a new sector must be read */ - if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { - ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); - if (ret < 0) { - ide_transfer_stop(s); - ide_atapi_io_error(s, ret); - return; - } - s->lba++; - s->io_buffer_index = 0; - } - if (s->elementary_transfer_size > 0) { - /* there are some data left to transmit in this elementary - transfer */ - size = s->cd_sector_size - s->io_buffer_index; - if (size > s->elementary_transfer_size) - size = s->elementary_transfer_size; - s->packet_transfer_size -= size; - s->elementary_transfer_size -= size; - s->io_buffer_index += size; - ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size, - size, ide_atapi_cmd_reply_end); - } else { - /* a new transfer is needed */ - s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; - byte_count_limit = s->lcyl | (s->hcyl << 8); -#ifdef DEBUG_IDE_ATAPI - printf("byte_count_limit=%d\n", byte_count_limit); -#endif - if (byte_count_limit == 0xffff) - byte_count_limit--; - size = s->packet_transfer_size; - if (size > byte_count_limit) { - /* byte count limit must be even if this case */ - if (byte_count_limit & 1) - byte_count_limit--; - size = byte_count_limit; - } - s->lcyl = size; - s->hcyl = size >> 8; - s->elementary_transfer_size = size; - /* we cannot transmit more than one sector at a time */ - if (s->lba != -1) { - if (size > (s->cd_sector_size - s->io_buffer_index)) - size = (s->cd_sector_size - s->io_buffer_index); - } - s->packet_transfer_size -= size; - s->elementary_transfer_size -= size; - s->io_buffer_index += size; - ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size, - size, ide_atapi_cmd_reply_end); - ide_set_irq(s->bus); -#ifdef DEBUG_IDE_ATAPI - printf("status=0x%x\n", s->status); -#endif - } - } -} - -/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ -static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) -{ - if (size > max_size) - size = max_size; - s->lba = -1; /* no sector read */ - s->packet_transfer_size = size; - s->io_buffer_size = size; /* dma: send the reply data as one chunk */ - s->elementary_transfer_size = 0; - s->io_buffer_index = 0; - - if (s->atapi_dma) { - s->status = READY_STAT | SEEK_STAT | DRQ_STAT; - s->bus->dma->ops->start_dma(s->bus->dma, s, - ide_atapi_cmd_read_dma_cb); - } else { - s->status = READY_STAT | SEEK_STAT; - ide_atapi_cmd_reply_end(s); - } -} - -/* start a CD-CDROM read command */ -static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, - int sector_size) -{ - s->lba = lba; - s->packet_transfer_size = nb_sectors * sector_size; - s->elementary_transfer_size = 0; - s->io_buffer_index = sector_size; - s->cd_sector_size = sector_size; - - s->status = READY_STAT | SEEK_STAT; - ide_atapi_cmd_reply_end(s); -} - -/* ATAPI DMA support */ - -/* XXX: handle read errors */ -static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) -{ - IDEState *s = opaque; - int data_offset, n; - - if (ret < 0) { - ide_atapi_io_error(s, ret); - goto eot; - } - - if (s->io_buffer_size > 0) { - /* - * For a cdrom read sector command (s->lba != -1), - * adjust the lba for the next s->io_buffer_size chunk - * and dma the current chunk. - * For a command != read (s->lba == -1), just transfer - * the reply data. - */ - if (s->lba != -1) { - if (s->cd_sector_size == 2352) { - n = 1; - cd_data_to_raw(s->io_buffer, s->lba); - } else { - n = s->io_buffer_size >> 11; - } - s->lba += n; - } - s->packet_transfer_size -= s->io_buffer_size; - if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0) - goto eot; - } - - if (s->packet_transfer_size <= 0) { - s->status = READY_STAT | SEEK_STAT; - s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; - ide_set_irq(s->bus); - eot: - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); - ide_set_inactive(s); - return; - } - - s->io_buffer_index = 0; - if (s->cd_sector_size == 2352) { - n = 1; - s->io_buffer_size = s->cd_sector_size; - data_offset = 16; - } else { - n = s->packet_transfer_size >> 11; - if (n > (IDE_DMA_BUF_SECTORS / 4)) - n = (IDE_DMA_BUF_SECTORS / 4); - s->io_buffer_size = n * 2048; - data_offset = 0; - } -#ifdef DEBUG_AIO - printf("aio_read_cd: lba=%u n=%d\n", s->lba, n); -#endif - s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset); - s->bus->dma->iov.iov_len = n * 4 * 512; - qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1); - s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, - &s->bus->dma->qiov, n * 4, - ide_atapi_cmd_read_dma_cb, s); - if (!s->bus->dma->aiocb) { - /* Note: media not present is the most likely case */ - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - goto eot; - } -} - -/* start a CD-CDROM read command with DMA */ -/* XXX: test if DMA is available */ -static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, - int sector_size) -{ - s->lba = lba; - s->packet_transfer_size = nb_sectors * sector_size; - s->io_buffer_index = 0; - s->io_buffer_size = 0; - s->cd_sector_size = sector_size; - - /* XXX: check if BUSY_STAT should be set */ - s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; - s->bus->dma->ops->start_dma(s->bus->dma, s, - ide_atapi_cmd_read_dma_cb); -} - -static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, - int sector_size) -{ -#ifdef DEBUG_IDE_ATAPI - printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio", - lba, nb_sectors); -#endif - if (s->atapi_dma) { - ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size); - } else { - ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size); - } -} - -static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index, - uint16_t profile) -{ - uint8_t *buf_profile = buf + 12; /* start of profiles */ - - buf_profile += ((*index) * 4); /* start of indexed profile */ - cpu_to_ube16 (buf_profile, profile); - buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7])); - - /* each profile adds 4 bytes to the response */ - (*index)++; - buf[11] += 4; /* Additional Length */ - - return 4; -} - -static int ide_dvd_read_structure(IDEState *s, int format, - const uint8_t *packet, uint8_t *buf) -{ - switch (format) { - case 0x0: /* Physical format information */ - { - int layer = packet[6]; - uint64_t total_sectors; - - if (layer != 0) - return -ASC_INV_FIELD_IN_CMD_PACKET; - - bdrv_get_geometry(s->bs, &total_sectors); - total_sectors >>= 2; - if (total_sectors == 0) - return -ASC_MEDIUM_NOT_PRESENT; - - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - cpu_to_ube32(buf + 8, 0); /* start sector */ - cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */ - cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */ - - /* Size of buffer, not including 2 byte size field */ - cpu_to_be16wu((uint16_t *)buf, 2048 + 2); - - /* 2k data + 4 byte header */ - return (2048 + 4); - } - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - cpu_to_be16wu((uint16_t *)buf, 4 + 2); - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - return -ASC_INV_FIELD_IN_CMD_PACKET; - - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - cpu_to_be16wu((uint16_t *)buf, 2048 + 2); - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4); - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4); - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4); - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4); - - /* Size of buffer, not including 2 byte size field */ - cpu_to_be16wu((uint16_t *)buf, 16 + 2); - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - return -ASC_INV_FIELD_IN_CMD_PACKET; - } -} - -static unsigned int event_status_media(IDEState *s, - uint8_t *buf) -{ - enum media_event_code { - MEC_NO_CHANGE = 0, /* Status unchanged */ - MEC_EJECT_REQUESTED, /* received a request from user to eject */ - MEC_NEW_MEDIA, /* new media inserted and ready for access */ - MEC_MEDIA_REMOVAL, /* only for media changers */ - MEC_MEDIA_CHANGED, /* only for media changers */ - MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */ - MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */ - }; - enum media_status { - MS_TRAY_OPEN = 1, - MS_MEDIA_PRESENT = 2, - }; - uint8_t event_code, media_status; - - media_status = 0; - if (s->bs->tray_open) { - media_status = MS_TRAY_OPEN; - } else if (bdrv_is_inserted(s->bs)) { - media_status = MS_MEDIA_PRESENT; - } - - /* Event notification descriptor */ - event_code = MEC_NO_CHANGE; - if (media_status != MS_TRAY_OPEN && s->events.new_media) { - event_code = MEC_NEW_MEDIA; - s->events.new_media = false; - } - - buf[4] = event_code; - buf[5] = media_status; - - /* These fields are reserved, just clear them. */ - buf[6] = 0; - buf[7] = 0; - - return 8; /* We wrote to 4 extra bytes from the header */ -} - -static void handle_get_event_status_notification(IDEState *s, - uint8_t *buf, - const uint8_t *packet) -{ - struct { - uint8_t opcode; - uint8_t polled; /* lsb bit is polled; others are reserved */ - uint8_t reserved2[2]; - uint8_t class; - uint8_t reserved3[2]; - uint16_t len; - uint8_t control; - } __attribute__((packed)) *gesn_cdb; - - struct { - uint16_t len; - uint8_t notification_class; - uint8_t supported_events; - } __attribute((packed)) *gesn_event_header; - - enum notification_class_request_type { - NCR_RESERVED1 = 1 << 0, - NCR_OPERATIONAL_CHANGE = 1 << 1, - NCR_POWER_MANAGEMENT = 1 << 2, - NCR_EXTERNAL_REQUEST = 1 << 3, - NCR_MEDIA = 1 << 4, - NCR_MULTI_HOST = 1 << 5, - NCR_DEVICE_BUSY = 1 << 6, - NCR_RESERVED2 = 1 << 7, - }; - enum event_notification_class_field { - ENC_NO_EVENTS = 0, - ENC_OPERATIONAL_CHANGE, - ENC_POWER_MANAGEMENT, - ENC_EXTERNAL_REQUEST, - ENC_MEDIA, - ENC_MULTIPLE_HOSTS, - ENC_DEVICE_BUSY, - ENC_RESERVED, - }; - unsigned int max_len, used_len; - - gesn_cdb = (void *)packet; - gesn_event_header = (void *)buf; - - max_len = be16_to_cpu(gesn_cdb->len); - - /* It is fine by the MMC spec to not support async mode operations */ - if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - return; - } - - /* polling mode operation */ - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - */ - gesn_event_header->supported_events = NCR_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & NCR_MEDIA) { - gesn_event_header->notification_class |= ENC_MEDIA; - used_len = event_status_media(s, buf); - } else { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = cpu_to_be16(used_len - - sizeof(*gesn_event_header)); - ide_atapi_cmd_reply(s, used_len, max_len); -} - -static void ide_atapi_cmd(IDEState *s) -{ - const uint8_t *packet; - uint8_t *buf; - int max_len; - - packet = s->io_buffer; - buf = s->io_buffer; -#ifdef DEBUG_IDE_ATAPI - { - int i; - printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8)); - for(i = 0; i < ATAPI_PACKET_SIZE; i++) { - printf(" %02x", packet[i]); - } - printf("\n"); - } -#endif - /* - * If there's a UNIT_ATTENTION condition pending, only - * REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and - * GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete. - * MMC-5, section 4.1.6.1 lists only these commands being allowed - * to complete, with other commands getting a CHECK condition - * response unless a higher priority status, defined by the drive - * here, is pending. - */ - if (s->sense_key == SENSE_UNIT_ATTENTION && - s->io_buffer[0] != GPCMD_REQUEST_SENSE && - s->io_buffer[0] != GPCMD_INQUIRY && - s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) { - ide_atapi_cmd_check_status(s); - return; - } - switch(s->io_buffer[0]) { - case GPCMD_TEST_UNIT_READY: - if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) { - ide_atapi_cmd_ok(s); - } else { - s->cdrom_changed = 0; - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - } - break; - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - { - int action, code; - if (packet[0] == GPCMD_MODE_SENSE_10) - max_len = ube16_to_cpu(packet + 7); - else - max_len = packet[4]; - action = packet[2] >> 6; - code = packet[2] & 0x3f; - switch(action) { - case 0: /* current values */ - switch(code) { - case GPMODE_R_W_ERROR_PAGE: /* error recovery */ - cpu_to_ube16(&buf[0], 16 + 6); - buf[2] = 0x70; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - - buf[8] = 0x01; - buf[9] = 0x06; - buf[10] = 0x00; - buf[11] = 0x05; - buf[12] = 0x00; - buf[13] = 0x00; - buf[14] = 0x00; - buf[15] = 0x00; - ide_atapi_cmd_reply(s, 16, max_len); - break; - case GPMODE_AUDIO_CTL_PAGE: - cpu_to_ube16(&buf[0], 24 + 6); - buf[2] = 0x70; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - - /* Fill with CDROM audio volume */ - buf[17] = 0; - buf[19] = 0; - buf[21] = 0; - buf[23] = 0; - - ide_atapi_cmd_reply(s, 24, max_len); - break; - case GPMODE_CAPABILITIES_PAGE: - cpu_to_ube16(&buf[0], 28 + 6); - buf[2] = 0x70; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - - buf[8] = 0x2a; - buf[9] = 0x12; - buf[10] = 0x00; - buf[11] = 0x00; - - /* Claim PLAY_AUDIO capability (0x01) since some Linux - code checks for this to automount media. */ - buf[12] = 0x71; - buf[13] = 3 << 5; - buf[14] = (1 << 0) | (1 << 3) | (1 << 5); - if (bdrv_is_locked(s->bs)) - buf[6] |= 1 << 1; - buf[15] = 0x00; - cpu_to_ube16(&buf[16], 706); - buf[18] = 0; - buf[19] = 2; - cpu_to_ube16(&buf[20], 512); - cpu_to_ube16(&buf[22], 706); - buf[24] = 0; - buf[25] = 0; - buf[26] = 0; - buf[27] = 0; - ide_atapi_cmd_reply(s, 28, max_len); - break; - default: - goto error_cmd; - } - break; - case 1: /* changeable values */ - goto error_cmd; - case 2: /* default values */ - goto error_cmd; - default: - case 3: /* saved values */ - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_SAVING_PARAMETERS_NOT_SUPPORTED); - break; - } - } - break; - case GPCMD_REQUEST_SENSE: - max_len = packet[4]; - memset(buf, 0, 18); - buf[0] = 0x70 | (1 << 7); - buf[2] = s->sense_key; - buf[7] = 10; - buf[12] = s->asc; - if (s->sense_key == SENSE_UNIT_ATTENTION) - s->sense_key = SENSE_NONE; - ide_atapi_cmd_reply(s, 18, max_len); - break; - case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - bdrv_set_locked(s->bs, packet[4] & 1); - ide_atapi_cmd_ok(s); - break; - case GPCMD_READ_10: - case GPCMD_READ_12: - { - int nb_sectors, lba; - - if (packet[0] == GPCMD_READ_10) - nb_sectors = ube16_to_cpu(packet + 7); - else - nb_sectors = ube32_to_cpu(packet + 6); - lba = ube32_to_cpu(packet + 2); - if (nb_sectors == 0) { - ide_atapi_cmd_ok(s); - break; - } - ide_atapi_cmd_read(s, lba, nb_sectors, 2048); - } - break; - case GPCMD_READ_CD: - { - int nb_sectors, lba, transfer_request; - - nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; - lba = ube32_to_cpu(packet + 2); - if (nb_sectors == 0) { - ide_atapi_cmd_ok(s); - break; - } - transfer_request = packet[9]; - switch(transfer_request & 0xf8) { - case 0x00: - /* nothing */ - ide_atapi_cmd_ok(s); - break; - case 0x10: - /* normal read */ - ide_atapi_cmd_read(s, lba, nb_sectors, 2048); - break; - case 0xf8: - /* read all data */ - ide_atapi_cmd_read(s, lba, nb_sectors, 2352); - break; - default: - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - break; - } - } - break; - case GPCMD_SEEK: - { - unsigned int lba; - uint64_t total_sectors; - - bdrv_get_geometry(s->bs, &total_sectors); - total_sectors >>= 2; - if (total_sectors == 0) { - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - break; - } - lba = ube32_to_cpu(packet + 2); - if (lba >= total_sectors) { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_LOGICAL_BLOCK_OOR); - break; - } - ide_atapi_cmd_ok(s); - } - break; - case GPCMD_START_STOP_UNIT: - { - int start, eject, sense, err = 0; - start = packet[4] & 1; - eject = (packet[4] >> 1) & 1; - - if (eject) { - err = bdrv_eject(s->bs, !start); - } - - switch (err) { - case 0: - ide_atapi_cmd_ok(s); - break; - case -EBUSY: - sense = SENSE_NOT_READY; - if (bdrv_is_inserted(s->bs)) { - sense = SENSE_ILLEGAL_REQUEST; - } - ide_atapi_cmd_error(s, sense, - ASC_MEDIA_REMOVAL_PREVENTED); - break; - default: - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - break; - } - } - break; - case GPCMD_MECHANISM_STATUS: - { - max_len = ube16_to_cpu(packet + 8); - cpu_to_ube16(buf, 0); - /* no current LBA */ - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 1; - cpu_to_ube16(buf + 6, 0); - ide_atapi_cmd_reply(s, 8, max_len); - } - break; - case GPCMD_READ_TOC_PMA_ATIP: - { - int format, msf, start_track, len; - uint64_t total_sectors; - - bdrv_get_geometry(s->bs, &total_sectors); - total_sectors >>= 2; - if (total_sectors == 0) { - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - break; - } - max_len = ube16_to_cpu(packet + 7); - format = packet[9] >> 6; - msf = (packet[1] >> 1) & 1; - start_track = packet[6]; - switch(format) { - case 0: - len = cdrom_read_toc(total_sectors, buf, msf, start_track); - if (len < 0) - goto error_cmd; - ide_atapi_cmd_reply(s, len, max_len); - break; - case 1: - /* multi session : only a single session defined */ - memset(buf, 0, 12); - buf[1] = 0x0a; - buf[2] = 0x01; - buf[3] = 0x01; - ide_atapi_cmd_reply(s, 12, max_len); - break; - case 2: - len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track); - if (len < 0) - goto error_cmd; - ide_atapi_cmd_reply(s, len, max_len); - break; - default: - error_cmd: - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - break; - } - } - break; - case GPCMD_READ_CDVD_CAPACITY: - { - uint64_t total_sectors; - - bdrv_get_geometry(s->bs, &total_sectors); - total_sectors >>= 2; - if (total_sectors == 0) { - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - break; - } - /* NOTE: it is really the number of sectors minus 1 */ - cpu_to_ube32(buf, total_sectors - 1); - cpu_to_ube32(buf + 4, 2048); - ide_atapi_cmd_reply(s, 8, 8); - } - break; - case GPCMD_READ_DVD_STRUCTURE: - { - int media = packet[1]; - int format = packet[7]; - int ret; - - max_len = ube16_to_cpu(packet + 8); - - if (format < 0xff) { - if (media_is_cd(s)) { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INCOMPATIBLE_FORMAT); - break; - } else if (!media_present(s)) { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - break; - } - } - - memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ? - IDE_DMA_BUF_SECTORS * 512 + 4 : max_len); - - switch (format) { - case 0x00 ... 0x7f: - case 0xff: - if (media == 0) { - ret = ide_dvd_read_structure(s, format, packet, buf); - - if (ret < 0) - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret); - else - ide_atapi_cmd_reply(s, ret, max_len); - - break; - } - /* TODO: BD support, fall through for now */ - - /* Generic disk structures */ - case 0x80: /* TODO: AACS volume identifier */ - case 0x81: /* TODO: AACS media serial number */ - case 0x82: /* TODO: AACS media identifier */ - case 0x83: /* TODO: AACS media key block */ - case 0x90: /* TODO: List of recognized format layers */ - case 0xc0: /* TODO: Write protection status */ - default: - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - break; - } - } - break; - case GPCMD_SET_SPEED: - ide_atapi_cmd_ok(s); - break; - case GPCMD_INQUIRY: - max_len = packet[4]; - buf[0] = 0x05; /* CD-ROM */ - buf[1] = 0x80; /* removable */ - buf[2] = 0x00; /* ISO */ - buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */ - buf[4] = 31; /* additional length */ - buf[5] = 0; /* reserved */ - buf[6] = 0; /* reserved */ - buf[7] = 0; /* reserved */ - padstr8(buf + 8, 8, "QEMU"); - padstr8(buf + 16, 16, "QEMU DVD-ROM"); - padstr8(buf + 32, 4, s->version); - ide_atapi_cmd_reply(s, 36, max_len); - break; - case GPCMD_GET_CONFIGURATION: - { - uint32_t len; - uint8_t index = 0; - - /* only feature 0 is supported */ - if (packet[2] != 0 || packet[3] != 0) { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - break; - } - - /* XXX: could result in alignment problems in some architectures */ - max_len = ube16_to_cpu(packet + 7); - - /* - * XXX: avoid overflow for io_buffer if max_len is bigger than - * the size of that buffer (dimensioned to max number of - * sectors to transfer at once) - * - * Only a problem if the feature/profiles grow. - */ - if (max_len > 512) /* XXX: assume 1 sector */ - max_len = 512; - - memset(buf, 0, max_len); - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (media_is_dvd(s)) - cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); - else if (media_is_cd(s)) - cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); - - buf[10] = 0x02 | 0x01; /* persistent and current */ - len = 12; /* headers: 8 + 4 */ - len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM); - len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM); - cpu_to_ube32(buf, len - 4); /* data length */ - - ide_atapi_cmd_reply(s, len, max_len); - break; - } - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - handle_get_event_status_notification(s, buf, packet); - break; - default: - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_ILLEGAL_OPCODE); - break; - } -} - static void ide_cfata_metadata_inquiry(IDEState *s) { uint16_t *p; @@ -1734,8 +684,13 @@ static void cdrom_change_cb(void *opaque, int reason) bdrv_get_geometry(s->bs, &nb_sectors); s->nb_sectors = nb_sectors; - s->sense_key = SENSE_UNIT_ATTENTION; - s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED; + /* + * First indicate to the guest that a CD has been removed. That's + * done on the next command the guest sends us. + * + * Then we set SENSE_UNIT_ATTENTION, by which the guest will + * detect a new CD in the drive. See ide_atapi_cmd() for details. + */ s->cdrom_changed = 1; s->events.new_media = true; ide_set_irq(s->bus); diff --git a/hw/ide/ich.c b/hw/ide/ich.c index f242d7a81..a3d475c59 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -67,7 +67,6 @@ #include <hw/isa.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/pci.h> diff --git a/hw/ide/internal.h b/hw/ide/internal.h index ba7e9a8ee..aa198b6b1 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -9,6 +9,7 @@ #include <hw/ide.h> #include "block_int.h" #include "iorange.h" +#include "dma.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -570,6 +571,15 @@ void ide_sector_write(IDEState *s); void ide_sector_read(IDEState *s); void ide_flush_cache(IDEState *s); +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func); +void ide_transfer_stop(IDEState *s); +void ide_set_inactive(IDEState *s); + +/* hw/ide/atapi.c */ +void ide_atapi_cmd(IDEState *s); +void ide_atapi_cmd_reply_end(IDEState *s); + /* hw/ide/qdev.c */ void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 8c59c5a47..4ac745324 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -27,7 +27,6 @@ #include <hw/isa.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/macio.c b/hw/ide/macio.c index c1b4caab5..7107f6b3c 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -27,7 +27,6 @@ #include <hw/mac_dbdma.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 2ceeb87c0..9fbbf0e78 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -27,7 +27,6 @@ #include <hw/pcmcia.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 82b24b673..10f6f4063 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -25,7 +25,6 @@ #include <hw/hw.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 35168cb46..65cb56c38 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -28,7 +28,6 @@ #include <hw/isa.h> #include "block.h" #include "block_int.h" -#include "sysemu.h" #include "dma.h" #include <hw/ide/pci.h> diff --git a/hw/integratorcp.c b/hw/integratorcp.c index b04994082..a6c27be82 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -10,7 +10,6 @@ #include "sysbus.h" #include "primecell.h" #include "devices.h" -#include "sysemu.h" #include "boards.h" #include "arm-misc.h" #include "net.h" diff --git a/hw/ioapic.c b/hw/ioapic.c index e806822d9..2ac612711 100644 --- a/hw/ioapic.c +++ b/hw/ioapic.c @@ -163,8 +163,9 @@ static void ioapic_set_irq(void *opaque, int vector, int level) s->irr &= ~mask; } } else { - /* edge triggered */ - if (level) { + /* According to the 82093AA manual, we must ignore edge requests + * if the input pin is masked. */ + if (level && !(entry & IOAPIC_LVT_MASKED)) { s->irr |= mask; ioapic_service(s); } diff --git a/hw/isa-bus.c b/hw/isa-bus.c index d07aa410f..27655436a 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -17,7 +17,6 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "hw.h" -#include "sysemu.h" #include "monitor.h" #include "sysbus.h" #include "isa.h" diff --git a/hw/kvmclock.c b/hw/kvmclock.c index b6ceddfba..004c4add8 100644 --- a/hw/kvmclock.c +++ b/hw/kvmclock.c @@ -103,7 +103,11 @@ static SysBusDeviceInfo kvmclock_info = { void kvmclock_create(void) { if (kvm_enabled() && - first_cpu->cpuid_kvm_features & (1ULL << KVM_FEATURE_CLOCKSOURCE)) { + first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE) +#ifdef KVM_FEATURE_CLOCKSOURCE2 + || (1ULL << KVM_FEATURE_CLOCKSOURCE2) +#endif + )) { sysbus_create_simple("kvmclock", -1, NULL); } } diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index 85190f0bf..64629230c 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -21,7 +21,6 @@ #include "hw.h" #include "net.h" #include "flash.h" -#include "sysemu.h" #include "devices.h" #include "boards.h" #include "loader.h" diff --git a/hw/m48t59.c b/hw/m48t59.c index 9f39d6bbf..537c0f7b1 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -585,28 +585,18 @@ static CPUReadMemoryFunc * const nvram_read[] = { &nvram_readl, }; -static void m48t59_save(QEMUFile *f, void *opaque) -{ - M48t59State *s = opaque; - - qemu_put_8s(f, &s->lock); - qemu_put_be16s(f, &s->addr); - qemu_put_buffer(f, s->buffer, s->size); -} - -static int m48t59_load(QEMUFile *f, void *opaque, int version_id) -{ - M48t59State *s = opaque; - - if (version_id != 1) - return -EINVAL; - - qemu_get_8s(f, &s->lock); - qemu_get_be16s(f, &s->addr); - qemu_get_buffer(f, s->buffer, s->size); - - return 0; -} +static const VMStateDescription vmstate_m48t59 = { + .name = "m48t59", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(lock, M48t59State), + VMSTATE_UINT16(addr, M48t59State), + VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size), + VMSTATE_END_OF_LIST() + } +}; static void m48t59_reset_common(M48t59State *NVRAM) { @@ -696,7 +686,7 @@ static void m48t59_init_common(M48t59State *s) } qemu_get_timedate(&s->alarm, 0); - register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s); + vmstate_register(NULL, -1, &vmstate_m48t59, s); } static int m48t59_init_isa1(ISADevice *dev) diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index 5680fa9c1..ed4458e3b 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -165,6 +165,10 @@ typedef struct DBDMA_channel { int processing; } DBDMA_channel; +typedef struct { + DBDMA_channel channels[DBDMA_CHANNELS]; +} DBDMAState; + #ifdef DEBUG_DBDMA static void dump_dbdma_cmd(dbdma_cmd *cmd) { @@ -617,31 +621,34 @@ static void channel_run(DBDMA_channel *ch) } } -static void DBDMA_run (DBDMA_channel *ch) +static void DBDMA_run(DBDMAState *s) { int channel; - for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) { - uint32_t status = ch->regs[DBDMA_STATUS]; - if (!ch->processing && (status & RUN) && (status & ACTIVE)) - channel_run(ch); + for (channel = 0; channel < DBDMA_CHANNELS; channel++) { + DBDMA_channel *ch = &s->channels[channel]; + uint32_t status = ch->regs[DBDMA_STATUS]; + if (!ch->processing && (status & RUN) && (status & ACTIVE)) { + channel_run(ch); + } } } static void DBDMA_run_bh(void *opaque) { - DBDMA_channel *ch = opaque; + DBDMAState *s = opaque; DBDMA_DPRINTF("DBDMA_run_bh\n"); - DBDMA_run(ch); + DBDMA_run(s); } void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMA_rw rw, DBDMA_flush flush, void *opaque) { - DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan; + DBDMAState *s = dbdma; + DBDMA_channel *ch = &s->channels[nchan]; DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); @@ -700,7 +707,8 @@ static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { int channel = addr >> DBDMA_CHANNEL_SHIFT; - DBDMA_channel *ch = (DBDMA_channel *)opaque + channel; + DBDMAState *s = opaque; + DBDMA_channel *ch = &s->channels[channel]; int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value); @@ -749,7 +757,8 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr) { uint32_t value; int channel = addr >> DBDMA_CHANNEL_SHIFT; - DBDMA_channel *ch = (DBDMA_channel *)opaque + channel; + DBDMAState *s = opaque; + DBDMA_channel *ch = &s->channels[channel]; int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; value = ch->regs[reg]; @@ -801,49 +810,47 @@ static CPUReadMemoryFunc * const dbdma_read[] = { dbdma_readl, }; -static void dbdma_save(QEMUFile *f, void *opaque) -{ - DBDMA_channel *s = opaque; - unsigned int i, j; - - for (i = 0; i < DBDMA_CHANNELS; i++) - for (j = 0; j < DBDMA_REGS; j++) - qemu_put_be32s(f, &s[i].regs[j]); -} - -static int dbdma_load(QEMUFile *f, void *opaque, int version_id) -{ - DBDMA_channel *s = opaque; - unsigned int i, j; - - if (version_id != 2) - return -EINVAL; - - for (i = 0; i < DBDMA_CHANNELS; i++) - for (j = 0; j < DBDMA_REGS; j++) - qemu_get_be32s(f, &s[i].regs[j]); +static const VMStateDescription vmstate_dbdma_channel = { + .name = "dbdma_channel", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS), + VMSTATE_END_OF_LIST() + } +}; - return 0; -} +static const VMStateDescription vmstate_dbdma = { + .name = "dbdma", + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1, + vmstate_dbdma_channel, DBDMA_channel), + VMSTATE_END_OF_LIST() + } +}; static void dbdma_reset(void *opaque) { - DBDMA_channel *s = opaque; + DBDMAState *s = opaque; int i; for (i = 0; i < DBDMA_CHANNELS; i++) - memset(s[i].regs, 0, DBDMA_SIZE); + memset(s->channels[i].regs, 0, DBDMA_SIZE); } void* DBDMA_init (int *dbdma_mem_index) { - DBDMA_channel *s; + DBDMAState *s; - s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS); + s = qemu_mallocz(sizeof(DBDMAState)); *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s, DEVICE_LITTLE_ENDIAN); - register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s); + vmstate_register(NULL, -1, &vmstate_dbdma, s); qemu_register_reset(dbdma_reset, s); dbdma_bh = qemu_bh_new(DBDMA_run_bh, s); diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index c2a2fc21e..61e53d28b 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -38,7 +38,7 @@ #endif struct MacIONVRAMState { - target_phys_addr_t size; + uint32_t size; int mem_index; unsigned int it_shift; uint8_t *data; @@ -105,24 +105,17 @@ static CPUReadMemoryFunc * const nvram_read[] = { &macio_nvram_readb, }; -static void macio_nvram_save(QEMUFile *f, void *opaque) -{ - MacIONVRAMState *s = (MacIONVRAMState *)opaque; - - qemu_put_buffer(f, s->data, s->size); -} - -static int macio_nvram_load(QEMUFile *f, void *opaque, int version_id) -{ - MacIONVRAMState *s = (MacIONVRAMState *)opaque; - - if (version_id != 1) - return -EINVAL; - - qemu_get_buffer(f, s->data, s->size); +static const VMStateDescription vmstate_macio_nvram = { + .name = "macio_nvram", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size), + VMSTATE_END_OF_LIST() + } +}; - return 0; -} static void macio_nvram_reset(void *opaque) { @@ -141,8 +134,7 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size, s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s, DEVICE_NATIVE_ENDIAN); *mem_index = s->mem_index; - register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save, - macio_nvram_load, s); + vmstate_register(NULL, -1, &vmstate_macio_nvram, s); qemu_register_reset(macio_nvram_reset, s); return s; diff --git a/hw/mainstone.c b/hw/mainstone.c index 50691ca41..4792f0e3e 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -14,7 +14,6 @@ #include "net.h" #include "devices.h" #include "boards.h" -#include "sysemu.h" #include "flash.h" #include "blockdev.h" #include "sysbus.h" diff --git a/hw/max111x.c b/hw/max111x.c index 2844665ba..70cd1af24 100644 --- a/hw/max111x.c +++ b/hw/max111x.c @@ -15,7 +15,7 @@ typedef struct { uint8_t tb1, rb2, rb3; int cycle; - int input[8]; + uint8_t input[8]; int inputs, com; } MAX111xState; @@ -94,36 +94,22 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) return max111x_read(s); } -static void max111x_save(QEMUFile *f, void *opaque) -{ - MAX111xState *s = (MAX111xState *) opaque; - int i; - - qemu_put_8s(f, &s->tb1); - qemu_put_8s(f, &s->rb2); - qemu_put_8s(f, &s->rb3); - qemu_put_be32(f, s->inputs); - qemu_put_be32(f, s->com); - for (i = 0; i < s->inputs; i ++) - qemu_put_byte(f, s->input[i]); -} - -static int max111x_load(QEMUFile *f, void *opaque, int version_id) -{ - MAX111xState *s = (MAX111xState *) opaque; - int i; - - qemu_get_8s(f, &s->tb1); - qemu_get_8s(f, &s->rb2); - qemu_get_8s(f, &s->rb3); - if (s->inputs != qemu_get_be32(f)) - return -EINVAL; - s->com = qemu_get_be32(f); - for (i = 0; i < s->inputs; i ++) - s->input[i] = qemu_get_byte(f); - - return 0; -} +static const VMStateDescription vmstate_max111x = { + .name = "max111x", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8(tb1, MAX111xState), + VMSTATE_UINT8(rb2, MAX111xState), + VMSTATE_UINT8(rb3, MAX111xState), + VMSTATE_INT32_EQUAL(inputs, MAX111xState), + VMSTATE_INT32(com, MAX111xState), + VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs, + vmstate_info_uint8, uint8_t), + VMSTATE_END_OF_LIST() + } +}; static int max111x_init(SSISlave *dev, int inputs) { @@ -143,8 +129,7 @@ static int max111x_init(SSISlave *dev, int inputs) s->input[7] = 0x80; s->com = 0; - register_savevm(&dev->qdev, "max111x", -1, 0, - max111x_save, max111x_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_max111x, s); return 0; } diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h index 15acdbccd..20de68ecc 100644 --- a/hw/milkymist-hw.h +++ b/hw/milkymist-hw.h @@ -1,6 +1,9 @@ #ifndef QEMU_HW_MILKYMIST_H #define QEMU_HW_MILKYMIST_H +#include "qdev.h" +#include "qdev-addr.h" + static inline DeviceState *milkymist_uart_create(target_phys_addr_t base, qemu_irq rx_irq, qemu_irq tx_irq) { @@ -183,6 +186,23 @@ static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base, return dev; } +static inline DeviceState *milkymist_minimac2_create(target_phys_addr_t base, + target_phys_addr_t buffers_base, qemu_irq rx_irq, qemu_irq tx_irq) +{ + DeviceState *dev; + + qemu_check_nic_model(&nd_table[0], "minimac2"); + dev = qdev_create(NULL, "milkymist-minimac2"); + qdev_prop_set_taddr(dev, "buffers_base", buffers_base); + qdev_set_nic_properties(dev, &nd_table[0]); + qdev_init_nofail(dev); + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); + sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq); + sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq); + + return dev; +} + static inline DeviceState *milkymist_softusb_create(target_phys_addr_t base, qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size, uint32_t dmem_base, uint32_t dmem_size) diff --git a/hw/milkymist-minimac.c b/hw/milkymist-minimac2.c index b07f18d8a..c4e28187b 100644 --- a/hw/milkymist-minimac.c +++ b/hw/milkymist-minimac2.c @@ -1,7 +1,7 @@ /* - * QEMU model of the Milkymist minimac block. + * QEMU model of the Milkymist minimac2 block. * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> + * Copyright (c) 2011 Michael Walle <michael@walle.cc> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,7 +18,7 @@ * * * Specification available at: - * http://www.milkymist.org/socdoc/minimac.pdf + * not available yet * */ @@ -27,6 +27,7 @@ #include "trace.h" #include "net.h" #include "qemu-error.h" +#include "qdev-addr.h" #include <zlib.h> @@ -34,25 +35,15 @@ enum { R_SETUP = 0, R_MDIO, R_STATE0, - R_ADDR0, R_COUNT0, R_STATE1, - R_ADDR1, R_COUNT1, - R_STATE2, - R_ADDR2, - R_COUNT2, - R_STATE3, - R_ADDR3, - R_COUNT3, - R_TXADDR, R_TXCOUNT, R_MAX }; enum { - SETUP_RX_RST = (1<<0), - SETUP_TX_RST = (1<<2), + SETUP_PHY_RST = (1<<0), }; enum { @@ -85,9 +76,10 @@ enum { R_PHY_MAX = 32 }; -#define MINIMAC_MTU 1530 +#define MINIMAC2_MTU 1530 +#define MINIMAC2_BUFFER_SIZE 2048 -struct MilkymistMinimacMdioState { +struct MilkymistMinimac2MdioState { int last_clk; int count; uint32_t data; @@ -97,50 +89,55 @@ struct MilkymistMinimacMdioState { uint8_t phy_addr; uint8_t reg_addr; }; -typedef struct MilkymistMinimacMdioState MilkymistMinimacMdioState; +typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState; -struct MilkymistMinimacState { +struct MilkymistMinimac2State { SysBusDevice busdev; NICState *nic; NICConf conf; char *phy_model; + target_phys_addr_t buffers_base; qemu_irq rx_irq; qemu_irq tx_irq; uint32_t regs[R_MAX]; - MilkymistMinimacMdioState mdio; + MilkymistMinimac2MdioState mdio; uint16_t phy_regs[R_PHY_MAX]; + + uint8_t *rx0_buf; + uint8_t *rx1_buf; + uint8_t *tx_buf; }; -typedef struct MilkymistMinimacState MilkymistMinimacState; +typedef struct MilkymistMinimac2State MilkymistMinimac2State; static const uint8_t preamble_sfd[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5 }; -static void minimac_mdio_write_reg(MilkymistMinimacState *s, +static void minimac2_mdio_write_reg(MilkymistMinimac2State *s, uint8_t phy_addr, uint8_t reg_addr, uint16_t value) { - trace_milkymist_minimac_mdio_write(phy_addr, reg_addr, value); + trace_milkymist_minimac2_mdio_write(phy_addr, reg_addr, value); /* nop */ } -static uint16_t minimac_mdio_read_reg(MilkymistMinimacState *s, +static uint16_t minimac2_mdio_read_reg(MilkymistMinimac2State *s, uint8_t phy_addr, uint8_t reg_addr) { uint16_t r = s->phy_regs[reg_addr]; - trace_milkymist_minimac_mdio_read(phy_addr, reg_addr, r); + trace_milkymist_minimac2_mdio_read(phy_addr, reg_addr, r); return r; } -static void minimac_update_mdio(MilkymistMinimacState *s) +static void minimac2_update_mdio(MilkymistMinimac2State *s) { - MilkymistMinimacMdioState *m = &s->mdio; + MilkymistMinimac2MdioState *m = &s->mdio; /* detect rising clk edge */ if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) { @@ -173,7 +170,7 @@ static void minimac_update_mdio(MilkymistMinimacState *s) } if (m->state == MDIO_STATE_READING) { - m->data_out = minimac_mdio_read_reg(s, m->phy_addr, + m->data_out = minimac2_mdio_read_reg(s, m->phy_addr, m->reg_addr); } } @@ -192,7 +189,7 @@ static void minimac_update_mdio(MilkymistMinimacState *s) if (m->count == 0 && m->state) { if (m->state == MDIO_STATE_WRITING) { uint16_t data = m->data & 0xffff; - minimac_mdio_write_reg(s, m->phy_addr, m->reg_addr, data); + minimac2_mdio_write_reg(s, m->phy_addr, m->reg_addr, data); } m->state = MDIO_STATE_IDLE; } @@ -208,7 +205,7 @@ static size_t assemble_frame(uint8_t *buf, size_t size, uint32_t crc; if (size < payload_size + 12) { - error_report("milkymist_minimac: received too big ethernet frame"); + error_report("milkymist_minimac2: received too big ethernet frame"); return 0; } @@ -231,115 +228,102 @@ static size_t assemble_frame(uint8_t *buf, size_t size, return payload_size + 12; } -static void minimac_tx(MilkymistMinimacState *s) +static void minimac2_tx(MilkymistMinimac2State *s) { - uint8_t buf[MINIMAC_MTU]; uint32_t txcount = s->regs[R_TXCOUNT]; - - /* do nothing if transmission logic is in reset */ - if (s->regs[R_SETUP] & SETUP_TX_RST) { - return; - } + uint8_t *buf = s->tx_buf; if (txcount < 64) { - error_report("milkymist_minimac: ethernet frame too small (%u < %u)\n", + error_report("milkymist_minimac2: ethernet frame too small (%u < %u)\n", txcount, 64); - return; + goto err; } - if (txcount > MINIMAC_MTU) { - error_report("milkymist_minimac: MTU exceeded (%u > %u)\n", - txcount, MINIMAC_MTU); - return; + if (txcount > MINIMAC2_MTU) { + error_report("milkymist_minimac2: MTU exceeded (%u > %u)\n", + txcount, MINIMAC2_MTU); + goto err; } - /* dma */ - cpu_physical_memory_read(s->regs[R_TXADDR], buf, txcount); - if (memcmp(buf, preamble_sfd, 8) != 0) { - error_report("milkymist_minimac: frame doesn't contain the preamble " + error_report("milkymist_minimac2: frame doesn't contain the preamble " "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return; + goto err; } - trace_milkymist_minimac_tx_frame(txcount - 12); + trace_milkymist_minimac2_tx_frame(txcount - 12); /* send packet, skipping preamble and sfd */ qemu_send_packet_raw(&s->nic->nc, buf + 8, txcount - 12); s->regs[R_TXCOUNT] = 0; - trace_milkymist_minimac_pulse_irq_tx(); +err: + trace_milkymist_minimac2_pulse_irq_tx(); qemu_irq_pulse(s->tx_irq); } -static ssize_t minimac_rx(VLANClientState *nc, const uint8_t *buf, size_t size) +static void update_rx_interrupt(MilkymistMinimac2State *s) +{ + if (s->regs[R_STATE0] == STATE_PENDING + || s->regs[R_STATE1] == STATE_PENDING) { + trace_milkymist_minimac2_raise_irq_rx(); + qemu_irq_raise(s->rx_irq); + } else { + trace_milkymist_minimac2_lower_irq_rx(); + qemu_irq_lower(s->rx_irq); + } +} + +static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size) { - MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque; + MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; - uint32_t r_addr; uint32_t r_count; uint32_t r_state; + uint8_t *rx_buf; - uint8_t frame_buf[MINIMAC_MTU]; size_t frame_size; - trace_milkymist_minimac_rx_frame(buf, size); - - /* discard frames if nic is in reset */ - if (s->regs[R_SETUP] & SETUP_RX_RST) { - return size; - } + trace_milkymist_minimac2_rx_frame(buf, size); /* choose appropriate slot */ if (s->regs[R_STATE0] == STATE_LOADED) { - r_addr = R_ADDR0; r_count = R_COUNT0; r_state = R_STATE0; + rx_buf = s->rx0_buf; } else if (s->regs[R_STATE1] == STATE_LOADED) { - r_addr = R_ADDR1; r_count = R_COUNT1; r_state = R_STATE1; - } else if (s->regs[R_STATE2] == STATE_LOADED) { - r_addr = R_ADDR2; - r_count = R_COUNT2; - r_state = R_STATE2; - } else if (s->regs[R_STATE3] == STATE_LOADED) { - r_addr = R_ADDR3; - r_count = R_COUNT3; - r_state = R_STATE3; + rx_buf = s->rx1_buf; } else { - trace_milkymist_minimac_drop_rx_frame(buf); + trace_milkymist_minimac2_drop_rx_frame(buf); return size; } /* assemble frame */ - frame_size = assemble_frame(frame_buf, sizeof(frame_buf), buf, size); + frame_size = assemble_frame(rx_buf, MINIMAC2_BUFFER_SIZE, buf, size); if (frame_size == 0) { return size; } - trace_milkymist_minimac_rx_transfer(buf, frame_size); - - /* do dma */ - cpu_physical_memory_write(s->regs[r_addr], frame_buf, frame_size); + trace_milkymist_minimac2_rx_transfer(rx_buf, frame_size); /* update slot */ s->regs[r_count] = frame_size; s->regs[r_state] = STATE_PENDING; - trace_milkymist_minimac_pulse_irq_rx(); - qemu_irq_pulse(s->rx_irq); + update_rx_interrupt(s); return size; } static uint32_t -minimac_read(void *opaque, target_phys_addr_t addr) +minimac2_read(void *opaque, target_phys_addr_t addr) { - MilkymistMinimacState *s = opaque; + MilkymistMinimac2State *s = opaque; uint32_t r = 0; addr >>= 2; @@ -347,39 +331,30 @@ minimac_read(void *opaque, target_phys_addr_t addr) case R_SETUP: case R_MDIO: case R_STATE0: - case R_ADDR0: case R_COUNT0: case R_STATE1: - case R_ADDR1: case R_COUNT1: - case R_STATE2: - case R_ADDR2: - case R_COUNT2: - case R_STATE3: - case R_ADDR3: - case R_COUNT3: - case R_TXADDR: case R_TXCOUNT: r = s->regs[addr]; break; default: - error_report("milkymist_minimac: read access to unknown register 0x" + error_report("milkymist_minimac2: read access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } - trace_milkymist_minimac_memory_read(addr << 2, r); + trace_milkymist_minimac2_memory_read(addr << 2, r); return r; } static void -minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value) +minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value) { - MilkymistMinimacState *s = opaque; + MilkymistMinimac2State *s = opaque; - trace_milkymist_minimac_memory_read(addr, value); + trace_milkymist_minimac2_memory_read(addr, value); addr >>= 2; switch (addr) { @@ -394,58 +369,47 @@ minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value) s->regs[R_MDIO] &= ~mdio_di; } - minimac_update_mdio(s); + minimac2_update_mdio(s); } break; case R_TXCOUNT: s->regs[addr] = value; if (value > 0) { - minimac_tx(s); + minimac2_tx(s); } break; - case R_SETUP: case R_STATE0: - case R_ADDR0: - case R_COUNT0: case R_STATE1: - case R_ADDR1: + s->regs[addr] = value; + update_rx_interrupt(s); + break; + case R_SETUP: + case R_COUNT0: case R_COUNT1: - case R_STATE2: - case R_ADDR2: - case R_COUNT2: - case R_STATE3: - case R_ADDR3: - case R_COUNT3: - case R_TXADDR: s->regs[addr] = value; break; default: - error_report("milkymist_minimac: write access to unknown register 0x" + error_report("milkymist_minimac2: write access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } } -static CPUReadMemoryFunc * const minimac_read_fn[] = { +static CPUReadMemoryFunc * const minimac2_read_fn[] = { NULL, NULL, - &minimac_read, + &minimac2_read, }; -static CPUWriteMemoryFunc * const minimac_write_fn[] = { +static CPUWriteMemoryFunc * const minimac2_write_fn[] = { NULL, NULL, - &minimac_write, + &minimac2_write, }; -static int minimac_can_rx(VLANClientState *nc) +static int minimac2_can_rx(VLANClientState *nc) { - MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque; - - /* discard frames if nic is in reset */ - if (s->regs[R_SETUP] & SETUP_RX_RST) { - return 1; - } + MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; if (s->regs[R_STATE0] == STATE_LOADED) { return 1; @@ -453,27 +417,21 @@ static int minimac_can_rx(VLANClientState *nc) if (s->regs[R_STATE1] == STATE_LOADED) { return 1; } - if (s->regs[R_STATE2] == STATE_LOADED) { - return 1; - } - if (s->regs[R_STATE3] == STATE_LOADED) { - return 1; - } return 0; } -static void minimac_cleanup(VLANClientState *nc) +static void minimac2_cleanup(VLANClientState *nc) { - MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque; + MilkymistMinimac2State *s = DO_UPCAST(NICState, nc, nc)->opaque; s->nic = NULL; } -static void milkymist_minimac_reset(DeviceState *d) +static void milkymist_minimac2_reset(DeviceState *d) { - MilkymistMinimacState *s = - container_of(d, MilkymistMinimacState, busdev.qdev); + MilkymistMinimac2State *s = + container_of(d, MilkymistMinimac2State, busdev.qdev); int i; for (i = 0; i < R_MAX; i++) { @@ -488,81 +446,94 @@ static void milkymist_minimac_reset(DeviceState *d) s->phy_regs[R_PHY_ID2] = 0x161a; } -static NetClientInfo net_milkymist_minimac_info = { +static NetClientInfo net_milkymist_minimac2_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), - .can_receive = minimac_can_rx, - .receive = minimac_rx, - .cleanup = minimac_cleanup, + .can_receive = minimac2_can_rx, + .receive = minimac2_rx, + .cleanup = minimac2_cleanup, }; -static int milkymist_minimac_init(SysBusDevice *dev) +static int milkymist_minimac2_init(SysBusDevice *dev) { - MilkymistMinimacState *s = FROM_SYSBUS(typeof(*s), dev); + MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev); int regs; + ram_addr_t buffers; + size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE); sysbus_init_irq(dev, &s->rx_irq); sysbus_init_irq(dev, &s->tx_irq); - regs = cpu_register_io_memory(minimac_read_fn, minimac_write_fn, s, + regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s, DEVICE_NATIVE_ENDIAN); sysbus_init_mmio(dev, R_MAX * 4, regs); + /* register buffers memory */ + buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size); + s->rx0_buf = qemu_get_ram_ptr(buffers); + s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE; + s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE; + + cpu_register_physical_memory(s->buffers_base, buffers_size, + buffers | IO_MEM_RAM); + qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->nic = qemu_new_nic(&net_milkymist_minimac_info, &s->conf, + s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf, dev->qdev.info->name, dev->qdev.id, s); qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); return 0; } -static const VMStateDescription vmstate_milkymist_minimac_mdio = { - .name = "milkymist_minimac_mdio", +static const VMStateDescription vmstate_milkymist_minimac2_mdio = { + .name = "milkymist-minimac2-mdio", .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_INT32(last_clk, MilkymistMinimacMdioState), - VMSTATE_INT32(count, MilkymistMinimacMdioState), - VMSTATE_UINT32(data, MilkymistMinimacMdioState), - VMSTATE_UINT16(data_out, MilkymistMinimacMdioState), - VMSTATE_INT32(state, MilkymistMinimacMdioState), - VMSTATE_UINT8(phy_addr, MilkymistMinimacMdioState), - VMSTATE_UINT8(reg_addr, MilkymistMinimacMdioState), + VMSTATE_INT32(last_clk, MilkymistMinimac2MdioState), + VMSTATE_INT32(count, MilkymistMinimac2MdioState), + VMSTATE_UINT32(data, MilkymistMinimac2MdioState), + VMSTATE_UINT16(data_out, MilkymistMinimac2MdioState), + VMSTATE_INT32(state, MilkymistMinimac2MdioState), + VMSTATE_UINT8(phy_addr, MilkymistMinimac2MdioState), + VMSTATE_UINT8(reg_addr, MilkymistMinimac2MdioState), VMSTATE_END_OF_LIST() } }; -static const VMStateDescription vmstate_milkymist_minimac = { - .name = "milkymist-minimac", +static const VMStateDescription vmstate_milkymist_minimac2 = { + .name = "milkymist-minimac2", .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistMinimacState, R_MAX), - VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimacState, R_PHY_MAX), - VMSTATE_STRUCT(mdio, MilkymistMinimacState, 0, - vmstate_milkymist_minimac_mdio, MilkymistMinimacMdioState), + VMSTATE_UINT32_ARRAY(regs, MilkymistMinimac2State, R_MAX), + VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimac2State, R_PHY_MAX), + VMSTATE_STRUCT(mdio, MilkymistMinimac2State, 0, + vmstate_milkymist_minimac2_mdio, MilkymistMinimac2MdioState), VMSTATE_END_OF_LIST() } }; -static SysBusDeviceInfo milkymist_minimac_info = { - .init = milkymist_minimac_init, - .qdev.name = "milkymist-minimac", - .qdev.size = sizeof(MilkymistMinimacState), - .qdev.vmsd = &vmstate_milkymist_minimac, - .qdev.reset = milkymist_minimac_reset, +static SysBusDeviceInfo milkymist_minimac2_info = { + .init = milkymist_minimac2_init, + .qdev.name = "milkymist-minimac2", + .qdev.size = sizeof(MilkymistMinimac2State), + .qdev.vmsd = &vmstate_milkymist_minimac2, + .qdev.reset = milkymist_minimac2_reset, .qdev.props = (Property[]) { - DEFINE_NIC_PROPERTIES(MilkymistMinimacState, conf), - DEFINE_PROP_STRING("phy_model", MilkymistMinimacState, phy_model), + DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State, + buffers_base, 0), + DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf), + DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model), DEFINE_PROP_END_OF_LIST(), } }; -static void milkymist_minimac_register(void) +static void milkymist_minimac2_register(void) { - sysbus_register_withprop(&milkymist_minimac_info); + sysbus_register_withprop(&milkymist_minimac2_info); } -device_init(milkymist_minimac_register) +device_init(milkymist_minimac2_register) diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c index eaea543bf..6bd0cb974 100644 --- a/hw/milkymist-sysctl.c +++ b/hw/milkymist-sysctl.c @@ -140,24 +140,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value) case R_GPIO_OUT: case R_GPIO_INTEN: case R_TIMER0_COUNTER: - if (value > s->regs[R_TIMER0_COUNTER]) { - value = s->regs[R_TIMER0_COUNTER]; - error_report("milkymist_sysctl: timer0: trying to write a " - "value greater than the limit. Clipping."); - } - /* milkymist timer counts up */ - value = s->regs[R_TIMER0_COUNTER] - value; - ptimer_set_count(s->ptimer0, value); - break; case R_TIMER1_COUNTER: - if (value > s->regs[R_TIMER1_COUNTER]) { - value = s->regs[R_TIMER1_COUNTER]; - error_report("milkymist_sysctl: timer1: trying to write a " - "value greater than the limit. Clipping."); - } - /* milkymist timer counts up */ - value = s->regs[R_TIMER1_COUNTER] - value; - ptimer_set_count(s->ptimer1, value); + s->regs[addr] = value; break; case R_TIMER0_COMPARE: ptimer_set_limit(s->ptimer0, value, 0); @@ -170,10 +154,12 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value) case R_TIMER0_CONTROL: s->regs[addr] = value; if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) { - trace_milkymist_sysctl_start_timer1(); + trace_milkymist_sysctl_start_timer0(); + ptimer_set_count(s->ptimer0, + s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]); ptimer_run(s->ptimer0, 0); } else { - trace_milkymist_sysctl_stop_timer1(); + trace_milkymist_sysctl_stop_timer0(); ptimer_stop(s->ptimer0); } break; @@ -181,6 +167,8 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value) s->regs[addr] = value; if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) { trace_milkymist_sysctl_start_timer1(); + ptimer_set_count(s->ptimer1, + s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]); ptimer_run(s->ptimer1, 0); } else { trace_milkymist_sysctl_stop_timer1(); diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 892273151..2e55e42e3 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -199,6 +199,9 @@ vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value) addr >>= 2; switch (addr) { case R_CTRL: + s->regs[addr] = value; + vgafb_resize(s); + break; case R_HSYNC_START: case R_HSYNC_END: case R_HSCAN: diff --git a/hw/milkymist.c b/hw/milkymist.c index 8defad802..787984040 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -156,7 +156,7 @@ milkymist_init(ram_addr_t ram_size_not_used, milkymist_ac97_create(0x60005000, irq[5], irq[6], irq[7], irq[8]); milkymist_pfpu_create(0x60006000, irq[9]); milkymist_tmu2_create(0x60007000, irq[10]); - milkymist_minimac_create(0x60008000, irq[11], irq[12]); + milkymist_minimac2_create(0x60008000, 0x30000000, irq[11], irq[12]); milkymist_softusb_create(0x6000f000, irq[17], 0x20000000, 0x1000, 0x20020000, 0x2000); diff --git a/hw/mipsnet.c b/hw/mipsnet.c index c5e54ffc3..26aad51ea 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -202,44 +202,29 @@ static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -static void mipsnet_save(QEMUFile *f, void *opaque) -{ - MIPSnetState *s = opaque; - - qemu_put_be32s(f, &s->busy); - qemu_put_be32s(f, &s->rx_count); - qemu_put_be32s(f, &s->rx_read); - qemu_put_be32s(f, &s->tx_count); - qemu_put_be32s(f, &s->tx_written); - qemu_put_be32s(f, &s->intctl); - qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE); - qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE); -} - -static int mipsnet_load(QEMUFile *f, void *opaque, int version_id) -{ - MIPSnetState *s = opaque; - - if (version_id > 0) - return -EINVAL; - - qemu_get_be32s(f, &s->busy); - qemu_get_be32s(f, &s->rx_count); - qemu_get_be32s(f, &s->rx_read); - qemu_get_be32s(f, &s->tx_count); - qemu_get_be32s(f, &s->tx_written); - qemu_get_be32s(f, &s->intctl); - qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE); - qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE); - - return 0; -} +static const VMStateDescription vmstate_mipsnet = { + .name = "mipsnet", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(busy, MIPSnetState), + VMSTATE_UINT32(rx_count, MIPSnetState), + VMSTATE_UINT32(rx_read, MIPSnetState), + VMSTATE_UINT32(tx_count, MIPSnetState), + VMSTATE_UINT32(tx_written, MIPSnetState), + VMSTATE_UINT32(intctl, MIPSnetState), + VMSTATE_BUFFER(rx_buffer, MIPSnetState), + VMSTATE_BUFFER(tx_buffer, MIPSnetState), + VMSTATE_END_OF_LIST() + } +}; static void mipsnet_cleanup(VLANClientState *nc) { MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; - unregister_savevm(NULL, "mipsnet", s); + vmstate_unregister(NULL, &vmstate_mipsnet, s); isa_unassign_ioport(s->io_base, 36); @@ -284,5 +269,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) } mipsnet_reset(s); - register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s); + vmstate_register(NULL, 0, &vmstate_mipsnet, s); } @@ -52,7 +52,7 @@ struct NANDFlashState { BlockDriverState *bdrv; int mem_oob; - int cle, ale, ce, wp, gnd; + uint8_t cle, ale, ce, wp, gnd; uint8_t io[MAX_PAGE + MAX_OOB + 0x400]; uint8_t *ioaddr; @@ -66,6 +66,8 @@ struct NANDFlashState { void (*blk_write)(NANDFlashState *s); void (*blk_erase)(NANDFlashState *s); void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset); + + uint32_t ioaddr_vmstate; }; # define NAND_NO_AUTOINCR 0x00000001 @@ -281,56 +283,59 @@ static void nand_command(NANDFlashState *s) } } -static void nand_save(QEMUFile *f, void *opaque) +static void nand_pre_save(void *opaque) { - NANDFlashState *s = (NANDFlashState *) opaque; - qemu_put_byte(f, s->cle); - qemu_put_byte(f, s->ale); - qemu_put_byte(f, s->ce); - qemu_put_byte(f, s->wp); - qemu_put_byte(f, s->gnd); - qemu_put_buffer(f, s->io, sizeof(s->io)); - qemu_put_be32(f, s->ioaddr - s->io); - qemu_put_be32(f, s->iolen); - - qemu_put_be32s(f, &s->cmd); - qemu_put_be32s(f, &s->addr); - qemu_put_be32(f, s->addrlen); - qemu_put_be32(f, s->status); - qemu_put_be32(f, s->offset); - /* XXX: do we want to save s->storage too? */ + NANDFlashState *s = opaque; + + s->ioaddr_vmstate = s->ioaddr - s->io; } -static int nand_load(QEMUFile *f, void *opaque, int version_id) +static int nand_post_load(void *opaque, int version_id) { - NANDFlashState *s = (NANDFlashState *) opaque; - s->cle = qemu_get_byte(f); - s->ale = qemu_get_byte(f); - s->ce = qemu_get_byte(f); - s->wp = qemu_get_byte(f); - s->gnd = qemu_get_byte(f); - qemu_get_buffer(f, s->io, sizeof(s->io)); - s->ioaddr = s->io + qemu_get_be32(f); - s->iolen = qemu_get_be32(f); - if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io) + NANDFlashState *s = opaque; + + if (s->ioaddr_vmstate > sizeof(s->io)) { return -EINVAL; + } + s->ioaddr = s->io + s->ioaddr_vmstate; - qemu_get_be32s(f, &s->cmd); - qemu_get_be32s(f, &s->addr); - s->addrlen = qemu_get_be32(f); - s->status = qemu_get_be32(f); - s->offset = qemu_get_be32(f); return 0; } +static const VMStateDescription vmstate_nand = { + .name = "nand", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .pre_save = nand_pre_save, + .post_load = nand_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8(cle, NANDFlashState), + VMSTATE_UINT8(ale, NANDFlashState), + VMSTATE_UINT8(ce, NANDFlashState), + VMSTATE_UINT8(wp, NANDFlashState), + VMSTATE_UINT8(gnd, NANDFlashState), + VMSTATE_BUFFER(io, NANDFlashState), + VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState), + VMSTATE_INT32(iolen, NANDFlashState), + VMSTATE_UINT32(cmd, NANDFlashState), + VMSTATE_UINT32(addr, NANDFlashState), + VMSTATE_INT32(addrlen, NANDFlashState), + VMSTATE_INT32(status, NANDFlashState), + VMSTATE_INT32(offset, NANDFlashState), + /* XXX: do we want to save s->storage too? */ + VMSTATE_END_OF_LIST() + } +}; + /* * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip * outputs are R/B and eight I/O pins. * * CE, WP and R/B are active low. */ -void nand_setpins(NANDFlashState *s, - int cle, int ale, int ce, int wp, int gnd) +void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, + uint8_t ce, uint8_t wp, uint8_t gnd) { s->cle = cle; s->ale = ale; @@ -502,7 +507,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id) is used. */ s->ioaddr = s->io; - register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s); + vmstate_register(NULL, -1, &vmstate_nand, s); return s; } diff --git a/hw/ne2000.c b/hw/ne2000.c index 596635985..b668ad107 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -742,7 +742,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev) if (!pci_dev->qdev.hotplugged) { static int loaded = 0; if (!loaded) { - rom_add_option("pxe-ne2k_pci.bin", -1); + rom_add_option("pxe-ne2k_pci.rom", -1); loaded = 1; } } diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index 06bccbdc4..a7b687bc4 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -26,7 +26,6 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ #include "hw.h" -#include "sysemu.h" #include "console.h" #include "omap.h" #include "boards.h" @@ -18,8 +18,7 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "sysemu.h" -#include "range.h" +#include "qemu-common.h" #include "pci_bridge.h" #include "pcie.h" #include "msix.h" diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 339a40196..40ee29d38 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -310,7 +310,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev) if (!pci_dev->qdev.hotplugged) { static int loaded = 0; if (!loaded) { - rom_add_option("pxe-pcnet.bin", -1); + rom_add_option("pxe-pcnet.rom", -1); loaded = 1; } } diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index 370c5eef7..14bbc34e1 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -50,6 +50,8 @@ do { \ #define DPRINTF(fmt, ...) do { } while (0) #endif +#define PFLASH_LAZY_ROMD_THRESHOLD 42 + struct pflash_t { BlockDriverState *bs; target_phys_addr_t base; @@ -70,6 +72,7 @@ struct pflash_t { ram_addr_t off; int fl_mem; int rom_mode; + int read_counter; /* used for lazy switch-back to rom mode */ void *storage; }; @@ -112,10 +115,10 @@ static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset, DPRINTF("%s: offset " TARGET_FMT_plx "\n", __func__, offset); ret = -1; - if (!pfl->rom_mode) { - /* Lazy reset of to ROMD mode */ - if (pfl->wcycle == 0) - pflash_register_memory(pfl, 1); + /* Lazy reset to ROMD mode after a certain amount of read accesses */ + if (!pfl->rom_mode && pfl->wcycle == 0 && + ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) { + pflash_register_memory(pfl, 1); } offset &= pfl->chip_len - 1; boff = offset & 0xFF; @@ -254,6 +257,7 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset, /* Set the device in I/O access mode if required */ if (pfl->rom_mode) pflash_register_memory(pfl, 0); + pfl->read_counter = 0; /* We're in read mode */ check_unlock0: if (boff == 0x55 && cmd == 0x98) { diff --git a/hw/piix4.c b/hw/piix4.c index 72073cd0a..71f1f84dc 100644 --- a/hw/piix4.c +++ b/hw/piix4.c @@ -30,10 +30,14 @@ PCIDevice *piix4_dev; +typedef struct PIIX4State { + PCIDevice dev; +} PIIX4State; + static void piix4_reset(void *opaque) { - PCIDevice *d = opaque; - uint8_t *pci_conf = d->config; + PIIX4State *d = opaque; + uint8_t *pci_conf = d->dev.config; pci_conf[0x04] = 0x07; // master, memory and I/O pci_conf[0x05] = 0x00; @@ -68,33 +72,30 @@ static void piix4_reset(void *opaque) pci_conf[0xae] = 0x00; } -static void piix_save(QEMUFile* f, void *opaque) -{ - PCIDevice *d = opaque; - pci_device_save(d, f); -} - -static int piix_load(QEMUFile* f, void *opaque, int version_id) -{ - PCIDevice *d = opaque; - if (version_id != 2) - return -EINVAL; - return pci_device_load(d, f); -} +static const VMStateDescription vmstate_piix4 = { + .name = "PIIX4", + .version_id = 2, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, PIIX4State), + VMSTATE_END_OF_LIST() + } +}; -static int piix4_initfn(PCIDevice *d) +static int piix4_initfn(PCIDevice *dev) { + PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev); uint8_t *pci_conf; - isa_bus_new(&d->qdev); - register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d); + isa_bus_new(&d->dev.qdev); - pci_conf = d->config; + pci_conf = d->dev.config; pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA); - piix4_dev = d; + piix4_dev = &d->dev; qemu_register_reset(piix4_reset, d); return 0; } @@ -111,7 +112,8 @@ static PCIDeviceInfo piix4_info[] = { { .qdev.name = "PIIX4", .qdev.desc = "ISA bridge", - .qdev.size = sizeof(PCIDevice), + .qdev.size = sizeof(PIIX4State), + .qdev.vmsd = &vmstate_piix4, .qdev.no_user = 1, .no_hotplug = 1, .init = piix4_initfn, diff --git a/hw/pl011.c b/hw/pl011.c index 77f0dbf13..3b94b14cb 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -235,56 +235,30 @@ static CPUWriteMemoryFunc * const pl011_writefn[] = { pl011_write }; -static void pl011_save(QEMUFile *f, void *opaque) -{ - pl011_state *s = (pl011_state *)opaque; - int i; - - qemu_put_be32(f, s->readbuff); - qemu_put_be32(f, s->flags); - qemu_put_be32(f, s->lcr); - qemu_put_be32(f, s->cr); - qemu_put_be32(f, s->dmacr); - qemu_put_be32(f, s->int_enabled); - qemu_put_be32(f, s->int_level); - for (i = 0; i < 16; i++) - qemu_put_be32(f, s->read_fifo[i]); - qemu_put_be32(f, s->ilpr); - qemu_put_be32(f, s->ibrd); - qemu_put_be32(f, s->fbrd); - qemu_put_be32(f, s->ifl); - qemu_put_be32(f, s->read_pos); - qemu_put_be32(f, s->read_count); - qemu_put_be32(f, s->read_trigger); -} - -static int pl011_load(QEMUFile *f, void *opaque, int version_id) -{ - pl011_state *s = (pl011_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->readbuff = qemu_get_be32(f); - s->flags = qemu_get_be32(f); - s->lcr = qemu_get_be32(f); - s->cr = qemu_get_be32(f); - s->dmacr = qemu_get_be32(f); - s->int_enabled = qemu_get_be32(f); - s->int_level = qemu_get_be32(f); - for (i = 0; i < 16; i++) - s->read_fifo[i] = qemu_get_be32(f); - s->ilpr = qemu_get_be32(f); - s->ibrd = qemu_get_be32(f); - s->fbrd = qemu_get_be32(f); - s->ifl = qemu_get_be32(f); - s->read_pos = qemu_get_be32(f); - s->read_count = qemu_get_be32(f); - s->read_trigger = qemu_get_be32(f); - - return 0; -} +static const VMStateDescription vmstate_pl011 = { + .name = "pl011", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(readbuff, pl011_state), + VMSTATE_UINT32(flags, pl011_state), + VMSTATE_UINT32(lcr, pl011_state), + VMSTATE_UINT32(cr, pl011_state), + VMSTATE_UINT32(dmacr, pl011_state), + VMSTATE_UINT32(int_enabled, pl011_state), + VMSTATE_UINT32(int_level, pl011_state), + VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16), + VMSTATE_UINT32(ilpr, pl011_state), + VMSTATE_UINT32(ibrd, pl011_state), + VMSTATE_UINT32(fbrd, pl011_state), + VMSTATE_UINT32(ifl, pl011_state), + VMSTATE_INT32(read_pos, pl011_state), + VMSTATE_INT32(read_count, pl011_state), + VMSTATE_INT32(read_trigger, pl011_state), + VMSTATE_END_OF_LIST() + } +}; static int pl011_init(SysBusDevice *dev, const unsigned char *id) { @@ -307,7 +281,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, pl011_event, s); } - register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_pl011, s); return 0; } diff --git a/hw/pl022.c b/hw/pl022.c index ffe05ab74..00e494a0d 100644 --- a/hw/pl022.c +++ b/hw/pl022.c @@ -239,54 +239,42 @@ static CPUWriteMemoryFunc * const pl022_writefn[] = { pl022_write }; -static void pl022_save(QEMUFile *f, void *opaque) -{ - pl022_state *s = (pl022_state *)opaque; - int i; - - qemu_put_be32(f, s->cr0); - qemu_put_be32(f, s->cr1); - qemu_put_be32(f, s->bitmask); - qemu_put_be32(f, s->sr); - qemu_put_be32(f, s->cpsr); - qemu_put_be32(f, s->is); - qemu_put_be32(f, s->im); - qemu_put_be32(f, s->tx_fifo_head); - qemu_put_be32(f, s->rx_fifo_head); - qemu_put_be32(f, s->tx_fifo_len); - qemu_put_be32(f, s->rx_fifo_len); - for (i = 0; i < 8; i++) { - qemu_put_be16(f, s->tx_fifo[i]); - qemu_put_be16(f, s->rx_fifo[i]); - } -} - -static int pl022_load(QEMUFile *f, void *opaque, int version_id) -{ - pl022_state *s = (pl022_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->cr0 = qemu_get_be32(f); - s->cr1 = qemu_get_be32(f); - s->bitmask = qemu_get_be32(f); - s->sr = qemu_get_be32(f); - s->cpsr = qemu_get_be32(f); - s->is = qemu_get_be32(f); - s->im = qemu_get_be32(f); - s->tx_fifo_head = qemu_get_be32(f); - s->rx_fifo_head = qemu_get_be32(f); - s->tx_fifo_len = qemu_get_be32(f); - s->rx_fifo_len = qemu_get_be32(f); - for (i = 0; i < 8; i++) { - s->tx_fifo[i] = qemu_get_be16(f); - s->rx_fifo[i] = qemu_get_be16(f); +static const VMStateDescription vmstate_pl022 = { + .name = "pl022_ssp", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(cr0, pl022_state), + VMSTATE_UINT32(cr1, pl022_state), + VMSTATE_UINT32(bitmask, pl022_state), + VMSTATE_UINT32(sr, pl022_state), + VMSTATE_UINT32(cpsr, pl022_state), + VMSTATE_UINT32(is, pl022_state), + VMSTATE_UINT32(im, pl022_state), + VMSTATE_INT32(tx_fifo_head, pl022_state), + VMSTATE_INT32(rx_fifo_head, pl022_state), + VMSTATE_INT32(tx_fifo_len, pl022_state), + VMSTATE_INT32(rx_fifo_len, pl022_state), + VMSTATE_UINT16(tx_fifo[0], pl022_state), + VMSTATE_UINT16(rx_fifo[0], pl022_state), + VMSTATE_UINT16(tx_fifo[1], pl022_state), + VMSTATE_UINT16(rx_fifo[1], pl022_state), + VMSTATE_UINT16(tx_fifo[2], pl022_state), + VMSTATE_UINT16(rx_fifo[2], pl022_state), + VMSTATE_UINT16(tx_fifo[3], pl022_state), + VMSTATE_UINT16(rx_fifo[3], pl022_state), + VMSTATE_UINT16(tx_fifo[4], pl022_state), + VMSTATE_UINT16(rx_fifo[4], pl022_state), + VMSTATE_UINT16(tx_fifo[5], pl022_state), + VMSTATE_UINT16(rx_fifo[5], pl022_state), + VMSTATE_UINT16(tx_fifo[6], pl022_state), + VMSTATE_UINT16(rx_fifo[6], pl022_state), + VMSTATE_UINT16(tx_fifo[7], pl022_state), + VMSTATE_UINT16(rx_fifo[7], pl022_state), + VMSTATE_END_OF_LIST() } - - return 0; -} +}; static int pl022_init(SysBusDevice *dev) { @@ -300,7 +288,7 @@ static int pl022_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); s->ssi = ssi_create_bus(&dev->qdev, "ssi"); pl022_reset(s); - register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_pl022, s); return 0; } diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index db1f84abe..6627cd8aa 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -17,7 +17,6 @@ #include "hw.h" #include "pci.h" #include "boards.h" -#include "sysemu.h" #include "ppc440.h" #include "kvm.h" #include "kvm_ppc.h" diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index 5f581fe2c..7f9ed1713 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -24,7 +24,6 @@ #include "hw.h" #include "ppc.h" #include "ppc4xx.h" -#include "sysemu.h" #include "qemu-log.h" //#define DEBUG_MMIO diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index f62f1f91d..299473c4b 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -285,50 +285,48 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(pci_irqs[irq_num], level); } -static void ppc4xx_pci_save(QEMUFile *f, void *opaque) -{ - PPC4xxPCIState *controller = opaque; - int i; - - pci_device_save(controller->pci_dev, f); - - for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) { - qemu_put_be32s(f, &controller->pmm[i].la); - qemu_put_be32s(f, &controller->pmm[i].ma); - qemu_put_be32s(f, &controller->pmm[i].pcila); - qemu_put_be32s(f, &controller->pmm[i].pciha); - } - - for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) { - qemu_put_be32s(f, &controller->ptm[i].ms); - qemu_put_be32s(f, &controller->ptm[i].la); +static const VMStateDescription vmstate_pci_master_map = { + .name = "pci_master_map", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(la, struct PCIMasterMap), + VMSTATE_UINT32(ma, struct PCIMasterMap), + VMSTATE_UINT32(pcila, struct PCIMasterMap), + VMSTATE_UINT32(pciha, struct PCIMasterMap), + VMSTATE_END_OF_LIST() } -} - -static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id) -{ - PPC4xxPCIState *controller = opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - pci_device_load(controller->pci_dev, f); +}; - for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) { - qemu_get_be32s(f, &controller->pmm[i].la); - qemu_get_be32s(f, &controller->pmm[i].ma); - qemu_get_be32s(f, &controller->pmm[i].pcila); - qemu_get_be32s(f, &controller->pmm[i].pciha); +static const VMStateDescription vmstate_pci_target_map = { + .name = "pci_target_map", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ms, struct PCITargetMap), + VMSTATE_UINT32(la, struct PCITargetMap), + VMSTATE_END_OF_LIST() } +}; - for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) { - qemu_get_be32s(f, &controller->ptm[i].ms); - qemu_get_be32s(f, &controller->ptm[i].la); +static const VMStateDescription vmstate_ppc4xx_pci = { + .name = "ppc4xx_pci", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState), + VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1, + vmstate_pci_master_map, + struct PCIMasterMap), + VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1, + vmstate_pci_target_map, + struct PCITargetMap), + VMSTATE_END_OF_LIST() } - - return 0; -} +}; /* XXX Interrupt acknowledge cycles not supported. */ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], @@ -381,8 +379,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], qemu_register_reset(ppc4xx_pci_reset, controller); /* XXX load/save code not tested. */ - register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++, - 1, ppc4xx_pci_save, ppc4xx_pci_load, controller); + vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++, + &vmstate_ppc4xx_pci, controller); return controller->pci_state.bus; diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 2fc879236..83a20e462 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -216,56 +216,49 @@ static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(pic[irq_num], level); } -static void ppce500_pci_save(QEMUFile *f, void *opaque) -{ - PPCE500PCIState *controller = opaque; - int i; - - pci_device_save(controller->pci_dev, f); - - for (i = 0; i < PPCE500_PCI_NR_POBS; i++) { - qemu_put_be32s(f, &controller->pob[i].potar); - qemu_put_be32s(f, &controller->pob[i].potear); - qemu_put_be32s(f, &controller->pob[i].powbar); - qemu_put_be32s(f, &controller->pob[i].powar); - } - - for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) { - qemu_put_be32s(f, &controller->pib[i].pitar); - qemu_put_be32s(f, &controller->pib[i].piwbar); - qemu_put_be32s(f, &controller->pib[i].piwbear); - qemu_put_be32s(f, &controller->pib[i].piwar); +static const VMStateDescription vmstate_pci_outbound = { + .name = "pci_outbound", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(potar, struct pci_outbound), + VMSTATE_UINT32(potear, struct pci_outbound), + VMSTATE_UINT32(powbar, struct pci_outbound), + VMSTATE_UINT32(powar, struct pci_outbound), + VMSTATE_END_OF_LIST() } - qemu_put_be32s(f, &controller->gasket_time); -} - -static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id) -{ - PPCE500PCIState *controller = opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - pci_device_load(controller->pci_dev, f); +}; - for (i = 0; i < PPCE500_PCI_NR_POBS; i++) { - qemu_get_be32s(f, &controller->pob[i].potar); - qemu_get_be32s(f, &controller->pob[i].potear); - qemu_get_be32s(f, &controller->pob[i].powbar); - qemu_get_be32s(f, &controller->pob[i].powar); +static const VMStateDescription vmstate_pci_inbound = { + .name = "pci_inbound", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(pitar, struct pci_inbound), + VMSTATE_UINT32(piwbar, struct pci_inbound), + VMSTATE_UINT32(piwbear, struct pci_inbound), + VMSTATE_UINT32(piwar, struct pci_inbound), + VMSTATE_END_OF_LIST() } +}; - for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) { - qemu_get_be32s(f, &controller->pib[i].pitar); - qemu_get_be32s(f, &controller->pib[i].piwbar); - qemu_get_be32s(f, &controller->pib[i].piwbear); - qemu_get_be32s(f, &controller->pib[i].piwar); +static const VMStateDescription vmstate_ppce500_pci = { + .name = "ppce500_pci", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState), + VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1, + vmstate_pci_outbound, struct pci_outbound), + VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1, + vmstate_pci_outbound, struct pci_inbound), + VMSTATE_UINT32(gasket_time, PPCE500PCIState), + VMSTATE_END_OF_LIST() } - qemu_get_be32s(f, &controller->gasket_time); - - return 0; -} +}; PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers) { @@ -314,8 +307,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers) PCIE500_REG_SIZE, index); /* XXX load/save code not tested. */ - register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++, - 1, ppce500_pci_save, ppce500_pci_load, controller); + vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci, + controller); return controller->pci_state.bus; diff --git a/hw/ptimer.c b/hw/ptimer.c index e68c1d141..47964a67e 100644 --- a/hw/ptimer.c +++ b/hw/ptimer.c @@ -11,7 +11,7 @@ struct ptimer_state { - int enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */ + uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */ uint64_t limit; uint64_t delta; uint32_t period_frac; @@ -188,49 +188,22 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload) } } -void qemu_put_ptimer(QEMUFile *f, ptimer_state *s) -{ - qemu_put_byte(f, s->enabled); - qemu_put_be64s(f, &s->limit); - qemu_put_be64s(f, &s->delta); - qemu_put_be32s(f, &s->period_frac); - qemu_put_sbe64s(f, &s->period); - qemu_put_sbe64s(f, &s->last_event); - qemu_put_sbe64s(f, &s->next_event); - qemu_put_timer(f, s->timer); -} - -void qemu_get_ptimer(QEMUFile *f, ptimer_state *s) -{ - s->enabled = qemu_get_byte(f); - qemu_get_be64s(f, &s->limit); - qemu_get_be64s(f, &s->delta); - qemu_get_be32s(f, &s->period_frac); - qemu_get_sbe64s(f, &s->period); - qemu_get_sbe64s(f, &s->last_event); - qemu_get_sbe64s(f, &s->next_event); - qemu_get_timer(f, s->timer); -} - -static int get_ptimer(QEMUFile *f, void *pv, size_t size) -{ - ptimer_state *v = pv; - - qemu_get_ptimer(f, v); - return 0; -} - -static void put_ptimer(QEMUFile *f, void *pv, size_t size) -{ - ptimer_state *v = pv; - - qemu_put_ptimer(f, v); -} - -const VMStateInfo vmstate_info_ptimer = { +const VMStateDescription vmstate_ptimer = { .name = "ptimer", - .get = get_ptimer, - .put = put_ptimer, + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(enabled, ptimer_state), + VMSTATE_UINT64(limit, ptimer_state), + VMSTATE_UINT64(delta, ptimer_state), + VMSTATE_UINT32(period_frac, ptimer_state), + VMSTATE_INT64(period, ptimer_state), + VMSTATE_INT64(last_event, ptimer_state), + VMSTATE_INT64(next_event, ptimer_state), + VMSTATE_TIMER(timer, ptimer_state), + VMSTATE_END_OF_LIST() + } }; ptimer_state *ptimer_init(QEMUBH *bh) diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 9b95e2c8e..ac5d95d71 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -146,25 +146,16 @@ static CPUWriteMemoryFunc * const pxa2xx_pm_writefn[] = { pxa2xx_pm_write, }; -static void pxa2xx_pm_save(QEMUFile *f, void *opaque) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 0x40; i ++) - qemu_put_be32s(f, &s->pm_regs[i]); -} - -static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 0x40; i ++) - qemu_get_be32s(f, &s->pm_regs[i]); - - return 0; -} +static const VMStateDescription vmstate_pxa2xx_pm = { + .name = "pxa2xx_pm", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40), + VMSTATE_END_OF_LIST() + } +}; #define CCCR 0x00 /* Core Clock Configuration register */ #define CKEN 0x04 /* Clock Enable register */ @@ -227,29 +218,18 @@ static CPUWriteMemoryFunc * const pxa2xx_cm_writefn[] = { pxa2xx_cm_write, }; -static void pxa2xx_cm_save(QEMUFile *f, void *opaque) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 4; i ++) - qemu_put_be32s(f, &s->cm_regs[i]); - qemu_put_be32s(f, &s->clkcfg); - qemu_put_be32s(f, &s->pmnc); -} - -static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 4; i ++) - qemu_get_be32s(f, &s->cm_regs[i]); - qemu_get_be32s(f, &s->clkcfg); - qemu_get_be32s(f, &s->pmnc); - - return 0; -} +static const VMStateDescription vmstate_pxa2xx_cm = { + .name = "pxa2xx_cm", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4), + VMSTATE_UINT32(clkcfg, PXA2xxState), + VMSTATE_UINT32(pmnc, PXA2xxState), + VMSTATE_END_OF_LIST() + } +}; static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm) { @@ -527,25 +507,16 @@ static CPUWriteMemoryFunc * const pxa2xx_mm_writefn[] = { pxa2xx_mm_write, }; -static void pxa2xx_mm_save(QEMUFile *f, void *opaque) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 0x1a; i ++) - qemu_put_be32s(f, &s->mm_regs[i]); -} - -static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id) -{ - PXA2xxState *s = (PXA2xxState *) opaque; - int i; - - for (i = 0; i < 0x1a; i ++) - qemu_get_be32s(f, &s->mm_regs[i]); - - return 0; -} +static const VMStateDescription vmstate_pxa2xx_mm = { + .name = "pxa2xx_mm", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a), + VMSTATE_END_OF_LIST() + } +}; /* Synchronous Serial Ports */ typedef struct { @@ -1748,39 +1719,23 @@ static CPUWriteMemoryFunc * const pxa2xx_i2s_writefn[] = { pxa2xx_i2s_write, }; -static void pxa2xx_i2s_save(QEMUFile *f, void *opaque) -{ - PXA2xxI2SState *s = (PXA2xxI2SState *) opaque; - - qemu_put_be32s(f, &s->control[0]); - qemu_put_be32s(f, &s->control[1]); - qemu_put_be32s(f, &s->status); - qemu_put_be32s(f, &s->mask); - qemu_put_be32s(f, &s->clk); - - qemu_put_be32(f, s->enable); - qemu_put_be32(f, s->rx_len); - qemu_put_be32(f, s->tx_len); - qemu_put_be32(f, s->fifo_len); -} - -static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id) -{ - PXA2xxI2SState *s = (PXA2xxI2SState *) opaque; - - qemu_get_be32s(f, &s->control[0]); - qemu_get_be32s(f, &s->control[1]); - qemu_get_be32s(f, &s->status); - qemu_get_be32s(f, &s->mask); - qemu_get_be32s(f, &s->clk); - - s->enable = qemu_get_be32(f); - s->rx_len = qemu_get_be32(f); - s->tx_len = qemu_get_be32(f); - s->fifo_len = qemu_get_be32(f); - - return 0; -} +static const VMStateDescription vmstate_pxa2xx_i2s = { + .name = "pxa2xx_i2s", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2), + VMSTATE_UINT32(status, PXA2xxI2SState), + VMSTATE_UINT32(mask, PXA2xxI2SState), + VMSTATE_UINT32(clk, PXA2xxI2SState), + VMSTATE_INT32(enable, PXA2xxI2SState), + VMSTATE_INT32(rx_len, PXA2xxI2SState), + VMSTATE_INT32(tx_len, PXA2xxI2SState), + VMSTATE_INT32(fifo_len, PXA2xxI2SState), + VMSTATE_END_OF_LIST() + } +}; static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx) { @@ -1822,8 +1777,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base, pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(base, 0x100000, iomemtype); - register_savevm(NULL, "pxa2xx_i2s", base, 0, - pxa2xx_i2s_save, pxa2xx_i2s_load, s); + vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s); return s; } @@ -2188,7 +2142,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision) iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn, pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype); - register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); @@ -2199,13 +2153,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision) iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn, pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype); - register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s); s->pm_base = 0x40f00000; iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn, pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->pm_base, 0x100, iomemtype); - register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s); for (i = 0; pxa27x_ssp[i].io_base; i ++); s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i); @@ -2324,7 +2278,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size) iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn, pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype); - register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s); @@ -2335,13 +2289,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size) iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn, pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype); - register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s); s->pm_base = 0x40f00000; iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn, pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(s->pm_base, 0x100, iomemtype); - register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s); for (i = 0; pxa255_ssp[i].io_base; i ++); s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i); diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c index d77dbf179..10ef154aa 100644 --- a/hw/pxa2xx_keypad.c +++ b/hw/pxa2xx_keypad.c @@ -289,40 +289,22 @@ static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = { pxa2xx_keypad_write }; -static void pxa2xx_keypad_save(QEMUFile *f, void *opaque) -{ - PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque; - - qemu_put_be32s(f, &s->kpc); - qemu_put_be32s(f, &s->kpdk); - qemu_put_be32s(f, &s->kprec); - qemu_put_be32s(f, &s->kpmk); - qemu_put_be32s(f, &s->kpas); - qemu_put_be32s(f, &s->kpasmkp[0]); - qemu_put_be32s(f, &s->kpasmkp[1]); - qemu_put_be32s(f, &s->kpasmkp[2]); - qemu_put_be32s(f, &s->kpasmkp[3]); - qemu_put_be32s(f, &s->kpkdi); - -} - -static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id) -{ - PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque; - - qemu_get_be32s(f, &s->kpc); - qemu_get_be32s(f, &s->kpdk); - qemu_get_be32s(f, &s->kprec); - qemu_get_be32s(f, &s->kpmk); - qemu_get_be32s(f, &s->kpas); - qemu_get_be32s(f, &s->kpasmkp[0]); - qemu_get_be32s(f, &s->kpasmkp[1]); - qemu_get_be32s(f, &s->kpasmkp[2]); - qemu_get_be32s(f, &s->kpasmkp[3]); - qemu_get_be32s(f, &s->kpkdi); - - return 0; -} +static const VMStateDescription vmstate_pxa2xx_keypad = { + .name = "pxa2xx_keypad", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(kpc, PXA2xxKeyPadState), + VMSTATE_UINT32(kpdk, PXA2xxKeyPadState), + VMSTATE_UINT32(kprec, PXA2xxKeyPadState), + VMSTATE_UINT32(kpmk, PXA2xxKeyPadState), + VMSTATE_UINT32(kpas, PXA2xxKeyPadState), + VMSTATE_UINT32_ARRAY(kpasmkp, PXA2xxKeyPadState, 4), + VMSTATE_UINT32(kpkdi, PXA2xxKeyPadState), + VMSTATE_END_OF_LIST() + } +}; PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base, qemu_irq irq) @@ -337,8 +319,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base, pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(base, 0x00100000, iomemtype); - register_savevm(NULL, "pxa2xx_keypad", 0, 0, - pxa2xx_keypad_save, pxa2xx_keypad_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s); return s; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 5b2b07e02..e5248023f 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -15,6 +15,20 @@ #include "sysemu.h" #include "framebuffer.h" +struct DMAChannel { + target_phys_addr_t branch; + uint8_t up; + uint8_t palette[1024]; + uint8_t pbuffer[1024]; + void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr, + int *miny, int *maxy); + + target_phys_addr_t descriptor; + target_phys_addr_t source; + uint32_t id; + uint32_t command; +}; + struct PXA2xxLCDState { qemu_irq irq; int irqlevel; @@ -50,19 +64,7 @@ struct PXA2xxLCDState { uint32_t liidr; uint8_t bscntr; - struct { - target_phys_addr_t branch; - int up; - uint8_t palette[1024]; - uint8_t pbuffer[1024]; - void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr, - int *miny, int *maxy); - - target_phys_addr_t descriptor; - target_phys_addr_t source; - uint32_t id; - uint32_t command; - } dma_ch[7]; + struct DMAChannel dma_ch[7]; qemu_irq vsync_cb; int orientation; @@ -831,74 +833,26 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle) pxa2xx_lcdc_resize(s); } -static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque) -{ - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - int i; - - qemu_put_be32(f, s->irqlevel); - qemu_put_be32(f, s->transp); - - for (i = 0; i < 6; i ++) - qemu_put_be32s(f, &s->control[i]); - for (i = 0; i < 2; i ++) - qemu_put_be32s(f, &s->status[i]); - for (i = 0; i < 2; i ++) - qemu_put_be32s(f, &s->ovl1c[i]); - for (i = 0; i < 2; i ++) - qemu_put_be32s(f, &s->ovl2c[i]); - qemu_put_be32s(f, &s->ccr); - qemu_put_be32s(f, &s->cmdcr); - qemu_put_be32s(f, &s->trgbr); - qemu_put_be32s(f, &s->tcr); - qemu_put_be32s(f, &s->liidr); - qemu_put_8s(f, &s->bscntr); - - for (i = 0; i < 7; i ++) { - qemu_put_betl(f, s->dma_ch[i].branch); - qemu_put_byte(f, s->dma_ch[i].up); - qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer)); - - qemu_put_betl(f, s->dma_ch[i].descriptor); - qemu_put_betl(f, s->dma_ch[i].source); - qemu_put_be32s(f, &s->dma_ch[i].id); - qemu_put_be32s(f, &s->dma_ch[i].command); +static const VMStateDescription vmstate_dma_channel = { + .name = "dma_channel", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINTTL(branch, struct DMAChannel), + VMSTATE_UINT8(up, struct DMAChannel), + VMSTATE_BUFFER(pbuffer, struct DMAChannel), + VMSTATE_UINTTL(descriptor, struct DMAChannel), + VMSTATE_UINTTL(source, struct DMAChannel), + VMSTATE_UINT32(id, struct DMAChannel), + VMSTATE_UINT32(command, struct DMAChannel), + VMSTATE_END_OF_LIST() } -} +}; -static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id) +static int pxa2xx_lcdc_post_load(void *opaque, int version_id) { - PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; - int i; - - s->irqlevel = qemu_get_be32(f); - s->transp = qemu_get_be32(f); - - for (i = 0; i < 6; i ++) - qemu_get_be32s(f, &s->control[i]); - for (i = 0; i < 2; i ++) - qemu_get_be32s(f, &s->status[i]); - for (i = 0; i < 2; i ++) - qemu_get_be32s(f, &s->ovl1c[i]); - for (i = 0; i < 2; i ++) - qemu_get_be32s(f, &s->ovl2c[i]); - qemu_get_be32s(f, &s->ccr); - qemu_get_be32s(f, &s->cmdcr); - qemu_get_be32s(f, &s->trgbr); - qemu_get_be32s(f, &s->tcr); - qemu_get_be32s(f, &s->liidr); - qemu_get_8s(f, &s->bscntr); - - for (i = 0; i < 7; i ++) { - s->dma_ch[i].branch = qemu_get_betl(f); - s->dma_ch[i].up = qemu_get_byte(f); - qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer)); - - s->dma_ch[i].descriptor = qemu_get_betl(f); - s->dma_ch[i].source = qemu_get_betl(f); - qemu_get_be32s(f, &s->dma_ch[i].id); - qemu_get_be32s(f, &s->dma_ch[i].command); - } + PXA2xxLCDState *s = opaque; s->bpp = LCCR3_BPP(s->control[3]); s->xres = s->yres = s->pal_for = -1; @@ -906,6 +860,31 @@ static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id) return 0; } +static const VMStateDescription vmstate_pxa2xx_lcdc = { + .name = "pxa2xx_lcdc", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .post_load = pxa2xx_lcdc_post_load, + .fields = (VMStateField[]) { + VMSTATE_INT32(irqlevel, PXA2xxLCDState), + VMSTATE_INT32(transp, PXA2xxLCDState), + VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6), + VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2), + VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2), + VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2), + VMSTATE_UINT32(ccr, PXA2xxLCDState), + VMSTATE_UINT32(cmdcr, PXA2xxLCDState), + VMSTATE_UINT32(trgbr, PXA2xxLCDState), + VMSTATE_UINT32(tcr, PXA2xxLCDState), + VMSTATE_UINT32(liidr, PXA2xxLCDState), + VMSTATE_UINT8(bscntr, PXA2xxLCDState), + VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0, + vmstate_dma_channel, struct DMAChannel), + VMSTATE_END_OF_LIST() + } +}; + #define BITS 8 #include "pxa2xx_template.h" #define BITS 15 @@ -970,8 +949,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq) exit(1); } - register_savevm(NULL, "pxa2xx_lcdc", 0, 0, - pxa2xx_lcdc_save, pxa2xx_lcdc_load, s); + vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s); return s; } diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 1088a26f8..eff2d2494 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -354,10 +354,10 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str) if (*ptr == NULL) { return -ENOENT; } - if ((*ptr)->assigned) { + if ((*ptr)->avail_connections < 1) { return -EEXIST; } - (*ptr)->assigned = 1; + --(*ptr)->avail_connections; return 0; } diff --git a/hw/rtl8139.c b/hw/rtl8139.c index d5459336e..515652f27 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -85,9 +85,13 @@ #define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) #if defined (DEBUG_RTL8139) -# define DEBUG_PRINT(x) do { printf x ; } while (0) +# define DPRINTF(fmt, ...) \ + do { fprintf(stderr, "RTL8139: " fmt, ## __VA_ARGS__); } while (0) #else -# define DEBUG_PRINT(x) +static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) +{ + return 0; +} #endif /* Symbolic offsets to registers. */ @@ -510,7 +514,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time); static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) { - DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command)); + DPRINTF("eeprom command 0x%02x\n", command); switch (command & Chip9346_op_mask) { @@ -521,8 +525,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) eeprom->eedo = 0; eeprom->tick = 0; eeprom->mode = Chip9346_data_read; - DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output)); + DPRINTF("eeprom read from address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); } break; @@ -532,8 +536,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) eeprom->input = 0; eeprom->tick = 0; eeprom->mode = Chip9346_none; /* Chip9346_data_write */ - DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n", - eeprom->address)); + DPRINTF("eeprom begin write to address 0x%02x\n", + eeprom->address); } break; default: @@ -541,13 +545,13 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) switch (command & Chip9346_op_ext_mask) { case Chip9346_op_write_enable: - DEBUG_PRINT(("RTL8139: eeprom write enabled\n")); + DPRINTF("eeprom write enabled\n"); break; case Chip9346_op_write_all: - DEBUG_PRINT(("RTL8139: eeprom begin write all\n")); + DPRINTF("eeprom begin write all\n"); break; case Chip9346_op_write_disable: - DEBUG_PRINT(("RTL8139: eeprom write disabled\n")); + DPRINTF("eeprom write disabled\n"); break; } break; @@ -560,7 +564,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) ++ eeprom->tick; - DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo)); + DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, + eeprom->eedo); switch (eeprom->mode) { @@ -570,7 +575,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) eeprom->mode = Chip9346_read_command; eeprom->tick = 0; eeprom->input = 0; - DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n")); + DPRINTF("eeprom: +++ synchronized, begin command read\n"); } break; @@ -595,7 +600,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) eeprom->input = 0; eeprom->tick = 0; - DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n")); + DPRINTF("eeprom: +++ end of read, awaiting next command\n"); #else // original behaviour ++eeprom->address; @@ -603,8 +608,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) eeprom->output = eeprom->contents[eeprom->address]; eeprom->tick = 0; - DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output)); + DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); #endif } break; @@ -613,8 +618,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) eeprom->input = (eeprom->input << 1) | (bit & 1); if (eeprom->tick == 16) { - DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->input)); + DPRINTF("eeprom write to address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->input); eeprom->contents[eeprom->address] = eeprom->input; eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ @@ -632,8 +637,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) { eeprom->contents[i] = eeprom->input; } - DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n", - eeprom->input)); + DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input); eeprom->mode = Chip9346_enter_command_mode; eeprom->tick = 0; @@ -666,8 +670,8 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) eeprom->eesk = eesk; eeprom->eedi = eedi; - DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", - eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo)); + DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, + eeprom->eesk, eeprom->eedi, eeprom->eedo); if (!old_eecs && eecs) { @@ -677,12 +681,12 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) eeprom->output = 0; eeprom->mode = Chip9346_enter_command_mode; - DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n")); + DPRINTF("=== eeprom: begin access, enter command mode\n"); } if (!eecs) { - DEBUG_PRINT(("=== eeprom: end access\n")); + DPRINTF("=== eeprom: end access\n"); return; } @@ -698,8 +702,8 @@ static void rtl8139_update_irq(RTL8139State *s) int isr; isr = (s->IntrStatus & s->IntrMask) & 0xffff; - DEBUG_PRINT(("RTL8139: Set IRQ to %d (%04x %04x)\n", - isr ? 1 : 0, s->IntrStatus, s->IntrMask)); + DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus, + s->IntrMask); qemu_set_irq(s->dev.irq[0], (isr != 0)); } @@ -763,7 +767,7 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) /* write packet data */ if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) { - DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped)); + DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped); if (size > wrapped) { @@ -834,12 +838,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - DEBUG_PRINT((">>> RTL8139: received len=%d\n", size)); + DPRINTF(">>> received len=%d\n", size); /* test if board clock is stopped */ if (!s->clock_enabled) { - DEBUG_PRINT(("RTL8139: stopped ==========================\n")); + DPRINTF("stopped ==========================\n"); return -1; } @@ -847,21 +851,21 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (!rtl8139_receiver_enabled(s)) { - DEBUG_PRINT(("RTL8139: receiver disabled ================\n")); + DPRINTF("receiver disabled ================\n"); return -1; } /* XXX: check this */ if (s->RxConfig & AcceptAllPhys) { /* promiscuous: receive all */ - DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n")); + DPRINTF(">>> packet received in promiscuous mode\n"); } else { if (!memcmp(buf, broadcast_macaddr, 6)) { /* broadcast address */ if (!(s->RxConfig & AcceptBroadcast)) { - DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n")); + DPRINTF(">>> broadcast packet rejected\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -871,7 +875,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ packet_header |= RxBroadcast; - DEBUG_PRINT((">>> RTL8139: broadcast packet received\n")); + DPRINTF(">>> broadcast packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkBrd; @@ -880,7 +884,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* multicast */ if (!(s->RxConfig & AcceptMulticast)) { - DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n")); + DPRINTF(">>> multicast packet rejected\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -892,7 +896,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { - DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n")); + DPRINTF(">>> multicast address mismatch\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -902,7 +906,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ packet_header |= RxMulticast; - DEBUG_PRINT((">>> RTL8139: multicast packet received\n")); + DPRINTF(">>> multicast packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkMul; @@ -916,7 +920,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* match */ if (!(s->RxConfig & AcceptMyPhys)) { - DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n")); + DPRINTF(">>> rejecting physical address matching packet\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -926,14 +930,14 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ packet_header |= RxPhysical; - DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n")); + DPRINTF(">>> physical address matching packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkPhy; } else { - DEBUG_PRINT((">>> RTL8139: unknown packet\n")); + DPRINTF(">>> unknown packet\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -955,7 +959,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (rtl8139_cp_receiver_enabled(s)) { - DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n")); + DPRINTF("in C+ Rx mode ================\n"); /* begin C+ receiver mode */ @@ -978,8 +982,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor; - DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n", - descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc)); + DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at " + "%08x %08x = "TARGET_FMT_plx"\n", descriptor, s->RxRingAddrHI, + s->RxRingAddrLO, cplus_rx_ring_desc); uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; @@ -992,13 +997,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4); rxbufHI = le32_to_cpu(val); - DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", - descriptor, - rxdw0, rxdw1, rxbufLO, rxbufHI)); + DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", + descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); if (!(rxdw0 & CP_RX_OWN)) { - DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor)); + DPRINTF("C+ Rx mode : descriptor %d is owned by host\n", + descriptor); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1028,9 +1033,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *) &dot1q_buf[ETHER_TYPE_LEN]); - DEBUG_PRINT(("RTL8139: C+ Rx mode : extracted vlan tag with tci: " - "%u\n", be16_to_cpup((uint16_t *) - &dot1q_buf[ETHER_TYPE_LEN]))); + DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n", + be16_to_cpup((uint16_t *)&dot1q_buf[ETHER_TYPE_LEN])); } else { /* reset VLAN tag flag */ rxdw1 &= ~CP_RX_TAVA; @@ -1040,8 +1044,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (size+4 > rx_space) { - DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n", - descriptor, rx_space, size)); + DPRINTF("C+ Rx mode : descriptor %d size %d received %d + 4\n", + descriptor, rx_space, size); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1136,12 +1140,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ ++s->currCPlusRxDesc; } - DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n")); + DPRINTF("done C+ Rx mode ----------------\n"); } else { - DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n")); + DPRINTF("in ring Rx mode ================\n"); /* begin ring receiver mode */ int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); @@ -1150,8 +1154,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (avail != 0 && size + 8 >= avail) { - DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8)); + DPRINTF("rx overflow: rx buffer length %d head 0x%04x " + "read 0x%04x === available 0x%04x need 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1179,8 +1184,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* now we can signal we have received something */ - DEBUG_PRINT((" received: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr)); + DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } s->IntrStatus |= RxOK; @@ -1374,22 +1379,22 @@ static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val)); + DPRINTF("ChipCmd write val=0x%08x\n", val); if (val & CmdReset) { - DEBUG_PRINT(("RTL8139: ChipCmd reset\n")); + DPRINTF("ChipCmd reset\n"); rtl8139_reset(&s->dev.qdev); } if (val & CmdRxEnb) { - DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n")); + DPRINTF("ChipCmd enable receiver\n"); s->currCPlusRxDesc = 0; } if (val & CmdTxEnb) { - DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n")); + DPRINTF("ChipCmd enable transmitter\n"); s->currCPlusTxDesc = 0; } @@ -1409,11 +1414,11 @@ static int rtl8139_RxBufferEmpty(RTL8139State *s) if (unread != 0) { - DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", unread)); + DPRINTF("receiver buffer data available 0x%04x\n", unread); return 0; } - DEBUG_PRINT(("RTL8139: receiver buffer is empty\n")); + DPRINTF("receiver buffer is empty\n"); return 1; } @@ -1425,7 +1430,7 @@ static uint32_t rtl8139_ChipCmd_read(RTL8139State *s) if (rtl8139_RxBufferEmpty(s)) ret |= RxBufEmpty; - DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret)); + DPRINTF("ChipCmd read val=0x%04x\n", ret); return ret; } @@ -1434,7 +1439,7 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val)); + DPRINTF("C+ command register write(w) val=0x%04x\n", val); s->cplus_enabled = 1; @@ -1448,21 +1453,21 @@ static uint32_t rtl8139_CpCmd_read(RTL8139State *s) { uint32_t ret = s->CpCmd; - DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret)); + DPRINTF("C+ command register read(w) val=0x%04x\n", ret); return ret; } static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", val)); + DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val); } static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s) { uint32_t ret = 0; - DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret)); + DPRINTF("C+ IntrMitigate register read(w) val=0x%04x\n", ret); return ret; } @@ -1474,7 +1479,7 @@ static int rtl8139_config_writeable(RTL8139State *s) return 1; } - DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n")); + DPRINTF("Configuration registers are write-protected\n"); return 0; } @@ -1483,7 +1488,7 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val)); + DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val); /* mask unwriteable bits */ uint32_t mask = 0x4cff; @@ -1505,7 +1510,7 @@ static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s) { uint32_t ret = s->BasicModeCtrl; - DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret)); + DPRINTF("BasicModeCtrl register read(w) val=0x%04x\n", ret); return ret; } @@ -1514,7 +1519,7 @@ static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val)); + DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0xff3f, s->BasicModeStatus); @@ -1526,7 +1531,7 @@ static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s) { uint32_t ret = s->BasicModeStatus; - DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret)); + DPRINTF("BasicModeStatus register read(w) val=0x%04x\n", ret); return ret; } @@ -1535,7 +1540,7 @@ static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val)); + DPRINTF("Cfg9346 write val=0x%02x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0x31, s->Cfg9346); @@ -1578,7 +1583,7 @@ static uint32_t rtl8139_Cfg9346_read(RTL8139State *s) } } - DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret)); + DPRINTF("Cfg9346 read val=0x%02x\n", ret); return ret; } @@ -1587,7 +1592,7 @@ static void rtl8139_Config0_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val)); + DPRINTF("Config0 write val=0x%02x\n", val); if (!rtl8139_config_writeable(s)) return; @@ -1602,7 +1607,7 @@ static uint32_t rtl8139_Config0_read(RTL8139State *s) { uint32_t ret = s->Config0; - DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret)); + DPRINTF("Config0 read val=0x%02x\n", ret); return ret; } @@ -1611,7 +1616,7 @@ static void rtl8139_Config1_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val)); + DPRINTF("Config1 write val=0x%02x\n", val); if (!rtl8139_config_writeable(s)) return; @@ -1626,7 +1631,7 @@ static uint32_t rtl8139_Config1_read(RTL8139State *s) { uint32_t ret = s->Config1; - DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret)); + DPRINTF("Config1 read val=0x%02x\n", ret); return ret; } @@ -1635,7 +1640,7 @@ static void rtl8139_Config3_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val)); + DPRINTF("Config3 write val=0x%02x\n", val); if (!rtl8139_config_writeable(s)) return; @@ -1650,7 +1655,7 @@ static uint32_t rtl8139_Config3_read(RTL8139State *s) { uint32_t ret = s->Config3; - DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret)); + DPRINTF("Config3 read val=0x%02x\n", ret); return ret; } @@ -1659,7 +1664,7 @@ static void rtl8139_Config4_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val)); + DPRINTF("Config4 write val=0x%02x\n", val); if (!rtl8139_config_writeable(s)) return; @@ -1674,7 +1679,7 @@ static uint32_t rtl8139_Config4_read(RTL8139State *s) { uint32_t ret = s->Config4; - DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret)); + DPRINTF("Config4 read val=0x%02x\n", ret); return ret; } @@ -1683,7 +1688,7 @@ static void rtl8139_Config5_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val)); + DPRINTF("Config5 write val=0x%02x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0x80, s->Config5); @@ -1695,7 +1700,7 @@ static uint32_t rtl8139_Config5_read(RTL8139State *s) { uint32_t ret = s->Config5; - DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret)); + DPRINTF("Config5 read val=0x%02x\n", ret); return ret; } @@ -1704,11 +1709,11 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) { if (!rtl8139_transmitter_enabled(s)) { - DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val)); + DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val); return; } - DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val)); + DPRINTF("TxConfig write val=0x%08x\n", val); val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig); @@ -1717,7 +1722,7 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val)); + DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val); uint32_t tc = s->TxConfig; tc &= 0xFFFFFF00; @@ -1729,14 +1734,14 @@ static uint32_t rtl8139_TxConfig_read(RTL8139State *s) { uint32_t ret = s->TxConfig; - DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret)); + DPRINTF("TxConfig read val=0x%04x\n", ret); return ret; } static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val)); + DPRINTF("RxConfig write val=0x%08x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0xf0fc0040, s->RxConfig); @@ -1746,14 +1751,14 @@ static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) /* reset buffer size and read/write pointers */ rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3)); - DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize)); + DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize); } static uint32_t rtl8139_RxConfig_read(RTL8139State *s) { uint32_t ret = s->RxConfig; - DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret)); + DPRINTF("RxConfig read val=0x%08x\n", ret); return ret; } @@ -1765,7 +1770,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, if (!size) { - DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n")); + DPRINTF("+++ empty ethernet frame\n"); return; } @@ -1790,7 +1795,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, buf = buf2; } - DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n")); + DPRINTF("+++ transmit loopback mode\n"); rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt); if (iov) { @@ -1811,25 +1816,25 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor) { if (!rtl8139_transmitter_enabled(s)) { - DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n", - descriptor)); + DPRINTF("+++ cannot transmit from descriptor %d: transmitter " + "disabled\n", descriptor); return 0; } if (s->TxStatus[descriptor] & TxHostOwns) { - DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n", - descriptor, s->TxStatus[descriptor])); + DPRINTF("+++ cannot transmit from descriptor %d: owned by host " + "(%08x)\n", descriptor, s->TxStatus[descriptor]); return 0; } - DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", descriptor)); + DPRINTF("+++ transmitting from descriptor %d\n", descriptor); int txsize = s->TxStatus[descriptor] & 0x1fff; uint8_t txbuffer[0x2000]; - DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n", - txsize, s->TxAddr[descriptor])); + DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n", + txsize, s->TxAddr[descriptor]); cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize); @@ -1839,7 +1844,8 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor) rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL); - DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor)); + DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize, + descriptor); /* update interrupt */ s->IntrStatus |= TxOK; @@ -1939,13 +1945,13 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) { if (!rtl8139_transmitter_enabled(s)) { - DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n")); + DPRINTF("+++ C+ mode: transmitter disabled\n"); return 0; } if (!rtl8139_cp_transmitter_enabled(s)) { - DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n")); + DPRINTF("+++ C+ mode: C+ transmitter disabled\n"); return 0 ; } @@ -1957,8 +1963,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* Normal priority ring */ cplus_tx_ring_desc += 16 * descriptor; - DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n", - descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc)); + DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " + "%08x0x%08x = 0x"TARGET_FMT_plx"\n", descriptor, s->TxAddr[1], + s->TxAddr[0], cplus_tx_ring_desc); uint32_t val, txdw0,txdw1,txbufLO,txbufHI; @@ -1971,9 +1978,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4); txbufHI = le32_to_cpu(val); - DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", - descriptor, - txdw0, txdw1, txbufLO, txbufHI)); + DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, + txdw0, txdw1, txbufLO, txbufHI); /* w0 ownership flag */ #define CP_TX_OWN (1<<31) @@ -2019,15 +2025,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) if (!(txdw0 & CP_TX_OWN)) { - DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor)); + DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor); return 0 ; } - DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor)); + DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); if (txdw0 & CP_TX_FS) { - DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor)); + DPRINTF("+++ C+ Tx mode : descriptor %d is first segment " + "descriptor\n", descriptor); /* reset internal buffer offset */ s->cplus_txbuffer_offset = 0; @@ -2043,7 +2050,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer = qemu_malloc(s->cplus_txbuffer_len); s->cplus_txbuffer_offset = 0; - DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len)); + DPRINTF("+++ C+ mode transmission buffer allocated space %d\n", + s->cplus_txbuffer_len); } while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) @@ -2051,14 +2059,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE; s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len); - DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len)); + DPRINTF("+++ C+ mode transmission buffer space changed to %d\n", + s->cplus_txbuffer_len); } if (!s->cplus_txbuffer) { /* out of memory */ - DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d bytes\n", s->cplus_txbuffer_len)); + DPRINTF("+++ C+ mode transmiter failed to reallocate %d bytes\n", + s->cplus_txbuffer_len); /* update tally counter */ ++s->tally_counters.TxERR; @@ -2069,8 +2079,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* append more data to the packet */ - DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n", - txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset)); + DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at " + TARGET_FMT_plx" to offset %d\n", txsize, tx_addr, + s->cplus_txbuffer_offset); cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize); s->cplus_txbuffer_offset += txsize; @@ -2107,7 +2118,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) uint8_t dot1q_buffer_space[VLAN_HLEN]; uint16_t *dot1q_buffer; - DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor)); + DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n", + descriptor); /* can transfer fully assembled packet */ @@ -2119,8 +2131,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) if (txdw1 & CP_TX_TAGC) { /* the vlan tag is in BE byte order in the descriptor * BE + le_to_cpu() + ~swap()~ = cpu */ - DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with " - "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK))); + DPRINTF("+++ C+ Tx mode : inserting vlan tag with ""tci: %u\n", + bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); dot1q_buffer = (uint16_t *) dot1q_buffer_space; dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q); @@ -2137,7 +2149,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) { - DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n")); + DPRINTF("+++ C+ mode offloaded task checksum\n"); /* ip packet header */ ip_header *ip = NULL; @@ -2151,7 +2163,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); if (proto == ETH_P_IP) { - DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n")); + DPRINTF("+++ C+ mode has IP packet\n"); /* not aligned */ eth_payload_data = saved_buffer + ETH_HLEN; @@ -2160,7 +2172,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) ip = (ip_header*)eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { - DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4)); + DPRINTF("+++ C+ mode packet has bad IP version %d " + "expected %d\n", IP_HEADER_VERSION(ip), + IP_HEADER_VERSION_4); ip = NULL; } else { hlen = IP_HEADER_LENGTH(ip); @@ -2173,7 +2187,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) { if (txdw0 & CP_TX_IPCS) { - DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n")); + DPRINTF("+++ C+ mode need IP checksum\n"); if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ /* bad packet header len */ @@ -2183,17 +2197,18 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) { ip->ip_sum = 0; ip->ip_sum = ip_checksum(ip, hlen); - DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum)); + DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", + hlen, ip->ip_sum); } } if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) { -#if defined (DEBUG_RTL8139) int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; -#endif - DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n", - ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss)); + + DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " + "frame data %d specified MSS=%d\n", ETH_MTU, + ip_data_len, saved_size - ETH_HLEN, large_send_mss); int tcp_send_offset = 0; int send_count = 0; @@ -2217,8 +2232,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) int tcp_data_len = ip_data_len - tcp_hlen; int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n", - ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size)); + DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " + "data len %d TCP chunk size %d\n", ip_data_len, + tcp_hlen, tcp_data_len, tcp_chunk_size); /* note the cycle below overwrites IP header data, but restores it from saved_ip_header before sending packet */ @@ -2236,13 +2252,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) chunk_size = tcp_data_len - tcp_send_offset; } - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq))); + DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", + be32_to_cpu(p_tcp_hdr->th_seq)); /* add 4 TCP pseudoheader fields */ /* copy IP source and destination fields */ memcpy(data_to_checksum, saved_ip_header + 12, 8); - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size)); + DPRINTF("+++ C+ mode TSO calculating TCP checksum for " + "packet with %d bytes data\n", tcp_hlen + + chunk_size); if (tcp_send_offset) { @@ -2264,7 +2283,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum)); + DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", + tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; @@ -2279,10 +2299,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) ip->ip_sum = 0; ip->ip_sum = ip_checksum(eth_payload_data, hlen); - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum)); + DPRINTF("+++ C+ mode TSO IP header len=%d " + "checksum=%04x\n", hlen, ip->ip_sum); int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; - DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size)); + DPRINTF("+++ C+ mode TSO transferring packet size " + "%d\n", tso_send_size); rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0, (uint8_t *) dot1q_buffer); @@ -2296,7 +2318,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) { - DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n")); + DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; @@ -2311,7 +2333,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) { - DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len)); + DPRINTF("+++ C+ mode calculating TCP checksum for " + "packet with %d bytes data\n", ip_data_len); ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; p_tcpip_hdr->zeros = 0; @@ -2323,13 +2346,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); - DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum)); + DPRINTF("+++ C+ mode TCP checksum %04x\n", + tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; } else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) { - DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len)); + DPRINTF("+++ C+ mode calculating UDP checksum for " + "packet with %d bytes data\n", ip_data_len); ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; p_udpip_hdr->zeros = 0; @@ -2341,7 +2366,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) p_udp_hdr->uh_sum = 0; int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); - DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum)); + DPRINTF("+++ C+ mode UDP checksum %04x\n", + udp_checksum); p_udp_hdr->uh_sum = udp_checksum; } @@ -2355,7 +2381,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* update tally counter */ ++s->tally_counters.TxOk; - DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size)); + DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size); rtl8139_transfer_frame(s, saved_buffer, saved_size, 1, (uint8_t *) dot1q_buffer); @@ -2374,7 +2400,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } else { - DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next descriptor\n")); + DPRINTF("+++ C+ mode transmission continue to next descriptor\n"); } return 1; @@ -2392,8 +2418,8 @@ static void rtl8139_cplus_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { - DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n", - s->currCPlusTxDesc)); + DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n", + s->currCPlusTxDesc); } else { @@ -2418,7 +2444,8 @@ static void rtl8139_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { - DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc)); + DPRINTF("transmitter queue stalled, current TxDesc = %d\n", + s->currTxDesc); } } @@ -2431,7 +2458,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32 if (s->cplus_enabled) { - DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor)); + DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " + "descriptor=%d\n", txRegOffset, val, descriptor); /* handle Dump Tally Counters command */ s->TxStatus[descriptor] = val; @@ -2450,7 +2478,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32 return; } - DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor)); + DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", + txRegOffset, val, descriptor); /* mask only reserved bits */ val &= ~0xff00c000; /* these bits are reset on write */ @@ -2466,7 +2495,7 @@ static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset) { uint32_t ret = s->TxStatus[txRegOffset/4]; - DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret)); + DPRINTF("TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret); return ret; } @@ -2498,7 +2527,7 @@ static uint16_t rtl8139_TSAD_read(RTL8139State *s) |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; - DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret)); + DPRINTF("TSAD read val=0x%04x\n", ret); return ret; } @@ -2507,14 +2536,14 @@ static uint16_t rtl8139_CSCR_read(RTL8139State *s) { uint16_t ret = s->CSCR; - DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret)); + DPRINTF("CSCR read val=0x%04x\n", ret); return ret; } static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) { - DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val)); + DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); s->TxAddr[txAddrOffset/4] = val; } @@ -2523,20 +2552,20 @@ static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) { uint32_t ret = s->TxAddr[txAddrOffset/4]; - DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret)); + DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret); return ret; } static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val)); + DPRINTF("RxBufPtr write val=0x%04x\n", val); /* this value is off by 16 */ s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); - DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr)); + DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) @@ -2544,7 +2573,7 @@ static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) /* this value is off by 16 */ uint32_t ret = s->RxBufPtr - 0x10; - DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret)); + DPRINTF("RxBufPtr read val=0x%04x\n", ret); return ret; } @@ -2554,14 +2583,14 @@ static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s) /* this value is NOT off by 16 */ uint32_t ret = s->RxBufAddr; - DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret)); + DPRINTF("RxBufAddr read val=0x%04x\n", ret); return ret; } static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val)); + DPRINTF("RxBuf write val=0x%08x\n", val); s->RxBuf = val; @@ -2572,14 +2601,14 @@ static uint32_t rtl8139_RxBuf_read(RTL8139State *s) { uint32_t ret = s->RxBuf; - DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret)); + DPRINTF("RxBuf read val=0x%08x\n", ret); return ret; } static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val)); + DPRINTF("IntrMask write(w) val=0x%04x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0x1e00, s->IntrMask); @@ -2595,14 +2624,14 @@ static uint32_t rtl8139_IntrMask_read(RTL8139State *s) { uint32_t ret = s->IntrMask; - DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret)); + DPRINTF("IntrMask read(w) val=0x%04x\n", ret); return ret; } static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val)); + DPRINTF("IntrStatus write(w) val=0x%04x\n", val); #if 0 @@ -2639,7 +2668,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) uint32_t ret = s->IntrStatus; - DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret)); + DPRINTF("IntrStatus read(w) val=0x%04x\n", ret); #if 0 @@ -2655,7 +2684,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) { - DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val)); + DPRINTF("MultiIntr write(w) val=0x%04x\n", val); /* mask unwriteable bits */ val = SET_MASKED(val, 0xf000, s->MultiIntr); @@ -2667,7 +2696,7 @@ static uint32_t rtl8139_MultiIntr_read(RTL8139State *s) { uint32_t ret = s->MultiIntr; - DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret)); + DPRINTF("MultiIntr read(w) val=0x%04x\n", ret); return ret; } @@ -2715,11 +2744,12 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) break; case MediaStatus: /* ignore */ - DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus val=0x%02x\n", val)); + DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n", + val); break; case HltClk: - DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val)); + DPRINTF("HltClk write val=0x%08x\n", val); if (val == 'R') { s->clock_enabled = 1; @@ -2731,27 +2761,29 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) break; case TxThresh: - DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val)); + DPRINTF("C+ TxThresh write(b) val=0x%02x\n", val); s->TxThresh = val; break; case TxPoll: - DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val)); + DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val); if (val & (1 << 7)) { - DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not implemented)\n")); + DPRINTF("C+ TxPoll high priority transmission (not " + "implemented)\n"); //rtl8139_cplus_transmit(s); } if (val & (1 << 6)) { - DEBUG_PRINT(("RTL8139C+ TxPoll normal priority transmission\n")); + DPRINTF("C+ TxPoll normal priority transmission\n"); rtl8139_cplus_transmit(s); } break; default: - DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", addr, val)); + DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr, + val); break; } } @@ -2787,14 +2819,14 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val) rtl8139_BasicModeStatus_write(s, val); break; case NWayAdvert: - DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val)); + DPRINTF("NWayAdvert write(w) val=0x%04x\n", val); s->NWayAdvert = val; break; case NWayLPAR: - DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val)); + DPRINTF("forbidden NWayLPAR write(w) val=0x%04x\n", val); break; case NWayExpansion: - DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val)); + DPRINTF("NWayExpansion write(w) val=0x%04x\n", val); s->NWayExpansion = val; break; @@ -2807,7 +2839,8 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val) break; default: - DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val)); + DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", + addr, val); rtl8139_io_writeb(opaque, addr, val & 0xff); rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff); @@ -2820,7 +2853,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time) int64_t pci_time, next_time; uint32_t low_pci; - DEBUG_PRINT(("RTL8139: entered rtl8139_set_next_tctr_time\n")); + DPRINTF("entered rtl8139_set_next_tctr_time\n"); if (s->TimerExpire && current_time >= s->TimerExpire) { s->IntrStatus |= PCSTimeout; @@ -2864,7 +2897,7 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) switch (addr) { case RxMissed: - DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n")); + DPRINTF("RxMissed clearing on write\n"); s->RxMissed = 0; break; @@ -2889,23 +2922,23 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) break; case RxRingAddrLO: - DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", val)); + DPRINTF("C+ RxRing low bits write val=0x%08x\n", val); s->RxRingAddrLO = val; break; case RxRingAddrHI: - DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", val)); + DPRINTF("C+ RxRing high bits write val=0x%08x\n", val); s->RxRingAddrHI = val; break; case Timer: - DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n")); + DPRINTF("TCTR Timer reset on write\n"); s->TCTR_base = qemu_get_clock_ns(vm_clock); rtl8139_set_next_tctr_time(s, s->TCTR_base); break; case FlashReg: - DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val)); + DPRINTF("FlashReg TimerInt write val=0x%08x\n", val); if (s->TimerInt != val) { s->TimerInt = val; rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock)); @@ -2913,7 +2946,8 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) break; default: - DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val)); + DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", + addr, val); rtl8139_io_writeb(opaque, addr, val & 0xff); rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff); rtl8139_io_writeb(opaque, addr + 2, (val >> 16) & 0xff); @@ -2964,31 +2998,31 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr) case MediaStatus: ret = 0xd0; - DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret)); + DPRINTF("MediaStatus read 0x%x\n", ret); break; case HltClk: ret = s->clock_enabled; - DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret)); + DPRINTF("HltClk read 0x%x\n", ret); break; case PCIRevisionID: ret = RTL8139_PCI_REVID; - DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret)); + DPRINTF("PCI Revision ID read 0x%x\n", ret); break; case TxThresh: ret = s->TxThresh; - DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret)); + DPRINTF("C+ TxThresh read(b) val=0x%02x\n", ret); break; case 0x43: /* Part of TxConfig register. Windows driver tries to read it */ ret = s->TxConfig >> 24; - DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret)); + DPRINTF("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); break; default: - DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", addr)); + DPRINTF("not implemented read(b) addr=0x%x\n", addr); ret = 0; break; } @@ -3033,15 +3067,15 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr) break; case NWayAdvert: ret = s->NWayAdvert; - DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret)); + DPRINTF("NWayAdvert read(w) val=0x%04x\n", ret); break; case NWayLPAR: ret = s->NWayLPAR; - DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret)); + DPRINTF("NWayLPAR read(w) val=0x%04x\n", ret); break; case NWayExpansion: ret = s->NWayExpansion; - DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret)); + DPRINTF("NWayExpansion read(w) val=0x%04x\n", ret); break; case CpCmd: @@ -3061,12 +3095,12 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr) break; default: - DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr)); + DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr); ret = rtl8139_io_readb(opaque, addr); ret |= rtl8139_io_readb(opaque, addr + 1) << 8; - DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, ret)); + DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); break; } @@ -3085,7 +3119,7 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) case RxMissed: ret = s->RxMissed; - DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret)); + DPRINTF("RxMissed read val=0x%08x\n", ret); break; case TxConfig: @@ -3110,34 +3144,34 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) case RxRingAddrLO: ret = s->RxRingAddrLO; - DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret)); + DPRINTF("C+ RxRing low bits read val=0x%08x\n", ret); break; case RxRingAddrHI: ret = s->RxRingAddrHI; - DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret)); + DPRINTF("C+ RxRing high bits read val=0x%08x\n", ret); break; case Timer: ret = muldiv64(qemu_get_clock_ns(vm_clock) - s->TCTR_base, PCI_FREQUENCY, get_ticks_per_sec()); - DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret)); + DPRINTF("TCTR Timer read val=0x%08x\n", ret); break; case FlashReg: ret = s->TimerInt; - DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret)); + DPRINTF("FlashReg TimerInt read val=0x%08x\n", ret); break; default: - DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr)); + DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr); ret = rtl8139_io_readb(opaque, addr); ret |= rtl8139_io_readb(opaque, addr + 1) << 8; ret |= rtl8139_io_readb(opaque, addr + 2) << 16; ret |= rtl8139_io_readb(opaque, addr + 3) << 24; - DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret)); + DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret); break; } @@ -3382,7 +3416,7 @@ static void rtl8139_timer(void *opaque) if (!s->clock_enabled) { - DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n")); + DPRINTF(">>> timer: clock is not running\n"); return; } @@ -3484,7 +3518,7 @@ static PCIDeviceInfo rtl8139_info = { .qdev.vmsd = &vmstate_rtl8139, .init = pci_rtl8139_init, .exit = pci_rtl8139_uninit, - .romfile = "pxe-rtl8139.bin", + .romfile = "pxe-rtl8139.rom", .qdev.props = (Property[]) { DEFINE_NIC_PROPERTIES(RTL8139State, conf), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 175e5cb3a..bb49e393e 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -43,6 +43,8 @@ do { } while (0) #endif +#define VIRTIO_EXT_CODE 0x2603 + struct BusInfo s390_virtio_bus_info = { .name = "s390-virtio", .size = sizeof(VirtIOS390Bus), @@ -305,9 +307,13 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) { VirtIOS390Device *dev = (VirtIOS390Device*)opaque; uint64_t token = s390_virtio_device_vq_token(dev, vector); + CPUState *env = s390_cpu_addr2state(0); - /* XXX kvm dependency! */ - kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token); + if (kvm_enabled()) { + kvm_s390_virtio_irq(env, 0, token); + } else { + cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token); + } } static unsigned virtio_s390_get_features(void *opaque) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index d429f10d5..698ff6f34 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -82,13 +82,12 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr) return ipi_states[cpu_addr]; } -int s390_virtio_hypercall(CPUState *env) +int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall) { int r = 0, i; - target_ulong mem = env->regs[2]; - dprintf("KVM hypercall: %ld\n", env->regs[1]); - switch (env->regs[1]) { + dprintf("KVM hypercall: %ld\n", hypercall); + switch (hypercall) { case KVM_S390_VIRTIO_NOTIFY: if (mem > ram_size) { VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, @@ -128,8 +127,7 @@ int s390_virtio_hypercall(CPUState *env) break; } - env->regs[2] = r; - return 0; + return r; } /* PC hardware initialisation */ @@ -145,14 +143,9 @@ static void s390_init(ram_addr_t ram_size, ram_addr_t kernel_size = 0; ram_addr_t initrd_offset; ram_addr_t initrd_size = 0; + uint8_t *storage_keys; int i; - /* XXX we only work on KVM for now */ - - if (!kvm_enabled()) { - fprintf(stderr, "The S390 target only works with KVM enabled\n"); - exit(1); - } /* get a BUS */ s390_bus = s390_virtio_bus_init(&ram_size); @@ -161,6 +154,9 @@ static void s390_init(ram_addr_t ram_size, ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size); cpu_register_physical_memory(0, ram_size, ram_addr); + /* allocate storage keys */ + storage_keys = qemu_mallocz(ram_size / TARGET_PAGE_SIZE); + /* init CPUs */ if (cpu_model == NULL) { cpu_model = "host"; @@ -178,6 +174,7 @@ static void s390_init(ram_addr_t ram_size, ipi_states[i] = tmp_env; tmp_env->halted = 1; tmp_env->exception_index = EXCP_HLT; + tmp_env->storage_keys = storage_keys; } env->halted = 0; diff --git a/hw/stellaris.c b/hw/stellaris.c index 0d5292688..ac9fcc1f3 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -14,7 +14,6 @@ #include "qemu-timer.h" #include "i2c.h" #include "net.h" -#include "sysemu.h" #include "boards.h" #define GPIO_A 0 @@ -280,64 +279,28 @@ static CPUWriteMemoryFunc * const gptm_writefn[] = { gptm_write }; -static void gptm_save(QEMUFile *f, void *opaque) -{ - gptm_state *s = (gptm_state *)opaque; - - qemu_put_be32(f, s->config); - qemu_put_be32(f, s->mode[0]); - qemu_put_be32(f, s->mode[1]); - qemu_put_be32(f, s->control); - qemu_put_be32(f, s->state); - qemu_put_be32(f, s->mask); - qemu_put_be32(f, s->mode[0]); - qemu_put_be32(f, s->mode[0]); - qemu_put_be32(f, s->load[0]); - qemu_put_be32(f, s->load[1]); - qemu_put_be32(f, s->match[0]); - qemu_put_be32(f, s->match[1]); - qemu_put_be32(f, s->prescale[0]); - qemu_put_be32(f, s->prescale[1]); - qemu_put_be32(f, s->match_prescale[0]); - qemu_put_be32(f, s->match_prescale[1]); - qemu_put_be32(f, s->rtc); - qemu_put_be64(f, s->tick[0]); - qemu_put_be64(f, s->tick[1]); - qemu_put_timer(f, s->timer[0]); - qemu_put_timer(f, s->timer[1]); -} - -static int gptm_load(QEMUFile *f, void *opaque, int version_id) -{ - gptm_state *s = (gptm_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->config = qemu_get_be32(f); - s->mode[0] = qemu_get_be32(f); - s->mode[1] = qemu_get_be32(f); - s->control = qemu_get_be32(f); - s->state = qemu_get_be32(f); - s->mask = qemu_get_be32(f); - s->mode[0] = qemu_get_be32(f); - s->mode[0] = qemu_get_be32(f); - s->load[0] = qemu_get_be32(f); - s->load[1] = qemu_get_be32(f); - s->match[0] = qemu_get_be32(f); - s->match[1] = qemu_get_be32(f); - s->prescale[0] = qemu_get_be32(f); - s->prescale[1] = qemu_get_be32(f); - s->match_prescale[0] = qemu_get_be32(f); - s->match_prescale[1] = qemu_get_be32(f); - s->rtc = qemu_get_be32(f); - s->tick[0] = qemu_get_be64(f); - s->tick[1] = qemu_get_be64(f); - qemu_get_timer(f, s->timer[0]); - qemu_get_timer(f, s->timer[1]); - - return 0; -} +static const VMStateDescription vmstate_stellaris_gptm = { + .name = "stellaris_gptm", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(config, gptm_state), + VMSTATE_UINT32_ARRAY(mode, gptm_state, 2), + VMSTATE_UINT32(control, gptm_state), + VMSTATE_UINT32(state, gptm_state), + VMSTATE_UINT32(mask, gptm_state), + VMSTATE_UNUSED(8), + VMSTATE_UINT32_ARRAY(load, gptm_state, 2), + VMSTATE_UINT32_ARRAY(match, gptm_state, 2), + VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2), + VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2), + VMSTATE_UINT32(rtc, gptm_state), + VMSTATE_INT64_ARRAY(tick, gptm_state, 2), + VMSTATE_TIMER_ARRAY(timer, gptm_state, 2), + VMSTATE_END_OF_LIST() + } +}; static int stellaris_gptm_init(SysBusDevice *dev) { @@ -355,8 +318,7 @@ static int stellaris_gptm_init(SysBusDevice *dev) s->opaque[0] = s->opaque[1] = s; s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]); s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]); - register_savevm(&dev->qdev, "stellaris_gptm", -1, 1, - gptm_save, gptm_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s); return 0; } @@ -605,58 +567,37 @@ static void ssys_reset(void *opaque) s->dcgc[0] = 1; } -static void ssys_save(QEMUFile *f, void *opaque) -{ - ssys_state *s = (ssys_state *)opaque; - - qemu_put_be32(f, s->pborctl); - qemu_put_be32(f, s->ldopctl); - qemu_put_be32(f, s->int_mask); - qemu_put_be32(f, s->int_status); - qemu_put_be32(f, s->resc); - qemu_put_be32(f, s->rcc); - qemu_put_be32(f, s->rcgc[0]); - qemu_put_be32(f, s->rcgc[1]); - qemu_put_be32(f, s->rcgc[2]); - qemu_put_be32(f, s->scgc[0]); - qemu_put_be32(f, s->scgc[1]); - qemu_put_be32(f, s->scgc[2]); - qemu_put_be32(f, s->dcgc[0]); - qemu_put_be32(f, s->dcgc[1]); - qemu_put_be32(f, s->dcgc[2]); - qemu_put_be32(f, s->clkvclr); - qemu_put_be32(f, s->ldoarst); -} - -static int ssys_load(QEMUFile *f, void *opaque, int version_id) +static int stellaris_sys_post_load(void *opaque, int version_id) { - ssys_state *s = (ssys_state *)opaque; + ssys_state *s = opaque; - if (version_id != 1) - return -EINVAL; - - s->pborctl = qemu_get_be32(f); - s->ldopctl = qemu_get_be32(f); - s->int_mask = qemu_get_be32(f); - s->int_status = qemu_get_be32(f); - s->resc = qemu_get_be32(f); - s->rcc = qemu_get_be32(f); - s->rcgc[0] = qemu_get_be32(f); - s->rcgc[1] = qemu_get_be32(f); - s->rcgc[2] = qemu_get_be32(f); - s->scgc[0] = qemu_get_be32(f); - s->scgc[1] = qemu_get_be32(f); - s->scgc[2] = qemu_get_be32(f); - s->dcgc[0] = qemu_get_be32(f); - s->dcgc[1] = qemu_get_be32(f); - s->dcgc[2] = qemu_get_be32(f); - s->clkvclr = qemu_get_be32(f); - s->ldoarst = qemu_get_be32(f); ssys_calculate_system_clock(s); return 0; } +static const VMStateDescription vmstate_stellaris_sys = { + .name = "stellaris_sys", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = stellaris_sys_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(pborctl, ssys_state), + VMSTATE_UINT32(ldopctl, ssys_state), + VMSTATE_UINT32(int_mask, ssys_state), + VMSTATE_UINT32(int_status, ssys_state), + VMSTATE_UINT32(resc, ssys_state), + VMSTATE_UINT32(rcc, ssys_state), + VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3), + VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3), + VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3), + VMSTATE_UINT32(clkvclr, ssys_state), + VMSTATE_UINT32(ldoarst, ssys_state), + VMSTATE_END_OF_LIST() + } +}; + static int stellaris_sys_init(uint32_t base, qemu_irq irq, stellaris_board_info * board, uint8_t *macaddr) @@ -676,7 +617,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(base, 0x00001000, iomemtype); ssys_reset(s); - register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s); + vmstate_register(NULL, -1, &vmstate_stellaris_sys, s); return 0; } @@ -844,36 +785,22 @@ static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = { stellaris_i2c_write }; -static void stellaris_i2c_save(QEMUFile *f, void *opaque) -{ - stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; - - qemu_put_be32(f, s->msa); - qemu_put_be32(f, s->mcs); - qemu_put_be32(f, s->mdr); - qemu_put_be32(f, s->mtpr); - qemu_put_be32(f, s->mimr); - qemu_put_be32(f, s->mris); - qemu_put_be32(f, s->mcr); -} - -static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id) -{ - stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->msa = qemu_get_be32(f); - s->mcs = qemu_get_be32(f); - s->mdr = qemu_get_be32(f); - s->mtpr = qemu_get_be32(f); - s->mimr = qemu_get_be32(f); - s->mris = qemu_get_be32(f); - s->mcr = qemu_get_be32(f); - - return 0; -} +static const VMStateDescription vmstate_stellaris_i2c = { + .name = "stellaris_i2c", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(msa, stellaris_i2c_state), + VMSTATE_UINT32(mcs, stellaris_i2c_state), + VMSTATE_UINT32(mdr, stellaris_i2c_state), + VMSTATE_UINT32(mtpr, stellaris_i2c_state), + VMSTATE_UINT32(mimr, stellaris_i2c_state), + VMSTATE_UINT32(mris, stellaris_i2c_state), + VMSTATE_UINT32(mcr, stellaris_i2c_state), + VMSTATE_END_OF_LIST() + } +}; static int stellaris_i2c_init(SysBusDevice * dev) { @@ -891,8 +818,7 @@ static int stellaris_i2c_init(SysBusDevice * dev) sysbus_init_mmio(dev, 0x1000, iomemtype); /* ??? For now we only implement the master interface. */ stellaris_i2c_reset(s); - register_savevm(&dev->qdev, "stellaris_i2c", -1, 1, - stellaris_i2c_save, stellaris_i2c_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s); return 0; } @@ -1130,60 +1056,40 @@ static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = { stellaris_adc_write }; -static void stellaris_adc_save(QEMUFile *f, void *opaque) -{ - stellaris_adc_state *s = (stellaris_adc_state *)opaque; - int i; - int j; - - qemu_put_be32(f, s->actss); - qemu_put_be32(f, s->ris); - qemu_put_be32(f, s->im); - qemu_put_be32(f, s->emux); - qemu_put_be32(f, s->ostat); - qemu_put_be32(f, s->ustat); - qemu_put_be32(f, s->sspri); - qemu_put_be32(f, s->sac); - for (i = 0; i < 4; i++) { - qemu_put_be32(f, s->fifo[i].state); - for (j = 0; j < 16; j++) { - qemu_put_be32(f, s->fifo[i].data[j]); - } - qemu_put_be32(f, s->ssmux[i]); - qemu_put_be32(f, s->ssctl[i]); - } - qemu_put_be32(f, s->noise); -} - -static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id) -{ - stellaris_adc_state *s = (stellaris_adc_state *)opaque; - int i; - int j; - - if (version_id != 1) - return -EINVAL; - - s->actss = qemu_get_be32(f); - s->ris = qemu_get_be32(f); - s->im = qemu_get_be32(f); - s->emux = qemu_get_be32(f); - s->ostat = qemu_get_be32(f); - s->ustat = qemu_get_be32(f); - s->sspri = qemu_get_be32(f); - s->sac = qemu_get_be32(f); - for (i = 0; i < 4; i++) { - s->fifo[i].state = qemu_get_be32(f); - for (j = 0; j < 16; j++) { - s->fifo[i].data[j] = qemu_get_be32(f); - } - s->ssmux[i] = qemu_get_be32(f); - s->ssctl[i] = qemu_get_be32(f); +static const VMStateDescription vmstate_stellaris_adc = { + .name = "stellaris_adc", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(actss, stellaris_adc_state), + VMSTATE_UINT32(ris, stellaris_adc_state), + VMSTATE_UINT32(im, stellaris_adc_state), + VMSTATE_UINT32(emux, stellaris_adc_state), + VMSTATE_UINT32(ostat, stellaris_adc_state), + VMSTATE_UINT32(ustat, stellaris_adc_state), + VMSTATE_UINT32(sspri, stellaris_adc_state), + VMSTATE_UINT32(sac, stellaris_adc_state), + VMSTATE_UINT32(fifo[0].state, stellaris_adc_state), + VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16), + VMSTATE_UINT32(ssmux[0], stellaris_adc_state), + VMSTATE_UINT32(ssctl[0], stellaris_adc_state), + VMSTATE_UINT32(fifo[1].state, stellaris_adc_state), + VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16), + VMSTATE_UINT32(ssmux[1], stellaris_adc_state), + VMSTATE_UINT32(ssctl[1], stellaris_adc_state), + VMSTATE_UINT32(fifo[2].state, stellaris_adc_state), + VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16), + VMSTATE_UINT32(ssmux[2], stellaris_adc_state), + VMSTATE_UINT32(ssctl[2], stellaris_adc_state), + VMSTATE_UINT32(fifo[3].state, stellaris_adc_state), + VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16), + VMSTATE_UINT32(ssmux[3], stellaris_adc_state), + VMSTATE_UINT32(ssctl[3], stellaris_adc_state), + VMSTATE_UINT32(noise, stellaris_adc_state), + VMSTATE_END_OF_LIST() } - s->noise = qemu_get_be32(f); - - return 0; -} +}; static int stellaris_adc_init(SysBusDevice *dev) { @@ -1201,8 +1107,7 @@ static int stellaris_adc_init(SysBusDevice *dev) sysbus_init_mmio(dev, 0x1000, iomemtype); stellaris_adc_reset(s); qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1); - register_savevm(&dev->qdev, "stellaris_adc", -1, 1, - stellaris_adc_save, stellaris_adc_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s); return 0; } @@ -1234,24 +1139,16 @@ static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val) return ssi_transfer(s->bus[s->current_dev], val); } -static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque) -{ - stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; - - qemu_put_be32(f, s->current_dev); -} - -static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id) -{ - stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->current_dev = qemu_get_be32(f); - - return 0; -} +static const VMStateDescription vmstate_stellaris_ssi_bus = { + .name = "stellaris_ssi_bus", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32(current_dev, stellaris_ssi_bus_state), + VMSTATE_END_OF_LIST() + } +}; static int stellaris_ssi_bus_init(SSISlave *dev) { @@ -1261,8 +1158,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev) s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1"); qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1); - register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1, - stellaris_ssi_bus_save, stellaris_ssi_bus_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s); return 0; } diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c index 16aae96f2..06c5f9d95 100644 --- a/hw/stellaris_input.c +++ b/hw/stellaris_input.c @@ -13,7 +13,7 @@ typedef struct { qemu_irq irq; int keycode; - int pressed; + uint8_t pressed; } gamepad_button; typedef struct { @@ -47,30 +47,29 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode) s->extension = 0; } -static void stellaris_gamepad_save(QEMUFile *f, void *opaque) -{ - gamepad_state *s = (gamepad_state *)opaque; - int i; - - qemu_put_be32(f, s->extension); - for (i = 0; i < s->num_buttons; i++) - qemu_put_byte(f, s->buttons[i].pressed); -} - -static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id) -{ - gamepad_state *s = (gamepad_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->extension = qemu_get_be32(f); - for (i = 0; i < s->num_buttons; i++) - s->buttons[i].pressed = qemu_get_byte(f); +static const VMStateDescription vmstate_stellaris_button = { + .name = "stellaris_button", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8(pressed, gamepad_button), + VMSTATE_END_OF_LIST() + } +}; - return 0; -} +static const VMStateDescription vmstate_stellaris_gamepad = { + .name = "stellaris_gamepad", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32(extension, gamepad_state), + VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0, + vmstate_stellaris_button, gamepad_button), + VMSTATE_END_OF_LIST() + } +}; /* Returns an array 5 ouput slots. */ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) @@ -86,6 +85,5 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) } s->num_buttons = n; qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); - register_savevm(NULL, "stellaris_gamepad", -1, 1, - stellaris_gamepad_save, stellaris_gamepad_load, s); + vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s); } diff --git a/hw/strongarm.c b/hw/strongarm.c new file mode 100644 index 000000000..de08bdf67 --- /dev/null +++ b/hw/strongarm.c @@ -0,0 +1,1598 @@ +/* + * StrongARM SA-1100/SA-1110 emulation + * + * Copyright (C) 2011 Dmitry Eremin-Solenikov + * + * Largely based on StrongARM emulation: + * Copyright (c) 2006 Openedhand Ltd. + * Written by Andrzej Zaborowski <balrog@zabor.org> + * + * UART code based on QEMU 16550A UART emulation + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2008 Citrix Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "sysbus.h" +#include "strongarm.h" +#include "qemu-error.h" +#include "arm-misc.h" +#include "sysemu.h" +#include "ssi.h" + +//#define DEBUG + +/* + TODO + - Implement cp15, c14 ? + - Implement cp15, c15 !!! (idle used in L) + - Implement idle mode handling/DIM + - Implement sleep mode/Wake sources + - Implement reset control + - Implement memory control regs + - PCMCIA handling + - Maybe support MBGNT/MBREQ + - DMA channels + - GPCLK + - IrDA + - MCP + - Enhance UART with modem signals + */ + +#ifdef DEBUG +# define DPRINTF(format, ...) printf(format , ## __VA_ARGS__) +#else +# define DPRINTF(format, ...) do { } while (0) +#endif + +static struct { + target_phys_addr_t io_base; + int irq; +} sa_serial[] = { + { 0x80010000, SA_PIC_UART1 }, + { 0x80030000, SA_PIC_UART2 }, + { 0x80050000, SA_PIC_UART3 }, + { 0, 0 } +}; + +/* Interrupt Controller */ +typedef struct { + SysBusDevice busdev; + qemu_irq irq; + qemu_irq fiq; + + uint32_t pending; + uint32_t enabled; + uint32_t is_fiq; + uint32_t int_idle; +} StrongARMPICState; + +#define ICIP 0x00 +#define ICMR 0x04 +#define ICLR 0x08 +#define ICFP 0x10 +#define ICPR 0x20 +#define ICCR 0x0c + +#define SA_PIC_SRCS 32 + + +static void strongarm_pic_update(void *opaque) +{ + StrongARMPICState *s = opaque; + + /* FIXME: reflect DIM */ + qemu_set_irq(s->fiq, s->pending & s->enabled & s->is_fiq); + qemu_set_irq(s->irq, s->pending & s->enabled & ~s->is_fiq); +} + +static void strongarm_pic_set_irq(void *opaque, int irq, int level) +{ + StrongARMPICState *s = opaque; + + if (level) { + s->pending |= 1 << irq; + } else { + s->pending &= ~(1 << irq); + } + + strongarm_pic_update(s); +} + +static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset) +{ + StrongARMPICState *s = opaque; + + switch (offset) { + case ICIP: + return s->pending & ~s->is_fiq & s->enabled; + case ICMR: + return s->enabled; + case ICLR: + return s->is_fiq; + case ICCR: + return s->int_idle == 0; + case ICFP: + return s->pending & s->is_fiq & s->enabled; + case ICPR: + return s->pending; + default: + printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n", + __func__, offset); + return 0; + } +} + +static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset, + uint32_t value) +{ + StrongARMPICState *s = opaque; + + switch (offset) { + case ICMR: + s->enabled = value; + break; + case ICLR: + s->is_fiq = value; + break; + case ICCR: + s->int_idle = (value & 1) ? 0 : ~0; + break; + default: + printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n", + __func__, offset); + break; + } + strongarm_pic_update(s); +} + +static CPUReadMemoryFunc * const strongarm_pic_readfn[] = { + strongarm_pic_mem_read, + strongarm_pic_mem_read, + strongarm_pic_mem_read, +}; + +static CPUWriteMemoryFunc * const strongarm_pic_writefn[] = { + strongarm_pic_mem_write, + strongarm_pic_mem_write, + strongarm_pic_mem_write, +}; + +static int strongarm_pic_initfn(SysBusDevice *dev) +{ + StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev); + int iomemtype; + + qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS); + iomemtype = cpu_register_io_memory(strongarm_pic_readfn, + strongarm_pic_writefn, s, DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, iomemtype); + sysbus_init_irq(dev, &s->irq); + sysbus_init_irq(dev, &s->fiq); + + return 0; +} + +static int strongarm_pic_post_load(void *opaque, int version_id) +{ + strongarm_pic_update(opaque); + return 0; +} + +static VMStateDescription vmstate_strongarm_pic_regs = { + .name = "strongarm_pic", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .post_load = strongarm_pic_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(pending, StrongARMPICState), + VMSTATE_UINT32(enabled, StrongARMPICState), + VMSTATE_UINT32(is_fiq, StrongARMPICState), + VMSTATE_UINT32(int_idle, StrongARMPICState), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_pic_info = { + .init = strongarm_pic_initfn, + .qdev.name = "strongarm_pic", + .qdev.desc = "StrongARM PIC", + .qdev.size = sizeof(StrongARMPICState), + .qdev.vmsd = &vmstate_strongarm_pic_regs, +}; + +/* Real-Time Clock */ +#define RTAR 0x00 /* RTC Alarm register */ +#define RCNR 0x04 /* RTC Counter register */ +#define RTTR 0x08 /* RTC Timer Trim register */ +#define RTSR 0x10 /* RTC Status register */ + +#define RTSR_AL (1 << 0) /* RTC Alarm detected */ +#define RTSR_HZ (1 << 1) /* RTC 1Hz detected */ +#define RTSR_ALE (1 << 2) /* RTC Alarm enable */ +#define RTSR_HZE (1 << 3) /* RTC 1Hz enable */ + +/* 16 LSB of RTTR are clockdiv for internal trim logic, + * trim delete isn't emulated, so + * f = 32 768 / (RTTR_trim + 1) */ + +typedef struct { + SysBusDevice busdev; + uint32_t rttr; + uint32_t rtsr; + uint32_t rtar; + uint32_t last_rcnr; + int64_t last_hz; + QEMUTimer *rtc_alarm; + QEMUTimer *rtc_hz; + qemu_irq rtc_irq; + qemu_irq rtc_hz_irq; +} StrongARMRTCState; + +static inline void strongarm_rtc_int_update(StrongARMRTCState *s) +{ + qemu_set_irq(s->rtc_irq, s->rtsr & RTSR_AL); + qemu_set_irq(s->rtc_hz_irq, s->rtsr & RTSR_HZ); +} + +static void strongarm_rtc_hzupdate(StrongARMRTCState *s) +{ + int64_t rt = qemu_get_clock_ms(rt_clock); + s->last_rcnr += ((rt - s->last_hz) << 15) / + (1000 * ((s->rttr & 0xffff) + 1)); + s->last_hz = rt; +} + +static inline void strongarm_rtc_timer_update(StrongARMRTCState *s) +{ + if ((s->rtsr & RTSR_HZE) && !(s->rtsr & RTSR_HZ)) { + qemu_mod_timer(s->rtc_hz, s->last_hz + 1000); + } else { + qemu_del_timer(s->rtc_hz); + } + + if ((s->rtsr & RTSR_ALE) && !(s->rtsr & RTSR_AL)) { + qemu_mod_timer(s->rtc_alarm, s->last_hz + + (((s->rtar - s->last_rcnr) * 1000 * + ((s->rttr & 0xffff) + 1)) >> 15)); + } else { + qemu_del_timer(s->rtc_alarm); + } +} + +static inline void strongarm_rtc_alarm_tick(void *opaque) +{ + StrongARMRTCState *s = opaque; + s->rtsr |= RTSR_AL; + strongarm_rtc_timer_update(s); + strongarm_rtc_int_update(s); +} + +static inline void strongarm_rtc_hz_tick(void *opaque) +{ + StrongARMRTCState *s = opaque; + s->rtsr |= RTSR_HZ; + strongarm_rtc_timer_update(s); + strongarm_rtc_int_update(s); +} + +static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr) +{ + StrongARMRTCState *s = opaque; + + switch (addr) { + case RTTR: + return s->rttr; + case RTSR: + return s->rtsr; + case RTAR: + return s->rtar; + case RCNR: + return s->last_rcnr + + ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) / + (1000 * ((s->rttr & 0xffff) + 1)); + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + return 0; + } +} + +static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + StrongARMRTCState *s = opaque; + uint32_t old_rtsr; + + switch (addr) { + case RTTR: + strongarm_rtc_hzupdate(s); + s->rttr = value; + strongarm_rtc_timer_update(s); + break; + + case RTSR: + old_rtsr = s->rtsr; + s->rtsr = (value & (RTSR_ALE | RTSR_HZE)) | + (s->rtsr & ~(value & (RTSR_AL | RTSR_HZ))); + + if (s->rtsr != old_rtsr) { + strongarm_rtc_timer_update(s); + } + + strongarm_rtc_int_update(s); + break; + + case RTAR: + s->rtar = value; + strongarm_rtc_timer_update(s); + break; + + case RCNR: + strongarm_rtc_hzupdate(s); + s->last_rcnr = value; + strongarm_rtc_timer_update(s); + break; + + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + } +} + +static CPUReadMemoryFunc * const strongarm_rtc_readfn[] = { + strongarm_rtc_read, + strongarm_rtc_read, + strongarm_rtc_read, +}; + +static CPUWriteMemoryFunc * const strongarm_rtc_writefn[] = { + strongarm_rtc_write, + strongarm_rtc_write, + strongarm_rtc_write, +}; + +static int strongarm_rtc_init(SysBusDevice *dev) +{ + StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev); + struct tm tm; + int iomemtype; + + s->rttr = 0x0; + s->rtsr = 0; + + qemu_get_timedate(&tm, 0); + + s->last_rcnr = (uint32_t) mktimegm(&tm); + s->last_hz = qemu_get_clock_ms(rt_clock); + + s->rtc_alarm = qemu_new_timer_ms(rt_clock, strongarm_rtc_alarm_tick, s); + s->rtc_hz = qemu_new_timer_ms(rt_clock, strongarm_rtc_hz_tick, s); + + sysbus_init_irq(dev, &s->rtc_irq); + sysbus_init_irq(dev, &s->rtc_hz_irq); + + iomemtype = cpu_register_io_memory(strongarm_rtc_readfn, + strongarm_rtc_writefn, s, DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, 0x10000, iomemtype); + + return 0; +} + +static void strongarm_rtc_pre_save(void *opaque) +{ + StrongARMRTCState *s = opaque; + + strongarm_rtc_hzupdate(s); +} + +static int strongarm_rtc_post_load(void *opaque, int version_id) +{ + StrongARMRTCState *s = opaque; + + strongarm_rtc_timer_update(s); + strongarm_rtc_int_update(s); + + return 0; +} + +static const VMStateDescription vmstate_strongarm_rtc_regs = { + .name = "strongarm-rtc", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .pre_save = strongarm_rtc_pre_save, + .post_load = strongarm_rtc_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(rttr, StrongARMRTCState), + VMSTATE_UINT32(rtsr, StrongARMRTCState), + VMSTATE_UINT32(rtar, StrongARMRTCState), + VMSTATE_UINT32(last_rcnr, StrongARMRTCState), + VMSTATE_INT64(last_hz, StrongARMRTCState), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_rtc_sysbus_info = { + .init = strongarm_rtc_init, + .qdev.name = "strongarm-rtc", + .qdev.desc = "StrongARM RTC Controller", + .qdev.size = sizeof(StrongARMRTCState), + .qdev.vmsd = &vmstate_strongarm_rtc_regs, +}; + +/* GPIO */ +#define GPLR 0x00 +#define GPDR 0x04 +#define GPSR 0x08 +#define GPCR 0x0c +#define GRER 0x10 +#define GFER 0x14 +#define GEDR 0x18 +#define GAFR 0x1c + +typedef struct StrongARMGPIOInfo StrongARMGPIOInfo; +struct StrongARMGPIOInfo { + SysBusDevice busdev; + qemu_irq handler[28]; + qemu_irq irqs[11]; + qemu_irq irqX; + + uint32_t ilevel; + uint32_t olevel; + uint32_t dir; + uint32_t rising; + uint32_t falling; + uint32_t status; + uint32_t gpsr; + uint32_t gafr; + + uint32_t prev_level; +}; + + +static void strongarm_gpio_irq_update(StrongARMGPIOInfo *s) +{ + int i; + for (i = 0; i < 11; i++) { + qemu_set_irq(s->irqs[i], s->status & (1 << i)); + } + + qemu_set_irq(s->irqX, (s->status & ~0x7ff)); +} + +static void strongarm_gpio_set(void *opaque, int line, int level) +{ + StrongARMGPIOInfo *s = opaque; + uint32_t mask; + + mask = 1 << line; + + if (level) { + s->status |= s->rising & mask & + ~s->ilevel & ~s->dir; + s->ilevel |= mask; + } else { + s->status |= s->falling & mask & + s->ilevel & ~s->dir; + s->ilevel &= ~mask; + } + + if (s->status & mask) { + strongarm_gpio_irq_update(s); + } +} + +static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s) +{ + uint32_t level, diff; + int bit; + + level = s->olevel & s->dir; + + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { + bit = ffs(diff) - 1; + qemu_set_irq(s->handler[bit], (level >> bit) & 1); + } + + s->prev_level = level; +} + +static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset) +{ + StrongARMGPIOInfo *s = opaque; + + switch (offset) { + case GPDR: /* GPIO Pin-Direction registers */ + return s->dir; + + case GPSR: /* GPIO Pin-Output Set registers */ + DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n", + __func__, offset); + return s->gpsr; /* Return last written value. */ + + case GPCR: /* GPIO Pin-Output Clear registers */ + DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n", + __func__, offset); + return 31337; /* Specified as unpredictable in the docs. */ + + case GRER: /* GPIO Rising-Edge Detect Enable registers */ + return s->rising; + + case GFER: /* GPIO Falling-Edge Detect Enable registers */ + return s->falling; + + case GAFR: /* GPIO Alternate Function registers */ + return s->gafr; + + case GPLR: /* GPIO Pin-Level registers */ + return (s->olevel & s->dir) | + (s->ilevel & ~s->dir); + + case GEDR: /* GPIO Edge Detect Status registers */ + return s->status; + + default: + printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset); + } + + return 0; +} + +static void strongarm_gpio_write(void *opaque, + target_phys_addr_t offset, uint32_t value) +{ + StrongARMGPIOInfo *s = opaque; + + switch (offset) { + case GPDR: /* GPIO Pin-Direction registers */ + s->dir = value; + strongarm_gpio_handler_update(s); + break; + + case GPSR: /* GPIO Pin-Output Set registers */ + s->olevel |= value; + strongarm_gpio_handler_update(s); + s->gpsr = value; + break; + + case GPCR: /* GPIO Pin-Output Clear registers */ + s->olevel &= ~value; + strongarm_gpio_handler_update(s); + break; + + case GRER: /* GPIO Rising-Edge Detect Enable registers */ + s->rising = value; + break; + + case GFER: /* GPIO Falling-Edge Detect Enable registers */ + s->falling = value; + break; + + case GAFR: /* GPIO Alternate Function registers */ + s->gafr = value; + break; + + case GEDR: /* GPIO Edge Detect Status registers */ + s->status &= ~value; + strongarm_gpio_irq_update(s); + break; + + default: + printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset); + } +} + +static CPUReadMemoryFunc * const strongarm_gpio_readfn[] = { + strongarm_gpio_read, + strongarm_gpio_read, + strongarm_gpio_read +}; + +static CPUWriteMemoryFunc * const strongarm_gpio_writefn[] = { + strongarm_gpio_write, + strongarm_gpio_write, + strongarm_gpio_write +}; + +static DeviceState *strongarm_gpio_init(target_phys_addr_t base, + DeviceState *pic) +{ + DeviceState *dev; + int i; + + dev = qdev_create(NULL, "strongarm-gpio"); + qdev_init_nofail(dev); + + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); + for (i = 0; i < 12; i++) + sysbus_connect_irq(sysbus_from_qdev(dev), i, + qdev_get_gpio_in(pic, SA_PIC_GPIO0_EDGE + i)); + + return dev; +} + +static int strongarm_gpio_initfn(SysBusDevice *dev) +{ + int iomemtype; + StrongARMGPIOInfo *s; + int i; + + s = FROM_SYSBUS(StrongARMGPIOInfo, dev); + + qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28); + qdev_init_gpio_out(&dev->qdev, s->handler, 28); + + iomemtype = cpu_register_io_memory(strongarm_gpio_readfn, + strongarm_gpio_writefn, s, DEVICE_NATIVE_ENDIAN); + + sysbus_init_mmio(dev, 0x1000, iomemtype); + for (i = 0; i < 11; i++) { + sysbus_init_irq(dev, &s->irqs[i]); + } + sysbus_init_irq(dev, &s->irqX); + + return 0; +} + +static const VMStateDescription vmstate_strongarm_gpio_regs = { + .name = "strongarm-gpio", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ilevel, StrongARMGPIOInfo), + VMSTATE_UINT32(olevel, StrongARMGPIOInfo), + VMSTATE_UINT32(dir, StrongARMGPIOInfo), + VMSTATE_UINT32(rising, StrongARMGPIOInfo), + VMSTATE_UINT32(falling, StrongARMGPIOInfo), + VMSTATE_UINT32(status, StrongARMGPIOInfo), + VMSTATE_UINT32(gafr, StrongARMGPIOInfo), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_gpio_info = { + .init = strongarm_gpio_initfn, + .qdev.name = "strongarm-gpio", + .qdev.desc = "StrongARM GPIO controller", + .qdev.size = sizeof(StrongARMGPIOInfo), +}; + +/* Peripheral Pin Controller */ +#define PPDR 0x00 +#define PPSR 0x04 +#define PPAR 0x08 +#define PSDR 0x0c +#define PPFR 0x10 + +typedef struct StrongARMPPCInfo StrongARMPPCInfo; +struct StrongARMPPCInfo { + SysBusDevice busdev; + qemu_irq handler[28]; + + uint32_t ilevel; + uint32_t olevel; + uint32_t dir; + uint32_t ppar; + uint32_t psdr; + uint32_t ppfr; + + uint32_t prev_level; +}; + +static void strongarm_ppc_set(void *opaque, int line, int level) +{ + StrongARMPPCInfo *s = opaque; + + if (level) { + s->ilevel |= 1 << line; + } else { + s->ilevel &= ~(1 << line); + } +} + +static void strongarm_ppc_handler_update(StrongARMPPCInfo *s) +{ + uint32_t level, diff; + int bit; + + level = s->olevel & s->dir; + + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { + bit = ffs(diff) - 1; + qemu_set_irq(s->handler[bit], (level >> bit) & 1); + } + + s->prev_level = level; +} + +static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset) +{ + StrongARMPPCInfo *s = opaque; + + switch (offset) { + case PPDR: /* PPC Pin Direction registers */ + return s->dir | ~0x3fffff; + + case PPSR: /* PPC Pin State registers */ + return (s->olevel & s->dir) | + (s->ilevel & ~s->dir) | + ~0x3fffff; + + case PPAR: + return s->ppar | ~0x41000; + + case PSDR: + return s->psdr; + + case PPFR: + return s->ppfr | ~0x7f001; + + default: + printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset); + } + + return 0; +} + +static void strongarm_ppc_write(void *opaque, + target_phys_addr_t offset, uint32_t value) +{ + StrongARMPPCInfo *s = opaque; + + switch (offset) { + case PPDR: /* PPC Pin Direction registers */ + s->dir = value & 0x3fffff; + strongarm_ppc_handler_update(s); + break; + + case PPSR: /* PPC Pin State registers */ + s->olevel = value & s->dir & 0x3fffff; + strongarm_ppc_handler_update(s); + break; + + case PPAR: + s->ppar = value & 0x41000; + break; + + case PSDR: + s->psdr = value & 0x3fffff; + break; + + case PPFR: + s->ppfr = value & 0x7f001; + break; + + default: + printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset); + } +} + +static CPUReadMemoryFunc * const strongarm_ppc_readfn[] = { + strongarm_ppc_read, + strongarm_ppc_read, + strongarm_ppc_read +}; + +static CPUWriteMemoryFunc * const strongarm_ppc_writefn[] = { + strongarm_ppc_write, + strongarm_ppc_write, + strongarm_ppc_write +}; + +static int strongarm_ppc_init(SysBusDevice *dev) +{ + int iomemtype; + StrongARMPPCInfo *s; + + s = FROM_SYSBUS(StrongARMPPCInfo, dev); + + qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22); + qdev_init_gpio_out(&dev->qdev, s->handler, 22); + + iomemtype = cpu_register_io_memory(strongarm_ppc_readfn, + strongarm_ppc_writefn, s, DEVICE_NATIVE_ENDIAN); + + sysbus_init_mmio(dev, 0x1000, iomemtype); + + return 0; +} + +static const VMStateDescription vmstate_strongarm_ppc_regs = { + .name = "strongarm-ppc", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ilevel, StrongARMPPCInfo), + VMSTATE_UINT32(olevel, StrongARMPPCInfo), + VMSTATE_UINT32(dir, StrongARMPPCInfo), + VMSTATE_UINT32(ppar, StrongARMPPCInfo), + VMSTATE_UINT32(psdr, StrongARMPPCInfo), + VMSTATE_UINT32(ppfr, StrongARMPPCInfo), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_ppc_info = { + .init = strongarm_ppc_init, + .qdev.name = "strongarm-ppc", + .qdev.desc = "StrongARM PPC controller", + .qdev.size = sizeof(StrongARMPPCInfo), +}; + +/* UART Ports */ +#define UTCR0 0x00 +#define UTCR1 0x04 +#define UTCR2 0x08 +#define UTCR3 0x0c +#define UTDR 0x14 +#define UTSR0 0x1c +#define UTSR1 0x20 + +#define UTCR0_PE (1 << 0) /* Parity enable */ +#define UTCR0_OES (1 << 1) /* Even parity */ +#define UTCR0_SBS (1 << 2) /* 2 stop bits */ +#define UTCR0_DSS (1 << 3) /* 8-bit data */ + +#define UTCR3_RXE (1 << 0) /* Rx enable */ +#define UTCR3_TXE (1 << 1) /* Tx enable */ +#define UTCR3_BRK (1 << 2) /* Force Break */ +#define UTCR3_RIE (1 << 3) /* Rx int enable */ +#define UTCR3_TIE (1 << 4) /* Tx int enable */ +#define UTCR3_LBM (1 << 5) /* Loopback */ + +#define UTSR0_TFS (1 << 0) /* Tx FIFO nearly empty */ +#define UTSR0_RFS (1 << 1) /* Rx FIFO nearly full */ +#define UTSR0_RID (1 << 2) /* Receiver Idle */ +#define UTSR0_RBB (1 << 3) /* Receiver begin break */ +#define UTSR0_REB (1 << 4) /* Receiver end break */ +#define UTSR0_EIF (1 << 5) /* Error in FIFO */ + +#define UTSR1_RNE (1 << 1) /* Receive FIFO not empty */ +#define UTSR1_TNF (1 << 2) /* Transmit FIFO not full */ +#define UTSR1_PRE (1 << 3) /* Parity error */ +#define UTSR1_FRE (1 << 4) /* Frame error */ +#define UTSR1_ROR (1 << 5) /* Receive Over Run */ + +#define RX_FIFO_PRE (1 << 8) +#define RX_FIFO_FRE (1 << 9) +#define RX_FIFO_ROR (1 << 10) + +typedef struct { + SysBusDevice busdev; + CharDriverState *chr; + qemu_irq irq; + + uint8_t utcr0; + uint16_t brd; + uint8_t utcr3; + uint8_t utsr0; + uint8_t utsr1; + + uint8_t tx_fifo[8]; + uint8_t tx_start; + uint8_t tx_len; + uint16_t rx_fifo[12]; /* value + error flags in high bits */ + uint8_t rx_start; + uint8_t rx_len; + + uint64_t char_transmit_time; /* time to transmit a char in ticks*/ + bool wait_break_end; + QEMUTimer *rx_timeout_timer; + QEMUTimer *tx_timer; +} StrongARMUARTState; + +static void strongarm_uart_update_status(StrongARMUARTState *s) +{ + uint16_t utsr1 = 0; + + if (s->tx_len != 8) { + utsr1 |= UTSR1_TNF; + } + + if (s->rx_len != 0) { + uint16_t ent = s->rx_fifo[s->rx_start]; + + utsr1 |= UTSR1_RNE; + if (ent & RX_FIFO_PRE) { + s->utsr1 |= UTSR1_PRE; + } + if (ent & RX_FIFO_FRE) { + s->utsr1 |= UTSR1_FRE; + } + if (ent & RX_FIFO_ROR) { + s->utsr1 |= UTSR1_ROR; + } + } + + s->utsr1 = utsr1; +} + +static void strongarm_uart_update_int_status(StrongARMUARTState *s) +{ + uint16_t utsr0 = s->utsr0 & + (UTSR0_REB | UTSR0_RBB | UTSR0_RID); + int i; + + if ((s->utcr3 & UTCR3_TXE) && + (s->utcr3 & UTCR3_TIE) && + s->tx_len <= 4) { + utsr0 |= UTSR0_TFS; + } + + if ((s->utcr3 & UTCR3_RXE) && + (s->utcr3 & UTCR3_RIE) && + s->rx_len > 4) { + utsr0 |= UTSR0_RFS; + } + + for (i = 0; i < s->rx_len && i < 4; i++) + if (s->rx_fifo[(s->rx_start + i) % 12] & ~0xff) { + utsr0 |= UTSR0_EIF; + break; + } + + s->utsr0 = utsr0; + qemu_set_irq(s->irq, utsr0); +} + +static void strongarm_uart_update_parameters(StrongARMUARTState *s) +{ + int speed, parity, data_bits, stop_bits, frame_size; + QEMUSerialSetParams ssp; + + /* Start bit. */ + frame_size = 1; + if (s->utcr0 & UTCR0_PE) { + /* Parity bit. */ + frame_size++; + if (s->utcr0 & UTCR0_OES) { + parity = 'E'; + } else { + parity = 'O'; + } + } else { + parity = 'N'; + } + if (s->utcr0 & UTCR0_SBS) { + stop_bits = 2; + } else { + stop_bits = 1; + } + + data_bits = (s->utcr0 & UTCR0_DSS) ? 8 : 7; + frame_size += data_bits + stop_bits; + speed = 3686400 / 16 / (s->brd + 1); + ssp.speed = speed; + ssp.parity = parity; + ssp.data_bits = data_bits; + ssp.stop_bits = stop_bits; + s->char_transmit_time = (get_ticks_per_sec() / speed) * frame_size; + if (s->chr) { + qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); + } + + DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label, + speed, parity, data_bits, stop_bits); +} + +static void strongarm_uart_rx_to(void *opaque) +{ + StrongARMUARTState *s = opaque; + + if (s->rx_len) { + s->utsr0 |= UTSR0_RID; + strongarm_uart_update_int_status(s); + } +} + +static void strongarm_uart_rx_push(StrongARMUARTState *s, uint16_t c) +{ + if ((s->utcr3 & UTCR3_RXE) == 0) { + /* rx disabled */ + return; + } + + if (s->wait_break_end) { + s->utsr0 |= UTSR0_REB; + s->wait_break_end = false; + } + + if (s->rx_len < 12) { + s->rx_fifo[(s->rx_start + s->rx_len) % 12] = c; + s->rx_len++; + } else + s->rx_fifo[(s->rx_start + 11) % 12] |= RX_FIFO_ROR; +} + +static int strongarm_uart_can_receive(void *opaque) +{ + StrongARMUARTState *s = opaque; + + if (s->rx_len == 12) { + return 0; + } + /* It's best not to get more than 2/3 of RX FIFO, so advertise that much */ + if (s->rx_len < 8) { + return 8 - s->rx_len; + } + return 1; +} + +static void strongarm_uart_receive(void *opaque, const uint8_t *buf, int size) +{ + StrongARMUARTState *s = opaque; + int i; + + for (i = 0; i < size; i++) { + strongarm_uart_rx_push(s, buf[i]); + } + + /* call the timeout receive callback in 3 char transmit time */ + qemu_mod_timer(s->rx_timeout_timer, + qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3); + + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); +} + +static void strongarm_uart_event(void *opaque, int event) +{ + StrongARMUARTState *s = opaque; + if (event == CHR_EVENT_BREAK) { + s->utsr0 |= UTSR0_RBB; + strongarm_uart_rx_push(s, RX_FIFO_FRE); + s->wait_break_end = true; + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); + } +} + +static void strongarm_uart_tx(void *opaque) +{ + StrongARMUARTState *s = opaque; + uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock); + + if (s->utcr3 & UTCR3_LBM) /* loopback */ { + strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1); + } else if (s->chr) { + qemu_chr_write(s->chr, &s->tx_fifo[s->tx_start], 1); + } + + s->tx_start = (s->tx_start + 1) % 8; + s->tx_len--; + if (s->tx_len) { + qemu_mod_timer(s->tx_timer, new_xmit_ts + s->char_transmit_time); + } + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); +} + +static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr) +{ + StrongARMUARTState *s = opaque; + uint16_t ret; + + switch (addr) { + case UTCR0: + return s->utcr0; + + case UTCR1: + return s->brd >> 8; + + case UTCR2: + return s->brd & 0xff; + + case UTCR3: + return s->utcr3; + + case UTDR: + if (s->rx_len != 0) { + ret = s->rx_fifo[s->rx_start]; + s->rx_start = (s->rx_start + 1) % 12; + s->rx_len--; + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); + return ret; + } + return 0; + + case UTSR0: + return s->utsr0; + + case UTSR1: + return s->utsr1; + + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + return 0; + } +} + +static void strongarm_uart_write(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + StrongARMUARTState *s = opaque; + + switch (addr) { + case UTCR0: + s->utcr0 = value & 0x7f; + strongarm_uart_update_parameters(s); + break; + + case UTCR1: + s->brd = (s->brd & 0xff) | ((value & 0xf) << 8); + strongarm_uart_update_parameters(s); + break; + + case UTCR2: + s->brd = (s->brd & 0xf00) | (value & 0xff); + strongarm_uart_update_parameters(s); + break; + + case UTCR3: + s->utcr3 = value & 0x3f; + if ((s->utcr3 & UTCR3_RXE) == 0) { + s->rx_len = 0; + } + if ((s->utcr3 & UTCR3_TXE) == 0) { + s->tx_len = 0; + } + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); + break; + + case UTDR: + if ((s->utcr3 & UTCR3_TXE) && s->tx_len != 8) { + s->tx_fifo[(s->tx_start + s->tx_len) % 8] = value; + s->tx_len++; + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); + if (s->tx_len == 1) { + strongarm_uart_tx(s); + } + } + break; + + case UTSR0: + s->utsr0 = s->utsr0 & ~(value & + (UTSR0_REB | UTSR0_RBB | UTSR0_RID)); + strongarm_uart_update_int_status(s); + break; + + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + } +} + +static CPUReadMemoryFunc * const strongarm_uart_readfn[] = { + strongarm_uart_read, + strongarm_uart_read, + strongarm_uart_read, +}; + +static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = { + strongarm_uart_write, + strongarm_uart_write, + strongarm_uart_write, +}; + +static int strongarm_uart_init(SysBusDevice *dev) +{ + StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev); + int iomemtype; + + iomemtype = cpu_register_io_memory(strongarm_uart_readfn, + strongarm_uart_writefn, s, DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, 0x10000, iomemtype); + sysbus_init_irq(dev, &s->irq); + + s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s); + s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s); + + if (s->chr) { + qemu_chr_add_handlers(s->chr, + strongarm_uart_can_receive, + strongarm_uart_receive, + strongarm_uart_event, + s); + } + + return 0; +} + +static void strongarm_uart_reset(DeviceState *dev) +{ + StrongARMUARTState *s = DO_UPCAST(StrongARMUARTState, busdev.qdev, dev); + + s->utcr0 = UTCR0_DSS; /* 8 data, no parity */ + s->brd = 23; /* 9600 */ + /* enable send & recv - this actually violates spec */ + s->utcr3 = UTCR3_TXE | UTCR3_RXE; + + s->rx_len = s->tx_len = 0; + + strongarm_uart_update_parameters(s); + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); +} + +static int strongarm_uart_post_load(void *opaque, int version_id) +{ + StrongARMUARTState *s = opaque; + + strongarm_uart_update_parameters(s); + strongarm_uart_update_status(s); + strongarm_uart_update_int_status(s); + + /* tx and restart timer */ + if (s->tx_len) { + strongarm_uart_tx(s); + } + + /* restart rx timeout timer */ + if (s->rx_len) { + qemu_mod_timer(s->rx_timeout_timer, + qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3); + } + + return 0; +} + +static const VMStateDescription vmstate_strongarm_uart_regs = { + .name = "strongarm-uart", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .post_load = strongarm_uart_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8(utcr0, StrongARMUARTState), + VMSTATE_UINT16(brd, StrongARMUARTState), + VMSTATE_UINT8(utcr3, StrongARMUARTState), + VMSTATE_UINT8(utsr0, StrongARMUARTState), + VMSTATE_UINT8_ARRAY(tx_fifo, StrongARMUARTState, 8), + VMSTATE_UINT8(tx_start, StrongARMUARTState), + VMSTATE_UINT8(tx_len, StrongARMUARTState), + VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMUARTState, 12), + VMSTATE_UINT8(rx_start, StrongARMUARTState), + VMSTATE_UINT8(rx_len, StrongARMUARTState), + VMSTATE_BOOL(wait_break_end, StrongARMUARTState), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_uart_info = { + .init = strongarm_uart_init, + .qdev.name = "strongarm-uart", + .qdev.desc = "StrongARM UART controller", + .qdev.size = sizeof(StrongARMUARTState), + .qdev.reset = strongarm_uart_reset, + .qdev.vmsd = &vmstate_strongarm_uart_regs, + .qdev.props = (Property[]) { + DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr), + DEFINE_PROP_END_OF_LIST(), + } +}; + +/* Synchronous Serial Ports */ +typedef struct { + SysBusDevice busdev; + qemu_irq irq; + SSIBus *bus; + + uint16_t sscr[2]; + uint16_t sssr; + + uint16_t rx_fifo[8]; + uint8_t rx_level; + uint8_t rx_start; +} StrongARMSSPState; + +#define SSCR0 0x60 /* SSP Control register 0 */ +#define SSCR1 0x64 /* SSP Control register 1 */ +#define SSDR 0x6c /* SSP Data register */ +#define SSSR 0x74 /* SSP Status register */ + +/* Bitfields for above registers */ +#define SSCR0_SPI(x) (((x) & 0x30) == 0x00) +#define SSCR0_SSP(x) (((x) & 0x30) == 0x10) +#define SSCR0_UWIRE(x) (((x) & 0x30) == 0x20) +#define SSCR0_PSP(x) (((x) & 0x30) == 0x30) +#define SSCR0_SSE (1 << 7) +#define SSCR0_DSS(x) (((x) & 0xf) + 1) +#define SSCR1_RIE (1 << 0) +#define SSCR1_TIE (1 << 1) +#define SSCR1_LBM (1 << 2) +#define SSSR_TNF (1 << 2) +#define SSSR_RNE (1 << 3) +#define SSSR_TFS (1 << 5) +#define SSSR_RFS (1 << 6) +#define SSSR_ROR (1 << 7) +#define SSSR_RW 0x0080 + +static void strongarm_ssp_int_update(StrongARMSSPState *s) +{ + int level = 0; + + level |= (s->sssr & SSSR_ROR); + level |= (s->sssr & SSSR_RFS) && (s->sscr[1] & SSCR1_RIE); + level |= (s->sssr & SSSR_TFS) && (s->sscr[1] & SSCR1_TIE); + qemu_set_irq(s->irq, level); +} + +static void strongarm_ssp_fifo_update(StrongARMSSPState *s) +{ + s->sssr &= ~SSSR_TFS; + s->sssr &= ~SSSR_TNF; + if (s->sscr[0] & SSCR0_SSE) { + if (s->rx_level >= 4) { + s->sssr |= SSSR_RFS; + } else { + s->sssr &= ~SSSR_RFS; + } + if (s->rx_level) { + s->sssr |= SSSR_RNE; + } else { + s->sssr &= ~SSSR_RNE; + } + /* TX FIFO is never filled, so it is always in underrun + condition if SSP is enabled */ + s->sssr |= SSSR_TFS; + s->sssr |= SSSR_TNF; + } + + strongarm_ssp_int_update(s); +} + +static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr) +{ + StrongARMSSPState *s = opaque; + uint32_t retval; + + switch (addr) { + case SSCR0: + return s->sscr[0]; + case SSCR1: + return s->sscr[1]; + case SSSR: + return s->sssr; + case SSDR: + if (~s->sscr[0] & SSCR0_SSE) { + return 0xffffffff; + } + if (s->rx_level < 1) { + printf("%s: SSP Rx Underrun\n", __func__); + return 0xffffffff; + } + s->rx_level--; + retval = s->rx_fifo[s->rx_start++]; + s->rx_start &= 0x7; + strongarm_ssp_fifo_update(s); + return retval; + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + break; + } + return 0; +} + +static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + StrongARMSSPState *s = opaque; + + switch (addr) { + case SSCR0: + s->sscr[0] = value & 0xffbf; + if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) { + printf("%s: Wrong data size: %i bits\n", __func__, + SSCR0_DSS(value)); + } + if (!(value & SSCR0_SSE)) { + s->sssr = 0; + s->rx_level = 0; + } + strongarm_ssp_fifo_update(s); + break; + + case SSCR1: + s->sscr[1] = value & 0x2f; + if (value & SSCR1_LBM) { + printf("%s: Attempt to use SSP LBM mode\n", __func__); + } + strongarm_ssp_fifo_update(s); + break; + + case SSSR: + s->sssr &= ~(value & SSSR_RW); + strongarm_ssp_int_update(s); + break; + + case SSDR: + if (SSCR0_UWIRE(s->sscr[0])) { + value &= 0xff; + } else + /* Note how 32bits overflow does no harm here */ + value &= (1 << SSCR0_DSS(s->sscr[0])) - 1; + + /* Data goes from here to the Tx FIFO and is shifted out from + * there directly to the slave, no need to buffer it. + */ + if (s->sscr[0] & SSCR0_SSE) { + uint32_t readval; + if (s->sscr[1] & SSCR1_LBM) { + readval = value; + } else { + readval = ssi_transfer(s->bus, value); + } + + if (s->rx_level < 0x08) { + s->rx_fifo[(s->rx_start + s->rx_level++) & 0x7] = readval; + } else { + s->sssr |= SSSR_ROR; + } + } + strongarm_ssp_fifo_update(s); + break; + + default: + printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr); + break; + } +} + +static CPUReadMemoryFunc * const strongarm_ssp_readfn[] = { + strongarm_ssp_read, + strongarm_ssp_read, + strongarm_ssp_read, +}; + +static CPUWriteMemoryFunc * const strongarm_ssp_writefn[] = { + strongarm_ssp_write, + strongarm_ssp_write, + strongarm_ssp_write, +}; + +static int strongarm_ssp_post_load(void *opaque, int version_id) +{ + StrongARMSSPState *s = opaque; + + strongarm_ssp_fifo_update(s); + + return 0; +} + +static int strongarm_ssp_init(SysBusDevice *dev) +{ + int iomemtype; + StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev); + + sysbus_init_irq(dev, &s->irq); + + iomemtype = cpu_register_io_memory(strongarm_ssp_readfn, + strongarm_ssp_writefn, s, + DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, iomemtype); + + s->bus = ssi_create_bus(&dev->qdev, "ssi"); + return 0; +} + +static void strongarm_ssp_reset(DeviceState *dev) +{ + StrongARMSSPState *s = DO_UPCAST(StrongARMSSPState, busdev.qdev, dev); + s->sssr = 0x03; /* 3 bit data, SPI, disabled */ + s->rx_start = 0; + s->rx_level = 0; +} + +static const VMStateDescription vmstate_strongarm_ssp_regs = { + .name = "strongarm-ssp", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .post_load = strongarm_ssp_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2), + VMSTATE_UINT16(sssr, StrongARMSSPState), + VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMSSPState, 8), + VMSTATE_UINT8(rx_start, StrongARMSSPState), + VMSTATE_UINT8(rx_level, StrongARMSSPState), + VMSTATE_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo strongarm_ssp_info = { + .init = strongarm_ssp_init, + .qdev.name = "strongarm-ssp", + .qdev.desc = "StrongARM SSP controller", + .qdev.size = sizeof(StrongARMSSPState), + .qdev.reset = strongarm_ssp_reset, + .qdev.vmsd = &vmstate_strongarm_ssp_regs, +}; + +/* Main CPU functions */ +StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev) +{ + StrongARMState *s; + qemu_irq *pic; + int i; + + s = qemu_mallocz(sizeof(StrongARMState)); + + if (!rev) { + rev = "sa1110-b5"; + } + + if (strncmp(rev, "sa1110", 6)) { + error_report("Machine requires a SA1110 processor.\n"); + exit(1); + } + + s->env = cpu_init(rev); + + if (!s->env) { + error_report("Unable to find CPU definition\n"); + exit(1); + } + + cpu_register_physical_memory(SA_SDCS0, + sdram_size, qemu_ram_alloc(NULL, "strongarm.sdram", + sdram_size) | IO_MEM_RAM); + + pic = arm_pic_init_cpu(s->env); + s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000, + pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL); + + sysbus_create_varargs("pxa25x-timer", 0x90000000, + qdev_get_gpio_in(s->pic, SA_PIC_OSTC0), + qdev_get_gpio_in(s->pic, SA_PIC_OSTC1), + qdev_get_gpio_in(s->pic, SA_PIC_OSTC2), + qdev_get_gpio_in(s->pic, SA_PIC_OSTC3), + NULL); + + sysbus_create_simple("strongarm-rtc", 0x90010000, + qdev_get_gpio_in(s->pic, SA_PIC_RTC_ALARM)); + + s->gpio = strongarm_gpio_init(0x90040000, s->pic); + + s->ppc = sysbus_create_varargs("strongarm-ppc", 0x90060000, NULL); + + for (i = 0; sa_serial[i].io_base; i++) { + DeviceState *dev = qdev_create(NULL, "strongarm-uart"); + qdev_prop_set_chr(dev, "chardev", serial_hds[i]); + qdev_init_nofail(dev); + sysbus_mmio_map(sysbus_from_qdev(dev), 0, + sa_serial[i].io_base); + sysbus_connect_irq(sysbus_from_qdev(dev), 0, + qdev_get_gpio_in(s->pic, sa_serial[i].irq)); + } + + s->ssp = sysbus_create_varargs("strongarm-ssp", 0x80070000, + qdev_get_gpio_in(s->pic, SA_PIC_SSP), NULL); + s->ssp_bus = (SSIBus *)qdev_get_child_bus(s->ssp, "ssi"); + + return s; +} + +static void strongarm_register_devices(void) +{ + sysbus_register_withprop(&strongarm_pic_info); + sysbus_register_withprop(&strongarm_rtc_sysbus_info); + sysbus_register_withprop(&strongarm_gpio_info); + sysbus_register_withprop(&strongarm_ppc_info); + sysbus_register_withprop(&strongarm_uart_info); + sysbus_register_withprop(&strongarm_ssp_info); +} +device_init(strongarm_register_devices) diff --git a/hw/strongarm.h b/hw/strongarm.h new file mode 100644 index 000000000..a81b110e2 --- /dev/null +++ b/hw/strongarm.h @@ -0,0 +1,64 @@ +#ifndef _STRONGARM_H +#define _STRONGARM_H + +#define SA_CS0 0x00000000 +#define SA_CS1 0x08000000 +#define SA_CS2 0x10000000 +#define SA_CS3 0x18000000 +#define SA_PCMCIA_CS0 0x20000000 +#define SA_PCMCIA_CS1 0x30000000 +#define SA_CS4 0x40000000 +#define SA_CS5 0x48000000 +/* system registers here */ +#define SA_SDCS0 0xc0000000 +#define SA_SDCS1 0xc8000000 +#define SA_SDCS2 0xd0000000 +#define SA_SDCS3 0xd8000000 + +enum { + SA_PIC_GPIO0_EDGE = 0, + SA_PIC_GPIO1_EDGE, + SA_PIC_GPIO2_EDGE, + SA_PIC_GPIO3_EDGE, + SA_PIC_GPIO4_EDGE, + SA_PIC_GPIO5_EDGE, + SA_PIC_GPIO6_EDGE, + SA_PIC_GPIO7_EDGE, + SA_PIC_GPIO8_EDGE, + SA_PIC_GPIO9_EDGE, + SA_PIC_GPIO10_EDGE, + SA_PIC_GPIOX_EDGE, + SA_PIC_LCD, + SA_PIC_UDC, + SA_PIC_RSVD1, + SA_PIC_UART1, + SA_PIC_UART2, + SA_PIC_UART3, + SA_PIC_MCP, + SA_PIC_SSP, + SA_PIC_DMA_CH0, + SA_PIC_DMA_CH1, + SA_PIC_DMA_CH2, + SA_PIC_DMA_CH3, + SA_PIC_DMA_CH4, + SA_PIC_DMA_CH5, + SA_PIC_OSTC0, + SA_PIC_OSTC1, + SA_PIC_OSTC2, + SA_PIC_OSTC3, + SA_PIC_RTC_HZ, + SA_PIC_RTC_ALARM, +}; + +typedef struct { + CPUState *env; + DeviceState *pic; + DeviceState *gpio; + DeviceState *ppc; + DeviceState *ssp; + SSIBus *ssp_bus; +} StrongARMState; + +StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev); + +#endif diff --git a/hw/syborg.c b/hw/syborg.c index 758c69a9c..bc200e48a 100644 --- a/hw/syborg.c +++ b/hw/syborg.c @@ -25,7 +25,6 @@ #include "sysbus.h" #include "boards.h" #include "arm-misc.h" -#include "sysemu.h" #include "net.h" static struct arm_boot_info syborg_binfo; diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c index d295e99eb..706a03966 100644 --- a/hw/syborg_keyboard.c +++ b/hw/syborg_keyboard.c @@ -51,11 +51,11 @@ enum { typedef struct { SysBusDevice busdev; - int int_enabled; + uint32_t int_enabled; int extension_bit; uint32_t fifo_size; uint32_t *key_fifo; - int read_pos, read_count; + uint32_t read_pos, read_count; qemu_irq irq; } SyborgKeyboardState; @@ -165,43 +165,21 @@ static void syborg_keyboard_event(void *opaque, int keycode) syborg_keyboard_update(s); } -static void syborg_keyboard_save(QEMUFile *f, void *opaque) -{ - SyborgKeyboardState *s = (SyborgKeyboardState *)opaque; - int i; - - qemu_put_be32(f, s->fifo_size); - qemu_put_be32(f, s->int_enabled); - qemu_put_be32(f, s->extension_bit); - qemu_put_be32(f, s->read_pos); - qemu_put_be32(f, s->read_count); - for (i = 0; i < s->fifo_size; i++) { - qemu_put_be32(f, s->key_fifo[i]); - } -} - -static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgKeyboardState *s = (SyborgKeyboardState *)opaque; - uint32_t val; - int i; - - if (version_id != 1) - return -EINVAL; - - val = qemu_get_be32(f); - if (val != s->fifo_size) - return -EINVAL; - - s->int_enabled = qemu_get_be32(f); - s->extension_bit = qemu_get_be32(f); - s->read_pos = qemu_get_be32(f); - s->read_count = qemu_get_be32(f); - for (i = 0; i < s->fifo_size; i++) { - s->key_fifo[i] = qemu_get_be32(f); +static const VMStateDescription vmstate_syborg_keyboard = { + .name = "syborg_keyboard", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState), + VMSTATE_UINT32(int_enabled, SyborgKeyboardState), + VMSTATE_UINT32(read_pos, SyborgKeyboardState), + VMSTATE_UINT32(read_count, SyborgKeyboardState), + VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1, + vmstate_info_uint32, uint32), + VMSTATE_END_OF_LIST() } - return 0; -} +}; static int syborg_keyboard_init(SysBusDevice *dev) { @@ -221,8 +199,7 @@ static int syborg_keyboard_init(SysBusDevice *dev) qemu_add_kbd_event_handler(syborg_keyboard_event, s); - register_savevm(&dev->qdev, "syborg_keyboard", -1, 1, - syborg_keyboard_save, syborg_keyboard_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s); return 0; } diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c index a88688846..2f9970704 100644 --- a/hw/syborg_pointer.c +++ b/hw/syborg_pointer.c @@ -152,52 +152,36 @@ static void syborg_pointer_event(void *opaque, int dx, int dy, int dz, syborg_pointer_update(s); } -static void syborg_pointer_save(QEMUFile *f, void *opaque) -{ - SyborgPointerState *s = (SyborgPointerState *)opaque; - int i; - - qemu_put_be32(f, s->fifo_size); - qemu_put_be32(f, s->absolute); - qemu_put_be32(f, s->int_enabled); - qemu_put_be32(f, s->read_pos); - qemu_put_be32(f, s->read_count); - for (i = 0; i < s->fifo_size; i++) { - qemu_put_be32(f, s->event_fifo[i].x); - qemu_put_be32(f, s->event_fifo[i].y); - qemu_put_be32(f, s->event_fifo[i].z); - qemu_put_be32(f, s->event_fifo[i].pointer_buttons); +static const VMStateDescription vmstate_event_data = { + .name = "dbma_channel", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_INT32(x, event_data), + VMSTATE_INT32(y, event_data), + VMSTATE_INT32(z, event_data), + VMSTATE_INT32(pointer_buttons, event_data), + VMSTATE_END_OF_LIST() } -} +}; -static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgPointerState *s = (SyborgPointerState *)opaque; - uint32_t val; - int i; - - if (version_id != 1) - return -EINVAL; - - val = qemu_get_be32(f); - if (val != s->fifo_size) - return -EINVAL; - - val = qemu_get_be32(f); - if (val != s->absolute) - return -EINVAL; - - s->int_enabled = qemu_get_be32(f); - s->read_pos = qemu_get_be32(f); - s->read_count = qemu_get_be32(f); - for (i = 0; i < s->fifo_size; i++) { - s->event_fifo[i].x = qemu_get_be32(f); - s->event_fifo[i].y = qemu_get_be32(f); - s->event_fifo[i].z = qemu_get_be32(f); - s->event_fifo[i].pointer_buttons = qemu_get_be32(f); +static const VMStateDescription vmstate_syborg_pointer = { + .name = "syborg_pointer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState), + VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState), + VMSTATE_INT32(int_enabled, SyborgPointerState), + VMSTATE_INT32(read_pos, SyborgPointerState), + VMSTATE_INT32(read_count, SyborgPointerState), + VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size, + 1, vmstate_event_data, event_data), + VMSTATE_END_OF_LIST() } - return 0; -} +}; static int syborg_pointer_init(SysBusDevice *dev) { @@ -219,8 +203,7 @@ static int syborg_pointer_init(SysBusDevice *dev) qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute, "Syborg Pointer"); - register_savevm(&dev->qdev, "syborg_pointer", -1, 1, - syborg_pointer_save, syborg_pointer_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s); return 0; } diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c index 16d8f9edb..69f6ccf29 100644 --- a/hw/syborg_rtc.c +++ b/hw/syborg_rtc.c @@ -102,26 +102,17 @@ static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = { syborg_rtc_write }; -static void syborg_rtc_save(QEMUFile *f, void *opaque) -{ - SyborgRTCState *s = opaque; - - qemu_put_be64(f, s->offset); - qemu_put_be64(f, s->data); -} - -static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgRTCState *s = opaque; - - if (version_id != 1) - return -EINVAL; - - s->offset = qemu_get_be64(f); - s->data = qemu_get_be64(f); - - return 0; -} +static const VMStateDescription vmstate_syborg_rtc = { + .name = "syborg_keyboard", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(offset, SyborgRTCState), + VMSTATE_INT64(data, SyborgRTCState), + VMSTATE_END_OF_LIST() + } +}; static int syborg_rtc_init(SysBusDevice *dev) { @@ -137,8 +128,7 @@ static int syborg_rtc_init(SysBusDevice *dev) qemu_get_timedate(&tm, 0); s->offset = (uint64_t)mktime(&tm) * 1000000000; - register_savevm(&dev->qdev, "syborg_rtc", -1, 1, - syborg_rtc_save, syborg_rtc_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s); return 0; } diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c index 34ce076d4..df2950fe8 100644 --- a/hw/syborg_serial.c +++ b/hw/syborg_serial.c @@ -273,47 +273,24 @@ static CPUWriteMemoryFunc * const syborg_serial_writefn[] = { syborg_serial_write }; -static void syborg_serial_save(QEMUFile *f, void *opaque) -{ - SyborgSerialState *s = opaque; - int i; - - qemu_put_be32(f, s->fifo_size); - qemu_put_be32(f, s->int_enable); - qemu_put_be32(f, s->read_pos); - qemu_put_be32(f, s->read_count); - qemu_put_be32(f, s->dma_tx_ptr); - qemu_put_be32(f, s->dma_rx_ptr); - qemu_put_be32(f, s->dma_rx_size); - for (i = 0; i < s->fifo_size; i++) { - qemu_put_be32(f, s->read_fifo[i]); - } -} - -static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgSerialState *s = opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - i = qemu_get_be32(f); - if (s->fifo_size != i) - return -EINVAL; - - s->int_enable = qemu_get_be32(f); - s->read_pos = qemu_get_be32(f); - s->read_count = qemu_get_be32(f); - s->dma_tx_ptr = qemu_get_be32(f); - s->dma_rx_ptr = qemu_get_be32(f); - s->dma_rx_size = qemu_get_be32(f); - for (i = 0; i < s->fifo_size; i++) { - s->read_fifo[i] = qemu_get_be32(f); +static const VMStateDescription vmstate_syborg_serial = { + .name = "syborg_serial", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState), + VMSTATE_UINT32(int_enable, SyborgSerialState), + VMSTATE_INT32(read_pos, SyborgSerialState), + VMSTATE_INT32(read_count, SyborgSerialState), + VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState), + VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState), + VMSTATE_UINT32(dma_rx_size, SyborgSerialState), + VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1, + vmstate_info_uint32, uint32), + VMSTATE_END_OF_LIST() } - - return 0; -} +}; static int syborg_serial_init(SysBusDevice *dev) { @@ -336,8 +313,6 @@ static int syborg_serial_init(SysBusDevice *dev) } s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0])); - register_savevm(&dev->qdev, "syborg_serial", -1, 1, - syborg_serial_save, syborg_serial_load, s); return 0; } @@ -345,6 +320,7 @@ static SysBusDeviceInfo syborg_serial_info = { .init = syborg_serial_init, .qdev.name = "syborg,serial", .qdev.size = sizeof(SyborgSerialState), + .qdev.vmsd = &vmstate_syborg_serial, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c index cedcd8ed4..50c813e96 100644 --- a/hw/syborg_timer.c +++ b/hw/syborg_timer.c @@ -174,34 +174,21 @@ static CPUWriteMemoryFunc * const syborg_timer_writefn[] = { syborg_timer_write }; -static void syborg_timer_save(QEMUFile *f, void *opaque) -{ - SyborgTimerState *s = opaque; - - qemu_put_be32(f, s->running); - qemu_put_be32(f, s->oneshot); - qemu_put_be32(f, s->limit); - qemu_put_be32(f, s->int_level); - qemu_put_be32(f, s->int_enabled); - qemu_put_ptimer(f, s->timer); -} - -static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgTimerState *s = opaque; - - if (version_id != 1) - return -EINVAL; - - s->running = qemu_get_be32(f); - s->oneshot = qemu_get_be32(f); - s->limit = qemu_get_be32(f); - s->int_level = qemu_get_be32(f); - s->int_enabled = qemu_get_be32(f); - qemu_get_ptimer(f, s->timer); - - return 0; -} +static const VMStateDescription vmstate_syborg_timer = { + .name = "syborg_timer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32(running, SyborgTimerState), + VMSTATE_INT32(oneshot, SyborgTimerState), + VMSTATE_UINT32(limit, SyborgTimerState), + VMSTATE_UINT32(int_level, SyborgTimerState), + VMSTATE_UINT32(int_enabled, SyborgTimerState), + VMSTATE_PTIMER(timer, SyborgTimerState), + VMSTATE_END_OF_LIST() + } +}; static int syborg_timer_init(SysBusDevice *dev) { @@ -222,8 +209,7 @@ static int syborg_timer_init(SysBusDevice *dev) bh = qemu_bh_new(syborg_timer_tick, s); s->timer = ptimer_init(bh); ptimer_set_freq(s->timer, s->freq); - register_savevm(&dev->qdev, "syborg_timer", -1, 1, - syborg_timer_save, syborg_timer_load, s); + vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s); return 0; } diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c index ee08c4910..2f3e6da4e 100644 --- a/hw/syborg_virtio.c +++ b/hw/syborg_virtio.c @@ -26,7 +26,6 @@ #include "sysbus.h" #include "virtio.h" #include "virtio-net.h" -#include "sysemu.h" //#define DEBUG_SYBORG_VIRTIO diff --git a/hw/sysbus.c b/hw/sysbus.c index acad72abe..2e22be7b2 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -18,7 +18,6 @@ */ #include "sysbus.h" -#include "sysemu.h" #include "monitor.h" static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); diff --git a/hw/tc58128.c b/hw/tc58128.c index 672a01c46..61b99dd4d 100644 --- a/hw/tc58128.c +++ b/hw/tc58128.c @@ -1,6 +1,5 @@ #include "hw.h" #include "sh.h" -#include "sysemu.h" #include "loader.h" #define CE1 0x0100 @@ -11,7 +11,6 @@ #include "hw.h" #include "pxa.h" #include "arm-misc.h" -#include "sysemu.h" #include "devices.h" #include "sharpsl.h" #include "pcmcia.h" diff --git a/hw/twl92230.c b/hw/twl92230.c index 8e74acc05..a75448f06 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -22,7 +22,6 @@ #include "hw.h" #include "qemu-timer.h" #include "i2c.h" -#include "sysemu.h" #include "console.h" #define VERBOSE 1 diff --git a/hw/usb-hid.c b/hw/usb-hid.c index c25362cc9..89c293c46 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -26,7 +26,7 @@ #include "console.h" #include "usb.h" #include "usb-desc.h" -#include "sysemu.h" +#include "qemu-timer.h" /* HID interface requests */ #define GET_REPORT 0xa101 diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 76f5b027b..947fd3f83 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -33,7 +33,7 @@ do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0) enum USBMSDMode { USB_MSDM_CBW, /* Command Block. */ - USB_MSDM_DATAOUT, /* Tranfer data to device. */ + USB_MSDM_DATAOUT, /* Transfer data to device. */ USB_MSDM_DATAIN, /* Transfer data from device. */ USB_MSDM_CSW /* Command Status. */ }; @@ -253,7 +253,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag, usb_msd_copy_data(s); if (s->usb_len == 0) { /* Set s->packet to NULL before calling usb_packet_complete - because annother request may be issued before + because another request may be issued before usb_packet_complete returns. */ DPRINTF("Packet complete %p\n", p); s->packet = NULL; diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index f9add1cd4..447b337e0 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -15,7 +15,6 @@ #include "qemu-common.h" #include "virtio.h" #include "pc.h" -#include "sysemu.h" #include "cpu.h" #include "monitor.h" #include "balloon.h" diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 6b5237b3c..de539c4ea 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -28,6 +28,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) return qemu_chr_write(vcon->chr, buf, len); } +/* Callback function that's called when the guest opens the port */ +static void guest_open(VirtIOSerialPort *port) +{ + VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + + qemu_chr_guest_open(vcon->chr); +} + +/* Callback function that's called when the guest closes the port */ +static void guest_close(VirtIOSerialPort *port) +{ + VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + + qemu_chr_guest_close(vcon->chr); +} + /* Readiness of the guest to accept data on a port */ static int chr_can_read(void *opaque) { @@ -64,6 +80,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialPort *port) qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, vcon); vcon->port.info->have_data = flush_buf; + vcon->port.info->guest_open = guest_open; + vcon->port.info->guest_close = guest_close; } return 0; } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 5236470ba..991005bca 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -961,7 +961,7 @@ static PCIDeviceInfo virtio_info[] = { .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_net_init_pci, .exit = virtio_net_exit_pci, - .romfile = "pxe-virtio.bin", + .romfile = "pxe-virtio.rom", .qdev.props = (Property[]) { DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 62273799b..f10d48fdb 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -494,7 +494,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque) VirtIOSerial *s = opaque; VirtIOSerialPort *port; uint32_t nr_active_ports; - unsigned int i; + unsigned int i, max_nr_ports; /* The virtio device */ virtio_save(&s->vdev, f); @@ -506,8 +506,8 @@ static void virtio_serial_save(QEMUFile *f, void *opaque) qemu_put_be32s(f, &s->config.max_nr_ports); /* The ports map */ - - for (i = 0; i < (s->config.max_nr_ports + 31) / 32; i++) { + max_nr_ports = tswap32(s->config.max_nr_ports); + for (i = 0; i < (max_nr_ports + 31) / 32; i++) { qemu_put_be32s(f, &s->ports_map[i]); } @@ -568,7 +568,8 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be16s(f, &s->config.rows); qemu_get_be32s(f, &max_nr_ports); - if (max_nr_ports > s->config.max_nr_ports) { + tswap32s(&max_nr_ports); + if (max_nr_ports > tswap32(s->config.max_nr_ports)) { /* Source could have had more ports than us. Fail migration. */ return -EINVAL; } @@ -670,9 +671,10 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) /* This function is only used if a port id is not provided by the user */ static uint32_t find_free_port_id(VirtIOSerial *vser) { - unsigned int i; + unsigned int i, max_nr_ports; - for (i = 0; i < (vser->config.max_nr_ports + 31) / 32; i++) { + max_nr_ports = tswap32(vser->config.max_nr_ports); + for (i = 0; i < (max_nr_ports + 31) / 32; i++) { uint32_t map, bit; map = vser->ports_map[i]; @@ -720,7 +722,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base) VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev, base); VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus); - int ret; + int ret, max_nr_ports; bool plugging_port0; port->vser = bus->vser; @@ -750,9 +752,10 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base) } } - if (port->id >= port->vser->config.max_nr_ports) { + max_nr_ports = tswap32(port->vser->config.max_nr_ports); + if (port->id >= max_nr_ports) { error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u\n", - port->vser->config.max_nr_ports - 1); + max_nr_ports - 1); return -1; } @@ -863,7 +866,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output); } - vser->config.max_nr_ports = conf->max_virtserial_ports; + vser->config.max_nr_ports = tswap32(conf->max_virtserial_ports); vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32) * sizeof(vser->ports_map[0])); /* diff --git a/hw/virtio.c b/hw/virtio.c index 31bd9e32d..6e8814cb6 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -16,7 +16,6 @@ #include "trace.h" #include "qemu-error.h" #include "virtio.h" -#include "sysemu.h" /* The alignment to use between consumer and producer parts of vring. * x86 pagesize again. */ diff --git a/hw/vmport.c b/hw/vmport.c index 19010e484..c8aefaabb 100644 --- a/hw/vmport.c +++ b/hw/vmport.c @@ -24,7 +24,6 @@ #include "hw.h" #include "isa.h" #include "pc.h" -#include "sysemu.h" #include "kvm.h" #include "qdev.h" diff --git a/hw/xen_console.c b/hw/xen_console.c index d2261f413..c6c816381 100644 --- a/hw/xen_console.c +++ b/hw/xen_console.c @@ -33,7 +33,6 @@ #include <xenctrl.h> #include "hw.h" -#include "sysemu.h" #include "qemu-char.h" #include "xen_backend.h" diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c index 371c56206..4093587df 100644 --- a/hw/xen_domainbuild.c +++ b/hw/xen_domainbuild.c @@ -1,7 +1,6 @@ #include <signal.h> #include "xen_backend.h" #include "xen_domainbuild.h" -#include "sysemu.h" #include "qemu-timer.h" #include "qemu-log.h" diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c index 77a34bf11..0d7f73ed8 100644 --- a/hw/xen_machine_pv.c +++ b/hw/xen_machine_pv.c @@ -24,7 +24,6 @@ #include "hw.h" #include "pc.h" -#include "sysemu.h" #include "boards.h" #include "xen_backend.h" #include "xen_domainbuild.h" diff --git a/hw/xenfb.c b/hw/xenfb.c index da5297b49..1db75fbe4 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -44,7 +44,6 @@ #include <xen/io/protocols.h> #include "hw.h" -#include "sysemu.h" #include "console.h" #include "qemu-char.h" #include "xen_backend.h" diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index 30827b03c..d398c18e9 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -23,7 +23,6 @@ */ #include "sysbus.h" -#include "sysemu.h" #include "qemu-timer.h" #define D(x) |