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
This commit is contained in:
Ali Saidi 2004-01-26 13:26:34 -05:00
parent 9b397ce7f4
commit b7f44f6e06
6 changed files with 393 additions and 42 deletions

View 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>
@ -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)

View file

@ -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);

199
dev/tsunami_uart.cc Normal file
View file

@ -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)

62
dev/tsunami_uart.hh Normal file
View file

@ -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__

View file

@ -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__

View 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)) {