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 §ion) 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