summaryrefslogtreecommitdiff
path: root/dev/tsunami_io.cc
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2004-01-22 19:02:07 -0500
committerAli Saidi <saidi@eecs.umich.edu>2004-01-22 19:02:07 -0500
commitf9f4a7498611082079ae4acd2d421a857cab30d8 (patch)
treec6e4ba0168a2f2bc8223e6715d88637f71b1c41e /dev/tsunami_io.cc
parentd9e8ecbf46ead49c2c8174c1362a5cb136b4b5f9 (diff)
downloadgem5-f9f4a7498611082079ae4acd2d421a857cab30d8.tar.xz
added the 8254 programmable interval timer
--HG-- extra : convert_revision : 6a111db98c05a3dd692c757611c3eb9c8cfdd32f
Diffstat (limited to 'dev/tsunami_io.cc')
-rw-r--r--dev/tsunami_io.cc113
1 files changed, 109 insertions, 4 deletions
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index d5f2af960..eb0b9ae91 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -23,11 +23,56 @@
using namespace std;
+TsunamiIO::ClockEvent::ClockEvent()
+ : Event(&mainEventQueue)
+{
+ DPRINTF(Tsunami, "Clock Event Initilizing\n");
+ mode = 0;
+}
+
+void
+TsunamiIO::ClockEvent::process()
+{
+ DPRINTF(Tsunami, "Timer Interrupt\n");
+ if (mode == 0)
+ status = 0x20; // set bit that linux is looking for
+ else
+ schedule(curTick + interval);
+}
+
+void
+TsunamiIO::ClockEvent::Program(int count)
+{
+ DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
+ interval = count * ticksPerSecond/1193180UL; // should be count * (cpufreq/pitfreq)
+ schedule(curTick + interval);
+ status = 0;
+}
+
+const char *
+TsunamiIO::ClockEvent::description()
+{
+ return "tsunami 8254 Interval timer";
+}
+
+void
+TsunamiIO::ClockEvent::ChangeMode(uint8_t md)
+{
+ mode = md;
+}
+
+uint8_t
+TsunamiIO::ClockEvent::Status()
+{
+ return status;
+}
+
+
TsunamiIO::TsunamiIO(const string &name, /*Tsunami *t,*/
Addr addr, Addr mask, MemoryController *mmu)
: MmapDevice(name, addr, mask, mmu)/*, tsunami(t) */
{
-
+ timerData = 0;
}
Fault
@@ -36,11 +81,26 @@ TsunamiIO::read(MemReqPtr req, uint8_t *data)
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff);
- // Addr daddr = (req->paddr & addr_mask) >> 6;
+ Addr daddr = (req->paddr & addr_mask);
// ExecContext *xc = req->xc;
// int cpuid = xc->cpu_id;
+
+ switch(req->size) {
+ case sizeof(uint8_t):
+ switch(daddr) {
+ case TSDEV_TMR_CTL:
+ *(uint8_t*)data = timer2.Status();
+ return No_Fault;
+ default:
+ panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
+ }
+ case sizeof(uint16_t):
+ case sizeof(uint32_t):
+ case sizeof(uint64_t):
+ default:
+ panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size);
+ }
panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
- // *(uint64_t*)data = 0x00;
return No_Fault;
}
@@ -75,7 +135,52 @@ TsunamiIO::write(MemReqPtr req, const uint8_t *data)
case TSDEV_DMA1_MASK:
case TSDEV_DMA2_MASK:
return No_Fault;
- default:
+ case TSDEV_TMR_CTL:
+ return No_Fault;
+ case TSDEV_TMR2_CTL:
+ if ((*(uint8_t*)data & 0x30) != 0x30)
+ panic("Only L/M write supported\n");
+
+ switch(*(uint8_t*)data >> 6) {
+ case 0:
+ timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
+ break;
+ case 1:
+ timer1.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
+ break;
+ case 2:
+ timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
+ break;
+ case 3:
+ default:
+ panic("Read Back Command not implemented\n");
+ }
+ return No_Fault;
+ case TSDEV_TMR2_DATA:
+ /* two writes before we actually start the Timer
+ so I set a flag in the timerData */
+ if(timerData & 0x1000) {
+ timerData &= 0x1000;
+ timerData += *(uint8_t*)data << 8;
+ timer2.Program(timerData);
+ } else {
+ timerData = *(uint8_t*)data;
+ timerData |= 0x1000;
+ }
+ return No_Fault;
+ case TSDEV_TMR0_DATA:
+ /* two writes before we actually start the Timer
+ so I set a flag in the timerData */
+ if(timerData & 0x1000) {
+ timerData &= 0x1000;
+ timerData += *(uint8_t*)data << 8;
+ timer0.Program(timerData);
+ } else {
+ timerData = *(uint8_t*)data;
+ timerData |= 0x1000;
+ }
+ return No_Fault;
+ default:
panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
}
case sizeof(uint16_t):