tsunami_io.cc revision 1817
113325Sgabeblack@google.com/*
213325Sgabeblack@google.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
313325Sgabeblack@google.com * All rights reserved.
413325Sgabeblack@google.com *
513325Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
613325Sgabeblack@google.com * modification, are permitted provided that the following conditions are
713325Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
813325Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
913325Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1013325Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1113325Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1213325Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1313325Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1413325Sgabeblack@google.com * this software without specific prior written permission.
1513325Sgabeblack@google.com *
1613325Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713325Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813325Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913325Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013325Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113325Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213325Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313325Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413325Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513325Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613325Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713325Sgabeblack@google.com */
2813325Sgabeblack@google.com
2913325Sgabeblack@google.com/** @file
3013325Sgabeblack@google.com * Tsunami I/O including PIC, PIT, RTC, DMA
3113325Sgabeblack@google.com */
3213325Sgabeblack@google.com
3313325Sgabeblack@google.com#include <sys/time.h>
3413325Sgabeblack@google.com
3513325Sgabeblack@google.com#include <deque>
3613325Sgabeblack@google.com#include <string>
3713325Sgabeblack@google.com#include <vector>
3813325Sgabeblack@google.com
3913325Sgabeblack@google.com#include "base/trace.hh"
4013325Sgabeblack@google.com#include "dev/tsunami_io.hh"
4113325Sgabeblack@google.com#include "dev/tsunami.hh"
4213325Sgabeblack@google.com#include "dev/pitreg.h"
4313325Sgabeblack@google.com#include "mem/bus/bus.hh"
4413325Sgabeblack@google.com#include "mem/bus/pio_interface.hh"
4513325Sgabeblack@google.com#include "mem/bus/pio_interface_impl.hh"
4613325Sgabeblack@google.com#include "sim/builder.hh"
4713325Sgabeblack@google.com#include "dev/tsunami_cchip.hh"
4813325Sgabeblack@google.com#include "dev/tsunamireg.h"
4913325Sgabeblack@google.com#include "dev/rtcreg.h"
5013325Sgabeblack@google.com#include "mem/functional/memory_control.hh"
5113325Sgabeblack@google.com
5213325Sgabeblack@google.comusing namespace std;
53
54TsunamiIO::RTC::RTC(Tsunami* t, Tick i)
55    : SimObject("RTC"), event(t, i), addr(0)
56{
57    memset(clock_data, 0, sizeof(clock_data));
58    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
59    stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
60}
61
62void
63TsunamiIO::RTC::set_time(time_t t)
64{
65    struct tm tm;
66    gmtime_r(&t, &tm);
67
68    sec = tm.tm_sec;
69    min = tm.tm_min;
70    hour = tm.tm_hour;
71    wday = tm.tm_wday + 1;
72    mday = tm.tm_mday;
73    mon = tm.tm_mon + 1;
74    year = tm.tm_year;
75
76    DPRINTFN("Real-time clock set to %s", asctime(&tm));
77}
78
79void
80TsunamiIO::RTC::writeAddr(const uint8_t *data)
81{
82    if (*data <= RTC_STAT_REGD)
83        addr = *data;
84    else
85        panic("RTC addresses over 0xD are not implemented.\n");
86}
87
88void
89TsunamiIO::RTC::writeData(const uint8_t *data)
90{
91    if (addr < RTC_STAT_REGA)
92        clock_data[addr] = *data;
93    else {
94        switch (addr) {
95          case RTC_STAT_REGA:
96            if (*data != (RTCA_32768HZ | RTCA_1024HZ))
97                panic("Unimplemented RTC register A value write!\n");
98            stat_regA = *data;
99            break;
100          case RTC_STAT_REGB:
101            if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
102                panic("Write to RTC reg B bits that are not implemented!\n");
103
104            if (*data & RTCB_PRDC_IE) {
105                if (!event.scheduled())
106                    event.scheduleIntr();
107            } else {
108                if (event.scheduled())
109                    event.deschedule();
110            }
111            stat_regB = *data;
112            break;
113          case RTC_STAT_REGC:
114          case RTC_STAT_REGD:
115            panic("RTC status registers C and D are not implemented.\n");
116            break;
117        }
118    }
119}
120
121void
122TsunamiIO::RTC::readData(uint8_t *data)
123{
124    if (addr < RTC_STAT_REGA)
125        *data = clock_data[addr];
126    else {
127        switch (addr) {
128          case RTC_STAT_REGA:
129            // toggle UIP bit for linux
130            stat_regA ^= RTCA_UIP;
131            *data = stat_regA;
132            break;
133          case RTC_STAT_REGB:
134            *data = stat_regB;
135            break;
136          case RTC_STAT_REGC:
137          case RTC_STAT_REGD:
138            *data = 0x00;
139            break;
140        }
141    }
142}
143
144void
145TsunamiIO::RTC::serialize(std::ostream &os)
146{
147    SERIALIZE_SCALAR(addr);
148    SERIALIZE_ARRAY(clock_data, sizeof(clock_data));
149    SERIALIZE_SCALAR(stat_regA);
150    SERIALIZE_SCALAR(stat_regB);
151
152    // serialize the RTC event
153    nameOut(os, csprintf("%s.event", name()));
154    event.serialize(os);
155}
156
157void
158TsunamiIO::RTC::unserialize(Checkpoint *cp, const std::string &section)
159{
160    UNSERIALIZE_SCALAR(addr);
161    UNSERIALIZE_ARRAY(clock_data, sizeof(clock_data));
162    UNSERIALIZE_SCALAR(stat_regA);
163    UNSERIALIZE_SCALAR(stat_regB);
164
165    // unserialze the event
166    event.unserialize(cp, csprintf("%s.event", section));
167}
168
169TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i)
170    : Event(&mainEventQueue), tsunami(t), interval(i)
171{
172    DPRINTF(MC146818, "RTC Event Initilizing\n");
173    schedule(curTick + interval);
174}
175
176void
177TsunamiIO::RTC::RTCEvent::scheduleIntr()
178{
179  schedule(curTick + interval);
180}
181
182void
183TsunamiIO::RTC::RTCEvent::process()
184{
185    DPRINTF(MC146818, "RTC Timer Interrupt\n");
186    schedule(curTick + interval);
187    //Actually interrupt the processor here
188    tsunami->cchip->postRTC();
189}
190
191const char *
192TsunamiIO::RTC::RTCEvent::description()
193{
194    return "tsunami RTC interrupt";
195}
196
197void
198TsunamiIO::RTC::RTCEvent::serialize(std::ostream &os)
199{
200    Tick time = when();
201    SERIALIZE_SCALAR(time);
202}
203
204void
205TsunamiIO::RTC::RTCEvent::unserialize(Checkpoint *cp, const std::string &section)
206{
207    Tick time;
208    UNSERIALIZE_SCALAR(time);
209    reschedule(time);
210}
211
212TsunamiIO::PITimer::PITimer()
213    : SimObject("PITimer"), counter0(counter[0]), counter1(counter[1]),
214      counter2(counter[2])
215{
216
217}
218
219void
220TsunamiIO::PITimer::writeControl(const uint8_t *data)
221{
222    int rw;
223    int sel;
224
225    sel = GET_CTRL_SEL(*data);
226
227    if (sel == PIT_READ_BACK)
228       panic("PITimer Read-Back Command is not implemented.\n");
229
230    rw = GET_CTRL_RW(*data);
231
232    if (rw == PIT_RW_LATCH_COMMAND)
233        counter[sel].latchCount();
234    else {
235        counter[sel].setRW(rw);
236        counter[sel].setMode(GET_CTRL_MODE(*data));
237        counter[sel].setBCD(GET_CTRL_BCD(*data));
238    }
239}
240
241void
242TsunamiIO::PITimer::serialize(std::ostream &os)
243{
244    // serialize the counters
245    nameOut(os, csprintf("%s.counter0", name()));
246    counter0.serialize(os);
247
248    nameOut(os, csprintf("%s.counter1", name()));
249    counter1.serialize(os);
250
251    nameOut(os, csprintf("%s.counter2", name()));
252    counter2.serialize(os);
253}
254
255void
256TsunamiIO::PITimer::unserialize(Checkpoint *cp, const std::string &section)
257{
258    // unserialze the counters
259    counter0.unserialize(cp, csprintf("%s.counter0", section));
260    counter1.unserialize(cp, csprintf("%s.counter1", section));
261    counter2.unserialize(cp, csprintf("%s.counter2", section));
262}
263
264TsunamiIO::PITimer::Counter::Counter()
265    : SimObject("Counter"), event(this), count(0), latched_count(0), period(0),
266      mode(0), output_high(false), latch_on(false), read_byte(LSB),
267      write_byte(LSB)
268{
269
270}
271
272void
273TsunamiIO::PITimer::Counter::latchCount()
274{
275    // behave like a real latch
276    if(!latch_on) {
277        latch_on = true;
278        read_byte = LSB;
279        latched_count = count;
280    }
281}
282
283void
284TsunamiIO::PITimer::Counter::read(uint8_t *data)
285{
286    if (latch_on) {
287        switch (read_byte) {
288          case LSB:
289            read_byte = MSB;
290            *data = (uint8_t)latched_count;
291            break;
292          case MSB:
293            read_byte = LSB;
294            latch_on = false;
295            *data = latched_count >> 8;
296            break;
297        }
298    } else {
299        switch (read_byte) {
300          case LSB:
301            read_byte = MSB;
302            *data = (uint8_t)count;
303            break;
304          case MSB:
305            read_byte = LSB;
306            *data = count >> 8;
307            break;
308        }
309    }
310}
311
312void
313TsunamiIO::PITimer::Counter::write(const uint8_t *data)
314{
315    switch (write_byte) {
316      case LSB:
317        count = (count & 0xFF00) | *data;
318
319        if (event.scheduled())
320          event.deschedule();
321        output_high = false;
322        write_byte = MSB;
323        break;
324
325      case MSB:
326        count = (count & 0x00FF) | (*data << 8);
327        period = count;
328
329        if (period > 0) {
330            DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * event.interval);
331            event.schedule(curTick + count * event.interval);
332        }
333        write_byte = LSB;
334        break;
335    }
336}
337
338void
339TsunamiIO::PITimer::Counter::setRW(int rw_val)
340{
341    if (rw_val != PIT_RW_16BIT)
342        panic("Only LSB/MSB read/write is implemented.\n");
343}
344
345void
346TsunamiIO::PITimer::Counter::setMode(int mode_val)
347{
348    if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
349       mode_val != PIT_MODE_SQWAVE)
350        panic("PIT mode %#x is not implemented: \n", mode_val);
351
352    mode = mode_val;
353}
354
355void
356TsunamiIO::PITimer::Counter::setBCD(int bcd_val)
357{
358    if (bcd_val != PIT_BCD_FALSE)
359        panic("PITimer does not implement BCD counts.\n");
360}
361
362bool
363TsunamiIO::PITimer::Counter::outputHigh()
364{
365    return output_high;
366}
367
368void
369TsunamiIO::PITimer::Counter::serialize(std::ostream &os)
370{
371    SERIALIZE_SCALAR(count);
372    SERIALIZE_SCALAR(latched_count);
373    SERIALIZE_SCALAR(period);
374    SERIALIZE_SCALAR(mode);
375    SERIALIZE_SCALAR(output_high);
376    SERIALIZE_SCALAR(latch_on);
377    SERIALIZE_SCALAR(read_byte);
378    SERIALIZE_SCALAR(write_byte);
379
380    // serialize the counter event
381    nameOut(os, csprintf("%s.event", name()));
382    event.serialize(os);
383}
384
385void
386TsunamiIO::PITimer::Counter::unserialize(Checkpoint *cp, const std::string &section)
387{
388    UNSERIALIZE_SCALAR(count);
389    UNSERIALIZE_SCALAR(latched_count);
390    UNSERIALIZE_SCALAR(period);
391    UNSERIALIZE_SCALAR(mode);
392    UNSERIALIZE_SCALAR(output_high);
393    UNSERIALIZE_SCALAR(latch_on);
394    UNSERIALIZE_SCALAR(read_byte);
395    UNSERIALIZE_SCALAR(write_byte);
396
397    // unserialze the counter event
398    event.unserialize(cp, csprintf("%s.event", section));
399}
400
401TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
402    : Event(&mainEventQueue)
403{
404    interval = (Tick)(Clock::Float::s / 1193180.0);
405    counter = c_ptr;
406}
407
408void
409TsunamiIO::PITimer::Counter::CounterEvent::process()
410{
411    DPRINTF(Tsunami, "Timer Interrupt\n");
412    switch (counter->mode) {
413      case PIT_MODE_INTTC:
414        counter->output_high = true;
415      case PIT_MODE_RATEGEN:
416      case PIT_MODE_SQWAVE:
417        break;
418      default:
419        panic("Unimplemented PITimer mode.\n");
420    }
421}
422
423const char *
424TsunamiIO::PITimer::Counter::CounterEvent::description()
425{
426    return "tsunami 8254 Interval timer";
427}
428
429void
430TsunamiIO::PITimer::Counter::CounterEvent::serialize(std::ostream &os)
431{
432    Tick time = scheduled() ? when() : 0;
433    SERIALIZE_SCALAR(time);
434    SERIALIZE_SCALAR(interval);
435}
436
437void
438TsunamiIO::PITimer::Counter::CounterEvent::unserialize(Checkpoint *cp, const std::string &section)
439{
440    Tick time;
441    UNSERIALIZE_SCALAR(time);
442    UNSERIALIZE_SCALAR(interval);
443    if (time)
444        schedule(time);
445}
446
447TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
448                     Addr a, MemoryController *mmu, HierParams *hier, Bus *bus,
449                     Tick pio_latency, Tick ci)
450    : PioDevice(name, t), addr(a), clockInterval(ci), tsunami(t), rtc(t, ci)
451{
452    mmu->add_child(this, RangeSize(addr, size));
453
454    if (bus) {
455        pioInterface = newPioInterface(name, hier, bus, this,
456                                       &TsunamiIO::cacheAccess);
457        pioInterface->addAddrRange(RangeSize(addr, size));
458        pioLatency = pio_latency * bus->clockRate;
459    }
460
461    // set the back pointer from tsunami to myself
462    tsunami->io = this;
463
464    timerData = 0;
465    rtc.set_time(init_time == 0 ? time(NULL) : init_time);
466    picr = 0;
467    picInterrupting = false;
468}
469
470Tick
471TsunamiIO::frequency() const
472{
473    return Clock::Frequency / clockInterval;
474}
475
476Fault
477TsunamiIO::read(MemReqPtr &req, uint8_t *data)
478{
479    DPRINTF(Tsunami, "io read  va=%#x size=%d IOPorrt=%#x\n",
480            req->vaddr, req->size, req->vaddr & 0xfff);
481
482    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
483
484
485    switch(req->size) {
486      case sizeof(uint8_t):
487        switch(daddr) {
488          // PIC1 mask read
489          case TSDEV_PIC1_MASK:
490            *(uint8_t*)data = ~mask1;
491            return No_Fault;
492          case TSDEV_PIC2_MASK:
493            *(uint8_t*)data = ~mask2;
494            return No_Fault;
495          case TSDEV_PIC1_ISR:
496              // !!! If this is modified 64bit case needs to be too
497              // Pal code has to do a 64 bit physical read because there is
498              // no load physical byte instruction
499              *(uint8_t*)data = picr;
500              return No_Fault;
501          case TSDEV_PIC2_ISR:
502              // PIC2 not implemnted... just return 0
503              *(uint8_t*)data = 0x00;
504              return No_Fault;
505          case TSDEV_TMR0_DATA:
506            pitimer.counter0.read(data);
507            return No_Fault;
508          case TSDEV_TMR1_DATA:
509            pitimer.counter1.read(data);
510            return No_Fault;
511          case TSDEV_TMR2_DATA:
512            pitimer.counter2.read(data);
513            return No_Fault;
514          case TSDEV_RTC_DATA:
515            rtc.readData(data);
516            return No_Fault;
517          case TSDEV_CTRL_PORTB:
518            if (pitimer.counter2.outputHigh())
519                *data = PORTB_SPKR_HIGH;
520            else
521                *data = 0x00;
522            return No_Fault;
523          default:
524            panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
525        }
526      case sizeof(uint16_t):
527      case sizeof(uint32_t):
528        panic("I/O Read - invalid size - va %#x size %d\n",
529              req->vaddr, req->size);
530
531      case sizeof(uint64_t):
532       switch(daddr) {
533          case TSDEV_PIC1_ISR:
534              // !!! If this is modified 8bit case needs to be too
535              // Pal code has to do a 64 bit physical read because there is
536              // no load physical byte instruction
537              *(uint64_t*)data = (uint64_t)picr;
538              return No_Fault;
539          default:
540              panic("I/O Read - invalid size - va %#x size %d\n",
541                    req->vaddr, req->size);
542       }
543
544      default:
545        panic("I/O Read - invalid size - va %#x size %d\n",
546              req->vaddr, req->size);
547    }
548    panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
549
550    return No_Fault;
551}
552
553Fault
554TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
555{
556
557#if TRACING_ON
558    uint8_t dt = *(uint8_t*)data;
559    uint64_t dt64 = dt;
560#endif
561
562    DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
563            req->vaddr, req->size, req->vaddr & 0xfff, dt64);
564
565    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
566
567    switch(req->size) {
568      case sizeof(uint8_t):
569        switch(daddr) {
570          case TSDEV_PIC1_MASK:
571            mask1 = ~(*(uint8_t*)data);
572            if ((picr & mask1) && !picInterrupting) {
573                picInterrupting = true;
574                tsunami->cchip->postDRIR(55);
575                DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
576            }
577            if ((!(picr & mask1)) && picInterrupting) {
578                picInterrupting = false;
579                tsunami->cchip->clearDRIR(55);
580                DPRINTF(Tsunami, "clearing pic interrupt\n");
581            }
582            return No_Fault;
583          case TSDEV_PIC2_MASK:
584            mask2 = *(uint8_t*)data;
585            //PIC2 Not implemented to interrupt
586            return No_Fault;
587          case TSDEV_PIC1_ACK:
588            // clear the interrupt on the PIC
589            picr &= ~(1 << (*(uint8_t*)data & 0xF));
590            if (!(picr & mask1))
591                tsunami->cchip->clearDRIR(55);
592            return No_Fault;
593          case TSDEV_DMA1_CMND:
594            return No_Fault;
595          case TSDEV_DMA2_CMND:
596            return No_Fault;
597          case TSDEV_DMA1_MMASK:
598            return No_Fault;
599          case TSDEV_DMA2_MMASK:
600            return No_Fault;
601          case TSDEV_PIC2_ACK:
602            return No_Fault;
603          case TSDEV_DMA1_RESET:
604            return No_Fault;
605          case TSDEV_DMA2_RESET:
606            return No_Fault;
607          case TSDEV_DMA1_MODE:
608            mode1 = *(uint8_t*)data;
609            return No_Fault;
610          case TSDEV_DMA2_MODE:
611            mode2 = *(uint8_t*)data;
612            return No_Fault;
613          case TSDEV_DMA1_MASK:
614          case TSDEV_DMA2_MASK:
615            return No_Fault;
616          case TSDEV_TMR0_DATA:
617            pitimer.counter0.write(data);
618            return No_Fault;
619          case TSDEV_TMR1_DATA:
620            pitimer.counter1.write(data);
621            return No_Fault;
622          case TSDEV_TMR2_DATA:
623            pitimer.counter2.write(data);
624            return No_Fault;
625          case TSDEV_TMR_CTRL:
626            pitimer.writeControl(data);
627            return No_Fault;
628          case TSDEV_RTC_ADDR:
629            rtc.writeAddr(data);
630            return No_Fault;
631          case TSDEV_KBD:
632            return No_Fault;
633          case TSDEV_RTC_DATA:
634            rtc.writeData(data);
635            return No_Fault;
636          case TSDEV_CTRL_PORTB:
637            // System Control Port B not implemented
638            return No_Fault;
639          default:
640            panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data);
641        }
642      case sizeof(uint16_t):
643      case sizeof(uint32_t):
644      case sizeof(uint64_t):
645      default:
646        panic("I/O Write - invalid size - va %#x size %d\n",
647              req->vaddr, req->size);
648    }
649
650
651    return No_Fault;
652}
653
654void
655TsunamiIO::postPIC(uint8_t bitvector)
656{
657    //PIC2 Is not implemented, because nothing of interest there
658    picr |= bitvector;
659    if (picr & mask1) {
660        tsunami->cchip->postDRIR(55);
661        DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
662    }
663}
664
665void
666TsunamiIO::clearPIC(uint8_t bitvector)
667{
668    //PIC2 Is not implemented, because nothing of interest there
669    picr &= ~bitvector;
670    if (!(picr & mask1)) {
671        tsunami->cchip->clearDRIR(55);
672        DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
673    }
674}
675
676Tick
677TsunamiIO::cacheAccess(MemReqPtr &req)
678{
679    return curTick + pioLatency;
680}
681
682void
683TsunamiIO::serialize(std::ostream &os)
684{
685    SERIALIZE_SCALAR(timerData);
686    SERIALIZE_SCALAR(mask1);
687    SERIALIZE_SCALAR(mask2);
688    SERIALIZE_SCALAR(mode1);
689    SERIALIZE_SCALAR(mode2);
690    SERIALIZE_SCALAR(picr);
691    SERIALIZE_SCALAR(picInterrupting);
692
693    // Serialize the timers
694    nameOut(os, csprintf("%s.pitimer", name()));
695    pitimer.serialize(os);
696    nameOut(os, csprintf("%s.rtc", name()));
697    rtc.serialize(os);
698}
699
700void
701TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
702{
703    UNSERIALIZE_SCALAR(timerData);
704    UNSERIALIZE_SCALAR(mask1);
705    UNSERIALIZE_SCALAR(mask2);
706    UNSERIALIZE_SCALAR(mode1);
707    UNSERIALIZE_SCALAR(mode2);
708    UNSERIALIZE_SCALAR(picr);
709    UNSERIALIZE_SCALAR(picInterrupting);
710
711    // Unserialize the timers
712    pitimer.unserialize(cp, csprintf("%s.pitimer", section));
713    rtc.unserialize(cp, csprintf("%s.rtc", section));
714}
715
716BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
717
718    SimObjectParam<Tsunami *> tsunami;
719    Param<time_t> time;
720    SimObjectParam<MemoryController *> mmu;
721    Param<Addr> addr;
722    SimObjectParam<Bus*> io_bus;
723    Param<Tick> pio_latency;
724    SimObjectParam<HierParams *> hier;
725    Param<Tick> frequency;
726
727END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
728
729BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
730
731    INIT_PARAM(tsunami, "Tsunami"),
732    INIT_PARAM(time, "System time to use (0 for actual time"),
733    INIT_PARAM(mmu, "Memory Controller"),
734    INIT_PARAM(addr, "Device Address"),
735    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
736    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
737    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
738    INIT_PARAM(frequency, "clock interrupt frequency")
739
740END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
741
742CREATE_SIM_OBJECT(TsunamiIO)
743{
744    return new TsunamiIO(getInstanceName(), tsunami, time,  addr, mmu, hier,
745                         io_bus, pio_latency, frequency);
746}
747
748REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
749