Devices: Separate out the MC146818 RTC so both Alpha and X86 can use it.
authorGabe Black <gblack@eecs.umich.edu>
Tue, 25 Mar 2008 06:15:06 +0000 (02:15 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Tue, 25 Mar 2008 06:15:06 +0000 (02:15 -0400)
--HG--
extra : convert_revision : 1e7f5185654ed0845678c2169c702d3b977159ed

src/dev/SConscript
src/dev/alpha/SConscript
src/dev/alpha/tsunami_io.cc
src/dev/alpha/tsunami_io.hh
src/dev/mc146818.cc [new file with mode: 0644]
src/dev/mc146818.hh [new file with mode: 0644]

index 0aba8ac35295ed1d48569e4ecbdc500be94b7f3d..ee7adb8c8b20f39447b65bfb962e9bd7d1cfd42f 100644 (file)
@@ -56,6 +56,7 @@ if env['FULL_SYSTEM']:
     Source('ide_disk.cc')
     Source('io_device.cc')
     Source('isa_fake.cc')
+    Source('mc146818.cc')
     Source('ns_gige.cc')
     Source('pciconfigall.cc')
     Source('pcidev.cc')
@@ -84,6 +85,7 @@ if env['FULL_SYSTEM']:
     TraceFlag('IdeCtrl')
     TraceFlag('IdeDisk')
     TraceFlag('IsaFake')
+    TraceFlag('MC146818')
     TraceFlag('PCIDEV')
     TraceFlag('PciConfigAll')
     TraceFlag('SimpleDisk')
index 2292c3c57e47fe75e5484abfce7d537dbd2dea30..6bd26a9b1cb53b885f4557870ead9dd106b98dea 100644 (file)
@@ -42,5 +42,4 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'alpha':
     Source('tsunami_pchip.cc')
 
     TraceFlag('AlphaConsole')
-    TraceFlag('MC146818')
     TraceFlag('Tsunami')
index 710aca48df307c06048284cbc619b251fa942ab3..88999ecc5c9602bcc78f5020ff1f28fe8925efaa 100644 (file)
@@ -57,157 +57,9 @@ using namespace std;
 //Should this be AlphaISA?
 using namespace TheISA;
 
-TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami,
-                    const TsunamiIO::Params *p)
-    : _name(n), event(tsunami, p->frequency), addr(0)
+TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) :
+    MC146818(n, p->time, p->year_is_bcd, p->frequency), tsunami(p->tsunami)
 {
-    memset(clock_data, 0, sizeof(clock_data));
-    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
-    stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
-
-    year = p->time.tm_year;
-
-    if (p->year_is_bcd) {
-        // The datasheet says that the year field can be either BCD or
-        // years since 1900.  Linux seems to be happy with years since
-        // 1900.
-        year = year % 100;
-        int tens = year / 10;
-        int ones = year % 10;
-        year = (tens << 4) + ones;
-    }
-
-    // Unix is 0-11 for month, data seet says start at 1
-    mon = p->time.tm_mon + 1;
-    mday = p->time.tm_mday;
-    hour = p->time.tm_hour;
-    min = p->time.tm_min;
-    sec = p->time.tm_sec;
-
-    // Datasheet says 1 is sunday
-    wday = p->time.tm_wday + 1;
-
-    DPRINTFN("Real-time clock set to %s", asctime(&p->time));
-}
-
-void
-TsunamiIO::RTC::writeAddr(const uint8_t data)
-{
-    if (data <= RTC_STAT_REGD)
-        addr = data;
-    else
-        panic("RTC addresses over 0xD are not implemented.\n");
-}
-
-void
-TsunamiIO::RTC::writeData(const uint8_t data)
-{
-    if (addr < RTC_STAT_REGA)
-        clock_data[addr] = data;
-    else {
-        switch (addr) {
-          case RTC_STAT_REGA:
-            if (data != (RTCA_32768HZ | RTCA_1024HZ))
-                panic("Unimplemented RTC register A value write!\n");
-            stat_regA = data;
-            break;
-          case RTC_STAT_REGB:
-            if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
-                panic("Write to RTC reg B bits that are not implemented!\n");
-
-            if (data & RTCB_PRDC_IE) {
-                if (!event.scheduled())
-                    event.scheduleIntr();
-            } else {
-                if (event.scheduled())
-                    event.deschedule();
-            }
-            stat_regB = data;
-            break;
-          case RTC_STAT_REGC:
-          case RTC_STAT_REGD:
-            panic("RTC status registers C and D are not implemented.\n");
-            break;
-        }
-    }
-}
-
-uint8_t
-TsunamiIO::RTC::readData()
-{
-    if (addr < RTC_STAT_REGA)
-        return clock_data[addr];
-    else {
-        switch (addr) {
-          case RTC_STAT_REGA:
-            // toggle UIP bit for linux
-            stat_regA ^= RTCA_UIP;
-            return stat_regA;
-            break;
-          case RTC_STAT_REGB:
-            return stat_regB;
-            break;
-          case RTC_STAT_REGC:
-          case RTC_STAT_REGD:
-            return 0x00;
-            break;
-          default:
-            panic("Shouldn't be here");
-        }
-    }
-}
-
-void
-TsunamiIO::RTC::serialize(const string &base, ostream &os)
-{
-    paramOut(os, base + ".addr", addr);
-    arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
-    paramOut(os, base + ".stat_regA", stat_regA);
-    paramOut(os, base + ".stat_regB", stat_regB);
-}
-
-void
-TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp,
-                            const string &section)
-{
-    paramIn(cp, section, base + ".addr", addr);
-    arrayParamIn(cp, section, base + ".clock_data", clock_data,
-                 sizeof(clock_data));
-    paramIn(cp, section, base + ".stat_regA", stat_regA);
-    paramIn(cp, section, base + ".stat_regB", stat_regB);
-
-    // We're not unserializing the event here, but we need to
-    // rescehedule the event since curTick was moved forward by the
-    // checkpoint
-    event.reschedule(curTick + event.interval);
-}
-
-TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i)
-    : Event(&mainEventQueue), tsunami(t), interval(i)
-{
-    DPRINTF(MC146818, "RTC Event Initilizing\n");
-    schedule(curTick + interval);
-}
-
-void
-TsunamiIO::RTC::RTCEvent::scheduleIntr()
-{
-  schedule(curTick + interval);
-}
-
-void
-TsunamiIO::RTC::RTCEvent::process()
-{
-    DPRINTF(MC146818, "RTC Timer Interrupt\n");
-    schedule(curTick + interval);
-    //Actually interrupt the processor here
-    tsunami->cchip->postRTC();
-}
-
-const char *
-TsunamiIO::RTC::RTCEvent::description() const
-{
-    return "tsunami RTC interrupt";
 }
 
 TsunamiIO::PITimer::PITimer(const string &name)
