1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "qemu/osdep.h"
19#include "qemu-common.h"
20#include "migration/vmstate.h"
21#include "hw/sysbus.h"
22#include "hw/irq.h"
23#include "qemu/timer.h"
24#include "hw/misc/mac_via.h"
25#include "hw/misc/mos6522.h"
26#include "hw/input/adb.h"
27#include "sysemu/runstate.h"
28#include "qapi/error.h"
29#include "qemu/cutils.h"
30
31
32
33
34
35
36#define VIA_SIZE (0x2000)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#define VIA1A_vSccWrReq 0x80
52
53
54
55
56
57
58
59#define VIA1A_vRev8 0x40
60
61
62
63
64
65
66
67
68
69
70#define VIA1A_vHeadSel 0x20
71
72
73
74
75
76#define VIA1A_vOverlay 0x10
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91#define VIA1A_vSync 0x08
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110#define VIA1A_vVolume 0x07
111#define VIA1A_CPUID0 0x02
112#define VIA1A_CPUID1 0x04
113#define VIA1A_CPUID2 0x10
114#define VIA1A_CPUID3 0x40
115
116
117
118
119
120#define VIA1B_vSound 0x80
121
122
123
124
125
126#define VIA1B_vMystery 0x40
127
128
129
130
131
132#define VIA1B_vADBS2 0x20
133#define VIA1B_vADBS1 0x10
134#define VIA1B_vADBInt 0x08
135#define VIA1B_vRTCEnb 0x04
136#define VIA1B_vRTCClk 0x02
137#define VIA1B_vRTCData 0x01
138
139
140
141
142
143
144
145
146
147
148
149#define VIA2A_vRAM1 0x80
150#define VIA2A_vRAM0 0x40
151#define VIA2A_vIRQE 0x20
152#define VIA2A_vIRQD 0x10
153#define VIA2A_vIRQC 0x08
154#define VIA2A_vIRQB 0x04
155#define VIA2A_vIRQA 0x02
156#define VIA2A_vIRQ9 0x01
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171#define VIA2B_vVBL 0x80
172
173
174
175
176
177#define VIA2B_vSndJck 0x40
178
179
180
181#define VIA2B_vTfr0 0x20
182#define VIA2B_vTfr1 0x10
183#define VIA2B_vMode32 0x08
184
185
186
187
188
189
190
191
192#define VIA2B_vPower 0x04
193
194
195
196#define VIA2B_vBusLk 0x02
197
198
199
200#define VIA2B_vCDis 0x01
201
202
203
204
205
206
207
208#define IRQ_SET 0x80
209
210
211
212#define VIA_IRQ_TIMER1 0x40
213#define VIA_IRQ_TIMER2 0x20
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232#define vBufB 0x0000
233#define vBufAH 0x0200
234#define vDirB 0x0400
235#define vDirA 0x0600
236#define vT1CL 0x0800
237#define vT1CH 0x0a00
238#define vT1LL 0x0c00
239#define vT1LH 0x0e00
240#define vT2CL 0x1000
241#define vT2CH 0x1200
242#define vSR 0x1400
243#define vACR 0x1600
244#define vPCR 0x1800
245
246
247
248
249
250#define vIFR 0x1a00
251#define vIER 0x1c00
252#define vBufA 0x1e00
253
254
255
256
257
258#define VIA1ACR_vShiftCtrl 0x1c
259#define VIA1ACR_vShiftExtClk 0x0c
260#define VIA1ACR_vShiftOut 0x10
261
262
263
264
265
266
267#define ADB_STATE_NEW 0
268#define ADB_STATE_EVEN 1
269#define ADB_STATE_ODD 2
270#define ADB_STATE_IDLE 3
271
272#define VIA1B_vADB_StateMask (VIA1B_vADBS1 | VIA1B_vADBS2)
273#define VIA1B_vADB_StateShift 4
274
275#define VIA_TIMER_FREQ (783360)
276#define VIA_ADB_POLL_FREQ 50
277
278
279#define RTC_OFFSET 2082844800
280
281static void via1_VBL_update(MOS6522Q800VIA1State *v1s)
282{
283 MOS6522State *s = MOS6522(v1s);
284
285
286 v1s->next_VBL = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 16630) /
287 16630 * 16630;
288
289 if (s->ier & VIA1_IRQ_VBLANK) {
290 timer_mod(v1s->VBL_timer, v1s->next_VBL);
291 } else {
292 timer_del(v1s->VBL_timer);
293 }
294}
295
296static void via1_one_second_update(MOS6522Q800VIA1State *v1s)
297{
298 MOS6522State *s = MOS6522(v1s);
299
300 v1s->next_second = (qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000) /
301 1000 * 1000;
302 if (s->ier & VIA1_IRQ_ONE_SECOND) {
303 timer_mod(v1s->one_second_timer, v1s->next_second);
304 } else {
305 timer_del(v1s->one_second_timer);
306 }
307}
308
309static void via1_VBL(void *opaque)
310{
311 MOS6522Q800VIA1State *v1s = opaque;
312 MOS6522State *s = MOS6522(v1s);
313 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
314
315 s->ifr |= VIA1_IRQ_VBLANK;
316 mdc->update_irq(s);
317
318 via1_VBL_update(v1s);
319}
320
321static void via1_one_second(void *opaque)
322{
323 MOS6522Q800VIA1State *v1s = opaque;
324 MOS6522State *s = MOS6522(v1s);
325 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
326
327 s->ifr |= VIA1_IRQ_ONE_SECOND;
328 mdc->update_irq(s);
329
330 via1_one_second_update(v1s);
331}
332
333static void via1_irq_request(void *opaque, int irq, int level)
334{
335 MOS6522Q800VIA1State *v1s = opaque;
336 MOS6522State *s = MOS6522(v1s);
337 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
338
339 if (level) {
340 s->ifr |= 1 << irq;
341 } else {
342 s->ifr &= ~(1 << irq);
343 }
344
345 mdc->update_irq(s);
346}
347
348static void via2_irq_request(void *opaque, int irq, int level)
349{
350 MOS6522Q800VIA2State *v2s = opaque;
351 MOS6522State *s = MOS6522(v2s);
352 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
353
354 if (level) {
355 s->ifr |= 1 << irq;
356 } else {
357 s->ifr &= ~(1 << irq);
358 }
359
360 mdc->update_irq(s);
361}
362
363static void via1_rtc_update(MacVIAState *m)
364{
365 MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
366 MOS6522State *s = MOS6522(v1s);
367
368 if (s->b & VIA1B_vRTCEnb) {
369 return;
370 }
371
372 if (s->dirb & VIA1B_vRTCData) {
373
374 if (!(v1s->last_b & VIA1B_vRTCClk) && (s->b & VIA1B_vRTCClk)) {
375 m->data_out <<= 1;
376 m->data_out |= s->b & VIA1B_vRTCData;
377 m->data_out_cnt++;
378 }
379 } else {
380
381 if ((v1s->last_b & VIA1B_vRTCClk) &&
382 !(s->b & VIA1B_vRTCClk) &&
383 m->data_in_cnt) {
384 s->b = (s->b & ~VIA1B_vRTCData) |
385 ((m->data_in >> 7) & VIA1B_vRTCData);
386 m->data_in <<= 1;
387 m->data_in_cnt--;
388 }
389 }
390
391 if (m->data_out_cnt == 8) {
392 m->data_out_cnt = 0;
393
394 if (m->cmd == 0) {
395 if (m->data_out & 0x80) {
396
397 uint32_t time = m->tick_offset +
398 (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
399 NANOSECONDS_PER_SECOND);
400 if (m->data_out == 0x81) {
401 m->data_in = time & 0xff;
402 m->data_in_cnt = 8;
403 } else if (m->data_out == 0x85) {
404 m->data_in = (time >> 8) & 0xff;
405 m->data_in_cnt = 8;
406 } else if (m->data_out == 0x89) {
407 m->data_in = (time >> 16) & 0xff;
408 m->data_in_cnt = 8;
409 } else if (m->data_out == 0x8d) {
410 m->data_in = (time >> 24) & 0xff;
411 m->data_in_cnt = 8;
412 } else if ((m->data_out & 0xf3) == 0xa1) {
413
414 int addr = (m->data_out >> 2) & 0x03;
415 m->data_in = v1s->PRAM[addr];
416 m->data_in_cnt = 8;
417 } else if ((m->data_out & 0xf3) == 0xa1) {
418
419 int addr = (m->data_out >> 2) & 0x0f;
420 m->data_in = v1s->PRAM[addr];
421 m->data_in_cnt = 8;
422 } else if ((m->data_out & 0xf8) == 0xb8) {
423
424 m->cmd = m->data_out;
425 }
426 } else {
427
428 m->cmd = m->data_out;
429 }
430 } else {
431 if (m->cmd & 0x80) {
432 if ((m->cmd & 0xf8) == 0xb8) {
433
434 int sector = m->cmd & 0x07;
435 int addr = (m->data_out >> 2) & 0x1f;
436
437 m->data_in = v1s->PRAM[sector * 8 + addr];
438 m->data_in_cnt = 8;
439 }
440 } else if (!m->wprotect) {
441
442 if (m->alt != 0) {
443
444 int sector = m->cmd & 0x07;
445 int addr = (m->alt >> 2) & 0x1f;
446
447 v1s->PRAM[sector * 8 + addr] = m->data_out;
448
449 m->alt = 0;
450 } else if (m->cmd == 0x01) {
451
452 } else if (m->cmd == 0x05) {
453
454 } else if (m->cmd == 0x09) {
455
456 } else if (m->cmd == 0x0d) {
457
458 } else if (m->cmd == 0x31) {
459
460 } else if (m->cmd == 0x35) {
461
462 m->wprotect = m->data_out & 1;
463 } else if ((m->cmd & 0xf3) == 0xa1) {
464
465 int addr = (m->cmd >> 2) & 0x03;
466 v1s->PRAM[addr] = m->data_out;
467 } else if ((m->cmd & 0xf3) == 0xa1) {
468
469 int addr = (m->cmd >> 2) & 0x0f;
470 v1s->PRAM[addr] = m->data_out;
471 } else if ((m->cmd & 0xf8) == 0xb8) {
472
473 m->alt = m->cmd;
474 }
475 }
476 }
477 m->data_out = 0;
478 }
479}
480
481static int adb_via_poll(MacVIAState *s, int state, uint8_t *data)
482{
483 if (state != ADB_STATE_IDLE) {
484 return 0;
485 }
486
487 if (s->adb_data_in_size < s->adb_data_in_index) {
488 return 0;
489 }
490
491 if (s->adb_data_out_index != 0) {
492 return 0;
493 }
494
495 s->adb_data_in_index = 0;
496 s->adb_data_out_index = 0;
497 s->adb_data_in_size = adb_poll(&s->adb_bus, s->adb_data_in, 0xffff);
498
499 if (s->adb_data_in_size) {
500 *data = s->adb_data_in[s->adb_data_in_index++];
501 qemu_irq_raise(s->adb_data_ready);
502 }
503
504 return s->adb_data_in_size;
505}
506
507static int adb_via_send(MacVIAState *s, int state, uint8_t data)
508{
509 switch (state) {
510 case ADB_STATE_NEW:
511 s->adb_data_out_index = 0;
512 break;
513 case ADB_STATE_EVEN:
514 if ((s->adb_data_out_index & 1) == 0) {
515 return 0;
516 }
517 break;
518 case ADB_STATE_ODD:
519 if (s->adb_data_out_index & 1) {
520 return 0;
521 }
522 break;
523 case ADB_STATE_IDLE:
524 return 0;
525 }
526
527 assert(s->adb_data_out_index < sizeof(s->adb_data_out) - 1);
528
529 s->adb_data_out[s->adb_data_out_index++] = data;
530 qemu_irq_raise(s->adb_data_ready);
531 return 1;
532}
533
534static int adb_via_receive(MacVIAState *s, int state, uint8_t *data)
535{
536 switch (state) {
537 case ADB_STATE_NEW:
538 return 0;
539
540 case ADB_STATE_EVEN:
541 if (s->adb_data_in_size <= 0) {
542 qemu_irq_raise(s->adb_data_ready);
543 return 0;
544 }
545
546 if (s->adb_data_in_index >= s->adb_data_in_size) {
547 *data = 0;
548 qemu_irq_raise(s->adb_data_ready);
549 return 1;
550 }
551
552 if ((s->adb_data_in_index & 1) == 0) {
553 return 0;
554 }
555
556 break;
557
558 case ADB_STATE_ODD:
559 if (s->adb_data_in_size <= 0) {
560 qemu_irq_raise(s->adb_data_ready);
561 return 0;
562 }
563
564 if (s->adb_data_in_index >= s->adb_data_in_size) {
565 *data = 0;
566 qemu_irq_raise(s->adb_data_ready);
567 return 1;
568 }
569
570 if (s->adb_data_in_index & 1) {
571 return 0;
572 }
573
574 break;
575
576 case ADB_STATE_IDLE:
577 if (s->adb_data_out_index == 0) {
578 return 0;
579 }
580
581 s->adb_data_in_size = adb_request(&s->adb_bus, s->adb_data_in,
582 s->adb_data_out,
583 s->adb_data_out_index);
584 s->adb_data_out_index = 0;
585 s->adb_data_in_index = 0;
586 if (s->adb_data_in_size < 0) {
587 *data = 0xff;
588 qemu_irq_raise(s->adb_data_ready);
589 return -1;
590 }
591
592 if (s->adb_data_in_size == 0) {
593 return 0;
594 }
595
596 break;
597 }
598
599 assert(s->adb_data_in_index < sizeof(s->adb_data_in) - 1);
600
601 *data = s->adb_data_in[s->adb_data_in_index++];
602 qemu_irq_raise(s->adb_data_ready);
603 if (*data == 0xff || *data == 0) {
604 return 0;
605 }
606 return 1;
607}
608
609static void via1_adb_update(MacVIAState *m)
610{
611 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
612 MOS6522State *s = MOS6522(v1s);
613 int state;
614 int ret;
615
616 state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
617
618 if (s->acr & VIA1ACR_vShiftOut) {
619
620 ret = adb_via_send(m, state, s->sr);
621 if (ret > 0) {
622 s->b &= ~VIA1B_vADBInt;
623 } else {
624 s->b |= VIA1B_vADBInt;
625 }
626 } else {
627
628 ret = adb_via_receive(m, state, &s->sr);
629 if (ret > 0 && s->sr != 0xff) {
630 s->b &= ~VIA1B_vADBInt;
631 } else {
632 s->b |= VIA1B_vADBInt;
633 }
634 }
635}
636
637static void via_adb_poll(void *opaque)
638{
639 MacVIAState *m = opaque;
640 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
641 MOS6522State *s = MOS6522(v1s);
642 int state;
643
644 if (s->b & VIA1B_vADBInt) {
645 state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
646 if (adb_via_poll(m, state, &s->sr)) {
647 s->b &= ~VIA1B_vADBInt;
648 }
649 }
650
651 timer_mod(m->adb_poll_timer,
652 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
653 (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ));
654}
655
656static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
657{
658 MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
659 MOS6522State *ms = MOS6522(s);
660 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
661
662
663
664
665
666
667 if (now >= s->next_VBL) {
668 ms->ifr |= VIA1_IRQ_VBLANK;
669 via1_VBL_update(s);
670 }
671 if (now >= s->next_second) {
672 ms->ifr |= VIA1_IRQ_ONE_SECOND;
673 via1_one_second_update(s);
674 }
675
676 addr = (addr >> 9) & 0xf;
677 return mos6522_read(ms, addr, size);
678}
679
680static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
681 unsigned size)
682{
683 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
684 MOS6522State *ms = MOS6522(v1s);
685
686 addr = (addr >> 9) & 0xf;
687 mos6522_write(ms, addr, val, size);
688
689 via1_one_second_update(v1s);
690 via1_VBL_update(v1s);
691}
692
693static const MemoryRegionOps mos6522_q800_via1_ops = {
694 .read = mos6522_q800_via1_read,
695 .write = mos6522_q800_via1_write,
696 .endianness = DEVICE_BIG_ENDIAN,
697 .valid = {
698 .min_access_size = 1,
699 .max_access_size = 1,
700 },
701};
702
703static uint64_t mos6522_q800_via2_read(void *opaque, hwaddr addr, unsigned size)
704{
705 MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque);
706 MOS6522State *ms = MOS6522(s);
707
708 addr = (addr >> 9) & 0xf;
709 return mos6522_read(ms, addr, size);
710}
711
712static void mos6522_q800_via2_write(void *opaque, hwaddr addr, uint64_t val,
713 unsigned size)
714{
715 MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque);
716 MOS6522State *ms = MOS6522(s);
717
718 addr = (addr >> 9) & 0xf;
719 mos6522_write(ms, addr, val, size);
720}
721
722static const MemoryRegionOps mos6522_q800_via2_ops = {
723 .read = mos6522_q800_via2_read,
724 .write = mos6522_q800_via2_write,
725 .endianness = DEVICE_BIG_ENDIAN,
726 .valid = {
727 .min_access_size = 1,
728 .max_access_size = 1,
729 },
730};
731
732static void mac_via_reset(DeviceState *dev)
733{
734 MacVIAState *m = MAC_VIA(dev);
735 MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
736
737 timer_mod(m->adb_poll_timer,
738 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
739 (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ));
740
741 timer_del(v1s->VBL_timer);
742 v1s->next_VBL = 0;
743 timer_del(v1s->one_second_timer);
744 v1s->next_second = 0;
745}
746
747static void mac_via_realize(DeviceState *dev, Error **errp)
748{
749 MacVIAState *m = MAC_VIA(dev);
750 MOS6522State *ms;
751 struct tm tm;
752
753
754 sysbus_init_child_obj(OBJECT(dev), "via1", &m->mos6522_via1,
755 sizeof(m->mos6522_via1), TYPE_MOS6522_Q800_VIA1);
756
757 sysbus_init_child_obj(OBJECT(dev), "via2", &m->mos6522_via2,
758 sizeof(m->mos6522_via2), TYPE_MOS6522_Q800_VIA2);
759
760
761 ms = MOS6522(&m->mos6522_via1);
762 object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms),
763 SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort);
764 ms = MOS6522(&m->mos6522_via2);
765 object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms),
766 SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort);
767
768
769 qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq");
770 qdev_pass_gpios(DEVICE(&m->mos6522_via2), dev, "via2-irq");
771
772
773 m->mos6522_via1.one_second_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
774 via1_one_second,
775 &m->mos6522_via1);
776 m->mos6522_via1.VBL_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via1_VBL,
777 &m->mos6522_via1);
778
779 qemu_get_timedate(&tm, 0);
780 m->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
781
782 m->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via_adb_poll, m);
783 m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
784 VIA1_IRQ_ADB_READY_BIT);
785}
786
787static void mac_via_init(Object *obj)
788{
789 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
790 MacVIAState *m = MAC_VIA(obj);
791
792
793 memory_region_init(&m->mmio, obj, "mac-via", 2 * VIA_SIZE);
794 sysbus_init_mmio(sbd, &m->mmio);
795
796 memory_region_init_io(&m->via1mem, obj, &mos6522_q800_via1_ops,
797 &m->mos6522_via1, "via1", VIA_SIZE);
798 memory_region_add_subregion(&m->mmio, 0x0, &m->via1mem);
799
800 memory_region_init_io(&m->via2mem, obj, &mos6522_q800_via2_ops,
801 &m->mos6522_via2, "via2", VIA_SIZE);
802 memory_region_add_subregion(&m->mmio, VIA_SIZE, &m->via2mem);
803
804
805 qbus_create_inplace((BusState *)&m->adb_bus, sizeof(m->adb_bus),
806 TYPE_ADB_BUS, DEVICE(obj), "adb.0");
807}
808
809static const VMStateDescription vmstate_mac_via = {
810 .name = "mac-via",
811 .version_id = 1,
812 .minimum_version_id = 1,
813 .fields = (VMStateField[]) {
814
815 VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mos6522,
816 MOS6522State),
817 VMSTATE_UINT8(mos6522_via1.last_b, MacVIAState),
818 VMSTATE_BUFFER(mos6522_via1.PRAM, MacVIAState),
819 VMSTATE_TIMER_PTR(mos6522_via1.one_second_timer, MacVIAState),
820 VMSTATE_INT64(mos6522_via1.next_second, MacVIAState),
821 VMSTATE_TIMER_PTR(mos6522_via1.VBL_timer, MacVIAState),
822 VMSTATE_INT64(mos6522_via1.next_VBL, MacVIAState),
823 VMSTATE_STRUCT(mos6522_via2.parent_obj, MacVIAState, 0, vmstate_mos6522,
824 MOS6522State),
825
826 VMSTATE_UINT32(tick_offset, MacVIAState),
827 VMSTATE_UINT8(data_out, MacVIAState),
828 VMSTATE_INT32(data_out_cnt, MacVIAState),
829 VMSTATE_UINT8(data_in, MacVIAState),
830 VMSTATE_UINT8(data_in_cnt, MacVIAState),
831 VMSTATE_UINT8(cmd, MacVIAState),
832 VMSTATE_INT32(wprotect, MacVIAState),
833 VMSTATE_INT32(alt, MacVIAState),
834
835 VMSTATE_TIMER_PTR(adb_poll_timer, MacVIAState),
836 VMSTATE_INT32(adb_data_in_size, MacVIAState),
837 VMSTATE_INT32(adb_data_in_index, MacVIAState),
838 VMSTATE_INT32(adb_data_out_index, MacVIAState),
839 VMSTATE_BUFFER(adb_data_in, MacVIAState),
840 VMSTATE_BUFFER(adb_data_out, MacVIAState),
841 VMSTATE_END_OF_LIST()
842 }
843};
844
845static void mac_via_class_init(ObjectClass *oc, void *data)
846{
847 DeviceClass *dc = DEVICE_CLASS(oc);
848
849 dc->realize = mac_via_realize;
850 dc->reset = mac_via_reset;
851 dc->vmsd = &vmstate_mac_via;
852}
853
854static TypeInfo mac_via_info = {
855 .name = TYPE_MAC_VIA,
856 .parent = TYPE_SYS_BUS_DEVICE,
857 .instance_size = sizeof(MacVIAState),
858 .instance_init = mac_via_init,
859 .class_init = mac_via_class_init,
860};
861
862
863static void mos6522_q800_via1_portB_write(MOS6522State *s)
864{
865 MOS6522Q800VIA1State *v1s = container_of(s, MOS6522Q800VIA1State,
866 parent_obj);
867 MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1);
868
869 via1_rtc_update(m);
870 via1_adb_update(m);
871
872 v1s->last_b = s->b;
873}
874
875static void mos6522_q800_via1_reset(DeviceState *dev)
876{
877 MOS6522State *ms = MOS6522(dev);
878 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
879
880 mdc->parent_reset(dev);
881
882 ms->timers[0].frequency = VIA_TIMER_FREQ;
883 ms->timers[1].frequency = VIA_TIMER_FREQ;
884
885 ms->b = VIA1B_vADB_StateMask | VIA1B_vADBInt | VIA1B_vRTCEnb;
886}
887
888static void mos6522_q800_via1_init(Object *obj)
889{
890 qdev_init_gpio_in_named(DEVICE(obj), via1_irq_request, "via1-irq",
891 VIA1_IRQ_NB);
892}
893
894static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data)
895{
896 DeviceClass *dc = DEVICE_CLASS(oc);
897 MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
898
899 dc->reset = mos6522_q800_via1_reset;
900 mdc->portB_write = mos6522_q800_via1_portB_write;
901}
902
903static const TypeInfo mos6522_q800_via1_type_info = {
904 .name = TYPE_MOS6522_Q800_VIA1,
905 .parent = TYPE_MOS6522,
906 .instance_size = sizeof(MOS6522Q800VIA1State),
907 .instance_init = mos6522_q800_via1_init,
908 .class_init = mos6522_q800_via1_class_init,
909};
910
911
912static void mos6522_q800_via2_portB_write(MOS6522State *s)
913{
914 if (s->dirb & VIA2B_vPower && (s->b & VIA2B_vPower) == 0) {
915
916 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
917 }
918}
919
920static void mos6522_q800_via2_reset(DeviceState *dev)
921{
922 MOS6522State *ms = MOS6522(dev);
923 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
924
925 mdc->parent_reset(dev);
926
927 ms->timers[0].frequency = VIA_TIMER_FREQ;
928 ms->timers[1].frequency = VIA_TIMER_FREQ;
929
930 ms->dirb = 0;
931 ms->b = 0;
932}
933
934static void mos6522_q800_via2_init(Object *obj)
935{
936 qdev_init_gpio_in_named(DEVICE(obj), via2_irq_request, "via2-irq",
937 VIA2_IRQ_NB);
938}
939
940static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data)
941{
942 DeviceClass *dc = DEVICE_CLASS(oc);
943 MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
944
945 dc->reset = mos6522_q800_via2_reset;
946 mdc->portB_write = mos6522_q800_via2_portB_write;
947}
948
949static const TypeInfo mos6522_q800_via2_type_info = {
950 .name = TYPE_MOS6522_Q800_VIA2,
951 .parent = TYPE_MOS6522,
952 .instance_size = sizeof(MOS6522Q800VIA2State),
953 .instance_init = mos6522_q800_via2_init,
954 .class_init = mos6522_q800_via2_class_init,
955};
956
957static void mac_via_register_types(void)
958{
959 type_register_static(&mos6522_q800_via1_type_info);
960 type_register_static(&mos6522_q800_via2_type_info);
961 type_register_static(&mac_via_info);
962}
963
964type_init(mac_via_register_types);
965