Commit 23e39294034e13d29a0707483542bab850d601b4
1 parent
ab19b0ec
Save/restore for stellaris boards.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4824 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
12 changed files
with
761 additions
and
14 deletions
hw/arm_gic.c
... | ... | @@ -650,6 +650,79 @@ static void gic_reset(gic_state *s) |
650 | 650 | #endif |
651 | 651 | } |
652 | 652 | |
653 | +static void gic_save(QEMUFile *f, void *opaque) | |
654 | +{ | |
655 | + gic_state *s = (gic_state *)opaque; | |
656 | + int i; | |
657 | + int j; | |
658 | + | |
659 | + qemu_put_be32(f, s->enabled); | |
660 | + for (i = 0; i < NCPU; i++) { | |
661 | + qemu_put_be32(f, s->cpu_enabled[i]); | |
662 | +#ifndef NVIC | |
663 | + qemu_put_be32(f, s->irq_target[i]); | |
664 | +#endif | |
665 | + for (j = 0; j < 32; j++) | |
666 | + qemu_put_be32(f, s->priority1[j][i]); | |
667 | + for (j = 0; j < GIC_NIRQ; j++) | |
668 | + qemu_put_be32(f, s->last_active[j][i]); | |
669 | + qemu_put_be32(f, s->priority_mask[i]); | |
670 | + qemu_put_be32(f, s->running_irq[i]); | |
671 | + qemu_put_be32(f, s->running_priority[i]); | |
672 | + qemu_put_be32(f, s->current_pending[i]); | |
673 | + } | |
674 | + for (i = 0; i < GIC_NIRQ - 32; i++) { | |
675 | + qemu_put_be32(f, s->priority2[i]); | |
676 | + } | |
677 | + for (i = 0; i < GIC_NIRQ; i++) { | |
678 | + qemu_put_byte(f, s->irq_state[i].enabled); | |
679 | + qemu_put_byte(f, s->irq_state[i].pending); | |
680 | + qemu_put_byte(f, s->irq_state[i].active); | |
681 | + qemu_put_byte(f, s->irq_state[i].level); | |
682 | + qemu_put_byte(f, s->irq_state[i].model); | |
683 | + qemu_put_byte(f, s->irq_state[i].trigger); | |
684 | + } | |
685 | +} | |
686 | + | |
687 | +static int gic_load(QEMUFile *f, void *opaque, int version_id) | |
688 | +{ | |
689 | + gic_state *s = (gic_state *)opaque; | |
690 | + int i; | |
691 | + int j; | |
692 | + | |
693 | + if (version_id != 1) | |
694 | + return -EINVAL; | |
695 | + | |
696 | + s->enabled = qemu_get_be32(f); | |
697 | + for (i = 0; i < NCPU; i++) { | |
698 | + s->cpu_enabled[i] = qemu_get_be32(f); | |
699 | +#ifndef NVIC | |
700 | + s->irq_target[i] = qemu_get_be32(f); | |
701 | +#endif | |
702 | + for (j = 0; j < 32; j++) | |
703 | + s->priority1[j][i] = qemu_get_be32(f); | |
704 | + for (j = 0; j < GIC_NIRQ; j++) | |
705 | + s->last_active[j][i] = qemu_get_be32(f); | |
706 | + s->priority_mask[i] = qemu_get_be32(f); | |
707 | + s->running_irq[i] = qemu_get_be32(f); | |
708 | + s->running_priority[i] = qemu_get_be32(f); | |
709 | + s->current_pending[i] = qemu_get_be32(f); | |
710 | + } | |
711 | + for (i = 0; i < GIC_NIRQ - 32; i++) { | |
712 | + s->priority2[i] = qemu_get_be32(f); | |
713 | + } | |
714 | + for (i = 0; i < GIC_NIRQ; i++) { | |
715 | + s->irq_state[i].enabled = qemu_get_byte(f); | |
716 | + s->irq_state[i].pending = qemu_get_byte(f); | |
717 | + s->irq_state[i].active = qemu_get_byte(f); | |
718 | + s->irq_state[i].level = qemu_get_byte(f); | |
719 | + s->irq_state[i].model = qemu_get_byte(f); | |
720 | + s->irq_state[i].trigger = qemu_get_byte(f); | |
721 | + } | |
722 | + | |
723 | + return 0; | |
724 | +} | |
725 | + | |
653 | 726 | static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq) |
654 | 727 | { |
655 | 728 | gic_state *s; |
... | ... | @@ -669,5 +742,6 @@ static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq) |
669 | 742 | iomemtype); |
670 | 743 | s->base = base; |
671 | 744 | gic_reset(s); |
745 | + register_savevm("arm_gic", -1, 1, gic_save, gic_load, s); | |
672 | 746 | return s; |
673 | 747 | } | ... | ... |
hw/arm_timer.c
... | ... | @@ -143,6 +143,29 @@ static void arm_timer_tick(void *opaque) |
143 | 143 | arm_timer_update(s); |
144 | 144 | } |
145 | 145 | |
146 | +static void arm_timer_save(QEMUFile *f, void *opaque) | |
147 | +{ | |
148 | + arm_timer_state *s = (arm_timer_state *)opaque; | |
149 | + qemu_put_be32(f, s->control); | |
150 | + qemu_put_be32(f, s->limit); | |
151 | + qemu_put_be32(f, s->int_level); | |
152 | + qemu_put_ptimer(f, s->timer); | |
153 | +} | |
154 | + | |
155 | +static int arm_timer_load(QEMUFile *f, void *opaque, int version_id) | |
156 | +{ | |
157 | + arm_timer_state *s = (arm_timer_state *)opaque; | |
158 | + | |
159 | + if (version_id != 1) | |
160 | + return -EINVAL; | |
161 | + | |
162 | + s->control = qemu_get_be32(f); | |
163 | + s->limit = qemu_get_be32(f); | |
164 | + s->int_level = qemu_get_be32(f); | |
165 | + qemu_get_ptimer(f, s->timer); | |
166 | + return 0; | |
167 | +} | |
168 | + | |
146 | 169 | static void *arm_timer_init(uint32_t freq, qemu_irq irq) |
147 | 170 | { |
148 | 171 | arm_timer_state *s; |
... | ... | @@ -155,7 +178,7 @@ static void *arm_timer_init(uint32_t freq, qemu_irq irq) |
155 | 178 | |
156 | 179 | bh = qemu_bh_new(arm_timer_tick, s); |
157 | 180 | s->timer = ptimer_init(bh); |
158 | - /* ??? Save/restore. */ | |
181 | + register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s); | |
159 | 182 | return s; |
160 | 183 | } |
161 | 184 | |
... | ... | @@ -218,6 +241,25 @@ static CPUWriteMemoryFunc *sp804_writefn[] = { |
218 | 241 | sp804_write |
219 | 242 | }; |
220 | 243 | |
244 | +static void sp804_save(QEMUFile *f, void *opaque) | |
245 | +{ | |
246 | + sp804_state *s = (sp804_state *)opaque; | |
247 | + qemu_put_be32(f, s->level[0]); | |
248 | + qemu_put_be32(f, s->level[1]); | |
249 | +} | |
250 | + | |
251 | +static int sp804_load(QEMUFile *f, void *opaque, int version_id) | |
252 | +{ | |
253 | + sp804_state *s = (sp804_state *)opaque; | |
254 | + | |
255 | + if (version_id != 1) | |
256 | + return -EINVAL; | |
257 | + | |
258 | + s->level[0] = qemu_get_be32(f); | |
259 | + s->level[1] = qemu_get_be32(f); | |
260 | + return 0; | |
261 | +} | |
262 | + | |
221 | 263 | void sp804_init(uint32_t base, qemu_irq irq) |
222 | 264 | { |
223 | 265 | int iomemtype; |
... | ... | @@ -235,7 +277,7 @@ void sp804_init(uint32_t base, qemu_irq irq) |
235 | 277 | iomemtype = cpu_register_io_memory(0, sp804_readfn, |
236 | 278 | sp804_writefn, s); |
237 | 279 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
238 | - /* ??? Save/restore. */ | |
280 | + register_savevm("sp804", -1, 1, sp804_save, sp804_load, s); | |
239 | 281 | } |
240 | 282 | |
241 | 283 | |
... | ... | @@ -303,6 +345,7 @@ void icp_pit_init(uint32_t base, qemu_irq *pic, int irq) |
303 | 345 | iomemtype = cpu_register_io_memory(0, icp_pit_readfn, |
304 | 346 | icp_pit_writefn, s); |
305 | 347 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
306 | - /* ??? Save/restore. */ | |
348 | + /* This device has no state to save/restore. The component timers will | |
349 | + save themselves. */ | |
307 | 350 | } |
308 | 351 | ... | ... |
hw/armv7m_nvic.c
... | ... | @@ -368,6 +368,31 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) |
368 | 368 | } |
369 | 369 | } |
370 | 370 | |
371 | +static void nvic_save(QEMUFile *f, void *opaque) | |
372 | +{ | |
373 | + nvic_state *s = (nvic_state *)opaque; | |
374 | + | |
375 | + qemu_put_be32(f, s->systick.control); | |
376 | + qemu_put_be32(f, s->systick.reload); | |
377 | + qemu_put_be64(f, s->systick.tick); | |
378 | + qemu_put_timer(f, s->systick.timer); | |
379 | +} | |
380 | + | |
381 | +static int nvic_load(QEMUFile *f, void *opaque, int version_id) | |
382 | +{ | |
383 | + nvic_state *s = (nvic_state *)opaque; | |
384 | + | |
385 | + if (version_id != 1) | |
386 | + return -EINVAL; | |
387 | + | |
388 | + s->systick.control = qemu_get_be32(f); | |
389 | + s->systick.reload = qemu_get_be32(f); | |
390 | + s->systick.tick = qemu_get_be64(f); | |
391 | + qemu_get_timer(f, s->systick.timer); | |
392 | + | |
393 | + return 0; | |
394 | +} | |
395 | + | |
371 | 396 | qemu_irq *armv7m_nvic_init(CPUState *env) |
372 | 397 | { |
373 | 398 | nvic_state *s; |
... | ... | @@ -381,5 +406,6 @@ qemu_irq *armv7m_nvic_init(CPUState *env) |
381 | 406 | if (env->v7m.nvic) |
382 | 407 | cpu_abort(env, "CPU can only have one NVIC\n"); |
383 | 408 | env->v7m.nvic = s; |
409 | + register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s); | |
384 | 410 | return s->gic->in; |
385 | 411 | } | ... | ... |
hw/pl011.c
... | ... | @@ -238,6 +238,57 @@ static CPUWriteMemoryFunc *pl011_writefn[] = { |
238 | 238 | pl011_write |
239 | 239 | }; |
240 | 240 | |
241 | +static void pl011_save(QEMUFile *f, void *opaque) | |
242 | +{ | |
243 | + pl011_state *s = (pl011_state *)opaque; | |
244 | + int i; | |
245 | + | |
246 | + qemu_put_be32(f, s->readbuff); | |
247 | + qemu_put_be32(f, s->flags); | |
248 | + qemu_put_be32(f, s->lcr); | |
249 | + qemu_put_be32(f, s->cr); | |
250 | + qemu_put_be32(f, s->dmacr); | |
251 | + qemu_put_be32(f, s->int_enabled); | |
252 | + qemu_put_be32(f, s->int_level); | |
253 | + for (i = 0; i < 16; i++) | |
254 | + qemu_put_be32(f, s->read_fifo[i]); | |
255 | + qemu_put_be32(f, s->ilpr); | |
256 | + qemu_put_be32(f, s->ibrd); | |
257 | + qemu_put_be32(f, s->fbrd); | |
258 | + qemu_put_be32(f, s->ifl); | |
259 | + qemu_put_be32(f, s->read_pos); | |
260 | + qemu_put_be32(f, s->read_count); | |
261 | + qemu_put_be32(f, s->read_trigger); | |
262 | +} | |
263 | + | |
264 | +static int pl011_load(QEMUFile *f, void *opaque, int version_id) | |
265 | +{ | |
266 | + pl011_state *s = (pl011_state *)opaque; | |
267 | + int i; | |
268 | + | |
269 | + if (version_id != 1) | |
270 | + return -EINVAL; | |
271 | + | |
272 | + s->readbuff = qemu_get_be32(f); | |
273 | + s->flags = qemu_get_be32(f); | |
274 | + s->lcr = qemu_get_be32(f); | |
275 | + s->cr = qemu_get_be32(f); | |
276 | + s->dmacr = qemu_get_be32(f); | |
277 | + s->int_enabled = qemu_get_be32(f); | |
278 | + s->int_level = qemu_get_be32(f); | |
279 | + for (i = 0; i < 16; i++) | |
280 | + s->read_fifo[i] = qemu_get_be32(f); | |
281 | + s->ilpr = qemu_get_be32(f); | |
282 | + s->ibrd = qemu_get_be32(f); | |
283 | + s->fbrd = qemu_get_be32(f); | |
284 | + s->ifl = qemu_get_be32(f); | |
285 | + s->read_pos = qemu_get_be32(f); | |
286 | + s->read_count = qemu_get_be32(f); | |
287 | + s->read_trigger = qemu_get_be32(f); | |
288 | + | |
289 | + return 0; | |
290 | +} | |
291 | + | |
241 | 292 | void pl011_init(uint32_t base, qemu_irq irq, |
242 | 293 | CharDriverState *chr, enum pl011_type type) |
243 | 294 | { |
... | ... | @@ -260,6 +311,6 @@ void pl011_init(uint32_t base, qemu_irq irq, |
260 | 311 | qemu_chr_add_handlers(chr, pl011_can_receive, pl011_receive, |
261 | 312 | pl011_event, s); |
262 | 313 | } |
263 | - /* ??? Save/restore. */ | |
314 | + register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s); | |
264 | 315 | } |
265 | 316 | ... | ... |
hw/pl022.c
... | ... | @@ -244,6 +244,55 @@ static CPUWriteMemoryFunc *pl022_writefn[] = { |
244 | 244 | pl022_write |
245 | 245 | }; |
246 | 246 | |
247 | +static void pl022_save(QEMUFile *f, void *opaque) | |
248 | +{ | |
249 | + pl022_state *s = (pl022_state *)opaque; | |
250 | + int i; | |
251 | + | |
252 | + qemu_put_be32(f, s->cr0); | |
253 | + qemu_put_be32(f, s->cr1); | |
254 | + qemu_put_be32(f, s->bitmask); | |
255 | + qemu_put_be32(f, s->sr); | |
256 | + qemu_put_be32(f, s->cpsr); | |
257 | + qemu_put_be32(f, s->is); | |
258 | + qemu_put_be32(f, s->im); | |
259 | + qemu_put_be32(f, s->tx_fifo_head); | |
260 | + qemu_put_be32(f, s->rx_fifo_head); | |
261 | + qemu_put_be32(f, s->tx_fifo_len); | |
262 | + qemu_put_be32(f, s->rx_fifo_len); | |
263 | + for (i = 0; i < 8; i++) { | |
264 | + qemu_put_be16(f, s->tx_fifo[i]); | |
265 | + qemu_put_be16(f, s->rx_fifo[i]); | |
266 | + } | |
267 | +} | |
268 | + | |
269 | +static int pl022_load(QEMUFile *f, void *opaque, int version_id) | |
270 | +{ | |
271 | + pl022_state *s = (pl022_state *)opaque; | |
272 | + int i; | |
273 | + | |
274 | + if (version_id != 1) | |
275 | + return -EINVAL; | |
276 | + | |
277 | + s->cr0 = qemu_get_be32(f); | |
278 | + s->cr1 = qemu_get_be32(f); | |
279 | + s->bitmask = qemu_get_be32(f); | |
280 | + s->sr = qemu_get_be32(f); | |
281 | + s->cpsr = qemu_get_be32(f); | |
282 | + s->is = qemu_get_be32(f); | |
283 | + s->im = qemu_get_be32(f); | |
284 | + s->tx_fifo_head = qemu_get_be32(f); | |
285 | + s->rx_fifo_head = qemu_get_be32(f); | |
286 | + s->tx_fifo_len = qemu_get_be32(f); | |
287 | + s->rx_fifo_len = qemu_get_be32(f); | |
288 | + for (i = 0; i < 8; i++) { | |
289 | + s->tx_fifo[i] = qemu_get_be16(f); | |
290 | + s->rx_fifo[i] = qemu_get_be16(f); | |
291 | + } | |
292 | + | |
293 | + return 0; | |
294 | +} | |
295 | + | |
247 | 296 | void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), |
248 | 297 | void * opaque) |
249 | 298 | { |
... | ... | @@ -259,7 +308,7 @@ void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), |
259 | 308 | s->xfer_cb = xfer_cb; |
260 | 309 | s->opaque = opaque; |
261 | 310 | pl022_reset(s); |
262 | - /* ??? Save/restore. */ | |
311 | + register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s); | |
263 | 312 | } |
264 | 313 | |
265 | 314 | ... | ... |
hw/pl061.c
... | ... | @@ -240,6 +240,62 @@ static CPUWriteMemoryFunc *pl061_writefn[] = { |
240 | 240 | pl061_write |
241 | 241 | }; |
242 | 242 | |
243 | +static void pl061_save(QEMUFile *f, void *opaque) | |
244 | +{ | |
245 | + pl061_state *s = (pl061_state *)opaque; | |
246 | + | |
247 | + qemu_put_be32(f, s->locked); | |
248 | + qemu_put_be32(f, s->data); | |
249 | + qemu_put_be32(f, s->old_data); | |
250 | + qemu_put_be32(f, s->dir); | |
251 | + qemu_put_be32(f, s->isense); | |
252 | + qemu_put_be32(f, s->ibe); | |
253 | + qemu_put_be32(f, s->iev); | |
254 | + qemu_put_be32(f, s->im); | |
255 | + qemu_put_be32(f, s->istate); | |
256 | + qemu_put_be32(f, s->afsel); | |
257 | + qemu_put_be32(f, s->dr2r); | |
258 | + qemu_put_be32(f, s->dr4r); | |
259 | + qemu_put_be32(f, s->dr8r); | |
260 | + qemu_put_be32(f, s->odr); | |
261 | + qemu_put_be32(f, s->pur); | |
262 | + qemu_put_be32(f, s->pdr); | |
263 | + qemu_put_be32(f, s->slr); | |
264 | + qemu_put_be32(f, s->den); | |
265 | + qemu_put_be32(f, s->cr); | |
266 | + qemu_put_be32(f, s->float_high); | |
267 | +} | |
268 | + | |
269 | +static int pl061_load(QEMUFile *f, void *opaque, int version_id) | |
270 | +{ | |
271 | + pl061_state *s = (pl061_state *)opaque; | |
272 | + if (version_id != 1) | |
273 | + return -EINVAL; | |
274 | + | |
275 | + s->locked = qemu_get_be32(f); | |
276 | + s->data = qemu_get_be32(f); | |
277 | + s->old_data = qemu_get_be32(f); | |
278 | + s->dir = qemu_get_be32(f); | |
279 | + s->isense = qemu_get_be32(f); | |
280 | + s->ibe = qemu_get_be32(f); | |
281 | + s->iev = qemu_get_be32(f); | |
282 | + s->im = qemu_get_be32(f); | |
283 | + s->istate = qemu_get_be32(f); | |
284 | + s->afsel = qemu_get_be32(f); | |
285 | + s->dr2r = qemu_get_be32(f); | |
286 | + s->dr4r = qemu_get_be32(f); | |
287 | + s->dr8r = qemu_get_be32(f); | |
288 | + s->odr = qemu_get_be32(f); | |
289 | + s->pur = qemu_get_be32(f); | |
290 | + s->pdr = qemu_get_be32(f); | |
291 | + s->slr = qemu_get_be32(f); | |
292 | + s->den = qemu_get_be32(f); | |
293 | + s->cr = qemu_get_be32(f); | |
294 | + s->float_high = qemu_get_be32(f); | |
295 | + | |
296 | + return 0; | |
297 | +} | |
298 | + | |
243 | 299 | /* Returns an array of inputs. */ |
244 | 300 | qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) |
245 | 301 | { |
... | ... | @@ -256,7 +312,7 @@ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) |
256 | 312 | if (out) |
257 | 313 | *out = s->out; |
258 | 314 | |
259 | - /* ??? Save/restore. */ | |
315 | + register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s); | |
260 | 316 | return qemu_allocate_irqs(pl061_set_irq, s, 8); |
261 | 317 | } |
262 | 318 | ... | ... |
hw/ssd0303.c
... | ... | @@ -261,6 +261,49 @@ static void ssd0303_invalidate_display(void * opaque) |
261 | 261 | s->redraw = 1; |
262 | 262 | } |
263 | 263 | |
264 | +static void ssd0303_save(QEMUFile *f, void *opaque) | |
265 | +{ | |
266 | + ssd0303_state *s = (ssd0303_state *)opaque; | |
267 | + | |
268 | + qemu_put_be32(f, s->row); | |
269 | + qemu_put_be32(f, s->col); | |
270 | + qemu_put_be32(f, s->start_line); | |
271 | + qemu_put_be32(f, s->mirror); | |
272 | + qemu_put_be32(f, s->flash); | |
273 | + qemu_put_be32(f, s->enabled); | |
274 | + qemu_put_be32(f, s->inverse); | |
275 | + qemu_put_be32(f, s->redraw); | |
276 | + qemu_put_be32(f, s->mode); | |
277 | + qemu_put_be32(f, s->cmd_state); | |
278 | + qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); | |
279 | + | |
280 | + i2c_slave_save(f, &s->i2c); | |
281 | +} | |
282 | + | |
283 | +static int ssd0303_load(QEMUFile *f, void *opaque, int version_id) | |
284 | +{ | |
285 | + ssd0303_state *s = (ssd0303_state *)opaque; | |
286 | + | |
287 | + if (version_id != 1) | |
288 | + return -EINVAL; | |
289 | + | |
290 | + s->row = qemu_get_be32(f); | |
291 | + s->col = qemu_get_be32(f); | |
292 | + s->start_line = qemu_get_be32(f); | |
293 | + s->mirror = qemu_get_be32(f); | |
294 | + s->flash = qemu_get_be32(f); | |
295 | + s->enabled = qemu_get_be32(f); | |
296 | + s->inverse = qemu_get_be32(f); | |
297 | + s->redraw = qemu_get_be32(f); | |
298 | + s->mode = qemu_get_be32(f); | |
299 | + s->cmd_state = qemu_get_be32(f); | |
300 | + qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); | |
301 | + | |
302 | + i2c_slave_load(f, &s->i2c); | |
303 | + | |
304 | + return 0; | |
305 | +} | |
306 | + | |
264 | 307 | void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address) |
265 | 308 | { |
266 | 309 | ssd0303_state *s; |
... | ... | @@ -274,4 +317,5 @@ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address) |
274 | 317 | ssd0303_invalidate_display, |
275 | 318 | NULL, NULL, s); |
276 | 319 | qemu_console_resize(s->console, 96 * MAGNIFY, 16 * MAGNIFY); |
320 | + register_savevm("ssd0303_oled", -1, 1, ssd0303_save, ssd0303_load, s); | |
277 | 321 | } | ... | ... |
hw/ssd0323.c
... | ... | @@ -273,6 +273,53 @@ static void ssd0323_cd(void *opaque, int n, int level) |
273 | 273 | s->mode = level ? SSD0323_DATA : SSD0323_CMD; |
274 | 274 | } |
275 | 275 | |
276 | +static void ssd0323_save(QEMUFile *f, void *opaque) | |
277 | +{ | |
278 | + ssd0323_state *s = (ssd0323_state *)opaque; | |
279 | + int i; | |
280 | + | |
281 | + qemu_put_be32(f, s->cmd_len); | |
282 | + qemu_put_be32(f, s->cmd); | |
283 | + for (i = 0; i < 8; i++) | |
284 | + qemu_put_be32(f, s->cmd_data[i]); | |
285 | + qemu_put_be32(f, s->row); | |
286 | + qemu_put_be32(f, s->row_start); | |
287 | + qemu_put_be32(f, s->row_end); | |
288 | + qemu_put_be32(f, s->col); | |
289 | + qemu_put_be32(f, s->col_start); | |
290 | + qemu_put_be32(f, s->col_end); | |
291 | + qemu_put_be32(f, s->redraw); | |
292 | + qemu_put_be32(f, s->remap); | |
293 | + qemu_put_be32(f, s->mode); | |
294 | + qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); | |
295 | +} | |
296 | + | |
297 | +static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) | |
298 | +{ | |
299 | + ssd0323_state *s = (ssd0323_state *)opaque; | |
300 | + int i; | |
301 | + | |
302 | + if (version_id != 1) | |
303 | + return -EINVAL; | |
304 | + | |
305 | + s->cmd_len = qemu_get_be32(f); | |
306 | + s->cmd = qemu_get_be32(f); | |
307 | + for (i = 0; i < 8; i++) | |
308 | + s->cmd_data[i] = qemu_get_be32(f); | |
309 | + s->row = qemu_get_be32(f); | |
310 | + s->row_start = qemu_get_be32(f); | |
311 | + s->row_end = qemu_get_be32(f); | |
312 | + s->col = qemu_get_be32(f); | |
313 | + s->col_start = qemu_get_be32(f); | |
314 | + s->col_end = qemu_get_be32(f); | |
315 | + s->redraw = qemu_get_be32(f); | |
316 | + s->remap = qemu_get_be32(f); | |
317 | + s->mode = qemu_get_be32(f); | |
318 | + qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); | |
319 | + | |
320 | + return 0; | |
321 | +} | |
322 | + | |
276 | 323 | void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) |
277 | 324 | { |
278 | 325 | ssd0323_state *s; |
... | ... | @@ -290,5 +337,7 @@ void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) |
290 | 337 | cmd = qemu_allocate_irqs(ssd0323_cd, s, 1); |
291 | 338 | *cmd_p = *cmd; |
292 | 339 | |
340 | + register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s); | |
341 | + | |
293 | 342 | return s; |
294 | 343 | } | ... | ... |
hw/ssi-sd.c
... | ... | @@ -190,6 +190,43 @@ int ssi_sd_xfer(void *opaque, int val) |
190 | 190 | return 0xff; |
191 | 191 | } |
192 | 192 | |
193 | +static void ssi_sd_save(QEMUFile *f, void *opaque) | |
194 | +{ | |
195 | + ssi_sd_state *s = (ssi_sd_state *)opaque; | |
196 | + int i; | |
197 | + | |
198 | + qemu_put_be32(f, s->mode); | |
199 | + qemu_put_be32(f, s->cmd); | |
200 | + for (i = 0; i < 4; i++) | |
201 | + qemu_put_be32(f, s->cmdarg[i]); | |
202 | + for (i = 0; i < 5; i++) | |
203 | + qemu_put_be32(f, s->response[i]); | |
204 | + qemu_put_be32(f, s->arglen); | |
205 | + qemu_put_be32(f, s->response_pos); | |
206 | + qemu_put_be32(f, s->stopping); | |
207 | +} | |
208 | + | |
209 | +static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) | |
210 | +{ | |
211 | + ssi_sd_state *s = (ssi_sd_state *)opaque; | |
212 | + int i; | |
213 | + | |
214 | + if (version_id != 1) | |
215 | + return -EINVAL; | |
216 | + | |
217 | + s->mode = qemu_get_be32(f); | |
218 | + s->cmd = qemu_get_be32(f); | |
219 | + for (i = 0; i < 4; i++) | |
220 | + s->cmdarg[i] = qemu_get_be32(f); | |
221 | + for (i = 0; i < 5; i++) | |
222 | + s->response[i] = qemu_get_be32(f); | |
223 | + s->arglen = qemu_get_be32(f); | |
224 | + s->response_pos = qemu_get_be32(f); | |
225 | + s->stopping = qemu_get_be32(f); | |
226 | + | |
227 | + return 0; | |
228 | +} | |
229 | + | |
193 | 230 | void *ssi_sd_init(BlockDriverState *bs) |
194 | 231 | { |
195 | 232 | ssi_sd_state *s; |
... | ... | @@ -197,6 +234,7 @@ void *ssi_sd_init(BlockDriverState *bs) |
197 | 234 | s = (ssi_sd_state *)qemu_mallocz(sizeof(ssi_sd_state)); |
198 | 235 | s->mode = SSI_SD_CMD; |
199 | 236 | s->sd = sd_init(bs, 1); |
237 | + register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); | |
200 | 238 | return s; |
201 | 239 | } |
202 | 240 | ... | ... |
hw/stellaris.c
... | ... | @@ -286,6 +286,65 @@ static CPUWriteMemoryFunc *gptm_writefn[] = { |
286 | 286 | gptm_write |
287 | 287 | }; |
288 | 288 | |
289 | +static void gptm_save(QEMUFile *f, void *opaque) | |
290 | +{ | |
291 | + gptm_state *s = (gptm_state *)opaque; | |
292 | + | |
293 | + qemu_put_be32(f, s->config); | |
294 | + qemu_put_be32(f, s->mode[0]); | |
295 | + qemu_put_be32(f, s->mode[1]); | |
296 | + qemu_put_be32(f, s->control); | |
297 | + qemu_put_be32(f, s->state); | |
298 | + qemu_put_be32(f, s->mask); | |
299 | + qemu_put_be32(f, s->mode[0]); | |
300 | + qemu_put_be32(f, s->mode[0]); | |
301 | + qemu_put_be32(f, s->load[0]); | |
302 | + qemu_put_be32(f, s->load[1]); | |
303 | + qemu_put_be32(f, s->match[0]); | |
304 | + qemu_put_be32(f, s->match[1]); | |
305 | + qemu_put_be32(f, s->prescale[0]); | |
306 | + qemu_put_be32(f, s->prescale[1]); | |
307 | + qemu_put_be32(f, s->match_prescale[0]); | |
308 | + qemu_put_be32(f, s->match_prescale[1]); | |
309 | + qemu_put_be32(f, s->rtc); | |
310 | + qemu_put_be64(f, s->tick[0]); | |
311 | + qemu_put_be64(f, s->tick[1]); | |
312 | + qemu_put_timer(f, s->timer[0]); | |
313 | + qemu_put_timer(f, s->timer[1]); | |
314 | +} | |
315 | + | |
316 | +static int gptm_load(QEMUFile *f, void *opaque, int version_id) | |
317 | +{ | |
318 | + gptm_state *s = (gptm_state *)opaque; | |
319 | + | |
320 | + if (version_id != 1) | |
321 | + return -EINVAL; | |
322 | + | |
323 | + s->config = qemu_get_be32(f); | |
324 | + s->mode[0] = qemu_get_be32(f); | |
325 | + s->mode[1] = qemu_get_be32(f); | |
326 | + s->control = qemu_get_be32(f); | |
327 | + s->state = qemu_get_be32(f); | |
328 | + s->mask = qemu_get_be32(f); | |
329 | + s->mode[0] = qemu_get_be32(f); | |
330 | + s->mode[0] = qemu_get_be32(f); | |
331 | + s->load[0] = qemu_get_be32(f); | |
332 | + s->load[1] = qemu_get_be32(f); | |
333 | + s->match[0] = qemu_get_be32(f); | |
334 | + s->match[1] = qemu_get_be32(f); | |
335 | + s->prescale[0] = qemu_get_be32(f); | |
336 | + s->prescale[1] = qemu_get_be32(f); | |
337 | + s->match_prescale[0] = qemu_get_be32(f); | |
338 | + s->match_prescale[1] = qemu_get_be32(f); | |
339 | + s->rtc = qemu_get_be32(f); | |
340 | + s->tick[0] = qemu_get_be64(f); | |
341 | + s->tick[1] = qemu_get_be64(f); | |
342 | + qemu_get_timer(f, s->timer[0]); | |
343 | + qemu_get_timer(f, s->timer[1]); | |
344 | + | |
345 | + return 0; | |
346 | +} | |
347 | + | |
289 | 348 | static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger) |
290 | 349 | { |
291 | 350 | int iomemtype; |
... | ... | @@ -302,7 +361,7 @@ static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger) |
302 | 361 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
303 | 362 | s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]); |
304 | 363 | s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]); |
305 | - /* ??? Save/restore. */ | |
364 | + register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s); | |
306 | 365 | } |
307 | 366 | |
308 | 367 | |
... | ... | @@ -452,6 +511,11 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) |
452 | 511 | } |
453 | 512 | } |
454 | 513 | |
514 | +static void ssys_calculate_system_clock(ssys_state *s) | |
515 | +{ | |
516 | + system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); | |
517 | +} | |
518 | + | |
455 | 519 | static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) |
456 | 520 | { |
457 | 521 | ssys_state *s = (ssys_state *)opaque; |
... | ... | @@ -484,7 +548,7 @@ static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) |
484 | 548 | s->int_status |= (1 << 6); |
485 | 549 | } |
486 | 550 | s->rcc = value; |
487 | - system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); | |
551 | + ssys_calculate_system_clock(s); | |
488 | 552 | break; |
489 | 553 | case 0x100: /* RCGC0 */ |
490 | 554 | s->rcgc[0] = value; |
... | ... | @@ -548,6 +612,58 @@ static void ssys_reset(void *opaque) |
548 | 612 | s->dcgc[0] = 1; |
549 | 613 | } |
550 | 614 | |
615 | +static void ssys_save(QEMUFile *f, void *opaque) | |
616 | +{ | |
617 | + ssys_state *s = (ssys_state *)opaque; | |
618 | + | |
619 | + qemu_put_be32(f, s->pborctl); | |
620 | + qemu_put_be32(f, s->ldopctl); | |
621 | + qemu_put_be32(f, s->int_mask); | |
622 | + qemu_put_be32(f, s->int_status); | |
623 | + qemu_put_be32(f, s->resc); | |
624 | + qemu_put_be32(f, s->rcc); | |
625 | + qemu_put_be32(f, s->rcgc[0]); | |
626 | + qemu_put_be32(f, s->rcgc[1]); | |
627 | + qemu_put_be32(f, s->rcgc[2]); | |
628 | + qemu_put_be32(f, s->scgc[0]); | |
629 | + qemu_put_be32(f, s->scgc[1]); | |
630 | + qemu_put_be32(f, s->scgc[2]); | |
631 | + qemu_put_be32(f, s->dcgc[0]); | |
632 | + qemu_put_be32(f, s->dcgc[1]); | |
633 | + qemu_put_be32(f, s->dcgc[2]); | |
634 | + qemu_put_be32(f, s->clkvclr); | |
635 | + qemu_put_be32(f, s->ldoarst); | |
636 | +} | |
637 | + | |
638 | +static int ssys_load(QEMUFile *f, void *opaque, int version_id) | |
639 | +{ | |
640 | + ssys_state *s = (ssys_state *)opaque; | |
641 | + | |
642 | + if (version_id != 1) | |
643 | + return -EINVAL; | |
644 | + | |
645 | + s->pborctl = qemu_get_be32(f); | |
646 | + s->ldopctl = qemu_get_be32(f); | |
647 | + s->int_mask = qemu_get_be32(f); | |
648 | + s->int_status = qemu_get_be32(f); | |
649 | + s->resc = qemu_get_be32(f); | |
650 | + s->rcc = qemu_get_be32(f); | |
651 | + s->rcgc[0] = qemu_get_be32(f); | |
652 | + s->rcgc[1] = qemu_get_be32(f); | |
653 | + s->rcgc[2] = qemu_get_be32(f); | |
654 | + s->scgc[0] = qemu_get_be32(f); | |
655 | + s->scgc[1] = qemu_get_be32(f); | |
656 | + s->scgc[2] = qemu_get_be32(f); | |
657 | + s->dcgc[0] = qemu_get_be32(f); | |
658 | + s->dcgc[1] = qemu_get_be32(f); | |
659 | + s->dcgc[2] = qemu_get_be32(f); | |
660 | + s->clkvclr = qemu_get_be32(f); | |
661 | + s->ldoarst = qemu_get_be32(f); | |
662 | + ssys_calculate_system_clock(s); | |
663 | + | |
664 | + return 0; | |
665 | +} | |
666 | + | |
551 | 667 | static void stellaris_sys_init(uint32_t base, qemu_irq irq, |
552 | 668 | stellaris_board_info * board, |
553 | 669 | uint8_t *macaddr) |
... | ... | @@ -567,7 +683,7 @@ static void stellaris_sys_init(uint32_t base, qemu_irq irq, |
567 | 683 | ssys_writefn, s); |
568 | 684 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
569 | 685 | ssys_reset(s); |
570 | - /* ??? Save/restore. */ | |
686 | + register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s); | |
571 | 687 | } |
572 | 688 | |
573 | 689 | |
... | ... | @@ -737,6 +853,37 @@ static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = { |
737 | 853 | stellaris_i2c_write |
738 | 854 | }; |
739 | 855 | |
856 | +static void stellaris_i2c_save(QEMUFile *f, void *opaque) | |
857 | +{ | |
858 | + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; | |
859 | + | |
860 | + qemu_put_be32(f, s->msa); | |
861 | + qemu_put_be32(f, s->mcs); | |
862 | + qemu_put_be32(f, s->mdr); | |
863 | + qemu_put_be32(f, s->mtpr); | |
864 | + qemu_put_be32(f, s->mimr); | |
865 | + qemu_put_be32(f, s->mris); | |
866 | + qemu_put_be32(f, s->mcr); | |
867 | +} | |
868 | + | |
869 | +static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id) | |
870 | +{ | |
871 | + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; | |
872 | + | |
873 | + if (version_id != 1) | |
874 | + return -EINVAL; | |
875 | + | |
876 | + s->msa = qemu_get_be32(f); | |
877 | + s->mcs = qemu_get_be32(f); | |
878 | + s->mdr = qemu_get_be32(f); | |
879 | + s->mtpr = qemu_get_be32(f); | |
880 | + s->mimr = qemu_get_be32(f); | |
881 | + s->mris = qemu_get_be32(f); | |
882 | + s->mcr = qemu_get_be32(f); | |
883 | + | |
884 | + return 0; | |
885 | +} | |
886 | + | |
740 | 887 | static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus) |
741 | 888 | { |
742 | 889 | stellaris_i2c_state *s; |
... | ... | @@ -752,6 +899,8 @@ static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus) |
752 | 899 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
753 | 900 | /* ??? For now we only implement the master interface. */ |
754 | 901 | stellaris_i2c_reset(s); |
902 | + register_savevm("stellaris_i2c", -1, 1, | |
903 | + stellaris_i2c_save, stellaris_i2c_load, s); | |
755 | 904 | } |
756 | 905 | |
757 | 906 | /* Analogue to Digital Converter. This is only partially implemented, |
... | ... | @@ -785,6 +934,7 @@ typedef struct |
785 | 934 | } fifo[4]; |
786 | 935 | uint32_t ssmux[4]; |
787 | 936 | uint32_t ssctl[4]; |
937 | + uint32_t noise; | |
788 | 938 | qemu_irq irq; |
789 | 939 | } stellaris_adc_state; |
790 | 940 | |
... | ... | @@ -833,17 +983,16 @@ static void stellaris_adc_update(stellaris_adc_state *s) |
833 | 983 | static void stellaris_adc_trigger(void *opaque, int irq, int level) |
834 | 984 | { |
835 | 985 | stellaris_adc_state *s = (stellaris_adc_state *)opaque; |
836 | - /* Some applications use the ADC as a random number source, so introduce | |
837 | - some variation into the signal. */ | |
838 | - static uint32_t noise = 0; | |
839 | 986 | |
840 | 987 | if ((s->actss & 1) == 0) { |
841 | 988 | return; |
842 | 989 | } |
843 | 990 | |
844 | - noise = noise * 314159 + 1; | |
991 | + /* Some applications use the ADC as a random number source, so introduce | |
992 | + some variation into the signal. */ | |
993 | + s->noise = s->noise * 314159 + 1; | |
845 | 994 | /* ??? actual inputs not implemented. Return an arbitrary value. */ |
846 | - stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7)); | |
995 | + stellaris_adc_fifo_write(s, 0, 0x200 + ((s->noise >> 16) & 7)); | |
847 | 996 | s->ris |= 1; |
848 | 997 | stellaris_adc_update(s); |
849 | 998 | } |
... | ... | @@ -983,6 +1132,61 @@ static CPUWriteMemoryFunc *stellaris_adc_writefn[] = { |
983 | 1132 | stellaris_adc_write |
984 | 1133 | }; |
985 | 1134 | |
1135 | +static void stellaris_adc_save(QEMUFile *f, void *opaque) | |
1136 | +{ | |
1137 | + stellaris_adc_state *s = (stellaris_adc_state *)opaque; | |
1138 | + int i; | |
1139 | + int j; | |
1140 | + | |
1141 | + qemu_put_be32(f, s->actss); | |
1142 | + qemu_put_be32(f, s->ris); | |
1143 | + qemu_put_be32(f, s->im); | |
1144 | + qemu_put_be32(f, s->emux); | |
1145 | + qemu_put_be32(f, s->ostat); | |
1146 | + qemu_put_be32(f, s->ustat); | |
1147 | + qemu_put_be32(f, s->sspri); | |
1148 | + qemu_put_be32(f, s->sac); | |
1149 | + for (i = 0; i < 4; i++) { | |
1150 | + qemu_put_be32(f, s->fifo[i].state); | |
1151 | + for (j = 0; j < 16; j++) { | |
1152 | + qemu_put_be32(f, s->fifo[i].data[j]); | |
1153 | + } | |
1154 | + qemu_put_be32(f, s->ssmux[i]); | |
1155 | + qemu_put_be32(f, s->ssctl[i]); | |
1156 | + } | |
1157 | + qemu_put_be32(f, s->noise); | |
1158 | +} | |
1159 | + | |
1160 | +static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id) | |
1161 | +{ | |
1162 | + stellaris_adc_state *s = (stellaris_adc_state *)opaque; | |
1163 | + int i; | |
1164 | + int j; | |
1165 | + | |
1166 | + if (version_id != 1) | |
1167 | + return -EINVAL; | |
1168 | + | |
1169 | + s->actss = qemu_get_be32(f); | |
1170 | + s->ris = qemu_get_be32(f); | |
1171 | + s->im = qemu_get_be32(f); | |
1172 | + s->emux = qemu_get_be32(f); | |
1173 | + s->ostat = qemu_get_be32(f); | |
1174 | + s->ustat = qemu_get_be32(f); | |
1175 | + s->sspri = qemu_get_be32(f); | |
1176 | + s->sac = qemu_get_be32(f); | |
1177 | + for (i = 0; i < 4; i++) { | |
1178 | + s->fifo[i].state = qemu_get_be32(f); | |
1179 | + for (j = 0; j < 16; j++) { | |
1180 | + s->fifo[i].data[j] = qemu_get_be32(f); | |
1181 | + } | |
1182 | + s->ssmux[i] = qemu_get_be32(f); | |
1183 | + s->ssctl[i] = qemu_get_be32(f); | |
1184 | + } | |
1185 | + s->noise = qemu_get_be32(f); | |
1186 | + | |
1187 | + return 0; | |
1188 | +} | |
1189 | + | |
986 | 1190 | static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq) |
987 | 1191 | { |
988 | 1192 | stellaris_adc_state *s; |
... | ... | @@ -998,6 +1202,8 @@ static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq) |
998 | 1202 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |
999 | 1203 | stellaris_adc_reset(s); |
1000 | 1204 | qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1); |
1205 | + register_savevm("stellaris_adc", -1, 1, | |
1206 | + stellaris_adc_save, stellaris_adc_load, s); | |
1001 | 1207 | return qi[0]; |
1002 | 1208 | } |
1003 | 1209 | |
... | ... | @@ -1029,6 +1235,25 @@ static int stellaris_ssi_bus_xfer(void *opaque, int val) |
1029 | 1235 | return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val); |
1030 | 1236 | } |
1031 | 1237 | |
1238 | +static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque) | |
1239 | +{ | |
1240 | + stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; | |
1241 | + | |
1242 | + qemu_put_be32(f, s->current_dev); | |
1243 | +} | |
1244 | + | |
1245 | +static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id) | |
1246 | +{ | |
1247 | + stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; | |
1248 | + | |
1249 | + if (version_id != 1) | |
1250 | + return -EINVAL; | |
1251 | + | |
1252 | + s->current_dev = qemu_get_be32(f); | |
1253 | + | |
1254 | + return 0; | |
1255 | +} | |
1256 | + | |
1032 | 1257 | static void *stellaris_ssi_bus_init(qemu_irq *irqp, |
1033 | 1258 | ssi_xfer_cb cb0, void *opaque0, |
1034 | 1259 | ssi_xfer_cb cb1, void *opaque1) |
... | ... | @@ -1043,6 +1268,8 @@ static void *stellaris_ssi_bus_init(qemu_irq *irqp, |
1043 | 1268 | s->opaque[1] = opaque1; |
1044 | 1269 | qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1); |
1045 | 1270 | *irqp = *qi; |
1271 | + register_savevm("stellaris_ssi_bus", -1, 1, | |
1272 | + stellaris_ssi_bus_save, stellaris_ssi_bus_load, s); | |
1046 | 1273 | return s; |
1047 | 1274 | } |
1048 | 1275 | ... | ... |
hw/stellaris_enet.c
... | ... | @@ -326,6 +326,67 @@ static void stellaris_enet_reset(stellaris_enet_state *s) |
326 | 326 | s->tx_frame_len = -1; |
327 | 327 | } |
328 | 328 | |
329 | +static void stellaris_enet_save(QEMUFile *f, void *opaque) | |
330 | +{ | |
331 | + stellaris_enet_state *s = (stellaris_enet_state *)opaque; | |
332 | + int i; | |
333 | + | |
334 | + qemu_put_be32(f, s->ris); | |
335 | + qemu_put_be32(f, s->im); | |
336 | + qemu_put_be32(f, s->rctl); | |
337 | + qemu_put_be32(f, s->tctl); | |
338 | + qemu_put_be32(f, s->thr); | |
339 | + qemu_put_be32(f, s->mctl); | |
340 | + qemu_put_be32(f, s->mdv); | |
341 | + qemu_put_be32(f, s->mtxd); | |
342 | + qemu_put_be32(f, s->mrxd); | |
343 | + qemu_put_be32(f, s->np); | |
344 | + qemu_put_be32(f, s->tx_frame_len); | |
345 | + qemu_put_be32(f, s->tx_fifo_len); | |
346 | + qemu_put_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); | |
347 | + for (i = 0; i < 31; i++) { | |
348 | + qemu_put_be32(f, s->rx[i].len); | |
349 | + qemu_put_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); | |
350 | + | |
351 | + } | |
352 | + qemu_put_be32(f, s->next_packet); | |
353 | + qemu_put_be32(f, s->rx_fifo - s->rx[s->next_packet].data); | |
354 | + qemu_put_be32(f, s->rx_fifo_len); | |
355 | +} | |
356 | + | |
357 | +static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) | |
358 | +{ | |
359 | + stellaris_enet_state *s = (stellaris_enet_state *)opaque; | |
360 | + int i; | |
361 | + | |
362 | + if (version_id != 1) | |
363 | + return -EINVAL; | |
364 | + | |
365 | + s->ris = qemu_get_be32(f); | |
366 | + s->im = qemu_get_be32(f); | |
367 | + s->rctl = qemu_get_be32(f); | |
368 | + s->tctl = qemu_get_be32(f); | |
369 | + s->thr = qemu_get_be32(f); | |
370 | + s->mctl = qemu_get_be32(f); | |
371 | + s->mdv = qemu_get_be32(f); | |
372 | + s->mtxd = qemu_get_be32(f); | |
373 | + s->mrxd = qemu_get_be32(f); | |
374 | + s->np = qemu_get_be32(f); | |
375 | + s->tx_frame_len = qemu_get_be32(f); | |
376 | + s->tx_fifo_len = qemu_get_be32(f); | |
377 | + qemu_get_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); | |
378 | + for (i = 0; i < 31; i++) { | |
379 | + s->rx[i].len = qemu_get_be32(f); | |
380 | + qemu_get_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); | |
381 | + | |
382 | + } | |
383 | + s->next_packet = qemu_get_be32(f); | |
384 | + s->rx_fifo = s->rx[s->next_packet].data + qemu_get_be32(f); | |
385 | + s->rx_fifo_len = qemu_get_be32(f); | |
386 | + | |
387 | + return 0; | |
388 | +} | |
389 | + | |
329 | 390 | void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) |
330 | 391 | { |
331 | 392 | stellaris_enet_state *s; |
... | ... | @@ -344,4 +405,6 @@ void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) |
344 | 405 | stellaris_enet_can_receive, s); |
345 | 406 | |
346 | 407 | stellaris_enet_reset(s); |
408 | + register_savevm("stellaris_enet", -1, 1, | |
409 | + stellaris_enet_save, stellaris_enet_load, s); | |
347 | 410 | } | ... | ... |
hw/stellaris_input.c
... | ... | @@ -47,6 +47,31 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode) |
47 | 47 | s->extension = 0; |
48 | 48 | } |
49 | 49 | |
50 | +static void stellaris_gamepad_save(QEMUFile *f, void *opaque) | |
51 | +{ | |
52 | + gamepad_state *s = (gamepad_state *)opaque; | |
53 | + int i; | |
54 | + | |
55 | + qemu_put_be32(f, s->extension); | |
56 | + for (i = 0; i < s->num_buttons; i++) | |
57 | + qemu_put_byte(f, s->buttons[i].pressed); | |
58 | +} | |
59 | + | |
60 | +static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id) | |
61 | +{ | |
62 | + gamepad_state *s = (gamepad_state *)opaque; | |
63 | + int i; | |
64 | + | |
65 | + if (version_id != 1) | |
66 | + return -EINVAL; | |
67 | + | |
68 | + s->extension = qemu_get_be32(f); | |
69 | + for (i = 0; i < s->num_buttons; i++) | |
70 | + s->buttons[i].pressed = qemu_get_byte(f); | |
71 | + | |
72 | + return 0; | |
73 | +} | |
74 | + | |
50 | 75 | /* Returns an array 5 ouput slots. */ |
51 | 76 | void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) |
52 | 77 | { |
... | ... | @@ -61,6 +86,8 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) |
61 | 86 | } |
62 | 87 | s->num_buttons = n; |
63 | 88 | qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); |
89 | + register_savevm("stellaris_gamepad", -1, 1, | |
90 | + stellaris_gamepad_save, stellaris_gamepad_load, s); | |
64 | 91 | } |
65 | 92 | |
66 | 93 | ... | ... |