i8259.cc revision 13229:b45254f2733a
16313Sgblack@eecs.umich.edu/* 26313Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 36313Sgblack@eecs.umich.edu * All rights reserved. 46313Sgblack@eecs.umich.edu * 56313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 66313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 76313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 86313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 96313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 106313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 116313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 126313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 136313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu * 286313Sgblack@eecs.umich.edu * Authors: Gabe Black 296313Sgblack@eecs.umich.edu */ 306313Sgblack@eecs.umich.edu 316313Sgblack@eecs.umich.edu#include "dev/x86/i8259.hh" 326313Sgblack@eecs.umich.edu 336313Sgblack@eecs.umich.edu#include "base/bitfield.hh" 348229Snate@binkert.org#include "debug/I8259.hh" 358229Snate@binkert.org#include "dev/x86/i82094aa.hh" 368229Snate@binkert.org#include "mem/packet.hh" 376335Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 386313Sgblack@eecs.umich.edu 396335Sgblack@eecs.umich.eduX86ISA::I8259::I8259(Params * p) 409384SAndreas.Sandberg@arm.com : BasicPioDevice(p, 2), IntDevice(this), 416335Sgblack@eecs.umich.edu latency(p->pio_latency), output(p->output), 426313Sgblack@eecs.umich.edu mode(p->mode), slave(p->slave), 436313Sgblack@eecs.umich.edu IRR(0), ISR(0), IMR(0), 449384SAndreas.Sandberg@arm.com readIRR(true), initControlWord(0), autoEOI(false) 456335Sgblack@eecs.umich.edu{ 466313Sgblack@eecs.umich.edu for (int i = 0; i < NumLines; i++) 476313Sgblack@eecs.umich.edu pinStates[i] = false; 486313Sgblack@eecs.umich.edu} 499384SAndreas.Sandberg@arm.com 507741Sgblack@eecs.umich.eduTick 517741Sgblack@eecs.umich.eduX86ISA::I8259::read(PacketPtr pkt) 526335Sgblack@eecs.umich.edu{ 537741Sgblack@eecs.umich.edu assert(pkt->getSize() == 1); 547741Sgblack@eecs.umich.edu switch(pkt->getAddr() - pioAddr) 557741Sgblack@eecs.umich.edu { 567741Sgblack@eecs.umich.edu case 0x0: 577741Sgblack@eecs.umich.edu if (readIRR) { 587741Sgblack@eecs.umich.edu DPRINTF(I8259, "Reading IRR as %#x.\n", IRR); 597741Sgblack@eecs.umich.edu pkt->setLE(IRR); 607741Sgblack@eecs.umich.edu } else { 617741Sgblack@eecs.umich.edu DPRINTF(I8259, "Reading ISR as %#x.\n", ISR); 627741Sgblack@eecs.umich.edu pkt->setLE(ISR); 637741Sgblack@eecs.umich.edu } 646335Sgblack@eecs.umich.edu break; 656335Sgblack@eecs.umich.edu case 0x1: 667741Sgblack@eecs.umich.edu DPRINTF(I8259, "Reading IMR as %#x.\n", IMR); 677741Sgblack@eecs.umich.edu pkt->setLE(IMR); 687741Sgblack@eecs.umich.edu break; 697741Sgblack@eecs.umich.edu } 707741Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 717741Sgblack@eecs.umich.edu return latency; 727741Sgblack@eecs.umich.edu} 737741Sgblack@eecs.umich.edu 747741Sgblack@eecs.umich.eduTick 756335Sgblack@eecs.umich.eduX86ISA::I8259::write(PacketPtr pkt) 768829Sgblack@eecs.umich.edu{ 777741Sgblack@eecs.umich.edu assert(pkt->getSize() == 1); 787741Sgblack@eecs.umich.edu uint8_t val = pkt->getLE<uint8_t>(); 797741Sgblack@eecs.umich.edu switch (pkt->getAddr() - pioAddr) { 807741Sgblack@eecs.umich.edu case 0x0: 817741Sgblack@eecs.umich.edu if (bits(val, 4)) { 827741Sgblack@eecs.umich.edu DPRINTF(I8259, "Received initialization command word 1.\n"); 837741Sgblack@eecs.umich.edu IMR = 0; 847741Sgblack@eecs.umich.edu edgeTriggered = bits(val, 3); 857741Sgblack@eecs.umich.edu DPRINTF(I8259, "%s triggered mode.\n", 866335Sgblack@eecs.umich.edu edgeTriggered ? "Edge" : "Level"); 877741Sgblack@eecs.umich.edu cascadeMode = !bits(val, 1); 888829Sgblack@eecs.umich.edu DPRINTF(I8259, "%s mode.\n", 897741Sgblack@eecs.umich.edu cascadeMode ? "Cascade" : "Single"); 907741Sgblack@eecs.umich.edu expectICW4 = bits(val, 0); 917741Sgblack@eecs.umich.edu if (!expectICW4) { 927741Sgblack@eecs.umich.edu autoEOI = false; 936335Sgblack@eecs.umich.edu } 947741Sgblack@eecs.umich.edu initControlWord = 1; 956335Sgblack@eecs.umich.edu DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2); 967741Sgblack@eecs.umich.edu } else if (bits(val, 4, 3) == 0) { 977741Sgblack@eecs.umich.edu DPRINTF(I8259, "Received operation command word 2.\n"); 986335Sgblack@eecs.umich.edu switch (bits(val, 7, 5)) { 997741Sgblack@eecs.umich.edu case 0x0: 1007741Sgblack@eecs.umich.edu DPRINTF(I8259, 1017741Sgblack@eecs.umich.edu "Subcommand: Rotate in auto-EOI mode (clear).\n"); 1027741Sgblack@eecs.umich.edu break; 1037741Sgblack@eecs.umich.edu case 0x1: 1046335Sgblack@eecs.umich.edu { 1057741Sgblack@eecs.umich.edu int line = findMsbSet(ISR); 1066335Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Nonspecific EOI on line %d.\n", 1077741Sgblack@eecs.umich.edu line); 1087741Sgblack@eecs.umich.edu handleEOI(line); 1097741Sgblack@eecs.umich.edu } 1107741Sgblack@eecs.umich.edu break; 1117741Sgblack@eecs.umich.edu case 0x2: 1127741Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: No operation.\n"); 1137741Sgblack@eecs.umich.edu break; 1147741Sgblack@eecs.umich.edu case 0x3: 1156335Sgblack@eecs.umich.edu { 1167741Sgblack@eecs.umich.edu int line = bits(val, 2, 0); 1177741Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Specific EIO on line %d.\n", 1187741Sgblack@eecs.umich.edu line); 1197741Sgblack@eecs.umich.edu handleEOI(line); 1206335Sgblack@eecs.umich.edu } 1217741Sgblack@eecs.umich.edu break; 1227741Sgblack@eecs.umich.edu case 0x4: 1236335Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n"); 1247741Sgblack@eecs.umich.edu break; 1257741Sgblack@eecs.umich.edu case 0x5: 1267741Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Rotate on nonspecific EOI.\n"); 1277741Sgblack@eecs.umich.edu break; 1287741Sgblack@eecs.umich.edu case 0x6: 1296335Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Set priority command.\n"); 1307741Sgblack@eecs.umich.edu DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n", 1317741Sgblack@eecs.umich.edu bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8); 1327741Sgblack@eecs.umich.edu break; 1336335Sgblack@eecs.umich.edu case 0x7: 1347741Sgblack@eecs.umich.edu DPRINTF(I8259, "Subcommand: Rotate on specific EOI.\n"); 1357741Sgblack@eecs.umich.edu DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n", 1367741Sgblack@eecs.umich.edu bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8); 1376335Sgblack@eecs.umich.edu break; 1387741Sgblack@eecs.umich.edu } 1397741Sgblack@eecs.umich.edu } else if (bits(val, 4, 3) == 1) { 1407741Sgblack@eecs.umich.edu DPRINTF(I8259, "Received operation command word 3.\n"); 1416337Sgblack@eecs.umich.edu if (bits(val, 7)) { 1427741Sgblack@eecs.umich.edu DPRINTF(I8259, "%s special mask mode.\n", 1437741Sgblack@eecs.umich.edu bits(val, 6) ? "Set" : "Clear"); 1447741Sgblack@eecs.umich.edu } 1456337Sgblack@eecs.umich.edu if (bits(val, 1)) { 1467741Sgblack@eecs.umich.edu readIRR = bits(val, 0); 1477741Sgblack@eecs.umich.edu DPRINTF(I8259, "Read %s.\n", readIRR ? "IRR" : "ISR"); 1487741Sgblack@eecs.umich.edu } 1496337Sgblack@eecs.umich.edu } 1507741Sgblack@eecs.umich.edu break; 1517741Sgblack@eecs.umich.edu case 0x1: 1527741Sgblack@eecs.umich.edu switch (initControlWord) { 1537741Sgblack@eecs.umich.edu case 0x0: 1547741Sgblack@eecs.umich.edu DPRINTF(I8259, "Received operation command word 1.\n"); 1557741Sgblack@eecs.umich.edu DPRINTF(I8259, "Wrote IMR value %#x.\n", val); 1567741Sgblack@eecs.umich.edu IMR = val; 1577741Sgblack@eecs.umich.edu break; 1587741Sgblack@eecs.umich.edu case 0x1: 1597741Sgblack@eecs.umich.edu DPRINTF(I8259, "Received initialization command word 2.\n"); 1606337Sgblack@eecs.umich.edu vectorOffset = val & ~mask(3); 1617741Sgblack@eecs.umich.edu DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n", 1627741Sgblack@eecs.umich.edu vectorOffset, vectorOffset | mask(3)); 1637741Sgblack@eecs.umich.edu if (cascadeMode) { 1647741Sgblack@eecs.umich.edu initControlWord++; 1656337Sgblack@eecs.umich.edu } else { 1667741Sgblack@eecs.umich.edu cascadeBits = 0; 1676335Sgblack@eecs.umich.edu initControlWord = 0; 1687741Sgblack@eecs.umich.edu } 1696335Sgblack@eecs.umich.edu break; 1709425SAndreas.Sandberg@ARM.com case 0x2: 1716335Sgblack@eecs.umich.edu DPRINTF(I8259, "Received initialization command word 3.\n"); 1729425SAndreas.Sandberg@ARM.com if (mode == Enums::I8259Master) { 1736335Sgblack@eecs.umich.edu DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n", 1749461Snilay@cs.wisc.edu bits(val, 0) ? " 0" : "", 1759461Snilay@cs.wisc.edu bits(val, 1) ? " 1" : "", 1769553Sandreas.hansson@arm.com bits(val, 2) ? " 2" : "", 1779553Sandreas.hansson@arm.com bits(val, 3) ? " 3" : "", 1789553Sandreas.hansson@arm.com bits(val, 4) ? " 4" : "", 1797741Sgblack@eecs.umich.edu bits(val, 5) ? " 5" : "", 1806335Sgblack@eecs.umich.edu bits(val, 6) ? " 6" : "", 1818829Sgblack@eecs.umich.edu bits(val, 7) ? " 7" : ""); 1828829Sgblack@eecs.umich.edu cascadeBits = val; 1837741Sgblack@eecs.umich.edu } else { 1846313Sgblack@eecs.umich.edu DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3)); 1857741Sgblack@eecs.umich.edu cascadeBits = val & mask(3); 1866313Sgblack@eecs.umich.edu } 1877741Sgblack@eecs.umich.edu if (expectICW4) 1887741Sgblack@eecs.umich.edu initControlWord++; 1896313Sgblack@eecs.umich.edu else 1907741Sgblack@eecs.umich.edu initControlWord = 0; 1917741Sgblack@eecs.umich.edu break; 1927741Sgblack@eecs.umich.edu case 0x3: 1936313Sgblack@eecs.umich.edu DPRINTF(I8259, "Received initialization command word 4.\n"); 1947741Sgblack@eecs.umich.edu if (bits(val, 4)) { 1957741Sgblack@eecs.umich.edu DPRINTF(I8259, "Special fully nested mode.\n"); 1967741Sgblack@eecs.umich.edu } else { 1977741Sgblack@eecs.umich.edu DPRINTF(I8259, "Not special fully nested mode.\n"); 1987741Sgblack@eecs.umich.edu } 1997741Sgblack@eecs.umich.edu if (bits(val, 3) == 0) { 2007741Sgblack@eecs.umich.edu DPRINTF(I8259, "Nonbuffered.\n"); 2017741Sgblack@eecs.umich.edu } else if (bits(val, 2) == 0) { 2026313Sgblack@eecs.umich.edu DPRINTF(I8259, "Buffered.\n"); 2037741Sgblack@eecs.umich.edu } else { 2047741Sgblack@eecs.umich.edu DPRINTF(I8259, "Unrecognized buffer mode.\n"); 2057741Sgblack@eecs.umich.edu } 2067741Sgblack@eecs.umich.edu autoEOI = bits(val, 1); 2077741Sgblack@eecs.umich.edu DPRINTF(I8259, "%s End Of Interrupt.\n", 2086313Sgblack@eecs.umich.edu autoEOI ? "Automatic" : "Normal"); 2099920Syasuko.eckert@amd.com 2109920Syasuko.eckert@amd.com DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85"); 2119920Syasuko.eckert@amd.com initControlWord = 0; 2129920Syasuko.eckert@amd.com break; 2139920Syasuko.eckert@amd.com } 2149920Syasuko.eckert@amd.com break; 2159920Syasuko.eckert@amd.com } 2169384SAndreas.Sandberg@arm.com pkt->makeAtomicResponse(); 2179384SAndreas.Sandberg@arm.com return latency; 2187703Sgblack@eecs.umich.edu} 2199384SAndreas.Sandberg@arm.com 2207741Sgblack@eecs.umich.eduvoid 2216313Sgblack@eecs.umich.eduX86ISA::I8259::handleEOI(int line) 2226313Sgblack@eecs.umich.edu{ 2236313Sgblack@eecs.umich.edu ISR &= ~(1 << line); 224 // There may be an interrupt that was waiting which can 225 // now be sent. 226 if (IRR) 227 requestInterrupt(findMsbSet(IRR)); 228} 229 230void 231X86ISA::I8259::requestInterrupt(int line) 232{ 233 if (bits(ISR, 7, line) == 0) { 234 if (output) { 235 DPRINTF(I8259, "Propogating interrupt.\n"); 236 output->raise(); 237 //XXX This is a hack. 238 output->lower(); 239 } else { 240 warn("Received interrupt but didn't have " 241 "anyone to tell about it.\n"); 242 } 243 } 244} 245 246void 247X86ISA::I8259::signalInterrupt(int line) 248{ 249 DPRINTF(I8259, "Interrupt requested for line %d.\n", line); 250 if (line >= NumLines) 251 fatal("Line number %d doesn't exist. The max is %d.\n", 252 line, NumLines - 1); 253 if (bits(IMR, line)) { 254 DPRINTF(I8259, "Interrupt %d was masked.\n", line); 255 } else { 256 IRR |= 1 << line; 257 requestInterrupt(line); 258 } 259} 260 261void 262X86ISA::I8259::raiseInterruptPin(int number) 263{ 264 DPRINTF(I8259, "Interrupt signal raised for pin %d.\n", number); 265 if (number >= NumLines) 266 fatal("Line number %d doesn't exist. The max is %d.\n", 267 number, NumLines - 1); 268 if (!pinStates[number]) 269 signalInterrupt(number); 270 pinStates[number] = true; 271} 272 273void 274X86ISA::I8259::lowerInterruptPin(int number) 275{ 276 DPRINTF(I8259, "Interrupt signal lowered for pin %d.\n", number); 277 if (number >= NumLines) 278 fatal("Line number %d doesn't exist. The max is %d.\n", 279 number, NumLines - 1); 280 pinStates[number] = false; 281} 282 283int 284X86ISA::I8259::getVector() 285{ 286 /* 287 * This code only handles one slave. Since that's how the PC platform 288 * always uses the 8259 PIC, there shouldn't be any need for more. If 289 * there -is- a need for more for some reason, "slave" can become a 290 * vector of slaves. 291 */ 292 int line = findMsbSet(IRR); 293 IRR &= ~(1 << line); 294 DPRINTF(I8259, "Interrupt %d was accepted.\n", line); 295 if (autoEOI) { 296 handleEOI(line); 297 } else { 298 ISR |= 1 << line; 299 } 300 if (slave && bits(cascadeBits, line)) { 301 DPRINTF(I8259, "Interrupt was from slave who will " 302 "provide the vector.\n"); 303 return slave->getVector(); 304 } 305 return line | vectorOffset; 306} 307 308void 309X86ISA::I8259::serialize(CheckpointOut &cp) const 310{ 311 SERIALIZE_ARRAY(pinStates, NumLines); 312 SERIALIZE_ENUM(mode); 313 SERIALIZE_SCALAR(IRR); 314 SERIALIZE_SCALAR(ISR); 315 SERIALIZE_SCALAR(IMR); 316 SERIALIZE_SCALAR(vectorOffset); 317 SERIALIZE_SCALAR(cascadeMode); 318 SERIALIZE_SCALAR(cascadeBits); 319 SERIALIZE_SCALAR(edgeTriggered); 320 SERIALIZE_SCALAR(readIRR); 321 SERIALIZE_SCALAR(expectICW4); 322 SERIALIZE_SCALAR(initControlWord); 323 SERIALIZE_SCALAR(autoEOI); 324} 325 326void 327X86ISA::I8259::unserialize(CheckpointIn &cp) 328{ 329 UNSERIALIZE_ARRAY(pinStates, NumLines); 330 UNSERIALIZE_ENUM(mode); 331 UNSERIALIZE_SCALAR(IRR); 332 UNSERIALIZE_SCALAR(ISR); 333 UNSERIALIZE_SCALAR(IMR); 334 UNSERIALIZE_SCALAR(vectorOffset); 335 UNSERIALIZE_SCALAR(cascadeMode); 336 UNSERIALIZE_SCALAR(cascadeBits); 337 UNSERIALIZE_SCALAR(edgeTriggered); 338 UNSERIALIZE_SCALAR(readIRR); 339 UNSERIALIZE_SCALAR(expectICW4); 340 UNSERIALIZE_SCALAR(initControlWord); 341 UNSERIALIZE_SCALAR(autoEOI); 342} 343 344X86ISA::I8259 * 345I8259Params::create() 346{ 347 return new X86ISA::I8259(this); 348} 349