X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Falpha%2Ftsunami_io.cc;h=0c1937a3288ef611bade5ddf1e650df91748db31;hb=eddac53ff60c579eff28134bde84783fe36d6214;hp=d701dc98f27144110609d9b9ef200833a5d79695;hpb=73dd0ea35716b90c8448d729273cc153888a223b;p=gem5.git diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index d701dc98f..0c1937a32 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -40,444 +40,33 @@ #include #include +#include "base/time.hh" #include "base/trace.hh" -#include "dev/pitreg.h" -#include "dev/rtcreg.h" -#include "dev/alpha/tsunami_cchip.hh" +#include "config/the_isa.hh" +#include "debug/Tsunami.hh" #include "dev/alpha/tsunami.hh" +#include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami_io.hh" #include "dev/alpha/tsunamireg.h" +#include "dev/rtcreg.h" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/port.hh" -#include "sim/builder.hh" #include "sim/system.hh" using namespace std; //Should this be AlphaISA? using namespace TheISA; -TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, const vector &t, - bool bcd, Tick i) - : _name(n), event(tsunami, i), addr(0), year_is_bcd(bcd) -{ - memset(clock_data, 0, sizeof(clock_data)); - stat_regA = RTCA_32768HZ | RTCA_1024HZ; - stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; - - if (year_is_bcd) { - // The RTC uses BCD for the last two digits in the year. - // They python year is a full year. - int _year = t[0] % 100; - int tens = _year / 10; - int ones = _year % 10; - - year = (tens << 4) + ones; - } else { - // Even though the datasheet says that the year field should be - // interpreted as BCD, we just enter the number of years since - // 1900 since linux seems to be happy with that (and I believe - // that Tru64 was as well) - year = t[0] - 1900; - } - - mon = t[1]; - mday = t[2]; - hour = t[3]; - min = t[4]; - sec = t[5]; - - // wday is defined to be in the range from 1 - 7 with 1 being Sunday. - // the value coming from python is in the range from 0 - 6 with 0 being - // Monday. Fix that here. - wday = t[6] + 2; - if (wday > 7) - wday -= 7; - - DPRINTFN("Real-time clock set to %s", getDateString()); -} - -std::string -TsunamiIO::RTC::getDateString() -{ - struct tm tm; - - memset(&tm, 0, sizeof(tm)); - - if (year_is_bcd) { - // undo the BCD and conver to years since 1900 guessing that - // anything before 1970 is actually after 2000 - int _year = (year >> 4) * 10 + (year & 0xf); - if (_year < 70) - _year += 100; - - tm.tm_year = _year; - } else { - // number of years since 1900 - tm.tm_year = year; - } - - // unix is 0-11 for month - tm.tm_mon = mon - 1; - tm.tm_mday = mday; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - // to add more annoyance unix is 0 - 6 with 0 as sunday - tm.tm_wday = wday - 1; - - return asctime(&tm); -} - -void -TsunamiIO::RTC::writeAddr(const uint8_t data) -{ - if (data <= RTC_STAT_REGD) - addr = data; - else - panic("RTC addresses over 0xD are not implemented.\n"); -} - -void -TsunamiIO::RTC::writeData(const uint8_t data) -{ - if (addr < RTC_STAT_REGA) - clock_data[addr] = data; - else { - switch (addr) { - case RTC_STAT_REGA: - if (data != (RTCA_32768HZ | RTCA_1024HZ)) - panic("Unimplemented RTC register A value write!\n"); - stat_regA = data; - break; - case RTC_STAT_REGB: - if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) - panic("Write to RTC reg B bits that are not implemented!\n"); - - if (data & RTCB_PRDC_IE) { - if (!event.scheduled()) - event.scheduleIntr(); - } else { - if (event.scheduled()) - event.deschedule(); - } - stat_regB = data; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - panic("RTC status registers C and D are not implemented.\n"); - break; - } - } -} - -uint8_t -TsunamiIO::RTC::readData() -{ - if (addr < RTC_STAT_REGA) - return clock_data[addr]; - else { - switch (addr) { - case RTC_STAT_REGA: - // toggle UIP bit for linux - stat_regA ^= RTCA_UIP; - return stat_regA; - break; - case RTC_STAT_REGB: - return stat_regB; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - return 0x00; - break; - default: - panic("Shouldn't be here"); - } - } -} - -void -TsunamiIO::RTC::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".addr", addr); - arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); - paramOut(os, base + ".stat_regA", stat_regA); - paramOut(os, base + ".stat_regB", stat_regB); -} - -void -TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".addr", addr); - arrayParamIn(cp, section, base + ".clock_data", clock_data, - sizeof(clock_data)); - paramIn(cp, section, base + ".stat_regA", stat_regA); - paramIn(cp, section, base + ".stat_regB", stat_regB); - - // We're not unserializing the event here, but we need to - // rescehedule the event since curTick was moved forward by the - // checkpoint - event.reschedule(curTick + event.interval); -} - -TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) - : Event(&mainEventQueue), tsunami(t), interval(i) -{ - DPRINTF(MC146818, "RTC Event Initilizing\n"); - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::scheduleIntr() -{ - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::process() -{ - DPRINTF(MC146818, "RTC Timer Interrupt\n"); - schedule(curTick + interval); - //Actually interrupt the processor here - tsunami->cchip->postRTC(); -} - -const char * -TsunamiIO::RTC::RTCEvent::description() +TsunamiIO::RTC::RTC(const string &n, const TsunamiIOParams *p) + : MC146818(p->tsunami, n, p->time, p->year_is_bcd, p->frequency), + tsunami(p->tsunami) { - return "tsunami RTC interrupt"; } -TsunamiIO::PITimer::PITimer(const string &name) - : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), - counter2(name + ".counter2") -{ - counter[0] = &counter0; - counter[1] = &counter0; - counter[2] = &counter0; -} - -void -TsunamiIO::PITimer::writeControl(const uint8_t data) -{ - int rw; - int sel; - - sel = GET_CTRL_SEL(data); - - if (sel == PIT_READ_BACK) - panic("PITimer Read-Back Command is not implemented.\n"); - - rw = GET_CTRL_RW(data); - - if (rw == PIT_RW_LATCH_COMMAND) - counter[sel]->latchCount(); - else { - counter[sel]->setRW(rw); - counter[sel]->setMode(GET_CTRL_MODE(data)); - counter[sel]->setBCD(GET_CTRL_BCD(data)); - } -} - -void -TsunamiIO::PITimer::serialize(const string &base, ostream &os) -{ - // serialize the counters - counter0.serialize(base + ".counter0", os); - counter1.serialize(base + ".counter1", os); - counter2.serialize(base + ".counter2", os); -} - -void -TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - // unserialze the counters - counter0.unserialize(base + ".counter0", cp, section); - counter1.unserialize(base + ".counter1", cp, section); - counter2.unserialize(base + ".counter2", cp, section); -} - -TsunamiIO::PITimer::Counter::Counter(const string &name) - : _name(name), event(this), count(0), latched_count(0), period(0), - mode(0), output_high(false), latch_on(false), read_byte(LSB), - write_byte(LSB) -{ - -} - -void -TsunamiIO::PITimer::Counter::latchCount() -{ - // behave like a real latch - if(!latch_on) { - latch_on = true; - read_byte = LSB; - latched_count = count; - } -} - -uint8_t -TsunamiIO::PITimer::Counter::read() -{ - if (latch_on) { - switch (read_byte) { - case LSB: - read_byte = MSB; - return (uint8_t)latched_count; - break; - case MSB: - read_byte = LSB; - latch_on = false; - return latched_count >> 8; - break; - default: - panic("Shouldn't be here"); - } - } else { - switch (read_byte) { - case LSB: - read_byte = MSB; - return (uint8_t)count; - break; - case MSB: - read_byte = LSB; - return count >> 8; - break; - default: - panic("Shouldn't be here"); - } - } -} - -void -TsunamiIO::PITimer::Counter::write(const uint8_t data) -{ - switch (write_byte) { - case LSB: - count = (count & 0xFF00) | data; - - if (event.scheduled()) - event.deschedule(); - output_high = false; - write_byte = MSB; - break; - - case MSB: - count = (count & 0x00FF) | (data << 8); - period = count; - - if (period > 0) { - DPRINTF(Tsunami, "Timer set to curTick + %d\n", - count * event.interval); - event.schedule(curTick + count * event.interval); - } - write_byte = LSB; - break; - } -} - -void -TsunamiIO::PITimer::Counter::setRW(int rw_val) -{ - if (rw_val != PIT_RW_16BIT) - panic("Only LSB/MSB read/write is implemented.\n"); -} - -void -TsunamiIO::PITimer::Counter::setMode(int mode_val) -{ - if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && - mode_val != PIT_MODE_SQWAVE) - panic("PIT mode %#x is not implemented: \n", mode_val); - - mode = mode_val; -} - -void -TsunamiIO::PITimer::Counter::setBCD(int bcd_val) -{ - if (bcd_val != PIT_BCD_FALSE) - panic("PITimer does not implement BCD counts.\n"); -} - -bool -TsunamiIO::PITimer::Counter::outputHigh() -{ - return output_high; -} - -void -TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".count", count); - paramOut(os, base + ".latched_count", latched_count); - paramOut(os, base + ".period", period); - paramOut(os, base + ".mode", mode); - paramOut(os, base + ".output_high", output_high); - paramOut(os, base + ".latch_on", latch_on); - paramOut(os, base + ".read_byte", read_byte); - paramOut(os, base + ".write_byte", write_byte); - - Tick event_tick = 0; - if (event.scheduled()) - event_tick = event.when(); - paramOut(os, base + ".event_tick", event_tick); -} - -void -TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".count", count); - paramIn(cp, section, base + ".latched_count", latched_count); - paramIn(cp, section, base + ".period", period); - paramIn(cp, section, base + ".mode", mode); - paramIn(cp, section, base + ".output_high", output_high); - paramIn(cp, section, base + ".latch_on", latch_on); - paramIn(cp, section, base + ".read_byte", read_byte); - paramIn(cp, section, base + ".write_byte", write_byte); - - Tick event_tick; - paramIn(cp, section, base + ".event_tick", event_tick); - if (event_tick) - event.schedule(event_tick); -} - -TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) - : Event(&mainEventQueue) -{ - interval = (Tick)(Clock::Float::s / 1193180.0); - counter = c_ptr; -} - -void -TsunamiIO::PITimer::Counter::CounterEvent::process() -{ - DPRINTF(Tsunami, "Timer Interrupt\n"); - switch (counter->mode) { - case PIT_MODE_INTTC: - counter->output_high = true; - case PIT_MODE_RATEGEN: - case PIT_MODE_SQWAVE: - break; - default: - panic("Unimplemented PITimer mode.\n"); - } -} - -const char * -TsunamiIO::PITimer::Counter::CounterEvent::description() -{ - return "tsunami 8254 Interval timer"; -} - -TsunamiIO::TsunamiIO(Params *p) - : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), - rtc(p->name + ".rtc", p->tsunami, p->init_time, p->year_is_bcd, - p->frequency) +TsunamiIO::TsunamiIO(const Params *p) + : BasicPioDevice(p), tsunami(p->tsunami), + pitimer(this, p->name + "pitimer"), rtc(p->name + ".rtc", p) { pioSize = 0x100; @@ -492,13 +81,12 @@ TsunamiIO::TsunamiIO(Params *p) Tick TsunamiIO::frequency() const { - return Clock::Frequency / params()->frequency; + return SimClock::Frequency / params()->frequency; } Tick TsunamiIO::read(PacketPtr pkt) { - assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; @@ -528,19 +116,19 @@ TsunamiIO::read(PacketPtr pkt) pkt->set(0x00); break; case TSDEV_TMR0_DATA: - pkt->set(pitimer.counter0.read()); + pkt->set(pitimer.readCounter(0)); break; case TSDEV_TMR1_DATA: - pkt->set(pitimer.counter1.read()); + pkt->set(pitimer.readCounter(1)); break; case TSDEV_TMR2_DATA: - pkt->set(pitimer.counter2.read()); + pkt->set(pitimer.readCounter(2)); break; case TSDEV_RTC_DATA: - pkt->set(rtc.readData()); + pkt->set(rtc.readData(rtcAddr)); break; case TSDEV_CTRL_PORTB: - if (pitimer.counter2.outputHigh()) + if (pitimer.outputHigh(2)) pkt->set(PORTB_SPKR_HIGH); else pkt->set(0x00); @@ -557,14 +145,13 @@ TsunamiIO::read(PacketPtr pkt) } else { panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); } - pkt->result = Packet::Success; + pkt->makeAtomicResponse(); return pioDelay; } Tick TsunamiIO::write(PacketPtr pkt) { - assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; @@ -604,22 +191,22 @@ TsunamiIO::write(PacketPtr pkt) mode2 = pkt->get(); break; case TSDEV_TMR0_DATA: - pitimer.counter0.write(pkt->get()); + pitimer.writeCounter(0, pkt->get()); break; case TSDEV_TMR1_DATA: - pitimer.counter1.write(pkt->get()); + pitimer.writeCounter(1, pkt->get()); break; case TSDEV_TMR2_DATA: - pitimer.counter2.write(pkt->get()); + pitimer.writeCounter(2, pkt->get()); break; case TSDEV_TMR_CTRL: pitimer.writeControl(pkt->get()); break; case TSDEV_RTC_ADDR: - rtc.writeAddr(pkt->get()); + rtcAddr = pkt->get(); break; case TSDEV_RTC_DATA: - rtc.writeData(pkt->get()); + rtc.writeData(rtcAddr, pkt->get()); break; case TSDEV_KBD: case TSDEV_DMA1_CMND: @@ -637,7 +224,7 @@ TsunamiIO::write(PacketPtr pkt) panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get()); } - pkt->result = Packet::Success; + pkt->makeAtomicResponse(); return pioDelay; } @@ -666,6 +253,7 @@ TsunamiIO::clearPIC(uint8_t bitvector) void TsunamiIO::serialize(ostream &os) { + SERIALIZE_SCALAR(rtcAddr); SERIALIZE_SCALAR(timerData); SERIALIZE_SCALAR(mask1); SERIALIZE_SCALAR(mask2); @@ -682,6 +270,7 @@ TsunamiIO::serialize(ostream &os) void TsunamiIO::unserialize(Checkpoint *cp, const string §ion) { + UNSERIALIZE_SCALAR(rtcAddr); UNSERIALIZE_SCALAR(timerData); UNSERIALIZE_SCALAR(mask1); UNSERIALIZE_SCALAR(mask2); @@ -695,45 +284,8 @@ TsunamiIO::unserialize(Checkpoint *cp, const string §ion) rtc.unserialize("rtc", cp, section); } -BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) - - Param pio_addr; - Param pio_latency; - Param frequency; - SimObjectParam platform; - SimObjectParam system; - VectorParam time; - Param year_is_bcd; - SimObjectParam tsunami; - -END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) - -BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) - - INIT_PARAM(pio_addr, "Device Address"), - INIT_PARAM(pio_latency, "Programmed IO latency"), - INIT_PARAM(frequency, "clock interrupt frequency"), - INIT_PARAM(platform, "platform"), - INIT_PARAM(system, "system object"), - INIT_PARAM(time, "System time to use (0 for actual time"), - INIT_PARAM(year_is_bcd, ""), - INIT_PARAM(tsunami, "Tsunami") - -END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) - -CREATE_SIM_OBJECT(TsunamiIO) +TsunamiIO * +TsunamiIOParams::create() { - TsunamiIO::Params *p = new TsunamiIO::Params; - p->frequency = frequency; - p->name = getInstanceName(); - p->pio_addr = pio_addr; - p->pio_delay = pio_latency; - p->platform = platform; - p->system = system; - p->init_time = time; - p->year_is_bcd = year_is_bcd; - p->tsunami = tsunami; - return new TsunamiIO(p); + return new TsunamiIO(this); } - -REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)