malta_io.cc revision 5222
15222Sksewell@umich.edu/*
25222Sksewell@umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
35222Sksewell@umich.edu * All rights reserved.
45222Sksewell@umich.edu *
55222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65222Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115222Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145222Sksewell@umich.edu * this software without specific prior written permission.
155222Sksewell@umich.edu *
165222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275222Sksewell@umich.edu *
285222Sksewell@umich.edu * Authors: Ali Saidi
295222Sksewell@umich.edu *          Andrew Schultz
305222Sksewell@umich.edu *          Miguel Serrano
315222Sksewell@umich.edu */
325222Sksewell@umich.edu
335222Sksewell@umich.edu/** @file
345222Sksewell@umich.edu * Malta I/O including PIC, PIT, RTC, DMA
355222Sksewell@umich.edu */
365222Sksewell@umich.edu
375222Sksewell@umich.edu#include <sys/time.h>
385222Sksewell@umich.edu
395222Sksewell@umich.edu#include <deque>
405222Sksewell@umich.edu#include <string>
415222Sksewell@umich.edu#include <vector>
425222Sksewell@umich.edu
435222Sksewell@umich.edu#include "base/trace.hh"
445222Sksewell@umich.edu#include "dev/pitreg.h"
455222Sksewell@umich.edu#include "dev/rtcreg.h"
465222Sksewell@umich.edu#include "dev/mips/malta_cchip.hh"
475222Sksewell@umich.edu#include "dev/mips/malta.hh"
485222Sksewell@umich.edu#include "dev/mips/malta_io.hh"
495222Sksewell@umich.edu#include "dev/mips/maltareg.h"
505222Sksewell@umich.edu#include "mem/packet.hh"
515222Sksewell@umich.edu#include "mem/packet_access.hh"
525222Sksewell@umich.edu#include "mem/port.hh"
535222Sksewell@umich.edu#include "params/MaltaIO.hh"
545222Sksewell@umich.edu#include "sim/system.hh"
555222Sksewell@umich.edu
565222Sksewell@umich.eduusing namespace std;
575222Sksewell@umich.eduusing namespace TheISA;
585222Sksewell@umich.edu
595222Sksewell@umich.eduMaltaIO::RTC::RTC(const string &name, Malta* t, Tick i)
605222Sksewell@umich.edu    : _name(name), event(t, i), addr(0)
615222Sksewell@umich.edu{
625222Sksewell@umich.edu    memset(clock_data, 0, sizeof(clock_data));
635222Sksewell@umich.edu    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
645222Sksewell@umich.edu    stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
655222Sksewell@umich.edu}
665222Sksewell@umich.edu
675222Sksewell@umich.eduvoid
685222Sksewell@umich.eduMaltaIO::RTC::set_time(time_t t)
695222Sksewell@umich.edu{
705222Sksewell@umich.edu    struct tm tm;
715222Sksewell@umich.edu    gmtime_r(&t, &tm);
725222Sksewell@umich.edu
735222Sksewell@umich.edu    sec = tm.tm_sec;
745222Sksewell@umich.edu    min = tm.tm_min;
755222Sksewell@umich.edu    hour = tm.tm_hour;
765222Sksewell@umich.edu    wday = tm.tm_wday + 1;
775222Sksewell@umich.edu    mday = tm.tm_mday;
785222Sksewell@umich.edu    mon = tm.tm_mon + 1;
795222Sksewell@umich.edu    year = tm.tm_year;
805222Sksewell@umich.edu
815222Sksewell@umich.edu    DPRINTFN("Real-time clock set to %s", asctime(&tm));
825222Sksewell@umich.edu}
835222Sksewell@umich.edu
845222Sksewell@umich.eduvoid
855222Sksewell@umich.eduMaltaIO::RTC::writeAddr(const uint8_t data)
865222Sksewell@umich.edu{
875222Sksewell@umich.edu        panic("MaltaIO::RTC::writeAddr has not been implemented for malta");
885222Sksewell@umich.edu        /*
895222Sksewell@umich.edu    if (data <= RTC_STAT_REGD)
905222Sksewell@umich.edu        addr = data;
915222Sksewell@umich.edu    else
925222Sksewell@umich.edu        panic("RTC addresses over 0xD are not implemented.\n");
935222Sksewell@umich.edu  */
945222Sksewell@umich.edu}
955222Sksewell@umich.edu
965222Sksewell@umich.eduvoid
975222Sksewell@umich.eduMaltaIO::RTC::writeData(const uint8_t data)
985222Sksewell@umich.edu{
995222Sksewell@umich.edu                panic("MaltaIO::RTC::writeData has not been implemented for malta");
1005222Sksewell@umich.edu                /*
1015222Sksewell@umich.edu    if (addr < RTC_STAT_REGA)
1025222Sksewell@umich.edu        clock_data[addr] = data;
1035222Sksewell@umich.edu    else {
1045222Sksewell@umich.edu        switch (addr) {
1055222Sksewell@umich.edu          case RTC_STAT_REGA:
1065222Sksewell@umich.edu            if (data != (RTCA_32768HZ | RTCA_1024HZ))
1075222Sksewell@umich.edu                panic("Unimplemented RTC register A value write!\n");
1085222Sksewell@umich.edu            stat_regA = data;
1095222Sksewell@umich.edu            break;
1105222Sksewell@umich.edu          case RTC_STAT_REGB:
1115222Sksewell@umich.edu            if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
1125222Sksewell@umich.edu                panic("Write to RTC reg B bits that are not implemented!\n");
1135222Sksewell@umich.edu
1145222Sksewell@umich.edu            if (data & RTCB_PRDC_IE) {
1155222Sksewell@umich.edu                if (!event.scheduled())
1165222Sksewell@umich.edu                    event.scheduleIntr();
1175222Sksewell@umich.edu            } else {
1185222Sksewell@umich.edu                if (event.scheduled())
1195222Sksewell@umich.edu                    event.deschedule();
1205222Sksewell@umich.edu            }
1215222Sksewell@umich.edu            stat_regB = data;
1225222Sksewell@umich.edu            break;
1235222Sksewell@umich.edu          case RTC_STAT_REGC:
1245222Sksewell@umich.edu          case RTC_STAT_REGD:
1255222Sksewell@umich.edu            panic("RTC status registers C and D are not implemented.\n");
1265222Sksewell@umich.edu            break;
1275222Sksewell@umich.edu        }
1285222Sksewell@umich.edu    }
1295222Sksewell@umich.edu    */
1305222Sksewell@umich.edu
1315222Sksewell@umich.edu}
1325222Sksewell@umich.edu
1335222Sksewell@umich.eduuint8_t
1345222Sksewell@umich.eduMaltaIO::RTC::readData()
1355222Sksewell@umich.edu{
1365222Sksewell@umich.edu                panic("MaltaIO::RTC::readData() has not been implemented for malta");
1375222Sksewell@umich.edu                /*
1385222Sksewell@umich.edu    if (addr < RTC_STAT_REGA)
1395222Sksewell@umich.edu        return clock_data[addr];
1405222Sksewell@umich.edu    else {
1415222Sksewell@umich.edu        switch (addr) {
1425222Sksewell@umich.edu          case RTC_STAT_REGA:
1435222Sksewell@umich.edu            // toggle UIP bit for linux
1445222Sksewell@umich.edu            stat_regA ^= RTCA_UIP;
1455222Sksewell@umich.edu            return stat_regA;
1465222Sksewell@umich.edu            break;
1475222Sksewell@umich.edu          case RTC_STAT_REGB:
1485222Sksewell@umich.edu            return stat_regB;
1495222Sksewell@umich.edu            break;
1505222Sksewell@umich.edu          case RTC_STAT_REGC:
1515222Sksewell@umich.edu          case RTC_STAT_REGD:
1525222Sksewell@umich.edu            return 0x00;
1535222Sksewell@umich.edu            break;
1545222Sksewell@umich.edu          default:
1555222Sksewell@umich.edu            panic("Shouldn't be here");
1565222Sksewell@umich.edu        }
1575222Sksewell@umich.edu    }
1585222Sksewell@umich.edu    */
1595222Sksewell@umich.edu}
1605222Sksewell@umich.edu
1615222Sksewell@umich.eduvoid
1625222Sksewell@umich.eduMaltaIO::RTC::serialize(const string &base, ostream &os)
1635222Sksewell@umich.edu{
1645222Sksewell@umich.edu    paramOut(os, base + ".addr", addr);
1655222Sksewell@umich.edu    arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
1665222Sksewell@umich.edu    paramOut(os, base + ".stat_regA", stat_regA);
1675222Sksewell@umich.edu    paramOut(os, base + ".stat_regB", stat_regB);
1685222Sksewell@umich.edu}
1695222Sksewell@umich.edu
1705222Sksewell@umich.eduvoid
1715222Sksewell@umich.eduMaltaIO::RTC::unserialize(const string &base, Checkpoint *cp,
1725222Sksewell@umich.edu                            const string &section)
1735222Sksewell@umich.edu{
1745222Sksewell@umich.edu    paramIn(cp, section, base + ".addr", addr);
1755222Sksewell@umich.edu    arrayParamIn(cp, section, base + ".clock_data", clock_data,
1765222Sksewell@umich.edu                 sizeof(clock_data));
1775222Sksewell@umich.edu    paramIn(cp, section, base + ".stat_regA", stat_regA);
1785222Sksewell@umich.edu    paramIn(cp, section, base + ".stat_regB", stat_regB);
1795222Sksewell@umich.edu
1805222Sksewell@umich.edu    // We're not unserializing the event here, but we need to
1815222Sksewell@umich.edu    // rescehedule the event since curTick was moved forward by the
1825222Sksewell@umich.edu    // checkpoint
1835222Sksewell@umich.edu    event.reschedule(curTick + event.interval);
1845222Sksewell@umich.edu}
1855222Sksewell@umich.edu
1865222Sksewell@umich.eduMaltaIO::RTC::RTCEvent::RTCEvent(Malta*t, Tick i)
1875222Sksewell@umich.edu    : Event(&mainEventQueue), malta(t), interval(i)
1885222Sksewell@umich.edu{
1895222Sksewell@umich.edu    DPRINTF(MC146818, "RTC Event Initilizing\n");
1905222Sksewell@umich.edu    warn("MaltaIO::RTC::RTCEvent::process() RTC interrupt has been disabled.");
1915222Sksewell@umich.edu    //schedule(curTick + interval);
1925222Sksewell@umich.edu}
1935222Sksewell@umich.edu
1945222Sksewell@umich.eduvoid
1955222Sksewell@umich.eduMaltaIO::RTC::RTCEvent::scheduleIntr()
1965222Sksewell@umich.edu{
1975222Sksewell@umich.edu        panic("MaltaIO::RTC::RTCEvent::scheduleIntr() has not been implemented for malta");
1985222Sksewell@umich.edu  //schedule(curTick + interval);
1995222Sksewell@umich.edu}
2005222Sksewell@umich.edu
2015222Sksewell@umich.eduvoid
2025222Sksewell@umich.eduMaltaIO::RTC::RTCEvent::process()
2035222Sksewell@umich.edu{
2045222Sksewell@umich.edu    DPRINTF(MC146818, "RTC Timer Interrupt\n");
2055222Sksewell@umich.edu    schedule(curTick + interval);
2065222Sksewell@umich.edu    //Actually interrupt the processor here
2075222Sksewell@umich.edu    malta->cchip->postRTC();
2085222Sksewell@umich.edu}
2095222Sksewell@umich.edu
2105222Sksewell@umich.educonst char *
2115222Sksewell@umich.eduMaltaIO::RTC::RTCEvent::description()
2125222Sksewell@umich.edu{
2135222Sksewell@umich.edu    return "malta RTC interrupt";
2145222Sksewell@umich.edu}
2155222Sksewell@umich.edu
2165222Sksewell@umich.eduMaltaIO::PITimer::PITimer(const string &name)
2175222Sksewell@umich.edu    : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"),
2185222Sksewell@umich.edu      counter2(name + ".counter2")
2195222Sksewell@umich.edu{
2205222Sksewell@umich.edu    counter[0] = &counter0;
2215222Sksewell@umich.edu    counter[1] = &counter0;
2225222Sksewell@umich.edu    counter[2] = &counter0;
2235222Sksewell@umich.edu}
2245222Sksewell@umich.edu
2255222Sksewell@umich.eduvoid
2265222Sksewell@umich.eduMaltaIO::PITimer::writeControl(const uint8_t data)
2275222Sksewell@umich.edu{
2285222Sksewell@umich.edu        panic("MaltoIO::PITimer::writeControl(data) not implemented inside malta_io.cc");
2295222Sksewell@umich.edu        /*
2305222Sksewell@umich.edu    int rw;
2315222Sksewell@umich.edu    int sel;
2325222Sksewell@umich.edu
2335222Sksewell@umich.edu    sel = GET_CTRL_SEL(data);
2345222Sksewell@umich.edu
2355222Sksewell@umich.edu    if (sel == PIT_READ_BACK)
2365222Sksewell@umich.edu       panic("PITimer Read-Back Command is not implemented.\n");
2375222Sksewell@umich.edu
2385222Sksewell@umich.edu    rw = GET_CTRL_RW(data);
2395222Sksewell@umich.edu
2405222Sksewell@umich.edu    if (rw == PIT_RW_LATCH_COMMAND)
2415222Sksewell@umich.edu        counter[sel]->latchCount();
2425222Sksewell@umich.edu    else {
2435222Sksewell@umich.edu        counter[sel]->setRW(rw);
2445222Sksewell@umich.edu        counter[sel]->setMode(GET_CTRL_MODE(data));
2455222Sksewell@umich.edu        counter[sel]->setBCD(GET_CTRL_BCD(data));
2465222Sksewell@umich.edu    }
2475222Sksewell@umich.edu    */
2485222Sksewell@umich.edu}
2495222Sksewell@umich.edu
2505222Sksewell@umich.eduvoid
2515222Sksewell@umich.eduMaltaIO::PITimer::serialize(const string &base, ostream &os)
2525222Sksewell@umich.edu{
2535222Sksewell@umich.edu    // serialize the counters
2545222Sksewell@umich.edu    counter0.serialize(base + ".counter0", os);
2555222Sksewell@umich.edu    counter1.serialize(base + ".counter1", os);
2565222Sksewell@umich.edu    counter2.serialize(base + ".counter2", os);
2575222Sksewell@umich.edu}
2585222Sksewell@umich.edu
2595222Sksewell@umich.eduvoid
2605222Sksewell@umich.eduMaltaIO::PITimer::unserialize(const string &base, Checkpoint *cp,
2615222Sksewell@umich.edu                                const string &section)
2625222Sksewell@umich.edu{
2635222Sksewell@umich.edu    // unserialze the counters
2645222Sksewell@umich.edu    counter0.unserialize(base + ".counter0", cp, section);
2655222Sksewell@umich.edu    counter1.unserialize(base + ".counter1", cp, section);
2665222Sksewell@umich.edu    counter2.unserialize(base + ".counter2", cp, section);
2675222Sksewell@umich.edu}
2685222Sksewell@umich.edu
2695222Sksewell@umich.eduMaltaIO::PITimer::Counter::Counter(const string &name)
2705222Sksewell@umich.edu    : _name(name), event(this), count(0), latched_count(0), period(0),
2715222Sksewell@umich.edu      mode(0), output_high(false), latch_on(false), read_byte(LSB),
2725222Sksewell@umich.edu      write_byte(LSB)
2735222Sksewell@umich.edu{
2745222Sksewell@umich.edu
2755222Sksewell@umich.edu}
2765222Sksewell@umich.edu
2775222Sksewell@umich.eduvoid
2785222Sksewell@umich.eduMaltaIO::PITimer::Counter::latchCount()
2795222Sksewell@umich.edu{
2805222Sksewell@umich.edu                panic("MaltoIO::PITimer::latchCount(...) not implemented inside malta_io.cc");
2815222Sksewell@umich.edu    // behave like a real latch
2825222Sksewell@umich.edu    /*
2835222Sksewell@umich.edu    if(!latch_on) {
2845222Sksewell@umich.edu        latch_on = true;
2855222Sksewell@umich.edu        read_byte = LSB;
2865222Sksewell@umich.edu        latched_count = count;
2875222Sksewell@umich.edu    }
2885222Sksewell@umich.edu    */
2895222Sksewell@umich.edu}
2905222Sksewell@umich.edu
2915222Sksewell@umich.eduuint8_t
2925222Sksewell@umich.eduMaltaIO::PITimer::Counter::read()
2935222Sksewell@umich.edu{
2945222Sksewell@umich.edu                panic("MaltoIO::PITimer::Count::read(...) not implemented inside malta_io.cc");
2955222Sksewell@umich.edu                return 0;
2965222Sksewell@umich.edu                /*
2975222Sksewell@umich.edu    if (latch_on) {
2985222Sksewell@umich.edu        switch (read_byte) {
2995222Sksewell@umich.edu          case LSB:
3005222Sksewell@umich.edu            read_byte = MSB;
3015222Sksewell@umich.edu            return (uint8_t)latched_count;
3025222Sksewell@umich.edu            break;
3035222Sksewell@umich.edu          case MSB:
3045222Sksewell@umich.edu            read_byte = LSB;
3055222Sksewell@umich.edu            latch_on = false;
3065222Sksewell@umich.edu            return latched_count >> 8;
3075222Sksewell@umich.edu            break;
3085222Sksewell@umich.edu          default:
3095222Sksewell@umich.edu            panic("Shouldn't be here");
3105222Sksewell@umich.edu        }
3115222Sksewell@umich.edu    } else {
3125222Sksewell@umich.edu        switch (read_byte) {
3135222Sksewell@umich.edu          case LSB:
3145222Sksewell@umich.edu            read_byte = MSB;
3155222Sksewell@umich.edu            return (uint8_t)count;
3165222Sksewell@umich.edu            break;
3175222Sksewell@umich.edu          case MSB:
3185222Sksewell@umich.edu            read_byte = LSB;
3195222Sksewell@umich.edu            return count >> 8;
3205222Sksewell@umich.edu            break;
3215222Sksewell@umich.edu          default:
3225222Sksewell@umich.edu            panic("Shouldn't be here");
3235222Sksewell@umich.edu        }
3245222Sksewell@umich.edu    }
3255222Sksewell@umich.edu    */
3265222Sksewell@umich.edu}
3275222Sksewell@umich.edu
3285222Sksewell@umich.eduvoid
3295222Sksewell@umich.eduMaltaIO::PITimer::Counter::write(const uint8_t data)
3305222Sksewell@umich.edu{
3315222Sksewell@umich.edu                panic("MaltoIO::PITimer::Counter::write(...) not implemented inside malta_io.cc");
3325222Sksewell@umich.edu                /*
3335222Sksewell@umich.edu    switch (write_byte) {
3345222Sksewell@umich.edu      case LSB:
3355222Sksewell@umich.edu        count = (count & 0xFF00) | data;
3365222Sksewell@umich.edu
3375222Sksewell@umich.edu        if (event.scheduled())
3385222Sksewell@umich.edu          event.deschedule();
3395222Sksewell@umich.edu        output_high = false;
3405222Sksewell@umich.edu        write_byte = MSB;
3415222Sksewell@umich.edu        break;
3425222Sksewell@umich.edu
3435222Sksewell@umich.edu      case MSB:
3445222Sksewell@umich.edu        count = (count & 0x00FF) | (data << 8);
3455222Sksewell@umich.edu        period = count;
3465222Sksewell@umich.edu
3475222Sksewell@umich.edu        if (period > 0) {
3485222Sksewell@umich.edu            DPRINTF(Malta, "Timer set to curTick + %d\n",
3495222Sksewell@umich.edu                    count * event.interval);
3505222Sksewell@umich.edu            event.schedule(curTick + count * event.interval);
3515222Sksewell@umich.edu        }
3525222Sksewell@umich.edu        write_byte = LSB;
3535222Sksewell@umich.edu        break;
3545222Sksewell@umich.edu    }
3555222Sksewell@umich.edu    */
3565222Sksewell@umich.edu}
3575222Sksewell@umich.edu
3585222Sksewell@umich.eduvoid
3595222Sksewell@umich.eduMaltaIO::PITimer::Counter::setRW(int rw_val)
3605222Sksewell@umich.edu{
3615222Sksewell@umich.edu                panic("MaltoIO::PITimer::Counter::setRW(...) not implemented inside malta_io.cc");
3625222Sksewell@umich.edu                /*
3635222Sksewell@umich.edu    if (rw_val != PIT_RW_16BIT)
3645222Sksewell@umich.edu        panic("Only LSB/MSB read/write is implemented.\n");
3655222Sksewell@umich.edu    */
3665222Sksewell@umich.edu}
3675222Sksewell@umich.edu
3685222Sksewell@umich.eduvoid
3695222Sksewell@umich.eduMaltaIO::PITimer::Counter::setMode(int mode_val)
3705222Sksewell@umich.edu{
3715222Sksewell@umich.edu                panic("MaltoIO::PITimer::Counter::setMode(...) not implemented inside malta_io.cc");
3725222Sksewell@umich.edu                /*
3735222Sksewell@umich.edu    if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
3745222Sksewell@umich.edu       mode_val != PIT_MODE_SQWAVE)
3755222Sksewell@umich.edu        panic("PIT mode %#x is not implemented: \n", mode_val);
3765222Sksewell@umich.edu
3775222Sksewell@umich.edu    mode = mode_val;
3785222Sksewell@umich.edu        */
3795222Sksewell@umich.edu}
3805222Sksewell@umich.edu
3815222Sksewell@umich.eduvoid
3825222Sksewell@umich.eduMaltaIO::PITimer::Counter::setBCD(int bcd_val)
3835222Sksewell@umich.edu{
3845222Sksewell@umich.edu                panic("MaltoIO::PITimer::Counter::setBCD(...) not implemented inside malta_io.cc");
3855222Sksewell@umich.edu                /*
3865222Sksewell@umich.edu    if (bcd_val != PIT_BCD_FALSE)
3875222Sksewell@umich.edu        panic("PITimer does not implement BCD counts.\n");
3885222Sksewell@umich.edu    */
3895222Sksewell@umich.edu}
3905222Sksewell@umich.edu
3915222Sksewell@umich.edubool
3925222Sksewell@umich.eduMaltaIO::PITimer::Counter::outputHigh()
3935222Sksewell@umich.edu{
3945222Sksewell@umich.edu                panic("MaltoIO::PITimer::Counter::outputHigh(...) not implemented inside malta_io.cc");
3955222Sksewell@umich.edu                return false;
3965222Sksewell@umich.edu                /*
3975222Sksewell@umich.edu    return output_high;
3985222Sksewell@umich.edu    */
3995222Sksewell@umich.edu}
4005222Sksewell@umich.edu
4015222Sksewell@umich.eduvoid
4025222Sksewell@umich.eduMaltaIO::PITimer::Counter::serialize(const string &base, ostream &os)
4035222Sksewell@umich.edu{
4045222Sksewell@umich.edu    paramOut(os, base + ".count", count);
4055222Sksewell@umich.edu    paramOut(os, base + ".latched_count", latched_count);
4065222Sksewell@umich.edu    paramOut(os, base + ".period", period);
4075222Sksewell@umich.edu    paramOut(os, base + ".mode", mode);
4085222Sksewell@umich.edu    paramOut(os, base + ".output_high", output_high);
4095222Sksewell@umich.edu    paramOut(os, base + ".latch_on", latch_on);
4105222Sksewell@umich.edu    paramOut(os, base + ".read_byte", read_byte);
4115222Sksewell@umich.edu    paramOut(os, base + ".write_byte", write_byte);
4125222Sksewell@umich.edu
4135222Sksewell@umich.edu    Tick event_tick = 0;
4145222Sksewell@umich.edu    if (event.scheduled())
4155222Sksewell@umich.edu        event_tick = event.when();
4165222Sksewell@umich.edu    paramOut(os, base + ".event_tick", event_tick);
4175222Sksewell@umich.edu}
4185222Sksewell@umich.edu
4195222Sksewell@umich.eduvoid
4205222Sksewell@umich.eduMaltaIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp,
4215222Sksewell@umich.edu                                         const string &section)
4225222Sksewell@umich.edu{
4235222Sksewell@umich.edu    paramIn(cp, section, base + ".count", count);
4245222Sksewell@umich.edu    paramIn(cp, section, base + ".latched_count", latched_count);
4255222Sksewell@umich.edu    paramIn(cp, section, base + ".period", period);
4265222Sksewell@umich.edu    paramIn(cp, section, base + ".mode", mode);
4275222Sksewell@umich.edu    paramIn(cp, section, base + ".output_high", output_high);
4285222Sksewell@umich.edu    paramIn(cp, section, base + ".latch_on", latch_on);
4295222Sksewell@umich.edu    paramIn(cp, section, base + ".read_byte", read_byte);
4305222Sksewell@umich.edu    paramIn(cp, section, base + ".write_byte", write_byte);
4315222Sksewell@umich.edu
4325222Sksewell@umich.edu    Tick event_tick;
4335222Sksewell@umich.edu    paramIn(cp, section, base + ".event_tick", event_tick);
4345222Sksewell@umich.edu    if (event_tick)
4355222Sksewell@umich.edu        event.schedule(event_tick);
4365222Sksewell@umich.edu}
4375222Sksewell@umich.edu
4385222Sksewell@umich.eduMaltaIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
4395222Sksewell@umich.edu    : Event(&mainEventQueue)
4405222Sksewell@umich.edu{
4415222Sksewell@umich.edu    interval = (Tick)(Clock::Float::s / 1193180.0);
4425222Sksewell@umich.edu    counter = c_ptr;
4435222Sksewell@umich.edu}
4445222Sksewell@umich.edu
4455222Sksewell@umich.eduvoid
4465222Sksewell@umich.eduMaltaIO::PITimer::Counter::CounterEvent::process()
4475222Sksewell@umich.edu{
4485222Sksewell@umich.edu                panic("MaltaIO::PITimer::Counter::CounterEvent::process(...) not implemented inside malta_io.cc");
4495222Sksewell@umich.edu                /*
4505222Sksewell@umich.edu    DPRINTF(Malta, "Timer Interrupt\n");
4515222Sksewell@umich.edu    switch (counter->mode) {
4525222Sksewell@umich.edu      case PIT_MODE_INTTC:
4535222Sksewell@umich.edu        counter->output_high = true;
4545222Sksewell@umich.edu      case PIT_MODE_RATEGEN:
4555222Sksewell@umich.edu      case PIT_MODE_SQWAVE:
4565222Sksewell@umich.edu        break;
4575222Sksewell@umich.edu      default:
4585222Sksewell@umich.edu        panic("Unimplemented PITimer mode.\n");
4595222Sksewell@umich.edu    }
4605222Sksewell@umich.edu    */
4615222Sksewell@umich.edu}
4625222Sksewell@umich.edu
4635222Sksewell@umich.educonst char *
4645222Sksewell@umich.eduMaltaIO::PITimer::Counter::CounterEvent::description()
4655222Sksewell@umich.edu{
4665222Sksewell@umich.edu    return "malta 8254 Interval timer";
4675222Sksewell@umich.edu}
4685222Sksewell@umich.edu
4695222Sksewell@umich.eduMaltaIO::MaltaIO(Params *p)
4705222Sksewell@umich.edu    : BasicPioDevice(p), malta(p->malta), pitimer(p->name + "pitimer"),
4715222Sksewell@umich.edu      rtc(p->name + ".rtc", p->malta, p->frequency)
4725222Sksewell@umich.edu{
4735222Sksewell@umich.edu    pioSize = 0x100;
4745222Sksewell@umich.edu
4755222Sksewell@umich.edu    // set the back pointer from malta to myself
4765222Sksewell@umich.edu    malta->io = this;
4775222Sksewell@umich.edu
4785222Sksewell@umich.edu    timerData = 0;
4795222Sksewell@umich.edu    picr = 0;
4805222Sksewell@umich.edu    picInterrupting = false;
4815222Sksewell@umich.edu}
4825222Sksewell@umich.edu
4835222Sksewell@umich.eduTick
4845222Sksewell@umich.eduMaltaIO::frequency() const
4855222Sksewell@umich.edu{
4865222Sksewell@umich.edu    return Clock::Frequency / params()->frequency;
4875222Sksewell@umich.edu}
4885222Sksewell@umich.edu
4895222Sksewell@umich.eduTick
4905222Sksewell@umich.eduMaltaIO::read(PacketPtr pkt)
4915222Sksewell@umich.edu{
4925222Sksewell@umich.edu                panic("MaltaIO::read(...) not implemented inside malta_io.cc");
4935222Sksewell@umich.edu                return pioDelay;
4945222Sksewell@umich.edu                /*
4955222Sksewell@umich.edu    assert(pkt->result == Packet::Unknown);
4965222Sksewell@umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
4975222Sksewell@umich.edu
4985222Sksewell@umich.edu    Addr daddr = pkt->getAddr() - pioAddr;
4995222Sksewell@umich.edu
5005222Sksewell@umich.edu    DPRINTF(Malta, "io read  va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
5015222Sksewell@umich.edu            pkt->getSize(), daddr);
5025222Sksewell@umich.edu
5035222Sksewell@umich.edu    pkt->allocate();
5045222Sksewell@umich.edu
5055222Sksewell@umich.edu    if (pkt->getSize() == sizeof(uint8_t)) {
5065222Sksewell@umich.edu        switch(daddr) {
5075222Sksewell@umich.edu          // PIC1 mask read
5085222Sksewell@umich.edu          case TSDEV_PIC1_MASK:
5095222Sksewell@umich.edu            pkt->set(~mask1);
5105222Sksewell@umich.edu            break;
5115222Sksewell@umich.edu          case TSDEV_PIC2_MASK:
5125222Sksewell@umich.edu            pkt->set(~mask2);
5135222Sksewell@umich.edu            break;
5145222Sksewell@umich.edu          case TSDEV_PIC1_ISR:
5155222Sksewell@umich.edu              // !!! If this is modified 64bit case needs to be too
5165222Sksewell@umich.edu              // Pal code has to do a 64 bit physical read because there is
5175222Sksewell@umich.edu              // no load physical byte instruction
5185222Sksewell@umich.edu              pkt->set(picr);
5195222Sksewell@umich.edu              break;
5205222Sksewell@umich.edu          case TSDEV_PIC2_ISR:
5215222Sksewell@umich.edu              // PIC2 not implemnted... just return 0
5225222Sksewell@umich.edu              pkt->set(0x00);
5235222Sksewell@umich.edu              break;
5245222Sksewell@umich.edu          case TSDEV_TMR0_DATA:
5255222Sksewell@umich.edu            pkt->set(pitimer.counter0.read());
5265222Sksewell@umich.edu            break;
5275222Sksewell@umich.edu          case TSDEV_TMR1_DATA:
5285222Sksewell@umich.edu            pkt->set(pitimer.counter1.read());
5295222Sksewell@umich.edu            break;
5305222Sksewell@umich.edu          case TSDEV_TMR2_DATA:
5315222Sksewell@umich.edu            pkt->set(pitimer.counter2.read());
5325222Sksewell@umich.edu            break;
5335222Sksewell@umich.edu          case TSDEV_RTC_DATA:
5345222Sksewell@umich.edu            pkt->set(rtc.readData());
5355222Sksewell@umich.edu            break;
5365222Sksewell@umich.edu          case TSDEV_CTRL_PORTB:
5375222Sksewell@umich.edu            if (pitimer.counter2.outputHigh())
5385222Sksewell@umich.edu                pkt->set(PORTB_SPKR_HIGH);
5395222Sksewell@umich.edu            else
5405222Sksewell@umich.edu                pkt->set(0x00);
5415222Sksewell@umich.edu            break;
5425222Sksewell@umich.edu          default:
5435222Sksewell@umich.edu            panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize());
5445222Sksewell@umich.edu        }
5455222Sksewell@umich.edu    } else if (pkt->getSize() == sizeof(uint64_t)) {
5465222Sksewell@umich.edu        if (daddr == TSDEV_PIC1_ISR)
5475222Sksewell@umich.edu            pkt->set<uint64_t>(picr);
5485222Sksewell@umich.edu        else
5495222Sksewell@umich.edu           panic("I/O Read - invalid addr - va %#x size %d\n",
5505222Sksewell@umich.edu                   pkt->getAddr(), pkt->getSize());
5515222Sksewell@umich.edu    } else {
5525222Sksewell@umich.edu       panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
5535222Sksewell@umich.edu    }
5545222Sksewell@umich.edu    pkt->result = Packet::Success;
5555222Sksewell@umich.edu    return pioDelay;
5565222Sksewell@umich.edu    */
5575222Sksewell@umich.edu}
5585222Sksewell@umich.edu
5595222Sksewell@umich.eduTick
5605222Sksewell@umich.eduMaltaIO::write(PacketPtr pkt)
5615222Sksewell@umich.edu{
5625222Sksewell@umich.edu                panic("MaltaIO::write(...) not implemented inside malta_io.cc");
5635222Sksewell@umich.edu                return pioDelay;
5645222Sksewell@umich.edu                /*
5655222Sksewell@umich.edu    assert(pkt->result == Packet::Unknown);
5665222Sksewell@umich.edu    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
5675222Sksewell@umich.edu    Addr daddr = pkt->getAddr() - pioAddr;
5685222Sksewell@umich.edu
5695222Sksewell@umich.edu    DPRINTF(Malta, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
5705222Sksewell@umich.edu            pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>());
5715222Sksewell@umich.edu
5725222Sksewell@umich.edu    assert(pkt->getSize() == sizeof(uint8_t));
5735222Sksewell@umich.edu    warn ("GOT HERE daddr=0x%x\n", daddr);
5745222Sksewell@umich.edu    switch(daddr) {
5755222Sksewell@umich.edu      case TSDEV_PIC1_MASK:
5765222Sksewell@umich.edu        mask1 = ~(pkt->get<uint8_t>());
5775222Sksewell@umich.edu        if ((picr & mask1) && !picInterrupting) {
5785222Sksewell@umich.edu            picInterrupting = true;
5795222Sksewell@umich.edu            malta->cchip->postDRIR(55);
5805222Sksewell@umich.edu            DPRINTF(Malta, "posting pic interrupt to cchip\n");
5815222Sksewell@umich.edu        }
5825222Sksewell@umich.edu        if ((!(picr & mask1)) && picInterrupting) {
5835222Sksewell@umich.edu            picInterrupting = false;
5845222Sksewell@umich.edu            malta->cchip->clearDRIR(55);
5855222Sksewell@umich.edu            DPRINTF(Malta, "clearing pic interrupt\n");
5865222Sksewell@umich.edu        }
5875222Sksewell@umich.edu        break;
5885222Sksewell@umich.edu      case TSDEV_PIC2_MASK:
5895222Sksewell@umich.edu        mask2 = pkt->get<uint8_t>();
5905222Sksewell@umich.edu        //PIC2 Not implemented to interrupt
5915222Sksewell@umich.edu        break;
5925222Sksewell@umich.edu      case TSDEV_PIC1_ACK:
5935222Sksewell@umich.edu        // clear the interrupt on the PIC
5945222Sksewell@umich.edu        picr &= ~(1 << (pkt->get<uint8_t>() & 0xF));
5955222Sksewell@umich.edu        if (!(picr & mask1))
5965222Sksewell@umich.edu            malta->cchip->clearDRIR(55);
5975222Sksewell@umich.edu        break;
5985222Sksewell@umich.edu      case TSDEV_DMA1_MODE:
5995222Sksewell@umich.edu        mode1 = pkt->get<uint8_t>();
6005222Sksewell@umich.edu        break;
6015222Sksewell@umich.edu      case TSDEV_DMA2_MODE:
6025222Sksewell@umich.edu        mode2 = pkt->get<uint8_t>();
6035222Sksewell@umich.edu        break;
6045222Sksewell@umich.edu      case TSDEV_TMR0_DATA:
6055222Sksewell@umich.edu        pitimer.counter0.write(pkt->get<uint8_t>());
6065222Sksewell@umich.edu        break;
6075222Sksewell@umich.edu      case TSDEV_TMR1_DATA:
6085222Sksewell@umich.edu        pitimer.counter1.write(pkt->get<uint8_t>());
6095222Sksewell@umich.edu        break;
6105222Sksewell@umich.edu      case TSDEV_TMR2_DATA:
6115222Sksewell@umich.edu        pitimer.counter2.write(pkt->get<uint8_t>());
6125222Sksewell@umich.edu        break;
6135222Sksewell@umich.edu      case TSDEV_TMR_CTRL:
6145222Sksewell@umich.edu        pitimer.writeControl(pkt->get<uint8_t>());
6155222Sksewell@umich.edu        break;
6165222Sksewell@umich.edu      case TSDEV_RTC_ADDR:
6175222Sksewell@umich.edu        rtc.writeAddr(pkt->get<uint8_t>());
6185222Sksewell@umich.edu        break;
6195222Sksewell@umich.edu      case TSDEV_RTC_DATA:
6205222Sksewell@umich.edu        rtc.writeData(pkt->get<uint8_t>());
6215222Sksewell@umich.edu        break;
6225222Sksewell@umich.edu      case TSDEV_KBD:
6235222Sksewell@umich.edu      case TSDEV_DMA1_CMND:
6245222Sksewell@umich.edu      case TSDEV_DMA2_CMND:
6255222Sksewell@umich.edu      case TSDEV_DMA1_MMASK:
6265222Sksewell@umich.edu      case TSDEV_DMA2_MMASK:
6275222Sksewell@umich.edu      case TSDEV_PIC2_ACK:
6285222Sksewell@umich.edu      case TSDEV_DMA1_RESET:
6295222Sksewell@umich.edu      case TSDEV_DMA2_RESET:
6305222Sksewell@umich.edu      case TSDEV_DMA1_MASK:
6315222Sksewell@umich.edu      case TSDEV_DMA2_MASK:
6325222Sksewell@umich.edu      case TSDEV_CTRL_PORTB:
6335222Sksewell@umich.edu        break;
6345222Sksewell@umich.edu      default:
6355222Sksewell@umich.edu        panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
6365222Sksewell@umich.edu    }
6375222Sksewell@umich.edu
6385222Sksewell@umich.edu    pkt->result = Packet::Success;
6395222Sksewell@umich.edu    return pioDelay;
6405222Sksewell@umich.edu    */
6415222Sksewell@umich.edu}
6425222Sksewell@umich.edu
6435222Sksewell@umich.eduvoid
6445222Sksewell@umich.eduMaltaIO::postIntr(uint8_t interrupt)
6455222Sksewell@umich.edu{
6465222Sksewell@umich.edu    malta->cchip->postIntr(interrupt);
6475222Sksewell@umich.edu    DPRINTF(Malta, "posting pic interrupt to cchip\n");
6485222Sksewell@umich.edu}
6495222Sksewell@umich.edu
6505222Sksewell@umich.eduvoid
6515222Sksewell@umich.eduMaltaIO::clearIntr(uint8_t interrupt)
6525222Sksewell@umich.edu{
6535222Sksewell@umich.edu    malta->cchip->clearIntr(interrupt);
6545222Sksewell@umich.edu    DPRINTF(Malta, "posting pic interrupt to cchip\n");
6555222Sksewell@umich.edu}
6565222Sksewell@umich.edu
6575222Sksewell@umich.eduvoid
6585222Sksewell@umich.eduMaltaIO::serialize(ostream &os)
6595222Sksewell@umich.edu{
6605222Sksewell@umich.edu    SERIALIZE_SCALAR(timerData);
6615222Sksewell@umich.edu    SERIALIZE_SCALAR(mask1);
6625222Sksewell@umich.edu    SERIALIZE_SCALAR(mask2);
6635222Sksewell@umich.edu    SERIALIZE_SCALAR(mode1);
6645222Sksewell@umich.edu    SERIALIZE_SCALAR(mode2);
6655222Sksewell@umich.edu    SERIALIZE_SCALAR(picr);
6665222Sksewell@umich.edu    SERIALIZE_SCALAR(picInterrupting);
6675222Sksewell@umich.edu
6685222Sksewell@umich.edu    // Serialize the timers
6695222Sksewell@umich.edu    pitimer.serialize("pitimer", os);
6705222Sksewell@umich.edu    rtc.serialize("rtc", os);
6715222Sksewell@umich.edu}
6725222Sksewell@umich.edu
6735222Sksewell@umich.eduvoid
6745222Sksewell@umich.eduMaltaIO::unserialize(Checkpoint *cp, const string &section)
6755222Sksewell@umich.edu{
6765222Sksewell@umich.edu    UNSERIALIZE_SCALAR(timerData);
6775222Sksewell@umich.edu    UNSERIALIZE_SCALAR(mask1);
6785222Sksewell@umich.edu    UNSERIALIZE_SCALAR(mask2);
6795222Sksewell@umich.edu    UNSERIALIZE_SCALAR(mode1);
6805222Sksewell@umich.edu    UNSERIALIZE_SCALAR(mode2);
6815222Sksewell@umich.edu    UNSERIALIZE_SCALAR(picr);
6825222Sksewell@umich.edu    UNSERIALIZE_SCALAR(picInterrupting);
6835222Sksewell@umich.edu
6845222Sksewell@umich.edu    // Unserialize the timers
6855222Sksewell@umich.edu    pitimer.unserialize("pitimer", cp, section);
6865222Sksewell@umich.edu    rtc.unserialize("rtc", cp, section);
6875222Sksewell@umich.edu}
6885222Sksewell@umich.edu
6895222Sksewell@umich.eduMaltaIO *
6905222Sksewell@umich.eduMaltaIOParams::create()
6915222Sksewell@umich.edu{
6925222Sksewell@umich.edu    return new MaltaIO(this);
6935222Sksewell@umich.edu}
694