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#include "hw/qdev-properties.h"
31#include "sysemu/block-backend.h"
32#include "trace.h"
33#include "qemu/log.h"
34
35
36
37
38
39#define VIA_SIZE (0x2000)
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54#define VIA1A_vSccWrReq 0x80
55
56
57
58
59
60
61
62#define VIA1A_vRev8 0x40
63
64
65
66
67
68
69
70
71
72
73#define VIA1A_vHeadSel 0x20
74
75
76
77
78
79#define VIA1A_vOverlay 0x10
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94#define VIA1A_vSync 0x08
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113#define VIA1A_vVolume 0x07
114#define VIA1A_CPUID0 0x02
115#define VIA1A_CPUID1 0x04
116#define VIA1A_CPUID2 0x10
117#define VIA1A_CPUID3 0x40
118
119
120
121
122
123#define VIA1B_vSound 0x80
124
125
126
127
128
129#define VIA1B_vMystery 0x40
130
131
132
133
134
135#define VIA1B_vADBS2 0x20
136#define VIA1B_vADBS1 0x10
137#define VIA1B_vADBInt 0x08
138#define VIA1B_vRTCEnb 0x04
139#define VIA1B_vRTCClk 0x02
140#define VIA1B_vRTCData 0x01
141
142
143
144
145
146
147
148
149
150
151
152#define VIA2A_vRAM1 0x80
153#define VIA2A_vRAM0 0x40
154#define VIA2A_vIRQE 0x20
155#define VIA2A_vIRQD 0x10
156#define VIA2A_vIRQC 0x08
157#define VIA2A_vIRQB 0x04
158#define VIA2A_vIRQA 0x02
159#define VIA2A_vIRQ9 0x01
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174#define VIA2B_vVBL 0x80
175
176
177
178
179
180#define VIA2B_vSndJck 0x40
181
182
183
184#define VIA2B_vTfr0 0x20
185#define VIA2B_vTfr1 0x10
186#define VIA2B_vMode32 0x08
187
188
189
190
191
192
193
194
195#define VIA2B_vPower 0x04
196
197
198
199#define VIA2B_vBusLk 0x02
200
201
202
203#define VIA2B_vCDis 0x01
204
205
206
207
208
209
210
211#define IRQ_SET 0x80
212
213
214
215#define VIA_IRQ_TIMER1 0x40
216#define VIA_IRQ_TIMER2 0x20
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235#define vBufB 0x0000
236#define vBufAH 0x0200
237#define vDirB 0x0400
238#define vDirA 0x0600
239#define vT1CL 0x0800
240#define vT1CH 0x0a00
241#define vT1LL 0x0c00
242#define vT1LH 0x0e00
243#define vT2CL 0x1000
244#define vT2CH 0x1200
245#define vSR 0x1400
246#define vACR 0x1600
247#define vPCR 0x1800
248
249
250
251
252
253#define vIFR 0x1a00
254#define vIER 0x1c00
255#define vBufA 0x1e00
256
257
258
259
260
261#define VIA1ACR_vShiftCtrl 0x1c
262#define VIA1ACR_vShiftExtClk 0x0c
263#define VIA1ACR_vShiftOut 0x10
264
265
266
267
268
269
270#define ADB_STATE_NEW 0
271#define ADB_STATE_EVEN 1
272#define ADB_STATE_ODD 2
273#define ADB_STATE_IDLE 3
274
275#define VIA1B_vADB_StateMask (VIA1B_vADBS1 | VIA1B_vADBS2)
276#define VIA1B_vADB_StateShift 4
277
278#define VIA_TIMER_FREQ (783360)
279#define VIA_ADB_POLL_FREQ 50
280
281
282#define RTC_OFFSET 2082844800
283
284enum {
285 REG_0,
286 REG_1,
287 REG_2,
288 REG_3,
289 REG_TEST,
290 REG_WPROTECT,
291 REG_PRAM_ADDR,
292 REG_PRAM_ADDR_LAST = REG_PRAM_ADDR + 19,
293 REG_PRAM_SECT,
294 REG_PRAM_SECT_LAST = REG_PRAM_SECT + 7,
295 REG_INVALID,
296 REG_EMPTY = 0xff,
297};
298
299static void via1_VBL_update(MOS6522Q800VIA1State *v1s)
300{
301 MOS6522State *s = MOS6522(v1s);
302
303
304 v1s->next_VBL = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 16630) /
305 16630 * 16630;
306
307 if (s->ier & VIA1_IRQ_VBLANK) {
308 timer_mod(v1s->VBL_timer, v1s->next_VBL);
309 } else {
310 timer_del(v1s->VBL_timer);
311 }
312}
313
314static void via1_one_second_update(MOS6522Q800VIA1State *v1s)
315{
316 MOS6522State *s = MOS6522(v1s);
317
318 v1s->next_second = (qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000) /
319 1000 * 1000;
320 if (s->ier & VIA1_IRQ_ONE_SECOND) {
321 timer_mod(v1s->one_second_timer, v1s->next_second);
322 } else {
323 timer_del(v1s->one_second_timer);
324 }
325}
326
327static void via1_VBL(void *opaque)
328{
329 MOS6522Q800VIA1State *v1s = opaque;
330 MOS6522State *s = MOS6522(v1s);
331 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
332
333 s->ifr |= VIA1_IRQ_VBLANK;
334 mdc->update_irq(s);
335
336 via1_VBL_update(v1s);
337}
338
339static void via1_one_second(void *opaque)
340{
341 MOS6522Q800VIA1State *v1s = opaque;
342 MOS6522State *s = MOS6522(v1s);
343 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
344
345 s->ifr |= VIA1_IRQ_ONE_SECOND;
346 mdc->update_irq(s);
347
348 via1_one_second_update(v1s);
349}
350
351static void via1_irq_request(void *opaque, int irq, int level)
352{
353 MOS6522Q800VIA1State *v1s = opaque;
354 MOS6522State *s = MOS6522(v1s);
355 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
356
357 if (level) {
358 s->ifr |= 1 << irq;
359 } else {
360 s->ifr &= ~(1 << irq);
361 }
362
363 mdc->update_irq(s);
364}
365
366static void via2_irq_request(void *opaque, int irq, int level)
367{
368 MOS6522Q800VIA2State *v2s = opaque;
369 MOS6522State *s = MOS6522(v2s);
370 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
371
372 if (level) {
373 s->ifr |= 1 << irq;
374 } else {
375 s->ifr &= ~(1 << irq);
376 }
377
378 mdc->update_irq(s);
379}
380
381
382static void pram_update(MacVIAState *m)
383{
384 if (m->blk) {
385 if (blk_pwrite(m->blk, 0, m->mos6522_via1.PRAM,
386 sizeof(m->mos6522_via1.PRAM), 0) < 0) {
387 qemu_log("pram_update: cannot write to file\n");
388 }
389 }
390}
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411static int via1_rtc_compact_cmd(uint8_t value)
412{
413 uint8_t read = value & 0x80;
414
415 value &= 0x7f;
416
417
418 if ((value & 0x78) == 0x38) {
419
420 return read | (REG_PRAM_SECT + (value & 0x07));
421 }
422 if ((value & 0x03) == 0x01) {
423 value >>= 2;
424 if ((value & 0x1c) == 0) {
425
426 return read | (REG_0 + (value & 0x03));
427 } else if ((value == 0x0c) && !read) {
428 return REG_TEST;
429 } else if ((value == 0x0d) && !read) {
430 return REG_WPROTECT;
431 } else if ((value & 0x1c) == 0x08) {
432
433 return read | (REG_PRAM_ADDR + 0x10 + (value & 0x03));
434 } else if ((value & 0x43) == 0x41) {
435
436 return read | (REG_PRAM_ADDR + (value & 0x0f));
437 }
438 }
439 return REG_INVALID;
440}
441
442static void via1_rtc_update(MacVIAState *m)
443{
444 MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
445 MOS6522State *s = MOS6522(v1s);
446 int cmd, sector, addr;
447 uint32_t time;
448
449 if (s->b & VIA1B_vRTCEnb) {
450 return;
451 }
452
453 if (s->dirb & VIA1B_vRTCData) {
454
455 if (!(v1s->last_b & VIA1B_vRTCClk) && (s->b & VIA1B_vRTCClk)) {
456 m->data_out <<= 1;
457 m->data_out |= s->b & VIA1B_vRTCData;
458 m->data_out_cnt++;
459 }
460 trace_via1_rtc_update_data_out(m->data_out_cnt, m->data_out);
461 } else {
462 trace_via1_rtc_update_data_in(m->data_in_cnt, m->data_in);
463
464 if ((v1s->last_b & VIA1B_vRTCClk) &&
465 !(s->b & VIA1B_vRTCClk) &&
466 m->data_in_cnt) {
467 s->b = (s->b & ~VIA1B_vRTCData) |
468 ((m->data_in >> 7) & VIA1B_vRTCData);
469 m->data_in <<= 1;
470 m->data_in_cnt--;
471 }
472 return;
473 }
474
475 if (m->data_out_cnt != 8) {
476 return;
477 }
478
479 m->data_out_cnt = 0;
480
481 trace_via1_rtc_internal_status(m->cmd, m->alt, m->data_out);
482
483 if (m->cmd == REG_EMPTY) {
484
485 cmd = via1_rtc_compact_cmd(m->data_out);
486 trace_via1_rtc_internal_cmd(cmd);
487
488 if (cmd == REG_INVALID) {
489 trace_via1_rtc_cmd_invalid(m->data_out);
490 return;
491 }
492
493 if (cmd & 0x80) {
494 switch (cmd & 0x7f) {
495 case REG_0...REG_3:
496
497
498
499
500
501 time = m->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
502 / NANOSECONDS_PER_SECOND);
503 trace_via1_rtc_internal_time(time);
504 m->data_in = (time >> ((cmd & 0x03) << 3)) & 0xff;
505 m->data_in_cnt = 8;
506 trace_via1_rtc_cmd_seconds_read((cmd & 0x7f) - REG_0,
507 m->data_in);
508 break;
509 case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
510
511 m->data_in = v1s->PRAM[(cmd & 0x7f) - REG_PRAM_ADDR];
512 m->data_in_cnt = 8;
513 trace_via1_rtc_cmd_pram_read((cmd & 0x7f) - REG_PRAM_ADDR,
514 m->data_in);
515 break;
516 case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
517
518
519
520
521 trace_via1_rtc_internal_set_cmd(cmd);
522 m->cmd = cmd;
523 break;
524 default:
525 g_assert_not_reached();
526 break;
527 }
528 return;
529 }
530
531
532 if (cmd == REG_WPROTECT || !m->wprotect) {
533 trace_via1_rtc_internal_set_cmd(cmd);
534 m->cmd = cmd;
535 } else {
536 trace_via1_rtc_internal_ignore_cmd(cmd);
537 }
538 return;
539 }
540
541
542 if (m->alt == REG_EMPTY) {
543 switch (m->cmd & 0x7f) {
544 case REG_0...REG_3:
545
546 trace_via1_rtc_cmd_seconds_write(m->cmd - REG_0, m->data_out);
547 m->cmd = REG_EMPTY;
548 break;
549 case REG_TEST:
550
551 trace_via1_rtc_cmd_test_write(m->data_out);
552 m->cmd = REG_EMPTY;
553 break;
554 case REG_WPROTECT:
555
556 trace_via1_rtc_cmd_wprotect_write(m->data_out);
557 m->wprotect = !!(m->data_out & 0x80);
558 m->cmd = REG_EMPTY;
559 break;
560 case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
561
562 trace_via1_rtc_cmd_pram_write(m->cmd - REG_PRAM_ADDR, m->data_out);
563 v1s->PRAM[m->cmd - REG_PRAM_ADDR] = m->data_out;
564 pram_update(m);
565 m->cmd = REG_EMPTY;
566 break;
567 case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
568 addr = (m->data_out >> 2) & 0x1f;
569 sector = (m->cmd & 0x7f) - REG_PRAM_SECT;
570 if (m->cmd & 0x80) {
571
572 m->data_in = v1s->PRAM[sector * 32 + addr];
573 m->data_in_cnt = 8;
574 trace_via1_rtc_cmd_pram_sect_read(sector, addr,
575 sector * 32 + addr,
576 m->data_in);
577 m->cmd = REG_EMPTY;
578 } else {
579
580 trace_via1_rtc_internal_set_alt(addr, sector, addr);
581 m->alt = addr;
582 }
583 break;
584 default:
585 g_assert_not_reached();
586 break;
587 }
588 return;
589 }
590
591
592 g_assert(REG_PRAM_SECT <= m->cmd && m->cmd <= REG_PRAM_SECT_LAST);
593 sector = m->cmd - REG_PRAM_SECT;
594 v1s->PRAM[sector * 32 + m->alt] = m->data_out;
595 pram_update(m);
596 trace_via1_rtc_cmd_pram_sect_write(sector, m->alt, sector * 32 + m->alt,
597 m->data_out);
598 m->alt = REG_EMPTY;
599 m->cmd = REG_EMPTY;
600}
601
602static void adb_via_poll(void *opaque)
603{
604 MacVIAState *m = opaque;
605 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
606 MOS6522State *s = MOS6522(v1s);
607 ADBBusState *adb_bus = &m->adb_bus;
608 uint8_t obuf[9];
609 uint8_t *data = &s->sr;
610 int olen;
611 uint16_t pending;
612
613
614
615
616
617
618 adb_autopoll_block(adb_bus);
619
620 m->adb_data_in_index = 0;
621 m->adb_data_out_index = 0;
622 olen = adb_poll(adb_bus, obuf, adb_bus->autopoll_mask);
623
624 if (olen > 0) {
625
626 *data = obuf[0];
627 olen--;
628 memcpy(m->adb_data_in, &obuf[1], olen);
629 m->adb_data_in_size = olen;
630
631 s->b &= ~VIA1B_vADBInt;
632 qemu_irq_raise(m->adb_data_ready);
633 } else if (olen < 0) {
634
635 *data = 0xff;
636 s->b |= VIA1B_vADBInt;
637 adb_autopoll_unblock(adb_bus);
638 } else {
639 pending = adb_bus->pending & ~(1 << (m->adb_autopoll_cmd >> 4));
640
641 if (pending) {
642
643
644
645
646
647 *data = m->adb_autopoll_cmd;
648 s->b &= ~VIA1B_vADBInt;
649
650 obuf[0] = 0xff;
651 obuf[1] = 0xff;
652 olen = 2;
653
654 memcpy(m->adb_data_in, obuf, olen);
655 m->adb_data_in_size = olen;
656
657 qemu_irq_raise(m->adb_data_ready);
658 } else {
659
660 *data = 0;
661 s->b |= VIA1B_vADBInt;
662 adb_autopoll_unblock(adb_bus);
663 }
664 }
665
666 trace_via1_adb_poll(*data, (s->b & VIA1B_vADBInt) ? "+" : "-",
667 adb_bus->status, m->adb_data_in_index, olen);
668}
669
670static int adb_via_send_len(uint8_t data)
671{
672
673 uint8_t cmd = data & 0xc;
674 uint8_t reg = data & 0x3;
675
676 switch (cmd) {
677 case 0x8:
678
679 switch (reg) {
680 case 2:
681
682 return 3;
683 case 3:
684
685
686
687
688 return 3;
689 default:
690 qemu_log_mask(LOG_UNIMP, "ADB unknown length for register %d\n",
691 reg);
692 return 1;
693 }
694 default:
695
696 return 1;
697 }
698}
699
700static void adb_via_send(MacVIAState *s, int state, uint8_t data)
701{
702 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
703 MOS6522State *ms = MOS6522(v1s);
704 ADBBusState *adb_bus = &s->adb_bus;
705 uint16_t autopoll_mask;
706
707 switch (state) {
708 case ADB_STATE_NEW:
709
710
711
712
713 adb_autopoll_block(adb_bus);
714
715 if (adb_bus->status & ADB_STATUS_POLLREPLY) {
716
717 ms->b &= ~VIA1B_vADBInt;
718 } else {
719 ms->b |= VIA1B_vADBInt;
720 s->adb_data_out_index = 0;
721 s->adb_data_out[s->adb_data_out_index++] = data;
722 }
723
724 trace_via1_adb_send(" NEW", data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
725 qemu_irq_raise(s->adb_data_ready);
726 break;
727
728 case ADB_STATE_EVEN:
729 case ADB_STATE_ODD:
730 ms->b |= VIA1B_vADBInt;
731 s->adb_data_out[s->adb_data_out_index++] = data;
732
733 trace_via1_adb_send(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
734 data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
735 qemu_irq_raise(s->adb_data_ready);
736 break;
737
738 case ADB_STATE_IDLE:
739 return;
740 }
741
742
743 if (s->adb_data_out_index == adb_via_send_len(s->adb_data_out[0])) {
744 s->adb_data_in_size = adb_request(adb_bus, s->adb_data_in,
745 s->adb_data_out,
746 s->adb_data_out_index);
747 s->adb_data_in_index = 0;
748
749 if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
750
751
752
753
754 s->adb_data_in[0] = 0xff;
755 s->adb_data_in[1] = 0xff;
756 s->adb_data_in_size = 2;
757 }
758
759
760
761
762
763 if ((s->adb_data_out[0] & 0xc) == 0xc) {
764 s->adb_autopoll_cmd = s->adb_data_out[0];
765
766 autopoll_mask = 1 << (s->adb_autopoll_cmd >> 4);
767 adb_set_autopoll_mask(adb_bus, autopoll_mask);
768 }
769 }
770}
771
772static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
773{
774 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
775 MOS6522State *ms = MOS6522(v1s);
776 ADBBusState *adb_bus = &s->adb_bus;
777 uint16_t pending;
778
779 switch (state) {
780 case ADB_STATE_NEW:
781 ms->b |= VIA1B_vADBInt;
782 return;
783
784 case ADB_STATE_IDLE:
785
786
787
788
789
790
791 if (s->adb_data_in_index == 0) {
792 if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
793 *data = 0xff;
794 ms->b |= VIA1B_vADBInt;
795 qemu_irq_raise(s->adb_data_ready);
796 } else if (s->adb_data_in_size > 0) {
797 adb_bus->status = ADB_STATUS_POLLREPLY;
798 *data = s->adb_autopoll_cmd;
799 ms->b &= ~VIA1B_vADBInt;
800 qemu_irq_raise(s->adb_data_ready);
801 }
802 } else {
803 ms->b |= VIA1B_vADBInt;
804 adb_autopoll_unblock(adb_bus);
805 }
806
807 trace_via1_adb_receive("IDLE", *data,
808 (ms->b & VIA1B_vADBInt) ? "+" : "-", adb_bus->status,
809 s->adb_data_in_index, s->adb_data_in_size);
810
811 break;
812
813 case ADB_STATE_EVEN:
814 case ADB_STATE_ODD:
815 switch (s->adb_data_in_index) {
816 case 0:
817
818 trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
819 *data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
820 adb_bus->status, s->adb_data_in_index,
821 s->adb_data_in_size);
822
823 *data = s->adb_data_in[s->adb_data_in_index++];
824 if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
825 ms->b &= ~VIA1B_vADBInt;
826 } else {
827 ms->b |= VIA1B_vADBInt;
828 }
829 break;
830
831 case 1:
832
833 trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
834 *data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
835 adb_bus->status, s->adb_data_in_index,
836 s->adb_data_in_size);
837
838 *data = s->adb_data_in[s->adb_data_in_index++];
839 pending = adb_bus->pending & ~(1 << (s->adb_autopoll_cmd >> 4));
840 if (pending) {
841 ms->b &= ~VIA1B_vADBInt;
842 } else {
843 ms->b |= VIA1B_vADBInt;
844 }
845 break;
846
847 default:
848
849
850
851
852
853
854 trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
855 *data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
856 adb_bus->status, s->adb_data_in_index,
857 s->adb_data_in_size);
858
859 if (s->adb_data_in_index < s->adb_data_in_size) {
860
861 *data = s->adb_data_in[s->adb_data_in_index++];
862 ms->b |= VIA1B_vADBInt;
863 } else if (s->adb_data_in_index == s->adb_data_in_size) {
864 if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
865
866 *data = 0xff;
867 } else {
868
869 *data = 0;
870 }
871 s->adb_data_in_index++;
872 ms->b &= ~VIA1B_vADBInt;
873 } else {
874
875 *data = 0xff;
876 ms->b &= ~VIA1B_vADBInt;
877 adb_bus->status = 0;
878 adb_autopoll_unblock(adb_bus);
879 }
880 break;
881 }
882
883 qemu_irq_raise(s->adb_data_ready);
884 break;
885 }
886}
887
888static void via1_adb_update(MacVIAState *m)
889{
890 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
891 MOS6522State *s = MOS6522(v1s);
892 int oldstate, state;
893
894 oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
895 state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
896
897 if (state != oldstate) {
898 if (s->acr & VIA1ACR_vShiftOut) {
899
900 adb_via_send(m, state, s->sr);
901 } else {
902
903 adb_via_receive(m, state, &s->sr);
904 }
905 }
906}
907
908static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
909{
910 MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
911 MOS6522State *ms = MOS6522(s);
912 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
913
914
915
916
917
918
919 if (now >= s->next_VBL) {
920 ms->ifr |= VIA1_IRQ_VBLANK;
921 via1_VBL_update(s);
922 }
923 if (now >= s->next_second) {
924 ms->ifr |= VIA1_IRQ_ONE_SECOND;
925 via1_one_second_update(s);
926 }
927
928 addr = (addr >> 9) & 0xf;
929 return mos6522_read(ms, addr, size);
930}
931
932static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
933 unsigned size)
934{
935 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
936 MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1);
937 MOS6522State *ms = MOS6522(v1s);
938
939 addr = (addr >> 9) & 0xf;
940 mos6522_write(ms, addr, val, size);
941
942 switch (addr) {
943 case VIA_REG_B:
944 via1_rtc_update(m);
945 via1_adb_update(m);
946
947 v1s->last_b = ms->b;
948 break;
949 }
950
951 via1_one_second_update(v1s);
952 via1_VBL_update(v1s);
953}
954
955static const MemoryRegionOps mos6522_q800_via1_ops = {
956 .read = mos6522_q800_via1_read,
957 .write = mos6522_q800_via1_write,
958 .endianness = DEVICE_BIG_ENDIAN,
959 .valid = {
960 .min_access_size = 1,
961 .max_access_size = 1,
962 },
963};
964
965static uint64_t mos6522_q800_via2_read(void *opaque, hwaddr addr, unsigned size)
966{
967 MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque);
968 MOS6522State *ms = MOS6522(s);
969
970 addr = (addr >> 9) & 0xf;
971 return mos6522_read(ms, addr, size);
972}
973
974static void mos6522_q800_via2_write(void *opaque, hwaddr addr, uint64_t val,
975 unsigned size)
976{
977 MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque);
978 MOS6522State *ms = MOS6522(s);
979
980 addr = (addr >> 9) & 0xf;
981 mos6522_write(ms, addr, val, size);
982}
983
984static const MemoryRegionOps mos6522_q800_via2_ops = {
985 .read = mos6522_q800_via2_read,
986 .write = mos6522_q800_via2_write,
987 .endianness = DEVICE_BIG_ENDIAN,
988 .valid = {
989 .min_access_size = 1,
990 .max_access_size = 1,
991 },
992};
993
994static void mac_via_reset(DeviceState *dev)
995{
996 MacVIAState *m = MAC_VIA(dev);
997 MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
998 ADBBusState *adb_bus = &m->adb_bus;
999
1000 adb_set_autopoll_enabled(adb_bus, true);
1001
1002 timer_del(v1s->VBL_timer);
1003 v1s->next_VBL = 0;
1004 timer_del(v1s->one_second_timer);
1005 v1s->next_second = 0;
1006
1007 m->cmd = REG_EMPTY;
1008 m->alt = REG_EMPTY;
1009}
1010
1011static void mac_via_realize(DeviceState *dev, Error **errp)
1012{
1013 MacVIAState *m = MAC_VIA(dev);
1014 MOS6522State *ms;
1015 ADBBusState *adb_bus = &m->adb_bus;
1016 struct tm tm;
1017 int ret;
1018
1019
1020 object_initialize_child(OBJECT(dev), "via1", &m->mos6522_via1,
1021 TYPE_MOS6522_Q800_VIA1);
1022
1023 object_initialize_child(OBJECT(dev), "via2", &m->mos6522_via2,
1024 TYPE_MOS6522_Q800_VIA2);
1025
1026
1027 ms = MOS6522(&m->mos6522_via1);
1028 object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms),
1029 SYSBUS_DEVICE_GPIO_IRQ "[0]");
1030 ms = MOS6522(&m->mos6522_via2);
1031 object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms),
1032 SYSBUS_DEVICE_GPIO_IRQ "[0]");
1033
1034 sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via1), &error_abort);
1035 sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via2), &error_abort);
1036
1037
1038 qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq");
1039 qdev_pass_gpios(DEVICE(&m->mos6522_via2), dev, "via2-irq");
1040
1041
1042 m->mos6522_via1.one_second_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
1043 via1_one_second,
1044 &m->mos6522_via1);
1045 m->mos6522_via1.VBL_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via1_VBL,
1046 &m->mos6522_via1);
1047
1048 qemu_get_timedate(&tm, 0);
1049 m->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
1050
1051 adb_register_autopoll_callback(adb_bus, adb_via_poll, m);
1052 m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
1053 VIA1_IRQ_ADB_READY_BIT);
1054
1055 if (m->blk) {
1056 int64_t len = blk_getlength(m->blk);
1057 if (len < 0) {
1058 error_setg_errno(errp, -len,
1059 "could not get length of backing image");
1060 return;
1061 }
1062 ret = blk_set_perm(m->blk,
1063 BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
1064 BLK_PERM_ALL, errp);
1065 if (ret < 0) {
1066 return;
1067 }
1068
1069 len = blk_pread(m->blk, 0, m->mos6522_via1.PRAM,
1070 sizeof(m->mos6522_via1.PRAM));
1071 if (len != sizeof(m->mos6522_via1.PRAM)) {
1072 error_setg(errp, "can't read PRAM contents");
1073 return;
1074 }
1075 }
1076}
1077
1078static void mac_via_init(Object *obj)
1079{
1080 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1081 MacVIAState *m = MAC_VIA(obj);
1082
1083
1084 memory_region_init(&m->mmio, obj, "mac-via", 2 * VIA_SIZE);
1085 sysbus_init_mmio(sbd, &m->mmio);
1086
1087 memory_region_init_io(&m->via1mem, obj, &mos6522_q800_via1_ops,
1088 &m->mos6522_via1, "via1", VIA_SIZE);
1089 memory_region_add_subregion(&m->mmio, 0x0, &m->via1mem);
1090
1091 memory_region_init_io(&m->via2mem, obj, &mos6522_q800_via2_ops,
1092 &m->mos6522_via2, "via2", VIA_SIZE);
1093 memory_region_add_subregion(&m->mmio, VIA_SIZE, &m->via2mem);
1094
1095
1096 qbus_create_inplace((BusState *)&m->adb_bus, sizeof(m->adb_bus),
1097 TYPE_ADB_BUS, DEVICE(obj), "adb.0");
1098}
1099
1100static void postload_update_cb(void *opaque, int running, RunState state)
1101{
1102 MacVIAState *m = MAC_VIA(opaque);
1103
1104 qemu_del_vm_change_state_handler(m->vmstate);
1105 m->vmstate = NULL;
1106
1107 pram_update(m);
1108}
1109
1110static int mac_via_post_load(void *opaque, int version_id)
1111{
1112 MacVIAState *m = MAC_VIA(opaque);
1113
1114 if (m->blk) {
1115 m->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
1116 m);
1117 }
1118
1119 return 0;
1120}
1121
1122static const VMStateDescription vmstate_mac_via = {
1123 .name = "mac-via",
1124 .version_id = 2,
1125 .minimum_version_id = 2,
1126 .post_load = mac_via_post_load,
1127 .fields = (VMStateField[]) {
1128
1129 VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mos6522,
1130 MOS6522State),
1131 VMSTATE_UINT8(mos6522_via1.last_b, MacVIAState),
1132 VMSTATE_BUFFER(mos6522_via1.PRAM, MacVIAState),
1133 VMSTATE_TIMER_PTR(mos6522_via1.one_second_timer, MacVIAState),
1134 VMSTATE_INT64(mos6522_via1.next_second, MacVIAState),
1135 VMSTATE_TIMER_PTR(mos6522_via1.VBL_timer, MacVIAState),
1136 VMSTATE_INT64(mos6522_via1.next_VBL, MacVIAState),
1137 VMSTATE_STRUCT(mos6522_via2.parent_obj, MacVIAState, 0, vmstate_mos6522,
1138 MOS6522State),
1139
1140 VMSTATE_UINT32(tick_offset, MacVIAState),
1141 VMSTATE_UINT8(data_out, MacVIAState),
1142 VMSTATE_INT32(data_out_cnt, MacVIAState),
1143 VMSTATE_UINT8(data_in, MacVIAState),
1144 VMSTATE_UINT8(data_in_cnt, MacVIAState),
1145 VMSTATE_UINT8(cmd, MacVIAState),
1146 VMSTATE_INT32(wprotect, MacVIAState),
1147 VMSTATE_INT32(alt, MacVIAState),
1148
1149 VMSTATE_INT32(adb_data_in_size, MacVIAState),
1150 VMSTATE_INT32(adb_data_in_index, MacVIAState),
1151 VMSTATE_INT32(adb_data_out_index, MacVIAState),
1152 VMSTATE_BUFFER(adb_data_in, MacVIAState),
1153 VMSTATE_BUFFER(adb_data_out, MacVIAState),
1154 VMSTATE_UINT8(adb_autopoll_cmd, MacVIAState),
1155 VMSTATE_END_OF_LIST()
1156 }
1157};
1158
1159static Property mac_via_properties[] = {
1160 DEFINE_PROP_DRIVE("drive", MacVIAState, blk),
1161 DEFINE_PROP_END_OF_LIST(),
1162};
1163
1164static void mac_via_class_init(ObjectClass *oc, void *data)
1165{
1166 DeviceClass *dc = DEVICE_CLASS(oc);
1167
1168 dc->realize = mac_via_realize;
1169 dc->reset = mac_via_reset;
1170 dc->vmsd = &vmstate_mac_via;
1171 device_class_set_props(dc, mac_via_properties);
1172}
1173
1174static TypeInfo mac_via_info = {
1175 .name = TYPE_MAC_VIA,
1176 .parent = TYPE_SYS_BUS_DEVICE,
1177 .instance_size = sizeof(MacVIAState),
1178 .instance_init = mac_via_init,
1179 .class_init = mac_via_class_init,
1180};
1181
1182
1183static void mos6522_q800_via1_reset(DeviceState *dev)
1184{
1185 MOS6522State *ms = MOS6522(dev);
1186 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
1187
1188 mdc->parent_reset(dev);
1189
1190 ms->timers[0].frequency = VIA_TIMER_FREQ;
1191 ms->timers[1].frequency = VIA_TIMER_FREQ;
1192
1193 ms->b = VIA1B_vADB_StateMask | VIA1B_vADBInt | VIA1B_vRTCEnb;
1194}
1195
1196static void mos6522_q800_via1_init(Object *obj)
1197{
1198 qdev_init_gpio_in_named(DEVICE(obj), via1_irq_request, "via1-irq",
1199 VIA1_IRQ_NB);
1200}
1201
1202static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data)
1203{
1204 DeviceClass *dc = DEVICE_CLASS(oc);
1205
1206 dc->reset = mos6522_q800_via1_reset;
1207}
1208
1209static const TypeInfo mos6522_q800_via1_type_info = {
1210 .name = TYPE_MOS6522_Q800_VIA1,
1211 .parent = TYPE_MOS6522,
1212 .instance_size = sizeof(MOS6522Q800VIA1State),
1213 .instance_init = mos6522_q800_via1_init,
1214 .class_init = mos6522_q800_via1_class_init,
1215};
1216
1217
1218static void mos6522_q800_via2_portB_write(MOS6522State *s)
1219{
1220 if (s->dirb & VIA2B_vPower && (s->b & VIA2B_vPower) == 0) {
1221
1222 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
1223 }
1224}
1225
1226static void mos6522_q800_via2_reset(DeviceState *dev)
1227{
1228 MOS6522State *ms = MOS6522(dev);
1229 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
1230
1231 mdc->parent_reset(dev);
1232
1233 ms->timers[0].frequency = VIA_TIMER_FREQ;
1234 ms->timers[1].frequency = VIA_TIMER_FREQ;
1235
1236 ms->dirb = 0;
1237 ms->b = 0;
1238}
1239
1240static void mos6522_q800_via2_init(Object *obj)
1241{
1242 qdev_init_gpio_in_named(DEVICE(obj), via2_irq_request, "via2-irq",
1243 VIA2_IRQ_NB);
1244}
1245
1246static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data)
1247{
1248 DeviceClass *dc = DEVICE_CLASS(oc);
1249 MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
1250
1251 dc->reset = mos6522_q800_via2_reset;
1252 mdc->portB_write = mos6522_q800_via2_portB_write;
1253}
1254
1255static const TypeInfo mos6522_q800_via2_type_info = {
1256 .name = TYPE_MOS6522_Q800_VIA2,
1257 .parent = TYPE_MOS6522,
1258 .instance_size = sizeof(MOS6522Q800VIA2State),
1259 .instance_init = mos6522_q800_via2_init,
1260 .class_init = mos6522_q800_via2_class_init,
1261};
1262
1263static void mac_via_register_types(void)
1264{
1265 type_register_static(&mos6522_q800_via1_type_info);
1266 type_register_static(&mos6522_q800_via2_type_info);
1267 type_register_static(&mac_via_info);
1268}
1269
1270type_init(mac_via_register_types);
1271