///////////////////////////////////////////////////////////////////////// // $Id: ioapic.cc,v 1.6 2001-10-03 13:10:38 bdenney Exp $ ///////////////////////////////////////////////////////////////////////// // #include #include "bochs.h" class bx_ioapic_c bx_ioapic; #define LOG_THIS bx_ioapic. void bx_io_redirect_entry_t::parse_value () { dest = (value >> 56) & 0xff; masked = (value >> 16) & 1; trig_mode = (value >> 15) & 1; remote_irr = (value >> 14) & 1; polarity = (value >> 13) & 1; //delivery_status = (value >> 12) & 1; delivery_status = 0; // always say the message has gone through dest_mode = (value >> 11) & 1; delivery_mode = (value >> 8) & 7; vector = (value >> 0) & 0xff; } void bx_io_redirect_entry_t::sprintf_self (char *buf) { sprintf (buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector); } bx_ioapic_c::bx_ioapic_c () : bx_generic_apic_c () { put("IOAP"); settype(IOAPICLOG); } bx_ioapic_c::~bx_ioapic_c () { } void bx_ioapic_c::init () { bx_generic_apic_c::init (); if (bx_dbg.ioapic) BX_INFO(("initializing I/O APIC")); base_addr = 0xfec00000; ioregsel = 0; // all interrupts masked for (int i=0; i> 1; if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { bx_io_redirect_entry_t *entry = ioredtbl + index; *data = (ioregsel&1) ? entry->get_odd_word() : entry->get_even_word (); return; } BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); } } void bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len) { if (bx_dbg.ioapic) BX_INFO(("IOAPIC: write addr=%08x, data=%08x, len=%d", address, *value, len)); address &= 0xff; if (address == 0x00) { ioregsel = *value; return; } else if (address != 0x10) { BX_PANIC(("IOAPIC: write to unsupported address")); } // only reached when writing data register switch (ioregsel) { case 0x00: // set APIC ID { Bit8u newid = (*value >> 24) & 0xf; BX_INFO(("IOAPIC: setting id to 0x%x", newid)); set_id (newid); return; } case 0x01: // version case 0x02: // arbitration id BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel)); return; default: int index = (ioregsel - 0x10) >> 1; if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { bx_io_redirect_entry_t *entry = ioredtbl + index; if (ioregsel&1) entry->set_odd_word (*value); else entry->set_even_word (*value); char buf[1024]; entry->sprintf_self (buf); if (bx_dbg.ioapic) BX_INFO(("IOAPIC: now entry[%d] is %s", index, buf)); service_ioapic (); return; } BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); } } void bx_ioapic_c::trigger_irq (unsigned vector, unsigned from) { if (bx_dbg.ioapic) BX_INFO(("IOAPIC: received interrupt %d", vector)); if (vector >= 0 && vector < BX_IOAPIC_NUM_PINS) { Bit32u bit = 1<masked) { // clear irr bit and deliver Boolean done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode); if (done) irr &= ~(1<