added IOAPIC control from the PIIX3 (enable /disable and address relocation)

This commit is contained in:
Volker Ruppert 2012-11-25 19:06:03 +00:00
parent 7efd6866ce
commit 2f036fe5ca
5 changed files with 41 additions and 5 deletions

View File

@ -119,7 +119,7 @@ void bx_io_redirect_entry_t::register_state(bx_param_c *parent)
#define BX_IOAPIC_BASE_ADDR (0xfec00000)
#define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)
bx_ioapic_c::bx_ioapic_c(): base_addr(BX_IOAPIC_BASE_ADDR)
bx_ioapic_c::bx_ioapic_c(): enabled(0), base_addr(BX_IOAPIC_BASE_ADDR)
{
set_id(BX_IOAPIC_DEFAULT_ID);
put("ioapic", "IOAP");
@ -134,8 +134,7 @@ bx_ioapic_c::~bx_ioapic_c()
void bx_ioapic_c::init(void)
{
BX_INFO(("initializing I/O APIC"));
DEV_register_memory_handlers(theIOAPIC,
ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
set_enabled(1, 0x0000);
reset(BX_RESET_HARDWARE);
#if BX_DEBUGGER
// register device for the 'info device' command (calls debug_dump())
@ -235,6 +234,26 @@ void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u value)
}
}
void bx_ioapic_c::set_enabled(bx_bool _enabled, Bit16u base_offset)
{
if (_enabled != enabled) {
if (_enabled) {
base_addr = BX_IOAPIC_BASE_ADDR | base_offset;
DEV_register_memory_handlers(theIOAPIC,
ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
} else {
DEV_unregister_memory_handlers(theIOAPIC, base_addr, base_addr + 0xfff);
}
enabled = _enabled;
} else if (enabled && (base_offset != (base_addr & 0xffff))) {
DEV_unregister_memory_handlers(theIOAPIC, base_addr, base_addr + 0xfff);
base_addr = BX_IOAPIC_BASE_ADDR | base_offset;
DEV_register_memory_handlers(theIOAPIC,
ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
}
BX_INFO(("IOAPIC %sabled (base address = 0x%08x)", enabled?"en":"dis", (Bit32u)base_addr));
}
void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level)
{
if (int_in == 0) { // timer connected to pin #2

View File

@ -82,6 +82,7 @@ public:
virtual void debug_dump(int argc, char **argv);
#endif
virtual void set_enabled(bx_bool enabled, Bit16u base_offset);
virtual void receive_eoi(Bit8u vector);
virtual void set_irq_level(Bit8u int_in, bx_bool level);
@ -89,12 +90,12 @@ public:
void write_aligned(bx_phy_address address, Bit32u data);
private:
bx_phy_address get_base(void) const { return base_addr; }
void set_id(Bit32u new_id) { id = new_id; }
Bit32u get_id() const { return id; }
void service_ioapic(void);
bx_bool enabled;
bx_phy_address base_addr;
Bit32u id;

View File

@ -308,6 +308,7 @@ public:
#if BX_SUPPORT_APIC
class BOCHSAPI bx_ioapic_stub_c : public bx_devmodel_c {
public:
virtual void set_enabled(bx_bool enabled, Bit16u base_offset) {}
virtual void receive_eoi(Bit8u vector) {}
virtual void set_irq_level(Bit8u int_in, bx_bool level) {}
};

View File

@ -388,8 +388,12 @@ void bx_piix3_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
break;
case 0x4f:
if (BX_P2I_THIS s.chipset == BX_PCI_CHIPSET_I440FX) {
// TODO: enable / disable IOAPIC chip select
BX_P2I_THIS pci_conf[address+i] = (value8 & 0x01);
#if BX_SUPPORT_APIC
if (DEV_ioapic_present()) {
DEV_ioapic_set_enabled(value8 & 0x01, (BX_P2I_THIS pci_conf[0x80] & 0x3f) << 10);
}
#endif
}
break;
case 0x60:
@ -413,6 +417,16 @@ void bx_piix3_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
BX_P2I_THIS pci_conf[address+i] = (value8 & 0xd7);
}
break;
case 0x80:
if (BX_P2I_THIS s.chipset == BX_PCI_CHIPSET_I440FX) {
BX_P2I_THIS pci_conf[address+i] = (value8 & 0x7f);
#if BX_SUPPORT_APIC
if (DEV_ioapic_present()) {
DEV_ioapic_set_enabled(BX_P2I_THIS pci_conf[0x4f] & 0x01, (value8 & 0x3f) << 10);
}
#endif
}
break;
default:
BX_P2I_THIS pci_conf[address+i] = value8;
BX_DEBUG(("PIIX3 PCI-to-ISA write register 0x%02x value 0x%02x", address+i,

View File

@ -148,6 +148,7 @@ extern "C" {
///////// I/O APIC macros
#define DEV_ioapic_present() (bx_devices.pluginIOAPIC != &bx_devices.stubIOAPIC)
#define DEV_ioapic_set_enabled(a,b) (bx_devices.pluginIOAPIC->set_enabled(a,b))
#define DEV_ioapic_receive_eoi(a) (bx_devices.pluginIOAPIC->receive_eoi(a))
#define DEV_ioapic_set_irq_level(a,b) (bx_devices.pluginIOAPIC->set_irq_level(a,b))