Patchwork [8/8,MIPS] qdev: convert rc4030 to sysbus device

login
register
mail settings
Submitter Hervé Poussineau
Date Sept. 8, 2010, 8:39 p.m.
Message ID <1283978392-6313-9-git-send-email-hpoussin@reactos.org>
Download mbox | patch
Permalink /patch/64213/
State New
Headers show

Comments

Hervé Poussineau - Sept. 8, 2010, 8:39 p.m.
Use it in Jazz emulation
Remove rc4030_init() function, which is not used anymore

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/mips.h      |    4 +-
 hw/mips_jazz.c |    8 +--
 hw/rc4030.c    |  135 ++++++++++++++++++++++++++-----------------------------
 3 files changed, 69 insertions(+), 78 deletions(-)
Blue Swirl - Sept. 9, 2010, 2:37 p.m.
2010/9/8 Hervé Poussineau <hpoussin@reactos.org>:
> Use it in Jazz emulation
> Remove rc4030_init() function, which is not used anymore
>
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  hw/mips.h      |    4 +-
>  hw/mips_jazz.c |    8 +--
>  hw/rc4030.c    |  135 ++++++++++++++++++++++++++-----------------------------
>  3 files changed, 69 insertions(+), 78 deletions(-)
>
> diff --git a/hw/mips.h b/hw/mips.h
> index 2897ea6..bdbe024 100644
> --- a/hw/mips.h
> +++ b/hw/mips.h
> @@ -16,8 +16,8 @@ typedef struct rc4030DMAState *rc4030_dma;
>  void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
>  void rc4030_dma_read(void *dma, uint8_t *buf, int len);
>  void rc4030_dma_write(void *dma, uint8_t *buf, int len);
> -
> -void *rc4030_init(qemu_irq timer, rc4030_dma **dmas);
> +extern rc4030_dma *rc4030_dmas;
> +extern void *rc4030_dma_opaque;

