i82094aa.cc revision 5827:ac2c268bf4f1
12686Sksewell@umich.edu/*
22100SN/A * Copyright (c) 2008 The Regents of The University of Michigan
35222Sksewell@umich.edu * All rights reserved.
45222Sksewell@umich.edu *
55222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65222Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115222Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145222Sksewell@umich.edu * this software without specific prior written permission.
155222Sksewell@umich.edu *
165222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275222Sksewell@umich.edu *
285222Sksewell@umich.edu * Authors: Gabe Black
295222Sksewell@umich.edu */
305222Sksewell@umich.edu
315222Sksewell@umich.edu#include "arch/x86/intmessage.hh"
325222Sksewell@umich.edu#include "dev/x86/i82094aa.hh"
335222Sksewell@umich.edu#include "dev/x86/i8259.hh"
345222Sksewell@umich.edu#include "mem/packet.hh"
355222Sksewell@umich.edu#include "mem/packet_access.hh"
365222Sksewell@umich.edu#include "sim/system.hh"
375222Sksewell@umich.edu
382706Sksewell@umich.eduX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
392022SN/A    latency(p->pio_latency), pioAddr(p->pio_addr),
402022SN/A    extIntPic(p->external_int_pic)
412043SN/A{
422024SN/A    // This assumes there's only one I/O APIC in the system
432024SN/A    id = sys->numContexts();
442043SN/A    assert(id <= 0xf);
452686Sksewell@umich.edu    arbId = id;
464661Sksewell@umich.edu    regSel = 0;
472022SN/A    RedirTableEntry entry = 0;
482083SN/A    entry.mask = 1;
492686Sksewell@umich.edu    for (int i = 0; i < TableSize; i++) {
502101SN/A        redirTable[i] = entry;
512043SN/A        pinStates[i] = false;
522043SN/A    }
532101SN/A}
542101SN/A
552686Sksewell@umich.eduTick
562686Sksewell@umich.eduX86ISA::I82094AA::read(PacketPtr pkt)
572101SN/A{
582101SN/A    assert(pkt->getSize() == 4);
592101SN/A    Addr offset = pkt->getAddr() - pioAddr;
602046SN/A    switch(offset) {
612686Sksewell@umich.edu      case 0:
622686Sksewell@umich.edu        pkt->set<uint32_t>(regSel);
632686Sksewell@umich.edu        break;
642470SN/A      case 16:
652686Sksewell@umich.edu        pkt->set<uint32_t>(readReg(regSel));
664661Sksewell@umich.edu        break;
675222Sksewell@umich.edu      default:
685222Sksewell@umich.edu        panic("Illegal read from I/O APIC.\n");
692686Sksewell@umich.edu    }
702686Sksewell@umich.edu    return latency;
712470SN/A}
722241SN/A
732101SN/ATick
742495SN/AX86ISA::I82094AA::write(PacketPtr pkt)
752495SN/A{
762495SN/A    assert(pkt->getSize() == 4);
772101SN/A    Addr offset = pkt->getAddr() - pioAddr;
782495SN/A    switch(offset) {
792495SN/A      case 0:
802495SN/A        regSel = pkt->get<uint32_t>();
812101SN/A        break;
822101SN/A      case 16:
832495SN/A        writeReg(regSel, pkt->get<uint32_t>());
842495SN/A        break;
852495SN/A      default:
862495SN/A        panic("Illegal write to I/O APIC.\n");
872495SN/A    }
882495SN/A    return latency;
892495SN/A}
902495SN/A
912495SN/Avoid
922495SN/AX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
932495SN/A{
942495SN/A    if (offset == 0x0) {
952495SN/A        id = bits(value, 27, 24);
962101SN/A    } else if (offset == 0x1) {
972101SN/A        // The IOAPICVER register is read only.
982101SN/A    } else if (offset == 0x2) {
992101SN/A        arbId = bits(value, 27, 24);
1002101SN/A    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1012101SN/A        int index = (offset - 0x10) / 2;
1022101SN/A        if (offset % 2) {
1032101SN/A            redirTable[index].topDW = value;
1042101SN/A            redirTable[index].topReserved = 0;
1052101SN/A        } else {
1062495SN/A            redirTable[index].bottomDW = value;
1072495SN/A            redirTable[index].bottomReserved = 0;
1082495SN/A        }
1092495SN/A    } else {
1102495SN/A        warn("Access to undefined I/O APIC register %#x.\n", offset);
1112495SN/A    }
1122495SN/A    DPRINTF(I82094AA,
1132495SN/A            "Wrote %#x to I/O APIC register %#x .\n", value, offset);
1142495SN/A}
1152495SN/A
1162495SN/Auint32_t
1172495SN/AX86ISA::I82094AA::readReg(uint8_t offset)
1182495SN/A{
1192495SN/A    uint32_t result = 0;
1202495SN/A    if (offset == 0x0) {
1212043SN/A        result = id << 24;
1222043SN/A    } else if (offset == 0x1) {
1232025SN/A        result = ((TableSize - 1) << 16) | APICVersion;
1242043SN/A    } else if (offset == 0x2) {
1252686Sksewell@umich.edu        result = arbId << 24;
1262686Sksewell@umich.edu    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1272123SN/A        int index = (offset - 0x10) / 2;
1282101SN/A        if (offset % 2) {
1295222Sksewell@umich.edu            result = redirTable[index].topDW;
1305222Sksewell@umich.edu        } else {
1312101SN/A            result = redirTable[index].bottomDW;
1322042SN/A        }
1332101SN/A    } else {
1344661Sksewell@umich.edu        warn("Access to undefined I/O APIC register %#x.\n", offset);
1352686Sksewell@umich.edu    }
1364661Sksewell@umich.edu    DPRINTF(I82094AA,
1372101SN/A            "Read %#x from I/O APIC register %#x.\n", result, offset);
1382101SN/A    return result;
1392042SN/A}
1402101SN/A
1412686Sksewell@umich.eduvoid
1422686Sksewell@umich.eduX86ISA::I82094AA::signalInterrupt(int line)
1435222Sksewell@umich.edu{
1445222Sksewell@umich.edu    DPRINTF(I82094AA, "Received interrupt %d.\n", line);
1455222Sksewell@umich.edu    assert(line < TableSize);
1465222Sksewell@umich.edu    RedirTableEntry entry = redirTable[line];
1475222Sksewell@umich.edu    if (entry.mask) {
1482965Sksewell@umich.edu        DPRINTF(I82094AA, "Entry was masked.\n");
1495222Sksewell@umich.edu        return;
1505222Sksewell@umich.edu    } else {
1512686Sksewell@umich.edu        TriggerIntMessage message;
1525222Sksewell@umich.edu        message.destination = entry.dest;
1532101SN/A        if (entry.deliveryMode == DeliveryMode::ExtInt) {
1542083SN/A            assert(extIntPic);
1552043SN/A            message.vector = extIntPic->getVector();
1562025SN/A        } else {
1572043SN/A            message.vector = entry.vector;
1585222Sksewell@umich.edu        }
1594661Sksewell@umich.edu        message.deliveryMode = entry.deliveryMode;
1605222Sksewell@umich.edu        message.destMode = entry.destMode;
1614661Sksewell@umich.edu        message.level = entry.polarity;
1622083SN/A        message.trigger = entry.trigger;
1632025SN/A
1642043SN/A        if (DeliveryMode::isReserved(entry.deliveryMode)) {
1654661Sksewell@umich.edu            fatal("Tried to use reserved delivery mode "
1665222Sksewell@umich.edu                    "for IO APIC entry %d.\n", line);
1675222Sksewell@umich.edu        } else if (DTRACE(I82094AA)) {
1684661Sksewell@umich.edu            DPRINTF(I82094AA, "Delivery mode is: %s.\n",
1694661Sksewell@umich.edu                    DeliveryMode::names[entry.deliveryMode]);
1702686Sksewell@umich.edu            DPRINTF(I82094AA, "Vector is %#x.\n", message.vector);
1714661Sksewell@umich.edu        }
1724661Sksewell@umich.edu
1734661Sksewell@umich.edu        if (entry.destMode == 0) {
1744661Sksewell@umich.edu            DPRINTF(I82094AA,
1755222Sksewell@umich.edu                    "Sending interrupt to APIC ID %d.\n", entry.dest);
1765222Sksewell@umich.edu            PacketPtr pkt = buildIntRequest(entry.dest, message);
1774661Sksewell@umich.edu            if (sys->getMemoryMode() == Enums::timing)
1784661Sksewell@umich.edu                intPort->sendMessageTiming(pkt, latency);
1794661Sksewell@umich.edu            else if (sys->getMemoryMode() == Enums::atomic)
1804661Sksewell@umich.edu                intPort->sendMessageAtomic(pkt);
1815222Sksewell@umich.edu            else
1822101SN/A                panic("Unrecognized memory mode.\n");
1832084SN/A        } else {
1842025SN/A            DPRINTF(I82094AA, "Sending interrupts to APIC IDs:"
1852495SN/A                    "%s%s%s%s%s%s%s%s\n",
1862495SN/A                    bits((int)entry.dest, 0) ? " 0": "",
1872495SN/A                    bits((int)entry.dest, 1) ? " 1": "",
1885222Sksewell@umich.edu                    bits((int)entry.dest, 2) ? " 2": "",
1895222Sksewell@umich.edu                    bits((int)entry.dest, 3) ? " 3": "",
1905222Sksewell@umich.edu                    bits((int)entry.dest, 4) ? " 4": "",
1915222Sksewell@umich.edu                    bits((int)entry.dest, 5) ? " 5": "",
1925222Sksewell@umich.edu                    bits((int)entry.dest, 6) ? " 6": "",
1935222Sksewell@umich.edu                    bits((int)entry.dest, 7) ? " 7": ""
1945222Sksewell@umich.edu                    );
1955222Sksewell@umich.edu            uint8_t dests = entry.dest;
1965222Sksewell@umich.edu            uint8_t id = 0;
1975222Sksewell@umich.edu            while(dests) {
1985222Sksewell@umich.edu                if (dests & 0x1) {
1995222Sksewell@umich.edu                    PacketPtr pkt = buildIntRequest(id, message);
2005222Sksewell@umich.edu                    if (sys->getMemoryMode() == Enums::timing)
2015222Sksewell@umich.edu                        intPort->sendMessageTiming(pkt, latency);
2025222Sksewell@umich.edu                    else if (sys->getMemoryMode() == Enums::atomic)
2035222Sksewell@umich.edu                        intPort->sendMessageAtomic(pkt);
2045222Sksewell@umich.edu                    else
2055222Sksewell@umich.edu                        panic("Unrecognized memory mode.\n");
2065222Sksewell@umich.edu                }
2075222Sksewell@umich.edu                dests >>= 1;
2082495SN/A                id++;
2095222Sksewell@umich.edu            }
2105222Sksewell@umich.edu        }
2115222Sksewell@umich.edu    }
2125222Sksewell@umich.edu}
2135222Sksewell@umich.edu
2145222Sksewell@umich.eduvoid
2155222Sksewell@umich.eduX86ISA::I82094AA::raiseInterruptPin(int number)
2165222Sksewell@umich.edu{
2175222Sksewell@umich.edu    assert(number < TableSize);
2185222Sksewell@umich.edu    if (!pinStates[number])
2195222Sksewell@umich.edu        signalInterrupt(number);
2205222Sksewell@umich.edu    pinStates[number] = true;
2215222Sksewell@umich.edu}
2225222Sksewell@umich.edu
2235222Sksewell@umich.eduvoid
2242495SN/AX86ISA::I82094AA::lowerInterruptPin(int number)
2252495SN/A{
2262495SN/A    assert(number < TableSize);
2272495SN/A    pinStates[number] = false;
2282495SN/A}
2292495SN/A
2302101SN/AX86ISA::I82094AA *
2312043SN/AI82094AAParams::create()
2322025SN/A{
2332495SN/A    return new X86ISA::I82094AA(this);
2342495SN/A}
2352495SN/A