@@ -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,22 +499,66 @@ 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);
+
+ 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);
- pit_reset(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;
}