Support for Tsunami coming along... RTC, PIC working, UART in progress
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 26 Jan 2004 18:26:34 +0000 (13:26 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 26 Jan 2004 18:26:34 +0000 (13:26 -0500)
dev/tsunami_io.cc:
    PIC, PIT, RTC implementation for tsunami working so far
dev/tsunami_io.hh:
    PIT, PIC, RTC implementation for tlaser working so far
dev/tsunamireg.h:
    Added RTC defines
kern/linux/linux_system.cc:
    wrote cycle frequency into variable so linux doesn't probe for it.
    The support exists, but it takes two seconds of time to do on a real
    machine, so forever in the simulator.

--HG--
extra : convert_revision : e0ed7f271ece4ed69c06af35d1b0e8ed848cd138

dev/tsunami_io.cc
dev/tsunami_io.hh
dev/tsunami_uart.cc [new file with mode: 0644]
dev/tsunami_uart.hh [new file with mode: 0644]
dev/tsunamireg.h
kern/linux/linux_system.cc

index 537e40a2256c7a1266b48d3eaceead28e1118529..b6533dcbacb76a78d49cd59a8fe78a8b65a8e0f9 100644 (file)
@@ -1,9 +1,11 @@
 /* $Id$ */
 
 /* @file
- * Tsunami DMA fake
+ * Tsunami I/O including PIC, PIT, RTC, DMA
  */
 
+#include <sys/time.h>
+
 #include <deque>
 #include <string>
 #include <vector>
 #include "base/trace.hh"
 #include "cpu/exec_context.hh"
 #include "dev/console.hh"
-#include "dev/etherdev.hh"
-#include "dev/scsi_ctrl.hh"
 #include "dev/tlaser_clock.hh"
 #include "dev/tsunami_io.hh"
 #include "dev/tsunamireg.h"
 #include "dev/tsunami.hh"
 #include "mem/functional_mem/memory_control.hh"
 #include "sim/builder.hh"
-#include "sim/system.hh"
 
 using namespace std;
+
+#define UNIX_YEAR_OFFSET 52
+
+//This will have to be dynamic if we want support usermode access of the RTC
+#define RTC_RATE  1024
+
+// Timer Event for Periodic interrupt of RTC
 TsunamiIO::RTCEvent::RTCEvent()
     : Event(&mainEventQueue)
 {
-    DPRINTF(Tsunami, "RTC Event Initilizing\n");
-    rtc_uip = 0;
-    schedule(curTick + (curTick % ticksPerSecond));
+    DPRINTF(MC146818, "RTC Event Initilizing\n");
+    schedule(curTick + ticksPerSecond/RTC_RATE);
 }
 
 void
 TsunamiIO::RTCEvent::process()
 {
-    DPRINTF(Tsunami, "Timer Interrupt\n");
-    if (rtc_uip == 0) {
-        rtc_uip = 1; //Signal a second has occured
-        schedule(curTick + (curTick % ticksPerSecond) - 10);
-            }
-    else
-        rtc_uip = 0; //Done signaling second has occured
-        schedule(curTick + (curTick % ticksPerSecond));
+    DPRINTF(MC146818, "Timer Interrupt\n");
+    schedule(curTick + ticksPerSecond/RTC_RATE);
+    //Actually interrupt the processor here
 }
 
 const char *
 TsunamiIO::RTCEvent::description()
 {
-    return "tsunami RTC changte second";
-}
-
-uint8_t
-TsunamiIO::RTCEvent::rtc_uip_value()
-{
-    return rtc_uip;
+    return "tsunami RTC 1024Hz interrupt";
 }
 
+// Timer Event for PIT Timers
 TsunamiIO::ClockEvent::ClockEvent()
     : Event(&mainEventQueue)
 {
@@ -76,7 +71,8 @@ void
 TsunamiIO::ClockEvent::Program(int count)
 {
     DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
-    interval = count * ticksPerSecond/1193180UL; // should be count * (cpufreq/pitfreq)
+    // should be count * (cpufreq/pitfreq)
+    interval = count * ticksPerSecond/1193180UL;
     schedule(curTick + interval);
     status = 0;
 }
@@ -100,11 +96,22 @@ TsunamiIO::ClockEvent::Status()
 }
 
 
-TsunamiIO::TsunamiIO(const string &name, /*Tsunami *t,*/
+
+
+TsunamiIO::TsunamiIO(const string &name, /*Tsunami *t,*/ time_t init_time,
                        Addr addr, Addr mask, MemoryController *mmu)
     : MmapDevice(name, addr, mask, mmu)/*, tsunami(t) */
 {
     timerData = 0;
+    set_time(init_time == 0 ? time(NULL) : init_time);
+    uip = 1;
+}
+
+void
+TsunamiIO::set_time(time_t t)
+{
+    gmtime_r(&t, &tm);
+    DPRINTFN("Real-time clock set to %s", asctime(&tm));
 }
 
 Fault
@@ -123,6 +130,47 @@ TsunamiIO::read(MemReqPtr req, uint8_t *data)
                 case TSDEV_TMR_CTL:
                     *(uint8_t*)data = timer2.Status();
                     return No_Fault;
+                case TSDEV_RTC_DATA:
+                    switch(RTCAddress) {
+                        case RTC_CONTROL_REGISTERA:
+                            *(uint8_t*)data = uip << 7 | 0x26;
+                            uip = !uip;
+                            return No_Fault;
+                        case RTC_CONTROL_REGISTERB:
+                            // DM and 24/12 and UIE
+                            *(uint8_t*)data = 0x46;
+                            return No_Fault;
+                        case RTC_CONTROL_REGISTERC:
+                            // If we want to support RTC user access in linux
+                            // This won't work, but for now it's fine
+                            *(uint8_t*)data = 0x00;
+                            return No_Fault;
+                        case RTC_CONTROL_REGISTERD:
+                            panic("RTC Control Register D not implemented");
+                        case RTC_SECOND:
+                            *(uint8_t *)data = tm.tm_sec;
+                            return No_Fault;
+                        case RTC_MINUTE:
+                            *(uint8_t *)data = tm.tm_min;
+                            return No_Fault;
+                        case RTC_HOUR:
+                            *(uint8_t *)data = tm.tm_hour;
+                            return No_Fault;
+                        case RTC_DAY_OF_WEEK:
+                            *(uint8_t *)data = tm.tm_wday;
+                            return No_Fault;
+                        case RTC_DAY_OF_MONTH:
+                            *(uint8_t *)data = tm.tm_mday;
+                        case RTC_MONTH:
+                            *(uint8_t *)data = tm.tm_mon + 1;
+                            return No_Fault;
+                        case RTC_YEAR:
+                            *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET;
+                            return No_Fault;
+                        default:
+                            panic("Unknown RTC Address\n");
+                    }
+
                 default:
                     panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
             }
@@ -177,13 +225,9 @@ TsunamiIO::write(MemReqPtr req, const uint8_t *data)
                         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");
                     }
