Prepared devices and timer code for HPET support

- PIT / CMOS: added methods to control IRQ generation (for HPET legacy mode).
- Added method for activating timer with nanosecond value.
- Removed unused declaration in the keyboard code.
- TODO: virtual timer code also needs to handle nanosecond values.
This commit is contained in:
Volker Ruppert 2017-04-15 20:31:07 +00:00
parent 73bcd4f8ca
commit 89654a4beb
10 changed files with 76 additions and 14 deletions

View File

@ -278,6 +278,7 @@ void bx_cmos_c::init(void)
void bx_cmos_c::reset(unsigned type)
{
BX_CMOS_THIS s.cmos_mem_address = 0;
BX_CMOS_THIS s.irq_enabled = 1;
// RESET affects the following registers:
// CRA: no effects
@ -318,6 +319,7 @@ void bx_cmos_c::register_state(void)
{
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "cmos", "CMOS State");
BXRS_HEX_PARAM_FIELD(list, mem_address, BX_CMOS_THIS s.cmos_mem_address);
BXRS_PARAM_BOOL(list, irq_enabled, BX_CMOS_THIS s.irq_enabled);
new bx_shadow_data_c(list, "ram", BX_CMOS_THIS s.reg, 128, 1);
}
@ -386,7 +388,9 @@ Bit32u bx_cmos_c::read(Bit32u address, unsigned io_len)
// all bits of Register C are cleared after a read occurs.
if (BX_CMOS_THIS s.cmos_mem_address == REG_STAT_C) {
BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00;
DEV_pic_lower_irq(8);
if (BX_CMOS_THIS s.irq_enabled) {
DEV_pic_lower_irq(8);
}
}
return(ret8);
@ -659,7 +663,9 @@ void bx_cmos_c::periodic_timer()
// update status register C
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) {
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xc0; // Interrupt Request, Periodic Int
DEV_pic_raise_irq(8);
if (BX_CMOS_THIS s.irq_enabled) {
DEV_pic_raise_irq(8);
}
}
}
@ -703,7 +709,9 @@ void bx_cmos_c::uip_timer()
// update status register C
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x10) {
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0x90; // Interrupt Request, Update Ended
DEV_pic_raise_irq(8);
if (BX_CMOS_THIS s.irq_enabled) {
DEV_pic_raise_irq(8);
}
}
// compare CMOS user copy of time/date to alarm time/date here
@ -727,7 +735,9 @@ void bx_cmos_c::uip_timer()
}
if (alarm_match) {
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xa0; // Interrupt Request, Alarm Int
DEV_pic_raise_irq(8);
if (BX_CMOS_THIS s.irq_enabled) {
DEV_pic_raise_irq(8);
}
}
}
BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x7f; // clear UIP bit

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2012 The Bochs Project
// Copyright (C) 2002-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -55,6 +55,9 @@ public:
virtual time_t get_timeval() {
return s.timeval;
}
virtual void enable_irq(bx_bool enabled) {
s.irq_enabled = enabled;
}
struct {
int periodic_timer_index;
@ -67,6 +70,7 @@ public:
bx_bool rtc_mode_12hour;
bx_bool rtc_mode_binary;
bx_bool rtc_sync;
bx_bool irq_enabled;
Bit8u reg[128];
} s; // state information

View File

@ -74,6 +74,7 @@ void bx_devices_c::init_stubs()
pluginHardDrive = &stubHardDrive;
pluginKeyboard = &stubKeyboard;
pluginPicDevice = &stubPic;
pluginPitDevice = &stubPit;
pluginSpeaker = &stubSpeaker;
pluginVgaDevice = &stubVga;
#if BX_SUPPORT_IODEBUG

View File

@ -176,6 +176,16 @@ public:
virtual void checksum_cmos(void) {
STUBFUNC(cmos, checksum);
}
virtual void enable_irq(bx_bool enabled) {
STUBFUNC(cmos, enable_irq);
}
};
class BOCHSAPI bx_pit_stub_c : public bx_devmodel_c {
public:
virtual void enable_irq(bx_bool enabled) {
STUBFUNC(pit, enable_irq);
}
};
class BOCHSAPI bx_dma_stub_c : public bx_devmodel_c {
@ -410,6 +420,7 @@ public:
bx_hdimage_ctl_stub_c *pluginHDImageCtl;
bx_keyb_stub_c *pluginKeyboard;
bx_pic_stub_c *pluginPicDevice;
bx_pit_stub_c *pluginPitDevice;
bx_speaker_stub_c *pluginSpeaker;
bx_vga_stub_c *pluginVgaDevice;
#if BX_SUPPORT_IODEBUG
@ -439,6 +450,7 @@ public:
bx_hdimage_ctl_stub_c stubHDImage;
bx_keyb_stub_c stubKeyboard;
bx_pic_stub_c stubPic;
bx_pit_stub_c stubPit;
bx_speaker_stub_c stubSpeaker;
bx_vga_stub_c stubVga;
#if BX_SUPPORT_IODEBUG

View File

@ -227,7 +227,6 @@ private:
void mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy);
static void timer_handler(void *);
void timer(void);
int timer_handle;
int statusbar_id[3];
bx_bool bxkey_state[BX_KEY_NBKEYS];

