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.
34 * Tsunami I/O including PIC, PIT, RTC, DMA
43 #include "base/trace.hh"
44 #include "dev/pitreg.h"
45 #include "dev/rtcreg.h"
46 #include "dev/tsunami_cchip.hh"
47 #include "dev/tsunami.hh"
48 #include "dev/tsunami_io.hh"
49 #include "dev/tsunamireg.h"
50 #include "mem/port.hh"
51 #include "sim/builder.hh"
52 #include "sim/system.hh"
55 //Should this be AlphaISA?
56 using namespace TheISA
;
58 TsunamiIO::RTC::RTC(const string
&name
, Tsunami
* t
, Tick i
)
59 : _name(name
), event(t
, i
), addr(0)
61 memset(clock_data
, 0, sizeof(clock_data
));
62 stat_regA
= RTCA_32768HZ
| RTCA_1024HZ
;
63 stat_regB
= RTCB_PRDC_IE
|RTCB_BIN
| RTCB_24HR
;
67 TsunamiIO::RTC::set_time(time_t t
)
75 wday
= tm
.tm_wday
+ 1;
80 DPRINTFN("Real-time clock set to %s", asctime(&tm
));
84 TsunamiIO::RTC::writeAddr(const uint8_t data
)
86 if (data
<= RTC_STAT_REGD
)
89 panic("RTC addresses over 0xD are not implemented.\n");
93 TsunamiIO::RTC::writeData(const uint8_t data
)
95 if (addr
< RTC_STAT_REGA
)
96 clock_data
[addr
] = data
;
100 if (data
!= (RTCA_32768HZ
| RTCA_1024HZ
))
101 panic("Unimplemented RTC register A value write!\n");
105 if ((data
& ~(RTCB_PRDC_IE
| RTCB_SQWE
)) != (RTCB_BIN
| RTCB_24HR
))
106 panic("Write to RTC reg B bits that are not implemented!\n");
108 if (data
& RTCB_PRDC_IE
) {
109 if (!event
.scheduled())
110 event
.scheduleIntr();
112 if (event
.scheduled())
119 panic("RTC status registers C and D are not implemented.\n");
126 TsunamiIO::RTC::readData()
128 if (addr
< RTC_STAT_REGA
)
129 return clock_data
[addr
];
133 // toggle UIP bit for linux
134 stat_regA
^= RTCA_UIP
;
145 panic("Shouldn't be here");
151 TsunamiIO::RTC::serialize(const string
&base
, ostream
&os
)
153 paramOut(os
, base
+ ".addr", addr
);
154 arrayParamOut(os
, base
+ ".clock_data", clock_data
, sizeof(clock_data
));
155 paramOut(os
, base
+ ".stat_regA", stat_regA
);
156 paramOut(os
, base
+ ".stat_regB", stat_regB
);
160 TsunamiIO::RTC::unserialize(const string
&base
, Checkpoint
*cp
,
161 const string
§ion
)
163 paramIn(cp
, section
, base
+ ".addr", addr
);
164 arrayParamIn(cp
, section
, base
+ ".clock_data", clock_data
,
166 paramIn(cp
, section
, base
+ ".stat_regA", stat_regA
);
167 paramIn(cp
, section
, base
+ ".stat_regB", stat_regB
);
169 // We're not unserializing the event here, but we need to
170 // rescehedule the event since curTick was moved forward by the
172 event
.reschedule(curTick
+ event
.interval
);
175 TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami
*t
, Tick i
)
176 : Event(&mainEventQueue
), tsunami(t
), interval(i
)
178 DPRINTF(MC146818
, "RTC Event Initilizing\n");
179 schedule(curTick
+ interval
);
183 TsunamiIO::RTC::RTCEvent::scheduleIntr()
185 schedule(curTick
+ interval
);
189 TsunamiIO::RTC::RTCEvent::process()
191 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
192 schedule(curTick
+ interval
);
193 //Actually interrupt the processor here
194 tsunami
->cchip
->postRTC();
198 TsunamiIO::RTC::RTCEvent::description()
200 return "tsunami RTC interrupt";
203 TsunamiIO::PITimer::PITimer(const string
&name
)
204 : _name(name
), counter0(name
+ ".counter0"), counter1(name
+ ".counter1"),
205 counter2(name
+ ".counter2")
207 counter
[0] = &counter0
;
208 counter
[1] = &counter0
;
209 counter
[2] = &counter0
;
213 TsunamiIO::PITimer::writeControl(const uint8_t data
)
218 sel
= GET_CTRL_SEL(data
);
220 if (sel
== PIT_READ_BACK
)
221 panic("PITimer Read-Back Command is not implemented.\n");
223 rw
= GET_CTRL_RW(data
);
225 if (rw
== PIT_RW_LATCH_COMMAND
)
226 counter
[sel
]->latchCount();
228 counter
[sel
]->setRW(rw
);
229 counter
[sel
]->setMode(GET_CTRL_MODE(data
));
230 counter
[sel
]->setBCD(GET_CTRL_BCD(data
));
235 TsunamiIO::PITimer::serialize(const string
&base
, ostream
&os
)
237 // serialize the counters
238 counter0
.serialize(base
+ ".counter0", os
);
239 counter1
.serialize(base
+ ".counter1", os
);
240 counter2
.serialize(base
+ ".counter2", os
);
244 TsunamiIO::PITimer::unserialize(const string
&base
, Checkpoint
*cp
,
245 const string
§ion
)
247 // unserialze the counters
248 counter0
.unserialize(base
+ ".counter0", cp
, section
);
249 counter1
.unserialize(base
+ ".counter1", cp
, section
);
250 counter2
.unserialize(base
+ ".counter2", cp
, section
);
253 TsunamiIO::PITimer::Counter::Counter(const string
&name
)
254 : _name(name
), event(this), count(0), latched_count(0), period(0),
255 mode(0), output_high(false), latch_on(false), read_byte(LSB
),
262 TsunamiIO::PITimer::Counter::latchCount()
264 // behave like a real latch
268 latched_count
= count
;
273 TsunamiIO::PITimer::Counter::read()
279 return (uint8_t)latched_count
;
284 return latched_count
>> 8;
287 panic("Shouldn't be here");
293 return (uint8_t)count
;
300 panic("Shouldn't be here");
306 TsunamiIO::PITimer::Counter::write(const uint8_t data
)
308 switch (write_byte
) {
310 count
= (count
& 0xFF00) | data
;
312 if (event
.scheduled())
319 count
= (count
& 0x00FF) | (data
<< 8);
323 DPRINTF(Tsunami
, "Timer set to curTick + %d\n",
324 count
* event
.interval
);
325 event
.schedule(curTick
+ count
* event
.interval
);
333 TsunamiIO::PITimer::Counter::setRW(int rw_val
)
335 if (rw_val
!= PIT_RW_16BIT
)
336 panic("Only LSB/MSB read/write is implemented.\n");
340 TsunamiIO::PITimer::Counter::setMode(int mode_val
)
342 if(mode_val
!= PIT_MODE_INTTC
&& mode_val
!= PIT_MODE_RATEGEN
&&
343 mode_val
!= PIT_MODE_SQWAVE
)
344 panic("PIT mode %#x is not implemented: \n", mode_val
);
350 TsunamiIO::PITimer::Counter::setBCD(int bcd_val
)
352 if (bcd_val
!= PIT_BCD_FALSE
)
353 panic("PITimer does not implement BCD counts.\n");
357 TsunamiIO::PITimer::Counter::outputHigh()
363 TsunamiIO::PITimer::Counter::serialize(const string
&base
, ostream
&os
)
365 paramOut(os
, base
+ ".count", count
);
366 paramOut(os
, base
+ ".latched_count", latched_count
);
367 paramOut(os
, base
+ ".period", period
);
368 paramOut(os
, base
+ ".mode", mode
);
369 paramOut(os
, base
+ ".output_high", output_high
);
370 paramOut(os
, base
+ ".latch_on", latch_on
);
371 paramOut(os
, base
+ ".read_byte", read_byte
);
372 paramOut(os
, base
+ ".write_byte", write_byte
);
375 if (event
.scheduled())
376 event_tick
= event
.when();
377 paramOut(os
, base
+ ".event_tick", event_tick
);
381 TsunamiIO::PITimer::Counter::unserialize(const string
&base
, Checkpoint
*cp
,
382 const string
§ion
)
384 paramIn(cp
, section
, base
+ ".count", count
);
385 paramIn(cp
, section
, base
+ ".latched_count", latched_count
);
386 paramIn(cp
, section
, base
+ ".period", period
);
387 paramIn(cp
, section
, base
+ ".mode", mode
);
388 paramIn(cp
, section
, base
+ ".output_high", output_high
);
389 paramIn(cp
, section
, base
+ ".latch_on", latch_on
);
390 paramIn(cp
, section
, base
+ ".read_byte", read_byte
);
391 paramIn(cp
, section
, base
+ ".write_byte", write_byte
);
394 paramIn(cp
, section
, base
+ ".event_tick", event_tick
);
396 event
.schedule(event_tick
);
399 TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter
* c_ptr
)
400 : Event(&mainEventQueue
)
402 interval
= (Tick
)(Clock::Float::s
/ 1193180.0);
407 TsunamiIO::PITimer::Counter::CounterEvent::process()
409 DPRINTF(Tsunami
, "Timer Interrupt\n");
410 switch (counter
->mode
) {
412 counter
->output_high
= true;
413 case PIT_MODE_RATEGEN
:
414 case PIT_MODE_SQWAVE
:
417 panic("Unimplemented PITimer mode.\n");
422 TsunamiIO::PITimer::Counter::CounterEvent::description()
424 return "tsunami 8254 Interval timer";
427 TsunamiIO::TsunamiIO(Params
*p
)
428 : BasicPioDevice(p
), tsunami(p
->tsunami
), pitimer(p
->name
+ "pitimer"),
429 rtc(p
->name
+ ".rtc", p
->tsunami
, p
->frequency
)
433 // set the back pointer from tsunami to myself
437 rtc
.set_time(p
->init_time
== 0 ? time(NULL
) : p
->init_time
);
439 picInterrupting
= false;
443 TsunamiIO::frequency() const
445 return Clock::Frequency
/ params()->frequency
;
449 TsunamiIO::read(Packet
*pkt
)
451 assert(pkt
->result
== Packet::Unknown
);
452 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
454 Addr daddr
= pkt
->getAddr() - pioAddr
;
456 DPRINTF(Tsunami
, "io read va=%#x size=%d IOPorrt=%#x\n", pkt
->getAddr(),
457 pkt
->getSize(), daddr
);
461 if (pkt
->getSize() == sizeof(uint8_t)) {
464 case TSDEV_PIC1_MASK
:
467 case TSDEV_PIC2_MASK
:
471 // !!! If this is modified 64bit case needs to be too
472 // Pal code has to do a 64 bit physical read because there is
473 // no load physical byte instruction
477 // PIC2 not implemnted... just return 0
480 case TSDEV_TMR0_DATA
:
481 pkt
->set(pitimer
.counter0
.read());
483 case TSDEV_TMR1_DATA
:
484 pkt
->set(pitimer
.counter1
.read());
486 case TSDEV_TMR2_DATA
:
487 pkt
->set(pitimer
.counter2
.read());
490 pkt
->set(rtc
.readData());
492 case TSDEV_CTRL_PORTB
:
493 if (pitimer
.counter2
.outputHigh())
494 pkt
->set(PORTB_SPKR_HIGH
);
499 panic("I/O Read - va%#x size %d\n", pkt
->getAddr(), pkt
->getSize());
501 } else if (pkt
->getSize() == sizeof(uint64_t)) {
502 if (daddr
== TSDEV_PIC1_ISR
)
503 pkt
->set
<uint64_t>(picr
);
505 panic("I/O Read - invalid addr - va %#x size %d\n",
506 pkt
->getAddr(), pkt
->getSize());
508 panic("I/O Read - invalid size - va %#x size %d\n", pkt
->getAddr(), pkt
->getSize());
510 pkt
->result
= Packet::Success
;
515 TsunamiIO::write(Packet
*pkt
)
517 assert(pkt
->result
== Packet::Unknown
);
518 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
519 Addr daddr
= pkt
->getAddr() - pioAddr
;
521 DPRINTF(Tsunami
, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
522 pkt
->getAddr(), pkt
->getSize(), pkt
->getAddr() & 0xfff, (uint32_t)pkt
->get
<uint8_t>());
524 assert(pkt
->getSize() == sizeof(uint8_t));
527 case TSDEV_PIC1_MASK
:
528 mask1
= ~(pkt
->get
<uint8_t>());
529 if ((picr
& mask1
) && !picInterrupting
) {
530 picInterrupting
= true;
531 tsunami
->cchip
->postDRIR(55);
532 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
534 if ((!(picr
& mask1
)) && picInterrupting
) {
535 picInterrupting
= false;
536 tsunami
->cchip
->clearDRIR(55);
537 DPRINTF(Tsunami
, "clearing pic interrupt\n");
540 case TSDEV_PIC2_MASK
:
541 mask2
= pkt
->get
<uint8_t>();
542 //PIC2 Not implemented to interrupt
545 // clear the interrupt on the PIC
546 picr
&= ~(1 << (pkt
->get
<uint8_t>() & 0xF));
548 tsunami
->cchip
->clearDRIR(55);
550 case TSDEV_DMA1_MODE
:
551 mode1
= pkt
->get
<uint8_t>();
553 case TSDEV_DMA2_MODE
:
554 mode2
= pkt
->get
<uint8_t>();
556 case TSDEV_TMR0_DATA
:
557 pitimer
.counter0
.write(pkt
->get
<uint8_t>());
559 case TSDEV_TMR1_DATA
:
560 pitimer
.counter1
.write(pkt
->get
<uint8_t>());
562 case TSDEV_TMR2_DATA
:
563 pitimer
.counter2
.write(pkt
->get
<uint8_t>());
566 pitimer
.writeControl(pkt
->get
<uint8_t>());
569 rtc
.writeAddr(pkt
->get
<uint8_t>());
572 rtc
.writeData(pkt
->get
<uint8_t>());
575 case TSDEV_DMA1_CMND
:
576 case TSDEV_DMA2_CMND
:
577 case TSDEV_DMA1_MMASK
:
578 case TSDEV_DMA2_MMASK
:
580 case TSDEV_DMA1_RESET
:
581 case TSDEV_DMA2_RESET
:
582 case TSDEV_DMA1_MASK
:
583 case TSDEV_DMA2_MASK
:
584 case TSDEV_CTRL_PORTB
:
587 panic("I/O Write - va%#x size %d data %#x\n", pkt
->getAddr(), pkt
->getSize(), pkt
->get
<uint8_t>());
590 pkt
->result
= Packet::Success
;
595 TsunamiIO::postPIC(uint8_t bitvector
)
597 //PIC2 Is not implemented, because nothing of interest there
600 tsunami
->cchip
->postDRIR(55);
601 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
606 TsunamiIO::clearPIC(uint8_t bitvector
)
608 //PIC2 Is not implemented, because nothing of interest there
610 if (!(picr
& mask1
)) {
611 tsunami
->cchip
->clearDRIR(55);
612 DPRINTF(Tsunami
, "clearing pic interrupt to cchip\n");
617 TsunamiIO::serialize(ostream
&os
)
619 SERIALIZE_SCALAR(timerData
);
620 SERIALIZE_SCALAR(mask1
);
621 SERIALIZE_SCALAR(mask2
);
622 SERIALIZE_SCALAR(mode1
);
623 SERIALIZE_SCALAR(mode2
);
624 SERIALIZE_SCALAR(picr
);
625 SERIALIZE_SCALAR(picInterrupting
);
627 // Serialize the timers
628 pitimer
.serialize("pitimer", os
);
629 rtc
.serialize("rtc", os
);
633 TsunamiIO::unserialize(Checkpoint
*cp
, const string
§ion
)
635 UNSERIALIZE_SCALAR(timerData
);
636 UNSERIALIZE_SCALAR(mask1
);
637 UNSERIALIZE_SCALAR(mask2
);
638 UNSERIALIZE_SCALAR(mode1
);
639 UNSERIALIZE_SCALAR(mode2
);
640 UNSERIALIZE_SCALAR(picr
);
641 UNSERIALIZE_SCALAR(picInterrupting
);
643 // Unserialize the timers
644 pitimer
.unserialize("pitimer", cp
, section
);
645 rtc
.unserialize("rtc", cp
, section
);
648 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
650 Param
<Addr
> pio_addr
;
651 Param
<Tick
> pio_latency
;
652 Param
<Tick
> frequency
;
653 SimObjectParam
<Platform
*> platform
;
654 SimObjectParam
<System
*> system
;
656 SimObjectParam
<Tsunami
*> tsunami
;
658 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
660 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
662 INIT_PARAM(pio_addr
, "Device Address"),
663 INIT_PARAM(pio_latency
, "Programmed IO latency"),
664 INIT_PARAM(frequency
, "clock interrupt frequency"),
665 INIT_PARAM(platform
, "platform"),
666 INIT_PARAM(system
, "system object"),
667 INIT_PARAM(time
, "System time to use (0 for actual time"),
668 INIT_PARAM(tsunami
, "Tsunami")
670 END_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
672 CREATE_SIM_OBJECT(TsunamiIO
)
674 TsunamiIO::Params
*p
= new TsunamiIO::Params
;
675 p
->frequency
= frequency
;
676 p
->name
= getInstanceName();
677 p
->pio_addr
= pio_addr
;
678 p
->pio_delay
= pio_latency
;
679 p
->platform
= platform
;
682 p
->tsunami
= tsunami
;
683 return new TsunamiIO(p
);
686 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO
)