diff options
author | Ali Saidi <saidi@eecs.umich.edu> | 2004-01-22 19:02:07 -0500 |
---|---|---|
committer | Ali Saidi <saidi@eecs.umich.edu> | 2004-01-22 19:02:07 -0500 |
commit | f9f4a7498611082079ae4acd2d421a857cab30d8 (patch) | |
tree | c6e4ba0168a2f2bc8223e6715d88637f71b1c41e /dev/tsunami_io.cc | |
parent | d9e8ecbf46ead49c2c8174c1362a5cb136b4b5f9 (diff) | |
download | gem5-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.cc | 113 |
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): |