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