Revision 8caa0065 hw/hpet.c

b/hw/hpet.c
39 39
#define DPRINTF(...)
40 40
#endif
41 41

  
42
#define HPET_MSI_SUPPORT        0
43

  
42 44
struct HPETState;
43 45
typedef struct HPETTimer {  /* timers */
44 46
    uint8_t tn;             /*timer number*/
......
47 49
    /* Memory-mapped, software visible timer registers */
48 50
    uint64_t config;        /* configuration/cap */
49 51
    uint64_t cmp;           /* comparator */
50
    uint64_t fsb;           /* FSB route, not supported now */
52
    uint64_t fsb;           /* FSB route */
51 53
    /* Hidden register state */
52 54
    uint64_t period;        /* Last value written to comparator */
53 55
    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
......
59 61
    SysBusDevice busdev;
60 62
    uint64_t hpet_offset;
61 63
    qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
64
    uint32_t flags;
62 65
    uint8_t rtc_irq_level;
63 66
    uint8_t num_timers;
64 67
    HPETTimer timer[HPET_MAX_TIMERS];
......
80 83
    return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
81 84
}
82 85

  
86
static uint32_t timer_fsb_route(HPETTimer *t)
87
{
88
    return t->config & HPET_TN_FSB_ENABLE;
89
}
90

  
83 91
static uint32_t hpet_enabled(HPETState *s)
84 92
{
85 93
    return s->config & HPET_CFG_ENABLE;
......
179 187
    mask = 1 << timer->tn;
180 188
    if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
181 189
        s->isr &= ~mask;
182
        qemu_irq_lower(s->irqs[route]);
190
        if (!timer_fsb_route(timer)) {
191
            qemu_irq_lower(s->irqs[route]);
192
        }
193
    } else if (timer_fsb_route(timer)) {
194
        stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
183 195
    } else if (timer->config & HPET_TN_TYPE_LEVEL) {
184 196
        s->isr |= mask;
185 197
        qemu_irq_raise(s->irqs[route]);
......
216 228
    /* Push number of timers into capability returned via HPET_ID */
217 229
    s->capability &= ~HPET_ID_NUM_TIM_MASK;
218 230
    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
231

  
232
    /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
233
    s->flags &= ~(1 << HPET_MSI_SUPPORT);
234
    if (s->timer[0].config & HPET_TN_FSB_CAP) {
235
        s->flags |= 1 << HPET_MSI_SUPPORT;
236
    }
219 237
    return 0;
220 238
}
221 239

  
......
361 379
        case HPET_TN_CMP + 4:
362 380
            return timer->cmp >> 32;
363 381
        case HPET_TN_ROUTE:
382
            return timer->fsb;
383
        case HPET_TN_ROUTE + 4:
364 384
            return timer->fsb >> 32;
365 385
        default:
366 386
            DPRINTF("qemu: invalid hpet_ram_readl\n");
......
444 464
        switch ((addr - 0x100) % 0x20) {
445 465
        case HPET_TN_CFG:
446 466
            DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
467
            if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
468
                update_irq(timer, 0);
469
            }
447 470
            val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
448 471
            timer->config = (timer->config & 0xffffffff00000000ULL) | val;
449 472
            if (new_val & HPET_TN_32BIT) {
......
501 524
                    hpet_set_timer(timer);
502 525
                }
503 526
                break;
527
        case HPET_TN_ROUTE:
528
            timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
529
            break;
504 530
        case HPET_TN_ROUTE + 4:
505
            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
531
            timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
506 532
            break;
507 533
        default:
508 534
            DPRINTF("qemu: invalid hpet_ram_writel\n");
......
610 636

  
611 637
        hpet_del_timer(timer);
612 638
        timer->cmp = ~0ULL;
613
        timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
639
        timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
640
        if (s->flags & (1 << HPET_MSI_SUPPORT)) {
641
            timer->config |= HPET_TN_FSB_CAP;
642
        }
614 643
        /* advertise availability of ioapic inti2 */
615 644
        timer->config |=  0x00000004ULL << 32;
616 645
        timer->period = 0ULL;
......
686 715
    .init         = hpet_init,
687 716
    .qdev.props = (Property[]) {
688 717
        DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
718
        DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
689 719
        DEFINE_PROP_END_OF_LIST(),
690 720
    },
691 721
};

Also available in: Unified diff