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 &section)
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 &section)
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 &section)
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 &section)
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