These should be device properties (DEFINE_PROP_PTR, qdev_set_prop_ptr().

>
>  /* dp8393x.c */
>  void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
> diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
> index 56739db..eec30c8 100644
> --- a/hw/mips_jazz.c
> +++ b/hw/mips_jazz.c
> @@ -133,8 +133,6 @@ void mips_jazz_init (ram_addr_t ram_size,
>     CPUState *env;
>     DeviceState *dev;
>     qemu_irq rc4030[16], *i8259;
> -    rc4030_dma *dmas;
> -    void* rc4030_opaque;
>     int s_rtc, s_dma_dummy;
>     NICInfo *nd;
>     PITState *pit;
> @@ -196,7 +194,7 @@ void mips_jazz_init (ram_addr_t ram_size,
>         rc4030[n] = qdev_get_gpio_in(dev, n);
>     }
>
> -    rc4030_opaque = rc4030_init(env->irq[6], &dmas);
> +    sysbus_create_simple("rc4030", 0x80000000, env->irq[6]);
>     s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
>     cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
>
> @@ -237,7 +235,7 @@ void mips_jazz_init (ram_addr_t ram_size,
>             nd->model = qemu_strdup("dp83932");
>         if (strcmp(nd->model, "dp83932") == 0) {
>             dp83932_init(nd, 0x80001000, 2, rc4030[4],
> -                         rc4030_opaque, rc4030_dma_memory_rw);
> +                         rc4030_dma_opaque, rc4030_dma_memory_rw);
>             break;
>         } else if (strcmp(nd->model, "?") == 0) {
>             fprintf(stderr, "qemu: Supported NICs: dp83932\n");
> @@ -250,7 +248,7 @@ void mips_jazz_init (ram_addr_t ram_size,
>
>     /* SCSI adapter */
>     esp_init(0x80002000, 0,
> -             rc4030_dma_read, rc4030_dma_write, dmas[0],
> +             rc4030_dma_read, rc4030_dma_write, rc4030_dmas[0],
>              rc4030[5], &esp_reset);
>
>     /* Floppy */
> diff --git a/hw/rc4030.c b/hw/rc4030.c
> index 811d12d..0c77c44 100644
> --- a/hw/rc4030.c
> +++ b/hw/rc4030.c
> @@ -45,6 +45,9 @@ static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
>  #define RC4030_ERROR(fmt, ...) \
>  do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
>
> +rc4030_dma *rc4030_dmas = NULL;
> +void *rc4030_dma_opaque = NULL;
> +
>  /********************************************************/
>  /* rc4030 emulation                                     */
>
> @@ -584,9 +587,8 @@ static void jazzio_reset(JazzIoState* s)
>     qemu_irq_lower(s->irq);
>  }
>
> -static void rc4030_reset(void *opaque)
> +static void rc4030_reset(rc4030State *s)
>  {
> -    rc4030State *s = opaque;
>     int i;
>
>     s->config = 0x410; /* some boards seem to accept 0x104 too */
> @@ -611,63 +613,6 @@ static void rc4030_reset(void *opaque)
>     qemu_irq_lower(s->timer_irq);
>  }
>
> -static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
> -{
> -    rc4030State* s = opaque;
> -    int i, j;
> -
> -    if (version_id != 2)
> -        return -EINVAL;
> -
> -    s->config = qemu_get_be32(f);
> -    s->invalid_address_register = qemu_get_be32(f);
> -    for (i = 0; i < 8; i++)
> -        for (j = 0; j < 4; j++)
> -            s->dma_regs[i][j] = qemu_get_be32(f);
> -    s->dma_tl_base = qemu_get_be32(f);
> -    s->dma_tl_limit = qemu_get_be32(f);
> -    s->cache_maint = qemu_get_be32(f);
> -    s->remote_failed_address = qemu_get_be32(f);
> -    s->memory_failed_address = qemu_get_be32(f);
> -    s->cache_ptag = qemu_get_be32(f);
> -    s->cache_ltag = qemu_get_be32(f);
> -    s->cache_bmask = qemu_get_be32(f);
> -    s->offset210 = qemu_get_be32(f);
> -    s->nvram_protect = qemu_get_be32(f);
> -    for (i = 0; i < 15; i++)
> -        s->rem_speed[i] = qemu_get_be32(f);
> -    s->itr = qemu_get_be32(f);
> -
> -    set_next_tick(s);
> -
> -    return 0;
> -}
> -
> -static void rc4030_save(QEMUFile *f, void *opaque)
> -{
> -    rc4030State* s = opaque;
> -    int i, j;
> -
> -    qemu_put_be32(f, s->config);
> -    qemu_put_be32(f, s->invalid_address_register);
> -    for (i = 0; i < 8; i++)
> -        for (j = 0; j < 4; j++)
> -            qemu_put_be32(f, s->dma_regs[i][j]);
> -    qemu_put_be32(f, s->dma_tl_base);
> -    qemu_put_be32(f, s->dma_tl_limit);
> -    qemu_put_be32(f, s->cache_maint);
> -    qemu_put_be32(f, s->remote_failed_address);
> -    qemu_put_be32(f, s->memory_failed_address);
> -    qemu_put_be32(f, s->cache_ptag);
> -    qemu_put_be32(f, s->cache_ltag);
> -    qemu_put_be32(f, s->cache_bmask);
> -    qemu_put_be32(f, s->offset210);
> -    qemu_put_be32(f, s->nvram_protect);
> -    for (i = 0; i < 15; i++)
> -        qemu_put_be32(f, s->rem_speed[i]);
> -    qemu_put_be32(f, s->itr);
> -}
> -
>  void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)
>  {
>     rc4030State *s = opaque;
> @@ -788,28 +733,75 @@ static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
>     return s;
>  }
>
> -void *rc4030_init(qemu_irq timer, rc4030_dma **dmas)
> +static int rc4030_post_load(void *opaque, int version_id)
>  {
> -    rc4030State *s;
> -    int s_chipset;
> -
> -    s = qemu_mallocz(sizeof(rc4030State));
> +    rc4030State *s = opaque;
> +    set_next_tick(s);
> +    return 0;
> +}
>
> -    *dmas = rc4030_allocate_dmas(s, 4);
> +static const VMStateDescription vmstate_rc4030 = {
> +    .name = "rc4030",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .minimum_version_id_old = 0,
> +    .post_load = rc4030_post_load,
> +    .fields = (VMStateField []) {
> +        VMSTATE_UINT32(config, rc4030State),
> +        VMSTATE_UINT32(invalid_address_register, rc4030State),
> +        VMSTATE_BUFFER_UNSAFE(dma_regs, rc4030State, 0, 8 * 3 * sizeof(uint32_t)),
> +        VMSTATE_UINT32(dma_tl_base, rc4030State),
> +        VMSTATE_UINT32(dma_tl_limit, rc4030State),
> +        VMSTATE_UINT32(cache_maint, rc4030State),
> +        VMSTATE_UINT32(remote_failed_address, rc4030State),
> +        VMSTATE_UINT32(memory_failed_address, rc4030State),
> +        VMSTATE_UINT32(cache_ptag, rc4030State),
> +        VMSTATE_UINT32(cache_ltag, rc4030State),
> +        VMSTATE_UINT32(cache_bmask, rc4030State),
> +        VMSTATE_UINT32(offset210, rc4030State),
> +        VMSTATE_UINT32(nvram_protect, rc4030State),
> +        VMSTATE_UINT32_ARRAY(rem_speed, rc4030State, 16),
> +        VMSTATE_UINT32(itr, rc4030State),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
>
> -    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
> -    s->timer_irq = timer;
> +typedef struct {
> +    SysBusDevice busdev;
> +    rc4030State rc4030;
> +} SysBusRc4030State;
>
> -    qemu_register_reset(rc4030_reset, s);
> -    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
> +static void rc4030_sysbus_reset(DeviceState *d)
> +{
> +    rc4030State *s = &container_of(d, SysBusRc4030State, busdev.qdev)->rc4030;
>     rc4030_reset(s);
> +}
> +
> +static int rc4030_sysbus_initfn(SysBusDevice *dev)
> +{
> +    rc4030State *s = &FROM_SYSBUS(SysBusRc4030State, dev)->rc4030;
> +    int s_chipset;
> +
> +    rc4030_dmas = rc4030_allocate_dmas(s, 4);
> +    rc4030_dma_opaque = s;
> +
> +    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
> +    sysbus_init_irq(dev, &s->timer_irq);
>
>     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
> -    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
> +    sysbus_init_mmio(dev, 0x300, s_chipset);
>
> -    return s;
> +    return 0;
>  }
>
> +static SysBusDeviceInfo rc4030_sysbus_info = {
> +    .qdev.name  = "rc4030",
> +    .qdev.size  = sizeof(SysBusRc4030State),
> +    .qdev.vmsd  = &vmstate_rc4030,
> +    .qdev.reset = rc4030_sysbus_reset,
> +    .init       = rc4030_sysbus_initfn,
> +};
> +
>  static int jazzio_post_load(void *opaque, int version_id)
>  {
>     JazzIoState *s = opaque;
> @@ -878,6 +870,7 @@ static SysBusDeviceInfo jazzio_sysbus_info = {
>
>  static void jazz_register(void)
>  {
> +    sysbus_register_withprop(&rc4030_sysbus_info);
>     sysbus_register_withprop(&jazzio_sysbus_info);
>  }
>
> --
> 1.7.1.GIT
>
>
>
Markus Armbruster - Sept. 25, 2010, 9:59 a.m.
Blue Swirl <blauwirbel@gmail.com> writes:

> 2010/9/8 Hervé Poussineau <hpoussin@reactos.org>:
>> Use it in Jazz emulation
>> Remove rc4030_init() function, which is not used anymore
>>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  hw/mips.h      |    4 +-
>>  hw/mips_jazz.c |    8 +--
>>  hw/rc4030.c    |  135 ++++++++++++++++++++++++++-----------------------------
>>  3 files changed, 69 insertions(+), 78 deletions(-)
>>
>> diff --git a/hw/mips.h b/hw/mips.h
>> index 2897ea6..bdbe024 100644
>> --- a/hw/mips.h
>> +++ b/hw/mips.h
>> @@ -16,8 +16,8 @@ typedef struct rc4030DMAState *rc4030_dma;
>>  void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
>>  void rc4030_dma_read(void *dma, uint8_t *buf, int len);
>>  void rc4030_dma_write(void *dma, uint8_t *buf, int len);
>> -
>> -void *rc4030_init(qemu_irq timer, rc4030_dma **dmas);
>> +extern rc4030_dma *rc4030_dmas;
>> +extern void *rc4030_dma_opaque;
>
> These should be device properties (DEFINE_PROP_PTR, qdev_set_prop_ptr().

Note: DEFINE_PROP_PTR() & friends are for dirty hacks only.  Maybe we
should talk about how to do it cleanly.

[...]
Blue Swirl - Sept. 25, 2010, 10:43 a.m.
On Sat, Sep 25, 2010 at 9:59 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Blue Swirl <blauwirbel@gmail.com> writes:
>
>> 2010/9/8 Hervé Poussineau <hpoussin@reactos.org>:
>>> Use it in Jazz emulation
>>> Remove rc4030_init() function, which is not used anymore
>>>
>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>> ---
>>>  hw/mips.h      |    4 +-
>>>  hw/mips_jazz.c |    8 +--
>>>  hw/rc4030.c    |  135 ++++++++++++++++++++++++++-----------------------------
>>>  3 files changed, 69 insertions(+), 78 deletions(-)
>>>
>>> diff --git a/hw/mips.h b/hw/mips.h
>>> index 2897ea6..bdbe024 100644
>>> --- a/hw/mips.h
>>> +++ b/hw/mips.h
>>> @@ -16,8 +16,8 @@ typedef struct rc4030DMAState *rc4030_dma;
>>>  void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
>>>  void rc4030_dma_read(void *dma, uint8_t *buf, int len);
>>>  void rc4030_dma_write(void *dma, uint8_t *buf, int len);
>>> -
>>> -void *rc4030_init(qemu_irq timer, rc4030_dma **dmas);
>>> +extern rc4030_dma *rc4030_dmas;
>>> +extern void *rc4030_dma_opaque;
>>
>> These should be device properties (DEFINE_PROP_PTR, qdev_set_prop_ptr().
>
> Note: DEFINE_PROP_PTR() & friends are for dirty hacks only.  Maybe we
> should talk about how to do it cleanly.

We'd probably need something like an unified DMA structure at qdev
level. Then the global DMA access and mapping routines should be
hidden inside that structure.

Another interesting case is pcnet/lance, there also the bus is
different (PCI vs. SysBus). Can we still have common DMA structure, or
do we need PCIDMA and SysBusDMA?

Patch

diff --git a/hw/mips.h b/hw/mips.h
index 2897ea6..bdbe024 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -16,8 +16,8 @@  typedef struct rc4030DMAState *rc4030_dma;
 void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
 void rc4030_dma_read(void *dma, uint8_t *buf, int len);
 void rc4030_dma_write(void *dma, uint8_t *buf, int len);
-
-void *rc4030_init(qemu_irq timer, rc4030_dma **dmas);
+extern rc4030_dma *rc4030_dmas;
+extern void *rc4030_dma_opaque;
 
 /* dp8393x.c */
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 56739db..eec30c8 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -133,8 +133,6 @@  void mips_jazz_init (ram_addr_t ram_size,
     CPUState *env;
     DeviceState *dev;
     qemu_irq rc4030[16], *i8259;
-    rc4030_dma *dmas;
-    void* rc4030_opaque;
     int s_rtc, s_dma_dummy;
     NICInfo *nd;
     PITState *pit;
@@ -196,7 +194,7 @@  void mips_jazz_init (ram_addr_t ram_size,
         rc4030[n] = qdev_get_gpio_in(dev, n);
     }
 
-    rc4030_opaque = rc4030_init(env->irq[6], &dmas);
+    sysbus_create_simple("rc4030", 0x80000000, env->irq[6]);
     s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
     cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
 
@@ -237,7 +235,7 @@  void mips_jazz_init (ram_addr_t ram_size,
             nd->model = qemu_strdup("dp83932");
         if (strcmp(nd->model, "dp83932") == 0) {
             dp83932_init(nd, 0x80001000, 2, rc4030[4],
-                         rc4030_opaque, rc4030_dma_memory_rw);
+                         rc4030_dma_opaque, rc4030_dma_memory_rw);
             break;
         } else if (strcmp(nd->model, "?") == 0) {
             fprintf(stderr, "qemu: Supported NICs: dp83932\n");
@@ -250,7 +248,7 @@  void mips_jazz_init (ram_addr_t ram_size,
 
     /* SCSI adapter */
     esp_init(0x80002000, 0,
-             rc4030_dma_read, rc4030_dma_write, dmas[0],
+             rc4030_dma_read, rc4030_dma_write, rc4030_dmas[0],
              rc4030[5], &esp_reset);
 
     /* Floppy */
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 811d12d..0c77c44 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -45,6 +45,9 @@  static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
 #define RC4030_ERROR(fmt, ...) \
 do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
 
+rc4030_dma *rc4030_dmas = NULL;
+void *rc4030_dma_opaque = NULL;
+
 /********************************************************/
 /* rc4030 emulation                                     */
 
@@ -584,9 +587,8 @@  static void jazzio_reset(JazzIoState* s)
     qemu_irq_lower(s->irq);
 }
 
-static void rc4030_reset(void *opaque)
+static void rc4030_reset(rc4030State *s)
 {
-    rc4030State *s = opaque;
     int i;
 
     s->config = 0x410; /* some boards seem to accept 0x104 too */
@@ -611,63 +613,6 @@  static void rc4030_reset(void *opaque)
     qemu_irq_lower(s->timer_irq);
 }
 
-static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
-{
-    rc4030State* s = opaque;
-    int i, j;
-
-    if (version_id != 2)
-        return -EINVAL;
-
-    s->config = qemu_get_be32(f);
-    s->invalid_address_register = qemu_get_be32(f);
-    for (i = 0; i < 8; i++)
-        for (j = 0; j < 4; j++)
-            s->dma_regs[i][j] = qemu_get_be32(f);
-    s->dma_tl_base = qemu_get_be32(f);
-    s->dma_tl_limit = qemu_get_be32(f);
-    s->cache_maint = qemu_get_be32(f);
-    s->remote_failed_address = qemu_get_be32(f);
-    s->memory_failed_address = qemu_get_be32(f);
-    s->cache_ptag = qemu_get_be32(f);
-    s->cache_ltag = qemu_get_be32(f);
-    s->cache_bmask = qemu_get_be32(f);
-    s->offset210 = qemu_get_be32(f);
-    s->nvram_protect = qemu_get_be32(f);
-    for (i = 0; i < 15; i++)
-        s->rem_speed[i] = qemu_get_be32(f);
-    s->itr = qemu_get_be32(f);
-
-    set_next_tick(s);
-
-    return 0;
-}
-
-static void rc4030_save(QEMUFile *f, void *opaque)
-{
-    rc4030State* s = opaque;
-    int i, j;
-
-    qemu_put_be32(f, s->config);
-    qemu_put_be32(f, s->invalid_address_register);
-    for (i = 0; i < 8; i++)
-        for (j = 0; j < 4; j++)
-            qemu_put_be32(f, s->dma_regs[i][j]);
-    qemu_put_be32(f, s->dma_tl_base);
-    qemu_put_be32(f, s->dma_tl_limit);
-    qemu_put_be32(f, s->cache_maint);
-    qemu_put_be32(f, s->remote_failed_address);
-    qemu_put_be32(f, s->memory_failed_address);
-    qemu_put_be32(f, s->cache_ptag);
-    qemu_put_be32(f, s->cache_ltag);
-    qemu_put_be32(f, s->cache_bmask);
-    qemu_put_be32(f, s->offset210);
-    qemu_put_be32(f, s->nvram_protect);
-    for (i = 0; i < 15; i++)
-        qemu_put_be32(f, s->rem_speed[i]);
-    qemu_put_be32(f, s->itr);
-}
-
 void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)
 {
     rc4030State *s = opaque;
@@ -788,28 +733,75 @@  static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
     return s;
 }
 
-void *rc4030_init(qemu_irq timer, rc4030_dma **dmas)
+static int rc4030_post_load(void *opaque, int version_id)
 {
-    rc4030State *s;
-    int s_chipset;
-
-    s = qemu_mallocz(sizeof(rc4030State));
+    rc4030State *s = opaque;
+    set_next_tick(s);
+    return 0;
+}
 
-    *dmas = rc4030_allocate_dmas(s, 4);
+static const VMStateDescription vmstate_rc4030 = {
+    .name = "rc4030",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = rc4030_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT32(config, rc4030State),
+        VMSTATE_UINT32(invalid_address_register, rc4030State),
+        VMSTATE_BUFFER_UNSAFE(dma_regs, rc4030State, 0, 8 * 3 * sizeof(uint32_t)),
+        VMSTATE_UINT32(dma_tl_base, rc4030State),
+        VMSTATE_UINT32(dma_tl_limit, rc4030State),
+        VMSTATE_UINT32(cache_maint, rc4030State),
+        VMSTATE_UINT32(remote_failed_address, rc4030State),
+        VMSTATE_UINT32(memory_failed_address, rc4030State),
+        VMSTATE_UINT32(cache_ptag, rc4030State),
+        VMSTATE_UINT32(cache_ltag, rc4030State),
+        VMSTATE_UINT32(cache_bmask, rc4030State),
+        VMSTATE_UINT32(offset210, rc4030State),
+        VMSTATE_UINT32(nvram_protect, rc4030State),
+        VMSTATE_UINT32_ARRAY(rem_speed, rc4030State, 16),
+        VMSTATE_UINT32(itr, rc4030State),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
-    s->timer_irq = timer;
+typedef struct {
+    SysBusDevice busdev;
+    rc4030State rc4030;
+} SysBusRc4030State;
 
-    qemu_register_reset(rc4030_reset, s);
-    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
+static void rc4030_sysbus_reset(DeviceState *d)
+{
+    rc4030State *s = &container_of(d, SysBusRc4030State, busdev.qdev)->rc4030;
     rc4030_reset(s);
+}
+
+static int rc4030_sysbus_initfn(SysBusDevice *dev)
+{
+    rc4030State *s = &FROM_SYSBUS(SysBusRc4030State, dev)->rc4030;
+    int s_chipset;
+
+    rc4030_dmas = rc4030_allocate_dmas(s, 4);
+    rc4030_dma_opaque = s;
+
+    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
+    sysbus_init_irq(dev, &s->timer_irq);
 
     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
-    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
+    sysbus_init_mmio(dev, 0x300, s_chipset);
 
-    return s;
+    return 0;
 }
 
+static SysBusDeviceInfo rc4030_sysbus_info = {
+    .qdev.name  = "rc4030",
+    .qdev.size  = sizeof(SysBusRc4030State),
+    .qdev.vmsd  = &vmstate_rc4030,
+    .qdev.reset = rc4030_sysbus_reset,
+    .init       = rc4030_sysbus_initfn,
+};
+
 static int jazzio_post_load(void *opaque, int version_id)
 {
     JazzIoState *s = opaque;
@@ -878,6 +870,7 @@  static SysBusDeviceInfo jazzio_sysbus_info = {
 
 static void jazz_register(void)
 {
+    sysbus_register_withprop(&rc4030_sysbus_info);
     sysbus_register_withprop(&jazzio_sysbus_info);
 }