@@ -212,6 +256,11 @@ TsunamiIO::write(MemReqPtr req, const uint8_t *data)
                             timerData |= 0x1000;
                         }
                         return No_Fault;
+                case TSDEV_RTC_ADDR:
+                        RTCAddress = *(uint8_t*)data;
+                        return No_Fault;
+                case TSDEV_RTC_DATA:
+                        panic("RTC Write not implmented (rtc.o won't work)\n");
                  default:
                     panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
             }
@@ -241,6 +290,7 @@ TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
 
  //   SimObjectParam<Tsunami *> tsunami;
+    Param<time_t> time;
     SimObjectParam<MemoryController *> mmu;
     Param<Addr> addr;
     Param<Addr> mask;
@@ -250,6 +300,8 @@ END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
 
 //    INIT_PARAM(tsunami, "Tsunami"),
+    INIT_PARAM_DFLT(time, "System time to use "
+            "(0 for actual time, default is 1/1/06", ULL(1136073600)),
     INIT_PARAM(mmu, "Memory Controller"),
     INIT_PARAM(addr, "Device Address"),
     INIT_PARAM(mask, "Address Mask")
@@ -258,7 +310,7 @@ END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
 
 CREATE_SIM_OBJECT(TsunamiIO)
 {
-    return new TsunamiIO(getInstanceName(), /*tsunami,*/ addr, mask, mmu);
+    return new TsunamiIO(getInstanceName(), /*tsunami,*/ time,  addr, mask, mmu);
 }
 
 REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
