From f9f4a7498611082079ae4acd2d421a857cab30d8 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 22 Jan 2004 19:02:07 -0500 Subject: added the 8254 programmable interval timer --HG-- extra : convert_revision : 6a111db98c05a3dd692c757611c3eb9c8cfdd32f --- dev/tsunami_io.cc | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 4 deletions(-) (limited to 'dev/tsunami_io.cc') 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): -- cgit v1.2.3