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 §ion) 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