index 4e342523f36a699e0f362bc7614372137acf9edb..fe904605c6c5d0f495d102f5f310270814d12933 100644 (file)
 class TsunamiIO : public MmapDevice
 {
 
-  public:
+  private:
+    struct tm tm;
+
+    // In Tsunami RTC only has two i/o ports
+    // one  for data and one for address, so you
+    // write the address and then read/write the data
+    uint8_t RTCAddress;
 
   protected:
 
@@ -66,33 +72,43 @@ class TsunamiIO : public MmapDevice
 
     class RTCEvent : public Event
     {
-      protected:
-        Tick interval;
-        uint8_t rtc_uip;
-
       public:
         RTCEvent();
 
         virtual void process();
         virtual const char *description();
-        uint8_t rtc_uip_value();
     };
 
+      uint8_t uip;
+
       uint8_t mask1;
       uint8_t mask2;
       uint8_t mode1;
       uint8_t mode2;
 
+      /* This timer is initilized, but after I wrote the code
+         it doesn't seem to be used again, and best I can tell
+         it too is not connected to any interrupt port */
       ClockEvent timer0;
-      ClockEvent timer1;
+
+      /* This timer is used to control the speaker, which
+         we normally could care less about, however it is
+         also used to calculated the clockspeed and hense
+         bogomips which is kinda important to the scheduler
+         so we need to implemnt it although after boot I can't
+         imagine we would be playing with the PC speaker much */
       ClockEvent timer2;
 
+      RTCEvent rtc;
+
       uint32_t timerData;
 
   public:
-    TsunamiIO(const std::string &name, /*Tsunami *t,*/
+    TsunamiIO(const std::string &name, /*Tsunami *t,*/ time_t init_time,
                Addr addr, Addr mask, MemoryController *mmu);
 
+    void set_time(time_t t);
+
     virtual Fault read(MemReqPtr req, uint8_t *data);
     virtual Fault write(MemReqPtr req, const uint8_t *data);
 
diff --git a/dev/tsunami_uart.cc b/dev/tsunami_uart.cc
new file mode 100644 (file)
index 0000000..88f6a6f
--- /dev/null
@@ -0,0 +1,199 @@
+/* $Id$ */
+
+/* @file
+ * Tsunami UART
+ */
+
+/*
+ * Copyright (C) 1998 by the Board of Trustees
+ *    of Leland Stanford Junior University.
+ * Copyright (C) 1998 Digital Equipment Corporation
+ *
+ * This file is part of the SimOS distribution.
+ * See LICENSE file for terms of the license.
+ *
+ */
+
+#include <string>
+#include <vector>
+
+#include "base/inifile.hh"
+#include "base/str.hh" // for to_number
+#include "base/trace.hh"
+#include "dev/console.hh"
+#include "dev/tsunami_uart.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "sim/builder.hh"
+#include "targetarch/ev5.hh"
+
+using namespace std;
+
+#define CONS_INT_TX   0x01  // interrupt enable / state bits
+#define CONS_INT_RX   0x02
+
+TsunamiUart::TsunamiUart(const string &name, SimConsole *c,
+                       Addr addr, Addr mask, MemoryController *mmu)
+    : MmapDevice(name, addr, mask, mmu),
+      cons(c), status_store(0), next_char(-1)
+{
+}
+
+Fault
+TsunamiUart::read(MemReqPtr req, uint8_t *data)
+{
+    Addr daddr = req->paddr & addr_mask;
+
+    switch (req->size) {
+      case sizeof(uint64_t):
+        *(uint64_t *)data = 0;
+        break;
+      case sizeof(uint32_t):
+        *(uint32_t *)data = 0;
+        break;
+      case sizeof(uint16_t):
+        *(uint16_t *)data = 0;
+        break;
+      case sizeof(uint8_t):
+        *(uint8_t *)data = 0;
+        break;
+    }
+
+    switch (daddr) {
+      case 0xD: // Status Register
+        {
+            int status = cons->intStatus();
+            if (next_char < 0) {
+                next_char = cons->in();
+                if (next_char < 0) {
+                    status &= ~CONS_INT_RX;
+                }
+            } else {
+                status |= CONS_INT_RX;
+            }
+
+            if (status_store == 3) {
+                // RR3 stuff? Don't really understand it, btw
+                status_store = 0;
+                if (status & CONS_INT_TX) {
+                    *data = (1 << 4);
+                    return No_Fault;
+                } else if (status & CONS_INT_RX) {
+                    *data = (1 << 5);
+                    return No_Fault;
+                } else {
+                    DPRINTF(TsunamiUart, "spurious read\n");
+                    return No_Fault;
+                }
+            } else {
+                int reg = (1 << 2);
+                if (status & CONS_INT_RX)
+                    reg |= (1 << 0);
+                *data = reg;
+                return No_Fault;
+            }
+            break;
+        }
+
+      case 0x8: // Data register (RX)
+        if (next_char < 0)
+            panic("Invalid character");
+
+        DPRINTF(TsunamiUart, "read data register \'%c\' %#02x\n",
+                isprint(next_char) ? next_char : ' ', next_char);
+
+        *data = next_char;
+        next_char = -1;
+//    cons.next();
+        return No_Fault;
+    }
+
+    panic("%s: read daddr=%#x type=read *data=%#x\n", name(), daddr, *data);
+
+    return No_Fault;
+}
+
+Fault
+TsunamiUart::write(MemReqPtr req, const uint8_t *data)
+{
+    Addr daddr = req->paddr & addr_mask;
+    switch (daddr) {
+      case 0xb:
+        status_store = *data;
+        switch (*data) {
+          case 0x03: // going to read RR3
+            return No_Fault;
+
+          case 0x28: // Ack of TX
+            {
+                if ((cons->intStatus() & CONS_INT_TX) == 0)
+                    panic("Ack of transmit, though there was no interrupt");
+
+                cons->clearInt(CONS_INT_TX);
+                return No_Fault;
+            }
+
+          case 0x00:
+          case 0x01:
+          case 0x12:
+            // going to write data???
+            return No_Fault;
+
+          default:
+            DPRINTF(TsunamiUart, "writing status register %#x \n",
+                    *(uint64_t *)data);
+            return No_Fault;
+        }
+
+      case 0x8: // Data register (TX)
+        cons->out(*(uint64_t *)data);
+        return No_Fault;
+      case 0x9: // DLM
+        DPRINTF(TsunamiUart, "writing to DLM/IER %#x\n", *(uint64_t*)data);
+        return No_Fault;
+      case 0xc: // MCR
+        DPRINTF(TsunamiUart, "writing to MCR %#x\n", *(uint64_t*)data);
+        return No_Fault;
+
+    }
+
+    return No_Fault;
+}
+
+void
+TsunamiUart::serialize(ostream &os)
+{
+    SERIALIZE_SCALAR(status_store);
+    SERIALIZE_SCALAR(next_char);
+}
+
+void
+TsunamiUart::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(status_store);
+    UNSERIALIZE_SCALAR(next_char);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
+
+    SimObjectParam<SimConsole *> console;
+    SimObjectParam<MemoryController *> mmu;
+    Param<Addr> addr;
+    Param<Addr> mask;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiUart)
+
+    INIT_PARAM(console, "The console"),
+    INIT_PARAM(mmu, "Memory Controller"),
+    INIT_PARAM(addr, "Device Address"),
+    INIT_PARAM(mask, "Address Mask")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiUart)
+
+CREATE_SIM_OBJECT(TsunamiUart)
+{
+    return new TsunamiUart(getInstanceName(), console, addr, mask, mmu);
+}
+
+REGISTER_SIM_OBJECT("TsunamiUart", TsunamiUart)
diff --git a/dev/tsunami_uart.hh b/dev/tsunami_uart.hh
new file mode 100644 (file)
index 0000000..a1bd700
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/* @file
+ * Tsunami UART
+ */
+
+#ifndef __TSUNAMI_UART_HH__
+#define __TSUNAMI_UART_HH__
+
+#include "mem/functional_mem/mmap_device.hh"
+
+class SimConsole;
+
+/*
+ * Tsunami UART
+ */
+class TsunamiUart : public MmapDevice
+{
+  protected:
+    SimConsole *cons;
+    int status_store;
+    int next_char;
+
+  public:
+    TsunamiUart(const std::string &name, SimConsole *c,
+               Addr addr, Addr mask, MemoryController *mmu);
+
+    Fault read(MemReqPtr req, uint8_t *data);
+    Fault write(MemReqPtr req, const uint8_t *data);
+
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_UART_HH__
index f178974b9749f9fb42b93614076217960a62f2d1..7201edf9442bbc62d4d14477f3a16df5555f1160 100644 (file)
 #define TSDEV_TMR2_CTL      0x43
 #define TSDEV_TMR2_DATA     0x42
 #define TSDEV_TMR0_DATA     0x40
+
+#define TSDEV_RTC_ADDR      0x70
+#define TSDEV_RTC_DATA      0x71
+
+// RTC defines
+#define RTC_SECOND          0  // second of minute [0..59]
+#define RTC_SECOND_ALARM    1  // seconds to alarm
+#define RTC_MINUTE          2  // minute of hour [0..59]
+#define RTC_MINUTE_ALARM    3  // minutes to alarm
+#define RTC_HOUR            4  // hour of day [0..23]
+#define RTC_HOUR_ALARM      5  // hours to alarm
+#define RTC_DAY_OF_WEEK     6  // day of week [1..7]
+#define RTC_DAY_OF_MONTH    7  // day of month [1..31]
+#define RTC_MONTH           8  // month of year [1..12]
+#define RTC_YEAR            9  // year [00..99]
+#define RTC_CONTROL_REGISTERA   10     // control register A
+#define RTC_CONTROL_REGISTERB   11     // control register B
+#define RTC_CONTROL_REGISTERC   12     // control register C
+#define RTC_CONTROL_REGISTERD   13     // control register D
+#define RTC_REGNUMBER_RTC_CR1   0x6A   // control register 1
+
+
 #endif // __TSUNAMIREG_H__
index fe655ad74289f382e11ae7e91fa7b9f885bd8c26..db67c56195e568135f98a3473976cc612da81b99 100644 (file)
@@ -265,13 +265,13 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
 #endif //FS_MEASURE
 
     Addr addr = 0;
-    if (kernelSymtab->findAddress("enable_async_printf", addr)) {
+    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
         Addr paddr = vtophys(physmem, addr);
-        uint8_t *enable_async_printf =
-            physmem->dma_addr(paddr, sizeof(uint32_t));
+        uint8_t *est_cycle_frequency =
+            physmem->dma_addr(paddr, sizeof(uint64_t));
 
-        if (enable_async_printf)
-            *(uint32_t *)enable_async_printf = 0;
+        if (est_cycle_frequency)
+            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
     }
 
     if (consoleSymtab->findAddress("env_booted_osflags", addr)) {