tsunami_io.cc revision 8737
110743Sandreas.hansson@arm.com/*
210139Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
310139Sandreas.hansson@arm.com * All rights reserved.
410139Sandreas.hansson@arm.com *
510139Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
610139Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
710139Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
810139Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
910139Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1010139Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
1110139Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
1210139Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
1310139Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
1410139Sandreas.hansson@arm.com * this software without specific prior written permission.
1510139Sandreas.hansson@arm.com *
1610139Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710139Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810139Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910139Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010139Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110139Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210139Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310139Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410139Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510139Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610139Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710139Sandreas.hansson@arm.com *
2810139Sandreas.hansson@arm.com * Authors: Ali Saidi
2910139Sandreas.hansson@arm.com *          Andrew Schultz
3010139Sandreas.hansson@arm.com *          Miguel Serrano
3110139Sandreas.hansson@arm.com */
3210139Sandreas.hansson@arm.com
3310139Sandreas.hansson@arm.com/** @file
3410139Sandreas.hansson@arm.com * Tsunami I/O including PIC, PIT, RTC, DMA
3510139Sandreas.hansson@arm.com */
3610139Sandreas.hansson@arm.com
3710139Sandreas.hansson@arm.com#include <sys/time.h>
3810139Sandreas.hansson@arm.com
3910139Sandreas.hansson@arm.com#include <deque>
4010139Sandreas.hansson@arm.com#include <string>
4110139Sandreas.hansson@arm.com#include <vector>
4210139Sandreas.hansson@arm.com
4310139Sandreas.hansson@arm.com#include "base/time.hh"
4410139Sandreas.hansson@arm.com#include "base/trace.hh"
4511682Sandreas.hansson@arm.com#include "config/the_isa.hh"
4610139Sandreas.hansson@arm.com#include "debug/Tsunami.hh"
4711682Sandreas.hansson@arm.com#include "dev/alpha/tsunami.hh"
4810139Sandreas.hansson@arm.com#include "dev/alpha/tsunami_cchip.hh"
4910139Sandreas.hansson@arm.com#include "dev/alpha/tsunami_io.hh"
5010139Sandreas.hansson@arm.com#include "dev/alpha/tsunamireg.h"
5110139Sandreas.hansson@arm.com#include "dev/rtcreg.h"
5210139Sandreas.hansson@arm.com#include "mem/packet.hh"
5310139Sandreas.hansson@arm.com#include "mem/packet_access.hh"
5410139Sandreas.hansson@arm.com#include "mem/port.hh"
5510139Sandreas.hansson@arm.com#include "sim/system.hh"
5610139Sandreas.hansson@arm.com
5710789Sandreas.hansson@arm.com// clang complains about std::set being overloaded with Packet::set if
5810139Sandreas.hansson@arm.com// we open up the entire namespace std
5910139Sandreas.hansson@arm.comusing std::string;
6010139Sandreas.hansson@arm.comusing std::ostream;
6110743Sandreas.hansson@arm.com
6210392Swendy.elsasser@arm.com//Should this be AlphaISA?
6310392Swendy.elsasser@arm.comusing namespace TheISA;
6410392Swendy.elsasser@arm.com
6510392Swendy.elsasser@arm.comTsunamiIO::RTC::RTC(const string &n, const TsunamiIOParams *p)
6610392Swendy.elsasser@arm.com    : MC146818(p->tsunami, n, p->time, p->year_is_bcd, p->frequency),
6710392Swendy.elsasser@arm.com      tsunami(p->tsunami)
6810392Swendy.elsasser@arm.com{
6910392Swendy.elsasser@arm.com}
7010392Swendy.elsasser@arm.com
7110392Swendy.elsasser@arm.comTsunamiIO::TsunamiIO(const Params *p)
7210392Swendy.elsasser@arm.com    : BasicPioDevice(p), tsunami(p->tsunami),
7310392Swendy.elsasser@arm.com      pitimer(this, p->name + "pitimer"), rtc(p->name + ".rtc", p)
7410392Swendy.elsasser@arm.com{
7510139Sandreas.hansson@arm.com    pioSize = 0x100;
7610139Sandreas.hansson@arm.com
7710139Sandreas.hansson@arm.com    // set the back pointer from tsunami to myself
7810139Sandreas.hansson@arm.com    tsunami->io = this;
7910139Sandreas.hansson@arm.com
8010139Sandreas.hansson@arm.com    timerData = 0;
8110139Sandreas.hansson@arm.com    picr = 0;
8210139Sandreas.hansson@arm.com    picInterrupting = false;
8310139Sandreas.hansson@arm.com}
8411125Sandreas.hansson@arm.com
8511125Sandreas.hansson@arm.comTick
8611125Sandreas.hansson@arm.comTsunamiIO::frequency() const
8711125Sandreas.hansson@arm.com{
8811125Sandreas.hansson@arm.com    return SimClock::Frequency / params()->frequency;
8910139Sandreas.hansson@arm.com}
9010139Sandreas.hansson@arm.com
9110139Sandreas.hansson@arm.comTick
9210139Sandreas.hansson@arm.comTsunamiIO::read(PacketPtr pkt)
9310139Sandreas.hansson@arm.com{
9410139Sandreas.hansson@arm.com    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
9510139Sandreas.hansson@arm.com
9610833Sandreas.hansson@arm.com    Addr daddr = pkt->getAddr() - pioAddr;
9711223Sandreas.hansson@arm.com
9810833Sandreas.hansson@arm.com    DPRINTF(Tsunami, "io read  va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
9910139Sandreas.hansson@arm.com            pkt->getSize(), daddr);
10010139Sandreas.hansson@arm.com
10110139Sandreas.hansson@arm.com    pkt->allocate();
10210832Swendy.elsasser@arm.com
10311125Sandreas.hansson@arm.com    if (pkt->getSize() == sizeof(uint8_t)) {
10411251Sradhika.jagtap@ARM.com        switch(daddr) {
10510139Sandreas.hansson@arm.com          // PIC1 mask read
10610139Sandreas.hansson@arm.com          case TSDEV_PIC1_MASK:
10710139Sandreas.hansson@arm.com            pkt->set(~mask1);
10810139Sandreas.hansson@arm.com            break;
10910146Sandreas.hansson@arm.com          case TSDEV_PIC2_MASK:
11010146Sandreas.hansson@arm.com            pkt->set(~mask2);
11110139Sandreas.hansson@arm.com            break;
11210833Sandreas.hansson@arm.com          case TSDEV_PIC1_ISR:
11310833Sandreas.hansson@arm.com              // !!! If this is modified 64bit case needs to be too
11410833Sandreas.hansson@arm.com              // Pal code has to do a 64 bit physical read because there is
11510392Swendy.elsasser@arm.com              // no load physical byte instruction
11610392Swendy.elsasser@arm.com              pkt->set(picr);
11710392Swendy.elsasser@arm.com              break;
11810392Swendy.elsasser@arm.com          case TSDEV_PIC2_ISR:
11910392Swendy.elsasser@arm.com              // PIC2 not implemnted... just return 0
12010392Swendy.elsasser@arm.com              pkt->set(0x00);
12110392Swendy.elsasser@arm.com              break;
12210392Swendy.elsasser@arm.com          case TSDEV_TMR0_DATA:
12310139Sandreas.hansson@arm.com            pkt->set(pitimer.readCounter(0));
12410139Sandreas.hansson@arm.com            break;
12510139Sandreas.hansson@arm.com          case TSDEV_TMR1_DATA:
12610139Sandreas.hansson@arm.com            pkt->set(pitimer.readCounter(1));
12710139Sandreas.hansson@arm.com            break;
12810139Sandreas.hansson@arm.com          case TSDEV_TMR2_DATA:
12910139Sandreas.hansson@arm.com            pkt->set(pitimer.readCounter(2));
13010139Sandreas.hansson@arm.com            break;
13110139Sandreas.hansson@arm.com          case TSDEV_RTC_DATA:
13210139Sandreas.hansson@arm.com            pkt->set(rtc.readData(rtcAddr));
13310139Sandreas.hansson@arm.com            break;
13410139Sandreas.hansson@arm.com          case TSDEV_CTRL_PORTB:
13510139Sandreas.hansson@arm.com            if (pitimer.outputHigh(2))
13610139Sandreas.hansson@arm.com                pkt->set(PORTB_SPKR_HIGH);
13710139Sandreas.hansson@arm.com            else
13810139Sandreas.hansson@arm.com                pkt->set(0x00);
13910139Sandreas.hansson@arm.com            break;
14010139Sandreas.hansson@arm.com          default:
14110139Sandreas.hansson@arm.com            panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize());
14210139Sandreas.hansson@arm.com        }
14310139Sandreas.hansson@arm.com    } else if (pkt->getSize() == sizeof(uint64_t)) {
14410139Sandreas.hansson@arm.com        if (daddr == TSDEV_PIC1_ISR)
14510139Sandreas.hansson@arm.com            pkt->set<uint64_t>(picr);
14610139Sandreas.hansson@arm.com        else
14710139Sandreas.hansson@arm.com           panic("I/O Read - invalid addr - va %#x size %d\n",
14810139Sandreas.hansson@arm.com                   pkt->getAddr(), pkt->getSize());
14911223Sandreas.hansson@arm.com    } else {
15011223Sandreas.hansson@arm.com       panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
15110139Sandreas.hansson@arm.com    }
15210139Sandreas.hansson@arm.com    pkt->makeAtomicResponse();
15310139Sandreas.hansson@arm.com    return pioDelay;
15410139Sandreas.hansson@arm.com}
15510139Sandreas.hansson@arm.com
15610323Sandreas.hansson@arm.comTick
15710323Sandreas.hansson@arm.comTsunamiIO::write(PacketPtr pkt)
15810323Sandreas.hansson@arm.com{
15910323Sandreas.hansson@arm.com    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
16010139Sandreas.hansson@arm.com    Addr daddr = pkt->getAddr() - pioAddr;
16110323Sandreas.hansson@arm.com
16210323Sandreas.hansson@arm.com    DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
16310139Sandreas.hansson@arm.com            pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>());
16410139Sandreas.hansson@arm.com
16510323Sandreas.hansson@arm.com    assert(pkt->getSize() == sizeof(uint8_t));
16610392Swendy.elsasser@arm.com
16710392Swendy.elsasser@arm.com    switch(daddr) {
16810392Swendy.elsasser@arm.com      case TSDEV_PIC1_MASK:
16910392Swendy.elsasser@arm.com        mask1 = ~(pkt->get<uint8_t>());
17010392Swendy.elsasser@arm.com        if ((picr & mask1) && !picInterrupting) {
17110743Sandreas.hansson@arm.com            picInterrupting = true;
17210139Sandreas.hansson@arm.com            tsunami->cchip->postDRIR(55);
17310139Sandreas.hansson@arm.com            DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
17410139Sandreas.hansson@arm.com        }
17510139Sandreas.hansson@arm.com        if ((!(picr & mask1)) && picInterrupting) {
17610139Sandreas.hansson@arm.com            picInterrupting = false;
17710139Sandreas.hansson@arm.com            tsunami->cchip->clearDRIR(55);
17810139Sandreas.hansson@arm.com            DPRINTF(Tsunami, "clearing pic interrupt\n");
17910139Sandreas.hansson@arm.com        }
18010139Sandreas.hansson@arm.com        break;
18110139Sandreas.hansson@arm.com      case TSDEV_PIC2_MASK:
18210139Sandreas.hansson@arm.com        mask2 = pkt->get<uint8_t>();
18310139Sandreas.hansson@arm.com        //PIC2 Not implemented to interrupt
18410139Sandreas.hansson@arm.com        break;
18510139Sandreas.hansson@arm.com      case TSDEV_PIC1_ACK:
18610139Sandreas.hansson@arm.com        // clear the interrupt on the PIC
18710139Sandreas.hansson@arm.com        picr &= ~(1 << (pkt->get<uint8_t>() & 0xF));
18810139Sandreas.hansson@arm.com        if (!(picr & mask1))
18910139Sandreas.hansson@arm.com            tsunami->cchip->clearDRIR(55);
19010139Sandreas.hansson@arm.com        break;
19110139Sandreas.hansson@arm.com      case TSDEV_DMA1_MODE:
19210139Sandreas.hansson@arm.com        mode1 = pkt->get<uint8_t>();
19310139Sandreas.hansson@arm.com        break;
19410139Sandreas.hansson@arm.com      case TSDEV_DMA2_MODE:
19510139Sandreas.hansson@arm.com        mode2 = pkt->get<uint8_t>();
19610139Sandreas.hansson@arm.com        break;
19710139Sandreas.hansson@arm.com      case TSDEV_TMR0_DATA:
19810139Sandreas.hansson@arm.com        pitimer.writeCounter(0, pkt->get<uint8_t>());
19910139Sandreas.hansson@arm.com        break;
20010139Sandreas.hansson@arm.com      case TSDEV_TMR1_DATA:
20110139Sandreas.hansson@arm.com        pitimer.writeCounter(1, pkt->get<uint8_t>());
20210139Sandreas.hansson@arm.com        break;
20310139Sandreas.hansson@arm.com      case TSDEV_TMR2_DATA:
20410139Sandreas.hansson@arm.com        pitimer.writeCounter(2, pkt->get<uint8_t>());
20510139Sandreas.hansson@arm.com        break;
20610323Sandreas.hansson@arm.com      case TSDEV_TMR_CTRL:
20710323Sandreas.hansson@arm.com        pitimer.writeControl(pkt->get<uint8_t>());
20810323Sandreas.hansson@arm.com        break;
209      case TSDEV_RTC_ADDR:
210        rtcAddr = pkt->get<uint8_t>();
211        break;
212      case TSDEV_RTC_DATA:
213        rtc.writeData(rtcAddr, pkt->get<uint8_t>());
214        break;
215      case TSDEV_KBD:
216      case TSDEV_DMA1_CMND:
217      case TSDEV_DMA2_CMND:
218      case TSDEV_DMA1_MMASK:
219      case TSDEV_DMA2_MMASK:
220      case TSDEV_PIC2_ACK:
221      case TSDEV_DMA1_RESET:
222      case TSDEV_DMA2_RESET:
223      case TSDEV_DMA1_MASK:
224      case TSDEV_DMA2_MASK:
225      case TSDEV_CTRL_PORTB:
226        break;
227      default:
228        panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
229    }
230
231    pkt->makeAtomicResponse();
232    return pioDelay;
233}
234
235void
236TsunamiIO::postPIC(uint8_t bitvector)
237{
238    //PIC2 Is not implemented, because nothing of interest there
239    picr |= bitvector;
240    if (picr & mask1) {
241        tsunami->cchip->postDRIR(55);
242        DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
243    }
244}
245
246void
247TsunamiIO::clearPIC(uint8_t bitvector)
248{
249    //PIC2 Is not implemented, because nothing of interest there
250    picr &= ~bitvector;
251    if (!(picr & mask1)) {
252        tsunami->cchip->clearDRIR(55);
253        DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
254    }
255}
256
257void
258TsunamiIO::serialize(ostream &os)
259{
260    SERIALIZE_SCALAR(rtcAddr);
261    SERIALIZE_SCALAR(timerData);
262    SERIALIZE_SCALAR(mask1);
263    SERIALIZE_SCALAR(mask2);
264    SERIALIZE_SCALAR(mode1);
265    SERIALIZE_SCALAR(mode2);
266    SERIALIZE_SCALAR(picr);
267    SERIALIZE_SCALAR(picInterrupting);
268
269    // Serialize the timers
270    pitimer.serialize("pitimer", os);
271    rtc.serialize("rtc", os);
272}
273
274void
275TsunamiIO::unserialize(Checkpoint *cp, const string &section)
276{
277    UNSERIALIZE_SCALAR(rtcAddr);
278    UNSERIALIZE_SCALAR(timerData);
279    UNSERIALIZE_SCALAR(mask1);
280    UNSERIALIZE_SCALAR(mask2);
281    UNSERIALIZE_SCALAR(mode1);
282    UNSERIALIZE_SCALAR(mode2);
283    UNSERIALIZE_SCALAR(picr);
284    UNSERIALIZE_SCALAR(picInterrupting);
285
286    // Unserialize the timers
287    pitimer.unserialize("pitimer", cp, section);
288    rtc.unserialize("rtc", cp, section);
289}
290
291TsunamiIO *
292TsunamiIOParams::create()
293{
294    return new TsunamiIO(this);
295}
296