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/pitreg.h" 46#include "dev/rtcreg.h" 47#include "dev/alpha/tsunami_cchip.hh" 48#include "dev/alpha/tsunami.hh" 49#include "dev/alpha/tsunami_io.hh" 50#include "dev/alpha/tsunamireg.h" 51#include "mem/packet.hh" 52#include "mem/packet_access.hh" 53#include "mem/port.hh" 54#include "sim/system.hh" 55 56using namespace std; 57//Should this be AlphaISA? 58using namespace TheISA; 59
| 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/pitreg.h" 46#include "dev/rtcreg.h" 47#include "dev/alpha/tsunami_cchip.hh" 48#include "dev/alpha/tsunami.hh" 49#include "dev/alpha/tsunami_io.hh" 50#include "dev/alpha/tsunamireg.h" 51#include "mem/packet.hh" 52#include "mem/packet_access.hh" 53#include "mem/port.hh" 54#include "sim/system.hh" 55 56using namespace std; 57//Should this be AlphaISA? 58using namespace TheISA; 59
|
60TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, 61 const TsunamiIO::Params *p) 62 : _name(n), event(tsunami, p->frequency), addr(0)
| 60TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) : 61 MC146818(n, p->time, p->year_is_bcd, p->frequency), tsunami(p->tsunami)
|
63{
| 62{
|
64 memset(clock_data, 0, sizeof(clock_data)); 65 stat_regA = RTCA_32768HZ | RTCA_1024HZ; 66 stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 67 68 year = p->time.tm_year; 69 70 if (p->year_is_bcd) { 71 // The datasheet says that the year field can be either BCD or 72 // years since 1900. Linux seems to be happy with years since 73 // 1900. 74 year = year % 100; 75 int tens = year / 10; 76 int ones = year % 10; 77 year = (tens << 4) + ones; 78 } 79 80 // Unix is 0-11 for month, data seet says start at 1 81 mon = p->time.tm_mon + 1; 82 mday = p->time.tm_mday; 83 hour = p->time.tm_hour; 84 min = p->time.tm_min; 85 sec = p->time.tm_sec; 86 87 // Datasheet says 1 is sunday 88 wday = p->time.tm_wday + 1; 89 90 DPRINTFN("Real-time clock set to %s", asctime(&p->time));
| |
91} 92
| 63} 64
|
93void 94TsunamiIO::RTC::writeAddr(const uint8_t data) 95{ 96 if (data <= RTC_STAT_REGD) 97 addr = data; 98 else 99 panic("RTC addresses over 0xD are not implemented.\n"); 100} 101 102void 103TsunamiIO::RTC::writeData(const uint8_t data) 104{ 105 if (addr < RTC_STAT_REGA) 106 clock_data[addr] = data; 107 else { 108 switch (addr) { 109 case RTC_STAT_REGA: 110 if (data != (RTCA_32768HZ | RTCA_1024HZ)) 111 panic("Unimplemented RTC register A value write!\n"); 112 stat_regA = data; 113 break; 114 case RTC_STAT_REGB: 115 if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 116 panic("Write to RTC reg B bits that are not implemented!\n"); 117 118 if (data & RTCB_PRDC_IE) { 119 if (!event.scheduled()) 120 event.scheduleIntr(); 121 } else { 122 if (event.scheduled()) 123 event.deschedule(); 124 } 125 stat_regB = data; 126 break; 127 case RTC_STAT_REGC: 128 case RTC_STAT_REGD: 129 panic("RTC status registers C and D are not implemented.\n"); 130 break; 131 } 132 } 133} 134 135uint8_t 136TsunamiIO::RTC::readData() 137{ 138 if (addr < RTC_STAT_REGA) 139 return clock_data[addr]; 140 else { 141 switch (addr) { 142 case RTC_STAT_REGA: 143 // toggle UIP bit for linux 144 stat_regA ^= RTCA_UIP; 145 return stat_regA; 146 break; 147 case RTC_STAT_REGB: 148 return stat_regB; 149 break; 150 case RTC_STAT_REGC: 151 case RTC_STAT_REGD: 152 return 0x00; 153 break; 154 default: 155 panic("Shouldn't be here"); 156 } 157 } 158} 159 160void 161TsunamiIO::RTC::serialize(const string &base, ostream &os) 162{ 163 paramOut(os, base + ".addr", addr); 164 arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 165 paramOut(os, base + ".stat_regA", stat_regA); 166 paramOut(os, base + ".stat_regB", stat_regB); 167} 168 169void 170TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 171 const string §ion) 172{ 173 paramIn(cp, section, base + ".addr", addr); 174 arrayParamIn(cp, section, base + ".clock_data", clock_data, 175 sizeof(clock_data)); 176 paramIn(cp, section, base + ".stat_regA", stat_regA); 177 paramIn(cp, section, base + ".stat_regB", stat_regB); 178 179 // We're not unserializing the event here, but we need to 180 // rescehedule the event since curTick was moved forward by the 181 // checkpoint 182 event.reschedule(curTick + event.interval); 183} 184 185TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 186 : Event(&mainEventQueue), tsunami(t), interval(i) 187{ 188 DPRINTF(MC146818, "RTC Event Initilizing\n"); 189 schedule(curTick + interval); 190} 191 192void 193TsunamiIO::RTC::RTCEvent::scheduleIntr() 194{ 195 schedule(curTick + interval); 196} 197 198void 199TsunamiIO::RTC::RTCEvent::process() 200{ 201 DPRINTF(MC146818, "RTC Timer Interrupt\n"); 202 schedule(curTick + interval); 203 //Actually interrupt the processor here 204 tsunami->cchip->postRTC(); 205} 206 207const char * 208TsunamiIO::RTC::RTCEvent::description() const 209{ 210 return "tsunami RTC interrupt"; 211} 212
| |
213TsunamiIO::PITimer::PITimer(const string &name) 214 : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 215 counter2(name + ".counter2") 216{ 217 counter[0] = &counter0; 218 counter[1] = &counter0; 219 counter[2] = &counter0; 220} 221 222void 223TsunamiIO::PITimer::writeControl(const uint8_t data) 224{ 225 int rw; 226 int sel; 227 228 sel = GET_CTRL_SEL(data); 229 230 if (sel == PIT_READ_BACK) 231 panic("PITimer Read-Back Command is not implemented.\n"); 232 233 rw = GET_CTRL_RW(data); 234 235 if (rw == PIT_RW_LATCH_COMMAND) 236 counter[sel]->latchCount(); 237 else { 238 counter[sel]->setRW(rw); 239 counter[sel]->setMode(GET_CTRL_MODE(data)); 240 counter[sel]->setBCD(GET_CTRL_BCD(data)); 241 } 242} 243 244void 245TsunamiIO::PITimer::serialize(const string &base, ostream &os) 246{ 247 // serialize the counters 248 counter0.serialize(base + ".counter0", os); 249 counter1.serialize(base + ".counter1", os); 250 counter2.serialize(base + ".counter2", os); 251} 252 253void 254TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 255 const string §ion) 256{ 257 // unserialze the counters 258 counter0.unserialize(base + ".counter0", cp, section); 259 counter1.unserialize(base + ".counter1", cp, section); 260 counter2.unserialize(base + ".counter2", cp, section); 261} 262 263TsunamiIO::PITimer::Counter::Counter(const string &name) 264 : _name(name), event(this), count(0), latched_count(0), period(0), 265 mode(0), output_high(false), latch_on(false), read_byte(LSB), 266 write_byte(LSB) 267{ 268 269} 270 271void 272TsunamiIO::PITimer::Counter::latchCount() 273{ 274 // behave like a real latch 275 if(!latch_on) { 276 latch_on = true; 277 read_byte = LSB; 278 latched_count = count; 279 } 280} 281 282uint8_t 283TsunamiIO::PITimer::Counter::read() 284{ 285 if (latch_on) { 286 switch (read_byte) { 287 case LSB: 288 read_byte = MSB; 289 return (uint8_t)latched_count; 290 break; 291 case MSB: 292 read_byte = LSB; 293 latch_on = false; 294 return latched_count >> 8; 295 break; 296 default: 297 panic("Shouldn't be here"); 298 } 299 } else { 300 switch (read_byte) { 301 case LSB: 302 read_byte = MSB; 303 return (uint8_t)count; 304 break; 305 case MSB: 306 read_byte = LSB; 307 return count >> 8; 308 break; 309 default: 310 panic("Shouldn't be here"); 311 } 312 } 313} 314 315void 316TsunamiIO::PITimer::Counter::write(const uint8_t data) 317{ 318 switch (write_byte) { 319 case LSB: 320 count = (count & 0xFF00) | data; 321 322 if (event.scheduled()) 323 event.deschedule(); 324 output_high = false; 325 write_byte = MSB; 326 break; 327 328 case MSB: 329 count = (count & 0x00FF) | (data << 8); 330 period = count; 331 332 if (period > 0) { 333 DPRINTF(Tsunami, "Timer set to curTick + %d\n", 334 count * event.interval); 335 event.schedule(curTick + count * event.interval); 336 } 337 write_byte = LSB; 338 break; 339 } 340} 341 342void 343TsunamiIO::PITimer::Counter::setRW(int rw_val) 344{ 345 if (rw_val != PIT_RW_16BIT) 346 panic("Only LSB/MSB read/write is implemented.\n"); 347} 348 349void 350TsunamiIO::PITimer::Counter::setMode(int mode_val) 351{ 352 if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 353 mode_val != PIT_MODE_SQWAVE) 354 panic("PIT mode %#x is not implemented: \n", mode_val); 355 356 mode = mode_val; 357} 358 359void 360TsunamiIO::PITimer::Counter::setBCD(int bcd_val) 361{ 362 if (bcd_val != PIT_BCD_FALSE) 363 panic("PITimer does not implement BCD counts.\n"); 364} 365 366bool 367TsunamiIO::PITimer::Counter::outputHigh() 368{ 369 return output_high; 370} 371 372void 373TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 374{ 375 paramOut(os, base + ".count", count); 376 paramOut(os, base + ".latched_count", latched_count); 377 paramOut(os, base + ".period", period); 378 paramOut(os, base + ".mode", mode); 379 paramOut(os, base + ".output_high", output_high); 380 paramOut(os, base + ".latch_on", latch_on); 381 paramOut(os, base + ".read_byte", read_byte); 382 paramOut(os, base + ".write_byte", write_byte); 383 384 Tick event_tick = 0; 385 if (event.scheduled()) 386 event_tick = event.when(); 387 paramOut(os, base + ".event_tick", event_tick); 388} 389 390void 391TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 392 const string §ion) 393{ 394 paramIn(cp, section, base + ".count", count); 395 paramIn(cp, section, base + ".latched_count", latched_count); 396 paramIn(cp, section, base + ".period", period); 397 paramIn(cp, section, base + ".mode", mode); 398 paramIn(cp, section, base + ".output_high", output_high); 399 paramIn(cp, section, base + ".latch_on", latch_on); 400 paramIn(cp, section, base + ".read_byte", read_byte); 401 paramIn(cp, section, base + ".write_byte", write_byte); 402 403 Tick event_tick; 404 paramIn(cp, section, base + ".event_tick", event_tick); 405 if (event_tick) 406 event.schedule(event_tick); 407} 408 409TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 410 : Event(&mainEventQueue) 411{ 412 interval = (Tick)(Clock::Float::s / 1193180.0); 413 counter = c_ptr; 414} 415 416void 417TsunamiIO::PITimer::Counter::CounterEvent::process() 418{ 419 DPRINTF(Tsunami, "Timer Interrupt\n"); 420 switch (counter->mode) { 421 case PIT_MODE_INTTC: 422 counter->output_high = true; 423 case PIT_MODE_RATEGEN: 424 case PIT_MODE_SQWAVE: 425 break; 426 default: 427 panic("Unimplemented PITimer mode.\n"); 428 } 429} 430 431const char * 432TsunamiIO::PITimer::Counter::CounterEvent::description() const 433{ 434 return "tsunami 8254 Interval timer"; 435} 436 437TsunamiIO::TsunamiIO(const Params *p) 438 : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
| 65TsunamiIO::PITimer::PITimer(const string &name) 66 : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 67 counter2(name + ".counter2") 68{ 69 counter[0] = &counter0; 70 counter[1] = &counter0; 71 counter[2] = &counter0; 72} 73 74void 75TsunamiIO::PITimer::writeControl(const uint8_t data) 76{ 77 int rw; 78 int sel; 79 80 sel = GET_CTRL_SEL(data); 81 82 if (sel == PIT_READ_BACK) 83 panic("PITimer Read-Back Command is not implemented.\n"); 84 85 rw = GET_CTRL_RW(data); 86 87 if (rw == PIT_RW_LATCH_COMMAND) 88 counter[sel]->latchCount(); 89 else { 90 counter[sel]->setRW(rw); 91 counter[sel]->setMode(GET_CTRL_MODE(data)); 92 counter[sel]->setBCD(GET_CTRL_BCD(data)); 93 } 94} 95 96void 97TsunamiIO::PITimer::serialize(const string &base, ostream &os) 98{ 99 // serialize the counters 100 counter0.serialize(base + ".counter0", os); 101 counter1.serialize(base + ".counter1", os); 102 counter2.serialize(base + ".counter2", os); 103} 104 105void 106TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 107 const string §ion) 108{ 109 // unserialze the counters 110 counter0.unserialize(base + ".counter0", cp, section); 111 counter1.unserialize(base + ".counter1", cp, section); 112 counter2.unserialize(base + ".counter2", cp, section); 113} 114 115TsunamiIO::PITimer::Counter::Counter(const string &name) 116 : _name(name), event(this), count(0), latched_count(0), period(0), 117 mode(0), output_high(false), latch_on(false), read_byte(LSB), 118 write_byte(LSB) 119{ 120 121} 122 123void 124TsunamiIO::PITimer::Counter::latchCount() 125{ 126 // behave like a real latch 127 if(!latch_on) { 128 latch_on = true; 129 read_byte = LSB; 130 latched_count = count; 131 } 132} 133 134uint8_t 135TsunamiIO::PITimer::Counter::read() 136{ 137 if (latch_on) { 138 switch (read_byte) { 139 case LSB: 140 read_byte = MSB; 141 return (uint8_t)latched_count; 142 break; 143 case MSB: 144 read_byte = LSB; 145 latch_on = false; 146 return latched_count >> 8; 147 break; 148 default: 149 panic("Shouldn't be here"); 150 } 151 } else { 152 switch (read_byte) { 153 case LSB: 154 read_byte = MSB; 155 return (uint8_t)count; 156 break; 157 case MSB: 158 read_byte = LSB; 159 return count >> 8; 160 break; 161 default: 162 panic("Shouldn't be here"); 163 } 164 } 165} 166 167void 168TsunamiIO::PITimer::Counter::write(const uint8_t data) 169{ 170 switch (write_byte) { 171 case LSB: 172 count = (count & 0xFF00) | data; 173 174 if (event.scheduled()) 175 event.deschedule(); 176 output_high = false; 177 write_byte = MSB; 178 break; 179 180 case MSB: 181 count = (count & 0x00FF) | (data << 8); 182 period = count; 183 184 if (period > 0) { 185 DPRINTF(Tsunami, "Timer set to curTick + %d\n", 186 count * event.interval); 187 event.schedule(curTick + count * event.interval); 188 } 189 write_byte = LSB; 190 break; 191 } 192} 193 194void 195TsunamiIO::PITimer::Counter::setRW(int rw_val) 196{ 197 if (rw_val != PIT_RW_16BIT) 198 panic("Only LSB/MSB read/write is implemented.\n"); 199} 200 201void 202TsunamiIO::PITimer::Counter::setMode(int mode_val) 203{ 204 if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 205 mode_val != PIT_MODE_SQWAVE) 206 panic("PIT mode %#x is not implemented: \n", mode_val); 207 208 mode = mode_val; 209} 210 211void 212TsunamiIO::PITimer::Counter::setBCD(int bcd_val) 213{ 214 if (bcd_val != PIT_BCD_FALSE) 215 panic("PITimer does not implement BCD counts.\n"); 216} 217 218bool 219TsunamiIO::PITimer::Counter::outputHigh() 220{ 221 return output_high; 222} 223 224void 225TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 226{ 227 paramOut(os, base + ".count", count); 228 paramOut(os, base + ".latched_count", latched_count); 229 paramOut(os, base + ".period", period); 230 paramOut(os, base + ".mode", mode); 231 paramOut(os, base + ".output_high", output_high); 232 paramOut(os, base + ".latch_on", latch_on); 233 paramOut(os, base + ".read_byte", read_byte); 234 paramOut(os, base + ".write_byte", write_byte); 235 236 Tick event_tick = 0; 237 if (event.scheduled()) 238 event_tick = event.when(); 239 paramOut(os, base + ".event_tick", event_tick); 240} 241 242void 243TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 244 const string §ion) 245{ 246 paramIn(cp, section, base + ".count", count); 247 paramIn(cp, section, base + ".latched_count", latched_count); 248 paramIn(cp, section, base + ".period", period); 249 paramIn(cp, section, base + ".mode", mode); 250 paramIn(cp, section, base + ".output_high", output_high); 251 paramIn(cp, section, base + ".latch_on", latch_on); 252 paramIn(cp, section, base + ".read_byte", read_byte); 253 paramIn(cp, section, base + ".write_byte", write_byte); 254 255 Tick event_tick; 256 paramIn(cp, section, base + ".event_tick", event_tick); 257 if (event_tick) 258 event.schedule(event_tick); 259} 260 261TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 262 : Event(&mainEventQueue) 263{ 264 interval = (Tick)(Clock::Float::s / 1193180.0); 265 counter = c_ptr; 266} 267 268void 269TsunamiIO::PITimer::Counter::CounterEvent::process() 270{ 271 DPRINTF(Tsunami, "Timer Interrupt\n"); 272 switch (counter->mode) { 273 case PIT_MODE_INTTC: 274 counter->output_high = true; 275 case PIT_MODE_RATEGEN: 276 case PIT_MODE_SQWAVE: 277 break; 278 default: 279 panic("Unimplemented PITimer mode.\n"); 280 } 281} 282 283const char * 284TsunamiIO::PITimer::Counter::CounterEvent::description() const 285{ 286 return "tsunami 8254 Interval timer"; 287} 288 289TsunamiIO::TsunamiIO(const Params *p) 290 : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
439 rtc(p->name + ".rtc", p->tsunami, p)
| 291 rtc(p->name + ".rtc", p)
|
440{ 441 pioSize = 0x100; 442 443 // set the back pointer from tsunami to myself 444 tsunami->io = this; 445 446 timerData = 0; 447 picr = 0; 448 picInterrupting = false; 449} 450 451Tick 452TsunamiIO::frequency() const 453{ 454 return Clock::Frequency / params()->frequency; 455} 456 457Tick 458TsunamiIO::read(PacketPtr pkt) 459{ 460 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 461 462 Addr daddr = pkt->getAddr() - pioAddr; 463 464 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 465 pkt->getSize(), daddr); 466 467 pkt->allocate(); 468 469 if (pkt->getSize() == sizeof(uint8_t)) { 470 switch(daddr) { 471 // PIC1 mask read 472 case TSDEV_PIC1_MASK: 473 pkt->set(~mask1); 474 break; 475 case TSDEV_PIC2_MASK: 476 pkt->set(~mask2); 477 break; 478 case TSDEV_PIC1_ISR: 479 // !!! If this is modified 64bit case needs to be too 480 // Pal code has to do a 64 bit physical read because there is 481 // no load physical byte instruction 482 pkt->set(picr); 483 break; 484 case TSDEV_PIC2_ISR: 485 // PIC2 not implemnted... just return 0 486 pkt->set(0x00); 487 break; 488 case TSDEV_TMR0_DATA: 489 pkt->set(pitimer.counter0.read()); 490 break; 491 case TSDEV_TMR1_DATA: 492 pkt->set(pitimer.counter1.read()); 493 break; 494 case TSDEV_TMR2_DATA: 495 pkt->set(pitimer.counter2.read()); 496 break; 497 case TSDEV_RTC_DATA:
| 292{ 293 pioSize = 0x100; 294 295 // set the back pointer from tsunami to myself 296 tsunami->io = this; 297 298 timerData = 0; 299 picr = 0; 300 picInterrupting = false; 301} 302 303Tick 304TsunamiIO::frequency() const 305{ 306 return Clock::Frequency / params()->frequency; 307} 308 309Tick 310TsunamiIO::read(PacketPtr pkt) 311{ 312 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 313 314 Addr daddr = pkt->getAddr() - pioAddr; 315 316 DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 317 pkt->getSize(), daddr); 318 319 pkt->allocate(); 320 321 if (pkt->getSize() == sizeof(uint8_t)) { 322 switch(daddr) { 323 // PIC1 mask read 324 case TSDEV_PIC1_MASK: 325 pkt->set(~mask1); 326 break; 327 case TSDEV_PIC2_MASK: 328 pkt->set(~mask2); 329 break; 330 case TSDEV_PIC1_ISR: 331 // !!! If this is modified 64bit case needs to be too 332 // Pal code has to do a 64 bit physical read because there is 333 // no load physical byte instruction 334 pkt->set(picr); 335 break; 336 case TSDEV_PIC2_ISR: 337 // PIC2 not implemnted... just return 0 338 pkt->set(0x00); 339 break; 340 case TSDEV_TMR0_DATA: 341 pkt->set(pitimer.counter0.read()); 342 break; 343 case TSDEV_TMR1_DATA: 344 pkt->set(pitimer.counter1.read()); 345 break; 346 case TSDEV_TMR2_DATA: 347 pkt->set(pitimer.counter2.read()); 348 break; 349 case TSDEV_RTC_DATA:
|
498 pkt->set(rtc.readData());
| 350 pkt->set(rtc.readData(rtcAddr));
|
499 break; 500 case TSDEV_CTRL_PORTB: 501 if (pitimer.counter2.outputHigh()) 502 pkt->set(PORTB_SPKR_HIGH); 503 else 504 pkt->set(0x00); 505 break; 506 default: 507 panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 508 } 509 } else if (pkt->getSize() == sizeof(uint64_t)) { 510 if (daddr == TSDEV_PIC1_ISR) 511 pkt->set<uint64_t>(picr); 512 else 513 panic("I/O Read - invalid addr - va %#x size %d\n", 514 pkt->getAddr(), pkt->getSize()); 515 } else { 516 panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 517 } 518 pkt->makeAtomicResponse(); 519 return pioDelay; 520} 521 522Tick 523TsunamiIO::write(PacketPtr pkt) 524{ 525 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 526 Addr daddr = pkt->getAddr() - pioAddr; 527 528 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 529 pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 530 531 assert(pkt->getSize() == sizeof(uint8_t)); 532 533 switch(daddr) { 534 case TSDEV_PIC1_MASK: 535 mask1 = ~(pkt->get<uint8_t>()); 536 if ((picr & mask1) && !picInterrupting) { 537 picInterrupting = true; 538 tsunami->cchip->postDRIR(55); 539 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 540 } 541 if ((!(picr & mask1)) && picInterrupting) { 542 picInterrupting = false; 543 tsunami->cchip->clearDRIR(55); 544 DPRINTF(Tsunami, "clearing pic interrupt\n"); 545 } 546 break; 547 case TSDEV_PIC2_MASK: 548 mask2 = pkt->get<uint8_t>(); 549 //PIC2 Not implemented to interrupt 550 break; 551 case TSDEV_PIC1_ACK: 552 // clear the interrupt on the PIC 553 picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 554 if (!(picr & mask1)) 555 tsunami->cchip->clearDRIR(55); 556 break; 557 case TSDEV_DMA1_MODE: 558 mode1 = pkt->get<uint8_t>(); 559 break; 560 case TSDEV_DMA2_MODE: 561 mode2 = pkt->get<uint8_t>(); 562 break; 563 case TSDEV_TMR0_DATA: 564 pitimer.counter0.write(pkt->get<uint8_t>()); 565 break; 566 case TSDEV_TMR1_DATA: 567 pitimer.counter1.write(pkt->get<uint8_t>()); 568 break; 569 case TSDEV_TMR2_DATA: 570 pitimer.counter2.write(pkt->get<uint8_t>()); 571 break; 572 case TSDEV_TMR_CTRL: 573 pitimer.writeControl(pkt->get<uint8_t>()); 574 break; 575 case TSDEV_RTC_ADDR:
| 351 break; 352 case TSDEV_CTRL_PORTB: 353 if (pitimer.counter2.outputHigh()) 354 pkt->set(PORTB_SPKR_HIGH); 355 else 356 pkt->set(0x00); 357 break; 358 default: 359 panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 360 } 361 } else if (pkt->getSize() == sizeof(uint64_t)) { 362 if (daddr == TSDEV_PIC1_ISR) 363 pkt->set<uint64_t>(picr); 364 else 365 panic("I/O Read - invalid addr - va %#x size %d\n", 366 pkt->getAddr(), pkt->getSize()); 367 } else { 368 panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 369 } 370 pkt->makeAtomicResponse(); 371 return pioDelay; 372} 373 374Tick 375TsunamiIO::write(PacketPtr pkt) 376{ 377 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 378 Addr daddr = pkt->getAddr() - pioAddr; 379 380 DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 381 pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 382 383 assert(pkt->getSize() == sizeof(uint8_t)); 384 385 switch(daddr) { 386 case TSDEV_PIC1_MASK: 387 mask1 = ~(pkt->get<uint8_t>()); 388 if ((picr & mask1) && !picInterrupting) { 389 picInterrupting = true; 390 tsunami->cchip->postDRIR(55); 391 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 392 } 393 if ((!(picr & mask1)) && picInterrupting) { 394 picInterrupting = false; 395 tsunami->cchip->clearDRIR(55); 396 DPRINTF(Tsunami, "clearing pic interrupt\n"); 397 } 398 break; 399 case TSDEV_PIC2_MASK: 400 mask2 = pkt->get<uint8_t>(); 401 //PIC2 Not implemented to interrupt 402 break; 403 case TSDEV_PIC1_ACK: 404 // clear the interrupt on the PIC 405 picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 406 if (!(picr & mask1)) 407 tsunami->cchip->clearDRIR(55); 408 break; 409 case TSDEV_DMA1_MODE: 410 mode1 = pkt->get<uint8_t>(); 411 break; 412 case TSDEV_DMA2_MODE: 413 mode2 = pkt->get<uint8_t>(); 414 break; 415 case TSDEV_TMR0_DATA: 416 pitimer.counter0.write(pkt->get<uint8_t>()); 417 break; 418 case TSDEV_TMR1_DATA: 419 pitimer.counter1.write(pkt->get<uint8_t>()); 420 break; 421 case TSDEV_TMR2_DATA: 422 pitimer.counter2.write(pkt->get<uint8_t>()); 423 break; 424 case TSDEV_TMR_CTRL: 425 pitimer.writeControl(pkt->get<uint8_t>()); 426 break; 427 case TSDEV_RTC_ADDR:
|
576 rtc.writeAddr(pkt->get<uint8_t>());
| 428 rtcAddr = pkt->get<uint8_t>();
|
577 break; 578 case TSDEV_RTC_DATA:
| 429 break; 430 case TSDEV_RTC_DATA:
|
579 rtc.writeData(pkt->get());
| 431 rtc.writeData(rtcAddr, pkt->get<uint8_t>());
|
580 break; 581 case TSDEV_KBD: 582 case TSDEV_DMA1_CMND: 583 case TSDEV_DMA2_CMND: 584 case TSDEV_DMA1_MMASK: 585 case TSDEV_DMA2_MMASK: 586 case TSDEV_PIC2_ACK: 587 case TSDEV_DMA1_RESET: 588 case TSDEV_DMA2_RESET: 589 case TSDEV_DMA1_MASK: 590 case TSDEV_DMA2_MASK: 591 case TSDEV_CTRL_PORTB: 592 break; 593 default: 594 panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 595 } 596 597 pkt->makeAtomicResponse(); 598 return pioDelay; 599} 600 601void 602TsunamiIO::postPIC(uint8_t bitvector) 603{ 604 //PIC2 Is not implemented, because nothing of interest there 605 picr |= bitvector; 606 if (picr & mask1) { 607 tsunami->cchip->postDRIR(55); 608 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 609 } 610} 611 612void 613TsunamiIO::clearPIC(uint8_t bitvector) 614{ 615 //PIC2 Is not implemented, because nothing of interest there 616 picr &= ~bitvector; 617 if (!(picr & mask1)) { 618 tsunami->cchip->clearDRIR(55); 619 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 620 } 621} 622 623void 624TsunamiIO::serialize(ostream &os) 625{
| 432 break; 433 case TSDEV_KBD: 434 case TSDEV_DMA1_CMND: 435 case TSDEV_DMA2_CMND: 436 case TSDEV_DMA1_MMASK: 437 case TSDEV_DMA2_MMASK: 438 case TSDEV_PIC2_ACK: 439 case TSDEV_DMA1_RESET: 440 case TSDEV_DMA2_RESET: 441 case TSDEV_DMA1_MASK: 442 case TSDEV_DMA2_MASK: 443 case TSDEV_CTRL_PORTB: 444 break; 445 default: 446 panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 447 } 448 449 pkt->makeAtomicResponse(); 450 return pioDelay; 451} 452 453void 454TsunamiIO::postPIC(uint8_t bitvector) 455{ 456 //PIC2 Is not implemented, because nothing of interest there 457 picr |= bitvector; 458 if (picr & mask1) { 459 tsunami->cchip->postDRIR(55); 460 DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 461 } 462} 463 464void 465TsunamiIO::clearPIC(uint8_t bitvector) 466{ 467 //PIC2 Is not implemented, because nothing of interest there 468 picr &= ~bitvector; 469 if (!(picr & mask1)) { 470 tsunami->cchip->clearDRIR(55); 471 DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 472 } 473} 474 475void 476TsunamiIO::serialize(ostream &os) 477{
|
| 478 SERIALIZE_SCALAR(rtcAddr);
|
626 SERIALIZE_SCALAR(timerData); 627 SERIALIZE_SCALAR(mask1); 628 SERIALIZE_SCALAR(mask2); 629 SERIALIZE_SCALAR(mode1); 630 SERIALIZE_SCALAR(mode2); 631 SERIALIZE_SCALAR(picr); 632 SERIALIZE_SCALAR(picInterrupting); 633 634 // Serialize the timers 635 pitimer.serialize("pitimer", os); 636 rtc.serialize("rtc", os); 637} 638 639void 640TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 641{
| 479 SERIALIZE_SCALAR(timerData); 480 SERIALIZE_SCALAR(mask1); 481 SERIALIZE_SCALAR(mask2); 482 SERIALIZE_SCALAR(mode1); 483 SERIALIZE_SCALAR(mode2); 484 SERIALIZE_SCALAR(picr); 485 SERIALIZE_SCALAR(picInterrupting); 486 487 // Serialize the timers 488 pitimer.serialize("pitimer", os); 489 rtc.serialize("rtc", os); 490} 491 492void 493TsunamiIO::unserialize(Checkpoint *cp, const string §ion) 494{
|
| 495 UNSERIALIZE_SCALAR(rtcAddr);
|
642 UNSERIALIZE_SCALAR(timerData); 643 UNSERIALIZE_SCALAR(mask1); 644 UNSERIALIZE_SCALAR(mask2); 645 UNSERIALIZE_SCALAR(mode1); 646 UNSERIALIZE_SCALAR(mode2); 647 UNSERIALIZE_SCALAR(picr); 648 UNSERIALIZE_SCALAR(picInterrupting); 649 650 // Unserialize the timers 651 pitimer.unserialize("pitimer", cp, section); 652 rtc.unserialize("rtc", cp, section); 653} 654 655TsunamiIO * 656TsunamiIOParams::create() 657{ 658 return new TsunamiIO(this); 659}
| 496 UNSERIALIZE_SCALAR(timerData); 497 UNSERIALIZE_SCALAR(mask1); 498 UNSERIALIZE_SCALAR(mask2); 499 UNSERIALIZE_SCALAR(mode1); 500 UNSERIALIZE_SCALAR(mode2); 501 UNSERIALIZE_SCALAR(picr); 502 UNSERIALIZE_SCALAR(picInterrupting); 503 504 // Unserialize the timers 505 pitimer.unserialize("pitimer", cp, section); 506 rtc.unserialize("rtc", cp, section); 507} 508 509TsunamiIO * 510TsunamiIOParams::create() 511{ 512 return new TsunamiIO(this); 513}
|