Commit 4aa5d285 authored by Jan Kiszka's avatar Jan Kiszka Committed by Anthony Liguori
Browse files

i8254: Factor out pit_get_channel_info



Instead of providing 4 individual query functions for mode, gate, output
and initial counter state, introduce a service that queries all
information at once. This comes with tiny additional costs for
pcspk_callback but with a much cleaner interface. Also, it will simplify
the implementation of the KVM in-kernel PIT model.

Signed-off-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent 302fe51b
Loading
Loading
Loading
Loading
+10 −25
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ static int pit_get_count(PITChannelState *s)
}

/* get pit output bit */
static int pit_get_out1(PITChannelState *s, int64_t current_time)
static int pit_get_out(PITChannelState *s, int64_t current_time)
{
    uint64_t d;
    int out;
@@ -122,13 +122,6 @@ static int pit_get_out1(PITChannelState *s, int64_t current_time)
    return out;
}

int pit_get_out(ISADevice *dev, int channel, int64_t current_time)
{
    PITState *pit = DO_UPCAST(PITState, dev, dev);
    PITChannelState *s = &pit->channels[channel];
    return pit_get_out1(s, current_time);
}

/* return -1 if no transition will occur.  */
static int64_t pit_get_next_transition_time(PITChannelState *s,
                                            int64_t current_time)
@@ -215,25 +208,15 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
    s->gate = val;
}

int pit_get_gate(ISADevice *dev, int channel)
{
    PITState *pit = DO_UPCAST(PITState, dev, dev);
    PITChannelState *s = &pit->channels[channel];
    return s->gate;
}

int pit_get_initial_count(ISADevice *dev, int channel)
void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
{
    PITState *pit = DO_UPCAST(PITState, dev, dev);
    PITChannelState *s = &pit->channels[channel];
    return s->count;
}

int pit_get_mode(ISADevice *dev, int channel)
{
    PITState *pit = DO_UPCAST(PITState, dev, dev);
    PITChannelState *s = &pit->channels[channel];
    return s->mode;
    info->gate = s->gate;
    info->mode = s->mode;
    info->initial_count = s->count;
    info->out = pit_get_out(s, qemu_get_clock_ns(vm_clock));
}

static inline void pit_load_count(PITChannelState *s, int val)
@@ -274,7 +257,9 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                    if (!(val & 0x10) && !s->status_latched) {
                        /* status latch */
                        /* XXX: add BCD and null count */
                        s->status =  (pit_get_out1(s, qemu_get_clock_ns(vm_clock)) << 7) |
                        s->status =
                            (pit_get_out(s,
                                         qemu_get_clock_ns(vm_clock)) << 7) |
                            (s->rw_mode << 4) |
                            (s->mode << 1) |
                            s->bcd;
@@ -381,7 +366,7 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
        return;
    }
    expire_time = pit_get_next_transition_time(s, current_time);
    irq_level = pit_get_out1(s, current_time);
    irq_level = pit_get_out(s, current_time);
    qemu_set_irq(s->irq, irq_level);
#ifdef DEBUG_PIT
    printf("irq_level=%d next_delay=%f\n",
+8 −4
Original line number Diff line number Diff line
@@ -30,6 +30,13 @@

#define PIT_FREQ 1193182

typedef struct PITChannelInfo {
    int gate;
    int mode;
    int initial_count;
    int out;
} PITChannelInfo;

static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq,
                                  qemu_irq alt_irq)
{
@@ -45,9 +52,6 @@ static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq,
}

void pit_set_gate(ISADevice *dev, int channel, int val);
int pit_get_gate(ISADevice *dev, int channel);
int pit_get_initial_count(ISADevice *dev, int channel);
int pit_get_mode(ISADevice *dev, int channel);
int pit_get_out(ISADevice *dev, int channel, int64_t current_time);
void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info);

#endif /* !HW_I8254_H */
+11 −5
Original line number Diff line number Diff line
@@ -75,12 +75,16 @@ static inline void generate_samples(PCSpkState *s)
static void pcspk_callback(void *opaque, int free)
{
    PCSpkState *s = opaque;
    PITChannelInfo ch;
    unsigned int n;

    if (pit_get_mode(s->pit, 2) != 3)
    pit_get_channel_info(s->pit, 2, &ch);

    if (ch.mode != 3) {
        return;
    }

    n = pit_get_initial_count(s->pit, 2);
    n = ch.initial_count;
    /* avoid frequencies that are not reproducible with sample rate */
    if (n < PCSPK_MIN_COUNT)
        n = 0;
@@ -121,12 +125,14 @@ static uint64_t pcspk_io_read(void *opaque, target_phys_addr_t addr,
                              unsigned size)
{
    PCSpkState *s = opaque;
    int out;
    PITChannelInfo ch;

    pit_get_channel_info(s->pit, 2, &ch);

    s->dummy_refresh_clock ^= (1 << 4);
    out = pit_get_out(s->pit, 2, qemu_get_clock_ns(vm_clock)) << 5;

    return pit_get_gate(s->pit, 2) | (s->data_on << 1) | s->dummy_refresh_clock | out;
    return ch.gate | (s->data_on << 1) | s->dummy_refresh_clock |
       (ch.out << 5);
}

static void pcspk_io_write(void *opaque, target_phys_addr_t addr, uint64_t val,