text: /*
   * 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/bitunion.hh"
  #include "sim/eventq_impl.hh"
  
  /** Real-Time Clock (MC146818) */
  class MC146818 : public EventManager
  {
    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;
          Tick offset;
  
          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;
      };
  
      /** Event for RTC periodic interrupt */
      struct RTCTickEvent : public Event
      {
          MC146818 * parent;
          Tick offset;
  
          RTCTickEvent(MC146818 * _parent) :
              parent(_parent), offset(SimClock::Int::s)
          {}
  
          /** Event process to occur at interrupt*/
          void process();
  
          /** Event description */
          const char *description() const;
      };
  
    private:
      std::string _name;
      const std::string &name() const { return _name; }
  
      /** RTC periodic interrupt event */
      RTCEvent event;
  
      /** RTC tick event */
      RTCTickEvent tickEvent;
  
      /** 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;
          };
      };
  
      struct tm curTime;
  
      void setTime(const struct tm time);
  
      BitUnion8(RtcRegA)
          Bitfield<7> uip;    /// 1 = date and time update in progress
          Bitfield<6, 4> dv;  /// Divider configuration
          /** Rate selection
              0 = Disabled
              For 32768 Hz time bases:
                Freq = 32768Hz / 2**(n-1) for n >= 3
                Freq = 256Hz if n = 1
                Freq = 128Hz if n = 2
              Othwerise:
                Freq = 32768Hz / 2**(n-1)
          */
          Bitfield<3, 0> rs;
      EndBitUnion(RtcRegA)
  
      /// Is the DV field in regA set to disabled?
      static inline bool rega_dv_disabled(const RtcRegA &reg);
  
      BitUnion8(RtcRegB)
          Bitfield<7> set;       /// stop clock updates
          Bitfield<6> pie;       /// 1 = enable periodic clock interrupt
          Bitfield<5> aie;       /// 1 = enable alarm interrupt
          Bitfield<4> uie;       /// 1 = enable update-ended interrupt
          Bitfield<3> sqwe;      /// 1 = output sqare wave at SQW pin
          Bitfield<2> dm;        /// 0 = BCD, 1 = Binary coded time
          Bitfield<1> format24h; /// 0 = 12 hours, 1 = 24 hours
          Bitfield<0> dse;       /// USA Daylight Savings Time enable
      EndBitUnion(RtcRegB)
  
      /** RTC status register A */
      RtcRegA stat_regA;
  
      /** RTC status register B */
      RtcRegB stat_regB;
  
    public:
      MC146818(EventManager *em, const std::string &name, const struct tm time,
              bool bcd, Tick frequency);
      virtual ~MC146818();
  
      /** Start ticking */
      virtual void startup();
  
      /** RTC write data */
      void writeData(const uint8_t addr, const uint8_t data);
  
      /** RTC read data */
      uint8_t readData(const uint8_t addr);
  
      void tickClock();
  
      /**
        * 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__
  