i8259.cc revision 8232
12810SN/A/*
29614Srene.dejong@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
38856Sandreas.hansson@arm.com * All rights reserved.
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68856Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78856Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98856Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118856Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128856Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138856Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
142810SN/A * this software without specific prior written permission.
152810SN/A *
162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272810SN/A *
282810SN/A * Authors: Gabe Black
292810SN/A */
302810SN/A
312810SN/A#include "base/bitfield.hh"
322810SN/A#include "debug/I8259.hh"
332810SN/A#include "dev/x86/i82094aa.hh"
342810SN/A#include "dev/x86/i8259.hh"
352810SN/A#include "mem/packet.hh"
362810SN/A#include "mem/packet_access.hh"
372810SN/A
382810SN/AX86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this),
392810SN/A                    latency(p->pio_latency), output(p->output),
402810SN/A                    mode(p->mode), slave(p->slave),
412810SN/A                    IRR(0), ISR(0), IMR(0),
422810SN/A                    readIRR(true), initControlWord(0), autoEOI(false)
432810SN/A{
442810SN/A    for (int i = 0; i < NumLines; i++)
452810SN/A        pinStates[i] = false;
462810SN/A    pioSize = 2;
472810SN/A}
488232Snate@binkert.org
499152Satgutier@umich.eduTick
509795Sandreas.hansson@arm.comX86ISA::I8259::read(PacketPtr pkt)
519795Sandreas.hansson@arm.com{
5210263Satgutier@umich.edu    assert(pkt->getSize() == 1);
535338Sstever@gmail.com    switch(pkt->getAddr() - pioAddr)
549795Sandreas.hansson@arm.com    {
555338Sstever@gmail.com      case 0x0:
568786Sgblack@eecs.umich.edu        if (readIRR) {
572810SN/A            DPRINTF(I8259, "Reading IRR as %#x.\n", IRR);
582810SN/A            pkt->set(IRR);
592810SN/A        } else {
608856Sandreas.hansson@arm.com            DPRINTF(I8259, "Reading ISR as %#x.\n", ISR);
618856Sandreas.hansson@arm.com            pkt->set(ISR);
628856Sandreas.hansson@arm.com        }
638922Swilliam.wang@arm.com        break;
648914Sandreas.hansson@arm.com      case 0x1:
658856Sandreas.hansson@arm.com        DPRINTF(I8259, "Reading IMR as %#x.\n", IMR);
668856Sandreas.hansson@arm.com        pkt->set(IMR);
674475SN/A        break;
685034SN/A    }
695034SN/A    pkt->makeAtomicResponse();
7010360Sandreas.hansson@arm.com    return latency;
7110622Smitch.hayenga@arm.com}
7210622Smitch.hayenga@arm.com
734628SN/ATick
749814Sandreas.hansson@arm.comX86ISA::I8259::write(PacketPtr pkt)
7510693SMarco.Balboni@ARM.com{
7610693SMarco.Balboni@ARM.com    assert(pkt->getSize() == 1);
7710693SMarco.Balboni@ARM.com    uint8_t val = pkt->get<uint8_t>();
789263Smrinmoy.ghosh@arm.com    switch (pkt->getAddr() - pioAddr) {
795034SN/A      case 0x0:
806122SSteve.Reinhardt@amd.com        if (bits(val, 4)) {
818134SAli.Saidi@ARM.com            DPRINTF(I8259, "Received initialization command word 1.\n");
824626SN/A            IMR = 0;
8310360Sandreas.hansson@arm.com            edgeTriggered = bits(val, 3);
844626SN/A            DPRINTF(I8259, "%s triggered mode.\n",
855034SN/A                    edgeTriggered ? "Edge" : "Level");
868883SAli.Saidi@ARM.com            cascadeMode = !bits(val, 1);
878833Sdam.sunwoo@arm.com            DPRINTF(I8259, "%s mode.\n",
884458SN/A                    cascadeMode ? "Cascade" : "Single");
892810SN/A            expectICW4 = bits(val, 0);
902810SN/A            if (!expectICW4) {
913013SN/A                autoEOI = false;
928856Sandreas.hansson@arm.com            }
932810SN/A            initControlWord = 1;
943013SN/A            DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2);
9510714Sandreas.hansson@arm.com        } else if (bits(val, 4, 3) == 0) {
962810SN/A            DPRINTF(I8259, "Received operation command word 2.\n");
979614Srene.dejong@arm.com            switch (bits(val, 7, 5)) {
989614Srene.dejong@arm.com              case 0x0:
999614Srene.dejong@arm.com                DPRINTF(I8259,
10010345SCurtis.Dunham@arm.com                        "Subcommand: Rotate in auto-EOI mode (clear).\n");
10110714Sandreas.hansson@arm.com                break;
10210345SCurtis.Dunham@arm.com              case 0x1:
1039614Srene.dejong@arm.com                {
1042810SN/A                    int line = findMsbSet(ISR);
1052810SN/A                    DPRINTF(I8259, "Subcommand: Nonspecific EOI on line %d.\n",
1062810SN/A                            line);
1078856Sandreas.hansson@arm.com                    handleEOI(line);
1082810SN/A                }
1093013SN/A                break;
11010714Sandreas.hansson@arm.com              case 0x2:
1113013SN/A                DPRINTF(I8259, "Subcommand: No operation.\n");
1128856Sandreas.hansson@arm.com                break;
11310714Sandreas.hansson@arm.com              case 0x3:
1148922Swilliam.wang@arm.com                {
1152897SN/A                    int line = bits(val, 2, 0);
1162810SN/A                    DPRINTF(I8259, "Subcommand: Specific EIO on line %d.\n",
1172810SN/A                            line);
11810344Sandreas.hansson@arm.com                    handleEOI(line);
11910344Sandreas.hansson@arm.com                }
12010344Sandreas.hansson@arm.com                break;
12110714Sandreas.hansson@arm.com              case 0x4:
12210344Sandreas.hansson@arm.com                DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n");
12310344Sandreas.hansson@arm.com                break;
12410344Sandreas.hansson@arm.com              case 0x5:
12510713Sandreas.hansson@arm.com                DPRINTF(I8259, "Subcommand: Rotate on nonspecific EOI.\n");
12610344Sandreas.hansson@arm.com                break;
1272844SN/A              case 0x6:
1282810SN/A                DPRINTF(I8259, "Subcommand: Set priority command.\n");
1292858SN/A                DPRINTF(I8259, "Lowest: IRQ%d   Highest IRQ%d.\n",
1302858SN/A                        bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
1318856Sandreas.hansson@arm.com                break;
1328922Swilliam.wang@arm.com              case 0x7:
1338711Sandreas.hansson@arm.com                DPRINTF(I8259, "Subcommand: Rotate on specific EOI.\n");
1342858SN/A                DPRINTF(I8259, "Lowest: IRQ%d   Highest IRQ%d.\n",
1352858SN/A                        bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8);
1369294Sandreas.hansson@arm.com                break;
1379294Sandreas.hansson@arm.com            }
1388922Swilliam.wang@arm.com        } else if (bits(val, 4, 3) == 1) {
1398922Swilliam.wang@arm.com            DPRINTF(I8259, "Received operation command word 3.\n");
1408922Swilliam.wang@arm.com            if (bits(val, 7)) {
1418922Swilliam.wang@arm.com                DPRINTF(I8259, "%s special mask mode.\n",
1428922Swilliam.wang@arm.com                        bits(val, 6) ? "Set" : "Clear");
1438922Swilliam.wang@arm.com            }
1448922Swilliam.wang@arm.com            if (bits(val, 1)) {
1458922Swilliam.wang@arm.com                readIRR = bits(val, 0);
1469294Sandreas.hansson@arm.com                DPRINTF(I8259, "Read %s.\n", readIRR ? "IRR" : "ISR");
1479294Sandreas.hansson@arm.com            }
1488922Swilliam.wang@arm.com        }
1498922Swilliam.wang@arm.com        break;
1508922Swilliam.wang@arm.com      case 0x1:
1518922Swilliam.wang@arm.com        switch (initControlWord) {
1528922Swilliam.wang@arm.com          case 0x0:
1538922Swilliam.wang@arm.com            DPRINTF(I8259, "Received operation command word 1.\n");
1548922Swilliam.wang@arm.com            DPRINTF(I8259, "Wrote IMR value %#x.\n", val);
1554628SN/A            IMR = val;
1562858SN/A            break;
1572810SN/A          case 0x1:
1582810SN/A            DPRINTF(I8259, "Received initialization command word 2.\n");
1592810SN/A            vectorOffset = val & ~mask(3);
1602810SN/A            DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n",
1612810SN/A                    vectorOffset, vectorOffset | mask(3));
1624022SN/A            if (cascadeMode) {
1634022SN/A                initControlWord++;
1644022SN/A            } else {
1652810SN/A                cascadeBits = 0;
1662810SN/A                initControlWord = 0;
1678833Sdam.sunwoo@arm.com            }
1682810SN/A            break;
1692810SN/A          case 0x2:
1702810SN/A            DPRINTF(I8259, "Received initialization command word 3.\n");
1712810SN/A            if (mode == Enums::I8259Master) {
1728833Sdam.sunwoo@arm.com                DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n",
1738833Sdam.sunwoo@arm.com                        bits(val, 0) ? " 0" : "",
1748833Sdam.sunwoo@arm.com                        bits(val, 1) ? " 1" : "",
1752810SN/A                        bits(val, 2) ? " 2" : "",
1762810SN/A                        bits(val, 3) ? " 3" : "",
1774871SN/A                        bits(val, 4) ? " 4" : "",
1784871SN/A                        bits(val, 5) ? " 5" : "",
1794871SN/A                        bits(val, 6) ? " 6" : "",
1804871SN/A                        bits(val, 7) ? " 7" : "");
1814871SN/A                cascadeBits = val;
1824871SN/A            } else {
1834871SN/A                DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3));
1844871SN/A                cascadeBits = val & mask(3);
1854871SN/A            }
1864871SN/A            if (expectICW4)
1872810SN/A                initControlWord++;
1882810SN/A            else
1892810SN/A                initControlWord = 0;
1908833Sdam.sunwoo@arm.com            break;
1912810SN/A          case 0x3:
1924871SN/A            DPRINTF(I8259, "Received initialization command word 4.\n");
1938833Sdam.sunwoo@arm.com            if (bits(val, 4)) {
1948833Sdam.sunwoo@arm.com                DPRINTF(I8259, "Special fully nested mode.\n");
1958833Sdam.sunwoo@arm.com            } else {
1962810SN/A                DPRINTF(I8259, "Not special fully nested mode.\n");
1972810SN/A            }
1982810SN/A            if (bits(val, 3) == 0) {
1992810SN/A                DPRINTF(I8259, "Nonbuffered.\n");
2008833Sdam.sunwoo@arm.com            } else if (bits(val, 2) == 0) {
2012810SN/A                DPRINTF(I8259, "Buffered.\n");
2024871SN/A            } else {
2038833Sdam.sunwoo@arm.com                DPRINTF(I8259, "Unrecognized buffer mode.\n");
2048833Sdam.sunwoo@arm.com            }
2058833Sdam.sunwoo@arm.com            autoEOI = bits(val, 1);
2062810SN/A            DPRINTF(I8259, "%s End Of Interrupt.\n",
2072810SN/A                    autoEOI ? "Automatic" : "Normal");
2084022SN/A
2094022SN/A            DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85");
2104022SN/A            initControlWord = 0;
2112810SN/A            break;
2122810SN/A        }
2138833Sdam.sunwoo@arm.com        break;
2142810SN/A    }
2152810SN/A    pkt->makeAtomicResponse();
2162810SN/A    return latency;
2172810SN/A}
2188833Sdam.sunwoo@arm.com
2198833Sdam.sunwoo@arm.comvoid
2208833Sdam.sunwoo@arm.comX86ISA::I8259::handleEOI(int line)
2212810SN/A{
2222810SN/A    ISR &= ~(1 << line);
2232810SN/A    // There may be an interrupt that was waiting which can
2242810SN/A    // now be sent.
2252810SN/A    if (IRR)
2268833Sdam.sunwoo@arm.com        requestInterrupt(findMsbSet(IRR));
2272810SN/A}
2284871SN/A
2298833Sdam.sunwoo@arm.comvoid
2308833Sdam.sunwoo@arm.comX86ISA::I8259::requestInterrupt(int line)
2318833Sdam.sunwoo@arm.com{
2322810SN/A    if (bits(ISR, 7, line) == 0) {
2332810SN/A        if (output) {
2342810SN/A            DPRINTF(I8259, "Propogating interrupt.\n");
2352810SN/A            output->raise();
2368833Sdam.sunwoo@arm.com            //XXX This is a hack.
2372810SN/A            output->lower();
2384871SN/A        } else {
2398833Sdam.sunwoo@arm.com            warn("Received interrupt but didn't have "
2408833Sdam.sunwoo@arm.com                    "anyone to tell about it.\n");
2418833Sdam.sunwoo@arm.com        }
2422810SN/A    }
2432810SN/A}
2444022SN/A
2454022SN/Avoid
2464022SN/AX86ISA::I8259::signalInterrupt(int line)
2472810SN/A{
2482810SN/A    DPRINTF(I8259, "Interrupt requested for line %d.\n", line);
2498833Sdam.sunwoo@arm.com    if (line >= NumLines)
2502810SN/A        fatal("Line number %d doesn't exist. The max is %d.\n",
2512810SN/A                line, NumLines - 1);
2522810SN/A    if (bits(IMR, line)) {
2532810SN/A        DPRINTF(I8259, "Interrupt %d was masked.\n", line);
2548833Sdam.sunwoo@arm.com    } else {
2558833Sdam.sunwoo@arm.com        IRR |= 1 << line;
2568833Sdam.sunwoo@arm.com        requestInterrupt(line);
2572810SN/A    }
2582810SN/A}
2592810SN/A
2602810SN/Avoid
2612810SN/AX86ISA::I8259::raiseInterruptPin(int number)
2628833Sdam.sunwoo@arm.com{
2632810SN/A    DPRINTF(I8259, "Interrupt signal raised for pin %d.\n", number);
2644871SN/A    if (number >= NumLines)
2658833Sdam.sunwoo@arm.com        fatal("Line number %d doesn't exist. The max is %d.\n",
2668833Sdam.sunwoo@arm.com                number, NumLines - 1);
2678833Sdam.sunwoo@arm.com    if (!pinStates[number])
2682810SN/A        signalInterrupt(number);
2692810SN/A    pinStates[number] = true;
2702810SN/A}
2712810SN/A
2728833Sdam.sunwoo@arm.comvoid
2732810SN/AX86ISA::I8259::lowerInterruptPin(int number)
2744871SN/A{
2758833Sdam.sunwoo@arm.com    DPRINTF(I8259, "Interrupt signal lowered for pin %d.\n", number);
2768833Sdam.sunwoo@arm.com    if (number >= NumLines)
2778833Sdam.sunwoo@arm.com        fatal("Line number %d doesn't exist. The max is %d.\n",
2782810SN/A                number, NumLines - 1);
2792810SN/A    pinStates[number] = false;
2804022SN/A}
2814022SN/A
2824022SN/Aint
2832810SN/AX86ISA::I8259::getVector()
2842810SN/A{
2852810SN/A    /*
2862810SN/A     * This code only handles one slave. Since that's how the PC platform
2872810SN/A     * always uses the 8259 PIC, there shouldn't be any need for more. If
2882810SN/A     * there -is- a need for more for some reason, "slave" can become a
2898833Sdam.sunwoo@arm.com     * vector of slaves.
2902810SN/A     */
2918833Sdam.sunwoo@arm.com    int line = findMsbSet(IRR);
2928833Sdam.sunwoo@arm.com    IRR &= ~(1 << line);
2938833Sdam.sunwoo@arm.com    DPRINTF(I8259, "Interrupt %d was accepted.\n", line);
2942810SN/A    if (autoEOI) {
2952810SN/A        handleEOI(line);
2962810SN/A    } else {
2972810SN/A        ISR |= 1 << line;
2982810SN/A    }
2998833Sdam.sunwoo@arm.com    if (slave && bits(cascadeBits, line)) {
3002810SN/A        DPRINTF(I8259, "Interrupt was from slave who will "
3012810SN/A                "provide the vector.\n");
3028833Sdam.sunwoo@arm.com        return slave->getVector();
3038833Sdam.sunwoo@arm.com    }
3048833Sdam.sunwoo@arm.com    return line | vectorOffset;
3052810SN/A}
3062810SN/A
3072810SN/Avoid
3082810SN/AX86ISA::I8259::serialize(std::ostream &os)
3098833Sdam.sunwoo@arm.com{
3102810SN/A    SERIALIZE_ARRAY(pinStates, NumLines);
3112810SN/A    SERIALIZE_ENUM(mode);
3128833Sdam.sunwoo@arm.com    SERIALIZE_SCALAR(IRR);
3138833Sdam.sunwoo@arm.com    SERIALIZE_SCALAR(ISR);
3148833Sdam.sunwoo@arm.com    SERIALIZE_SCALAR(IMR);
3152810SN/A    SERIALIZE_SCALAR(vectorOffset);
3162810SN/A    SERIALIZE_SCALAR(cascadeMode);
3174022SN/A    SERIALIZE_SCALAR(cascadeBits);
3184022SN/A    SERIALIZE_SCALAR(edgeTriggered);
3194022SN/A    SERIALIZE_SCALAR(readIRR);
3202810SN/A    SERIALIZE_SCALAR(expectICW4);
3212810SN/A    SERIALIZE_SCALAR(initControlWord);
3222810SN/A    SERIALIZE_SCALAR(autoEOI);
3232810SN/A}
3242810SN/A
3252810SN/Avoid
3268833Sdam.sunwoo@arm.comX86ISA::I8259::unserialize(Checkpoint *cp, const std::string &section)
3272810SN/A{
3288833Sdam.sunwoo@arm.com    UNSERIALIZE_ARRAY(pinStates, NumLines);
3298833Sdam.sunwoo@arm.com    UNSERIALIZE_ENUM(mode);
3308833Sdam.sunwoo@arm.com    UNSERIALIZE_SCALAR(IRR);
3312810SN/A    UNSERIALIZE_SCALAR(ISR);
3322810SN/A    UNSERIALIZE_SCALAR(IMR);
3332810SN/A    UNSERIALIZE_SCALAR(vectorOffset);
3342810SN/A    UNSERIALIZE_SCALAR(cascadeMode);
3352810SN/A    UNSERIALIZE_SCALAR(cascadeBits);
3368833Sdam.sunwoo@arm.com    UNSERIALIZE_SCALAR(edgeTriggered);
3372810SN/A    UNSERIALIZE_SCALAR(readIRR);
3382810SN/A    UNSERIALIZE_SCALAR(expectICW4);
3398833Sdam.sunwoo@arm.com    UNSERIALIZE_SCALAR(initControlWord);
3408833Sdam.sunwoo@arm.com    UNSERIALIZE_SCALAR(autoEOI);
3418833Sdam.sunwoo@arm.com}
3422810SN/A
3432810SN/AX86ISA::I8259 *
3442810SN/AI8259Params::create()
3452810SN/A{
3468833Sdam.sunwoo@arm.com    return new X86ISA::I8259(this);
3472810SN/A}
3482810SN/A