added the 8254 programmable interval timer
authorAli Saidi <saidi@eecs.umich.edu>
Fri, 23 Jan 2004 00:02:07 +0000 (19:02 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Fri, 23 Jan 2004 00:02:07 +0000 (19:02 -0500)
--HG--
extra : convert_revision : 6a111db98c05a3dd692c757611c3eb9c8cfdd32f

dev/tsunami_io.cc
dev/tsunami_io.hh
dev/tsunamireg.h

index d5f2af960b1da490b84bd7fe9cf23a26da597040..eb0b9ae91a11dd7c0275b0f2f71bd3a2b2b2c34c 100644 (file)
 
 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):
index 943df77c242bb2abcf1beb7701fd8ff74153a1ee..1336a703e3fda992b26252d0afb34c8a6ec20a42 100644 (file)
  */
 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);
index b41b3994d32ec6e69d7ffeb32b0032e6be7aa21d..f178974b9749f9fb42b93614076217960a62f2d1 100644 (file)
@@ -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__