Signed-off-by: TAKEDA, toshiya <t-tak...@m1.interq.or.jp> --- hw/i8254.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/hw/i8254.c b/hw/i8254.c index faaa884..155f879 100644 --- a/hw/i8254.c +++ b/hw/i8254.c @@ -47,6 +47,7 @@ typedef struct PITChannelState { uint8_t bcd; /* not supported */ uint8_t gate; /* timer start */ int64_t count_load_time; + uint64_t frequency; /* irq handling */ int64_t next_transition_time; QEMUTimer *irq_timer; @@ -66,7 +67,7 @@ static int pit_get_count(PITChannelState *s) uint64_t d; int counter; - d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, + d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, s->frequency, get_ticks_per_sec()); switch(s->mode) { case 0: @@ -92,7 +93,7 @@ static int pit_get_out1(PITChannelState *s, int64_t current_time) uint64_t d; int out; - d = muldiv64(current_time - s->count_load_time, PIT_FREQ, + d = muldiv64(current_time - s->count_load_time, s->frequency, get_ticks_per_sec()); switch(s->mode) { default: @@ -132,7 +133,7 @@ static int64_t pit_get_next_transition_time(PITChannelState *s, uint64_t d, next_time, base; int period2; - d = muldiv64(current_time - s->count_load_time, PIT_FREQ, + d = muldiv64(current_time - s->count_load_time, s->frequency, get_ticks_per_sec()); switch(s->mode) { default: @@ -170,7 +171,7 @@ static int64_t pit_get_next_transition_time(PITChannelState *s, } /* convert to timer units */ next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(), - PIT_FREQ); + s->frequency); /* fix potential rounding problems */ /* XXX: better solution: use a clock at PIT_FREQ Hz */ if (next_time <= current_time) @@ -498,20 +499,64 @@ void hpet_pit_enable(void) pit_load_count(s, 0); } -PITState *pit_init(int base, qemu_irq irq) +static void pit_init_common(PITState *pit, int base, qemu_irq irq, + uint64_t frequency) { - PITState *pit = &pit_state; PITChannelState *s; + int i; s = &pit->channels[0]; /* the timer 0 is connected to an IRQ */ s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s); s->irq = irq; + for (i = 0; i < 3; i++) { + pit->channels[i].frequency = frequency; + } + vmstate_register(base, &vmstate_pit, pit); qemu_register_reset(pit_reset, pit); +} + +PITState *pit_init(int base, qemu_irq irq) +{ + PITState *pit = &pit_state; + + pit_init_common(pit, base, irq, PIT_FREQ); + register_ioport_write(base, 4, 1, pit_ioport_write, pit); register_ioport_read(base, 3, 1, pit_ioport_read, pit); return pit; } + +/* NEC PC-9821 */ + +static void pc98_pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + pit_ioport_write(opaque, addr >> 1, val); +} + +static uint32_t pc98_pit_ioport_read(void *opaque, uint32_t addr) +{ + return pit_ioport_read(opaque, addr >> 1); +} + +PITState *pc98_pit_init(qemu_irq irq) +{ + PITState *pit = &pit_state; + int i; + + pit_init_common(pit, 0, irq, PC98_PIT_FREQ); + + for (i = 0; i < 4; i++) { + register_ioport_write(0x71 + (i << 1), 1, 1, pc98_pit_ioport_write, pit); + register_ioport_write(0x3fd9 + (i << 1), 1, 1, pc98_pit_ioport_write, pit); + } + for (i = 0; i < 3; i++) { + register_ioport_read(0x71 + (i << 1), 1, 1, pc98_pit_ioport_read, pit); + register_ioport_read(0x3fd9 + (i << 1), 1, 1, pc98_pit_ioport_read, pit); + } + + return pit; +} -- 1.6.4