memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+ cmdReg.error = 1;
+
dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
// talk to controller to set interrupt
if (ctrl)
+ ctrl->bmi_regs[BMIS0] |= IDEINTS;
ctrl->intrPost();
}
void
TsunamiIO::RTCEvent::process()
{
+ static int intr_count = 0;
DPRINTF(MC146818, "RTC Timer Interrupt\n");
schedule(curTick + interval);
//Actually interrupt the processor here
tsunami->cchip->postRTC();
+ if (intr_count == 1023)
+ tm.tm_sec = (tm.tm_sec + 1) % 60;
+
+ intr_count = (intr_count + 1) % 1024;
- // For FreeBSD
- tm.tm_sec++;
}
const char *
DPRINTF(Tsunami, "Clock Event Initilizing\n");
mode = 0;
+
+ current_count.whole = 0;
+ latched_count.whole = 0;
+ latch_on = false;
+ read_msb = false;
}
void
status = 0x20; // set bit that linux is looking for
else
schedule(curTick + interval);
+
+ current_count.whole--; //decrement count
}
void
DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * interval);
schedule(curTick + count * interval);
status = 0;
+
+ current_count.whole = count;
}
const char *
return status;
}
+void
+TsunamiIO::ClockEvent::LatchCount()
+{
+ if(!latch_on) {
+ latch_on = true;
+ read_msb = false;
+ latched_count.whole = current_count.whole;
+ }
+}
+
+uint8_t
+TsunamiIO::ClockEvent::Read()
+{
+ if(latch_on) {
+ if(!read_msb) {
+ read_msb = true;
+ return latched_count.half.lsb;
+ } else {
+ latch_on = false;
+ return latched_count.half.msb;
+ }
+ } else {
+ if(!read_msb) {
+ read_msb = true;
+ return current_count.half.lsb;
+ } else {
+ return current_count.half.msb;
+ }
+ }
+}
+
+
void
TsunamiIO::ClockEvent::serialize(std::ostream &os)
{
case TSDEV_TMR_CTL:
*(uint8_t*)data = timer2.Status();
return No_Fault;
+ case TSDEV_TMR0_DATA:
+ *(uint8_t *)data = timer0.Read();
+ return No_Fault;
case TSDEV_RTC_DATA:
switch(RTCAddress) {
case RTC_CNTRL_REGA:
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 >> 4) & 0x3) {
+ case 0x0:
+ switch(*(uint8_t*)data >> 6) {
+ case 0:
+ timer0.LatchCount();
+ break;
+ case 2:
+ timer2.LatchCount();
+ break;
+ default:
+ panic("Read Back Command not implemented\n");
+ }
+ break;
+ case 0x3:
+ break;
+ default:
+ panic("Only L/M write and Counter-Latch read supported\n");
+ }
switch(*(uint8_t*)data >> 6) {
case 0:
uint8_t mode;
/** The status of the PIT */
uint8_t status;
+ /** The counts (current and latched) of the PIT */
+ union {
+ uint16_t whole;
+ struct {
+ uint8_t msb;
+ uint8_t lsb;
+ } half;
+ } current_count, latched_count;
+
+ /** Thse state of the output latch of the PIT */
+ bool latch_on;
+ bool read_msb;
public:
/**
uint8_t Status();
/**
+ * Latch the count of the PIT.
+ */
+ void LatchCount();
+
+ /**
+ * The current PIT count.
+ * @return the count of the PIT
+ */
+ uint8_t Read();
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
Addr addr = 0;
/**
- * Any time ide_delay_50ms, calibarte_delay or
- * determine_cpu_caches is called just skip the
- * function. Currently determine_cpu_caches only is used put
- * information in proc, however if that changes in the future we
- * will have to fill in the cache size variables appropriately.
+ * Any time DELAY is called just skip the function.
+ * Replace calibrate_clocks with function below.
*/
skipDelayEvent = new SkipFuncEvent(&pcEventQueue, "DELAY");
if (kernelSymtab->findAddress("DELAY", addr))
skipDelayEvent->schedule(addr+sizeof(MachInst));
- skipOROMEvent = new SkipFuncEvent(&pcEventQueue, "orm_identify");
- if (kernelSymtab->findAddress("orm_identify", addr))
- skipOROMEvent->schedule(addr+sizeof(MachInst));
-
- skipAicEvent = new SkipFuncEvent(&pcEventQueue, "ahc_isa_identify");
- if (kernelSymtab->findAddress("ahc_isa_identify", addr))
- skipAicEvent->schedule(addr+sizeof(MachInst));
-
- skipPNPEvent = new SkipFuncEvent(&pcEventQueue, "pnp_identify");
- if (kernelSymtab->findAddress("pnp_identify", addr))
- skipPNPEvent->schedule(addr+sizeof(MachInst));
-
- skipATAEvent = new SkipFuncEvent(&pcEventQueue, "ata_attach");
- if (kernelSymtab->findAddress("ata_attach", addr))
- skipATAEvent->schedule(addr+sizeof(MachInst));
-
skipCalibrateClocks = new FreebsdSkipCalibrateClocksEvent(&pcEventQueue, "calibrate_clocks");
if (kernelSymtab->findAddress("calibrate_clocks", addr))
skipCalibrateClocks->schedule(addr + sizeof(MachInst) * 2);
FreebsdSystem::~FreebsdSystem()
{
delete skipDelayEvent;
- delete skipOROMEvent;
- delete skipAicEvent;
- delete skipATAEvent;
- delete skipPNPEvent;
delete skipCalibrateClocks;
}
#include "kern/freebsd/freebsd_events.hh"
-/**
- * This class skips lengthy functions in the FreeBSD kernel.
- */
class FreebsdSystem : public System
{
private:
- /** PC based event to skip the DELAY call */
SkipFuncEvent *skipDelayEvent;
- SkipFuncEvent *skipOROMEvent;
-
- SkipFuncEvent *skipAicEvent;
-
- SkipFuncEvent *skipPNPEvent;
-
- SkipFuncEvent *skipATAEvent;
-
FreebsdSkipCalibrateClocksEvent *skipCalibrateClocks;
public:
class TsunamiFake(FooPioDevice):
type = 'TsunamiFake'
+ size = Param.Addr("Size of address range")
class TsunamiIO(FooPioDevice):
type = 'TsunamiIO'