2 * Copyright (c) 2003 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 "cpu/exec_context.hh"
41 #include "dev/console.hh"
42 #include "dev/tlaser_clock.hh"
43 #include "dev/tsunami_io.hh"
44 #include "dev/tsunamireg.h"
45 #include "dev/tsunami.hh"
46 #include "mem/functional_mem/memory_control.hh"
47 #include "sim/builder.hh"
48 #include "dev/tsunami_cchip.hh"
52 #define UNIX_YEAR_OFFSET 52
54 // Timer Event for Periodic interrupt of RTC
55 TsunamiIO::RTCEvent::RTCEvent(Tsunami
* t
)
56 : Event(&mainEventQueue
), tsunami(t
)
58 DPRINTF(MC146818
, "RTC Event Initilizing\n");
59 schedule(curTick
+ ticksPerSecond
/RTC_RATE
);
63 TsunamiIO::RTCEvent::process()
65 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
66 schedule(curTick
+ ticksPerSecond
/RTC_RATE
);
67 //Actually interrupt the processor here
68 if (!tsunami
->cchip
->RTCInterrupting
) {
69 tsunami
->cchip
->misc
|= 1 << 7;
70 tsunami
->cchip
->RTCInterrupting
= true;
71 tsunami
->intrctrl
->post(0, TheISA::INTLEVEL_IRQ2
, 0);
76 TsunamiIO::RTCEvent::description()
78 return "tsunami RTC 1024Hz interrupt";
81 // Timer Event for PIT Timers
82 TsunamiIO::ClockEvent::ClockEvent()
83 : Event(&mainEventQueue
)
85 DPRINTF(Tsunami
, "Clock Event Initilizing\n");
90 TsunamiIO::ClockEvent::process()
92 DPRINTF(Tsunami
, "Timer Interrupt\n");
94 status
= 0x20; // set bit that linux is looking for
96 schedule(curTick
+ interval
);
100 TsunamiIO::ClockEvent::Program(int count
)
102 DPRINTF(Tsunami
, "Timer set to curTick + %d\n", count
);
103 // should be count * (cpufreq/pitfreq)
104 interval
= count
* ticksPerSecond
/1193180UL;
105 schedule(curTick
+ interval
);
110 TsunamiIO::ClockEvent::description()
112 return "tsunami 8254 Interval timer";
116 TsunamiIO::ClockEvent::ChangeMode(uint8_t md
)
122 TsunamiIO::ClockEvent::Status()
127 TsunamiIO::TsunamiIO(const string
&name
, Tsunami
*t
, time_t init_time
,
128 Addr a
, MemoryController
*mmu
)
129 : FunctionalMemory(name
), addr(a
), tsunami(t
), rtc(t
)
131 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
133 // set the back pointer from tsunami to myself
137 set_time(init_time
== 0 ? time(NULL
) : init_time
);
140 picInterrupting
= false;
144 TsunamiIO::set_time(time_t t
)
147 DPRINTFN("Real-time clock set to %s", asctime(&tm
));
151 TsunamiIO::read(MemReqPtr
&req
, uint8_t *data
)
153 DPRINTF(Tsunami
, "io read va=%#x size=%d IOPorrt=%#x\n",
154 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff);
156 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
));
157 // ExecContext *xc = req->xc;
158 // int cpuid = xc->cpu_id;
161 case sizeof(uint8_t):
164 *(uint8_t*)data
= timer2
.Status();
168 case RTC_CONTROL_REGISTERA
:
169 *(uint8_t*)data
= uip
<< 7 | 0x26;
172 case RTC_CONTROL_REGISTERB
:
173 // DM and 24/12 and UIE
174 *(uint8_t*)data
= 0x46;
176 case RTC_CONTROL_REGISTERC
:
177 // If we want to support RTC user access in linux
178 // This won't work, but for now it's fine
179 *(uint8_t*)data
= 0x00;
181 case RTC_CONTROL_REGISTERD
:
182 panic("RTC Control Register D not implemented");
184 *(uint8_t *)data
= tm
.tm_sec
;
187 *(uint8_t *)data
= tm
.tm_min
;
190 *(uint8_t *)data
= tm
.tm_hour
;
192 case RTC_DAY_OF_WEEK
:
193 *(uint8_t *)data
= tm
.tm_wday
;
195 case RTC_DAY_OF_MONTH
:
196 *(uint8_t *)data
= tm
.tm_mday
;
198 *(uint8_t *)data
= tm
.tm_mon
+ 1;
201 *(uint8_t *)data
= tm
.tm_year
- UNIX_YEAR_OFFSET
;
204 panic("Unknown RTC Address\n");
208 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
210 case sizeof(uint16_t):
211 case sizeof(uint32_t):
212 case sizeof(uint64_t):
214 panic("I/O Read - invalid size - va %#x size %d\n",
215 req
->vaddr
, req
->size
);
217 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
223 TsunamiIO::write(MemReqPtr
&req
, const uint8_t *data
)
225 uint8_t dt
= *(uint8_t*)data
;
228 DPRINTF(Tsunami
, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
229 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff, dt64
);
231 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
));
234 case sizeof(uint8_t):
236 case TSDEV_PIC1_MASK
:
237 mask1
= *(uint8_t*)data
;
238 if ((picr
& mask1
) && !picInterrupting
) {
239 picInterrupting
= true;
240 tsunami
->cchip
->postDRIR(uint64_t(1) << 55);
241 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
244 case TSDEV_PIC2_MASK
:
245 mask2
= *(uint8_t*)data
;
246 //PIC2 Not implemented to interrupt
248 case TSDEV_DMA1_RESET
:
250 case TSDEV_DMA2_RESET
:
252 case TSDEV_DMA1_MODE
:
253 mode1
= *(uint8_t*)data
;
255 case TSDEV_DMA2_MODE
:
256 mode2
= *(uint8_t*)data
;
258 case TSDEV_DMA1_MASK
:
259 case TSDEV_DMA2_MASK
:
264 if ((*(uint8_t*)data
& 0x30) != 0x30)
265 panic("Only L/M write supported\n");
267 switch(*(uint8_t*)data
>> 6) {
269 timer0
.ChangeMode((*(uint8_t*)data
& 0xF) >> 1);
272 timer2
.ChangeMode((*(uint8_t*)data
& 0xF) >> 1);
275 panic("Read Back Command not implemented\n");
278 case TSDEV_TMR2_DATA
:
279 /* two writes before we actually start the Timer
280 so I set a flag in the timerData */
281 if(timerData
& 0x1000) {
283 timerData
+= *(uint8_t*)data
<< 8;
284 timer2
.Program(timerData
);
286 timerData
= *(uint8_t*)data
;
290 case TSDEV_TMR0_DATA
:
291 /* two writes before we actually start the Timer
292 so I set a flag in the timerData */
293 if(timerData
& 0x1000) {
295 timerData
+= *(uint8_t*)data
<< 8;
296 timer0
.Program(timerData
);
298 timerData
= *(uint8_t*)data
;
303 RTCAddress
= *(uint8_t*)data
;
306 panic("RTC Write not implmented (rtc.o won't work)\n");
308 panic("I/O Write - va%#x size %d\n", req
->vaddr
, req
->size
);
310 case sizeof(uint16_t):
311 case sizeof(uint32_t):
312 case sizeof(uint64_t):
314 panic("I/O Write - invalid size - va %#x size %d\n",
315 req
->vaddr
, req
->size
);
323 TsunamiIO::postPIC(uint8_t bitvector
)
325 //PIC2 Is not implemented, because nothing of interest there
327 if ((picr
& mask1
) && !picInterrupting
) {
328 picInterrupting
= true;
329 tsunami
->cchip
->postDRIR(uint64_t(1) << 55);
330 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
335 TsunamiIO::clearPIC(uint8_t bitvector
)
337 //PIC2 Is not implemented, because nothing of interest there
339 if (!(picr
& mask1
)) {
340 picInterrupting
= false;
341 tsunami
->cchip
->clearDRIR(uint64_t(1) << 55);
342 DPRINTF(Tsunami
, "clearing pic interrupt to cchip\n");
347 TsunamiIO::serialize(std::ostream
&os
)
349 SERIALIZE_SCALAR(timerData
);
350 SERIALIZE_SCALAR(uip
);
351 SERIALIZE_SCALAR(picr
);
352 SERIALIZE_SCALAR(picInterrupting
);
353 Tick time0when
= timer0
.when();
354 Tick time2when
= timer2
.when();
355 Tick rtcwhen
= rtc
.when();
356 SERIALIZE_SCALAR(time0when
);
357 SERIALIZE_SCALAR(time2when
);
358 SERIALIZE_SCALAR(rtcwhen
);
363 TsunamiIO::unserialize(Checkpoint
*cp
, const std::string
§ion
)
365 UNSERIALIZE_SCALAR(timerData
);
366 UNSERIALIZE_SCALAR(uip
);
367 UNSERIALIZE_SCALAR(picr
);
368 UNSERIALIZE_SCALAR(picInterrupting
);
372 UNSERIALIZE_SCALAR(time0when
);
373 UNSERIALIZE_SCALAR(time2when
);
374 UNSERIALIZE_SCALAR(rtcwhen
);
375 timer0
.reschedule(time0when
);
376 timer2
.reschedule(time2when
);
377 rtc
.reschedule(rtcwhen
);
380 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
382 SimObjectParam
<Tsunami
*> tsunami
;
384 SimObjectParam
<MemoryController
*> mmu
;
387 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
389 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
391 INIT_PARAM(tsunami
, "Tsunami"),
392 INIT_PARAM_DFLT(time
, "System time to use "
393 "(0 for actual time, default is 1/1/06", ULL(1136073600)),
394 INIT_PARAM(mmu
, "Memory Controller"),
395 INIT_PARAM(addr
, "Device Address")
397 END_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
399 CREATE_SIM_OBJECT(TsunamiIO
)
401 return new TsunamiIO(getInstanceName(), tsunami
, time
, addr
, mmu
);
404 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO
)