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 | |
parent | d9e8ecbf46ead49c2c8174c1362a5cb136b4b5f9 (diff) | |
download | gem5-f9f4a7498611082079ae4acd2d421a857cab30d8.tar.xz |
added the 8254 programmable interval timer
--HG--
extra : convert_revision : 6a111db98c05a3dd692c757611c3eb9c8cfdd32f
Diffstat (limited to 'dev')
-rw-r--r-- | dev/tsunami_io.cc | 113 | ||||
-rw-r--r-- | dev/tsunami_io.hh | 26 | ||||
-rw-r--r-- | dev/tsunamireg.h | 5 |
3 files changed, 139 insertions, 5 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): diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh index 943df77c2..1336a703e 100644 --- a/dev/tsunami_io.hh +++ b/dev/tsunami_io.hh @@ -41,15 +41,41 @@ */ class TsunamiIO : public MmapDevice { + public: protected: + class ClockEvent : public Event + { + protected: + Tick interval; + uint8_t mode; + uint8_t status; + + public: + ClockEvent(); + + virtual void process(); + virtual const char *description(); + void Program(int count); + void ChangeMode(uint8_t mode); + uint8_t Status(); + + }; + + uint8_t mask1; uint8_t mask2; uint8_t mode1; uint8_t mode2; + ClockEvent timer0; + ClockEvent timer1; + ClockEvent timer2; + + uint32_t timerData; + public: TsunamiIO(const std::string &name, /*Tsunami *t,*/ Addr addr, Addr mask, MemoryController *mmu); diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h index b41b3994d..f178974b9 100644 --- a/dev/tsunamireg.h +++ b/dev/tsunamireg.h @@ -74,5 +74,8 @@ #define TSDEV_DMA2_MODE 0xD6 #define TSDEV_DMA1_MASK 0x0A #define TSDEV_DMA2_MASK 0xD4 - +#define TSDEV_TMR_CTL 0x61 +#define TSDEV_TMR2_CTL 0x43 +#define TSDEV_TMR2_DATA 0x42 +#define TSDEV_TMR0_DATA 0x40 #endif // __TSUNAMIREG_H__ |