pit, hpet, pcspk: fixes & preparation for KVM
v4 cover pit, hpet, pcspk: fixes & preparation for KVM
Changes in V4:
- rebased over qom-upstream.13
- comment on rtc_irq_level clearing on reset
- fix call to isa_register_ioport by passing the pcspk device
Not changed:
- PIT pointer property of pcspk
(Paolo will port it together with other PROP_PTR users)
Jan Kiszka (7):
i8254: Do not raise IRQ level on reset
hpet: Save/restore cached RTC IRQ level
i8254: Factor out interface header
i8254: Pass alternative IRQ output object on initialization
i8254: Rework & fix interaction with HPET in legacy mode
pcspk: Convert to qdev
i8254: Factor out pit_get_channel_info
arch_init.c | 1 + hw/alpha_dp264.c | 3 +- hw/hpet.c | 68 ++++++++++++++++++++++++++++---------- hw/hpet_emul.h | 3 ++ hw/i82378.c | 6 ++- hw/i8254.c | 92 ++++++++++++++++++++++----------------------------- hw/i8254.h | 57 ++++++++++++++++++++++++++++++++ hw/mips_fulong2e.c | 3 +- hw/mips_jazz.c | 6 ++- hw/mips_malta.c | 3 +- hw/mips_r4k.c | 3 +- hw/pc.c | 19 ++++++++-- hw/pc.h | 29 ---------------- hw/pcspk.c | 84 +++++++++++++++++++++++++++++++++++++++-------- hw/pcspk.h | 45 +++++++++++++++++++++++++ 15 files changed, 296 insertions(+), 126 deletions(-) create mode 100644 hw/i8254.h create mode 100644 hw/pcspk.h
Signature · 1 line
1.7.3.4
PATCH v4 1/7 i8254: Do not raise IRQ level on reset
Avoid changing the IRQ level to high on reset as it may trigger spurious events. Instead, open-code the effects of pit_load_count(0) in the reset handler.
--- hw/i8254.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
hw/i8254.c +7 -1
@@ -481,7 +481,13 @@ static void pit_reset(DeviceState *dev) s = &pit->channels[i]; s->mode =3 ; s->gate = (i !=2 ); -pit_load_count (s,0 ); + s->count_load_time =qemu_get_clock_ns (vm_clock); + s->count =0x10000 ; +if (i ==0 ) { + s->next_transition_time = +pit_get_next_transition_time (s, s->count_load_time); +qemu_mod_timer (s->irq_timer, s->next_transition_time); + } } }
Signature · 1 line
1.7.3.4
PATCH v4 2/7 hpet: Save/restore cached RTC IRQ level
In reply to Jan KiszkaIn legacy mode, the HPET suppresses the RTC interrupt delivery via IRQ 8 but keeps track of the RTC output level and applies it when legacy mode is turned off again. This value has to be preserved across save/ restore as it cannot be reconstructed otherwise.
To document that a raised rtc_irq_level won't survive a vmload without a hpet/rtc_irq_level subsection, add an explicit clearing to the reset handler.
--- hw/hpet.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
hw/hpet.c +29 -0
@@ -240,6 +240,24 @@ static int hpet_post_load(void *opaque, int version_id)return 0 ; } +static bool hpet_rtc_irq_level_needed (void *opaque) +{ +HPETState *s = opaque; + +return s->rtc_irq_level !=0 ; +} + +static const VMStateDescription vmstate_hpet_rtc_irq_level = { + .name ="hpet/rtc_irq_level" , + .version_id =1 , + .minimum_version_id =1 , + .minimum_version_id_old =1 , + .fields = (VMStateField []) { +VMSTATE_UINT8 (rtc_irq_level, HPETState), +VMSTATE_END_OF_LIST () + } +}; +static const VMStateDescription vmstate_hpet_timer = { .name ="hpet_timer" , .version_id =1 ,
@@ -273,6 +291,14 @@ static const VMStateDescription vmstate_hpet = { VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0, vmstate_hpet_timer, HPETTimer),VMSTATE_END_OF_LIST () + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_hpet_rtc_irq_level, + .needed = hpet_rtc_irq_level_needed, + }, { +/* empty */ + } } };
@@ -636,6 +662,9 @@ static void hpet_reset(DeviceState *d) hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t )s->capability; hpet_cfg.hpet[s->hpet_id].address =sysbus_from_qdev (d)->mmio[0 ].addr; count =1 ; + +/* to document that the RTC lowers its output on reset as well */ + s->rtc_irq_level =0 ; }static void hpet_handle_rtc_irq (void *opaque,int n,int level)
Signature · 1 line
1.7.3.4
PATCH v4 3/7 i8254: Factor out interface header
In reply to Jan KiszkaMove the public interface of the PIT into its own header file and update all users.
--- hw/alpha_dp264.c | 1 + hw/hpet.c | 1 + hw/i82378.c | 1 + hw/i8254.c | 1 + hw/i8254.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/mips_fulong2e.c | 1 + hw/mips_jazz.c | 1 + hw/mips_malta.c | 1 + hw/mips_r4k.c | 1 + hw/pc.c | 1 + hw/pc.h | 25 ------------------------ hw/pcspk.c | 1 + 12 files changed, 64 insertions(+), 25 deletions(-) create mode 100644 hw/i8254.h
hw/alpha_dp264.c +1 -0
@@ -14,6 +14,7 @@#include "sysemu.h" #include "mc146818rtc.h" #include "ide.h" +#include "i8254.h" #define MAX_IDE_BUS 2
hw/hpet.c +1 -0
@@ -31,6 +31,7 @@#include "hpet_emul.h" #include "sysbus.h" #include "mc146818rtc.h" +#include "i8254.h" //#define HPET_DEBUG #ifdef HPET_DEBUG
hw/i82378.c +1 -0
@@ -19,6 +19,7 @@#include "pci.h" #include "pc.h" +#include "i8254.h" //#define DEBUG_I82378
hw/i8254.c +1 -0
@@ -25,6 +25,7 @@#include "pc.h" #include "isa.h" #include "qemu-timer.h" +#include "i8254.h" //#define DEBUG_PIT
hw/i8254.h new file +54 -0
54 lines not on this page · raw message
hw/mips_fulong2e.c +1 -0
@@ -40,6 +40,7 @@#include "elf.h" #include "vt82c686.h" #include "mc146818rtc.h" +#include "i8254.h" #include "blockdev.h" #include "exec-memory.h"
hw/mips_jazz.c +1 -0
@@ -36,6 +36,7 @@#include "mips-bios.h" #include "loader.h" #include "mc146818rtc.h" +#include "i8254.h" #include "blockdev.h" #include "sysbus.h" #include "exec-memory.h"
hw/mips_malta.c +1 -0
@@ -45,6 +45,7 @@#include "loader.h" #include "elf.h" #include "mc146818rtc.h" +#include "i8254.h" #include "blockdev.h" #include "exec-memory.h" #include "sysbus.h" /* SysBusDevice */
hw/mips_r4k.c +1 -0
@@ -22,6 +22,7 @@#include "loader.h" #include "elf.h" #include "mc146818rtc.h" +#include "i8254.h" #include "blockdev.h" #include "exec-memory.h"
hw/pc.c +1 -0
@@ -36,6 +36,7 @@#include "elf.h" #include "multiboot.h" #include "mc146818rtc.h" +#include "i8254.h" #include "msi.h" #include "sysbus.h" #include "sysemu.h"
hw/pc.h +0 -25
@@ -81,31 +81,6 @@ typedef struct GSIState {void gsi_handler (void *opaque,int n,int level); -/* i8254.c */ - -#define PIT_FREQ 1193182 - -static inline ISADevice *pit_init (ISABus *bus,int base,int irq) -{ -ISADevice *dev; - - dev =isa_create (bus,"isa-pit" ); -qdev_prop_set_uint32 (&dev->qdev,"iobase" , base); -qdev_prop_set_uint32 (&dev->qdev,"irq" , irq); -qdev_init_nofail (&dev->qdev); - -return dev; -} - -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 hpet_pit_disable (void ); -void hpet_pit_enable (void ); -/* vmport.c */ static inline void vmport_init (ISABus *bus) {
hw/pcspk.c +1 -0
@@ -27,6 +27,7 @@#include "isa.h" #include "audio/audio.h" #include "qemu-timer.h" +#include "i8254.h" #define PCSPK_BUF_LEN 1792#define PCSPK_SAMPLE_RATE 32000
Signature · 1 line
1.7.3.4
PATCH v4 4/7 i8254: Pass alternative IRQ output object on initialization
In reply to Jan KiszkaHPET legacy emulation will require control over the PIT IRQ output. To enable this, add support for an alternative IRQ output object to the PIT factory function. If the isa_irq number is < 0, this object will be used.
This also removes the IRQ number property from the PIT class as we now use a generic GPIO output pin that is connected by the factory function.
--- hw/alpha_dp264.c | 2 +- hw/i82378.c | 2 +- hw/i8254.c | 4 +--- hw/i8254.h | 6 ++++-- hw/mips_fulong2e.c | 2 +- hw/mips_jazz.c | 2 +- hw/mips_malta.c | 2 +- hw/mips_r4k.c | 2 +- hw/pc.c | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-)
hw/alpha_dp264.c +1 -1
@@ -73,7 +73,7 @@ static void clipper_init(ram_addr_t ram_size, clipper_pci_map_irq);rtc_init (isa_bus,1980 , rtc_irq); -pit_init (isa_bus,0x40 ,0 ); +pit_init (isa_bus,0x40 ,0 ,NULL );isa_create_simple (isa_bus,"i8042" );/* VGA setup. Don't bother loading the bios. */
hw/i82378.c +1 -1
@@ -192,7 +192,7 @@ static void i82378_init(DeviceState *dev, I82378State *s)isa_bus_irqs (isabus, s->i8259);/* 1 82C54 (pit) */ - pit =pit_init (isabus,0x40 ,0 ); + pit =pit_init (isabus,0x40 ,0 ,NULL );/* speaker */ pcspk_init (pit);
hw/i8254.c +1 -3
@@ -57,7 +57,6 @@ typedef struct PITChannelState {typedef struct PITState {ISADevice dev;MemoryRegion ioports; -uint32_t irq;uint32_t iobase;PITChannelState channels[3 ]; }PITState ;
@@ -532,7 +531,7 @@ static int pit_initfn(ISADevice *dev) s = &pit->channels[0 ];/* the timer 0 is connected to an IRQ */ s->irq_timer =qemu_new_timer_ns (vm_clock, pit_irq_timer, s); - s->irq =isa_get_irq (dev, pit->irq); +qdev_init_gpio_out (&dev->qdev, &s->irq,1 );memory_region_init_io (&pit->ioports, &pit_ioport_ops, pit,"pit" ,4 );isa_register_ioport (dev, &pit->ioports, pit->iobase);
@@ -543,7 +542,6 @@ static int pit_initfn(ISADevice *dev) }static Property pit_properties[] = { -DEFINE_PROP_UINT32 ("irq" , PITState, irq,-1 ),DEFINE_PROP_HEX32 ("iobase" , PITState, iobase,-1 ),DEFINE_PROP_END_OF_LIST (), };
hw/i8254.h +4 -2
@@ -30,14 +30,16 @@#define PIT_FREQ 1193182 -static inline ISADevice *pit_init (ISABus *bus,int base,int irq) +static inline ISADevice *pit_init (ISABus *bus,int base,int isa_irq, +qemu_irq alt_irq) {ISADevice *dev; dev =isa_create (bus,"isa-pit" );qdev_prop_set_uint32 (&dev->qdev,"iobase" , base); -qdev_prop_set_uint32 (&dev->qdev,"irq" , irq);qdev_init_nofail (&dev->qdev); +qdev_connect_gpio_out (&dev->qdev,0 , + isa_irq >=0 ?isa_get_irq (dev, isa_irq) : alt_irq);return dev; }
hw/mips_fulong2e.c +1 -1
@@ -364,7 +364,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,smbus_eeprom_init (smbus,1 , eeprom_spd,sizeof (eeprom_spd));/* init other devices */ - pit =pit_init (isa_bus,0x40 ,0 ); + pit =pit_init (isa_bus,0x40 ,0 ,NULL ); cpu_exit_irq =qemu_allocate_irqs (cpu_request_exit,NULL ,1 );DMA_init (0 , cpu_exit_irq);
hw/mips_jazz.c +1 -1
@@ -192,7 +192,7 @@ static void mips_jazz_init(MemoryRegion *address_space,isa_bus_irqs (isa_bus, i8259); cpu_exit_irq =qemu_allocate_irqs (cpu_request_exit,NULL ,1 );DMA_init (0 , cpu_exit_irq); - pit =pit_init (isa_bus,0x40 ,0 ); + pit =pit_init (isa_bus,0x40 ,0 ,NULL );pcspk_init (pit);/* ISA IO space at 0x90000000 */
hw/mips_malta.c +1 -1
@@ -970,7 +970,7 @@ void mips_malta_init (ram_addr_t ram_size, isa_get_irq(NULL, 9), NULL, NULL, 0);/* TODO: Populate SPD eeprom data. */ smbus_eeprom_init (smbus,8 ,NULL ,0 ); - pit =pit_init (isa_bus,0x40 ,0 ); + pit =pit_init (isa_bus,0x40 ,0 ,NULL ); cpu_exit_irq =qemu_allocate_irqs (cpu_request_exit,NULL ,1 );DMA_init (0 , cpu_exit_irq);
hw/mips_r4k.c +1 -1
@@ -270,7 +270,7 @@ void mips_r4k_init (ram_addr_t ram_size,isa_mmio_init (0x14000000 ,0x00010000 ); isa_mem_base =0x10000000 ; - pit =pit_init (isa_bus,0x40 ,0 ); + pit =pit_init (isa_bus,0x40 ,0 ,NULL );for (i =0 ; i <MAX_SERIAL_PORTS ; i++) {if (serial_hds[i]) {
hw/pc.c +1 -1
@@ -1161,7 +1161,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,qemu_register_boot_set (pc_boot_set, *rtc_state); - pit =pit_init (isa_bus,0x40 ,0 ); + pit =pit_init (isa_bus,0x40 ,0 ,NULL );pcspk_init (pit);for (i =0 ; i <MAX_SERIAL_PORTS ; i++) {
Signature · 1 line
1.7.3.4
PATCH v4 5/7 i8254: Rework & fix interaction with HPET in legacy mode
In reply to Jan KiszkaWhen the HPET enters legacy mode, the IRQ output of the PIT is suppressed and replaced by the HPET timer 0. But the current code to emulate this was broken in many ways. It reset the PIT state after re-enabling, it worked against a stale static PIT structure, and it did not properly saved/restored the IRQ output mask in the PIT vmstate.
This patch solves the PIT IRQ control in a different way. On x86, it both redirects the PIT IRQ to the HPET, just like the RTC. But it also keeps the control line from the HPET to the PIT. This allows to disable the PIT QEMU timer when it is not needed. The PIT's view on the control line state is now saved in the same format that qemu-kvm is already using.
Note that, in contrast to the suppressed RTC IRQ line, we do not need to save/restore the PIT line state in the HPET. As we trigger a PIT IRQ update via the control line, the line state is reconstructed on mode switch.
--- hw/hpet.c | 38 ++++++++++++++++++++------------------ hw/hpet_emul.h | 3 +++ hw/i8254.c | 46 ++++++++++++++++++++++------------------------ hw/i8254.h | 3 --- hw/pc.c | 15 ++++++++++++--- 5 files changed, 57 insertions(+), 48 deletions(-)
hw/hpet.c +20 -18
@@ -65,6 +65,7 @@ typedef struct HPETState {qemu_irq irqs[HPET_NUM_IRQ_ROUTES ];uint32_t flags;uint8_t rtc_irq_level; +qemu_irq pit_enabled;uint8_t num_timers;HPETTimer timer[HPET_MAX_TIMERS ];
@@ -573,12 +574,15 @@ static void hpet_ram_write(void *opaque, target_phys_addr_t addr,hpet_del_timer (&s->timer[i]); } } -/* i8254 and RTC are disabled when HPET is in legacy mode */ +/* i8254 and RTC output pins are disabled +* when HPET is in legacy mode */ if (activating_bit (old_val, new_val,HPET_CFG_LEGACY )) { -hpet_pit_disable (); +qemu_set_irq (s->pit_enabled,0 ); +qemu_irq_lower (s->irqs[0 ]);qemu_irq_lower (s->irqs[RTC_ISA_IRQ ]); }else if (deactivating_bit (old_val, new_val,HPET_CFG_LEGACY )) { -hpet_pit_enable (); +qemu_irq_lower (s->irqs[0 ]); +qemu_set_irq (s->pit_enabled,1 );qemu_set_irq (s->irqs[RTC_ISA_IRQ ], s->rtc_irq_level); }break ;
@@ -632,7 +636,6 @@ static void hpet_reset(DeviceState *d) {HPETState *s =FROM_SYSBUS (HPETState,sysbus_from_qdev (d));int i; -static int count =0 ;for (i =0 ; i < s->num_timers; i++) {HPETTimer *timer = &s->timer[i];
@@ -649,32 +652,30 @@ static void hpet_reset(DeviceState *d) timer->wrap_flag =0 ; } +qemu_set_irq (s->pit_enabled,1 ); s->hpet_counter =0ULL ; s->hpet_offset =0ULL ; s->config =0ULL ; -if (count >0 ) { -/* we don't enable pit when hpet_reset is first called (by hpet_init) -* because hpet is taking over for pit here. On subsequent invocations, -* hpet_reset is called due to system reset. At this point control must -* be returned to pit until SW reenables hpet. -*/ -hpet_pit_enable (); - } hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t )s->capability; hpet_cfg.hpet[s->hpet_id].address =sysbus_from_qdev (d)->mmio[0 ].addr; - count =1 ;/* to document that the RTC lowers its output on reset as well */ s->rtc_irq_level =0 ; } -static void hpet_handle_rtc_irq (void *opaque,int n,int level) +static void hpet_handle_legacy_irq (void *opaque,int n,int level) {HPETState *s =FROM_SYSBUS (HPETState, opaque); - s->rtc_irq_level = level; -if (!hpet_in_legacy_mode (s)) { -qemu_set_irq (s->irqs[RTC_ISA_IRQ ], level); +if (n ==HPET_LEGACY_PIT_INT ) { +if (!hpet_in_legacy_mode (s)) { +qemu_set_irq (s->irqs[0 ], level); + } + }else { + s->rtc_irq_level = level; +if (!hpet_in_legacy_mode (s)) { +qemu_set_irq (s->irqs[RTC_ISA_IRQ ], level); + } } }
@@ -717,7 +718,8 @@ static int hpet_init(SysBusDevice *dev) s->capability |= (s->num_timers -1 ) <<HPET_ID_NUM_TIM_SHIFT ; s->capability |= ((HPET_CLK_PERIOD ) <<32 ); -qdev_init_gpio_in (&dev->qdev, hpet_handle_rtc_irq,1 ); +qdev_init_gpio_in (&dev->qdev, hpet_handle_legacy_irq,2 ); +qdev_init_gpio_out (&dev->qdev, &s->pit_enabled,1 );/* HPET Area */ memory_region_init_io (&s->iomem, &hpet_ram_ops, s,"hpet" ,0x400 );
hw/hpet_emul.h +3 -0
@@ -22,6 +22,9 @@#define HPET_NUM_IRQ_ROUTES 32 +#define HPET_LEGACY_PIT_INT 0 +#define HPET_LEGACY_RTC_INT 1 +#define HPET_CFG_ENABLE 0x001#define HPET_CFG_LEGACY 0x002
hw/i8254.c +22 -24
100 lines not on this page · raw message
hw/i8254.h +0 -3
@@ -50,7 +50,4 @@ 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 hpet_pit_disable (void ); -void hpet_pit_enable (void ); -#endif /* !HW_I8254_H */
hw/pc.c +12 -3
@@ -1138,6 +1138,9 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, {int i;DriveInfo *fd[MAX_FD ]; +DeviceState *hpet =NULL ; +int pit_isa_irq =0 ; +qemu_irq pit_alt_irq =NULL ;qemu_irq rtc_irq =NULL ;qemu_irq *a20_line;ISADevice *i8042, *port92, *vmmouse, *pit;
@@ -1148,20 +1151,26 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,register_ioport_write (0xf0 ,1 ,1 , ioportF0_write,NULL );if (!no_hpet) { -DeviceState *hpet =sysbus_try_create_simple ("hpet" ,HPET_BASE ,NULL ); + hpet =sysbus_try_create_simple ("hpet" ,HPET_BASE ,NULL );if (hpet) {for (i =0 ; i <GSI_NUM_PINS ; i++) {sysbus_connect_irq (sysbus_from_qdev (hpet), i, gsi[i]); } - rtc_irq =qdev_get_gpio_in (hpet,0 ); + pit_isa_irq =-1 ; + pit_alt_irq =qdev_get_gpio_in (hpet,HPET_LEGACY_PIT_INT ); + rtc_irq =qdev_get_gpio_in (hpet,HPET_LEGACY_RTC_INT ); } } *rtc_state =rtc_init (isa_bus,2000 , rtc_irq);qemu_register_boot_set (pc_boot_set, *rtc_state); - pit =pit_init (isa_bus,0x40 ,0 ,NULL ); + pit =pit_init (isa_bus,0x40 , pit_isa_irq, pit_alt_irq); +if (hpet) { +/* connect PIT to output control line of the HPET */ +qdev_connect_gpio_out (hpet,0 ,qdev_get_gpio_in (&pit->qdev,0 )); + }pcspk_init (pit);for (i =0 ; i <MAX_SERIAL_PORTS ; i++) {
Signature · 1 line
1.7.3.4
PATCH v4 6/7 pcspk: Convert to qdev
In reply to Jan KiszkaConvert the PC speaker device to a qdev ISA model. Move the public interface to a dedicated header file at this chance.
--- arch_init.c | 1 + hw/i82378.c | 3 +- hw/mips_jazz.c | 3 +- hw/pc.c | 3 +- hw/pc.h | 4 --- hw/pcspk.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++-------- hw/pcspk.h | 45 +++++++++++++++++++++++++++++++++++++ 7 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 hw/pcspk.h
arch_init.c +1 -0
@@ -42,6 +42,7 @@#include "gdbstub.h" #include "hw/smbios.h" #include "exec-memory.h" +#include "hw/pcspk.h" #ifdef TARGET_SPARC int graphic_width =1024 ;
hw/i82378.c +2 -1
@@ -20,6 +20,7 @@#include "pci.h" #include "pc.h" #include "i8254.h" +#include "pcspk.h" //#define DEBUG_I82378
@@ -195,7 +196,7 @@ static void i82378_init(DeviceState *dev, I82378State *s) pit =pit_init (isabus,0x40 ,0 ,NULL );/* speaker */ -pcspk_init (pit); +pcspk_init (isabus, pit);/* 2 82C37 (dma) */ DMA_init (1 , &s->out[1 ]);
hw/mips_jazz.c +2 -1
@@ -37,6 +37,7 @@#include "loader.h" #include "mc146818rtc.h" #include "i8254.h" +#include "pcspk.h" #include "blockdev.h" #include "sysbus.h" #include "exec-memory.h"
@@ -193,7 +194,7 @@ static void mips_jazz_init(MemoryRegion *address_space, cpu_exit_irq =qemu_allocate_irqs (cpu_request_exit,NULL ,1 );DMA_init (0 , cpu_exit_irq); pit =pit_init (isa_bus,0x40 ,0 ,NULL ); -pcspk_init (pit); +pcspk_init (isa_bus, pit);/* ISA IO space at 0x90000000 */ isa_mmio_init (0x90000000 ,0x01000000 );
hw/pc.c +2 -1
@@ -37,6 +37,7 @@#include "multiboot.h" #include "mc146818rtc.h" #include "i8254.h" +#include "pcspk.h" #include "msi.h" #include "sysbus.h" #include "sysemu.h"
@@ -1171,7 +1172,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,/* connect PIT to output control line of the HPET */ qdev_connect_gpio_out (hpet,0 ,qdev_get_gpio_in (&pit->qdev,0 )); } -pcspk_init (pit); +pcspk_init (isa_bus, pit);for (i =0 ; i <MAX_SERIAL_PORTS ; i++) {if (serial_hds[i]) {
hw/pc.h +0 -4
@@ -149,10 +149,6 @@ void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);/* hpet.c */ extern int no_hpet; -/* pcspk.c */ -void pcspk_init (ISADevice *pit); -int pcspk_audio_init (ISABus *bus); -/* piix_pci.c */ struct PCII440FXState ;typedef struct PCII440FXState PCII440FXState ;
hw/pcspk.c +57 -10
112 lines not on this page · raw message
hw/pcspk.h new file +45 -0
45 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH v5 6/7 pcspk: Convert to qdev
Convert the PC speaker device to a qdev ISA model. Move the public interface to a dedicated header file at this chance.
---
Trivial rebase over git head. Would be great if this series could be merged now quickly.
arch_init.c | 1 + hw/i82378.c | 3 +- hw/mips_jazz.c | 3 +- hw/pc.c | 3 +- hw/pc.h | 4 --- hw/pcspk.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++-------- hw/pcspk.h | 45 +++++++++++++++++++++++++++++++++++++ 7 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 hw/pcspk.h
arch_init.c +1 -0
@@ -42,6 +42,7 @@#include "gdbstub.h" #include "hw/smbios.h" #include "exec-memory.h" +#include "hw/pcspk.h" #ifdef TARGET_SPARC int graphic_width =1024 ;
hw/i82378.c +2 -1
@@ -20,6 +20,7 @@#include "pci.h" #include "pc.h" #include "i8254.h" +#include "pcspk.h" //#define DEBUG_I82378
@@ -195,7 +196,7 @@ static void i82378_init(DeviceState *dev, I82378State *s) pit =pit_init (isabus,0x40 ,0 ,NULL );/* speaker */ -pcspk_init (pit); +pcspk_init (isabus, pit);/* 2 82C37 (dma) */ DMA_init (1 , &s->out[1 ]);
hw/mips_jazz.c +2 -1
@@ -37,6 +37,7 @@#include "loader.h" #include "mc146818rtc.h" #include "i8254.h" +#include "pcspk.h" #include "blockdev.h" #include "sysbus.h" #include "exec-memory.h"
@@ -193,7 +194,7 @@ static void mips_jazz_init(MemoryRegion *address_space, cpu_exit_irq =qemu_allocate_irqs (cpu_request_exit,NULL ,1 );DMA_init (0 , cpu_exit_irq); pit =pit_init (isa_bus,0x40 ,0 ,NULL ); -pcspk_init (pit); +pcspk_init (isa_bus, pit);/* ISA IO space at 0x90000000 */ isa_mmio_init (0x90000000 ,0x01000000 );
hw/pc.c +2 -1
@@ -37,6 +37,7 @@#include "multiboot.h" #include "mc146818rtc.h" #include "i8254.h" +#include "pcspk.h" #include "msi.h" #include "sysbus.h" #include "sysemu.h"
@@ -1172,7 +1173,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,/* connect PIT to output control line of the HPET */ qdev_connect_gpio_out (hpet,0 ,qdev_get_gpio_in (&pit->qdev,0 )); } -pcspk_init (pit); +pcspk_init (isa_bus, pit);for (i =0 ; i <MAX_SERIAL_PORTS ; i++) {if (serial_hds[i]) {
hw/pc.h +0 -4
@@ -149,10 +149,6 @@ void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);/* hpet.c */ extern int no_hpet; -/* pcspk.c */ -void pcspk_init (ISADevice *pit); -int pcspk_audio_init (ISABus *bus); -/* piix_pci.c */ struct PCII440FXState ;typedef struct PCII440FXState PCII440FXState ;
hw/pcspk.c +57 -10
112 lines not on this page · raw message
hw/pcspk.h new file +45 -0
45 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH v4 7/7 i8254: Factor out pit_get_channel_info
In reply to Jan KiszkaInstead 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.
--- hw/i8254.c | 35 ++++++++++------------------------- hw/i8254.h | 12 ++++++++---- hw/pcspk.c | 16 +++++++++++----- 3 files changed, 29 insertions(+), 34 deletions(-)
hw/i8254.c +10 -25
@@ -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",
hw/i8254.h +8 -4
@@ -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 */
hw/pcspk.c +11 -5
@@ -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,
Signature · 1 line
1.7.3.4
Anthony Liguori
AppliedQuoted 10 lines · Jan Kiszka
Changes in V4:
- rebased over qom-upstream.13
- comment onrtc_irq_levelclearing on reset
- fix call toisa_register_ioportby passing the pcspk deviceNot changed:
- PIT pointer property of pcspk
(Paolo will port it together with otherPROP_PTRusers)CC Paolo Bonzini<[email protected]>
Applied. Thanks.
Regards,
Anthony Liguori
Quoted 29 lines
Jan Kiszka (7):
i8254: Do not raise IRQ level on reset
hpet: Save/restore cached RTC IRQ level
i8254: Factor out interface header
i8254: Pass alternative IRQ output object on initialization
i8254: Rework& fix interaction with HPET in legacy mode
pcspk: Convert to qdev
i8254: Factor outpit_get_channel_infoarch_init.c | 1 + hw/alpha_dp264.c | 3 +- hw/hpet.c | 68 ++++++++++++++++++++++++++++---------- hw/hpet_emul.h | 3 ++ hw/i82378.c | 6 ++- hw/i8254.c | 92 ++++++++++++++++++++++----------------------------- hw/i8254.h | 57 ++++++++++++++++++++++++++++++++ hw/mips_fulong2e.c | 3 +- hw/mips_jazz.c | 6 ++- hw/mips_malta.c | 3 +- hw/mips_r4k.c | 3 +- hw/pc.c | 19 ++++++++-- hw/pc.h | 29 ---------------- hw/pcspk.c | 84 +++++++++++++++++++++++++++++++++++++++-------- hw/pcspk.h | 45 +++++++++++++++++++++++++ 15 files changed, 296 insertions(+), 126 deletions(-)create mode 100644
hw/i8254.h
create mode 100644hw/pcspk.h