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: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Jan Kiszka 2012-02-01 20:31:43 +01:00 committed by Anthony Liguori
parent 302fe51b59
commit 4aa5d2853a
3 changed files with 30 additions and 35 deletions

View file

@ -90,7 +90,7 @@ static int pit_get_count(PITChannelState *s)
} }
/* get pit output bit */ /* 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; uint64_t d;
int out; int out;
@ -122,13 +122,6 @@ static int pit_get_out1(PITChannelState *s, int64_t current_time)
return out; 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. */ /* return -1 if no transition will occur. */
static int64_t pit_get_next_transition_time(PITChannelState *s, static int64_t pit_get_next_transition_time(PITChannelState *s,
int64_t current_time) int64_t current_time)
@ -215,25 +208,15 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
s->gate = val; s->gate = val;
} }
int pit_get_gate(ISADevice *dev, int channel) void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
{ {
PITState *pit = DO_UPCAST(PITState, dev, dev); PITState *pit = DO_UPCAST(PITState, dev, dev);
PITChannelState *s = &pit->channels[channel]; PITChannelState *s = &pit->channels[channel];
return s->gate;
}
int pit_get_initial_count(ISADevice *dev, int channel) info->gate = s->gate;
{ info->mode = s->mode;
PITState *pit = DO_UPCAST(PITState, dev, dev); info->initial_count = s->count;
PITChannelState *s = &pit->channels[channel]; info->out = pit_get_out(s, qemu_get_clock_ns(vm_clock));
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;
} }
static inline void pit_load_count(PITChannelState *s, int val) 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) { if (!(val & 0x10) && !s->status_latched) {
/* status latch */ /* status latch */
/* XXX: add BCD and null count */ /* 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->rw_mode << 4) |
(s->mode << 1) | (s->mode << 1) |
s->bcd; s->bcd;
@ -381,7 +366,7 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
return; return;
} }
expire_time = pit_get_next_transition_time(s, current_time); 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); qemu_set_irq(s->irq, irq_level);
#ifdef DEBUG_PIT #ifdef DEBUG_PIT
printf("irq_level=%d next_delay=%f\n", printf("irq_level=%d next_delay=%f\n",

View file

@ -30,6 +30,13 @@
#define PIT_FREQ 1193182 #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, static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq,
qemu_irq alt_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); void pit_set_gate(ISADevice *dev, int channel, int val);
int pit_get_gate(ISADevice *dev, int channel); void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info);
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);
#endif /* !HW_I8254_H */ #endif /* !HW_I8254_H */

View file

@ -75,12 +75,16 @@ static inline void generate_samples(PCSpkState *s)
static void pcspk_callback(void *opaque, int free) static void pcspk_callback(void *opaque, int free)
{ {
PCSpkState *s = opaque; PCSpkState *s = opaque;
PITChannelInfo ch;
unsigned int n; unsigned int n;
if (pit_get_mode(s->pit, 2) != 3) pit_get_channel_info(s->pit, 2, &ch);
return;
n = pit_get_initial_count(s->pit, 2); if (ch.mode != 3) {
return;
}
n = ch.initial_count;
/* avoid frequencies that are not reproducible with sample rate */ /* avoid frequencies that are not reproducible with sample rate */
if (n < PCSPK_MIN_COUNT) if (n < PCSPK_MIN_COUNT)
n = 0; n = 0;
@ -121,12 +125,14 @@ static uint64_t pcspk_io_read(void *opaque, target_phys_addr_t addr,
unsigned size) unsigned size)
{ {
PCSpkState *s = opaque; PCSpkState *s = opaque;
int out; PITChannelInfo ch;
pit_get_channel_info(s->pit, 2, &ch);
s->dummy_refresh_clock ^= (1 << 4); 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, static void pcspk_io_write(void *opaque, target_phys_addr_t addr, uint64_t val,