i82094aa.cc revision 5898
12SN/A/*
21762SN/A * Copyright (c) 2008 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Gabe Black
292SN/A */
302SN/A
312439SN/A#include "arch/x86/intmessage.hh"
322984Sgblack@eecs.umich.edu#include "dev/x86/i82094aa.hh"
33146SN/A#include "dev/x86/i8259.hh"
34146SN/A#include "mem/packet.hh"
35146SN/A#include "mem/packet_access.hh"
36146SN/A#include "sim/system.hh"
37146SN/A
38146SN/AX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
391717SN/A    latency(p->pio_latency), pioAddr(p->pio_addr),
40146SN/A    extIntPic(p->external_int_pic)
411717SN/A{
42146SN/A    // This assumes there's only one I/O APIC in the system
431977SN/A    id = sys->numContexts();
442623SN/A    assert(id <= 0xf);
452683Sktlim@umich.edu    arbId = id;
461717SN/A    regSel = 0;
47146SN/A    RedirTableEntry entry = 0;
482683Sktlim@umich.edu    entry.mask = 1;
491917SN/A    for (int i = 0; i < TableSize; i++) {
502592SN/A        redirTable[i] = entry;
512683Sktlim@umich.edu        pinStates[i] = false;
522036SN/A    }
53146SN/A}
5456SN/A
5556SN/ATick
5656SN/AX86ISA::I82094AA::read(PacketPtr pkt)
57695SN/A{
582901Ssaidi@eecs.umich.edu    assert(pkt->getSize() == 4);
592SN/A    Addr offset = pkt->getAddr() - pioAddr;
601858SN/A    switch(offset) {
6156SN/A      case 0:
622171SN/A        pkt->set<uint32_t>(regSel);
632170SN/A        break;
642170SN/A      case 16:
65146SN/A        pkt->set<uint32_t>(readReg(regSel));
662462SN/A        break;
67146SN/A      default:
682SN/A        panic("Illegal read from I/O APIC.\n");
692SN/A    }
702449SN/A    pkt->makeAtomicResponse();
711355SN/A    return latency;
722623SN/A}
732683Sktlim@umich.edu
74224SN/ATick
751858SN/AX86ISA::I82094AA::write(PacketPtr pkt)
762683Sktlim@umich.edu{
772420SN/A    assert(pkt->getSize() == 4);
782683Sktlim@umich.edu    Addr offset = pkt->getAddr() - pioAddr;
792520SN/A    switch(offset) {
802420SN/A      case 0:
812SN/A        regSel = pkt->get<uint32_t>();
822683Sktlim@umich.edu        break;
832672Sktlim@umich.edu      case 16:
842683Sktlim@umich.edu        writeReg(regSel, pkt->get<uint32_t>());
852SN/A        break;
862SN/A      default:
87334SN/A        panic("Illegal write to I/O APIC.\n");
88140SN/A    }
89334SN/A    pkt->makeAtomicResponse();
902SN/A    return latency;
912SN/A}
922SN/A
932680Sktlim@umich.eduvoid
942SN/AX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
952SN/A{
962623SN/A    if (offset == 0x0) {
972SN/A        id = bits(value, 27, 24);
982SN/A    } else if (offset == 0x1) {
992SN/A        // The IOAPICVER register is read only.
100180SN/A    } else if (offset == 0x2) {
1012623SN/A        arbId = bits(value, 27, 24);
102393SN/A    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
103393SN/A        int index = (offset - 0x10) / 2;
104393SN/A        if (offset % 2) {
105393SN/A            redirTable[index].topDW = value;
106384SN/A            redirTable[index].topReserved = 0;
107384SN/A        } else {
108393SN/A            redirTable[index].bottomDW = value;
1092623SN/A            redirTable[index].bottomReserved = 0;
110393SN/A        }
111393SN/A    } else {
112393SN/A        warn("Access to undefined I/O APIC register %#x.\n", offset);
113393SN/A    }
114384SN/A    DPRINTF(I82094AA,
115189SN/A            "Wrote %#x to I/O APIC register %#x .\n", value, offset);
116189SN/A}
1172623SN/A
1182SN/Auint32_t
119729SN/AX86ISA::I82094AA::readReg(uint8_t offset)
120334SN/A{
1212SN/A    uint32_t result = 0;
1222SN/A    if (offset == 0x0) {
1232SN/A        result = id << 24;
1242SN/A    } else if (offset == 0x1) {
1252SN/A        result = ((TableSize - 1) << 16) | APICVersion;
1262SN/A    } else if (offset == 0x2) {
1272SN/A        result = arbId << 24;
1282SN/A    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1292SN/A        int index = (offset - 0x10) / 2;
1302SN/A        if (offset % 2) {
1312SN/A            result = redirTable[index].topDW;
1322SN/A        } else {
1331001SN/A            result = redirTable[index].bottomDW;
1341001SN/A        }
1351001SN/A    } else {
1361001SN/A        warn("Access to undefined I/O APIC register %#x.\n", offset);
1371001SN/A    }
1382SN/A    DPRINTF(I82094AA,
1392SN/A            "Read %#x from I/O APIC register %#x.\n", result, offset);
1402SN/A    return result;
1412SN/A}
1422SN/A
1432SN/Avoid
1442SN/AX86ISA::I82094AA::signalInterrupt(int line)
1452SN/A{
1462SN/A    DPRINTF(I82094AA, "Received interrupt %d.\n", line);
1472SN/A    assert(line < TableSize);
1482SN/A    RedirTableEntry entry = redirTable[line];
1492SN/A    if (entry.mask) {
1502SN/A        DPRINTF(I82094AA, "Entry was masked.\n");
1512SN/A        return;
1522SN/A    } else {
1532SN/A        TriggerIntMessage message;
1542SN/A        message.destination = entry.dest;
1552390SN/A        if (entry.deliveryMode == DeliveryMode::ExtInt) {
1562390SN/A            assert(extIntPic);
1572390SN/A            message.vector = extIntPic->getVector();
1582390SN/A        } else {
1592390SN/A            message.vector = entry.vector;
1602390SN/A        }
1612390SN/A        message.deliveryMode = entry.deliveryMode;
1622390SN/A        message.destMode = entry.destMode;
1632390SN/A        message.level = entry.polarity;
1642390SN/A        message.trigger = entry.trigger;
1652390SN/A
1662390SN/A        if (DeliveryMode::isReserved(entry.deliveryMode)) {
167385SN/A            fatal("Tried to use reserved delivery mode "
1682SN/A                    "for IO APIC entry %d.\n", line);
1692SN/A        } else if (DTRACE(I82094AA)) {
1702SN/A            DPRINTF(I82094AA, "Delivery mode is: %s.\n",
1712623SN/A                    DeliveryMode::names[entry.deliveryMode]);
172334SN/A            DPRINTF(I82094AA, "Vector is %#x.\n", message.vector);
1732361SN/A        }
1742623SN/A
175334SN/A        if (entry.destMode == 0) {
176334SN/A            DPRINTF(I82094AA,
177334SN/A                    "Sending interrupt to APIC ID %d.\n", entry.dest);
1782623SN/A            PacketPtr pkt = buildIntRequest(entry.dest, message);
1792SN/A            if (sys->getMemoryMode() == Enums::timing)
180921SN/A                intPort->sendMessageTiming(pkt, latency);
1812915Sktlim@umich.edu            else if (sys->getMemoryMode() == Enums::atomic)
1822915Sktlim@umich.edu                intPort->sendMessageAtomic(pkt);
1832683Sktlim@umich.edu            else
1842SN/A                panic("Unrecognized memory mode.\n");
1852SN/A        } else {
1862SN/A            DPRINTF(I82094AA, "Sending interrupts to APIC IDs:"
1872623SN/A                    "%s%s%s%s%s%s%s%s\n",
1882SN/A                    bits((int)entry.dest, 0) ? " 0": "",
189921SN/A                    bits((int)entry.dest, 1) ? " 1": "",
1902915Sktlim@umich.edu                    bits((int)entry.dest, 2) ? " 2": "",
1912915Sktlim@umich.edu                    bits((int)entry.dest, 3) ? " 3": "",
1922SN/A                    bits((int)entry.dest, 4) ? " 4": "",
1932SN/A                    bits((int)entry.dest, 5) ? " 5": "",
1942SN/A                    bits((int)entry.dest, 6) ? " 6": "",
1952SN/A                    bits((int)entry.dest, 7) ? " 7": ""
1962SN/A                    );
1972SN/A            uint8_t dests = entry.dest;
1982SN/A            uint8_t id = 0;
199595SN/A            while(dests) {
2002623SN/A                if (dests & 0x1) {
201595SN/A                    PacketPtr pkt = buildIntRequest(id, message);
2022390SN/A                    if (sys->getMemoryMode() == Enums::timing)
2031080SN/A                        intPort->sendMessageTiming(pkt, latency);
2041080SN/A                    else if (sys->getMemoryMode() == Enums::atomic)
2051080SN/A                        intPort->sendMessageAtomic(pkt);
2061080SN/A                    else
2071080SN/A                        panic("Unrecognized memory mode.\n");
2081080SN/A                }
2091080SN/A                dests >>= 1;
2101121SN/A                id++;
2112107SN/A            }
2121089SN/A        }
2131089SN/A    }
2141080SN/A}
2151080SN/A
2161080SN/Avoid
2171080SN/AX86ISA::I82094AA::raiseInterruptPin(int number)
218595SN/A{
2192623SN/A    assert(number < TableSize);
2202683Sktlim@umich.edu    if (!pinStates[number])
221595SN/A        signalInterrupt(number);
2222090SN/A    pinStates[number] = true;
2232683Sktlim@umich.edu}
2242683Sktlim@umich.edu
225595SN/Avoid
2262205SN/AX86ISA::I82094AA::lowerInterruptPin(int number)
2272205SN/A{
2282683Sktlim@umich.edu    assert(number < TableSize);
2292683Sktlim@umich.edu    pinStates[number] = false;
230595SN/A}
231595SN/A
2322390SN/AX86ISA::I82094AA *
2332423SN/AI82094AAParams::create()
2342390SN/A{
235595SN/A    return new X86ISA::I82094AA(this);
236595SN/A}
237595SN/A