Lines Matching +full:- +full:s
4 * Copyright (c) 2004-2007 Fabrice Bellard
6 * Copyright (c) 2018 Mark Cave-Ayland
30 #include "hw/qdev-properties.h"
34 #include "qapi/type-helpers.h"
49 static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
51 static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
54 static void mos6522_update_irq(MOS6522State *s) in mos6522_update_irq() argument
56 if (s->ifr & s->ier) { in mos6522_update_irq()
57 qemu_irq_raise(s->irq); in mos6522_update_irq()
59 qemu_irq_lower(s->irq); in mos6522_update_irq()
65 MOS6522State *s = MOS6522(opaque); in mos6522_set_irq() local
66 int last_level = !!(s->last_irq_levels & (1 << n)); in mos6522_set_irq()
67 uint8_t last_ifr = s->ifr; in mos6522_set_irq()
74 * are edge-triggered and latched in IFR in mos6522_set_irq()
87 ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; in mos6522_set_irq()
90 s->ifr |= 1 << n; in mos6522_set_irq()
94 ctrl = (s->pcr & CA1_CTRL_MASK) >> CA1_CTRL_SHIFT; in mos6522_set_irq()
97 s->ifr |= 1 << n; in mos6522_set_irq()
101 s->ifr |= 1 << n; in mos6522_set_irq()
104 ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; in mos6522_set_irq()
107 s->ifr |= 1 << n; in mos6522_set_irq()
111 ctrl = (s->pcr & CB1_CTRL_MASK) >> CB1_CTRL_SHIFT; in mos6522_set_irq()
114 s->ifr |= 1 << n; in mos6522_set_irq()
119 if (s->ifr != last_ifr) { in mos6522_set_irq()
120 mos6522_update_irq(s); in mos6522_set_irq()
124 s->last_irq_levels |= 1 << n; in mos6522_set_irq()
126 s->last_irq_levels &= ~(1 << n); in mos6522_set_irq()
130 static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti) in get_counter_value() argument
132 MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); in get_counter_value()
134 if (ti->index == 0) { in get_counter_value()
135 return mdc->get_timer1_counter_value(s, ti); in get_counter_value()
137 return mdc->get_timer2_counter_value(s, ti); in get_counter_value()
141 static uint64_t get_load_time(MOS6522State *s, MOS6522Timer *ti) in get_load_time() argument
143 MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); in get_load_time()
145 if (ti->index == 0) { in get_load_time()
146 return mdc->get_timer1_load_time(s, ti); in get_load_time()
148 return mdc->get_timer2_load_time(s, ti); in get_load_time()
152 static unsigned int get_counter(MOS6522State *s, MOS6522Timer *ti) in get_counter() argument
157 d = get_counter_value(s, ti); in get_counter()
159 if (ti->index == 0) { in get_counter()
160 /* the timer goes down from latch to -1 (period of latch + 2) */ in get_counter()
161 if (d <= (ti->counter_value + 1)) { in get_counter()
162 counter = (ti->counter_value - d) & 0xffff; in get_counter()
164 counter = (d - (ti->counter_value + 1)) % (ti->latch + 2); in get_counter()
165 counter = (ti->latch - counter) & 0xffff; in get_counter()
168 counter = (ti->counter_value - d) & 0xffff; in get_counter()
173 static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val) in set_counter() argument
175 trace_mos6522_set_counter(1 + ti->index, val); in set_counter()
176 ti->load_time = get_load_time(s, ti); in set_counter()
177 ti->counter_value = val; in set_counter()
178 if (ti->index == 0) { in set_counter()
179 mos6522_timer1_update(s, ti, ti->load_time); in set_counter()
181 mos6522_timer2_update(s, ti, ti->load_time); in set_counter()
185 static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti, in get_next_irq_time() argument
191 if (ti->frequency == 0) { in get_next_irq_time()
196 d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time, in get_next_irq_time()
197 ti->frequency, NANOSECONDS_PER_SECOND); in get_next_irq_time()
199 /* the timer goes down from latch to -1 (period of latch + 2) */ in get_next_irq_time()
200 if (d <= (ti->counter_value + 1)) { in get_next_irq_time()
201 counter = (ti->counter_value - d) & 0xffff; in get_next_irq_time()
203 counter = (d - (ti->counter_value + 1)) % (ti->latch + 2); in get_next_irq_time()
204 counter = (ti->latch - counter) & 0xffff; in get_next_irq_time()
209 next_time = d + ti->latch + 1; in get_next_irq_time()
211 next_time = d + ti->latch + 2; in get_next_irq_time()
215 trace_mos6522_get_next_irq_time(ti->latch, d, next_time - d); in get_next_irq_time()
216 next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) + in get_next_irq_time()
217 ti->load_time; in get_next_irq_time()
225 static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti, in mos6522_timer1_update() argument
228 if (!ti->timer) { in mos6522_timer1_update()
231 ti->next_irq_time = get_next_irq_time(s, ti, current_time); in mos6522_timer1_update()
232 if ((s->ier & T1_INT) == 0 || (s->acr & T1MODE) != T1MODE_CONT) { in mos6522_timer1_update()
233 timer_del(ti->timer); in mos6522_timer1_update()
235 timer_mod(ti->timer, ti->next_irq_time); in mos6522_timer1_update()
239 static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti, in mos6522_timer2_update() argument
242 if (!ti->timer) { in mos6522_timer2_update()
245 ti->next_irq_time = get_next_irq_time(s, ti, current_time); in mos6522_timer2_update()
246 if ((s->ier & T2_INT) == 0) { in mos6522_timer2_update()
247 timer_del(ti->timer); in mos6522_timer2_update()
249 timer_mod(ti->timer, ti->next_irq_time); in mos6522_timer2_update()
255 MOS6522State *s = opaque; in mos6522_timer1() local
256 MOS6522Timer *ti = &s->timers[0]; in mos6522_timer1()
258 mos6522_timer1_update(s, ti, ti->next_irq_time); in mos6522_timer1()
259 s->ifr |= T1_INT; in mos6522_timer1()
260 mos6522_update_irq(s); in mos6522_timer1()
265 MOS6522State *s = opaque; in mos6522_timer2() local
266 MOS6522Timer *ti = &s->timers[1]; in mos6522_timer2()
268 mos6522_timer2_update(s, ti, ti->next_irq_time); in mos6522_timer2()
269 s->ifr |= T2_INT; in mos6522_timer2()
270 mos6522_update_irq(s); in mos6522_timer2()
273 static uint64_t mos6522_get_counter_value(MOS6522State *s, MOS6522Timer *ti) in mos6522_get_counter_value() argument
275 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time, in mos6522_get_counter_value()
276 ti->frequency, NANOSECONDS_PER_SECOND); in mos6522_get_counter_value()
279 static uint64_t mos6522_get_load_time(MOS6522State *s, MOS6522Timer *ti) in mos6522_get_load_time() argument
286 static void mos6522_portA_write(MOS6522State *s) in mos6522_portA_write() argument
291 static void mos6522_portB_write(MOS6522State *s) in mos6522_portB_write() argument
298 MOS6522State *s = opaque; in mos6522_read() local
303 if (now >= s->timers[0].next_irq_time) { in mos6522_read()
304 mos6522_timer1_update(s, &s->timers[0], now); in mos6522_read()
305 s->ifr |= T1_INT; in mos6522_read()
307 if (now >= s->timers[1].next_irq_time) { in mos6522_read()
308 mos6522_timer2_update(s, &s->timers[1], now); in mos6522_read()
309 s->ifr |= T2_INT; in mos6522_read()
313 val = s->b; in mos6522_read()
314 ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; in mos6522_read()
316 s->ifr &= ~CB2_INT; in mos6522_read()
318 s->ifr &= ~CB1_INT; in mos6522_read()
319 mos6522_update_irq(s); in mos6522_read()
325 val = s->a; in mos6522_read()
326 ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; in mos6522_read()
328 s->ifr &= ~CA2_INT; in mos6522_read()
330 s->ifr &= ~CA1_INT; in mos6522_read()
331 mos6522_update_irq(s); in mos6522_read()
334 val = s->dirb; in mos6522_read()
337 val = s->dira; in mos6522_read()
340 val = get_counter(s, &s->timers[0]) & 0xff; in mos6522_read()
341 s->ifr &= ~T1_INT; in mos6522_read()
342 mos6522_update_irq(s); in mos6522_read()
345 val = get_counter(s, &s->timers[0]) >> 8; in mos6522_read()
346 mos6522_update_irq(s); in mos6522_read()
349 val = s->timers[0].latch & 0xff; in mos6522_read()
353 val = (s->timers[0].latch >> 8) & 0xff; in mos6522_read()
356 val = get_counter(s, &s->timers[1]) & 0xff; in mos6522_read()
357 s->ifr &= ~T2_INT; in mos6522_read()
358 mos6522_update_irq(s); in mos6522_read()
361 val = get_counter(s, &s->timers[1]) >> 8; in mos6522_read()
364 val = s->sr; in mos6522_read()
365 s->ifr &= ~SR_INT; in mos6522_read()
366 mos6522_update_irq(s); in mos6522_read()
369 val = s->acr; in mos6522_read()
372 val = s->pcr; in mos6522_read()
375 val = s->ifr; in mos6522_read()
376 if (s->ifr & s->ier) { in mos6522_read()
381 val = s->ier | 0x80; in mos6522_read()
396 MOS6522State *s = opaque; in mos6522_write() local
397 MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); in mos6522_write()
404 s->b = (s->b & ~s->dirb) | (val & s->dirb); in mos6522_write()
405 mdc->portB_write(s); in mos6522_write()
406 ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; in mos6522_write()
408 s->ifr &= ~CB2_INT; in mos6522_write()
410 s->ifr &= ~CB1_INT; in mos6522_write()
411 mos6522_update_irq(s); in mos6522_write()
417 s->a = (s->a & ~s->dira) | (val & s->dira); in mos6522_write()
418 mdc->portA_write(s); in mos6522_write()
419 ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; in mos6522_write()
421 s->ifr &= ~CA2_INT; in mos6522_write()
423 s->ifr &= ~CA1_INT; in mos6522_write()
424 mos6522_update_irq(s); in mos6522_write()
427 s->dirb = val; in mos6522_write()
430 s->dira = val; in mos6522_write()
433 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; in mos6522_write()
434 mos6522_timer1_update(s, &s->timers[0], in mos6522_write()
438 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); in mos6522_write()
439 s->ifr &= ~T1_INT; in mos6522_write()
440 set_counter(s, &s->timers[0], s->timers[0].latch); in mos6522_write()
443 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; in mos6522_write()
444 mos6522_timer1_update(s, &s->timers[0], in mos6522_write()
448 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); in mos6522_write()
449 s->ifr &= ~T1_INT; in mos6522_write()
450 mos6522_timer1_update(s, &s->timers[0], in mos6522_write()
454 s->timers[1].latch = (s->timers[1].latch & 0xff00) | val; in mos6522_write()
460 s->timers[1].latch = (s->timers[1].latch & 0xff) | (val << 8); in mos6522_write()
461 s->ifr &= ~T2_INT; in mos6522_write()
462 set_counter(s, &s->timers[1], s->timers[1].latch); in mos6522_write()
465 s->sr = val; in mos6522_write()
468 s->acr = val; in mos6522_write()
469 mos6522_timer1_update(s, &s->timers[0], in mos6522_write()
473 s->pcr = val; in mos6522_write()
477 s->ifr &= ~val; in mos6522_write()
478 mos6522_update_irq(s); in mos6522_write()
483 s->ier |= val & 0x7f; in mos6522_write()
486 s->ier &= ~val; in mos6522_write()
488 mos6522_update_irq(s); in mos6522_write()
490 mos6522_timer1_update(s, &s->timers[0], in mos6522_write()
492 mos6522_timer2_update(s, &s->timers[1], in mos6522_write()
505 MOS6522State *s = MOS6522(obj); in qmp_x_query_via_foreach() local
507 uint16_t t1counter = get_counter(s, &s->timers[0]); in qmp_x_query_via_foreach()
508 uint16_t t2counter = get_counter(s, &s->timers[1]); in qmp_x_query_via_foreach()
510 g_string_append_printf(buf, "%s:\n", object_get_typename(obj)); in qmp_x_query_via_foreach()
513 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
514 mos6522_reg_names[0], s->b); in qmp_x_query_via_foreach()
515 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
516 mos6522_reg_names[1], s->a); in qmp_x_query_via_foreach()
517 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
518 mos6522_reg_names[2], s->dirb); in qmp_x_query_via_foreach()
519 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
520 mos6522_reg_names[3], s->dira); in qmp_x_query_via_foreach()
521 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
523 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
525 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
527 s->timers[0].latch & 0xff); in qmp_x_query_via_foreach()
528 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
530 s->timers[0].latch >> 8); in qmp_x_query_via_foreach()
531 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
533 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
535 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
536 mos6522_reg_names[10], s->sr); in qmp_x_query_via_foreach()
537 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
538 mos6522_reg_names[11], s->acr); in qmp_x_query_via_foreach()
539 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
540 mos6522_reg_names[12], s->pcr); in qmp_x_query_via_foreach()
541 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
542 mos6522_reg_names[13], s->ifr); in qmp_x_query_via_foreach()
543 g_string_append_printf(buf, " %-*s: 0x%x\n", 4, in qmp_x_query_via_foreach()
544 mos6522_reg_names[14], s->ier); in qmp_x_query_via_foreach()
550 " mode=%s" in qmp_x_query_via_foreach()
555 s->timers[0].frequency, in qmp_x_query_via_foreach()
556 ((s->acr & T1MODE) == T1MODE_CONT) ? "continuous" in qmp_x_query_via_foreach()
557 : "one-shot", in qmp_x_query_via_foreach()
559 s->timers[0].latch, in qmp_x_query_via_foreach()
560 s->timers[0].load_time, in qmp_x_query_via_foreach()
561 get_next_irq_time(s, &s->timers[0], now)); in qmp_x_query_via_foreach()
563 " mode=%s" in qmp_x_query_via_foreach()
568 s->timers[1].frequency, in qmp_x_query_via_foreach()
569 "one-shot", in qmp_x_query_via_foreach()
571 s->timers[1].latch, in qmp_x_query_via_foreach()
572 s->timers[1].load_time, in qmp_x_query_via_foreach()
573 get_next_irq_time(s, &s->timers[1], now)); in qmp_x_query_via_foreach()
597 monitor_puts(mon, info->human_readable_text); in hmp_info_via()
647 MOS6522State *s = MOS6522(obj); in mos6522_reset_hold() local
649 s->b = 0; in mos6522_reset_hold()
650 s->a = 0; in mos6522_reset_hold()
651 s->dirb = 0xff; in mos6522_reset_hold()
652 s->dira = 0; in mos6522_reset_hold()
653 s->sr = 0; in mos6522_reset_hold()
654 s->acr = 0; in mos6522_reset_hold()
655 s->pcr = 0; in mos6522_reset_hold()
656 s->ifr = 0; in mos6522_reset_hold()
657 s->ier = 0; in mos6522_reset_hold()
658 /* s->ier = T1_INT | SR_INT; */ in mos6522_reset_hold()
660 s->timers[0].frequency = s->frequency; in mos6522_reset_hold()
661 s->timers[0].latch = 0xffff; in mos6522_reset_hold()
662 set_counter(s, &s->timers[0], 0xffff); in mos6522_reset_hold()
663 timer_del(s->timers[0].timer); in mos6522_reset_hold()
665 s->timers[1].frequency = s->frequency; in mos6522_reset_hold()
666 s->timers[1].latch = 0xffff; in mos6522_reset_hold()
667 timer_del(s->timers[1].timer); in mos6522_reset_hold()
673 MOS6522State *s = MOS6522(obj); in mos6522_init() local
676 memory_region_init_io(&s->mem, obj, &mos6522_ops, s, "mos6522", in mos6522_init()
678 sysbus_init_mmio(sbd, &s->mem); in mos6522_init()
679 sysbus_init_irq(sbd, &s->irq); in mos6522_init()
681 for (i = 0; i < ARRAY_SIZE(s->timers); i++) { in mos6522_init()
682 s->timers[i].index = i; in mos6522_init()
685 s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer1, s); in mos6522_init()
686 s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer2, s); in mos6522_init()
693 MOS6522State *s = MOS6522(obj); in mos6522_finalize() local
695 timer_free(s->timers[0].timer); in mos6522_finalize()
696 timer_free(s->timers[1].timer); in mos6522_finalize()
710 rc->phases.hold = mos6522_reset_hold; in mos6522_class_init()
711 dc->vmsd = &vmstate_mos6522; in mos6522_class_init()
713 mdc->portB_write = mos6522_portB_write; in mos6522_class_init()
714 mdc->portA_write = mos6522_portA_write; in mos6522_class_init()
715 mdc->get_timer1_counter_value = mos6522_get_counter_value; in mos6522_class_init()
716 mdc->get_timer2_counter_value = mos6522_get_counter_value; in mos6522_class_init()
717 mdc->get_timer1_load_time = mos6522_get_load_time; in mos6522_class_init()
718 mdc->get_timer2_load_time = mos6522_get_load_time; in mos6522_class_init()