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