149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * QEMU 8253/8254 interval timer emulation
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2003-2004 Fabrice Bellard
549ab747fSPaolo Bonzini *
649ab747fSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
749ab747fSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
849ab747fSPaolo Bonzini * in the Software without restriction, including without limitation the rights
949ab747fSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1049ab747fSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
1149ab747fSPaolo Bonzini * furnished to do so, subject to the following conditions:
1249ab747fSPaolo Bonzini *
1349ab747fSPaolo Bonzini * The above copyright notice and this permission notice shall be included in
1449ab747fSPaolo Bonzini * all copies or substantial portions of the Software.
1549ab747fSPaolo Bonzini *
1649ab747fSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1749ab747fSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1849ab747fSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1949ab747fSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2049ab747fSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2149ab747fSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2249ab747fSPaolo Bonzini * THE SOFTWARE.
2349ab747fSPaolo Bonzini */
240b8fa32fSMarkus Armbruster
25b6a0aa05SPeter Maydell #include "qemu/osdep.h"
2664552b6bSMarkus Armbruster #include "hw/irq.h"
270b8fa32fSMarkus Armbruster #include "qemu/module.h"
2849ab747fSPaolo Bonzini #include "qemu/timer.h"
2949ab747fSPaolo Bonzini #include "hw/timer/i8254.h"
3049ab747fSPaolo Bonzini #include "hw/timer/i8254_internal.h"
31db1015e9SEduardo Habkost #include "qom/object.h"
3249ab747fSPaolo Bonzini
3349ab747fSPaolo Bonzini //#define DEBUG_PIT
3449ab747fSPaolo Bonzini
3549ab747fSPaolo Bonzini #define RW_STATE_LSB 1
3649ab747fSPaolo Bonzini #define RW_STATE_MSB 2
3749ab747fSPaolo Bonzini #define RW_STATE_WORD0 3
3849ab747fSPaolo Bonzini #define RW_STATE_WORD1 4
3949ab747fSPaolo Bonzini
40db1015e9SEduardo Habkost typedef struct PITClass PITClass;
418110fa1dSEduardo Habkost DECLARE_CLASS_CHECKERS(PITClass, PIT,
428110fa1dSEduardo Habkost TYPE_I8254)
43a15d0912SAndreas Färber
44db1015e9SEduardo Habkost struct PITClass {
45a15d0912SAndreas Färber PITCommonClass parent_class;
46a15d0912SAndreas Färber
47a15d0912SAndreas Färber DeviceRealize parent_realize;
48db1015e9SEduardo Habkost };
49a15d0912SAndreas Färber
5049ab747fSPaolo Bonzini static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
5149ab747fSPaolo Bonzini
pit_get_count(PITChannelState * s)5249ab747fSPaolo Bonzini static int pit_get_count(PITChannelState *s)
5349ab747fSPaolo Bonzini {
5449ab747fSPaolo Bonzini uint64_t d;
5549ab747fSPaolo Bonzini int counter;
5649ab747fSPaolo Bonzini
57bc72ad67SAlex Bligh d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ,
5873bcb24dSRutuja Shah NANOSECONDS_PER_SECOND);
5949ab747fSPaolo Bonzini switch(s->mode) {
6049ab747fSPaolo Bonzini case 0:
6149ab747fSPaolo Bonzini case 1:
6249ab747fSPaolo Bonzini case 4:
6349ab747fSPaolo Bonzini case 5:
6449ab747fSPaolo Bonzini counter = (s->count - d) & 0xffff;
6549ab747fSPaolo Bonzini break;
6649ab747fSPaolo Bonzini case 3:
6749ab747fSPaolo Bonzini /* XXX: may be incorrect for odd counts */
6849ab747fSPaolo Bonzini counter = s->count - ((2 * d) % s->count);
6949ab747fSPaolo Bonzini break;
7049ab747fSPaolo Bonzini default:
7149ab747fSPaolo Bonzini counter = s->count - (d % s->count);
7249ab747fSPaolo Bonzini break;
7349ab747fSPaolo Bonzini }
7449ab747fSPaolo Bonzini return counter;
7549ab747fSPaolo Bonzini }
7649ab747fSPaolo Bonzini
7749ab747fSPaolo Bonzini /* val must be 0 or 1 */
pit_set_channel_gate(PITCommonState * s,PITChannelState * sc,int val)7849ab747fSPaolo Bonzini static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc,
7949ab747fSPaolo Bonzini int val)
8049ab747fSPaolo Bonzini {
8149ab747fSPaolo Bonzini switch (sc->mode) {
8249ab747fSPaolo Bonzini default:
8349ab747fSPaolo Bonzini case 0:
8449ab747fSPaolo Bonzini case 4:
8549ab747fSPaolo Bonzini /* XXX: just disable/enable counting */
8649ab747fSPaolo Bonzini break;
8749ab747fSPaolo Bonzini case 1:
8849ab747fSPaolo Bonzini case 5:
8949ab747fSPaolo Bonzini if (sc->gate < val) {
9049ab747fSPaolo Bonzini /* restart counting on rising edge */
91bc72ad67SAlex Bligh sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
9249ab747fSPaolo Bonzini pit_irq_timer_update(sc, sc->count_load_time);
9349ab747fSPaolo Bonzini }
9449ab747fSPaolo Bonzini break;
9549ab747fSPaolo Bonzini case 2:
9649ab747fSPaolo Bonzini case 3:
9749ab747fSPaolo Bonzini if (sc->gate < val) {
9849ab747fSPaolo Bonzini /* restart counting on rising edge */
99bc72ad67SAlex Bligh sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
10049ab747fSPaolo Bonzini pit_irq_timer_update(sc, sc->count_load_time);
10149ab747fSPaolo Bonzini }
10249ab747fSPaolo Bonzini /* XXX: disable/enable counting */
10349ab747fSPaolo Bonzini break;
10449ab747fSPaolo Bonzini }
10549ab747fSPaolo Bonzini sc->gate = val;
10649ab747fSPaolo Bonzini }
10749ab747fSPaolo Bonzini
pit_load_count(PITChannelState * s,int val)10849ab747fSPaolo Bonzini static inline void pit_load_count(PITChannelState *s, int val)
10949ab747fSPaolo Bonzini {
11049ab747fSPaolo Bonzini if (val == 0)
11149ab747fSPaolo Bonzini val = 0x10000;
112bc72ad67SAlex Bligh s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
11349ab747fSPaolo Bonzini s->count = val;
11449ab747fSPaolo Bonzini pit_irq_timer_update(s, s->count_load_time);
11549ab747fSPaolo Bonzini }
11649ab747fSPaolo Bonzini
11749ab747fSPaolo Bonzini /* if already latched, do not latch again */
pit_latch_count(PITChannelState * s)11849ab747fSPaolo Bonzini static void pit_latch_count(PITChannelState *s)
11949ab747fSPaolo Bonzini {
12049ab747fSPaolo Bonzini if (!s->count_latched) {
12149ab747fSPaolo Bonzini s->latched_count = pit_get_count(s);
12249ab747fSPaolo Bonzini s->count_latched = s->rw_mode;
12349ab747fSPaolo Bonzini }
12449ab747fSPaolo Bonzini }
12549ab747fSPaolo Bonzini
pit_ioport_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)12649ab747fSPaolo Bonzini static void pit_ioport_write(void *opaque, hwaddr addr,
12749ab747fSPaolo Bonzini uint64_t val, unsigned size)
12849ab747fSPaolo Bonzini {
12949ab747fSPaolo Bonzini PITCommonState *pit = opaque;
13049ab747fSPaolo Bonzini int channel, access;
13149ab747fSPaolo Bonzini PITChannelState *s;
13249ab747fSPaolo Bonzini
13349ab747fSPaolo Bonzini addr &= 3;
13449ab747fSPaolo Bonzini if (addr == 3) {
13549ab747fSPaolo Bonzini channel = val >> 6;
13649ab747fSPaolo Bonzini if (channel == 3) {
13749ab747fSPaolo Bonzini /* read back command */
13849ab747fSPaolo Bonzini for(channel = 0; channel < 3; channel++) {
13949ab747fSPaolo Bonzini s = &pit->channels[channel];
14049ab747fSPaolo Bonzini if (val & (2 << channel)) {
14149ab747fSPaolo Bonzini if (!(val & 0x20)) {
14249ab747fSPaolo Bonzini pit_latch_count(s);
14349ab747fSPaolo Bonzini }
14449ab747fSPaolo Bonzini if (!(val & 0x10) && !s->status_latched) {
14549ab747fSPaolo Bonzini /* status latch */
14649ab747fSPaolo Bonzini /* XXX: add BCD and null count */
14749ab747fSPaolo Bonzini s->status =
14849ab747fSPaolo Bonzini (pit_get_out(s,
149bc72ad67SAlex Bligh qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) |
15049ab747fSPaolo Bonzini (s->rw_mode << 4) |
15149ab747fSPaolo Bonzini (s->mode << 1) |
15249ab747fSPaolo Bonzini s->bcd;
15349ab747fSPaolo Bonzini s->status_latched = 1;
15449ab747fSPaolo Bonzini }
15549ab747fSPaolo Bonzini }
15649ab747fSPaolo Bonzini }
15749ab747fSPaolo Bonzini } else {
15849ab747fSPaolo Bonzini s = &pit->channels[channel];
15949ab747fSPaolo Bonzini access = (val >> 4) & 3;
16049ab747fSPaolo Bonzini if (access == 0) {
16149ab747fSPaolo Bonzini pit_latch_count(s);
16249ab747fSPaolo Bonzini } else {
16349ab747fSPaolo Bonzini s->rw_mode = access;
16449ab747fSPaolo Bonzini s->read_state = access;
16549ab747fSPaolo Bonzini s->write_state = access;
16649ab747fSPaolo Bonzini
16749ab747fSPaolo Bonzini s->mode = (val >> 1) & 7;
16849ab747fSPaolo Bonzini s->bcd = val & 1;
16949ab747fSPaolo Bonzini /* XXX: update irq timer ? */
17049ab747fSPaolo Bonzini }
17149ab747fSPaolo Bonzini }
17249ab747fSPaolo Bonzini } else {
17349ab747fSPaolo Bonzini s = &pit->channels[addr];
17449ab747fSPaolo Bonzini switch(s->write_state) {
17549ab747fSPaolo Bonzini default:
17649ab747fSPaolo Bonzini case RW_STATE_LSB:
17749ab747fSPaolo Bonzini pit_load_count(s, val);
17849ab747fSPaolo Bonzini break;
17949ab747fSPaolo Bonzini case RW_STATE_MSB:
18049ab747fSPaolo Bonzini pit_load_count(s, val << 8);
18149ab747fSPaolo Bonzini break;
18249ab747fSPaolo Bonzini case RW_STATE_WORD0:
18349ab747fSPaolo Bonzini s->write_latch = val;
18449ab747fSPaolo Bonzini s->write_state = RW_STATE_WORD1;
18549ab747fSPaolo Bonzini break;
18649ab747fSPaolo Bonzini case RW_STATE_WORD1:
18749ab747fSPaolo Bonzini pit_load_count(s, s->write_latch | (val << 8));
18849ab747fSPaolo Bonzini s->write_state = RW_STATE_WORD0;
18949ab747fSPaolo Bonzini break;
19049ab747fSPaolo Bonzini }
19149ab747fSPaolo Bonzini }
19249ab747fSPaolo Bonzini }
19349ab747fSPaolo Bonzini
pit_ioport_read(void * opaque,hwaddr addr,unsigned size)19449ab747fSPaolo Bonzini static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
19549ab747fSPaolo Bonzini unsigned size)
19649ab747fSPaolo Bonzini {
19749ab747fSPaolo Bonzini PITCommonState *pit = opaque;
19849ab747fSPaolo Bonzini int ret, count;
19949ab747fSPaolo Bonzini PITChannelState *s;
20049ab747fSPaolo Bonzini
20149ab747fSPaolo Bonzini addr &= 3;
202d4862a87SPetr Matousek
203d4862a87SPetr Matousek if (addr == 3) {
204d4862a87SPetr Matousek /* Mode/Command register is write only, read is ignored */
205d4862a87SPetr Matousek return 0;
206d4862a87SPetr Matousek }
207d4862a87SPetr Matousek
20849ab747fSPaolo Bonzini s = &pit->channels[addr];
20949ab747fSPaolo Bonzini if (s->status_latched) {
21049ab747fSPaolo Bonzini s->status_latched = 0;
21149ab747fSPaolo Bonzini ret = s->status;
21249ab747fSPaolo Bonzini } else if (s->count_latched) {
21349ab747fSPaolo Bonzini switch(s->count_latched) {
21449ab747fSPaolo Bonzini default:
21549ab747fSPaolo Bonzini case RW_STATE_LSB:
21649ab747fSPaolo Bonzini ret = s->latched_count & 0xff;
21749ab747fSPaolo Bonzini s->count_latched = 0;
21849ab747fSPaolo Bonzini break;
21949ab747fSPaolo Bonzini case RW_STATE_MSB:
22049ab747fSPaolo Bonzini ret = s->latched_count >> 8;
22149ab747fSPaolo Bonzini s->count_latched = 0;
22249ab747fSPaolo Bonzini break;
22349ab747fSPaolo Bonzini case RW_STATE_WORD0:
22449ab747fSPaolo Bonzini ret = s->latched_count & 0xff;
22549ab747fSPaolo Bonzini s->count_latched = RW_STATE_MSB;
22649ab747fSPaolo Bonzini break;
22749ab747fSPaolo Bonzini }
22849ab747fSPaolo Bonzini } else {
22949ab747fSPaolo Bonzini switch(s->read_state) {
23049ab747fSPaolo Bonzini default:
23149ab747fSPaolo Bonzini case RW_STATE_LSB:
23249ab747fSPaolo Bonzini count = pit_get_count(s);
23349ab747fSPaolo Bonzini ret = count & 0xff;
23449ab747fSPaolo Bonzini break;
23549ab747fSPaolo Bonzini case RW_STATE_MSB:
23649ab747fSPaolo Bonzini count = pit_get_count(s);
23749ab747fSPaolo Bonzini ret = (count >> 8) & 0xff;
23849ab747fSPaolo Bonzini break;
23949ab747fSPaolo Bonzini case RW_STATE_WORD0:
24049ab747fSPaolo Bonzini count = pit_get_count(s);
24149ab747fSPaolo Bonzini ret = count & 0xff;
24249ab747fSPaolo Bonzini s->read_state = RW_STATE_WORD1;
24349ab747fSPaolo Bonzini break;
24449ab747fSPaolo Bonzini case RW_STATE_WORD1:
24549ab747fSPaolo Bonzini count = pit_get_count(s);
24649ab747fSPaolo Bonzini ret = (count >> 8) & 0xff;
24749ab747fSPaolo Bonzini s->read_state = RW_STATE_WORD0;
24849ab747fSPaolo Bonzini break;
24949ab747fSPaolo Bonzini }
25049ab747fSPaolo Bonzini }
25149ab747fSPaolo Bonzini return ret;
25249ab747fSPaolo Bonzini }
25349ab747fSPaolo Bonzini
pit_irq_timer_update(PITChannelState * s,int64_t current_time)25449ab747fSPaolo Bonzini static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
25549ab747fSPaolo Bonzini {
25649ab747fSPaolo Bonzini int64_t expire_time;
25749ab747fSPaolo Bonzini int irq_level;
25849ab747fSPaolo Bonzini
25949ab747fSPaolo Bonzini if (!s->irq_timer || s->irq_disabled) {
26049ab747fSPaolo Bonzini return;
26149ab747fSPaolo Bonzini }
26249ab747fSPaolo Bonzini expire_time = pit_get_next_transition_time(s, current_time);
26349ab747fSPaolo Bonzini irq_level = pit_get_out(s, current_time);
26449ab747fSPaolo Bonzini qemu_set_irq(s->irq, irq_level);
26549ab747fSPaolo Bonzini #ifdef DEBUG_PIT
26649ab747fSPaolo Bonzini printf("irq_level=%d next_delay=%f\n",
26749ab747fSPaolo Bonzini irq_level,
26873bcb24dSRutuja Shah (double)(expire_time - current_time) / NANOSECONDS_PER_SECOND);
26949ab747fSPaolo Bonzini #endif
27049ab747fSPaolo Bonzini s->next_transition_time = expire_time;
27149ab747fSPaolo Bonzini if (expire_time != -1)
272bc72ad67SAlex Bligh timer_mod(s->irq_timer, expire_time);
27349ab747fSPaolo Bonzini else
274bc72ad67SAlex Bligh timer_del(s->irq_timer);
27549ab747fSPaolo Bonzini }
27649ab747fSPaolo Bonzini
pit_irq_timer(void * opaque)27749ab747fSPaolo Bonzini static void pit_irq_timer(void *opaque)
27849ab747fSPaolo Bonzini {
27949ab747fSPaolo Bonzini PITChannelState *s = opaque;
28049ab747fSPaolo Bonzini
28149ab747fSPaolo Bonzini pit_irq_timer_update(s, s->next_transition_time);
28249ab747fSPaolo Bonzini }
28349ab747fSPaolo Bonzini
pit_reset(DeviceState * dev)28449ab747fSPaolo Bonzini static void pit_reset(DeviceState *dev)
28549ab747fSPaolo Bonzini {
2863afe7e14SAndreas Färber PITCommonState *pit = PIT_COMMON(dev);
28749ab747fSPaolo Bonzini PITChannelState *s;
28849ab747fSPaolo Bonzini
28949ab747fSPaolo Bonzini pit_reset_common(pit);
29049ab747fSPaolo Bonzini
29149ab747fSPaolo Bonzini s = &pit->channels[0];
29249ab747fSPaolo Bonzini if (!s->irq_disabled) {
293bc72ad67SAlex Bligh timer_mod(s->irq_timer, s->next_transition_time);
29449ab747fSPaolo Bonzini }
29549ab747fSPaolo Bonzini }
29649ab747fSPaolo Bonzini
29749ab747fSPaolo Bonzini /* When HPET is operating in legacy mode, suppress the ignored timer IRQ,
29849ab747fSPaolo Bonzini * reenable it when legacy mode is left again. */
pit_irq_control(void * opaque,int n,int enable)29949ab747fSPaolo Bonzini static void pit_irq_control(void *opaque, int n, int enable)
30049ab747fSPaolo Bonzini {
30149ab747fSPaolo Bonzini PITCommonState *pit = opaque;
30249ab747fSPaolo Bonzini PITChannelState *s = &pit->channels[0];
30349ab747fSPaolo Bonzini
30449ab747fSPaolo Bonzini if (enable) {
30549ab747fSPaolo Bonzini s->irq_disabled = 0;
306bc72ad67SAlex Bligh pit_irq_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
30749ab747fSPaolo Bonzini } else {
30849ab747fSPaolo Bonzini s->irq_disabled = 1;
309bc72ad67SAlex Bligh timer_del(s->irq_timer);
31049ab747fSPaolo Bonzini }
31149ab747fSPaolo Bonzini }
31249ab747fSPaolo Bonzini
31349ab747fSPaolo Bonzini static const MemoryRegionOps pit_ioport_ops = {
31449ab747fSPaolo Bonzini .read = pit_ioport_read,
31549ab747fSPaolo Bonzini .write = pit_ioport_write,
31649ab747fSPaolo Bonzini .impl = {
31749ab747fSPaolo Bonzini .min_access_size = 1,
31849ab747fSPaolo Bonzini .max_access_size = 1,
31949ab747fSPaolo Bonzini },
32049ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
32149ab747fSPaolo Bonzini };
32249ab747fSPaolo Bonzini
pit_post_load(PITCommonState * s)32349ab747fSPaolo Bonzini static void pit_post_load(PITCommonState *s)
32449ab747fSPaolo Bonzini {
32549ab747fSPaolo Bonzini PITChannelState *sc = &s->channels[0];
32649ab747fSPaolo Bonzini
327c963fee4SPavel Dovgalyuk if (sc->next_transition_time != -1 && !sc->irq_disabled) {
328bc72ad67SAlex Bligh timer_mod(sc->irq_timer, sc->next_transition_time);
32949ab747fSPaolo Bonzini } else {
330bc72ad67SAlex Bligh timer_del(sc->irq_timer);
33149ab747fSPaolo Bonzini }
33249ab747fSPaolo Bonzini }
33349ab747fSPaolo Bonzini
pit_realizefn(DeviceState * dev,Error ** errp)334a7737e44SMarkus Armbruster static void pit_realizefn(DeviceState *dev, Error **errp)
33549ab747fSPaolo Bonzini {
336a15d0912SAndreas Färber PITCommonState *pit = PIT_COMMON(dev);
337a15d0912SAndreas Färber PITClass *pc = PIT_GET_CLASS(dev);
33849ab747fSPaolo Bonzini PITChannelState *s;
33949ab747fSPaolo Bonzini
34049ab747fSPaolo Bonzini s = &pit->channels[0];
34149ab747fSPaolo Bonzini /* the timer 0 is connected to an IRQ */
342bc72ad67SAlex Bligh s->irq_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pit_irq_timer, s);
343a15d0912SAndreas Färber qdev_init_gpio_out(dev, &s->irq, 1);
34449ab747fSPaolo Bonzini
345853dca12SPaolo Bonzini memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops,
346853dca12SPaolo Bonzini pit, "pit", 4);
34749ab747fSPaolo Bonzini
348a15d0912SAndreas Färber qdev_init_gpio_in(dev, pit_irq_control, 1);
34949ab747fSPaolo Bonzini
350a7737e44SMarkus Armbruster pc->parent_realize(dev, errp);
35149ab747fSPaolo Bonzini }
35249ab747fSPaolo Bonzini
pit_class_initfn(ObjectClass * klass,void * data)35349ab747fSPaolo Bonzini static void pit_class_initfn(ObjectClass *klass, void *data)
35449ab747fSPaolo Bonzini {
355a15d0912SAndreas Färber PITClass *pc = PIT_CLASS(klass);
35649ab747fSPaolo Bonzini PITCommonClass *k = PIT_COMMON_CLASS(klass);
35749ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass);
35849ab747fSPaolo Bonzini
359bf853881SPhilippe Mathieu-Daudé device_class_set_parent_realize(dc, pit_realizefn, &pc->parent_realize);
36049ab747fSPaolo Bonzini k->set_channel_gate = pit_set_channel_gate;
36149ab747fSPaolo Bonzini k->get_channel_info = pit_get_channel_info_common;
36249ab747fSPaolo Bonzini k->post_load = pit_post_load;
363*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, pit_reset);
36449ab747fSPaolo Bonzini }
36549ab747fSPaolo Bonzini
36649ab747fSPaolo Bonzini static const TypeInfo pit_info = {
3673afe7e14SAndreas Färber .name = TYPE_I8254,
36849ab747fSPaolo Bonzini .parent = TYPE_PIT_COMMON,
36949ab747fSPaolo Bonzini .instance_size = sizeof(PITCommonState),
37049ab747fSPaolo Bonzini .class_init = pit_class_initfn,
371a15d0912SAndreas Färber .class_size = sizeof(PITClass),
37249ab747fSPaolo Bonzini };
37349ab747fSPaolo Bonzini
pit_register_types(void)37449ab747fSPaolo Bonzini static void pit_register_types(void)
37549ab747fSPaolo Bonzini {
37649ab747fSPaolo Bonzini type_register_static(&pit_info);
37749ab747fSPaolo Bonzini }
37849ab747fSPaolo Bonzini
37949ab747fSPaolo Bonzini type_init(pit_register_types)
380