tsunami_io.cc revision 4762
1803SN/A/* 21363SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 3803SN/A * All rights reserved. 4803SN/A * 5803SN/A * Redistribution and use in source and binary forms, with or without 6803SN/A * modification, are permitted provided that the following conditions are 7803SN/A * met: redistributions of source code must retain the above copyright 8803SN/A * notice, this list of conditions and the following disclaimer; 9803SN/A * redistributions in binary form must reproduce the above copyright 10803SN/A * notice, this list of conditions and the following disclaimer in the 11803SN/A * documentation and/or other materials provided with the distribution; 12803SN/A * neither the name of the copyright holders nor the names of its 13803SN/A * contributors may be used to endorse or promote products derived from 14803SN/A * this software without specific prior written permission. 15803SN/A * 16803SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17803SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18803SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19803SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20803SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21803SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22803SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23803SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24803SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25803SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26803SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665SN/A * 282665SN/A * Authors: Ali Saidi 292665SN/A * Andrew Schultz 302665SN/A * Miguel Serrano 31803SN/A */ 32768SN/A 331730SN/A/** @file 34773SN/A * Tsunami I/O including PIC, PIT, RTC, DMA 35768SN/A */ 36768SN/A 37773SN/A#include <sys/time.h> 38773SN/A 39768SN/A#include <deque> 40768SN/A#include <string> 41768SN/A#include <vector> 42768SN/A 434762Snate@binkert.org#include "base/time.hh" 44768SN/A#include "base/trace.hh" 452542SN/A#include "dev/pitreg.h" 462542SN/A#include "dev/rtcreg.h" 473540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_cchip.hh" 483540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami.hh" 493540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_io.hh" 503540Sgblack@eecs.umich.edu#include "dev/alpha/tsunamireg.h" 513348SN/A#include "mem/packet.hh" 523348SN/A#include "mem/packet_access.hh" 532542SN/A#include "mem/port.hh" 542542SN/A#include "sim/system.hh" 55768SN/A 56768SN/Ausing namespace std; 572107SN/A//Should this be AlphaISA? 582107SN/Ausing namespace TheISA; 59773SN/A 604762Snate@binkert.orgTsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, 614762Snate@binkert.org const TsunamiIO::Params *p) 624762Snate@binkert.org : _name(n), event(tsunami, p->frequency), addr(0) 631817SN/A{ 641817SN/A memset(clock_data, 0, sizeof(clock_data)); 651817SN/A stat_regA = RTCA_32768HZ | RTCA_1024HZ; 661817SN/A stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; 67773SN/A 684762Snate@binkert.org year = p->time.tm_year; 693943Sbinkertn@umich.edu 704762Snate@binkert.org if (p->year_is_bcd) { 713943Sbinkertn@umich.edu // The datasheet says that the year field can be either BCD or 723943Sbinkertn@umich.edu // years since 1900. Linux seems to be happy with years since 733943Sbinkertn@umich.edu // 1900. 743943Sbinkertn@umich.edu year = year % 100; 753943Sbinkertn@umich.edu int tens = year / 10; 763943Sbinkertn@umich.edu int ones = year % 10; 773932Sbinkertn@umich.edu year = (tens << 4) + ones; 783932Sbinkertn@umich.edu } 793932Sbinkertn@umich.edu 803943Sbinkertn@umich.edu // Unix is 0-11 for month, data seet says start at 1 814762Snate@binkert.org mon = p->time.tm_mon + 1; 824762Snate@binkert.org mday = p->time.tm_mday; 834762Snate@binkert.org hour = p->time.tm_hour; 844762Snate@binkert.org min = p->time.tm_min; 854762Snate@binkert.org sec = p->time.tm_sec; 863932Sbinkertn@umich.edu 873943Sbinkertn@umich.edu // Datasheet says 1 is sunday 884762Snate@binkert.org wday = p->time.tm_wday + 1; 893932Sbinkertn@umich.edu 904762Snate@binkert.org DPRINTFN("Real-time clock set to %s", asctime(&p->time)); 911817SN/A} 921817SN/A 931817SN/Avoid 942539SN/ATsunamiIO::RTC::writeAddr(const uint8_t data) 951817SN/A{ 962542SN/A if (data <= RTC_STAT_REGD) 972539SN/A addr = data; 981817SN/A else 991817SN/A panic("RTC addresses over 0xD are not implemented.\n"); 1001817SN/A} 1011817SN/A 1021817SN/Avoid 1032539SN/ATsunamiIO::RTC::writeData(const uint8_t data) 1041817SN/A{ 1051817SN/A if (addr < RTC_STAT_REGA) 1062539SN/A clock_data[addr] = data; 1071817SN/A else { 1081817SN/A switch (addr) { 1091817SN/A case RTC_STAT_REGA: 1102539SN/A if (data != (RTCA_32768HZ | RTCA_1024HZ)) 1111817SN/A panic("Unimplemented RTC register A value write!\n"); 1122542SN/A stat_regA = data; 1131817SN/A break; 1141817SN/A case RTC_STAT_REGB: 1152539SN/A if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) 1161817SN/A panic("Write to RTC reg B bits that are not implemented!\n"); 1171817SN/A 1182542SN/A if (data & RTCB_PRDC_IE) { 1191817SN/A if (!event.scheduled()) 1201817SN/A event.scheduleIntr(); 1211817SN/A } else { 1221817SN/A if (event.scheduled()) 1231817SN/A event.deschedule(); 1241817SN/A } 1252539SN/A stat_regB = data; 1261817SN/A break; 1271817SN/A case RTC_STAT_REGC: 1281817SN/A case RTC_STAT_REGD: 1291817SN/A panic("RTC status registers C and D are not implemented.\n"); 1301817SN/A break; 1311817SN/A } 1321817SN/A } 1331817SN/A} 1341817SN/A 1352648SN/Auint8_t 1362648SN/ATsunamiIO::RTC::readData() 1371817SN/A{ 1381817SN/A if (addr < RTC_STAT_REGA) 1392648SN/A return clock_data[addr]; 1401817SN/A else { 1411817SN/A switch (addr) { 1421817SN/A case RTC_STAT_REGA: 1431817SN/A // toggle UIP bit for linux 1441817SN/A stat_regA ^= RTCA_UIP; 1452648SN/A return stat_regA; 1461817SN/A break; 1471817SN/A case RTC_STAT_REGB: 1482648SN/A return stat_regB; 1491817SN/A break; 1501817SN/A case RTC_STAT_REGC: 1511817SN/A case RTC_STAT_REGD: 1522648SN/A return 0x00; 1531817SN/A break; 1542648SN/A default: 1552648SN/A panic("Shouldn't be here"); 1561817SN/A } 1571817SN/A } 1581817SN/A} 1591817SN/A 1601817SN/Avoid 1611854SN/ATsunamiIO::RTC::serialize(const string &base, ostream &os) 1621817SN/A{ 1631854SN/A paramOut(os, base + ".addr", addr); 1641854SN/A arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); 1651854SN/A paramOut(os, base + ".stat_regA", stat_regA); 1661854SN/A paramOut(os, base + ".stat_regB", stat_regB); 1671817SN/A} 1681817SN/A 1691817SN/Avoid 1701854SN/ATsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, 1711854SN/A const string §ion) 1721817SN/A{ 1731854SN/A paramIn(cp, section, base + ".addr", addr); 1741854SN/A arrayParamIn(cp, section, base + ".clock_data", clock_data, 1751854SN/A sizeof(clock_data)); 1761854SN/A paramIn(cp, section, base + ".stat_regA", stat_regA); 1771854SN/A paramIn(cp, section, base + ".stat_regB", stat_regB); 1781817SN/A 1791854SN/A // We're not unserializing the event here, but we need to 1801854SN/A // rescehedule the event since curTick was moved forward by the 1811854SN/A // checkpoint 1821854SN/A event.reschedule(curTick + event.interval); 1831817SN/A} 1841817SN/A 1851817SN/ATsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) 1861634SN/A : Event(&mainEventQueue), tsunami(t), interval(i) 187772SN/A{ 188773SN/A DPRINTF(MC146818, "RTC Event Initilizing\n"); 1891634SN/A schedule(curTick + interval); 190772SN/A} 191772SN/A 192772SN/Avoid 1931817SN/ATsunamiIO::RTC::RTCEvent::scheduleIntr() 1941817SN/A{ 1951817SN/A schedule(curTick + interval); 1961817SN/A} 1971817SN/A 1981817SN/Avoid 1991817SN/ATsunamiIO::RTC::RTCEvent::process() 200772SN/A{ 201776SN/A DPRINTF(MC146818, "RTC Timer Interrupt\n"); 2021634SN/A schedule(curTick + interval); 203773SN/A //Actually interrupt the processor here 204831SN/A tsunami->cchip->postRTC(); 205772SN/A} 206772SN/A 207772SN/Aconst char * 2081817SN/ATsunamiIO::RTC::RTCEvent::description() 209772SN/A{ 2101634SN/A return "tsunami RTC interrupt"; 211772SN/A} 212772SN/A 2131854SN/ATsunamiIO::PITimer::PITimer(const string &name) 2141854SN/A : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), 2151854SN/A counter2(name + ".counter2") 216918SN/A{ 2171854SN/A counter[0] = &counter0; 2181854SN/A counter[1] = &counter0; 2191854SN/A counter[2] = &counter0; 220771SN/A} 221771SN/A 222771SN/Avoid 2232539SN/ATsunamiIO::PITimer::writeControl(const uint8_t data) 224771SN/A{ 2251817SN/A int rw; 2261817SN/A int sel; 2271817SN/A 2282539SN/A sel = GET_CTRL_SEL(data); 2291817SN/A 2301817SN/A if (sel == PIT_READ_BACK) 2311817SN/A panic("PITimer Read-Back Command is not implemented.\n"); 2321817SN/A 2332542SN/A rw = GET_CTRL_RW(data); 2341817SN/A 2351817SN/A if (rw == PIT_RW_LATCH_COMMAND) 2361854SN/A counter[sel]->latchCount(); 2371817SN/A else { 2381854SN/A counter[sel]->setRW(rw); 2392539SN/A counter[sel]->setMode(GET_CTRL_MODE(data)); 2402539SN/A counter[sel]->setBCD(GET_CTRL_BCD(data)); 2411817SN/A } 242771SN/A} 243771SN/A 244771SN/Avoid 2451854SN/ATsunamiIO::PITimer::serialize(const string &base, ostream &os) 246771SN/A{ 2471817SN/A // serialize the counters 2481854SN/A counter0.serialize(base + ".counter0", os); 2491854SN/A counter1.serialize(base + ".counter1", os); 2501854SN/A counter2.serialize(base + ".counter2", os); 2511817SN/A} 2521817SN/A 2531817SN/Avoid 2541854SN/ATsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, 2551854SN/A const string §ion) 2561817SN/A{ 2571817SN/A // unserialze the counters 2581854SN/A counter0.unserialize(base + ".counter0", cp, section); 2591854SN/A counter1.unserialize(base + ".counter1", cp, section); 2601854SN/A counter2.unserialize(base + ".counter2", cp, section); 2611817SN/A} 2621817SN/A 2631854SN/ATsunamiIO::PITimer::Counter::Counter(const string &name) 2641854SN/A : _name(name), event(this), count(0), latched_count(0), period(0), 2651817SN/A mode(0), output_high(false), latch_on(false), read_byte(LSB), 2661817SN/A write_byte(LSB) 2671817SN/A{ 2681817SN/A 2691817SN/A} 2701817SN/A 2711817SN/Avoid 2721817SN/ATsunamiIO::PITimer::Counter::latchCount() 2731817SN/A{ 2741817SN/A // behave like a real latch 2751817SN/A if(!latch_on) { 2761817SN/A latch_on = true; 2771817SN/A read_byte = LSB; 2781817SN/A latched_count = count; 2791817SN/A } 2801817SN/A} 2811817SN/A 2822648SN/Auint8_t 2832648SN/ATsunamiIO::PITimer::Counter::read() 2841817SN/A{ 2851817SN/A if (latch_on) { 2861817SN/A switch (read_byte) { 2871817SN/A case LSB: 2881817SN/A read_byte = MSB; 2892648SN/A return (uint8_t)latched_count; 2901817SN/A break; 2911817SN/A case MSB: 2921817SN/A read_byte = LSB; 2931817SN/A latch_on = false; 2942648SN/A return latched_count >> 8; 2951817SN/A break; 2962648SN/A default: 2972648SN/A panic("Shouldn't be here"); 2981817SN/A } 2991817SN/A } else { 3001817SN/A switch (read_byte) { 3011817SN/A case LSB: 3021817SN/A read_byte = MSB; 3032648SN/A return (uint8_t)count; 3041817SN/A break; 3051817SN/A case MSB: 3061817SN/A read_byte = LSB; 3072648SN/A return count >> 8; 3081817SN/A break; 3092648SN/A default: 3102648SN/A panic("Shouldn't be here"); 3111817SN/A } 3121817SN/A } 3131817SN/A} 3141817SN/A 3151817SN/Avoid 3162539SN/ATsunamiIO::PITimer::Counter::write(const uint8_t data) 3171817SN/A{ 3181817SN/A switch (write_byte) { 3191817SN/A case LSB: 3202539SN/A count = (count & 0xFF00) | data; 3211817SN/A 3221817SN/A if (event.scheduled()) 3231817SN/A event.deschedule(); 3241817SN/A output_high = false; 3251817SN/A write_byte = MSB; 3261817SN/A break; 3271817SN/A 3281817SN/A case MSB: 3292539SN/A count = (count & 0x00FF) | (data << 8); 3301817SN/A period = count; 3311817SN/A 3321817SN/A if (period > 0) { 3331854SN/A DPRINTF(Tsunami, "Timer set to curTick + %d\n", 3341854SN/A count * event.interval); 3351817SN/A event.schedule(curTick + count * event.interval); 3361817SN/A } 3371817SN/A write_byte = LSB; 3381817SN/A break; 3391817SN/A } 3401817SN/A} 3411817SN/A 3421817SN/Avoid 3431817SN/ATsunamiIO::PITimer::Counter::setRW(int rw_val) 3441817SN/A{ 3451817SN/A if (rw_val != PIT_RW_16BIT) 3461817SN/A panic("Only LSB/MSB read/write is implemented.\n"); 3471817SN/A} 3481817SN/A 3491817SN/Avoid 3501817SN/ATsunamiIO::PITimer::Counter::setMode(int mode_val) 3511817SN/A{ 3521817SN/A if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && 3531817SN/A mode_val != PIT_MODE_SQWAVE) 3541817SN/A panic("PIT mode %#x is not implemented: \n", mode_val); 3551817SN/A 3561817SN/A mode = mode_val; 3571817SN/A} 3581817SN/A 3591817SN/Avoid 3601817SN/ATsunamiIO::PITimer::Counter::setBCD(int bcd_val) 3611817SN/A{ 3621817SN/A if (bcd_val != PIT_BCD_FALSE) 3631817SN/A panic("PITimer does not implement BCD counts.\n"); 3641817SN/A} 3651817SN/A 3661817SN/Abool 3671817SN/ATsunamiIO::PITimer::Counter::outputHigh() 3681817SN/A{ 3691817SN/A return output_high; 3701817SN/A} 3711817SN/A 3721817SN/Avoid 3731854SN/ATsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) 3741817SN/A{ 3751854SN/A paramOut(os, base + ".count", count); 3761854SN/A paramOut(os, base + ".latched_count", latched_count); 3771854SN/A paramOut(os, base + ".period", period); 3781854SN/A paramOut(os, base + ".mode", mode); 3791854SN/A paramOut(os, base + ".output_high", output_high); 3801854SN/A paramOut(os, base + ".latch_on", latch_on); 3811854SN/A paramOut(os, base + ".read_byte", read_byte); 3821854SN/A paramOut(os, base + ".write_byte", write_byte); 3831817SN/A 3841854SN/A Tick event_tick = 0; 3851854SN/A if (event.scheduled()) 3861854SN/A event_tick = event.when(); 3871854SN/A paramOut(os, base + ".event_tick", event_tick); 3881817SN/A} 3891817SN/A 3901817SN/Avoid 3911854SN/ATsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, 3921854SN/A const string §ion) 3931817SN/A{ 3941854SN/A paramIn(cp, section, base + ".count", count); 3951854SN/A paramIn(cp, section, base + ".latched_count", latched_count); 3961854SN/A paramIn(cp, section, base + ".period", period); 3971854SN/A paramIn(cp, section, base + ".mode", mode); 3981854SN/A paramIn(cp, section, base + ".output_high", output_high); 3991854SN/A paramIn(cp, section, base + ".latch_on", latch_on); 4001854SN/A paramIn(cp, section, base + ".read_byte", read_byte); 4011854SN/A paramIn(cp, section, base + ".write_byte", write_byte); 4021817SN/A 4031854SN/A Tick event_tick; 4041854SN/A paramIn(cp, section, base + ".event_tick", event_tick); 4051854SN/A if (event_tick) 4061854SN/A event.schedule(event_tick); 4071817SN/A} 4081817SN/A 4091817SN/ATsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) 4101817SN/A : Event(&mainEventQueue) 4111817SN/A{ 4121817SN/A interval = (Tick)(Clock::Float::s / 1193180.0); 4131817SN/A counter = c_ptr; 4141817SN/A} 4151817SN/A 4161817SN/Avoid 4171817SN/ATsunamiIO::PITimer::Counter::CounterEvent::process() 4181817SN/A{ 4191817SN/A DPRINTF(Tsunami, "Timer Interrupt\n"); 4201817SN/A switch (counter->mode) { 4211817SN/A case PIT_MODE_INTTC: 4221817SN/A counter->output_high = true; 4231817SN/A case PIT_MODE_RATEGEN: 4241817SN/A case PIT_MODE_SQWAVE: 4251817SN/A break; 4261817SN/A default: 4271817SN/A panic("Unimplemented PITimer mode.\n"); 4281817SN/A } 429771SN/A} 430771SN/A 431771SN/Aconst char * 4321817SN/ATsunamiIO::PITimer::Counter::CounterEvent::description() 433771SN/A{ 434771SN/A return "tsunami 8254 Interval timer"; 435771SN/A} 436771SN/A 4374762Snate@binkert.orgTsunamiIO::TsunamiIO(const Params *p) 4382539SN/A : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), 4394762Snate@binkert.org rtc(p->name + ".rtc", p->tsunami, p) 440768SN/A{ 4413846Shsul@eecs.umich.edu pioSize = 0x100; 442909SN/A 443803SN/A // set the back pointer from tsunami to myself 444803SN/A tsunami->io = this; 445803SN/A 446771SN/A timerData = 0; 447777SN/A picr = 0; 448777SN/A picInterrupting = false; 449773SN/A} 450773SN/A 4511634SN/ATick 4521634SN/ATsunamiIO::frequency() const 4531634SN/A{ 4542539SN/A return Clock::Frequency / params()->frequency; 4551634SN/A} 4561634SN/A 4572542SN/ATick 4583349SN/ATsunamiIO::read(PacketPtr pkt) 459768SN/A{ 4602641SN/A assert(pkt->result == Packet::Unknown); 4612641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 462768SN/A 4632641SN/A Addr daddr = pkt->getAddr() - pioAddr; 464865SN/A 4652641SN/A DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), 4662641SN/A pkt->getSize(), daddr); 467771SN/A 4682630SN/A pkt->allocate(); 4692539SN/A 4702641SN/A if (pkt->getSize() == sizeof(uint8_t)) { 471803SN/A switch(daddr) { 4721817SN/A // PIC1 mask read 4731817SN/A case TSDEV_PIC1_MASK: 4742630SN/A pkt->set(~mask1); 4752539SN/A break; 4761817SN/A case TSDEV_PIC2_MASK: 4772630SN/A pkt->set(~mask2); 4782539SN/A break; 479865SN/A case TSDEV_PIC1_ISR: 480865SN/A // !!! If this is modified 64bit case needs to be too 481865SN/A // Pal code has to do a 64 bit physical read because there is 482865SN/A // no load physical byte instruction 4832630SN/A pkt->set(picr); 4842539SN/A break; 485865SN/A case TSDEV_PIC2_ISR: 486865SN/A // PIC2 not implemnted... just return 0 4872630SN/A pkt->set(0x00); 4882539SN/A break; 4891817SN/A case TSDEV_TMR0_DATA: 4902648SN/A pkt->set(pitimer.counter0.read()); 4912542SN/A break; 4921817SN/A case TSDEV_TMR1_DATA: 4932648SN/A pkt->set(pitimer.counter1.read()); 4942542SN/A break; 4951817SN/A case TSDEV_TMR2_DATA: 4962648SN/A pkt->set(pitimer.counter2.read()); 4972539SN/A break; 498803SN/A case TSDEV_RTC_DATA: 4992648SN/A pkt->set(rtc.readData()); 5002539SN/A break; 5011817SN/A case TSDEV_CTRL_PORTB: 5021817SN/A if (pitimer.counter2.outputHigh()) 5032630SN/A pkt->set(PORTB_SPKR_HIGH); 5041817SN/A else 5052630SN/A pkt->set(0x00); 5062539SN/A break; 507803SN/A default: 5082641SN/A panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize()); 509803SN/A } 5102641SN/A } else if (pkt->getSize() == sizeof(uint64_t)) { 5112539SN/A if (daddr == TSDEV_PIC1_ISR) 5122630SN/A pkt->set<uint64_t>(picr); 5132539SN/A else 5142539SN/A panic("I/O Read - invalid addr - va %#x size %d\n", 5152641SN/A pkt->getAddr(), pkt->getSize()); 5162539SN/A } else { 5172641SN/A panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize()); 518771SN/A } 5192641SN/A pkt->result = Packet::Success; 5202539SN/A return pioDelay; 521768SN/A} 522768SN/A 5232539SN/ATick 5243349SN/ATsunamiIO::write(PacketPtr pkt) 525768SN/A{ 5262641SN/A assert(pkt->result == Packet::Unknown); 5272641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 5282641SN/A Addr daddr = pkt->getAddr() - pioAddr; 529779SN/A 530779SN/A DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", 5312641SN/A pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>()); 532768SN/A 5332641SN/A assert(pkt->getSize() == sizeof(uint8_t)); 534769SN/A 5352539SN/A switch(daddr) { 5362539SN/A case TSDEV_PIC1_MASK: 5372630SN/A mask1 = ~(pkt->get<uint8_t>()); 5382539SN/A if ((picr & mask1) && !picInterrupting) { 5392539SN/A picInterrupting = true; 5402539SN/A tsunami->cchip->postDRIR(55); 5412539SN/A DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 542803SN/A } 5432539SN/A if ((!(picr & mask1)) && picInterrupting) { 5442539SN/A picInterrupting = false; 5452539SN/A tsunami->cchip->clearDRIR(55); 5462539SN/A DPRINTF(Tsunami, "clearing pic interrupt\n"); 5472539SN/A } 5482539SN/A break; 5492539SN/A case TSDEV_PIC2_MASK: 5502630SN/A mask2 = pkt->get<uint8_t>(); 5512539SN/A //PIC2 Not implemented to interrupt 5522539SN/A break; 5532539SN/A case TSDEV_PIC1_ACK: 5542539SN/A // clear the interrupt on the PIC 5552630SN/A picr &= ~(1 << (pkt->get<uint8_t>() & 0xF)); 5562539SN/A if (!(picr & mask1)) 5572539SN/A tsunami->cchip->clearDRIR(55); 5582539SN/A break; 5592539SN/A case TSDEV_DMA1_MODE: 5602630SN/A mode1 = pkt->get<uint8_t>(); 5612539SN/A break; 5622539SN/A case TSDEV_DMA2_MODE: 5632630SN/A mode2 = pkt->get<uint8_t>(); 5642539SN/A break; 5652539SN/A case TSDEV_TMR0_DATA: 5662630SN/A pitimer.counter0.write(pkt->get<uint8_t>()); 5672539SN/A break; 5682539SN/A case TSDEV_TMR1_DATA: 5692630SN/A pitimer.counter1.write(pkt->get<uint8_t>()); 5702539SN/A break; 5712539SN/A case TSDEV_TMR2_DATA: 5722630SN/A pitimer.counter2.write(pkt->get<uint8_t>()); 5732539SN/A break; 5742539SN/A case TSDEV_TMR_CTRL: 5752630SN/A pitimer.writeControl(pkt->get<uint8_t>()); 5762539SN/A break; 5772539SN/A case TSDEV_RTC_ADDR: 5782630SN/A rtc.writeAddr(pkt->get<uint8_t>()); 5792539SN/A break; 5802539SN/A case TSDEV_RTC_DATA: 5812630SN/A rtc.writeData(pkt->get<uint8_t>()); 5822539SN/A break; 5832539SN/A case TSDEV_KBD: 5842539SN/A case TSDEV_DMA1_CMND: 5852539SN/A case TSDEV_DMA2_CMND: 5862539SN/A case TSDEV_DMA1_MMASK: 5872539SN/A case TSDEV_DMA2_MMASK: 5882539SN/A case TSDEV_PIC2_ACK: 5892539SN/A case TSDEV_DMA1_RESET: 5902539SN/A case TSDEV_DMA2_RESET: 5912539SN/A case TSDEV_DMA1_MASK: 5922539SN/A case TSDEV_DMA2_MASK: 5932539SN/A case TSDEV_CTRL_PORTB: 5942539SN/A break; 595803SN/A default: 5962641SN/A panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>()); 597769SN/A } 598769SN/A 5992641SN/A pkt->result = Packet::Success; 6002539SN/A return pioDelay; 601768SN/A} 602768SN/A 603768SN/Avoid 604777SN/ATsunamiIO::postPIC(uint8_t bitvector) 605777SN/A{ 606777SN/A //PIC2 Is not implemented, because nothing of interest there 607777SN/A picr |= bitvector; 608865SN/A if (picr & mask1) { 609817SN/A tsunami->cchip->postDRIR(55); 610777SN/A DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); 611777SN/A } 612777SN/A} 613777SN/A 614777SN/Avoid 615777SN/ATsunamiIO::clearPIC(uint8_t bitvector) 616777SN/A{ 617777SN/A //PIC2 Is not implemented, because nothing of interest there 618777SN/A picr &= ~bitvector; 619777SN/A if (!(picr & mask1)) { 620817SN/A tsunami->cchip->clearDRIR(55); 621777SN/A DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); 622777SN/A } 623777SN/A} 624777SN/A 625777SN/Avoid 6261854SN/ATsunamiIO::serialize(ostream &os) 627768SN/A{ 628811SN/A SERIALIZE_SCALAR(timerData); 629899SN/A SERIALIZE_SCALAR(mask1); 630899SN/A SERIALIZE_SCALAR(mask2); 631899SN/A SERIALIZE_SCALAR(mode1); 632899SN/A SERIALIZE_SCALAR(mode2); 633811SN/A SERIALIZE_SCALAR(picr); 634811SN/A SERIALIZE_SCALAR(picInterrupting); 635811SN/A 636919SN/A // Serialize the timers 6371854SN/A pitimer.serialize("pitimer", os); 6381854SN/A rtc.serialize("rtc", os); 639768SN/A} 640768SN/A 641768SN/Avoid 6421854SN/ATsunamiIO::unserialize(Checkpoint *cp, const string §ion) 643768SN/A{ 644811SN/A UNSERIALIZE_SCALAR(timerData); 645899SN/A UNSERIALIZE_SCALAR(mask1); 646899SN/A UNSERIALIZE_SCALAR(mask2); 647899SN/A UNSERIALIZE_SCALAR(mode1); 648899SN/A UNSERIALIZE_SCALAR(mode2); 649811SN/A UNSERIALIZE_SCALAR(picr); 650811SN/A UNSERIALIZE_SCALAR(picInterrupting); 651919SN/A 652919SN/A // Unserialize the timers 6531854SN/A pitimer.unserialize("pitimer", cp, section); 6541854SN/A rtc.unserialize("rtc", cp, section); 655768SN/A} 656768SN/A 6574762Snate@binkert.orgTsunamiIO * 6584762Snate@binkert.orgTsunamiIOParams::create() 659768SN/A{ 6604762Snate@binkert.org return new TsunamiIO(this); 661768SN/A} 662