2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
30 * Tsunami I/O including PIC, PIT, RTC, DMA
39 #include "base/trace.hh"
40 #include "dev/pitreg.h"
41 #include "dev/rtcreg.h"
42 #include "dev/tsunami_cchip.hh"
43 #include "dev/tsunami.hh"
44 #include "dev/tsunami_io.hh"
45 #include "dev/tsunamireg.h"
46 #include "mem/port.hh"
47 #include "sim/builder.hh"
48 #include "sim/system.hh"
51 //Should this be AlphaISA?
52 using namespace TheISA
;
54 TsunamiIO::RTC::RTC(const string
&name
, Tsunami
* t
, Tick i
)
55 : _name(name
), event(t
, i
), addr(0)
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
;
63 TsunamiIO::RTC::set_time(time_t t
)
71 wday
= tm
.tm_wday
+ 1;
76 DPRINTFN("Real-time clock set to %s", asctime(&tm
));
80 TsunamiIO::RTC::writeAddr(const uint8_t data
)
82 if (data
<= RTC_STAT_REGD
)
85 panic("RTC addresses over 0xD are not implemented.\n");
89 TsunamiIO::RTC::writeData(const uint8_t data
)
91 if (addr
< RTC_STAT_REGA
)
92 clock_data
[addr
] = data
;
96 if (data
!= (RTCA_32768HZ
| RTCA_1024HZ
))
97 panic("Unimplemented RTC register A value write!\n");
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");
104 if (data
& RTCB_PRDC_IE
) {
105 if (!event
.scheduled())
106 event
.scheduleIntr();
108 if (event
.scheduled())
115 panic("RTC status registers C and D are not implemented.\n");
122 TsunamiIO::RTC::readData(uint8_t *data
)
124 if (addr
< RTC_STAT_REGA
)
125 *data
= clock_data
[addr
];
129 // toggle UIP bit for linux
130 stat_regA
^= RTCA_UIP
;
145 TsunamiIO::RTC::serialize(const string
&base
, ostream
&os
)
147 paramOut(os
, base
+ ".addr", addr
);
148 arrayParamOut(os
, base
+ ".clock_data", clock_data
, sizeof(clock_data
));
149 paramOut(os
, base
+ ".stat_regA", stat_regA
);
150 paramOut(os
, base
+ ".stat_regB", stat_regB
);
154 TsunamiIO::RTC::unserialize(const string
&base
, Checkpoint
*cp
,
155 const string
§ion
)
157 paramIn(cp
, section
, base
+ ".addr", addr
);
158 arrayParamIn(cp
, section
, base
+ ".clock_data", clock_data
,
160 paramIn(cp
, section
, base
+ ".stat_regA", stat_regA
);
161 paramIn(cp
, section
, base
+ ".stat_regB", stat_regB
);
163 // We're not unserializing the event here, but we need to
164 // rescehedule the event since curTick was moved forward by the
166 event
.reschedule(curTick
+ event
.interval
);
169 TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami
*t
, Tick i
)
170 : Event(&mainEventQueue
), tsunami(t
), interval(i
)
172 DPRINTF(MC146818
, "RTC Event Initilizing\n");
173 schedule(curTick
+ interval
);
177 TsunamiIO::RTC::RTCEvent::scheduleIntr()
179 schedule(curTick
+ interval
);
183 TsunamiIO::RTC::RTCEvent::process()
185 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
186 schedule(curTick
+ interval
);
187 //Actually interrupt the processor here
188 tsunami
->cchip
->postRTC();
192 TsunamiIO::RTC::RTCEvent::description()
194 return "tsunami RTC interrupt";
197 TsunamiIO::PITimer::PITimer(const string
&name
)
198 : _name(name
), counter0(name
+ ".counter0"), counter1(name
+ ".counter1"),
199 counter2(name
+ ".counter2")
201 counter
[0] = &counter0
;
202 counter
[1] = &counter0
;
203 counter
[2] = &counter0
;
207 TsunamiIO::PITimer::writeControl(const uint8_t data
)
212 sel
= GET_CTRL_SEL(data
);
214 if (sel
== PIT_READ_BACK
)
215 panic("PITimer Read-Back Command is not implemented.\n");
217 rw
= GET_CTRL_RW(data
);
219 if (rw
== PIT_RW_LATCH_COMMAND
)
220 counter
[sel
]->latchCount();
222 counter
[sel
]->setRW(rw
);
223 counter
[sel
]->setMode(GET_CTRL_MODE(data
));
224 counter
[sel
]->setBCD(GET_CTRL_BCD(data
));
229 TsunamiIO::PITimer::serialize(const string
&base
, ostream
&os
)
231 // serialize the counters
232 counter0
.serialize(base
+ ".counter0", os
);
233 counter1
.serialize(base
+ ".counter1", os
);
234 counter2
.serialize(base
+ ".counter2", os
);
238 TsunamiIO::PITimer::unserialize(const string
&base
, Checkpoint
*cp
,
239 const string
§ion
)
241 // unserialze the counters
242 counter0
.unserialize(base
+ ".counter0", cp
, section
);
243 counter1
.unserialize(base
+ ".counter1", cp
, section
);
244 counter2
.unserialize(base
+ ".counter2", cp
, section
);
247 TsunamiIO::PITimer::Counter::Counter(const string
&name
)
248 : _name(name
), event(this), count(0), latched_count(0), period(0),
249 mode(0), output_high(false), latch_on(false), read_byte(LSB
),
256 TsunamiIO::PITimer::Counter::latchCount()
258 // behave like a real latch
262 latched_count
= count
;
267 TsunamiIO::PITimer::Counter::read(uint8_t *data
)
273 *data
= (uint8_t)latched_count
;
278 *data
= latched_count
>> 8;
285 *data
= (uint8_t)count
;
296 TsunamiIO::PITimer::Counter::write(const uint8_t data
)
298 switch (write_byte
) {
300 count
= (count
& 0xFF00) | data
;
302 if (event
.scheduled())
309 count
= (count
& 0x00FF) | (data
<< 8);
313 DPRINTF(Tsunami
, "Timer set to curTick + %d\n",
314 count
* event
.interval
);
315 event
.schedule(curTick
+ count
* event
.interval
);
323 TsunamiIO::PITimer::Counter::setRW(int rw_val
)
325 if (rw_val
!= PIT_RW_16BIT
)
326 panic("Only LSB/MSB read/write is implemented.\n");
330 TsunamiIO::PITimer::Counter::setMode(int mode_val
)
332 if(mode_val
!= PIT_MODE_INTTC
&& mode_val
!= PIT_MODE_RATEGEN
&&
333 mode_val
!= PIT_MODE_SQWAVE
)
334 panic("PIT mode %#x is not implemented: \n", mode_val
);
340 TsunamiIO::PITimer::Counter::setBCD(int bcd_val
)
342 if (bcd_val
!= PIT_BCD_FALSE
)
343 panic("PITimer does not implement BCD counts.\n");
347 TsunamiIO::PITimer::Counter::outputHigh()
353 TsunamiIO::PITimer::Counter::serialize(const string
&base
, ostream
&os
)
355 paramOut(os
, base
+ ".count", count
);
356 paramOut(os
, base
+ ".latched_count", latched_count
);
357 paramOut(os
, base
+ ".period", period
);
358 paramOut(os
, base
+ ".mode", mode
);
359 paramOut(os
, base
+ ".output_high", output_high
);
360 paramOut(os
, base
+ ".latch_on", latch_on
);
361 paramOut(os
, base
+ ".read_byte", read_byte
);
362 paramOut(os
, base
+ ".write_byte", write_byte
);
365 if (event
.scheduled())
366 event_tick
= event
.when();
367 paramOut(os
, base
+ ".event_tick", event_tick
);
371 TsunamiIO::PITimer::Counter::unserialize(const string
&base
, Checkpoint
*cp
,
372 const string
§ion
)
374 paramIn(cp
, section
, base
+ ".count", count
);
375 paramIn(cp
, section
, base
+ ".latched_count", latched_count
);
376 paramIn(cp
, section
, base
+ ".period", period
);
377 paramIn(cp
, section
, base
+ ".mode", mode
);
378 paramIn(cp
, section
, base
+ ".output_high", output_high
);
379 paramIn(cp
, section
, base
+ ".latch_on", latch_on
);
380 paramIn(cp
, section
, base
+ ".read_byte", read_byte
);
381 paramIn(cp
, section
, base
+ ".write_byte", write_byte
);
384 paramIn(cp
, section
, base
+ ".event_tick", event_tick
);
386 event
.schedule(event_tick
);
389 TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter
* c_ptr
)
390 : Event(&mainEventQueue
)
392 interval
= (Tick
)(Clock::Float::s
/ 1193180.0);
397 TsunamiIO::PITimer::Counter::CounterEvent::process()
399 DPRINTF(Tsunami
, "Timer Interrupt\n");
400 switch (counter
->mode
) {
402 counter
->output_high
= true;
403 case PIT_MODE_RATEGEN
:
404 case PIT_MODE_SQWAVE
:
407 panic("Unimplemented PITimer mode.\n");
412 TsunamiIO::PITimer::Counter::CounterEvent::description()
414 return "tsunami 8254 Interval timer";
417 TsunamiIO::TsunamiIO(Params
*p
)
418 : BasicPioDevice(p
), tsunami(p
->tsunami
), pitimer(p
->name
+ "pitimer"),
419 rtc(p
->name
+ ".rtc", p
->tsunami
, p
->frequency
)
423 // set the back pointer from tsunami to myself
427 rtc
.set_time(p
->init_time
== 0 ? time(NULL
) : p
->init_time
);
429 picInterrupting
= false;
433 TsunamiIO::frequency() const
435 return Clock::Frequency
/ params()->frequency
;
439 TsunamiIO::read(Packet
*pkt
)
441 assert(pkt
->result
== Unknown
);
442 assert(pkt
->addr
>= pioAddr
&& pkt
->addr
< pioAddr
+ pioSize
);
444 pkt
->time
+= pioDelay
;
445 Addr daddr
= pkt
->addr
- pioAddr
;
447 DPRINTF(Tsunami
, "io read va=%#x size=%d IOPorrt=%#x\n", pkt
->addr
,
452 if (pkt
->size
== sizeof(uint8_t)) {
455 case TSDEV_PIC1_MASK
:
458 case TSDEV_PIC2_MASK
:
462 // !!! If this is modified 64bit case needs to be too
463 // Pal code has to do a 64 bit physical read because there is
464 // no load physical byte instruction
468 // PIC2 not implemnted... just return 0
471 case TSDEV_TMR0_DATA
:
472 pitimer
.counter0
.read(pkt
->getPtr
<uint8_t>());
474 case TSDEV_TMR1_DATA
:
475 pitimer
.counter1
.read(pkt
->getPtr
<uint8_t>());
477 case TSDEV_TMR2_DATA
:
478 pitimer
.counter2
.read(pkt
->getPtr
<uint8_t>());
481 rtc
.readData(pkt
->getPtr
<uint8_t>());
483 case TSDEV_CTRL_PORTB
:
484 if (pitimer
.counter2
.outputHigh())
485 pkt
->set(PORTB_SPKR_HIGH
);
490 panic("I/O Read - va%#x size %d\n", pkt
->addr
, pkt
->size
);
492 } else if (pkt
->size
== sizeof(uint64_t)) {
493 if (daddr
== TSDEV_PIC1_ISR
)
494 pkt
->set
<uint64_t>(picr
);
496 panic("I/O Read - invalid addr - va %#x size %d\n",
497 pkt
->addr
, pkt
->size
);
499 panic("I/O Read - invalid size - va %#x size %d\n", pkt
->addr
, pkt
->size
);
501 pkt
->result
= Success
;
506 TsunamiIO::write(Packet
*pkt
)
508 pkt
->time
+= pioDelay
;
510 assert(pkt
->result
== Unknown
);
511 assert(pkt
->addr
>= pioAddr
&& pkt
->addr
< pioAddr
+ pioSize
);
512 Addr daddr
= pkt
->addr
- pioAddr
;
514 DPRINTF(Tsunami
, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
515 pkt
->addr
, pkt
->size
, pkt
->addr
& 0xfff, (uint32_t)pkt
->get
<uint8_t>());
517 assert(pkt
->size
== sizeof(uint8_t));
520 case TSDEV_PIC1_MASK
:
521 mask1
= ~(pkt
->get
<uint8_t>());
522 if ((picr
& mask1
) && !picInterrupting
) {
523 picInterrupting
= true;
524 tsunami
->cchip
->postDRIR(55);
525 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
527 if ((!(picr
& mask1
)) && picInterrupting
) {
528 picInterrupting
= false;
529 tsunami
->cchip
->clearDRIR(55);
530 DPRINTF(Tsunami
, "clearing pic interrupt\n");
533 case TSDEV_PIC2_MASK
:
534 mask2
= pkt
->get
<uint8_t>();
535 //PIC2 Not implemented to interrupt
538 // clear the interrupt on the PIC
539 picr
&= ~(1 << (pkt
->get
<uint8_t>() & 0xF));
541 tsunami
->cchip
->clearDRIR(55);
543 case TSDEV_DMA1_MODE
:
544 mode1
= pkt
->get
<uint8_t>();
546 case TSDEV_DMA2_MODE
:
547 mode2
= pkt
->get
<uint8_t>();
549 case TSDEV_TMR0_DATA
:
550 pitimer
.counter0
.write(pkt
->get
<uint8_t>());
552 case TSDEV_TMR1_DATA
:
553 pitimer
.counter1
.write(pkt
->get
<uint8_t>());
555 case TSDEV_TMR2_DATA
:
556 pitimer
.counter2
.write(pkt
->get
<uint8_t>());
559 pitimer
.writeControl(pkt
->get
<uint8_t>());
562 rtc
.writeAddr(pkt
->get
<uint8_t>());
565 rtc
.writeData(pkt
->get
<uint8_t>());
568 case TSDEV_DMA1_CMND
:
569 case TSDEV_DMA2_CMND
:
570 case TSDEV_DMA1_MMASK
:
571 case TSDEV_DMA2_MMASK
:
573 case TSDEV_DMA1_RESET
:
574 case TSDEV_DMA2_RESET
:
575 case TSDEV_DMA1_MASK
:
576 case TSDEV_DMA2_MASK
:
577 case TSDEV_CTRL_PORTB
:
580 panic("I/O Write - va%#x size %d data %#x\n", pkt
->addr
, pkt
->size
, pkt
->get
<uint8_t>());
583 pkt
->result
= Success
;
588 TsunamiIO::postPIC(uint8_t bitvector
)
590 //PIC2 Is not implemented, because nothing of interest there
593 tsunami
->cchip
->postDRIR(55);
594 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
599 TsunamiIO::clearPIC(uint8_t bitvector
)
601 //PIC2 Is not implemented, because nothing of interest there
603 if (!(picr
& mask1
)) {
604 tsunami
->cchip
->clearDRIR(55);
605 DPRINTF(Tsunami
, "clearing pic interrupt to cchip\n");
610 TsunamiIO::serialize(ostream
&os
)
612 SERIALIZE_SCALAR(timerData
);
613 SERIALIZE_SCALAR(mask1
);
614 SERIALIZE_SCALAR(mask2
);
615 SERIALIZE_SCALAR(mode1
);
616 SERIALIZE_SCALAR(mode2
);
617 SERIALIZE_SCALAR(picr
);
618 SERIALIZE_SCALAR(picInterrupting
);
620 // Serialize the timers
621 pitimer
.serialize("pitimer", os
);
622 rtc
.serialize("rtc", os
);
626 TsunamiIO::unserialize(Checkpoint
*cp
, const string
§ion
)
628 UNSERIALIZE_SCALAR(timerData
);
629 UNSERIALIZE_SCALAR(mask1
);
630 UNSERIALIZE_SCALAR(mask2
);
631 UNSERIALIZE_SCALAR(mode1
);
632 UNSERIALIZE_SCALAR(mode2
);
633 UNSERIALIZE_SCALAR(picr
);
634 UNSERIALIZE_SCALAR(picInterrupting
);
636 // Unserialize the timers
637 pitimer
.unserialize("pitimer", cp
, section
);
638 rtc
.unserialize("rtc", cp
, section
);
641 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
643 Param
<Addr
> pio_addr
;
644 Param
<Tick
> pio_latency
;
645 Param
<Tick
> frequency
;
646 SimObjectParam
<Platform
*> platform
;
647 SimObjectParam
<System
*> system
;
649 SimObjectParam
<Tsunami
*> tsunami
;
651 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
653 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
655 INIT_PARAM(pio_addr
, "Device Address"),
656 INIT_PARAM(pio_latency
, "Programmed IO latency"),
657 INIT_PARAM(frequency
, "clock interrupt frequency"),
658 INIT_PARAM(platform
, "platform"),
659 INIT_PARAM(system
, "system object"),
660 INIT_PARAM(time
, "System time to use (0 for actual time"),
661 INIT_PARAM(tsunami
, "Tsunami")
663 END_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
665 CREATE_SIM_OBJECT(TsunamiIO
)
667 TsunamiIO::Params
*p
= new TsunamiIO::Params
;
668 p
->frequency
= frequency
;
669 p
->name
= getInstanceName();
670 p
->pio_addr
= pio_addr
;
671 p
->pio_delay
= pio_latency
;
672 p
->platform
= platform
;
675 p
->tsunami
= tsunami
;
676 return new TsunamiIO(p
);
679 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO
)