mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-10 19:14:58 -06:00
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:
parent
302fe51b59
commit
4aa5d2853a
3 changed files with 30 additions and 35 deletions
35
hw/i8254.c
35
hw/i8254.c
|
@ -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",
|
||||||
|
|
12
hw/i8254.h
12
hw/i8254.h
|
@ -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 */
|
||||||
|
|
18
hw/pcspk.c
18
hw/pcspk.c
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue