+static void fd_save (QEMUFile *f, fdrive_t *fd)
+{
+ uint8_t tmp;
+
+ tmp = fd->drflags;
+ qemu_put_8s(f, &tmp);
+ qemu_put_8s(f, &fd->head);
+ qemu_put_8s(f, &fd->track);
+ qemu_put_8s(f, &fd->sect);
+ qemu_put_8s(f, &fd->dir);
+ qemu_put_8s(f, &fd->rw);
+}
+
+static void fdc_save (QEMUFile *f, void *opaque)
+{
+ fdctrl_t *s = opaque;
+
+ qemu_put_8s(f, &s->state);
+ qemu_put_8s(f, &s->dma_en);
+ qemu_put_8s(f, &s->cur_drv);
+ qemu_put_8s(f, &s->bootsel);
+ qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
+ qemu_put_be32s(f, &s->data_pos);
+ qemu_put_be32s(f, &s->data_len);
+ qemu_put_8s(f, &s->data_state);
+ qemu_put_8s(f, &s->data_dir);
+ qemu_put_8s(f, &s->int_status);
+ qemu_put_8s(f, &s->eot);
+ qemu_put_8s(f, &s->timer0);
+ qemu_put_8s(f, &s->timer1);
+ qemu_put_8s(f, &s->precomp_trk);
+ qemu_put_8s(f, &s->config);
+ qemu_put_8s(f, &s->lock);
+ qemu_put_8s(f, &s->pwrd);
+ fd_save(f, &s->drives[0]);
+ fd_save(f, &s->drives[1]);
+}
+
+static int fd_load (QEMUFile *f, fdrive_t *fd)
+{
+ uint8_t tmp;
+
+ qemu_get_8s(f, &tmp);
+ fd->drflags = tmp;
+ qemu_get_8s(f, &fd->head);
+ qemu_get_8s(f, &fd->track);
+ qemu_get_8s(f, &fd->sect);
+ qemu_get_8s(f, &fd->dir);
+ qemu_get_8s(f, &fd->rw);
+
+ return 0;
+}
+
+static int fdc_load (QEMUFile *f, void *opaque, int version_id)
+{
+ fdctrl_t *s = opaque;
+ int ret;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_8s(f, &s->state);
+ qemu_get_8s(f, &s->dma_en);
+ qemu_get_8s(f, &s->cur_drv);
+ qemu_get_8s(f, &s->bootsel);
+ qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
+ qemu_get_be32s(f, &s->data_pos);
+ qemu_get_be32s(f, &s->data_len);
+ qemu_get_8s(f, &s->data_state);
+ qemu_get_8s(f, &s->data_dir);
+ qemu_get_8s(f, &s->int_status);
+ qemu_get_8s(f, &s->eot);
+ qemu_get_8s(f, &s->timer0);
+ qemu_get_8s(f, &s->timer1);
+ qemu_get_8s(f, &s->precomp_trk);
+ qemu_get_8s(f, &s->config);
+ qemu_get_8s(f, &s->lock);
+ qemu_get_8s(f, &s->pwrd);
+
+ ret = fd_load(f, &s->drives[0]);
+ if (ret == 0)
+ ret = fd_load(f, &s->drives[1]);
+
+ return ret;
+}
+
+static void fdctrl_external_reset(void *opaque)
+{
+ fdctrl_t *s = opaque;
+
+ fdctrl_reset(s, 0);
+}
+
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
+ target_phys_addr_t io_base,