///////////////////////////////////////////////////////////////////////// // $Id: ioapic.cc,v 1.14 2004-09-15 21:48:57 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // #include #include "iodev.h" #if BX_SUPPORT_APIC class bx_ioapic_c bx_ioapic; #define LOG_THIS bx_ioapic. void bx_io_redirect_entry_t::parse_value () { dest = (value >> 56) & APIC_ID_MASK; 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; // we'll change this later... dest_mode = (value >> 11) & 1; delivery_mode = (value >> 8) & 7; vector = value & 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 (); BX_DEBUG(("initializing I/O APIC")); base_addr = 0xfec00000; set_id(BX_IOAPIC_DEFAULT_ID); 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) { BX_DEBUG(("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) & APIC_ID_MASK; 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); BX_DEBUG(("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::raise_irq (unsigned vector, unsigned from) { BX_DEBUG(("IOAPIC: received vector %d", vector)); if ((vector >= 0) && (vector <= BX_APIC_LAST_VECTOR)) { Bit32u bit = 1<parse_value(); if (!entry->masked) { // clear irr bit and deliver bx_bool done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode); if (done) irr &= ~(1<delivery_status = 0; stuck = 0; } else { entry->delivery_status = 1; stuck++; if (stuck > 5) BX_INFO(("vector %#x stuck?\n", entry->vector)); } } } } } #endif /* if BX_SUPPORT_APIC */