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/tsunami_io.hh"
41 #include "dev/tsunami.hh"
42 #include "dev/pitreg.h"
43 #include "mem/bus/bus.hh"
44 #include "mem/bus/pio_interface.hh"
45 #include "mem/bus/pio_interface_impl.hh"
46 #include "sim/builder.hh"
47 #include "dev/tsunami_cchip.hh"
48 #include "dev/tsunamireg.h"
49 #include "dev/rtcreg.h"
50 #include "mem/functional/memory_control.hh"
53 //Should this be AlphaISA?
54 using namespace TheISA
;
56 TsunamiIO::RTC::RTC(const string
&name
, Tsunami
* t
, Tick i
)
57 : _name(name
), event(t
, i
), addr(0)
59 memset(clock_data
, 0, sizeof(clock_data
));
60 stat_regA
= RTCA_32768HZ
| RTCA_1024HZ
;
61 stat_regB
= RTCB_PRDC_IE
|RTCB_BIN
| RTCB_24HR
;
65 TsunamiIO::RTC::set_time(time_t t
)
73 wday
= tm
.tm_wday
+ 1;
78 DPRINTFN("Real-time clock set to %s", asctime(&tm
));
82 TsunamiIO::RTC::writeAddr(const uint8_t *data
)
84 if (*data
<= RTC_STAT_REGD
)
87 panic("RTC addresses over 0xD are not implemented.\n");
91 TsunamiIO::RTC::writeData(const uint8_t *data
)
93 if (addr
< RTC_STAT_REGA
)
94 clock_data
[addr
] = *data
;
98 if (*data
!= (RTCA_32768HZ
| RTCA_1024HZ
))
99 panic("Unimplemented RTC register A value write!\n");
103 if ((*data
& ~(RTCB_PRDC_IE
| RTCB_SQWE
)) != (RTCB_BIN
| RTCB_24HR
))
104 panic("Write to RTC reg B bits that are not implemented!\n");
106 if (*data
& RTCB_PRDC_IE
) {
107 if (!event
.scheduled())
108 event
.scheduleIntr();
110 if (event
.scheduled())
117 panic("RTC status registers C and D are not implemented.\n");
124 TsunamiIO::RTC::readData(uint8_t *data
)
126 if (addr
< RTC_STAT_REGA
)
127 *data
= clock_data
[addr
];
131 // toggle UIP bit for linux
132 stat_regA
^= RTCA_UIP
;
147 TsunamiIO::RTC::serialize(const string
&base
, ostream
&os
)
149 paramOut(os
, base
+ ".addr", addr
);
150 arrayParamOut(os
, base
+ ".clock_data", clock_data
, sizeof(clock_data
));
151 paramOut(os
, base
+ ".stat_regA", stat_regA
);
152 paramOut(os
, base
+ ".stat_regB", stat_regB
);
156 TsunamiIO::RTC::unserialize(const string
&base
, Checkpoint
*cp
,
157 const string
§ion
)
159 paramIn(cp
, section
, base
+ ".addr", addr
);
160 arrayParamIn(cp
, section
, base
+ ".clock_data", clock_data
,
162 paramIn(cp
, section
, base
+ ".stat_regA", stat_regA
);
163 paramIn(cp
, section
, base
+ ".stat_regB", stat_regB
);
165 // We're not unserializing the event here, but we need to
166 // rescehedule the event since curTick was moved forward by the
168 event
.reschedule(curTick
+ event
.interval
);
171 TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami
*t
, Tick i
)
172 : Event(&mainEventQueue
), tsunami(t
), interval(i
)
174 DPRINTF(MC146818
, "RTC Event Initilizing\n");
175 schedule(curTick
+ interval
);
179 TsunamiIO::RTC::RTCEvent::scheduleIntr()
181 schedule(curTick
+ interval
);
185 TsunamiIO::RTC::RTCEvent::process()
187 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
188 schedule(curTick
+ interval
);
189 //Actually interrupt the processor here
190 tsunami
->cchip
->postRTC();
194 TsunamiIO::RTC::RTCEvent::description()
196 return "tsunami RTC interrupt";
199 TsunamiIO::PITimer::PITimer(const string
&name
)
200 : _name(name
), counter0(name
+ ".counter0"), counter1(name
+ ".counter1"),
201 counter2(name
+ ".counter2")
203 counter
[0] = &counter0
;
204 counter
[1] = &counter0
;
205 counter
[2] = &counter0
;
209 TsunamiIO::PITimer::writeControl(const uint8_t *data
)
214 sel
= GET_CTRL_SEL(*data
);
216 if (sel
== PIT_READ_BACK
)
217 panic("PITimer Read-Back Command is not implemented.\n");
219 rw
= GET_CTRL_RW(*data
);
221 if (rw
== PIT_RW_LATCH_COMMAND
)
222 counter
[sel
]->latchCount();
224 counter
[sel
]->setRW(rw
);
225 counter
[sel
]->setMode(GET_CTRL_MODE(*data
));
226 counter
[sel
]->setBCD(GET_CTRL_BCD(*data
));
231 TsunamiIO::PITimer::serialize(const string
&base
, ostream
&os
)
233 // serialize the counters
234 counter0
.serialize(base
+ ".counter0", os
);
235 counter1
.serialize(base
+ ".counter1", os
);
236 counter2
.serialize(base
+ ".counter2", os
);
240 TsunamiIO::PITimer::unserialize(const string
&base
, Checkpoint
*cp
,
241 const string
§ion
)
243 // unserialze the counters
244 counter0
.unserialize(base
+ ".counter0", cp
, section
);
245 counter1
.unserialize(base
+ ".counter1", cp
, section
);
246 counter2
.unserialize(base
+ ".counter2", cp
, section
);
249 TsunamiIO::PITimer::Counter::Counter(const string
&name
)
250 : _name(name
), event(this), count(0), latched_count(0), period(0),
251 mode(0), output_high(false), latch_on(false), read_byte(LSB
),
258 TsunamiIO::PITimer::Counter::latchCount()
260 // behave like a real latch
264 latched_count
= count
;
269 TsunamiIO::PITimer::Counter::read(uint8_t *data
)
275 *data
= (uint8_t)latched_count
;
280 *data
= latched_count
>> 8;
287 *data
= (uint8_t)count
;
298 TsunamiIO::PITimer::Counter::write(const uint8_t *data
)
300 switch (write_byte
) {
302 count
= (count
& 0xFF00) | *data
;
304 if (event
.scheduled())
311 count
= (count
& 0x00FF) | (*data
<< 8);
315 DPRINTF(Tsunami
, "Timer set to curTick + %d\n",
316 count
* event
.interval
);
317 event
.schedule(curTick
+ count
* event
.interval
);
325 TsunamiIO::PITimer::Counter::setRW(int rw_val
)
327 if (rw_val
!= PIT_RW_16BIT
)
328 panic("Only LSB/MSB read/write is implemented.\n");
332 TsunamiIO::PITimer::Counter::setMode(int mode_val
)
334 if(mode_val
!= PIT_MODE_INTTC
&& mode_val
!= PIT_MODE_RATEGEN
&&
335 mode_val
!= PIT_MODE_SQWAVE
)
336 panic("PIT mode %#x is not implemented: \n", mode_val
);
342 TsunamiIO::PITimer::Counter::setBCD(int bcd_val
)
344 if (bcd_val
!= PIT_BCD_FALSE
)
345 panic("PITimer does not implement BCD counts.\n");
349 TsunamiIO::PITimer::Counter::outputHigh()
355 TsunamiIO::PITimer::Counter::serialize(const string
&base
, ostream
&os
)
357 paramOut(os
, base
+ ".count", count
);
358 paramOut(os
, base
+ ".latched_count", latched_count
);
359 paramOut(os
, base
+ ".period", period
);
360 paramOut(os
, base
+ ".mode", mode
);
361 paramOut(os
, base
+ ".output_high", output_high
);
362 paramOut(os
, base
+ ".latch_on", latch_on
);
363 paramOut(os
, base
+ ".read_byte", read_byte
);
364 paramOut(os
, base
+ ".write_byte", write_byte
);
367 if (event
.scheduled())
368 event_tick
= event
.when();
369 paramOut(os
, base
+ ".event_tick", event_tick
);
373 TsunamiIO::PITimer::Counter::unserialize(const string
&base
, Checkpoint
*cp
,
374 const string
§ion
)
376 paramIn(cp
, section
, base
+ ".count", count
);
377 paramIn(cp
, section
, base
+ ".latched_count", latched_count
);
378 paramIn(cp
, section
, base
+ ".period", period
);
379 paramIn(cp
, section
, base
+ ".mode", mode
);
380 paramIn(cp
, section
, base
+ ".output_high", output_high
);
381 paramIn(cp
, section
, base
+ ".latch_on", latch_on
);
382 paramIn(cp
, section
, base
+ ".read_byte", read_byte
);
383 paramIn(cp
, section
, base
+ ".write_byte", write_byte
);
386 paramIn(cp
, section
, base
+ ".event_tick", event_tick
);
388 event
.schedule(event_tick
);
391 TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter
* c_ptr
)
392 : Event(&mainEventQueue
)
394 interval
= (Tick
)(Clock::Float::s
/ 1193180.0);
399 TsunamiIO::PITimer::Counter::CounterEvent::process()
401 DPRINTF(Tsunami
, "Timer Interrupt\n");
402 switch (counter
->mode
) {
404 counter
->output_high
= true;
405 case PIT_MODE_RATEGEN
:
406 case PIT_MODE_SQWAVE
:
409 panic("Unimplemented PITimer mode.\n");
414 TsunamiIO::PITimer::Counter::CounterEvent::description()
416 return "tsunami 8254 Interval timer";
419 TsunamiIO::TsunamiIO(const string
&name
, Tsunami
*t
, time_t init_time
,
420 Addr a
, MemoryController
*mmu
, HierParams
*hier
,
421 Bus
*pio_bus
, Tick pio_latency
, Tick ci
)
422 : PioDevice(name
, t
), addr(a
), clockInterval(ci
), tsunami(t
),
423 pitimer(name
+ "pitimer"), rtc(name
+ ".rtc", t
, ci
)
425 mmu
->add_child(this, RangeSize(addr
, size
));
428 pioInterface
= newPioInterface(name
+ ".pio", hier
, pio_bus
, this,
429 &TsunamiIO::cacheAccess
);
430 pioInterface
->addAddrRange(RangeSize(addr
, size
));
431 pioLatency
= pio_latency
* pio_bus
->clockRate
;
434 // set the back pointer from tsunami to myself
438 rtc
.set_time(init_time
== 0 ? time(NULL
) : init_time
);
440 picInterrupting
= false;
444 TsunamiIO::frequency() const
446 return Clock::Frequency
/ clockInterval
;
450 TsunamiIO::read(MemReqPtr
&req
, uint8_t *data
)
452 DPRINTF(Tsunami
, "io read va=%#x size=%d IOPorrt=%#x\n",
453 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff);
455 Addr daddr
= (req
->paddr
- (addr
& EV5::PAddrImplMask
));
459 case sizeof(uint8_t):
462 case TSDEV_PIC1_MASK
:
463 *(uint8_t*)data
= ~mask1
;
465 case TSDEV_PIC2_MASK
:
466 *(uint8_t*)data
= ~mask2
;
469 // !!! If this is modified 64bit case needs to be too
470 // Pal code has to do a 64 bit physical read because there is
471 // no load physical byte instruction
472 *(uint8_t*)data
= picr
;
475 // PIC2 not implemnted... just return 0
476 *(uint8_t*)data
= 0x00;
478 case TSDEV_TMR0_DATA
:
479 pitimer
.counter0
.read(data
);
481 case TSDEV_TMR1_DATA
:
482 pitimer
.counter1
.read(data
);
484 case TSDEV_TMR2_DATA
:
485 pitimer
.counter2
.read(data
);
490 case TSDEV_CTRL_PORTB
:
491 if (pitimer
.counter2
.outputHigh())
492 *data
= PORTB_SPKR_HIGH
;
497 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
499 case sizeof(uint16_t):
500 case sizeof(uint32_t):
501 panic("I/O Read - invalid size - va %#x size %d\n",
502 req
->vaddr
, req
->size
);
504 case sizeof(uint64_t):
507 // !!! If this is modified 8bit case needs to be too
508 // Pal code has to do a 64 bit physical read because there is
509 // no load physical byte instruction
510 *(uint64_t*)data
= (uint64_t)picr
;
513 panic("I/O Read - invalid size - va %#x size %d\n",
514 req
->vaddr
, req
->size
);
518 panic("I/O Read - invalid size - va %#x size %d\n",
519 req
->vaddr
, req
->size
);
521 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
527 TsunamiIO::write(MemReqPtr
&req
, const uint8_t *data
)
531 uint8_t dt
= *(uint8_t*)data
;
535 DPRINTF(Tsunami
, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
536 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff, dt64
);
538 Addr daddr
= (req
->paddr
- (addr
& EV5::PAddrImplMask
));
541 case sizeof(uint8_t):
543 case TSDEV_PIC1_MASK
:
544 mask1
= ~(*(uint8_t*)data
);
545 if ((picr
& mask1
) && !picInterrupting
) {
546 picInterrupting
= true;
547 tsunami
->cchip
->postDRIR(55);
548 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
550 if ((!(picr
& mask1
)) && picInterrupting
) {
551 picInterrupting
= false;
552 tsunami
->cchip
->clearDRIR(55);
553 DPRINTF(Tsunami
, "clearing pic interrupt\n");
556 case TSDEV_PIC2_MASK
:
557 mask2
= *(uint8_t*)data
;
558 //PIC2 Not implemented to interrupt
561 // clear the interrupt on the PIC
562 picr
&= ~(1 << (*(uint8_t*)data
& 0xF));
564 tsunami
->cchip
->clearDRIR(55);
566 case TSDEV_DMA1_CMND
:
568 case TSDEV_DMA2_CMND
:
570 case TSDEV_DMA1_MMASK
:
572 case TSDEV_DMA2_MMASK
:
576 case TSDEV_DMA1_RESET
:
578 case TSDEV_DMA2_RESET
:
580 case TSDEV_DMA1_MODE
:
581 mode1
= *(uint8_t*)data
;
583 case TSDEV_DMA2_MODE
:
584 mode2
= *(uint8_t*)data
;
586 case TSDEV_DMA1_MASK
:
587 case TSDEV_DMA2_MASK
:
589 case TSDEV_TMR0_DATA
:
590 pitimer
.counter0
.write(data
);
592 case TSDEV_TMR1_DATA
:
593 pitimer
.counter1
.write(data
);
595 case TSDEV_TMR2_DATA
:
596 pitimer
.counter2
.write(data
);
599 pitimer
.writeControl(data
);
609 case TSDEV_CTRL_PORTB
:
610 // System Control Port B not implemented
613 panic("I/O Write - va%#x size %d data %#x\n", req
->vaddr
, req
->size
, (int)*data
);
615 case sizeof(uint16_t):
616 case sizeof(uint32_t):
617 case sizeof(uint64_t):
619 panic("I/O Write - invalid size - va %#x size %d\n",
620 req
->vaddr
, req
->size
);
628 TsunamiIO::postPIC(uint8_t bitvector
)
630 //PIC2 Is not implemented, because nothing of interest there
633 tsunami
->cchip
->postDRIR(55);
634 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
639 TsunamiIO::clearPIC(uint8_t bitvector
)
641 //PIC2 Is not implemented, because nothing of interest there
643 if (!(picr
& mask1
)) {
644 tsunami
->cchip
->clearDRIR(55);
645 DPRINTF(Tsunami
, "clearing pic interrupt to cchip\n");
650 TsunamiIO::cacheAccess(MemReqPtr
&req
)
652 return curTick
+ pioLatency
;
656 TsunamiIO::serialize(ostream
&os
)
658 SERIALIZE_SCALAR(timerData
);
659 SERIALIZE_SCALAR(mask1
);
660 SERIALIZE_SCALAR(mask2
);
661 SERIALIZE_SCALAR(mode1
);
662 SERIALIZE_SCALAR(mode2
);
663 SERIALIZE_SCALAR(picr
);
664 SERIALIZE_SCALAR(picInterrupting
);
666 // Serialize the timers
667 pitimer
.serialize("pitimer", os
);
668 rtc
.serialize("rtc", os
);
672 TsunamiIO::unserialize(Checkpoint
*cp
, const string
§ion
)
674 UNSERIALIZE_SCALAR(timerData
);
675 UNSERIALIZE_SCALAR(mask1
);
676 UNSERIALIZE_SCALAR(mask2
);
677 UNSERIALIZE_SCALAR(mode1
);
678 UNSERIALIZE_SCALAR(mode2
);
679 UNSERIALIZE_SCALAR(picr
);
680 UNSERIALIZE_SCALAR(picInterrupting
);
682 // Unserialize the timers
683 pitimer
.unserialize("pitimer", cp
, section
);
684 rtc
.unserialize("rtc", cp
, section
);
687 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
689 SimObjectParam
<Tsunami
*> tsunami
;
691 SimObjectParam
<MemoryController
*> mmu
;
693 SimObjectParam
<Bus
*> pio_bus
;
694 Param
<Tick
> pio_latency
;
695 SimObjectParam
<HierParams
*> hier
;
696 Param
<Tick
> frequency
;
698 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
700 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
702 INIT_PARAM(tsunami
, "Tsunami"),
703 INIT_PARAM(time
, "System time to use (0 for actual time"),
704 INIT_PARAM(mmu
, "Memory Controller"),
705 INIT_PARAM(addr
, "Device Address"),
706 INIT_PARAM(pio_bus
, "The IO Bus to attach to"),
707 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
708 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
709 INIT_PARAM(frequency
, "clock interrupt frequency")
711 END_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
713 CREATE_SIM_OBJECT(TsunamiIO
)
715 return new TsunamiIO(getInstanceName(), tsunami
, time
, addr
, mmu
, hier
,
716 pio_bus
, pio_latency
, frequency
);
719 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO
)