tsunami_io.cc revision 4870
1803SN/A/* 21363SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 3803SN/A * All rights reserved. 4803SN/A * 5803SN/A * Redistribution and use in source and binary forms, with or without 6803SN/A * modification, are permitted provided that the following conditions are 7803SN/A * met: redistributions of source code must retain the above copyright 8803SN/A * notice, this list of conditions and the following disclaimer; 9803SN/A * redistributions in binary form must reproduce the above copyright 10803SN/A * notice, this list of conditions and the following disclaimer in the 11803SN/A * documentation and/or other materials provided with the distribution; 12803SN/A * neither the name of the copyright holders nor the names of its 13803SN/A * contributors may be used to endorse or promote products derived from 14803SN/A * this software without specific prior written permission. 15803SN/A * 16803SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17803SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18803SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19803SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20803SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21803SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22803SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23803SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24803SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25803SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26803SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665SN/A * 282665SN/A * Authors: Ali Saidi 292665SN/A * Andrew Schultz 302665SN/A * Miguel Serrano 31803SN/A */ 32768SN/A 331730SN/A/** @file 34773SN/A * Tsunami I/O including PIC, PIT, RTC, DMA 35768SN/A */ 36768SN/A 37773SN/A#include <sys/time.h> 38773SN/A 39768SN/A#include <deque> 40768SN/A#include <string> 41768SN/A#include <vector> 42768SN/A 43768SN/A#include "base/trace.hh" 442542SN/A#include "dev/pitreg.h" 452542SN/A#include "dev/rtcreg.h" 463540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_cchip.hh" 473540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami.hh" 483540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_io.hh" 493540Sgblack@eecs.umich.edu#include "dev/alpha/tsunamireg.h" 503348SN/A#include "mem/packet.hh" 513348SN/A#include "mem/packet_access.hh" 522542SN/A#include "mem/port.hh" 53768SN/A#include "sim/builder.hh" 542542SN/A#include "sim/system.hh" 55768SN/A 56768SN/Ausing namespace std; 572107SN/A//Should this be AlphaISA? 582107SN/Ausing namespace TheISA; 59773SN/A 603932Sbinkertn@umich.eduTsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, const vector<int> &t, 613932Sbinkertn@umich.edu bool bcd, Tick i) 623932Sbinkertn@umich.edu : _name(n), event(tsunami, i), addr(0), year_is_bcd(bcd) 631817SN/A{ 641817SN/A memset(clock_data, 0, sizeof(clock_data)); 651817SN/A stat_regA = RTCA_32768HZ | RTCA_1024HZ; 661817SN/A stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 67773SN/A 683943Sbinkertn@umich.edu struct tm tm; 693943Sbinkertn@umich.edu parseTime(t, &tm); 703943Sbinkertn@umich.edu 713943Sbinkertn@umich.edu year = tm.tm_year; 723943Sbinkertn@umich.edu 733932Sbinkertn@umich.edu if (year_is_bcd) { 743943Sbinkertn@umich.edu // The datasheet says that the year field can be either BCD or 753943Sbinkertn@umich.edu // years since 1900. Linux seems to be happy with years since 763943Sbinkertn@umich.edu // 1900. 773943Sbinkertn@umich.edu year = year % 100; 783943Sbinkertn@umich.edu int tens = year / 10; 793943Sbinkertn@umich.edu int ones = year % 10; 803932Sbinkertn@umich.edu year = (tens << 4) + ones; 813932Sbinkertn@umich.edu } 823932Sbinkertn@umich.edu 833943Sbinkertn@umich.edu // Unix is 0-11 for month, data seet says start at 1 843943Sbinkertn@umich.edu mon = tm.tm_mon + 1; 853943Sbinkertn@umich.edu mday = tm.tm_mday; 863943Sbinkertn@umich.edu hour = tm.tm_hour; 873943Sbinkertn@umich.edu min = tm.tm_min; 883943Sbinkertn@umich.edu sec = tm.tm_sec; 893932Sbinkertn@umich.edu 903943Sbinkertn@umich.edu // Datasheet says 1 is sunday 913943Sbinkertn@umich.edu wday = tm.tm_wday + 1; 923932Sbinkertn@umich.edu 933943Sbinkertn@umich.edu DPRINTFN("Real-time clock set to %s", asctime(&tm)); 941817SN/A} 951817SN/A 961817SN/Avoid 972539SN/ATsunamiIO::RTC::writeAddr(const uint8_t data) 981817SN/A{ 992542SN/A if (data <= RTC_STAT_REGD) 1002539SN/A addr = data; 1011817SN/A else 1021817SN/A panic("RTC addresses over 0xD are not implemented.\n"); 1031817SN/A} 1041817SN/A 1051817SN/Avoid 1062539SN/ATsunamiIO::RTC::writeData(const uint8_t data) 1071817SN/A{ 1081817SN/A if (addr < RTC_STAT_REGA) 1092539SN/A clock_data[addr] = data; 1101817SN/A else { 1111817SN/A switch (addr) { 1121817SN/A case RTC_STAT_REGA: 1132539SN/A if (data != (RTCA_32768HZ | RTCA_1024HZ)) 1141817SN/A panic("Unimplemented RTC register A value write!\n"); 1152542SN/A stat_regA = data; 1161817SN/A break; 1171817SN/A case RTC_STAT_REGB: 1182539SN/A if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 1191817SN/A panic("Write to RTC reg B bits that are not implemented!\n"); 1201817SN/A 1212542SN/A if (data & RTCB_PRDC_IE) { 1221817SN/A if (!event.scheduled()) 1231817SN/A event.scheduleIntr(); 1241817SN/A } else { 1251817SN/A if (event.scheduled()) 1261817SN/A event.deschedule(); 1271817SN/A } 1282539SN/A stat_regB = data; 1291817SN/A break; 1301817SN/A case RTC_STAT_REGC: 1311817SN/A case RTC_STAT_REGD: 1321817SN/A panic("RTC status registers C and D are not implemented.\n"); 1331817SN/A break; 1341817SN/A } 1351817SN/A } 1361817SN/A} 1371817SN/A 1382648SN/Auint8_t 1392648SN/ATsunamiIO::RTC::readData() 1401817SN/A{ 1411817SN/A if (addr < RTC_STAT_REGA) 1422648SN/A return clock_data[addr]; 1431817SN/A else { 1441817SN/A switch (addr) { 1451817SN/A case RTC_STAT_REGA: 1461817SN/A // toggle UIP bit for linux 1471817SN/A stat_regA ^= RTCA_UIP; 1482648SN/A return stat_regA; 1491817SN/A break; 1501817SN/A case RTC_STAT_REGB: 1512648SN/A return stat_regB; 1521817SN/A break; 1531817SN/A case RTC_STAT_REGC: 1541817SN/A case RTC_STAT_REGD: 1552648SN/A return 0x00; 1561817SN/A break; 1572648SN/A default: 1582648SN/A panic("Shouldn't be here"); 1591817SN/A } 1601817SN/A } 1611817SN/A} 1621817SN/A 1631817SN/Avoid 1641854SN/ATsunamiIO::RTC::serialize(const string &base, ostream &os) 1651817SN/A{ 1661854SN/A paramOut(os, base + ".addr", addr); 1671854SN/A arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 1681854SN/A paramOut(os, base + ".stat_regA", stat_regA); 1691854SN/A paramOut(os, base + ".stat_regB", stat_regB); 1701817SN/A} 1711817SN/A 1721817SN/Avoid 1731854SN/ATsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 1741854SN/A const string §ion) 1751817SN/A{ 1761854SN/A paramIn(cp, section, base + ".addr", addr); 1771854SN/A arrayParamIn(cp, section, base + ".clock_data", clock_data, 1781854SN/A sizeof(clock_data)); 1791854SN/A paramIn(cp, section, base + ".stat_regA", stat_regA); 1801854SN/A paramIn(cp, section, base + ".stat_regB", stat_regB); 1811817SN/A 1821854SN/A // We're not unserializing the event here, but we need to 1831854SN/A // rescehedule the event since curTick was moved forward by the 1841854SN/A // checkpoint 1851854SN/A event.reschedule(curTick + event.interval); 1861817SN/A} 1871817SN/A 1881817SN/ATsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 1891634SN/A : Event(&mainEventQueue), tsunami(t), interval(i) 190772SN/A{ 191773SN/A DPRINTF(MC146818, "RTC Event Initilizing\n"); 1921634SN/A schedule(curTick + interval); 193772SN/A} 194772SN/A 195772SN/Avoid 1961817SN/ATsunamiIO::RTC::RTCEvent::scheduleIntr() 1971817SN/A{ 1981817SN/A schedule(curTick + interval); 1991817SN/A} 2001817SN/A 2011817SN/Avoid 2021817SN/ATsunamiIO::RTC::RTCEvent::process() 203772SN/A{ 204776SN/A DPRINTF(MC146818, "RTC Timer Interrupt\n"); 2051634SN/A schedule(curTick + interval); 206773SN/A //Actually interrupt the processor here 207831SN/A tsunami->cchip->postRTC(); 208772SN/A} 209772SN/A 210772SN/Aconst char * 2111817SN/ATsunamiIO::RTC::RTCEvent::description() 212772SN/A{ 2131634SN/A return "tsunami RTC interrupt"; 214772SN/A} 215772SN/A 2161854SN/ATsunamiIO::PITimer::PITimer(const string &name) 2171854SN/A : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 2181854SN/A counter2(name + ".counter2") 219918SN/A{ 2201854SN/A counter[0] = &counter0; 2211854SN/A counter[1] = &counter0; 2221854SN/A counter[2] = &counter0; 223771SN/A} 224771SN/A 225771SN/Avoid 2262539SN/ATsunamiIO::PITimer::writeControl(const uint8_t data) 227771SN/A{ 2281817SN/A int rw; 2291817SN/A int sel; 2301817SN/A 2312539SN/A sel = GET_CTRL_SEL(data); 2321817SN/A 2331817SN/A if (sel == PIT_READ_BACK) 2341817SN/A panic("PITimer Read-Back Command is not implemented.\n"); 2351817SN/A 2362542SN/A rw = GET_CTRL_RW(data); 2371817SN/A 2381817SN/A if (rw == PIT_RW_LATCH_COMMAND) 2391854SN/A counter[sel]->latchCount(); 2401817SN/A else { 2411854SN/A counter[sel]->setRW(rw); 2422539SN/A counter[sel]->setMode(GET_CTRL_MODE(data)); 2432539SN/A counter[sel]->setBCD(GET_CTRL_BCD(data)); 2441817SN/A } 245771SN/A} 246771SN/A 247771SN/Avoid 2481854SN/ATsunamiIO::PITimer::serialize(const string &base, ostream &os) 249771SN/A{ 2501817SN/A // serialize the counters 2511854SN/A counter0.serialize(base + ".counter0", os); 2521854SN/A counter1.serialize(base + ".counter1", os); 2531854SN/A counter2.serialize(base + ".counter2", os); 2541817SN/A} 2551817SN/A 2561817SN/Avoid 2571854SN/ATsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 2581854SN/A const string §ion) 2591817SN/A{ 2601817SN/A // unserialze the counters 2611854SN/A counter0.unserialize(base + ".counter0", cp, section); 2621854SN/A counter1.unserialize(base + ".counter1", cp, section); 2631854SN/A counter2.unserialize(base + ".counter2", cp, section); 2641817SN/A} 2651817SN/A 2661854SN/ATsunamiIO::PITimer::Counter::Counter(const string &name) 2671854SN/A : _name(name), event(this), count(0), latched_count(0), period(0), 2681817SN/A mode(0), output_high(false), latch_on(false), read_byte(LSB), 2691817SN/A write_byte(LSB) 2701817SN/A{ 2711817SN/A 2721817SN/A} 2731817SN/A 2741817SN/Avoid 2751817SN/ATsunamiIO::PITimer::Counter::latchCount() 2761817SN/A{ 2771817SN/A // behave like a real latch 2781817SN/A if(!latch_on) { 2791817SN/A latch_on = true; 2801817SN/A read_byte = LSB; 2811817SN/A latched_count = count; 2821817SN/A } 2831817SN/A} 2841817SN/A 2852648SN/Auint8_t 2862648SN/ATsunamiIO::PITimer::Counter::read() 2871817SN/A{ 2881817SN/A if (latch_on) { 2891817SN/A switch (read_byte) { 2901817SN/A case LSB: 2911817SN/A read_byte = MSB; 2922648SN/A return (uint8_t)latched_count; 2931817SN/A break; 2941817SN/A case MSB: 2951817SN/A read_byte = LSB; 2961817SN/A latch_on = false; 2972648SN/A return latched_count >> 8; 2981817SN/A break; 2992648SN/A default: 3002648SN/A panic("Shouldn't be here"); 3011817SN/A } 3021817SN/A } else { 3031817SN/A switch (read_byte) { 3041817SN/A case LSB: 3051817SN/A read_byte = MSB; 3062648SN/A return (uint8_t)count; 3071817SN/A break; 3081817SN/A case MSB: 3091817SN/A read_byte = LSB; 3102648SN/A return count >> 8; 3111817SN/A break; 3122648SN/A default: 3132648SN/A panic("Shouldn't be here"); 3141817SN/A } 3151817SN/A } 3161817SN/A} 3171817SN/A 3181817SN/Avoid 3192539SN/ATsunamiIO::PITimer::Counter::write(const uint8_t data) 3201817SN/A{ 3211817SN/A switch (write_byte) { 3221817SN/A case LSB: 3232539SN/A count = (count & 0xFF00) | data; 3241817SN/A 3251817SN/A if (event.scheduled()) 3261817SN/A event.deschedule(); 3271817SN/A output_high = false; 3281817SN/A write_byte = MSB; 3291817SN/A break; 3301817SN/A 3311817SN/A case MSB: 3322539SN/A count = (count & 0x00FF) | (data << 8); 3331817SN/A period = count; 3341817SN/A 3351817SN/A if (period > 0) { 3361854SN/A DPRINTF(Tsunami, "Timer set to curTick + %d\n", 3371854SN/A count * event.interval); 3381817SN/A event.schedule(curTick + count * event.interval); 3391817SN/A } 3401817SN/A write_byte = LSB; 3411817SN/A break; 3421817SN/A } 3431817SN/A} 3441817SN/A 3451817SN/Avoid 3461817SN/ATsunamiIO::PITimer::Counter::setRW(int rw_val) 3471817SN/A{ 3481817SN/A if (rw_val != PIT_RW_16BIT) 3491817SN/A panic("Only LSB/MSB read/write is implemented.\n"); 3501817SN/A} 3511817SN/A 3521817SN/Avoid 3531817SN/ATsunamiIO::PITimer::Counter::setMode(int mode_val) 3541817SN/A{ 3551817SN/A if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 3561817SN/A mode_val != PIT_MODE_SQWAVE) 3571817SN/A panic("PIT mode %#x is not implemented: \n", mode_val); 3581817SN/A 3591817SN/A mode = mode_val; 3601817SN/A} 3611817SN/A 3621817SN/Avoid 3631817SN/ATsunamiIO::PITimer::Counter::setBCD(int bcd_val) 3641817SN/A{ 3651817SN/A if (bcd_val != PIT_BCD_FALSE) 3661817SN/A panic("PITimer does not implement BCD counts.\n"); 3671817SN/A} 3681817SN/A 3691817SN/Abool 3701817SN/ATsunamiIO::PITimer::Counter::outputHigh() 3711817SN/A{ 3721817SN/A return output_high; 3731817SN/A} 3741817SN/A 3751817SN/Avoid 3761854SN/ATsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 3771817SN/A{ 3781854SN/A paramOut(os, base + ".count", count); 3791854SN/A paramOut(os, base + ".latched_count", latched_count); 3801854SN/A paramOut(os, base + ".period", period); 3811854SN/A paramOut(os, base + ".mode", mode); 3821854SN/A paramOut(os, base + ".output_high", output_high); 3831854SN/A paramOut(os, base + ".latch_on", latch_on); 3841854SN/A paramOut(os, base + ".read_byte", read_byte); 3851854SN/A paramOut(os, base + ".write_byte", write_byte); 3861817SN/A 3871854SN/A Tick event_tick = 0; 3881854SN/A if (event.scheduled()) 3891854SN/A event_tick = event.when(); 3901854SN/A paramOut(os, base + ".event_tick", event_tick); 3911817SN/A} 3921817SN/A 3931817SN/Avoid 3941854SN/ATsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 3951854SN/A const string §ion) 3961817SN/A{ 3971854SN/A paramIn(cp, section, base + ".count", count); 3981854SN/A paramIn(cp, section, base + ".latched_count", latched_count); 3991854SN/A paramIn(cp, section, base + ".period", period); 4001854SN/A paramIn(cp, section, base + ".mode", mode); 4011854SN/A paramIn(cp, section, base + ".output_high", output_high); 4021854SN/A paramIn(cp, section, base + ".latch_on", latch_on); 4031854SN/A paramIn(cp, section, base + ".read_byte", read_byte); 4041854SN/A paramIn(cp, section, base + ".write_byte", write_byte); 4051817SN/A 4061854SN/A Tick event_tick; 4071854SN/A paramIn(cp, section, base + ".event_tick", event_tick); 4081854SN/A if (event_tick) 4091854SN/A event.schedule(event_tick); 4101817SN/A} 4111817SN/A 4121817SN/ATsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 4131817SN/A : Event(&mainEventQueue) 4141817SN/A{ 4151817SN/A interval = (Tick)(Clock::Float::s / 1193180.0); 4161817SN/A counter = c_ptr; 4171817SN/A} 4181817SN/A 4191817SN/Avoid 4201817SN/ATsunamiIO::PITimer::Counter::CounterEvent::process() 4211817SN/A{ 4221817SN/A DPRINTF(Tsunami, "Timer Interrupt\n"); 4231817SN/A switch (counter->mode) { 4241817SN/A case PIT_MODE_INTTC: 4251817SN/A counter->output_high = true; 4261817SN/A case PIT_MODE_RATEGEN: 4271817SN/A case PIT_MODE_SQWAVE: 4281817SN/A break; 4291817SN/A default: 4301817SN/A panic("Unimplemented PITimer mode.\n"); 4311817SN/A } 432771SN/A} 433771SN/A 434771SN/Aconst char * 4351817SN/ATsunamiIO::PITimer::Counter::CounterEvent::description() 436771SN/A{ 437771SN/A return "tsunami 8254 Interval timer"; 438771SN/A} 439771SN/A 4402539SN/ATsunamiIO::TsunamiIO(Params *p) 4412539SN/A : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), 4423932Sbinkertn@umich.edu rtc(p->name + ".rtc", p->tsunami, p->init_time, p->year_is_bcd, 4433932Sbinkertn@umich.edu p->frequency) 444768SN/A{ 4453846Shsul@eecs.umich.edu pioSize = 0x100; 446909SN/A 447803SN/A // set the back pointer from tsunami to myself 448803SN/A tsunami->io = this; 449803SN/A 450771SN/A timerData = 0; 451777SN/A picr = 0; 452777SN/A picInterrupting = false; 453773SN/A} 454773SN/A 4551634SN/ATick 4561634SN/ATsunamiIO::frequency() const 4571634SN/A{ 4582539SN/A return Clock::Frequency / params()->frequency; 4591634SN/A} 4601634SN/A 4612542SN/ATick 4623349SN/ATsunamiIO::read(PacketPtr pkt) 463768SN/A{ 4642641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 465768SN/A 4662641SN/A Addr daddr = pkt->getAddr() - pioAddr; 467865SN/A 4682641SN/A DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 4692641SN/A pkt->getSize(), daddr); 470771SN/A 4712630SN/A pkt->allocate(); 4722539SN/A 4732641SN/A if (pkt->getSize() == sizeof(uint8_t)) { 474803SN/A switch(daddr) { 4751817SN/A // PIC1 mask read 4761817SN/A case TSDEV_PIC1_MASK: 4772630SN/A pkt->set(~mask1); 4782539SN/A break; 4791817SN/A case TSDEV_PIC2_MASK: 4802630SN/A pkt->set(~mask2); 4812539SN/A break; 482865SN/A case TSDEV_PIC1_ISR: 483865SN/A // !!! If this is modified 64bit case needs to be too 484865SN/A // Pal code has to do a 64 bit physical read because there is 485865SN/A // no load physical byte instruction 4862630SN/A pkt->set(picr); 4872539SN/A break; 488865SN/A case TSDEV_PIC2_ISR: 489865SN/A // PIC2 not implemnted... just return 0 4902630SN/A pkt->set(0x00); 4912539SN/A break; 4921817SN/A case TSDEV_TMR0_DATA: 4932648SN/A pkt->set(pitimer.counter0.read()); 4942542SN/A break; 4951817SN/A case TSDEV_TMR1_DATA: 4962648SN/A pkt->set(pitimer.counter1.read()); 4972542SN/A break; 4981817SN/A case TSDEV_TMR2_DATA: 4992648SN/A pkt->set(pitimer.counter2.read()); 5002539SN/A break; 501803SN/A case TSDEV_RTC_DATA: 5022648SN/A pkt->set(rtc.readData()); 5032539SN/A break; 5041817SN/A case TSDEV_CTRL_PORTB: 5051817SN/A if (pitimer.counter2.outputHigh()) 5062630SN/A pkt->set(PORTB_SPKR_HIGH); 5071817SN/A else 5082630SN/A pkt->set(0x00); 5092539SN/A break; 510803SN/A default: 5112641SN/A panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 512803SN/A } 5132641SN/A } else if (pkt->getSize() == sizeof(uint64_t)) { 5142539SN/A if (daddr == TSDEV_PIC1_ISR) 5152630SN/A pkt->set<uint64_t>(picr); 5162539SN/A else 5172539SN/A panic("I/O Read - invalid addr - va %#x size %d\n", 5182641SN/A pkt->getAddr(), pkt->getSize()); 5192539SN/A } else { 5202641SN/A panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 521771SN/A } 5224870Sstever@eecs.umich.edu pkt->makeAtomicResponse(); 5232539SN/A return pioDelay; 524768SN/A} 525768SN/A 5262539SN/ATick 5273349SN/ATsunamiIO::write(PacketPtr pkt) 528768SN/A{ 5292641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 5302641SN/A Addr daddr = pkt->getAddr() - pioAddr; 531779SN/A 532779SN/A DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 5332641SN/A pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 534768SN/A 5352641SN/A assert(pkt->getSize() == sizeof(uint8_t)); 536769SN/A 5372539SN/A switch(daddr) { 5382539SN/A case TSDEV_PIC1_MASK: 5392630SN/A mask1 = ~(pkt->get<uint8_t>()); 5402539SN/A if ((picr & mask1) && !picInterrupting) { 5412539SN/A picInterrupting = true; 5422539SN/A tsunami->cchip->postDRIR(55); 5432539SN/A DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 544803SN/A } 5452539SN/A if ((!(picr & mask1)) && picInterrupting) { 5462539SN/A picInterrupting = false; 5472539SN/A tsunami->cchip->clearDRIR(55); 5482539SN/A DPRINTF(Tsunami, "clearing pic interrupt\n"); 5492539SN/A } 5502539SN/A break; 5512539SN/A case TSDEV_PIC2_MASK: 5522630SN/A mask2 = pkt->get<uint8_t>(); 5532539SN/A //PIC2 Not implemented to interrupt 5542539SN/A break; 5552539SN/A case TSDEV_PIC1_ACK: 5562539SN/A // clear the interrupt on the PIC 5572630SN/A picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 5582539SN/A if (!(picr & mask1)) 5592539SN/A tsunami->cchip->clearDRIR(55); 5602539SN/A break; 5612539SN/A case TSDEV_DMA1_MODE: 5622630SN/A mode1 = pkt->get<uint8_t>(); 5632539SN/A break; 5642539SN/A case TSDEV_DMA2_MODE: 5652630SN/A mode2 = pkt->get<uint8_t>(); 5662539SN/A break; 5672539SN/A case TSDEV_TMR0_DATA: 5682630SN/A pitimer.counter0.write(pkt->get<uint8_t>()); 5692539SN/A break; 5702539SN/A case TSDEV_TMR1_DATA: 5712630SN/A pitimer.counter1.write(pkt->get<uint8_t>()); 5722539SN/A break; 5732539SN/A case TSDEV_TMR2_DATA: 5742630SN/A pitimer.counter2.write(pkt->get<uint8_t>()); 5752539SN/A break; 5762539SN/A case TSDEV_TMR_CTRL: 5772630SN/A pitimer.writeControl(pkt->get<uint8_t>()); 5782539SN/A break; 5792539SN/A case TSDEV_RTC_ADDR: 5802630SN/A rtc.writeAddr(pkt->get<uint8_t>()); 5812539SN/A break; 5822539SN/A case TSDEV_RTC_DATA: 5832630SN/A rtc.writeData(pkt->get<uint8_t>()); 5842539SN/A break; 5852539SN/A case TSDEV_KBD: 5862539SN/A case TSDEV_DMA1_CMND: 5872539SN/A case TSDEV_DMA2_CMND: 5882539SN/A case TSDEV_DMA1_MMASK: 5892539SN/A case TSDEV_DMA2_MMASK: 5902539SN/A case TSDEV_PIC2_ACK: 5912539SN/A case TSDEV_DMA1_RESET: 5922539SN/A case TSDEV_DMA2_RESET: 5932539SN/A case TSDEV_DMA1_MASK: 5942539SN/A case TSDEV_DMA2_MASK: 5952539SN/A case TSDEV_CTRL_PORTB: 5962539SN/A break; 597803SN/A default: 5982641SN/A panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 599769SN/A } 600769SN/A 6014870Sstever@eecs.umich.edu pkt->makeAtomicResponse(); 6022539SN/A return pioDelay; 603768SN/A} 604768SN/A 605768SN/Avoid 606777SN/ATsunamiIO::postPIC(uint8_t bitvector) 607777SN/A{ 608777SN/A //PIC2 Is not implemented, because nothing of interest there 609777SN/A picr |= bitvector; 610865SN/A if (picr & mask1) { 611817SN/A tsunami->cchip->postDRIR(55); 612777SN/A DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 613777SN/A } 614777SN/A} 615777SN/A 616777SN/Avoid 617777SN/ATsunamiIO::clearPIC(uint8_t bitvector) 618777SN/A{ 619777SN/A //PIC2 Is not implemented, because nothing of interest there 620777SN/A picr &= ~bitvector; 621777SN/A if (!(picr & mask1)) { 622817SN/A tsunami->cchip->clearDRIR(55); 623777SN/A DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 624777SN/A } 625777SN/A} 626777SN/A 627777SN/Avoid 6281854SN/ATsunamiIO::serialize(ostream &os) 629768SN/A{ 630811SN/A SERIALIZE_SCALAR(timerData); 631899SN/A SERIALIZE_SCALAR(mask1); 632899SN/A SERIALIZE_SCALAR(mask2); 633899SN/A SERIALIZE_SCALAR(mode1); 634899SN/A SERIALIZE_SCALAR(mode2); 635811SN/A SERIALIZE_SCALAR(picr); 636811SN/A SERIALIZE_SCALAR(picInterrupting); 637811SN/A 638919SN/A // Serialize the timers 6391854SN/A pitimer.serialize("pitimer", os); 6401854SN/A rtc.serialize("rtc", os); 641768SN/A} 642768SN/A 643768SN/Avoid 6441854SN/ATsunamiIO::unserialize(Checkpoint *cp, const string §ion) 645768SN/A{ 646811SN/A UNSERIALIZE_SCALAR(timerData); 647899SN/A UNSERIALIZE_SCALAR(mask1); 648899SN/A UNSERIALIZE_SCALAR(mask2); 649899SN/A UNSERIALIZE_SCALAR(mode1); 650899SN/A UNSERIALIZE_SCALAR(mode2); 651811SN/A UNSERIALIZE_SCALAR(picr); 652811SN/A UNSERIALIZE_SCALAR(picInterrupting); 653919SN/A 654919SN/A // Unserialize the timers 6551854SN/A pitimer.unserialize("pitimer", cp, section); 6561854SN/A rtc.unserialize("rtc", cp, section); 657768SN/A} 658768SN/A 659770SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 660768SN/A 6612539SN/A Param<Addr> pio_addr; 6622539SN/A Param<Tick> pio_latency; 6632539SN/A Param<Tick> frequency; 6642539SN/A SimObjectParam<Platform *> platform; 6652539SN/A SimObjectParam<System *> system; 6663932Sbinkertn@umich.edu VectorParam<int> time; 6673932Sbinkertn@umich.edu Param<bool> year_is_bcd; 668775SN/A SimObjectParam<Tsunami *> tsunami; 669768SN/A 670770SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) 671768SN/A 672770SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 673768SN/A 6742539SN/A INIT_PARAM(pio_addr, "Device Address"), 6752539SN/A INIT_PARAM(pio_latency, "Programmed IO latency"), 6762542SN/A INIT_PARAM(frequency, "clock interrupt frequency"), 6772539SN/A INIT_PARAM(platform, "platform"), 6782539SN/A INIT_PARAM(system, "system object"), 6791634SN/A INIT_PARAM(time, "System time to use (0 for actual time"), 6803932Sbinkertn@umich.edu INIT_PARAM(year_is_bcd, ""), 6812539SN/A INIT_PARAM(tsunami, "Tsunami") 682768SN/A 683770SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiIO) 684768SN/A 685770SN/ACREATE_SIM_OBJECT(TsunamiIO) 686768SN/A{ 6872539SN/A TsunamiIO::Params *p = new TsunamiIO::Params; 6882539SN/A p->frequency = frequency; 6892539SN/A p->name = getInstanceName(); 6902539SN/A p->pio_addr = pio_addr; 6912539SN/A p->pio_delay = pio_latency; 6922539SN/A p->platform = platform; 6932539SN/A p->system = system; 6942539SN/A p->init_time = time; 6953932Sbinkertn@umich.edu p->year_is_bcd = year_is_bcd; 6962539SN/A p->tsunami = tsunami; 6972539SN/A return new TsunamiIO(p); 698768SN/A} 699768SN/A 700770SN/AREGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) 701