from m5.params import *
from m5.proxy import *
from Device import BasicPioDevice
+from I8259 import I8259
class Cmos(BasicPioDevice):
type = 'Cmos'
time = Param.Time('01/01/2009',
"System time to use ('Now' for actual time)")
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
+ i8259 = Param.I8259('PIC to send RTC alarm interrupts to')
+ int_line = Param.Int(0,
+ 'PIC relative interrupt line to use for alarm interrupts')
type = 'I8259'
cxx_class='X86ISA::I8259'
pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
- master = Param.Bool(True, 'If this PIC is the master or slave')
+ master = Param.I8259('The master PIC this PIC is cascaded with, if any')
pciconfig = PciConfigAll()
south_bridge = SouthBridge()
- cmos = Cmos(pio_addr=x86IOAddress(0x70))
- pic1 = I8259(pio_addr=x86IOAddress(0x20), master=True)
- pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=False)
+ pic1 = I8259(pio_addr=x86IOAddress(0x20))
+ pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=pic1)
+ cmos = Cmos(pio_addr=x86IOAddress(0x70), i8259=pic2)
# "Non-existant" port used for timing purposes by the linux kernel
i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1)
*/
#include "dev/x86/cmos.hh"
+#include "dev/x86/i8259.hh"
#include "mem/packet_access.hh"
+void
+X86ISA::Cmos::X86RTC::handleEvent()
+{
+ i8259->signalInterrupt(intLine);
+}
+
Tick
X86ISA::Cmos::read(PacketPtr pkt)
{
namespace X86ISA
{
+class I8259;
+
class Cmos : public BasicPioDevice
{
protected:
class X86RTC : public MC146818
{
+ protected:
+ I8259 * i8259;
+ int intLine;
public:
X86RTC(EventManager *em, const std::string &n, const struct tm time,
- bool bcd, Tick frequency) :
- MC146818(em, n, time, bcd, frequency)
+ bool bcd, Tick frequency, I8259 *_i8259, int _intLine) :
+ MC146818(em, n, time, bcd, frequency),
+ i8259(_i8259), intLine(_intLine)
{
}
protected:
- void handleEvent()
- {
- return;
- }
+ void handleEvent();
} rtc;
public:
typedef CmosParams Params;
Cmos(const Params *p) : BasicPioDevice(p), latency(p->pio_latency),
- rtc(this, "rtc", p->time, true, ULL(5000000000))
+ rtc(this, "rtc", p->time, true, ULL(5000000000),
+ p->i8259, p->int_line)
{
pioSize = 2;
memset(regs, 0, numRegs * sizeof(uint8_t));
if (cascadeMode) {
initControlWord++;
} else {
+ cascadeBits = 0;
initControlWord = 0;
}
break;
case 0x2:
DPRINTF(I8259, "Received initialization command word 3.\n");
- if (master) {
+ if (master == NULL) {
DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n",
bits(val, 0) ? " 0" : "",
bits(val, 1) ? " 1" : "",
bits(val, 5) ? " 5" : "",
bits(val, 6) ? " 6" : "",
bits(val, 7) ? " 7" : "");
+ cascadeBits = val;
} else {
DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3));
+ cascadeBits = val & mask(3);
}
if (expectICW4)
initControlWord++;
return latency;
}
+void
+X86ISA::I8259::signalInterrupt(int line)
+{
+ DPRINTF(I8259, "Interrupt raised on line %d.\n", line);
+ if (line > 7)
+ fatal("Line number %d doesn't exist. The max is 7.\n");
+ if (bits(IMR, line)) {
+ DPRINTF(I8259, "Interrupt %d was masked.\n", line);
+ } else if (master != NULL) {
+ DPRINTF(I8259, "Propogating interrupt to master.\n");
+ master->signalInterrupt(cascadeBits);
+ }
+}
+
X86ISA::I8259 *
I8259Params::create()
{
{
protected:
Tick latency;
- bool master;
+ I8259 *master;
// Interrupt Request Register
uint8_t IRR;
// Interrupt Mask Register
uint8_t IMR;
- bool edgeTriggered;
bool cascadeMode;
- bool expectICW4;
+ // A bit vector of lines with slaves attached, or the slave id, depending
+ // on if this is a master or slave PIC.
+ uint8_t cascadeBits;
+
+ bool edgeTriggered;
bool readIRR;
+
+ // State machine information for reading in initialization control words.
+ bool expectICW4;
int initControlWord;
public:
Tick read(PacketPtr pkt);
Tick write(PacketPtr pkt);
+
+ void signalInterrupt(int line);
};
}; // namespace X86ISA