View File

@ -37,6 +37,7 @@ int CDECL libpit_LTX_plugin_init(plugin_t *plugin, plugintype_t type)
{
if (type == PLUGTYPE_CORE) {
thePit = new bx_pit_c();
bx_devices.pluginPitDevice = thePit;
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePit, BX_PLUGIN_PIT);
return 0; // Success
} else {
@ -101,6 +102,7 @@ void bx_pit_c::init(void)
(clock_mode == BX_CLOCK_SYNC_BOTH);
DEV_register_irq(0, "8254 PIT");
BX_PIT_THIS s.irq_enabled = 1;
DEV_register_ioread_handler(this, read_handler, 0x0040, "8254 PIT", 1);
DEV_register_ioread_handler(this, read_handler, 0x0041, "8254 PIT", 1);
DEV_register_ioread_handler(this, read_handler, 0x0042, "8254 PIT", 1);
@ -172,6 +174,7 @@ void bx_pit_c::register_state(void)
new bx_shadow_num_c(list, "last_next_event_time", &BX_PIT_THIS s.last_next_event_time);
new bx_shadow_num_c(list, "total_ticks", &BX_PIT_THIS s.total_ticks);
new bx_shadow_num_c(list, "total_usec", &BX_PIT_THIS s.total_usec);
BXRS_PARAM_BOOL(list, irq_enabled, BX_PIT_THIS s.irq_enabled);
bx_list_c *counter = new bx_list_c(list, "counter");
BX_PIT_THIS s.timer.register_state(counter);
}
@ -392,10 +395,12 @@ bx_bool bx_pit_c::periodic(Bit32u usec_delta)
void bx_pit_c::irq_handler(bx_bool value)
{
if (value == 1) {
DEV_pic_raise_irq(0);
} else {
DEV_pic_lower_irq(0);
if (BX_PIT_THIS s.irq_enabled) {
if (value == 1) {
DEV_pic_raise_irq(0);
} else {
DEV_pic_lower_irq(0);
}
}
}

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2014 The Bochs Project
// Copyright (C) 2001-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -32,7 +32,7 @@
# define BX_PIT_THIS this->
#endif
class bx_pit_c : public bx_devmodel_c {
class bx_pit_c : public bx_pit_stub_c {
public:
bx_pit_c();
virtual ~bx_pit_c();
@ -40,6 +40,9 @@ public:
virtual void reset(unsigned type);
virtual void register_state(void);
virtual void after_restore_state(void);
virtual void enable_irq(bx_bool enabled) {
s.irq_enabled = enabled;
}
#if BX_DEBUGGER
virtual void debug_dump(int argc, char **argv);
#endif
@ -61,6 +64,7 @@ private:
Bit64u total_ticks;
Bit64u total_usec;
int timer_handle[3];
bx_bool irq_enabled;
} s;
bx_bool is_realtime;

View File

@ -526,8 +526,30 @@ void bx_pc_system_c::activate_timer(unsigned i, Bit32u useconds, bx_bool continu
// If the timer frequency is rediculously low, make it more sane.
// This happens when 'ips' is too low.
if (ticks < MinAllowableTimerPeriod) {
//BX_INFO(("activate_timer: adjusting ticks of %llu to min of %u",
// ticks, MinAllowableTimerPeriod));
ticks = MinAllowableTimerPeriod;
}
timer[i].period = ticks;
}
activate_timer_ticks(i, ticks, continuous);
}
void bx_pc_system_c::activate_timer_nsec(unsigned i, Bit64u nseconds, bx_bool continuous)
{
Bit64u ticks;
// if nseconds = 0, use default stored in period field
// else set new period from useconds
if (nseconds==0) {
ticks = timer[i].period;
} else {
// convert nseconds to number of ticks
ticks = (Bit64u) (double(nseconds) * m_ips / 1000.0);
// If the timer frequency is rediculously low, make it more sane.
// This happens when 'ips' is too low.
if (ticks < MinAllowableTimerPeriod) {
ticks = MinAllowableTimerPeriod;
}

View File

@ -95,6 +95,7 @@ public:
void setTimerParam(unsigned timerID, Bit32u param);
void start_timers(void);
void activate_timer(unsigned timer_index, Bit32u useconds, bx_bool continuous);
void activate_timer_nsec(unsigned timer_index, Bit64u nseconds, bx_bool continuous);
void deactivate_timer(unsigned timer_index);
unsigned triggeredTimerID(void) {
return triggeredTimer;

View File

@ -161,6 +161,10 @@ extern "C" {
#define DEV_cmos_get_reg(a) (bx_devices.pluginCmosDevice->get_reg(a))
#define DEV_cmos_set_reg(a,b) (bx_devices.pluginCmosDevice->set_reg(a,b))
#define DEV_cmos_checksum() (bx_devices.pluginCmosDevice->checksum_cmos())
#define DEV_cmos_enable_irq(a) (bx_devices.pluginCmosDevice->enable_irq(a))
///////// PIT macro
#define DEV_pit_enable_irq(a) (bx_devices.pluginPitDevice->enable_irq(a))
///////// keyboard macros
#define DEV_kbd_gen_scancode(key) (bx_devices.gen_scancode(key))