@@ -436,7 +288,7 @@ TsunamiIO::PITimer::Counter::CounterEvent::description() const
 
 TsunamiIO::TsunamiIO(const Params *p)
     : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
-      rtc(p->name + ".rtc", p->tsunami, p)
+      rtc(p->name + ".rtc", p)
 {
     pioSize = 0x100;
 
@@ -495,7 +347,7 @@ TsunamiIO::read(PacketPtr pkt)
             pkt->set(pitimer.counter2.read());
             break;
           case TSDEV_RTC_DATA:
-            pkt->set(rtc.readData());
+            pkt->set(rtc.readData(rtcAddr));
             break;
           case TSDEV_CTRL_PORTB:
             if (pitimer.counter2.outputHigh())
@@ -573,10 +425,10 @@ TsunamiIO::write(PacketPtr pkt)
         pitimer.writeControl(pkt->get<uint8_t>());
         break;
       case TSDEV_RTC_ADDR:
-        rtc.writeAddr(pkt->get<uint8_t>());
+        rtcAddr = pkt->get<uint8_t>();
         break;
       case TSDEV_RTC_DATA:
-        rtc.writeData(pkt->get<uint8_t>());
+        rtc.writeData(rtcAddr, pkt->get<uint8_t>());
         break;
       case TSDEV_KBD:
       case TSDEV_DMA1_CMND:
@@ -623,6 +475,7 @@ TsunamiIO::clearPIC(uint8_t bitvector)
 void
 TsunamiIO::serialize(ostream &os)
 {
+    SERIALIZE_SCALAR(rtcAddr);
     SERIALIZE_SCALAR(timerData);
     SERIALIZE_SCALAR(mask1);
     SERIALIZE_SCALAR(mask2);
@@ -639,6 +492,7 @@ TsunamiIO::serialize(ostream &os)
 void
 TsunamiIO::unserialize(Checkpoint *cp, const string &section)
 {
+    UNSERIALIZE_SCALAR(rtcAddr);
     UNSERIALIZE_SCALAR(timerData);
     UNSERIALIZE_SCALAR(mask1);
     UNSERIALIZE_SCALAR(mask2);
index 05c4ee910e5f5725f2e6500cc26287c3e695e42b..3972efa48bf2d5e8f809836626122d8e3b0268ea 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "base/range.hh"
 #include "dev/alpha/tsunami.hh"
+#include "dev/mc146818.hh"
 #include "dev/io_device.hh"
 #include "params/TsunamiIO.hh"
 #include "sim/eventq.hh"
@@ -53,91 +54,19 @@ class TsunamiIO : public BasicPioDevice
     struct tm tm;
 
   protected:
-    /** Real-Time Clock (MC146818) */
-    class RTC
-    {
-      private:
-        /** Event for RTC periodic interrupt */
-        struct RTCEvent : public Event
-        {
-            /** A pointer back to tsunami to create interrupt the processor. */
-            Tsunami* tsunami;
-            Tick interval;
-
-            RTCEvent(Tsunami* t, Tick i);
-
-            /** Schedule the RTC periodic interrupt */
-            void scheduleIntr();
-
-            /** Event process to occur at interrupt*/
-            virtual void process();
-
-            /** Event description */
-            virtual const char *description() const;
-        };
-
-      private:
-        std::string _name;
-        const std::string &name() const { return _name; }
-
-        /** RTC periodic interrupt event */
-        RTCEvent event;
-
-        /** Current RTC register address/index */
-        int addr;
-
-        /** Data for real-time clock function */
-        union {
-            uint8_t clock_data[10];
-
-            struct {
-                uint8_t sec;
-                uint8_t sec_alrm;
-                uint8_t min;
-                uint8_t min_alrm;
-                uint8_t hour;
-                uint8_t hour_alrm;
-                uint8_t wday;
-                uint8_t mday;
-                uint8_t mon;
-                uint8_t year;
-            };
-        };
-
-        /** RTC status register A */
-        uint8_t stat_regA;
-
-        /** RTC status register B */
-        uint8_t stat_regB;
 
+    class TsunamiRTC : public MC146818
+    {
       public:
-        RTC(const std::string &name, Tsunami* tsunami,
-            const TsunamiIOParams *params);
-
-        /** RTC address port: write address of RTC RAM data to access */
-        void writeAddr(const uint8_t data);
-
-        /** RTC write data */
-        void writeData(const uint8_t data);
-
-        /** RTC read data */
-        uint8_t readData();
+        Tsunami * tsunami;
+        TsunamiRTC(const std::string &n, const TsunamiIOParams *p);
 
-        /**
-          * Serialize this object to the given output stream.
-          * @param base The base name of the counter object.
-          * @param os The stream to serialize to.
-          */
-        void serialize(const std::string &base, std::ostream &os);
-
-        /**
-         * Reconstruct the state of this object from a checkpoint.
-          * @param base The base name of the counter object.
-         * @param cp The checkpoint use.
-         * @param section The section name of this object
-         */
-        void unserialize(const std::string &base, Checkpoint *cp,
-                         const std::string &section);
+      protected:
+        void handleEvent()
+        {
+            //Actually interrupt the processor here
+            tsunami->cchip->postRTC();
+        }
     };
 
     /** Programmable Interval Timer (Intel 8254) */
@@ -296,7 +225,9 @@ class TsunamiIO : public BasicPioDevice
     /** Intel 8253 Periodic Interval Timer */
     PITimer pitimer;
 
-    RTC rtc;
+    TsunamiRTC rtc;
+
+    uint8_t rtcAddr;
 
     /** The interval is set via two writes to the PIT.
      * This variable contains a flag as to how many writes have happened, and
diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc
new file mode 100644 (file)
index 0000000..9844221
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ *          Andrew Schultz
+ *          Miguel Serrano
+ */
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <string>
+
+#include "base/time.hh"
+#include "base/trace.hh"
+#include "dev/mc146818.hh"
+#include "dev/rtcreg.h"
+
+using namespace std;
+
+MC146818::MC146818(const string &n, const struct tm time,
+        bool bcd, Tick frequency)
+    : _name(n), event(this, frequency)
+{
+    memset(clock_data, 0, sizeof(clock_data));
+    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
+    stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
+
+    year = time.tm_year;
+
+    if (bcd) {
+        // The datasheet says that the year field can be either BCD or
+        // years since 1900.  Linux seems to be happy with years since
+        // 1900.
+        year = year % 100;
+        int tens = year / 10;
+        int ones = year % 10;
+        year = (tens << 4) + ones;
+    }
+
+    // Unix is 0-11 for month, data seet says start at 1
+    mon = time.tm_mon + 1;
+    mday = time.tm_mday;
+    hour = time.tm_hour;
+    min = time.tm_min;
+    sec = time.tm_sec;
+
+    // Datasheet says 1 is sunday
+    wday = time.tm_wday + 1;
+
+    DPRINTFN("Real-time clock set to %s", asctime(&time));
+}
+
+void
+MC146818::writeData(const uint8_t addr, const uint8_t data)
+{
+    if (addr < RTC_STAT_REGA)
+        clock_data[addr] = data;
+    else {
+        switch (addr) {
+          case RTC_STAT_REGA:
+            if (data != (RTCA_32768HZ | RTCA_1024HZ))
+                panic("Unimplemented RTC register A value write!\n");
+            stat_regA = data;
+            break;
+          case RTC_STAT_REGB:
+            if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
+                panic("Write to RTC reg B bits that are not implemented!\n");
+
+            if (data & RTCB_PRDC_IE) {
+                if (!event.scheduled())
+                    event.scheduleIntr();
+            } else {
+                if (event.scheduled())
+                    event.deschedule();
+            }
+            stat_regB = data;
+            break;
+          case RTC_STAT_REGC:
+          case RTC_STAT_REGD:
+            panic("RTC status registers C and D are not implemented.\n");
+            break;
+        }
+    }
+}
+
+uint8_t
+MC146818::readData(uint8_t addr)
+{
+    if (addr < RTC_STAT_REGA)
+        return clock_data[addr];
+    else {
+        switch (addr) {
+          case RTC_STAT_REGA:
+            // toggle UIP bit for linux
+            stat_regA ^= RTCA_UIP;
+            return stat_regA;
+            break;
+          case RTC_STAT_REGB:
+            return stat_regB;
+            break;
+          case RTC_STAT_REGC:
+          case RTC_STAT_REGD:
+            return 0x00;
+            break;
+          default:
+            panic("Shouldn't be here");
+        }
+    }
+}
+
+void
+MC146818::serialize(const string &base, ostream &os)
+{
+    arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
+    paramOut(os, base + ".stat_regA", stat_regA);
+    paramOut(os, base + ".stat_regB", stat_regB);
+}
+
+void
+MC146818::unserialize(const string &base, Checkpoint *cp,
+                      const string &section)
+{
+    arrayParamIn(cp, section, base + ".clock_data", clock_data,
+                 sizeof(clock_data));
+    paramIn(cp, section, base + ".stat_regA", stat_regA);
+    paramIn(cp, section, base + ".stat_regB", stat_regB);
+
+    // We're not unserializing the event here, but we need to
+    // rescehedule the event since curTick was moved forward by the
+    // checkpoint
+    event.reschedule(curTick + event.interval);
+}
+
+MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i)
+    : Event(&mainEventQueue), parent(_parent), interval(i)
+{
+    DPRINTF(MC146818, "RTC Event Initilizing\n");
+    schedule(curTick + interval);
+}
+
+void
+MC146818::RTCEvent::scheduleIntr()
+{
+  schedule(curTick + interval);
+}
+
+void
+MC146818::RTCEvent::process()
+{
+    DPRINTF(MC146818, "RTC Timer Interrupt\n");
+    schedule(curTick + interval);
+    parent->handleEvent();
+}
+
+const char *
+MC146818::RTCEvent::description() const
+{
+    return "RTC interrupt";
+}
diff --git a/src/dev/mc146818.hh b/src/dev/mc146818.hh
new file mode 100644 (file)
index 0000000..f91e462
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ *          Andrew Schultz
+ *          Miguel Serrano
+ */
+
+#ifndef __DEV_MC146818_HH__
+#define __DEV_MC146818_HH__
+
+#include "base/range.hh"
+#include "sim/eventq.hh"
+
+/** Real-Time Clock (MC146818) */
+class MC146818
+{
+  protected:
+    virtual void handleEvent()
+    {
+        warn("No RTC event handler defined.\n");
+    }
+
+  private:
+    /** Event for RTC periodic interrupt */
+    struct RTCEvent : public Event
+    {
+        MC146818 * parent;
+        Tick interval;
+
+        RTCEvent(MC146818 * _parent, Tick i);
+
+        /** Schedule the RTC periodic interrupt */
+        void scheduleIntr();
+
+        /** Event process to occur at interrupt*/
+        virtual void process();
+
+        /** Event description */
+        virtual const char *description() const;
+    };
+
+  private:
+    std::string _name;
+    const std::string &name() const { return _name; }
+
+    /** RTC periodic interrupt event */
+    RTCEvent event;
+
+    /** Data for real-time clock function */
+    union {
+        uint8_t clock_data[10];
+
+        struct {
+            uint8_t sec;
+            uint8_t sec_alrm;
+            uint8_t min;
+            uint8_t min_alrm;
+            uint8_t hour;
+            uint8_t hour_alrm;
+            uint8_t wday;
+            uint8_t mday;
+            uint8_t mon;
+            uint8_t year;
+        };
+    };
+
+    /** RTC status register A */
+    uint8_t stat_regA;
+
+    /** RTC status register B */
+    uint8_t stat_regB;
+
+  public:
+    virtual ~MC146818()
+    {}
+
+    MC146818(const std::string &name, const struct tm time,
+            bool bcd, Tick frequency);
+
+    /** RTC write data */
+    void writeData(const uint8_t addr, const uint8_t data);
+
+    /** RTC read data */
+    uint8_t readData(const uint8_t addr);
+
+    /**
+      * Serialize this object to the given output stream.
+      * @param base The base name of the counter object.
+      * @param os The stream to serialize to.
+      */
+    void serialize(const std::string &base, std::ostream &os);
+
+    /**
+     * Reconstruct the state of this object from a checkpoint.
+     * @param base The base name of the counter object.
+     * @param cp The checkpoint use.
+     * @param section The section name of this object
+     */
+    void unserialize(const std::string &base, Checkpoint *cp,
+                     const std::string &section);
+};
+
+#endif // __DEV_MC146818_HH__