summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2004-01-26 13:26:34 -0500
committerAli Saidi <saidi@eecs.umich.edu>2004-01-26 13:26:34 -0500
commitb7f44f6e0676a933c5aa4d892d789c46daeaaa27 (patch)
tree1e48e5b6614ec85f5ee9d3d2254f90814ae88e0b /dev
parent9b397ce7f45fc275f9004d78520628e2e7c0dd16 (diff)
downloadgem5-b7f44f6e0676a933c5aa4d892d789c46daeaaa27.tar.xz
Support for Tsunami coming along... RTC, PIC working, UART in progress
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
Diffstat (limited to 'dev')
-rw-r--r--dev/tsunami_io.cc110
-rw-r--r--dev/tsunami_io.hh32
-rw-r--r--dev/tsunami_uart.cc199
-rw-r--r--dev/tsunami_uart.hh62
-rw-r--r--dev/tsunamireg.h22
5 files changed, 388 insertions, 37 deletions
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 537e40a22..b6533dcba 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -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>
@@ -11,50 +13,43 @@
#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)
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index 4e342523f..fe904605c 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -42,7 +42,13 @@
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
index 000000000..88f6a6f8a
--- /dev/null
+++ b/dev/tsunami_uart.cc
@@ -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
index 000000000..a1bd7006d
--- /dev/null
+++ b/dev/tsunami_uart.hh
@@ -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__
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index f178974b9..7201edf94 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -78,4 +78,26 @@
#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__