added the 8254 programmable interval timer
--HG-- extra : convert_revision : 6a111db98c05a3dd692c757611c3eb9c8cfdd32f
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__
|
||||
|
||||
Reference in New Issue
Block a user