4 * Tsunami I/O including PIC, PIT, RTC, DMA
13 #include "base/trace.hh"
14 #include "cpu/exec_context.hh"
15 #include "dev/console.hh"
16 #include "dev/tlaser_clock.hh"
17 #include "dev/tsunami_io.hh"
18 #include "dev/tsunamireg.h"
19 #include "dev/tsunami.hh"
20 #include "mem/functional_mem/memory_control.hh"
21 #include "sim/builder.hh"
22 #include "dev/tsunami_cchip.hh"
26 #define UNIX_YEAR_OFFSET 52
29 // Timer Event for Periodic interrupt of RTC
30 TsunamiIO::RTCEvent::RTCEvent(Tsunami
* t
)
31 : Event(&mainEventQueue
), tsunami(t
)
33 DPRINTF(MC146818
, "RTC Event Initilizing\n");
34 schedule(curTick
+ ticksPerSecond
/RTC_RATE
);
38 TsunamiIO::RTCEvent::process()
40 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
41 schedule(curTick
+ ticksPerSecond
/RTC_RATE
);
42 //Actually interrupt the processor here
43 if (!tsunami
->cchip
->RTCInterrupting
) {
44 tsunami
->cchip
->misc
|= 1 << 7;
45 tsunami
->cchip
->RTCInterrupting
= true;
46 tsunami
->intrctrl
->post(0, TheISA::INTLEVEL_IRQ2
, 0);
51 TsunamiIO::RTCEvent::description()
53 return "tsunami RTC 1024Hz interrupt";
56 // Timer Event for PIT Timers
57 TsunamiIO::ClockEvent::ClockEvent()
58 : Event(&mainEventQueue
)
60 DPRINTF(Tsunami
, "Clock Event Initilizing\n");
65 TsunamiIO::ClockEvent::process()
67 DPRINTF(Tsunami
, "Timer Interrupt\n");
69 status
= 0x20; // set bit that linux is looking for
71 schedule(curTick
+ interval
);
75 TsunamiIO::ClockEvent::Program(int count
)
77 DPRINTF(Tsunami
, "Timer set to curTick + %d\n", count
);
78 // should be count * (cpufreq/pitfreq)
79 interval
= count
* ticksPerSecond
/1193180UL;
80 schedule(curTick
+ interval
);
85 TsunamiIO::ClockEvent::description()
87 return "tsunami 8254 Interval timer";
91 TsunamiIO::ClockEvent::ChangeMode(uint8_t md
)
97 TsunamiIO::ClockEvent::Status()
105 TsunamiIO::TsunamiIO(const string
&name
, Tsunami
*t
, time_t init_time
,
106 Addr addr
, Addr mask
, MemoryController
*mmu
)
107 : MmapDevice(name
, addr
, mask
, mmu
), tsunami(t
), rtc(t
)
110 set_time(init_time
== 0 ? time(NULL
) : init_time
);
113 picInterrupting
= false;
117 TsunamiIO::set_time(time_t t
)
120 DPRINTFN("Real-time clock set to %s", asctime(&tm
));
124 TsunamiIO::read(MemReqPtr
&req
, uint8_t *data
)
126 DPRINTF(Tsunami
, "io read va=%#x size=%d IOPorrt=%#x\n",
127 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff);
129 Addr daddr
= (req
->paddr
& addr_mask
);
130 // ExecContext *xc = req->xc;
131 // int cpuid = xc->cpu_id;
134 case sizeof(uint8_t):
137 *(uint8_t*)data
= timer2
.Status();
141 case RTC_CONTROL_REGISTERA
:
142 *(uint8_t*)data
= uip
<< 7 | 0x26;
145 case RTC_CONTROL_REGISTERB
:
146 // DM and 24/12 and UIE
147 *(uint8_t*)data
= 0x46;
149 case RTC_CONTROL_REGISTERC
:
150 // If we want to support RTC user access in linux
151 // This won't work, but for now it's fine
152 *(uint8_t*)data
= 0x00;
154 case RTC_CONTROL_REGISTERD
:
155 panic("RTC Control Register D not implemented");
157 *(uint8_t *)data
= tm
.tm_sec
;
160 *(uint8_t *)data
= tm
.tm_min
;
163 *(uint8_t *)data
= tm
.tm_hour
;
165 case RTC_DAY_OF_WEEK
:
166 *(uint8_t *)data
= tm
.tm_wday
;
168 case RTC_DAY_OF_MONTH
:
169 *(uint8_t *)data
= tm
.tm_mday
;
171 *(uint8_t *)data
= tm
.tm_mon
+ 1;
174 *(uint8_t *)data
= tm
.tm_year
- UNIX_YEAR_OFFSET
;
177 panic("Unknown RTC Address\n");
181 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
183 case sizeof(uint16_t):
184 case sizeof(uint32_t):
185 case sizeof(uint64_t):
187 panic("I/O Read - invalid size - va %#x size %d\n", req
->vaddr
, req
->size
);
189 panic("I/O Read - va%#x size %d\n", req
->vaddr
, req
->size
);
195 TsunamiIO::write(MemReqPtr
&req
, const uint8_t *data
)
197 uint8_t dt
= *(uint8_t*)data
;
200 DPRINTF(Tsunami
, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
201 req
->vaddr
, req
->size
, req
->vaddr
& 0xfff, dt64
);
203 Addr daddr
= (req
->paddr
& addr_mask
);
206 case sizeof(uint8_t):
208 case TSDEV_PIC1_MASK
:
209 mask1
= *(uint8_t*)data
;
210 if ((picr
& mask1
) && !picInterrupting
) {
211 picInterrupting
= true;
212 tsunami
->cchip
->postDRIR(uint64_t(1) << 55);
213 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
216 case TSDEV_PIC2_MASK
:
217 mask2
= *(uint8_t*)data
;
218 //PIC2 Not implemented to interrupt
220 case TSDEV_DMA1_RESET
:
222 case TSDEV_DMA2_RESET
:
224 case TSDEV_DMA1_MODE
:
225 mode1
= *(uint8_t*)data
;
227 case TSDEV_DMA2_MODE
:
228 mode2
= *(uint8_t*)data
;
230 case TSDEV_DMA1_MASK
:
231 case TSDEV_DMA2_MASK
:
236 if ((*(uint8_t*)data
& 0x30) != 0x30)
237 panic("Only L/M write supported\n");
239 switch(*(uint8_t*)data
>> 6) {
241 timer0
.ChangeMode((*(uint8_t*)data
& 0xF) >> 1);
244 timer2
.ChangeMode((*(uint8_t*)data
& 0xF) >> 1);
247 panic("Read Back Command not implemented\n");
250 case TSDEV_TMR2_DATA
:
251 /* two writes before we actually start the Timer
252 so I set a flag in the timerData */
253 if(timerData
& 0x1000) {
255 timerData
+= *(uint8_t*)data
<< 8;
256 timer2
.Program(timerData
);
258 timerData
= *(uint8_t*)data
;
262 case TSDEV_TMR0_DATA
:
263 /* two writes before we actually start the Timer
264 so I set a flag in the timerData */
265 if(timerData
& 0x1000) {
267 timerData
+= *(uint8_t*)data
<< 8;
268 timer0
.Program(timerData
);
270 timerData
= *(uint8_t*)data
;
275 RTCAddress
= *(uint8_t*)data
;
278 panic("RTC Write not implmented (rtc.o won't work)\n");
280 panic("I/O Write - va%#x size %d\n", req
->vaddr
, req
->size
);
282 case sizeof(uint16_t):
283 case sizeof(uint32_t):
284 case sizeof(uint64_t):
286 panic("I/O Write - invalid size - va %#x size %d\n", req
->vaddr
, req
->size
);
294 TsunamiIO::postPIC(uint8_t bitvector
)
296 //PIC2 Is not implemented, because nothing of interest there
298 if ((picr
& mask1
) && !picInterrupting
) {
299 picInterrupting
= true;
300 tsunami
->cchip
->postDRIR(uint64_t(1) << 55);
301 DPRINTF(Tsunami
, "posting pic interrupt to cchip\n");
306 TsunamiIO::clearPIC(uint8_t bitvector
)
308 //PIC2 Is not implemented, because nothing of interest there
310 if (!(picr
& mask1
)) {
311 picInterrupting
= false;
312 tsunami
->cchip
->clearDRIR(uint64_t(1) << 55);
313 DPRINTF(Tsunami
, "clearing pic interrupt to cchip\n");
318 TsunamiIO::serialize(std::ostream
&os
)
320 // code should be written
324 TsunamiIO::unserialize(Checkpoint
*cp
, const std::string
§ion
)
326 //code should be written
329 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
331 SimObjectParam
<Tsunami
*> tsunami
;
333 SimObjectParam
<MemoryController
*> mmu
;
337 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO
)
339 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
341 INIT_PARAM(tsunami
, "Tsunami"),
342 INIT_PARAM_DFLT(time
, "System time to use "
343 "(0 for actual time, default is 1/1/06", ULL(1136073600)),
344 INIT_PARAM(mmu
, "Memory Controller"),
345 INIT_PARAM(addr
, "Device Address"),
346 INIT_PARAM(mask
, "Address Mask")
348 END_INIT_SIM_OBJECT_PARAMS(TsunamiIO
)
350 CREATE_SIM_OBJECT(TsunamiIO
)
352 return new TsunamiIO(getInstanceName(), tsunami
, time
, addr
,
356 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO
)