tsunami_io.cc revision 5455:d63afee4c46a
1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Andrew Schultz 30 * Miguel Serrano 31 */ 32 33/** @file 34 * Tsunami I/O including PIC, PIT, RTC, DMA 35 */ 36 37#include <sys/time.h> 38 39#include <deque> 40#include <string> 41#include <vector> 42 43#include "base/time.hh" 44#include "base/trace.hh" 45#include "dev/rtcreg.h" 46#include "dev/alpha/tsunami_cchip.hh" 47#include "dev/alpha/tsunami.hh" 48#include "dev/alpha/tsunami_io.hh" 49#include "dev/alpha/tsunamireg.h" 50#include "mem/packet.hh" 51#include "mem/packet_access.hh" 52#include "mem/port.hh" 53#include "sim/system.hh" 54 55using namespace std; 56//Should this be AlphaISA? 57using namespace TheISA; 58 59TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) : 60 MC146818(n, p->time, p->year_is_bcd, p->frequency), tsunami(p->tsunami) 61{ 62} 63 64TsunamiIO::TsunamiIO(const Params *p) 65 : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), 66 rtc(p->name + ".rtc", p) 67{ 68 pioSize = 0x100; 69 70 // set the back pointer from tsunami to myself 71 tsunami->io = this; 72 73 timerData = 0; 74 picr = 0; 75 picInterrupting = false; 76} 77 78Tick 79TsunamiIO::frequency() const 80{ 81 return Clock::Frequency / params()->frequency; 82} 83 84Tick 85TsunamiIO::read(PacketPtr pkt) 86{ 87 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 88 89 Addr daddr = pkt->getAddr() - pioAddr; 90 91 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 92 pkt->getSize(), daddr); 93 94 pkt->allocate(); 95 96 if (pkt->getSize() == sizeof(uint8_t)) { 97 switch(daddr) { 98 // PIC1 mask read 99 case TSDEV_PIC1_MASK: 100 pkt->set(~mask1); 101 break; 102 case TSDEV_PIC2_MASK: 103 pkt->set(~mask2); 104 break; 105 case TSDEV_PIC1_ISR: 106 // !!! If this is modified 64bit case needs to be too 107 // Pal code has to do a 64 bit physical read because there is 108 // no load physical byte instruction 109 pkt->set(picr); 110 break; 111 case TSDEV_PIC2_ISR: 112 // PIC2 not implemnted... just return 0 113 pkt->set(0x00); 114 break; 115 case TSDEV_TMR0_DATA: 116 pkt->set(pitimer.counter0.read()); 117 break; 118 case TSDEV_TMR1_DATA: 119 pkt->set(pitimer.counter1.read()); 120 break; 121 case TSDEV_TMR2_DATA: 122 pkt->set(pitimer.counter2.read()); 123 break; 124 case TSDEV_RTC_DATA: 125 pkt->set(rtc.readData(rtcAddr)); 126 break; 127 case TSDEV_CTRL_PORTB: 128 if (pitimer.counter2.outputHigh()) 129 pkt->set(PORTB_SPKR_HIGH); 130 else 131 pkt->set(0x00); 132 break; 133 default: 134 panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 135 } 136 } else if (pkt->getSize() == sizeof(uint64_t)) { 137 if (daddr == TSDEV_PIC1_ISR) 138 pkt->set<uint64_t>(picr); 139 else 140 panic("I/O Read - invalid addr - va %#x size %d\n", 141 pkt->getAddr(), pkt->getSize()); 142 } else { 143 panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 144 } 145 pkt->makeAtomicResponse(); 146 return pioDelay; 147} 148 149Tick 150TsunamiIO::write(PacketPtr pkt) 151{ 152 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 153 Addr daddr = pkt->getAddr() - pioAddr; 154 155 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 156 pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 157 158 assert(pkt->getSize() == sizeof(uint8_t)); 159 160 switch(daddr) { 161 case TSDEV_PIC1_MASK: 162 mask1 = ~(pkt->get<uint8_t>()); 163 if ((picr & mask1) && !picInterrupting) { 164 picInterrupting = true; 165 tsunami->cchip->postDRIR(55); 166 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 167 } 168 if ((!(picr & mask1)) && picInterrupting) { 169 picInterrupting = false; 170 tsunami->cchip->clearDRIR(55); 171 DPRINTF(Tsunami, "clearing pic interrupt\n"); 172 } 173 break; 174 case TSDEV_PIC2_MASK: 175 mask2 = pkt->get<uint8_t>(); 176 //PIC2 Not implemented to interrupt 177 break; 178 case TSDEV_PIC1_ACK: 179 // clear the interrupt on the PIC 180 picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 181 if (!(picr & mask1)) 182 tsunami->cchip->clearDRIR(55); 183 break; 184 case TSDEV_DMA1_MODE: 185 mode1 = pkt->get<uint8_t>(); 186 break; 187 case TSDEV_DMA2_MODE: 188 mode2 = pkt->get<uint8_t>(); 189 break; 190 case TSDEV_TMR0_DATA: 191 pitimer.counter0.write(pkt->get<uint8_t>()); 192 break; 193 case TSDEV_TMR1_DATA: 194 pitimer.counter1.write(pkt->get<uint8_t>()); 195 break; 196 case TSDEV_TMR2_DATA: 197 pitimer.counter2.write(pkt->get<uint8_t>()); 198 break; 199 case TSDEV_TMR_CTRL: 200 pitimer.writeControl(pkt->get<uint8_t>()); 201 break; 202 case TSDEV_RTC_ADDR: 203 rtcAddr = pkt->get<uint8_t>(); 204 break; 205 case TSDEV_RTC_DATA: 206 rtc.writeData(rtcAddr, pkt->get<uint8_t>()); 207 break; 208 case TSDEV_KBD: 209 case TSDEV_DMA1_CMND: 210 case TSDEV_DMA2_CMND: 211 case TSDEV_DMA1_MMASK: 212 case TSDEV_DMA2_MMASK: 213 case TSDEV_PIC2_ACK: 214 case TSDEV_DMA1_RESET: 215 case TSDEV_DMA2_RESET: 216 case TSDEV_DMA1_MASK: 217 case TSDEV_DMA2_MASK: 218 case TSDEV_CTRL_PORTB: 219 break; 220 default: 221 panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 222 } 223 224 pkt->makeAtomicResponse(); 225 return pioDelay; 226} 227 228void 229TsunamiIO::postPIC(uint8_t bitvector) 230{ 231 //PIC2 Is not implemented, because nothing of interest there 232 picr |= bitvector; 233 if (picr & mask1) { 234 tsunami->cchip->postDRIR(55); 235 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 236 } 237} 238 239void 240TsunamiIO::clearPIC(uint8_t bitvector) 241{ 242 //PIC2 Is not implemented, because nothing of interest there 243 picr &= ~bitvector; 244 if (!(picr & mask1)) { 245 tsunami->cchip->clearDRIR(55); 246 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 247 } 248} 249 250void 251TsunamiIO::serialize(ostream &os) 252{ 253 SERIALIZE_SCALAR(rtcAddr); 254 SERIALIZE_SCALAR(timerData); 255 SERIALIZE_SCALAR(mask1); 256 SERIALIZE_SCALAR(mask2); 257 SERIALIZE_SCALAR(mode1); 258 SERIALIZE_SCALAR(mode2); 259 SERIALIZE_SCALAR(picr); 260 SERIALIZE_SCALAR(picInterrupting); 261 262 // Serialize the timers 263 pitimer.serialize("pitimer", os); 264 rtc.serialize("rtc", os); 265} 266 267void 268TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 269{ 270 UNSERIALIZE_SCALAR(rtcAddr); 271 UNSERIALIZE_SCALAR(timerData); 272 UNSERIALIZE_SCALAR(mask1); 273 UNSERIALIZE_SCALAR(mask2); 274 UNSERIALIZE_SCALAR(mode1); 275 UNSERIALIZE_SCALAR(mode2); 276 UNSERIALIZE_SCALAR(picr); 277 UNSERIALIZE_SCALAR(picInterrupting); 278 279 // Unserialize the timers 280 pitimer.unserialize("pitimer", cp, section); 281 rtc.unserialize("rtc", cp, section); 282} 283 284TsunamiIO * 285TsunamiIOParams::create() 286{ 287 return new TsunamiIO(this); 288} 289