tsunami_io.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 660 行 · 第 1/2 页
CC
660 行
if (period > 0) { DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * event.interval); event.schedule(curTick + count * event.interval); } write_byte = LSB; break; }}voidTsunamiIO::PITimer::Counter::setRW(int rw_val){ if (rw_val != PIT_RW_16BIT) panic("Only LSB/MSB read/write is implemented.\n");}voidTsunamiIO::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;}voidTsunamiIO::PITimer::Counter::setBCD(int bcd_val){ if (bcd_val != PIT_BCD_FALSE) panic("PITimer does not implement BCD counts.\n");}boolTsunamiIO::PITimer::Counter::outputHigh(){ return output_high;}voidTsunamiIO::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);}voidTsunamiIO::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;}voidTsunamiIO::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() const{ return "tsunami 8254 Interval timer";}TsunamiIO::TsunamiIO(const Params *p) : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), rtc(p->name + ".rtc", p->tsunami, p){ pioSize = 0x100; // set the back pointer from tsunami to myself tsunami->io = this; timerData = 0; picr = 0; picInterrupting = false;}TickTsunamiIO::frequency() const{ return Clock::Frequency / params()->frequency;}TickTsunamiIO::read(PacketPtr pkt){ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), pkt->getSize(), daddr); pkt->allocate(); if (pkt->getSize() == sizeof(uint8_t)) { switch(daddr) { // PIC1 mask read case TSDEV_PIC1_MASK: pkt->set(~mask1); break; case TSDEV_PIC2_MASK: pkt->set(~mask2); break; case TSDEV_PIC1_ISR: // !!! If this is modified 64bit case needs to be too // Pal code has to do a 64 bit physical read because there is // no load physical byte instruction pkt->set(picr); break; case TSDEV_PIC2_ISR: // PIC2 not implemnted... just return 0 pkt->set(0x00); break; case TSDEV_TMR0_DATA: pkt->set(pitimer.counter0.read()); break; case TSDEV_TMR1_DATA: pkt->set(pitimer.counter1.read()); break; case TSDEV_TMR2_DATA: pkt->set(pitimer.counter2.read()); break; case TSDEV_RTC_DATA: pkt->set(rtc.readData()); break; case TSDEV_CTRL_PORTB: if (pitimer.counter2.outputHigh()) pkt->set(PORTB_SPKR_HIGH); else pkt->set(0x00); break; default: panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); } } else if (pkt->getSize() == sizeof(uint64_t)) { if (daddr == TSDEV_PIC1_ISR) pkt->set<uint64_t>(picr); else panic("I/O Read - invalid addr - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); } else { panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); } pkt->makeAtomicResponse(); return pioDelay;}TickTsunamiIO::write(PacketPtr pkt){ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); assert(pkt->getSize() == sizeof(uint8_t)); switch(daddr) { case TSDEV_PIC1_MASK: mask1 = ~(pkt->get<uint8_t>()); if ((picr & mask1) && !picInterrupting) { picInterrupting = true; tsunami->cchip->postDRIR(55); DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); } if ((!(picr & mask1)) && picInterrupting) { picInterrupting = false; tsunami->cchip->clearDRIR(55); DPRINTF(Tsunami, "clearing pic interrupt\n"); } break; case TSDEV_PIC2_MASK: mask2 = pkt->get<uint8_t>(); //PIC2 Not implemented to interrupt break; case TSDEV_PIC1_ACK: // clear the interrupt on the PIC picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); if (!(picr & mask1)) tsunami->cchip->clearDRIR(55); break; case TSDEV_DMA1_MODE: mode1 = pkt->get<uint8_t>(); break; case TSDEV_DMA2_MODE: mode2 = pkt->get<uint8_t>(); break; case TSDEV_TMR0_DATA: pitimer.counter0.write(pkt->get<uint8_t>()); break; case TSDEV_TMR1_DATA: pitimer.counter1.write(pkt->get<uint8_t>()); break; case TSDEV_TMR2_DATA: pitimer.counter2.write(pkt->get<uint8_t>()); break; case TSDEV_TMR_CTRL: pitimer.writeControl(pkt->get<uint8_t>()); break; case TSDEV_RTC_ADDR: rtc.writeAddr(pkt->get<uint8_t>()); break; case TSDEV_RTC_DATA: rtc.writeData(pkt->get<uint8_t>()); break; case TSDEV_KBD: case TSDEV_DMA1_CMND: case TSDEV_DMA2_CMND: case TSDEV_DMA1_MMASK: case TSDEV_DMA2_MMASK: case TSDEV_PIC2_ACK: case TSDEV_DMA1_RESET: case TSDEV_DMA2_RESET: case TSDEV_DMA1_MASK: case TSDEV_DMA2_MASK: case TSDEV_CTRL_PORTB: break; default: panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); } pkt->makeAtomicResponse(); return pioDelay;}voidTsunamiIO::postPIC(uint8_t bitvector){ //PIC2 Is not implemented, because nothing of interest there picr |= bitvector; if (picr & mask1) { tsunami->cchip->postDRIR(55); DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); }}voidTsunamiIO::clearPIC(uint8_t bitvector){ //PIC2 Is not implemented, because nothing of interest there picr &= ~bitvector; if (!(picr & mask1)) { tsunami->cchip->clearDRIR(55); DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); }}voidTsunamiIO::serialize(ostream &os){ SERIALIZE_SCALAR(timerData); SERIALIZE_SCALAR(mask1); SERIALIZE_SCALAR(mask2); SERIALIZE_SCALAR(mode1); SERIALIZE_SCALAR(mode2); SERIALIZE_SCALAR(picr); SERIALIZE_SCALAR(picInterrupting); // Serialize the timers pitimer.serialize("pitimer", os); rtc.serialize("rtc", os);}voidTsunamiIO::unserialize(Checkpoint *cp, const string §ion){ UNSERIALIZE_SCALAR(timerData); UNSERIALIZE_SCALAR(mask1); UNSERIALIZE_SCALAR(mask2); UNSERIALIZE_SCALAR(mode1); UNSERIALIZE_SCALAR(mode2); UNSERIALIZE_SCALAR(picr); UNSERIALIZE_SCALAR(picInterrupting); // Unserialize the timers pitimer.unserialize("pitimer", cp, section); rtc.unserialize("rtc", cp, section);}TsunamiIO *TsunamiIOParams::create(){ return new TsunamiIO(this);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?