summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/alpha_console.cc19
-rw-r--r--dev/alpha_console.hh7
-rw-r--r--dev/baddev.cc56
-rw-r--r--dev/baddev.hh43
-rw-r--r--dev/console.cc33
-rw-r--r--dev/console.hh28
-rw-r--r--dev/disk_image.cc2
-rw-r--r--dev/disk_image.hh2
-rw-r--r--dev/etherbus.cc2
-rw-r--r--dev/etherbus.hh2
-rw-r--r--dev/etherdump.cc2
-rw-r--r--dev/etherdump.hh2
-rw-r--r--dev/etherint.cc2
-rw-r--r--dev/etherint.hh2
-rw-r--r--dev/etherlink.cc2
-rw-r--r--dev/etherlink.hh2
-rw-r--r--dev/etherpkt.hh88
-rw-r--r--dev/ethertap.cc2
-rw-r--r--dev/ethertap.hh2
-rw-r--r--dev/ide_ctrl.cc80
-rw-r--r--dev/ide_ctrl.hh18
-rw-r--r--dev/ide_disk.cc266
-rw-r--r--dev/ide_disk.hh43
-rw-r--r--dev/io_device.cc2
-rw-r--r--dev/io_device.hh2
-rw-r--r--dev/ns_gige.cc481
-rw-r--r--dev/ns_gige.hh88
-rw-r--r--dev/ns_gige_reg.h2
-rw-r--r--dev/pciconfigall.cc45
-rw-r--r--dev/pciconfigall.hh79
-rw-r--r--dev/pcidev.cc21
-rw-r--r--dev/pcidev.hh76
-rw-r--r--dev/pcireg.h7
-rw-r--r--dev/platform.cc2
-rw-r--r--dev/platform.hh3
-rw-r--r--dev/simple_disk.cc2
-rw-r--r--dev/simple_disk.hh2
-rw-r--r--dev/tsunami.cc8
-rw-r--r--dev/tsunami.hh29
-rw-r--r--dev/tsunami_cchip.cc70
-rw-r--r--dev/tsunami_cchip.hh83
-rw-r--r--dev/tsunami_io.cc116
-rw-r--r--dev/tsunami_io.hh192
-rw-r--r--dev/tsunami_pchip.cc113
-rw-r--r--dev/tsunami_pchip.hh72
-rw-r--r--dev/tsunami_uart.cc93
-rw-r--r--dev/tsunami_uart.hh22
-rw-r--r--dev/tsunamireg.h40
48 files changed, 1653 insertions, 702 deletions
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index e9780b2d0..f8870496f 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@
using namespace std;
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
- System *system, BaseCPU *cpu, SimObject *clock,
+ System *system, BaseCPU *cpu, Platform *platform,
int num_cpus, MemoryController *mmu, Addr a,
HierParams *hier, Bus *bus)
: PioDevice(name), disk(d), console(cons), addr(a)
@@ -78,14 +78,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
alphaAccess->numCPUs = num_cpus;
alphaAccess->mem_size = system->physmem->size();
alphaAccess->cpuClock = cpu->getFreq() / 1000000;
- TsunamiIO *clock_linux = dynamic_cast<TsunamiIO *>(clock);
- TlaserClock *clock_tru64 = dynamic_cast<TlaserClock *>(clock);
- if (clock_linux)
- alphaAccess->intrClockFrequency = clock_linux->frequency();
- else if (clock_tru64)
- alphaAccess->intrClockFrequency = clock_tru64->frequency();
- else
- panic("clock must be of type TlaserClock or TsunamiIO\n");
+ alphaAccess->intrClockFrequency = platform->intrFrequency();
alphaAccess->diskUnit = 1;
}
@@ -321,7 +314,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
Param<Addr> addr;
SimObjectParam<System *> system;
SimObjectParam<BaseCPU *> cpu;
- SimObjectParam<SimObject *> clock;
+ SimObjectParam<Platform *> platform;
SimObjectParam<Bus*> io_bus;
SimObjectParam<HierParams *> hier;
@@ -336,7 +329,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(addr, "Device Address"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu, "Processor"),
- INIT_PARAM(clock, "Clock"),
+ INIT_PARAM(platform, "platform"),
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
@@ -345,7 +338,7 @@ END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
CREATE_SIM_OBJECT(AlphaConsole)
{
return new AlphaConsole(getInstanceName(), sim_console, disk,
- system, cpu, clock, num_cpus, mmu,
+ system, cpu, platform, num_cpus, mmu,
addr, hier, io_bus);
}
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index a5cc51c5e..47afa8f4a 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,13 +37,12 @@
#include "dev/alpha_access.h"
#include "dev/io_device.hh"
#include "sim/host.hh"
-#include "dev/tsunami_io.hh"
#include "sim/sim_object.hh"
class BaseCPU;
class SimConsole;
class System;
-class TlaserClock;
+class Platform;
class SimpleDisk;
/*
@@ -88,7 +87,7 @@ class AlphaConsole : public PioDevice
public:
/** Standard Constructor */
AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d,
- System *system, BaseCPU *cpu, SimObject *clock,
+ System *system, BaseCPU *cpu, Platform *platform,
int num_cpus, MemoryController *mmu, Addr addr,
HierParams *hier, Bus *bus);
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 8a5d68533..8b552e989 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -1,4 +1,30 @@
-/* $Id$ */
+/*
+ * Copyright (c) 2004 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
* BadDevice implemenation
@@ -10,10 +36,10 @@
#include "base/trace.hh"
#include "cpu/exec_context.hh"
-#include "dev/scsi_ctrl.hh"
#include "dev/baddev.hh"
-#include "dev/tsunamireg.h"
-#include "dev/tsunami.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
@@ -21,10 +47,17 @@
using namespace std;
BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
- const string &devicename)
- : FunctionalMemory(name), addr(a), devname(devicename)
+ HierParams *hier, Bus *bus, const string &devicename)
+ : PioDevice(name), addr(a), devname(devicename)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
+
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &BadDevice::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
}
Fault
@@ -42,11 +75,18 @@ BadDevice::write(MemReqPtr &req, const uint8_t *data)
return No_Fault;
}
+Tick
+BadDevice::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
+ SimObjectParam<HierParams *> hier;
+ SimObjectParam<Bus*> io_bus;
Param<string> devicename;
END_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
@@ -55,13 +95,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice)
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
INIT_PARAM(devicename, "Name of device to error on")
END_INIT_SIM_OBJECT_PARAMS(BadDevice)
CREATE_SIM_OBJECT(BadDevice)
{
- return new BadDevice(getInstanceName(), addr, mmu, devicename);
+ return new BadDevice(getInstanceName(), addr, mmu, hier, io_bus, devicename);
}
REGISTER_SIM_OBJECT("BadDevice", BadDevice)
diff --git a/dev/baddev.hh b/dev/baddev.hh
index ed896d792..8680f6b0a 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,8 @@
#ifndef __BADDEV_HH__
#define __BADDEV_HH__
-#include "mem/functional_mem/functional_memory.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
/**
* BadDevice
@@ -42,7 +43,7 @@
* the user that the kernel they are running has unsupported
* options (i.e. frame buffer)
*/
-class BadDevice : public FunctionalMemory
+class BadDevice : public PioDevice
{
private:
Addr addr;
@@ -51,14 +52,42 @@ class BadDevice : public FunctionalMemory
std::string devname;
public:
- /**
- * The default constructor.
- */
+ /**
+ * Constructor for the Baddev Class.
+ * @param name name of the object
+ * @param a base address of the write
+ * @param mmu the memory controller
+ * @param hier object to store parameters universal the device hierarchy
+ * @param bus The bus that this device is attached to
+ * @param devicename device that is not implemented
+ */
BadDevice(const std::string &name, Addr a, MemoryController *mmu,
- const std::string &devicename);
+ HierParams *hier, Bus *bus, const std::string &devicename);
+ /**
+ * On a read event we just panic aand hopefully print a
+ * meaningful error message.
+ * @param req Contains the address to read from.
+ * @param data A pointer to write the read data to.
+ * @return The fault condition of the access.
+ */
virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+ /**
+ * On a write event we just panic aand hopefully print a
+ * meaningful error message.
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
virtual Fault write(MemReqPtr &req, const uint8_t *data);
+
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __BADDEV_HH__
diff --git a/dev/console.cc b/dev/console.cc
index ef3f64d8d..b9bcbb3d1 100644
--- a/dev/console.cc
+++ b/dev/console.cc
@@ -1,30 +1,5 @@
-/*
- * 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.
- */
+/* $Id$ */
+
/* @file
* User Console Definitions
@@ -377,11 +352,15 @@ SimConsole::setPlatform(Platform *p)
void
SimConsole::serialize(ostream &os)
{
+ SERIALIZE_SCALAR(_status);
+ SERIALIZE_SCALAR(_enable);
}
void
SimConsole::unserialize(Checkpoint *cp, const std::string &section)
{
+ UNSERIALIZE_SCALAR(_status);
+ UNSERIALIZE_SCALAR(_enable);
}
diff --git a/dev/console.hh b/dev/console.hh
index 703d05d51..87be9ccbc 100644
--- a/dev/console.hh
+++ b/dev/console.hh
@@ -1,30 +1,4 @@
-/*
- * 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.
- */
+/* $Id$ */
/* @file
* User Console Interface
diff --git a/dev/disk_image.cc b/dev/disk_image.cc
index 4df196e64..d990d7078 100644
--- a/dev/disk_image.cc
+++ b/dev/disk_image.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/disk_image.hh b/dev/disk_image.hh
index 7b2c12ef7..b21978058 100644
--- a/dev/disk_image.hh
+++ b/dev/disk_image.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2003 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherbus.cc b/dev/etherbus.cc
index 76697dd3e..82722383c 100644
--- a/dev/etherbus.cc
+++ b/dev/etherbus.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherbus.hh b/dev/etherbus.hh
index 9ef477808..716636c79 100644
--- a/dev/etherbus.hh
+++ b/dev/etherbus.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index b6d6bbe30..54e573be4 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index e22b66166..ef4399e1a 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherint.cc b/dev/etherint.cc
index cfffb3a87..c78848674 100644
--- a/dev/etherint.cc
+++ b/dev/etherint.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2003 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherint.hh b/dev/etherint.hh
index 70e29eb7c..ddfe16d88 100644
--- a/dev/etherint.hh
+++ b/dev/etherint.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index 25991f1a7..3cc4f75ea 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index 3b1dd21bc..4f227fac5 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index 09516c427..76b4a9156 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,70 +35,13 @@
#include <iosfwd>
#include <memory>
+#include <assert.h>
#include "sim/host.hh"
#include "base/refcnt.hh"
-
-#define EADDR_LEN 6
+#include "base/inet_hdrs.hh"
class Checkpoint;
-
-struct pseudo_header
-{
- uint32_t src_ip_addr;
- uint32_t dest_ip_addr;
- uint16_t protocol;
- uint16_t len;
-};
-
-/** Ethernet header struct for casting purposes */
-struct eth_header
-{
- uint8_t dest[EADDR_LEN];
- uint8_t src[EADDR_LEN];
- uint16_t type;
-};
-
-struct ip_header
-{
- uint8_t vers_len;
- uint8_t service_type;
- uint16_t dgram_len;
- uint16_t ID;
- uint16_t flags_frag_offset;
- uint8_t TTL;
- uint8_t protocol;
- uint16_t hdr_chksum;
- uint32_t src_ip_addr;
- uint32_t dest_ip_addr;
- uint8_t *options;
- uint8_t *transport_header;
-};
-
-struct tcp_header
-{
- uint16_t src_port_num;
- uint16_t dest_port_num;
- uint32_t seq_num;
- uint32_t ack_num;
- uint8_t hdr_len;
- uint8_t flags;
- uint16_t rcv_window;
- uint16_t chksum;
- uint16_t urgent;
- uint8_t *options;
- uint8_t *data;
-};
-
-struct udp_header
-{
- uint16_t src_port_num;
- uint16_t dest_port_num;
- uint16_t len;
- uint16_t chksum;
- uint8_t *data;
-};
-
/*
* Reference counted class containing ethernet packet data
*/
@@ -119,14 +62,31 @@ class EtherPacket : public RefCounted
bool IsMulticast() { return data[0] == 0x01; }
bool IsBroadcast() { return data[0] == 0xff; }
- ip_header *getIpHdr() { return (ip_header *) (data + 14); }
-
- void *getTransportHdr() {
+ bool isIpPkt() {
+ eth_header *eth = (eth_header *) data;
+ return (eth->type == 0x800);
+ }
+ bool isTcpPkt() {
ip_header *ip = getIpHdr();
- return (void *) (ip + (ip->vers_len & 0xf));
+ return (ip->protocol == 6);
+ }
+ bool isUdpPkt() {
+ ip_header *ip = getIpHdr();
+ return (ip->protocol == 17);
+ }
+
+ ip_header *getIpHdr() {
+ assert(isIpPkt());
+ return (ip_header *) (data + sizeof(eth_header));
}
+ tcp_header *getTcpHdr(ip_header *ip) {
+ return (tcp_header *) (ip + (ip->vers_len & 0xf));
+ }
+ udp_header *getUdpHdr(ip_header *ip) {
+ return (udp_header *) (ip + (ip->vers_len & 0xf));
+ }
typedef RefCountingPtr<EtherPacket> PacketPtr;
void serialize(std::ostream &os);
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 297053e1e..edc400760 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index 0b853a11d..1fe368085 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index f78a8e1ef..46a0e8179 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -255,7 +255,10 @@ IdeController::cacheAccess(MemReqPtr &req)
void
IdeController::ReadConfig(int offset, int size, uint8_t *data)
{
+
+#if TRACING_ON
Addr origOffset = offset;
+#endif
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::ReadConfig(offset, size, data);
@@ -338,63 +341,74 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
memcpy((void *)&pci_regs[offset], (void *)&data, size);
}
- if (offset == PCI_COMMAND) {
- if (config.data[offset] & IOSE)
+ // Catch the writes to specific PCI registers that have side affects
+ // (like updating the PIO ranges)
+ switch (offset) {
+ case PCI_COMMAND:
+ if (config.data[offset] & PCI_CMD_IOSE)
io_enabled = true;
else
io_enabled = false;
- if (config.data[offset] & BME)
+ if (config.data[offset] & PCI_CMD_BME)
bm_enabled = true;
else
bm_enabled = false;
+ break;
- } else if (data != 0xffffffff) {
- switch (offset) {
- case PCI0_BASE_ADDR0:
+ case PCI0_BASE_ADDR0:
+ if (BARAddrs[0] != 0) {
pri_cmd_addr = BARAddrs[0];
if (pioInterface)
pioInterface->addAddrRange(pri_cmd_addr,
pri_cmd_addr + pri_cmd_size - 1);
- pri_cmd_addr = pri_cmd_addr & PA_UNCACHED_MASK;
- break;
+ pri_cmd_addr &= PA_UNCACHED_MASK;
+ }
+ break;
- case PCI0_BASE_ADDR1:
+ case PCI0_BASE_ADDR1:
+ if (BARAddrs[1] != 0) {
pri_ctrl_addr = BARAddrs[1];
if (pioInterface)
pioInterface->addAddrRange(pri_ctrl_addr,
pri_ctrl_addr + pri_ctrl_size - 1);
- pri_ctrl_addr = pri_ctrl_addr & PA_UNCACHED_MASK;
- break;
+ pri_ctrl_addr &= PA_UNCACHED_MASK;
+ }
+ break;
- case PCI0_BASE_ADDR2:
+ case PCI0_BASE_ADDR2:
+ if (BARAddrs[2] != 0) {
sec_cmd_addr = BARAddrs[2];
if (pioInterface)
pioInterface->addAddrRange(sec_cmd_addr,
sec_cmd_addr + sec_cmd_size - 1);
- sec_cmd_addr = sec_cmd_addr & PA_UNCACHED_MASK;
- break;
+ sec_cmd_addr &= PA_UNCACHED_MASK;
+ }
+ break;
- case PCI0_BASE_ADDR3:
+ case PCI0_BASE_ADDR3:
+ if (BARAddrs[3] != 0) {
sec_ctrl_addr = BARAddrs[3];
if (pioInterface)
pioInterface->addAddrRange(sec_ctrl_addr,
sec_ctrl_addr + sec_ctrl_size - 1);
- sec_ctrl_addr = sec_ctrl_addr & PA_UNCACHED_MASK;
- break;
+ sec_ctrl_addr &= PA_UNCACHED_MASK;
+ }
+ break;
- case PCI0_BASE_ADDR4:
+ case PCI0_BASE_ADDR4:
+ if (BARAddrs[4] != 0) {
bmi_addr = BARAddrs[4];
if (pioInterface)
pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
- bmi_addr = bmi_addr & PA_UNCACHED_MASK;
- break;
+ bmi_addr &= PA_UNCACHED_MASK;
}
+ break;
}
}
@@ -589,6 +603,9 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
void
IdeController::serialize(std::ostream &os)
{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
// Serialize register addresses and sizes
SERIALIZE_SCALAR(pri_cmd_addr);
SERIALIZE_SCALAR(pri_cmd_size);
@@ -615,6 +632,9 @@ IdeController::serialize(std::ostream &os)
void
IdeController::unserialize(Checkpoint *cp, const std::string &section)
{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
// Unserialize register addresses and sizes
UNSERIALIZE_SCALAR(pri_cmd_addr);
UNSERIALIZE_SCALAR(pri_cmd_size);
@@ -636,6 +656,18 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(io_enabled);
UNSERIALIZE_SCALAR(bm_enabled);
UNSERIALIZE_ARRAY(cmd_in_progress, 4);
+
+ if (pioInterface) {
+ pioInterface->addAddrRange(pri_cmd_addr, pri_cmd_addr +
+ pri_cmd_size - 1);
+ pioInterface->addAddrRange(pri_ctrl_addr, pri_ctrl_addr +
+ pri_ctrl_size - 1);
+ pioInterface->addAddrRange(sec_cmd_addr, sec_cmd_addr +
+ sec_cmd_size - 1);
+ pioInterface->addAddrRange(sec_ctrl_addr, sec_ctrl_addr +
+ sec_ctrl_size - 1);
+ pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
+ }
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -651,7 +683,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
- SimObjectParam<Bus *> host_bus;
+ SimObjectParam<Bus *> io_bus;
SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
@@ -667,7 +699,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
- INIT_PARAM_DFLT(host_bus, "Host bus to attach to", NULL),
+ INIT_PARAM_DFLT(io_bus, "Host bus to attach to", NULL),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(IdeController)
@@ -676,7 +708,7 @@ CREATE_SIM_OBJECT(IdeController)
{
return new IdeController(getInstanceName(), intr_ctrl, disks, mmu,
configspace, configdata, tsunami, pci_bus,
- pci_dev, pci_func, host_bus, hier);
+ pci_dev, pci_func, io_bus, hier);
}
REGISTER_SIM_OBJECT("IdeController", IdeController)
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index 9698724c1..679c7422b 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,10 +74,6 @@
#define UDMACTL (5)
#define UDMATIM (6)
-// PCI Command bit fields
-#define BME 0x04 // Bus master function enable
-#define IOSE 0x01 // I/O space enable
-
typedef enum RegType {
COMMAND_BLOCK = 0,
CONTROL_BLOCK,
@@ -199,12 +195,6 @@ class IdeController : public PciDev
virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
- * Cache access timing specific to device
- * @param req Memory request
- */
- Tick cacheAccess(MemReqPtr &req);
-
- /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
@@ -217,5 +207,11 @@ class IdeController : public PciDev
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __IDE_CTRL_HH_
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 0d12e797d..0f5c02660 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,25 +61,12 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this)
{
+ // Reset the device state
+ reset(id);
+
// calculate disk delay in microseconds
diskDelay = (delay * ticksPerSecond / 100000);
- // initialize the data buffer and shadow registers
- dataBuffer = new uint8_t[MAX_DMA_SIZE];
-
- memset(dataBuffer, 0, MAX_DMA_SIZE);
- memset(&cmdReg, 0, sizeof(CommandReg_t));
- memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
-
- dmaInterfaceBytes = 0;
- curPrdAddr = 0;
- curSector = 0;
- curCommand = 0;
- cmdBytesLeft = 0;
- drqBytesLeft = 0;
- dmaRead = false;
- intrPending = false;
-
// fill out the drive ID structure
memset(&driveID, 0, sizeof(struct hd_driveid));
@@ -132,6 +119,32 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
driveID.dma_ultra = 0x10;
// Statically set hardware config word
driveID.hw_config = 0x4001;
+}
+
+IdeDisk::~IdeDisk()
+{
+ // destroy the data buffer
+ delete [] dataBuffer;
+}
+
+void
+IdeDisk::reset(int id)
+{
+ // initialize the data buffer and shadow registers
+ dataBuffer = new uint8_t[MAX_DMA_SIZE];
+
+ memset(dataBuffer, 0, MAX_DMA_SIZE);
+ memset(&cmdReg, 0, sizeof(CommandReg_t));
+ memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+
+ dmaInterfaceBytes = 0;
+ curPrdAddr = 0;
+ curSector = 0;
+ cmdBytes = 0;
+ cmdBytesLeft = 0;
+ drqBytesLeft = 0;
+ dmaRead = false;
+ intrPending = false;
// set the device state to idle
dmaState = Dma_Idle;
@@ -147,13 +160,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
}
// set the device ready bit
- cmdReg.status |= STATUS_DRDY_BIT;
-}
-
-IdeDisk::~IdeDisk()
-{
- // destroy the data buffer
- delete [] dataBuffer;
+ status = STATUS_DRDY_BIT;
}
////
@@ -216,6 +223,7 @@ IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
// determine if an action needs to be taken on the state machine
if (offset == STATUS_OFFSET) {
action = ACT_STAT_READ;
+ *data = status; // status is in a shadow, explicity copy
} else if (offset == DATA_OFFSET) {
if (byte)
action = ACT_DATA_READ_BYTE;
@@ -230,7 +238,7 @@ IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
if (!byte)
panic("Invalid 16-bit read from control block\n");
- *data = ((uint8_t *)&cmdReg)[STATUS_OFFSET];
+ *data = status;
}
if (action != ACT_NONE)
@@ -262,6 +270,8 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
action = ACT_DATA_WRITE_BYTE;
else
action = ACT_DATA_WRITE_SHORT;
+ } else if (offset == SELECT_OFFSET) {
+ action = ACT_SELECT_WRITE;
}
} else {
@@ -271,8 +281,13 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
if (!byte)
panic("Invalid 16-bit write to control block\n");
- if (*data & CONTROL_RST_BIT)
- panic("Software reset not supported!\n");
+ if (*data & CONTROL_RST_BIT) {
+ // force the device into the reset state
+ devState = Device_Srst;
+ action = ACT_SRST_SET;
+ } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) {
+ action = ACT_SRST_CLEAR;
+ }
nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
}
@@ -315,7 +330,13 @@ IdeDisk::dmaPrdReadDone()
physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
sizeof(PrdEntry_t));
- curPrdAddr += sizeof(PrdEntry_t);
+ DPRINTF(IdeDisk, "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
+ curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
+ curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
+ curPrd.getEOT(), curSector);
+
+ // make sure the new curPrdAddr is properly translated from PCI to system
+ curPrdAddr = pciToDma(curPrdAddr + sizeof(PrdEntry_t));
if (dmaRead)
doDmaRead();
@@ -414,29 +435,8 @@ IdeDisk::dmaReadDone()
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
}
-#if 0
- // actually copy the data from memory to data buffer
- Addr dmaAddr =
- ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr());
- memcpy((void *)dataBuffer,
- physmem->dma_addr(dmaAddr, curPrd.getByteCount()),
- curPrd.getByteCount());
-
- uint32_t bytesWritten = 0;
-
- while (bytesWritten < curPrd.getByteCount()) {
- if (cmdBytesLeft <= 0)
- panic("DMA data is larger than # sectors specified\n");
-
- writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
-
- bytesWritten += SectorSize;
- cmdBytesLeft -= SectorSize;
- }
-#endif
-
// check for the EOT
- if (curPrd.getEOT()){
+ if (curPrd.getEOT()) {
assert(cmdBytesLeft == 0);
dmaState = Dma_Idle;
updateState(ACT_DMA_DONE);
@@ -543,14 +543,6 @@ IdeDisk::dmaWriteDone()
bytesInPage);
}
-#if 0
- Addr dmaAddr = ctrl->tsunami->pchip->
- translatePciToDma(curPrd.getBaseAddr());
-
- memcpy(physmem->dma_addr(dmaAddr, curPrd.getByteCount()),
- (void *)dataBuffer, curPrd.getByteCount());
-#endif
-
// check for the EOT
if (curPrd.getEOT()) {
assert(cmdBytesLeft == 0);
@@ -598,7 +590,8 @@ IdeDisk::startDma(const uint32_t &prdTableBase)
if (devState != Transfer_Data_Dma)
panic("Inconsistent device state for DMA start!\n");
- curPrdAddr = pciToDma((Addr)prdTableBase);
+ // PRD base address is given by bits 31:2
+ curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
dmaState = Dma_Transfer;
@@ -625,9 +618,6 @@ IdeDisk::startCommand()
uint32_t size = 0;
dmaRead = false;
- // copy the command to the shadow
- curCommand = cmdReg.command;
-
// Decode commands
switch (cmdReg.command) {
// Supported non-data commands
@@ -644,6 +634,7 @@ IdeDisk::startCommand()
case WIN_RECAL:
case WIN_SPECIFY:
+ case WIN_STANDBYNOW1:
case WIN_FLUSH_CACHE:
case WIN_VERIFY:
case WIN_SEEK:
@@ -655,7 +646,7 @@ IdeDisk::startCommand()
// Supported PIO data-in commands
case WIN_IDENTIFY:
- cmdBytesLeft = drqBytesLeft = sizeof(struct hd_driveid);
+ cmdBytes = cmdBytesLeft = sizeof(struct hd_driveid);
devState = Prepare_Data_In;
action = ACT_DATA_READY;
break;
@@ -666,13 +657,13 @@ IdeDisk::startCommand()
panic("Attempt to perform CHS access, only supports LBA\n");
if (cmdReg.sec_count == 0)
- cmdBytesLeft = (256 * SectorSize);
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
else
- cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
- drqBytesLeft = SectorSize;
curSector = getLBABase();
+ /** @todo make this a scheduled event to simulate disk delay */
devState = Prepare_Data_In;
action = ACT_DATA_READY;
break;
@@ -684,11 +675,10 @@ IdeDisk::startCommand()
panic("Attempt to perform CHS access, only supports LBA\n");
if (cmdReg.sec_count == 0)
- cmdBytesLeft = (256 * SectorSize);
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
else
- cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
- drqBytesLeft = SectorSize;
curSector = getLBABase();
devState = Prepare_Data_Out;
@@ -703,11 +693,10 @@ IdeDisk::startCommand()
panic("Attempt to perform CHS access, only supports LBA\n");
if (cmdReg.sec_count == 0)
- cmdBytesLeft = (256 * SectorSize);
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
else
- cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
- drqBytesLeft = SectorSize;
curSector = getLBABase();
devState = Prepare_Data_Dma;
@@ -720,9 +709,11 @@ IdeDisk::startCommand()
if (action != ACT_NONE) {
// set the BSY bit
- cmdReg.status |= STATUS_BSY_BIT;
+ status |= STATUS_BSY_BIT;
// clear the DRQ bit
- cmdReg.status &= ~STATUS_DRQ_BIT;
+ status &= ~STATUS_DRQ_BIT;
+ // clear the DF bit
+ status &= ~STATUS_DF_BIT;
updateState(action);
}
@@ -766,16 +757,30 @@ void
IdeDisk::updateState(DevAction_t action)
{
switch (devState) {
+ case Device_Srst:
+ if (action == ACT_SRST_SET) {
+ // set the BSY bit
+ status |= STATUS_BSY_BIT;
+ } else if (action == ACT_SRST_CLEAR) {
+ // clear the BSY bit
+ status &= ~STATUS_BSY_BIT;
+
+ // reset the device state
+ reset(devID);
+ }
+ break;
+
case Device_Idle_S:
- if (!isDEVSelect())
+ if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
devState = Device_Idle_NS;
- else if (action == ACT_CMD_WRITE)
+ } else if (action == ACT_CMD_WRITE) {
startCommand();
+ }
break;
case Device_Idle_SI:
- if (!isDEVSelect()) {
+ if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
devState = Device_Idle_NS;
intrClear();
} else if (action == ACT_STAT_READ || isIENSet()) {
@@ -789,7 +794,7 @@ IdeDisk::updateState(DevAction_t action)
break;
case Device_Idle_NS:
- if (isDEVSelect()) {
+ if (action == ACT_SELECT_WRITE && isDEVSelect()) {
if (!isIENSet() && intrPending) {
devState = Device_Idle_SI;
intrPost();
@@ -827,20 +832,27 @@ IdeDisk::updateState(DevAction_t action)
}
} else if (action == ACT_DATA_READY) {
// clear the BSY bit
- cmdReg.status &= ~STATUS_BSY_BIT;
+ status &= ~STATUS_BSY_BIT;
// set the DRQ bit
- cmdReg.status |= STATUS_DRQ_BIT;
-
- // put the first two bytes into the data register
- memcpy((void *)&cmdReg.data0, (void *)dataBuffer,
- sizeof(uint16_t));
+ status |= STATUS_DRQ_BIT;
// copy the data into the data buffer
- if (curCommand == WIN_IDENTIFY)
+ if (cmdReg.command == WIN_IDENTIFY) {
+ // Reset the drqBytes for this block
+ drqBytesLeft = sizeof(struct hd_driveid);
+
memcpy((void *)dataBuffer, (void *)&driveID,
sizeof(struct hd_driveid));
- else
+ } else {
+ // Reset the drqBytes for this block
+ drqBytesLeft = SectorSize;
+
readDisk(curSector++, dataBuffer);
+ }
+
+ // put the first two bytes into the data register
+ memcpy((void *)&cmdReg.data0, (void *)dataBuffer,
+ sizeof(uint16_t));
if (!isIENSet()) {
devState = Data_Ready_INTRQ_In;
@@ -867,9 +879,10 @@ IdeDisk::updateState(DevAction_t action)
cmdBytesLeft -= 2;
// copy next short into data registers
- memcpy((void *)&cmdReg.data0,
- (void *)&dataBuffer[SectorSize - drqBytesLeft],
- sizeof(uint16_t));
+ if (drqBytesLeft)
+ memcpy((void *)&cmdReg.data0,
+ (void *)&dataBuffer[SectorSize - drqBytesLeft],
+ sizeof(uint16_t));
}
if (drqBytesLeft == 0) {
@@ -879,7 +892,14 @@ IdeDisk::updateState(DevAction_t action)
devState = Device_Idle_S;
} else {
devState = Prepare_Data_In;
- cmdReg.status |= STATUS_BSY_BIT;
+ // set the BSY_BIT
+ status |= STATUS_BSY_BIT;
+ // clear the DRQ_BIT
+ status &= ~STATUS_DRQ_BIT;
+
+ /** @todo change this to a scheduled event to simulate
+ disk delay */
+ updateState(ACT_DATA_READY);
}
}
}
@@ -896,20 +916,23 @@ IdeDisk::updateState(DevAction_t action)
} else {
devState = Device_Idle_S;
}
- } else if (cmdBytesLeft != 0) {
+ } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
// clear the BSY bit
- cmdReg.status &= ~STATUS_BSY_BIT;
+ status &= ~STATUS_BSY_BIT;
// set the DRQ bit
- cmdReg.status |= STATUS_DRQ_BIT;
+ status |= STATUS_DRQ_BIT;
// clear the data buffer to get it ready for writes
memset(dataBuffer, 0, MAX_DMA_SIZE);
- if (!isIENSet()) {
+ // reset the drqBytes for this block
+ drqBytesLeft = SectorSize;
+
+ if (cmdBytesLeft == cmdBytes || isIENSet()) {
+ devState = Transfer_Data_Out;
+ } else {
devState = Data_Ready_INTRQ_Out;
intrPost();
- } else {
- devState = Transfer_Data_Out;
}
}
break;
@@ -942,11 +965,17 @@ IdeDisk::updateState(DevAction_t action)
writeDisk(curSector++, dataBuffer);
// set the BSY bit
- cmdReg.status |= STATUS_BSY_BIT;
+ status |= STATUS_BSY_BIT;
+ // set the seek bit
+ status |= STATUS_SEEK_BIT;
// clear the DRQ bit
- cmdReg.status &= ~STATUS_DRQ_BIT;
+ status &= ~STATUS_DRQ_BIT;
devState = Prepare_Data_Out;
+
+ /** @todo change this to a scheduled event to simulate
+ disk delay */
+ updateState(ACT_DATA_READY);
}
}
break;
@@ -964,9 +993,9 @@ IdeDisk::updateState(DevAction_t action)
}
} else if (action == ACT_DMA_READY) {
// clear the BSY bit
- cmdReg.status &= ~STATUS_BSY_BIT;
+ status &= ~STATUS_BSY_BIT;
// set the DRQ bit
- cmdReg.status |= STATUS_DRQ_BIT;
+ status |= STATUS_DRQ_BIT;
devState = Transfer_Data_Dma;
@@ -983,7 +1012,7 @@ IdeDisk::updateState(DevAction_t action)
// clear the BSY bit
setComplete();
// set the seek bit
- cmdReg.status |= 0x10;
+ status |= STATUS_SEEK_BIT;
// clear the controller state for DMA transfer
ctrl->setDmaComplete(this);
@@ -1009,26 +1038,41 @@ IdeDisk::serialize(ostream &os)
Tick reschedule = 0;
Events_t event = None;
+ int eventCount = 0;
+
if (dmaTransferEvent.scheduled()) {
reschedule = dmaTransferEvent.when();
event = Transfer;
- } else if (dmaReadWaitEvent.scheduled()) {
+ eventCount++;
+ }
+ if (dmaReadWaitEvent.scheduled()) {
reschedule = dmaReadWaitEvent.when();
event = ReadWait;
- } else if (dmaWriteWaitEvent.scheduled()) {
+ eventCount++;
+ }
+ if (dmaWriteWaitEvent.scheduled()) {
reschedule = dmaWriteWaitEvent.when();
event = WriteWait;
- } else if (dmaPrdReadEvent.scheduled()) {
+ eventCount++;
+ }
+ if (dmaPrdReadEvent.scheduled()) {
reschedule = dmaPrdReadEvent.when();
event = PrdRead;
- } else if (dmaReadEvent.scheduled()) {
+ eventCount++;
+ }
+ if (dmaReadEvent.scheduled()) {
reschedule = dmaReadEvent.when();
event = DmaRead;
- } else if (dmaWriteEvent.scheduled()) {
+ eventCount++;
+ }
+ if (dmaWriteEvent.scheduled()) {
reschedule = dmaWriteEvent.when();
event = DmaWrite;
+ eventCount++;
}
+ assert(eventCount <= 1);
+
SERIALIZE_SCALAR(reschedule);
SERIALIZE_ENUM(event);
@@ -1040,7 +1084,8 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_SCALAR(cmdReg.cyl_low);
SERIALIZE_SCALAR(cmdReg.cyl_high);
SERIALIZE_SCALAR(cmdReg.drive);
- SERIALIZE_SCALAR(cmdReg.status);
+ SERIALIZE_SCALAR(cmdReg.command);
+ SERIALIZE_SCALAR(status);
SERIALIZE_SCALAR(nIENBit);
SERIALIZE_SCALAR(devID);
@@ -1052,9 +1097,9 @@ IdeDisk::serialize(ostream &os)
// Serialize current transfer related information
SERIALIZE_SCALAR(cmdBytesLeft);
+ SERIALIZE_SCALAR(cmdBytes);
SERIALIZE_SCALAR(drqBytesLeft);
SERIALIZE_SCALAR(curSector);
- SERIALIZE_SCALAR(curCommand);
SERIALIZE_SCALAR(dmaRead);
SERIALIZE_SCALAR(dmaInterfaceBytes);
SERIALIZE_SCALAR(intrPending);
@@ -1092,7 +1137,8 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(cmdReg.cyl_low);
UNSERIALIZE_SCALAR(cmdReg.cyl_high);
UNSERIALIZE_SCALAR(cmdReg.drive);
- UNSERIALIZE_SCALAR(cmdReg.status);
+ UNSERIALIZE_SCALAR(cmdReg.command);
+ UNSERIALIZE_SCALAR(status);
UNSERIALIZE_SCALAR(nIENBit);
UNSERIALIZE_SCALAR(devID);
@@ -1103,10 +1149,10 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(curPrdAddr);
// Unserialize current transfer related information
+ UNSERIALIZE_SCALAR(cmdBytes);
UNSERIALIZE_SCALAR(cmdBytesLeft);
UNSERIALIZE_SCALAR(drqBytesLeft);
UNSERIALIZE_SCALAR(curSector);
- UNSERIALIZE_SCALAR(curCommand);
UNSERIALIZE_SCALAR(dmaRead);
UNSERIALIZE_SCALAR(dmaInterfaceBytes);
UNSERIALIZE_SCALAR(intrPending);
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
index 35e7404d5..409aaef9a 100644
--- a/dev/ide_disk.hh
+++ b/dev/ide_disk.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,8 +40,8 @@
#define DMA_BACKOFF_PERIOD 200
-#define MAX_DMA_SIZE (131072) // 256 * SectorSize (512)
-#define MAX_MULTSECT (128)
+#define MAX_DMA_SIZE (65536) // 64K
+#define MAX_MULTSECT (128)
#define PRD_BASE_MASK 0xfffffffe
#define PRD_COUNT_MASK 0xfffe
@@ -62,7 +62,7 @@ class PrdTableEntry {
return (entry.baseAddr & PRD_BASE_MASK);
}
- uint16_t getByteCount()
+ uint32_t getByteCount()
{
return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
(entry.byteCount & PRD_COUNT_MASK));
@@ -94,6 +94,8 @@ class PrdTableEntry {
#define STATUS_BSY_BIT 0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT 0x08
+#define STATUS_SEEK_BIT 0x10
+#define STATUS_DF_BIT 0x20
#define DRIVE_LBA_BIT 0x40
#define DEV0 (0)
@@ -114,10 +116,7 @@ typedef struct CommandReg {
uint8_t drive;
uint8_t head;
};
- union {
- uint8_t status;
- uint8_t command;
- };
+ uint8_t command;
} CommandReg_t;
typedef enum Events {
@@ -135,6 +134,7 @@ typedef enum DevAction {
ACT_CMD_WRITE,
ACT_CMD_COMPLETE,
ACT_CMD_ERROR,
+ ACT_SELECT_WRITE,
ACT_STAT_READ,
ACT_DATA_READY,
ACT_DATA_READ_BYTE,
@@ -142,7 +142,9 @@ typedef enum DevAction {
ACT_DATA_WRITE_BYTE,
ACT_DATA_WRITE_SHORT,
ACT_DMA_READY,
- ACT_DMA_DONE
+ ACT_DMA_DONE,
+ ACT_SRST_SET,
+ ACT_SRST_CLEAR
} DevAction_t;
typedef enum DevState {
@@ -151,6 +153,9 @@ typedef enum DevState {
Device_Idle_SI,
Device_Idle_NS,
+ // Software reset
+ Device_Srst,
+
// Non-data commands
Command_Execution,
@@ -202,6 +207,8 @@ class IdeDisk : public SimObject
struct hd_driveid driveID;
/** Data buffer for transfers */
uint8_t *dataBuffer;
+ /** Number of bytes in command data transfer */
+ uint32_t cmdBytes;
/** Number of bytes left in command data transfer */
uint32_t cmdBytesLeft;
/** Number of bytes left in DRQ block */
@@ -210,8 +217,8 @@ class IdeDisk : public SimObject
uint32_t curSector;
/** Command block registers */
CommandReg_t cmdReg;
- /** Shadow of the current command code */
- uint8_t curCommand;
+ /** Status register */
+ uint8_t status;
/** Interrupt enable bit */
bool nIENBit;
/** Device state */
@@ -249,6 +256,11 @@ class IdeDisk : public SimObject
~IdeDisk();
/**
+ * Reset the device state
+ */
+ void reset(int id);
+
+ /**
* Set the controller for this device
* @param c The IDE controller
*/
@@ -306,17 +318,18 @@ class IdeDisk : public SimObject
void updateState(DevAction_t action);
// Utility functions
- bool isBSYSet() { return (cmdReg.status & STATUS_BSY_BIT); }
+ bool isBSYSet() { return (status & STATUS_BSY_BIT); }
bool isIENSet() { return nIENBit; }
bool isDEVSelect() { return ((cmdReg.drive & SELECT_DEV_BIT) == devID); }
void setComplete()
{
// clear out the status byte
- cmdReg.status = 0;
-
+ status = 0;
// set the DRDY bit
- cmdReg.status |= STATUS_DRDY_BIT;
+ status |= STATUS_DRDY_BIT;
+ // set the SEEK bit
+ status |= STATUS_SEEK_BIT;
}
uint32_t getLBABase()
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 910b889d8..b39efa1f5 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/io_device.hh b/dev/io_device.hh
index 9300d87e7..e6014e73d 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index cae90a3b4..28181ba64 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -88,18 +88,18 @@ using namespace std;
///////////////////////////////////////////////////////////////////////
//
-// EtherDev PCI Device
+// NSGigE PCI Device
//
-EtherDev::EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
+NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
MemoryController *mmu, HierParams *hier, Bus *header_bus,
Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6], Addr addr)
- : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t),
- addr(addr), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
+ uint32_t func, bool rx_filter, const int eaddr[6])
+ : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), io_enable(false),
+ txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
txXferLen(0), rxXferLen(0), txPktXmitted(0), txState(txIdle), CTDD(false),
txFifoCnt(0), txFifoAvail(MAX_TX_FIFO_SIZE), txHalt(false),
txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
@@ -115,13 +115,12 @@ EtherDev::EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
physmem(pmem), intctrl(i), intrTick(0),
cpuPendingIntr(false), intrEvent(0), interface(0), pioLatency(pio_latency)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
tsunami->ethernet = this;
if (header_bus) {
pioInterface = newPioInterface(name, hier, header_bus, this,
- &EtherDev::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ &NSGigE::cacheAccess);
+
if (payload_bus)
dmaInterface = new DMAInterface<Bus>(name + ".dma",
header_bus, payload_bus, 1);
@@ -130,10 +129,10 @@ EtherDev::EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
header_bus, header_bus, 1);
} else if (payload_bus) {
pioInterface = newPioInterface(name, hier, payload_bus, this,
- &EtherDev::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
- dmaInterface = new DMAInterface<Bus>(name + ".dma",
- payload_bus, payload_bus, 1);
+ &NSGigE::cacheAccess);
+
+ dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus,
+ payload_bus, 1);
}
@@ -154,11 +153,11 @@ EtherDev::EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
rom.perfectMatch[5] = eaddr[5];
}
-EtherDev::~EtherDev()
+NSGigE::~NSGigE()
{}
void
-EtherDev::regStats()
+NSGigE::regStats()
{
txBytes
.name(name() + ".txBytes")
@@ -212,8 +211,8 @@ EtherDev::regStats()
.prereq(rxBytes)
;
- txBandwidth = txBytes * Statistics::constant(8) / simSeconds;
- rxBandwidth = rxBytes * Statistics::constant(8) / simSeconds;
+ txBandwidth = txBytes * Stats::constant(8) / simSeconds;
+ rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
txPacketRate = txPackets / simSeconds;
rxPacketRate = rxPackets / simSeconds;
}
@@ -222,25 +221,70 @@ EtherDev::regStats()
* This is to read the PCI general configuration registers
*/
void
-EtherDev::ReadConfig(int offset, int size, uint8_t *data)
+NSGigE::ReadConfig(int offset, int size, uint8_t *data)
{
if (offset < PCI_DEVICE_SPECIFIC)
PciDev::ReadConfig(offset, size, data);
- else {
- panic("need to do this\n");
- }
+ else
+ panic("Device specific PCI config space not implemented!\n");
}
/**
* This is to write to the PCI general configuration registers
*/
void
-EtherDev::WriteConfig(int offset, int size, uint32_t data)
+NSGigE::WriteConfig(int offset, int size, uint32_t data)
{
if (offset < PCI_DEVICE_SPECIFIC)
PciDev::WriteConfig(offset, size, data);
else
- panic("Need to do that\n");
+ panic("Device specific PCI config space not implemented!\n");
+
+ // Need to catch writes to BARs to update the PIO interface
+ switch (offset) {
+ //seems to work fine without all these, but i ut in the IO to
+ //double check, an assertion will fail if we need to properly
+ // imlpement it
+ case PCI_COMMAND:
+ if (config.data[offset] & PCI_CMD_IOSE)
+ io_enable = true;
+ else
+ io_enable = false;
+#if 0
+ if (config.data[offset] & PCI_CMD_BME)
+ bm_enabled = true;
+ else
+ bm_enabled = false;
+ break;
+
+ if (config.data[offset] & PCI_CMD_MSE)
+ mem_enable = true;
+ else
+ mem_enable = false;
+ break;
+#endif
+
+ case PCI0_BASE_ADDR0:
+ if (BARAddrs[0] != 0) {
+
+ if (pioInterface)
+ pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
+
+ BARAddrs[0] &= PA_UNCACHED_MASK;
+
+ }
+ break;
+ case PCI0_BASE_ADDR1:
+ if (BARAddrs[1] != 0) {
+
+ if (pioInterface)
+ pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
+
+ BARAddrs[1] &= PA_UNCACHED_MASK;
+
+ }
+ break;
+ }
}
/**
@@ -248,8 +292,10 @@ EtherDev::WriteConfig(int offset, int size, uint32_t data)
* spec sheet
*/
Fault
-EtherDev::read(MemReqPtr &req, uint8_t *data)
+NSGigE::read(MemReqPtr &req, uint8_t *data)
{
+ assert(io_enable);
+
//The mask is to give you only the offset into the device register file
Addr daddr = req->paddr & 0xfff;
DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n",
@@ -363,7 +409,6 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
break;
case RFDR:
- DPRINTF(Ethernet, "reading from RFDR\n");
switch (regs.rfcr & RFCR_RFADDR) {
case 0x000:
reg = rom.perfectMatch[1];
@@ -437,7 +482,8 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
panic("reading unimplemented register: addr = %#x", daddr);
}
- DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", daddr, reg, reg);
+ DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
+ daddr, reg, reg);
}
break;
@@ -450,8 +496,10 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
}
Fault
-EtherDev::write(MemReqPtr &req, const uint8_t *data)
+NSGigE::write(MemReqPtr &req, const uint8_t *data)
{
+ assert(io_enable);
+
Addr daddr = req->paddr & 0xfff;
DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n",
daddr, req->paddr, req->vaddr, req->size);
@@ -685,7 +733,6 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
case RFCR:
regs.rfcr = reg;
- DPRINTF(Ethernet, "Writing to RFCR, RFADDR is %#x\n", reg & RFCR_RFADDR);
rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
@@ -791,11 +838,8 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
}
void
-EtherDev::devIntrPost(uint32_t interrupts)
+NSGigE::devIntrPost(uint32_t interrupts)
{
- DPRINTF(Ethernet, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
- interrupts, regs.isr, regs.imr);
-
bool delay = false;
if (interrupts & ISR_RESERVE)
@@ -846,6 +890,9 @@ EtherDev::devIntrPost(uint32_t interrupts)
if (interrupts & ISR_RXERR)
regs.isr |= ISR_RXERR;
+ if (interrupts & ISR_RXDESC)
+ regs.isr |= ISR_RXDESC;
+
if (interrupts & ISR_RXOK) {
delay = true;
regs.isr |= ISR_RXOK;
@@ -857,14 +904,14 @@ EtherDev::devIntrPost(uint32_t interrupts)
when += intrDelay;
cpuIntrPost(when);
}
+
+ DPRINTF(Ethernet, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
+ interrupts, regs.isr, regs.imr);
}
void
-EtherDev::devIntrClear(uint32_t interrupts)
+NSGigE::devIntrClear(uint32_t interrupts)
{
- DPRINTF(Ethernet, "interrupt cleared intr=%x isr=%x imr=%x\n",
- interrupts, regs.isr, regs.imr);
-
if (interrupts & ISR_RESERVE)
panic("Cannot clear a reserved interrupt");
@@ -911,15 +958,21 @@ EtherDev::devIntrClear(uint32_t interrupts)
if (interrupts & ISR_RXERR)
regs.isr &= ~ISR_RXERR;
+ if (interrupts & ISR_RXDESC)
+ regs.isr &= ~ISR_RXDESC;
+
if (interrupts & ISR_RXOK)
regs.isr &= ~ISR_RXOK;
if (!(regs.isr & regs.imr))
cpuIntrClear();
+
+ DPRINTF(Ethernet, "interrupt cleared intr=%x isr=%x imr=%x\n",
+ interrupts, regs.isr, regs.imr);
}
void
-EtherDev::devIntrChangeMask()
+NSGigE::devIntrChangeMask()
{
DPRINTF(Ethernet, "interrupt mask changed\n");
@@ -930,7 +983,7 @@ EtherDev::devIntrChangeMask()
}
void
-EtherDev::cpuIntrPost(Tick when)
+NSGigE::cpuIntrPost(Tick when)
{
if (when > intrTick && intrTick != 0)
return;
@@ -951,7 +1004,7 @@ EtherDev::cpuIntrPost(Tick when)
}
void
-EtherDev::cpuInterrupt()
+NSGigE::cpuInterrupt()
{
// Don't send an interrupt if there's already one
if (cpuPendingIntr)
@@ -974,7 +1027,7 @@ EtherDev::cpuInterrupt()
}
void
-EtherDev::cpuIntrClear()
+NSGigE::cpuIntrClear()
{
if (cpuPendingIntr) {
cpuPendingIntr = false;
@@ -985,11 +1038,11 @@ EtherDev::cpuIntrClear()
}
bool
-EtherDev::cpuIntrPending() const
+NSGigE::cpuIntrPending() const
{ return cpuPendingIntr; }
void
-EtherDev::txReset()
+NSGigE::txReset()
{
DPRINTF(Ethernet, "transmit reset\n");
@@ -1007,7 +1060,7 @@ EtherDev::txReset()
}
void
-EtherDev::rxReset()
+NSGigE::rxReset()
{
DPRINTF(Ethernet, "receive reset\n");
@@ -1023,8 +1076,22 @@ EtherDev::rxReset()
rxState = rxIdle;
}
+void NSGigE::regsReset()
+{
+ memset(&regs, 0, sizeof(regs));
+ regs.config = 0x80000000;
+ regs.mear = 0x12;
+ regs.isr = 0x00608000;
+ regs.txcfg = 0x120;
+ regs.rxcfg = 0x4;
+ regs.srr = 0x0103;
+ regs.mibc = 0x2;
+ regs.vdr = 0x81;
+ regs.tesr = 0xc000;
+}
+
void
-EtherDev::rxDmaReadCopy()
+NSGigE::rxDmaReadCopy()
{
assert(rxDmaState == dmaReading);
@@ -1037,7 +1104,7 @@ EtherDev::rxDmaReadCopy()
}
bool
-EtherDev::doRxDmaRead()
+NSGigE::doRxDmaRead()
{
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
rxDmaState = dmaReading;
@@ -1063,7 +1130,7 @@ EtherDev::doRxDmaRead()
}
void
-EtherDev::rxDmaReadDone()
+NSGigE::rxDmaReadDone()
{
assert(rxDmaState == dmaReading);
rxDmaReadCopy();
@@ -1076,7 +1143,7 @@ EtherDev::rxDmaReadDone()
}
void
-EtherDev::rxDmaWriteCopy()
+NSGigE::rxDmaWriteCopy()
{
assert(rxDmaState == dmaWriting);
@@ -1089,7 +1156,7 @@ EtherDev::rxDmaWriteCopy()
}
bool
-EtherDev::doRxDmaWrite()
+NSGigE::doRxDmaWrite()
{
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
rxDmaState = dmaWriting;
@@ -1115,7 +1182,7 @@ EtherDev::doRxDmaWrite()
}
void
-EtherDev::rxDmaWriteDone()
+NSGigE::rxDmaWriteDone()
{
assert(rxDmaState == dmaWriting);
rxDmaWriteCopy();
@@ -1128,7 +1195,7 @@ EtherDev::rxDmaWriteDone()
}
void
-EtherDev::rxKick()
+NSGigE::rxKick()
{
DPRINTF(Ethernet, "receive kick state=%s (rxBuf.size=%d)\n",
NsRxStateStrings[rxState], rxFifo.size());
@@ -1200,6 +1267,11 @@ EtherDev::rxKick()
if (rxDmaState != dmaIdle)
goto exit;
+ DPRINTF(Ethernet,
+ "rxDescCache:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
+ ,rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
+ rxDescCache.extsts);
+
if (rxDescCache.cmdsts & CMDSTS_OWN) {
rxState = rxIdle;
} else {
@@ -1254,12 +1326,10 @@ EtherDev::rxKick()
//if (rxPktBytes == 0) { /* packet is done */
assert(rxPktBytes == 0);
- rxFifoCnt -= rxPacket->length;
- rxPacket = 0;
-
rxDescCache.cmdsts |= CMDSTS_OWN;
rxDescCache.cmdsts &= ~CMDSTS_MORE;
rxDescCache.cmdsts |= CMDSTS_OK;
+ rxDescCache.cmdsts &= 0xffff0000;
rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
#if 0
@@ -1279,31 +1349,33 @@ EtherDev::rxKick()
}
#endif
- eth_header *eth = (eth_header *) rxPacket->data;
- // eth->type 0x800 indicated that it's an ip packet.
- if (eth->type == 0x800 && extstsEnable) {
- rxDescCache.extsts |= EXTSTS_IPPKT;
+ if (rxPacket->isIpPkt() && extstsEnable) { rxDescCache.extsts |= EXTSTS_IPPKT;
if (!ipChecksum(rxPacket, false))
rxDescCache.extsts |= EXTSTS_IPERR;
- ip_header *ip = rxFifo.front()->getIpHdr();
- if (ip->protocol == 6) {
+ if (rxPacket->isTcpPkt()) {
rxDescCache.extsts |= EXTSTS_TCPPKT;
if (!tcpChecksum(rxPacket, false))
rxDescCache.extsts |= EXTSTS_TCPERR;
- } else if (ip->protocol == 17) {
+ } else if (rxPacket->isUdpPkt()) {
rxDescCache.extsts |= EXTSTS_UDPPKT;
if (!udpChecksum(rxPacket, false))
rxDescCache.extsts |= EXTSTS_UDPERR;
}
}
+ rxFifoCnt -= rxPacket->length;
+ rxPacket = 0;
+
/* the driver seems to always receive into desc buffers
of size 1514, so you never have a pkt that is split
into multiple descriptors on the receive side, so
i don't implement that case, hence the assert above.
*/
+ DPRINTF(Ethernet, "rxDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
+ rxDescCache.cmdsts, rxDescCache.extsts);
+
rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
rxDmaData = &(rxDescCache.cmdsts);
rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts);
@@ -1388,7 +1460,7 @@ EtherDev::rxKick()
}
void
-EtherDev::transmit()
+NSGigE::transmit()
{
if (txFifo.empty()) {
DPRINTF(Ethernet, "nothing to transmit\n");
@@ -1421,7 +1493,7 @@ EtherDev::transmit()
}
void
-EtherDev::txDmaReadCopy()
+NSGigE::txDmaReadCopy()
{
assert(txDmaState == dmaReading);
@@ -1434,7 +1506,7 @@ EtherDev::txDmaReadCopy()
}
bool
-EtherDev::doTxDmaRead()
+NSGigE::doTxDmaRead()
{
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
txDmaState = dmaReading;
@@ -1460,7 +1532,7 @@ EtherDev::doTxDmaRead()
}
void
-EtherDev::txDmaReadDone()
+NSGigE::txDmaReadDone()
{
assert(txDmaState == dmaReading);
txDmaReadCopy();
@@ -1473,7 +1545,7 @@ EtherDev::txDmaReadDone()
}
void
-EtherDev::txDmaWriteCopy()
+NSGigE::txDmaWriteCopy()
{
assert(txDmaState == dmaWriting);
@@ -1486,7 +1558,7 @@ EtherDev::txDmaWriteCopy()
}
bool
-EtherDev::doTxDmaWrite()
+NSGigE::doTxDmaWrite()
{
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
txDmaState = dmaWriting;
@@ -1512,7 +1584,7 @@ EtherDev::doTxDmaWrite()
}
void
-EtherDev::txDmaWriteDone()
+NSGigE::txDmaWriteDone()
{
assert(txDmaState == dmaWriting);
txDmaWriteCopy();
@@ -1525,7 +1597,7 @@ EtherDev::txDmaWriteDone()
}
void
-EtherDev::txKick()
+NSGigE::txKick()
{
DPRINTF(Ethernet, "transmit kick state=%s\n", NsTxStateStrings[txState]);
@@ -1560,8 +1632,8 @@ EtherDev::txKick()
if (CTDD) {
txState = txDescRefr;
- txDmaAddr = txDescCache.link & 0x3fffffff;
- txDmaData = &txDescCache;
+ txDmaAddr = regs.txdp & 0x3fffffff;
+ txDmaData = &txDescCache + offsetof(ns_desc, link);
txDmaLen = sizeof(txDescCache.link);
txDmaFree = dmaDescFree;
@@ -1572,7 +1644,7 @@ EtherDev::txKick()
txState = txDescRead;
txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &txDescCache + offsetof(ns_desc, link);
+ txDmaData = &txDescCache;
txDmaLen = sizeof(ns_desc);
txDmaFree = dmaDescFree;
@@ -1592,6 +1664,11 @@ EtherDev::txKick()
if (txDmaState != dmaIdle)
goto exit;
+ DPRINTF(Ethernet,
+ "txDescCache data:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
+ ,txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts,
+ txDescCache.extsts);
+
if (txDescCache.cmdsts & CMDSTS_OWN) {
txState = txFifoBlock;
txFragPtr = txDescCache.bufptr;
@@ -1656,12 +1733,15 @@ EtherDev::txKick()
txDescCache.cmdsts &= ~CMDSTS_OWN;
txDescCache.cmdsts |= CMDSTS_OK;
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &txDescCache + offsetof(ns_desc, cmdsts);
+ DPRINTF(Ethernet,
+ "txDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
+ txDescCache.cmdsts, txDescCache.extsts);
+
+ txDmaAddr = (regs.txdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
+ txDmaData = &(txDescCache.cmdsts);
txDmaLen = sizeof(txDescCache.cmdsts) + sizeof(txDescCache.extsts);
txDmaFree = dmaDescFree;
-
if (doTxDmaWrite())
goto exit;
@@ -1777,7 +1857,7 @@ EtherDev::txKick()
}
void
-EtherDev::transferDone()
+NSGigE::transferDone()
{
if (txFifo.empty())
return;
@@ -1791,7 +1871,7 @@ EtherDev::transferDone()
}
bool
-EtherDev::rxFilter(PacketPtr packet)
+NSGigE::rxFilter(PacketPtr packet)
{
bool drop = true;
string type;
@@ -1841,7 +1921,7 @@ EtherDev::rxFilter(PacketPtr packet)
}
bool
-EtherDev::recvPacket(PacketPtr packet)
+NSGigE::recvPacket(PacketPtr packet)
{
rxBytes += packet->length;
rxPackets++;
@@ -1878,11 +1958,10 @@ EtherDev::recvPacket(PacketPtr packet)
* else, it just checks what it calculates against the value in the header in packet
*/
bool
-EtherDev::udpChecksum(PacketPtr packet, bool gen)
+NSGigE::udpChecksum(PacketPtr packet, bool gen)
{
- udp_header *hdr = (udp_header *) packet->getTransportHdr();
-
ip_header *ip = packet->getIpHdr();
+ udp_header *hdr = packet->getUdpHdr(ip);
pseudo_header *pseudo = new pseudo_header;
@@ -1905,11 +1984,10 @@ EtherDev::udpChecksum(PacketPtr packet, bool gen)
}
bool
-EtherDev::tcpChecksum(PacketPtr packet, bool gen)
+NSGigE::tcpChecksum(PacketPtr packet, bool gen)
{
- tcp_header *hdr = (tcp_header *) packet->getTransportHdr();
-
ip_header *ip = packet->getIpHdr();
+ tcp_header *hdr = packet->getTcpHdr(ip);
pseudo_header *pseudo = new pseudo_header;
@@ -1932,7 +2010,7 @@ EtherDev::tcpChecksum(PacketPtr packet, bool gen)
}
bool
-EtherDev::ipChecksum(PacketPtr packet, bool gen)
+NSGigE::ipChecksum(PacketPtr packet, bool gen)
{
ip_header *hdr = packet->getIpHdr();
@@ -1948,7 +2026,7 @@ EtherDev::ipChecksum(PacketPtr packet, bool gen)
}
uint16_t
-EtherDev::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
+NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
{
uint32_t sum = 0;
@@ -1978,8 +2056,11 @@ EtherDev::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
//
//
void
-EtherDev::serialize(ostream &os)
+NSGigE::serialize(ostream &os)
{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
/*
* Finalize any DMA events now.
*/
@@ -2030,21 +2111,53 @@ EtherDev::serialize(ostream &os)
SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ SERIALIZE_SCALAR(io_enable);
+
/*
- * Serialize the various helper variables
+ * Serialize the data Fifos
*/
- uint32_t txPktBufPtr = (uint32_t) txPacketBufPtr;
- SERIALIZE_SCALAR(txPktBufPtr);
- uint32_t rxPktBufPtr = (uint32_t) rxPktBufPtr;
- SERIALIZE_SCALAR(rxPktBufPtr);
- SERIALIZE_SCALAR(txXferLen);
- SERIALIZE_SCALAR(rxXferLen);
- SERIALIZE_SCALAR(txPktXmitted);
+ int txNumPkts = txFifo.size();
+ SERIALIZE_SCALAR(txNumPkts);
+ int i = 0;
+ pktiter_t end = txFifo.end();
+ for (pktiter_t p = txFifo.begin(); p != end; ++p) {
+ nameOut(os, csprintf("%s.txFifo%d", name(), i++));
+ (*p)->serialize(os);
+ }
+ int rxNumPkts = rxFifo.size();
+ SERIALIZE_SCALAR(rxNumPkts);
+ i = 0;
+ end = rxFifo.end();
+ for (pktiter_t p = rxFifo.begin(); p != end; ++p) {
+ nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
+ (*p)->serialize(os);
+ }
+
+ /*
+ * Serialize the various helper variables
+ */
bool txPacketExists = txPacket;
SERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ nameOut(os, csprintf("%s.txPacket", name()));
+ txPacket->serialize(os);
+ uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
+ SERIALIZE_SCALAR(txPktBufPtr);
+ }
+
bool rxPacketExists = rxPacket;
SERIALIZE_SCALAR(rxPacketExists);
+ if (rxPacketExists) {
+ nameOut(os, csprintf("%s.rxPacket", name()));
+ rxPacket->serialize(os);
+ uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
+ SERIALIZE_SCALAR(rxPktBufPtr);
+ }
+
+ SERIALIZE_SCALAR(txXferLen);
+ SERIALIZE_SCALAR(rxXferLen);
+ SERIALIZE_SCALAR(txPktXmitted);
/*
* Serialize DescCaches
@@ -2061,8 +2174,6 @@ EtherDev::serialize(ostream &os)
/*
* Serialize tx state machine
*/
- int txNumPkts = txFifo.size();
- SERIALIZE_SCALAR(txNumPkts);
int txState = this->txState;
SERIALIZE_SCALAR(txState);
SERIALIZE_SCALAR(CTDD);
@@ -2077,8 +2188,6 @@ EtherDev::serialize(ostream &os)
/*
* Serialize rx state machine
*/
- int rxNumPkts = rxFifo.size();
- SERIALIZE_SCALAR(rxNumPkts);
int rxState = this->rxState;
SERIALIZE_SCALAR(rxState);
SERIALIZE_SCALAR(CRDD);
@@ -2091,7 +2200,7 @@ EtherDev::serialize(ostream &os)
SERIALIZE_SCALAR(extstsEnable);
- /*
+ /*
* If there's a pending transmit, store the time so we can
* reschedule it later
*/
@@ -2099,6 +2208,16 @@ EtherDev::serialize(ostream &os)
SERIALIZE_SCALAR(transmitTick);
/*
+ * receive address filter settings
+ */
+ SERIALIZE_SCALAR(rxFilterEnable);
+ SERIALIZE_SCALAR(acceptBroadcast);
+ SERIALIZE_SCALAR(acceptMulticast);
+ SERIALIZE_SCALAR(acceptUnicast);
+ SERIALIZE_SCALAR(acceptPerfect);
+ SERIALIZE_SCALAR(acceptArp);
+
+ /*
* Keep track of pending interrupt status.
*/
SERIALIZE_SCALAR(intrTick);
@@ -2108,29 +2227,14 @@ EtherDev::serialize(ostream &os)
intrEventTick = intrEvent->when();
SERIALIZE_SCALAR(intrEventTick);
- int i = 0;
- for (pktiter_t p = rxFifo.begin(); p != rxFifo.end(); ++p) {
- nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
- (*p)->serialize(os);
- }
- if (rxPacketExists) {
- nameOut(os, csprintf("%s.rxPacket", name()));
- rxPacket->serialize(os);
- }
- i = 0;
- for (pktiter_t p = txFifo.begin(); p != txFifo.end(); ++p) {
- nameOut(os, csprintf("%s.txFifo%d", name(), i++));
- (*p)->serialize(os);
- }
- if (txPacketExists) {
- nameOut(os, csprintf("%s.txPacket", name()));
- txPacket->serialize(os);
- }
}
void
-EtherDev::unserialize(Checkpoint *cp, const std::string &section)
+NSGigE::unserialize(Checkpoint *cp, const std::string &section)
{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
UNSERIALIZE_SCALAR(regs.command);
UNSERIALIZE_SCALAR(regs.config);
UNSERIALIZE_SCALAR(regs.mear);
@@ -2166,23 +2270,57 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ UNSERIALIZE_SCALAR(io_enable);
+
/*
- * unserialize the various helper variables
+ * unserialize the data fifos
*/
- uint32_t txPktBufPtr;
- UNSERIALIZE_SCALAR(txPktBufPtr);
- txPacketBufPtr = (uint8_t *) txPktBufPtr;
- uint32_t rxPktBufPtr;
- UNSERIALIZE_SCALAR(rxPktBufPtr);
- rxPacketBufPtr = (uint8_t *) rxPktBufPtr;
- UNSERIALIZE_SCALAR(txXferLen);
- UNSERIALIZE_SCALAR(rxXferLen);
- UNSERIALIZE_SCALAR(txPktXmitted);
+ int txNumPkts;
+ UNSERIALIZE_SCALAR(txNumPkts);
+ int i;
+ for (i = 0; i < txNumPkts; ++i) {
+ PacketPtr p = new EtherPacket;
+ p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
+ txFifo.push_back(p);
+ }
+
+ int rxNumPkts;
+ UNSERIALIZE_SCALAR(rxNumPkts);
+ for (i = 0; i < rxNumPkts; ++i) {
+ PacketPtr p = new EtherPacket;
+ p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
+ rxFifo.push_back(p);
+ }
+ /*
+ * unserialize the various helper variables
+ */
bool txPacketExists;
UNSERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket = new EtherPacket;
+ txPacket->unserialize(cp, csprintf("%s.txPacket", section));
+ uint32_t txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBufPtr);
+ txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
+ } else
+ txPacket = 0;
+
bool rxPacketExists;
UNSERIALIZE_SCALAR(rxPacketExists);
+ rxPacket = 0;
+ if (rxPacketExists) {
+ rxPacket = new EtherPacket;
+ rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
+ uint32_t rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBufPtr);
+ rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
+ } else
+ rxPacket = 0;
+
+ UNSERIALIZE_SCALAR(txXferLen);
+ UNSERIALIZE_SCALAR(rxXferLen);
+ UNSERIALIZE_SCALAR(txPktXmitted);
/*
* Unserialize DescCaches
@@ -2199,8 +2337,6 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
/*
* unserialize tx state machine
*/
- int txNumPkts;
- UNSERIALIZE_SCALAR(txNumPkts);
int txState;
UNSERIALIZE_SCALAR(txState);
this->txState = (TxState) txState;
@@ -2217,8 +2353,6 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
/*
* unserialize rx state machine
*/
- int rxNumPkts;
- UNSERIALIZE_SCALAR(rxNumPkts);
int rxState;
UNSERIALIZE_SCALAR(rxState);
this->rxState = (RxState) rxState;
@@ -2234,8 +2368,7 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(extstsEnable);
/*
- * If there's a pending transmit, store the time so we can
- * reschedule it later
+ * If there's a pending transmit, reschedule it now
*/
Tick transmitTick;
UNSERIALIZE_SCALAR(transmitTick);
@@ -2243,6 +2376,16 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
txEvent.schedule(curTick + transmitTick);
/*
+ * unserialize receive address filter settings
+ */
+ UNSERIALIZE_SCALAR(rxFilterEnable);
+ UNSERIALIZE_SCALAR(acceptBroadcast);
+ UNSERIALIZE_SCALAR(acceptMulticast);
+ UNSERIALIZE_SCALAR(acceptUnicast);
+ UNSERIALIZE_SCALAR(acceptPerfect);
+ UNSERIALIZE_SCALAR(acceptArp);
+
+ /*
* Keep track of pending interrupt status.
*/
UNSERIALIZE_SCALAR(intrTick);
@@ -2254,30 +2397,17 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
intrEvent->schedule(intrEventTick);
}
- for (int i = 0; i < rxNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- rxFifo.push_back(p);
- }
- rxPacket = NULL;
- if (rxPacketExists) {
- rxPacket = new EtherPacket;
- rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
- }
- for (int i = 0; i < txNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- txFifo.push_back(p);
- }
- if (txPacketExists) {
- txPacket = new EtherPacket;
- txPacket->unserialize(cp, csprintf("%s.txPacket", section));
+ /*
+ * re-add addrRanges to bus bridges
+ */
+ if (pioInterface) {
+ pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
+ pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
}
}
-
Tick
-EtherDev::cacheAccess(MemReqPtr &req)
+NSGigE::cacheAccess(MemReqPtr &req)
{
DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
req->paddr, req->paddr - addr);
@@ -2286,23 +2416,23 @@ EtherDev::cacheAccess(MemReqPtr &req)
//=====================================================================
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
SimObjectParam<EtherInt *> peer;
- SimObjectParam<EtherDev *> device;
+ SimObjectParam<NSGigE *> device;
-END_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt)
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDevInt)
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
INIT_PARAM_DFLT(peer, "peer interface", NULL),
INIT_PARAM(device, "Ethernet device of this interface")
-END_INIT_SIM_OBJECT_PARAMS(EtherDevInt)
+END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
-CREATE_SIM_OBJECT(EtherDevInt)
+CREATE_SIM_OBJECT(NSGigEInt)
{
- EtherDevInt *dev_int = new EtherDevInt(getInstanceName(), device);
+ NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
EtherInt *p = (EtherInt *)peer;
if (p) {
@@ -2313,10 +2443,10 @@ CREATE_SIM_OBJECT(EtherDevInt)
return dev_int;
}
-REGISTER_SIM_OBJECT("EtherDevInt", EtherDevInt)
+REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> tx_delay;
Param<Tick> rx_delay;
@@ -2324,7 +2454,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
Param<Tick> intr_delay;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PhysicalMemory *> physmem;
- Param<Addr> addr;
Param<bool> rx_filter;
Param<string> hardware_address;
SimObjectParam<Bus*> header_bus;
@@ -2344,9 +2473,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
-END_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev)
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
@@ -2354,7 +2483,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev)
INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(physmem, "Physical Memory"),
- INIT_PARAM(addr, "Device Address"),
INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
"00:99:00:00:00:01"),
@@ -2375,22 +2503,21 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev)
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code")
-END_INIT_SIM_OBJECT_PARAMS(EtherDev)
+END_INIT_SIM_OBJECT_PARAMS(NSGigE)
-CREATE_SIM_OBJECT(EtherDev)
+CREATE_SIM_OBJECT(NSGigE)
{
int eaddr[6];
sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
&eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
- return new EtherDev(getInstanceName(), intr_ctrl, intr_delay,
- physmem, tx_delay, rx_delay, mmu, hier, header_bus,
- payload_bus, pio_latency, dma_desc_free, dma_data_free,
- dma_read_delay, dma_write_delay, dma_read_factor,
- dma_write_factor, configspace, configdata,
- tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr,
- addr);
+ return new NSGigE(getInstanceName(), intr_ctrl, intr_delay,
+ physmem, tx_delay, rx_delay, mmu, hier, header_bus,
+ payload_bus, pio_latency, dma_desc_free, dma_data_free,
+ dma_read_delay, dma_write_delay, dma_read_factor,
+ dma_write_factor, configspace, configdata,
+ tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr);
}
-REGISTER_SIM_OBJECT("EtherDev", EtherDev)
+REGISTER_SIM_OBJECT("NSGigE", NSGigE)
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index cb6550720..25a7781e5 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -96,7 +96,7 @@ struct dp_rom {
};
class IntrControl;
-class EtherDevInt;
+class NSGigEInt;
class PhysicalMemory;
class BaseInterface;
class HierParams;
@@ -106,7 +106,7 @@ class PciConfigAll;
/**
* NS DP82830 Ethernet device model
*/
-class EtherDev : public PciDev
+class NSGigE : public PciDev
{
public:
/** Transmit State Machine states */
@@ -158,12 +158,21 @@ class EtherDev : public PciDev
dp_regs regs;
dp_rom rom;
- /*** BASIC STRUCTURES FOR TX/RX ***/
+ /** pci settings */
+ bool io_enable;
+#if 0
+ bool mem_enable;
+ bool bm_enable;
+#endif
+
+ /*** BASIC STRUCTURES FOR TX/RX ***/
/* Data FIFOs */
pktbuf_t txFifo;
pktbuf_t rxFifo;
/** various helper vars */
+ PacketPtr txPacket;
+ PacketPtr rxPacket;
uint8_t *txPacketBufPtr;
uint8_t *rxPacketBufPtr;
uint32_t txXferLen;
@@ -171,8 +180,6 @@ class EtherDev : public PciDev
uint32_t txPktXmitted;
bool rxDmaFree;
bool txDmaFree;
- PacketPtr txPacket;
- PacketPtr rxPacket;
/** DescCaches */
ns_desc txDescCache;
@@ -236,20 +243,20 @@ class EtherDev : public PciDev
void txDmaWriteCopy();
void rxDmaReadDone();
- friend class EventWrapper<EtherDev, &EtherDev::rxDmaReadDone>;
- EventWrapper<EtherDev, &EtherDev::rxDmaReadDone> rxDmaReadEvent;
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaReadDone> rxDmaReadEvent;
void rxDmaWriteDone();
- friend class EventWrapper<EtherDev, &EtherDev::rxDmaWriteDone>;
- EventWrapper<EtherDev, &EtherDev::rxDmaWriteDone> rxDmaWriteEvent;
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone> rxDmaWriteEvent;
void txDmaReadDone();
- friend class EventWrapper<EtherDev, &EtherDev::txDmaReadDone>;
- EventWrapper<EtherDev, &EtherDev::txDmaReadDone> txDmaReadEvent;
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaReadDone> txDmaReadEvent;
void txDmaWriteDone();
- friend class EventWrapper<EtherDev, &EtherDev::txDmaWriteDone>;
- EventWrapper<EtherDev, &EtherDev::txDmaWriteDone> txDmaWriteEvent;
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaWriteDone> txDmaWriteEvent;
bool dmaDescFree;
bool dmaDataFree;
@@ -261,34 +268,23 @@ class EtherDev : public PciDev
void txReset();
void rxReset();
- void regsReset() {
- memset(&regs, 0, sizeof(regs));
- regs.config = 0x80000000;
- regs.mear = 0x12;
- regs.isr = 0x00608000;
- regs.txcfg = 0x120;
- regs.rxcfg = 0x4;
- regs.srr = 0x0103;
- regs.mibc = 0x2;
- regs.vdr = 0x81;
- regs.tesr = 0xc000;
- }
+ void regsReset();
void rxKick();
Tick rxKickTick;
- typedef EventWrapper<EtherDev, &EtherDev::rxKick> RxKickEvent;
+ typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent;
friend class RxKickEvent;
void txKick();
Tick txKickTick;
- typedef EventWrapper<EtherDev, &EtherDev::txKick> TxKickEvent;
+ typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent;
friend class TxKickEvent;
/**
* Retransmit event
*/
void transmit();
- typedef EventWrapper<EtherDev, &EtherDev::transmit> TxEvent;
+ typedef EventWrapper<NSGigE, &NSGigE::transmit> TxEvent;
friend class TxEvent;
TxEvent txEvent;
@@ -323,7 +319,7 @@ class EtherDev : public PciDev
void cpuInterrupt();
void cpuIntrClear();
- typedef EventWrapper<EtherDev, &EtherDev::cpuInterrupt> IntrEvent;
+ typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
friend class IntrEvent;
IntrEvent *intrEvent;
@@ -335,18 +331,18 @@ class EtherDev : public PciDev
bool ipChecksum(PacketPtr packet, bool gen);
uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len);
- EtherDevInt *interface;
+ NSGigEInt *interface;
public:
- EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
+ NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
MemoryController *mmu, HierParams *hier, Bus *header_bus,
Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6], Addr addr);
- ~EtherDev();
+ uint32_t func, bool rx_filter, const int eaddr[6]);
+ ~NSGigE();
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);
@@ -360,7 +356,7 @@ class EtherDev : public PciDev
bool recvPacket(PacketPtr packet);
void transferDone();
- void setInterface(EtherDevInt *i) { assert(!interface); interface = i; }
+ void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
@@ -369,14 +365,14 @@ class EtherDev : public PciDev
void regStats();
private:
- Statistics::Scalar<> txBytes;
- Statistics::Scalar<> rxBytes;
- Statistics::Scalar<> txPackets;
- Statistics::Scalar<> rxPackets;
- Statistics::Formula txBandwidth;
- Statistics::Formula rxBandwidth;
- Statistics::Formula txPacketRate;
- Statistics::Formula rxPacketRate;
+ Stats::Scalar<> txBytes;
+ Stats::Scalar<> rxBytes;
+ Stats::Scalar<> txPackets;
+ Stats::Scalar<> rxPackets;
+ Stats::Formula txBandwidth;
+ Stats::Formula rxBandwidth;
+ Stats::Formula txPacketRate;
+ Stats::Formula rxPacketRate;
private:
Tick pioLatency;
@@ -388,13 +384,13 @@ class EtherDev : public PciDev
/*
* Ethernet Interface for an Ethernet Device
*/
-class EtherDevInt : public EtherInt
+class NSGigEInt : public EtherInt
{
private:
- EtherDev *dev;
+ NSGigE *dev;
public:
- EtherDevInt(const std::string &name, EtherDev *d)
+ NSGigEInt(const std::string &name, NSGigE *d)
: EtherInt(name), dev(d) { dev->setInterface(this); }
virtual bool recvPacket(PacketPtr &pkt) { return dev->recvPacket(pkt); }
diff --git a/dev/ns_gige_reg.h b/dev/ns_gige_reg.h
index 774fec435..c87dfe960 100644
--- a/dev/ns_gige_reg.h
+++ b/dev/ns_gige_reg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 226fd2749..8937b8e67 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,22 +35,29 @@
#include <vector>
#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "dev/scsi_ctrl.hh"
#include "dev/pciconfigall.hh"
#include "dev/pcidev.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
using namespace std;
-PciConfigAll::PciConfigAll(const string &name, Addr a,
- MemoryController *mmu)
- : FunctionalMemory(name), addr(a)
+PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
+ HierParams *hier, Bus *bus)
+ : PioDevice(name), addr(a)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &PciConfigAll::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
// Make all the pointers to devices null
for(int x=0; x < MAX_PCI_DEV; x++)
for(int y=0; y < MAX_PCI_FUNC; y++)
@@ -148,13 +155,27 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
void
PciConfigAll::serialize(std::ostream &os)
{
- // code should be written
+ /*
+ * There is no state associated with this object that requires
+ * serialization. The only real state are the device pointers
+ * which are all setup by the constructor of the PciDev class
+ */
}
void
PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
{
- //code should be written
+ /*
+ * There is no state associated with this object that requires
+ * serialization. The only real state are the device pointers
+ * which are all setup by the constructor of the PciDev class
+ */
+}
+
+Tick
+PciConfigAll::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -164,6 +185,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
Param<Addr> mask;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
@@ -171,13 +194,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(addr, "Device Address"),
- INIT_PARAM(mask, "Address Mask")
+ INIT_PARAM(mask, "Address Mask"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
CREATE_SIM_OBJECT(PciConfigAll)
{
- return new PciConfigAll(getInstanceName(), addr, mmu);
+ return new PciConfigAll(getInstanceName(), addr, mmu, hier, io_bus);
}
REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll)
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
index 6df1e2fe7..356e62a3c 100644
--- a/dev/pciconfigall.hh
+++ b/dev/pciconfigall.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,11 +34,13 @@
#ifndef __PCICONFIGALL_HH__
#define __PCICONFIGALL_HH__
-#include "mem/functional_mem/functional_memory.hh"
#include "dev/pcireg.h"
+#include "base/range.hh"
+#include "dev/io_device.hh"
-#define MAX_PCI_DEV 32
-#define MAX_PCI_FUNC 8
+
+static const uint32_t MAX_PCI_DEV = 32;
+static const uint32_t MAX_PCI_FUNC = 8;
class PciDev;
@@ -49,30 +51,89 @@ class PciDev;
* space and passes the requests on to TsunamiPCIDev devices as
* appropriate.
*/
-class PciConfigAll : public FunctionalMemory
+class PciConfigAll : public PioDevice
{
private:
Addr addr;
static const Addr size = 0xffffff;
- public:
/**
* Pointers to all the devices that are registered with this
* particular config space.
*/
PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
+ public:
/**
- * The default constructor.
- */
- PciConfigAll(const std::string &name, Addr a, MemoryController *mmu);
+ * Constructor for PCIConfigAll
+ * @param name name of the object
+ * @param a base address of the write
+ * @param mmu the memory controller
+ * @param hier object to store parameters universal the device hierarchy
+ * @param bus The bus that this device is attached to
+ */
+ PciConfigAll(const std::string &name, Addr a, MemoryController *mmu,
+ HierParams *hier, Bus *bus);
+
+
+ /**
+ * Check if a device exists.
+ * @param pcidev PCI device to check
+ * @param pcifunc PCI function to check
+ * @return true if device exists, false otherwise
+ */
+ bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
+ { return devices[pcidev][pcifunc] != NULL ? true : false; }
+
+ /**
+ * Registers a device with the config space object.
+ * @param pcidev PCI device to register
+ * @param pcifunc PCI function to register
+ * @param device device to register
+ */
+ void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
+ { devices[pcidev][pcifunc] = device; }
+ /**
+ * Read something in PCI config space. If the device does not exist
+ * -1 is returned, if the device does exist its PciDev::ReadConfig (or the
+ * virtual function that overrides) it is called.
+ * @param req Contains the address of the field to read.
+ * @param data Return the field read.
+ * @return The fault condition of the access.
+ */
virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+ /**
+ * Write to PCI config spcae. If the device does not exit the simulator
+ * panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
+ * function that overrides it).
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
+
virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __PCICONFIGALL_HH__
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 9ac170b5c..01f336ff8 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,10 +64,10 @@ PciDev::PciDev(const string &name, MemoryController *mmu, PciConfigAll *cf,
panic("NULL pointer to configuration data");
// Setup pointer in config space to point to this entry
- if (cf->devices[dev][func] != NULL)
+ if (cf->deviceExists(dev,func))
panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func);
else
- cf->devices[dev][func] = this;
+ cf->registerDevice(dev, func, this);
}
void
@@ -247,7 +247,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
break;
default:
- panic("writing to a read only register");
+ DPRINTF(PCIDEV, "Writing to a read only register");
}
break;
}
@@ -256,13 +256,26 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
void
PciDev::serialize(ostream &os)
{
+ SERIALIZE_ARRAY(BARSize, 6);
+ SERIALIZE_ARRAY(BARAddrs, 6);
SERIALIZE_ARRAY(config.data, 64);
}
void
PciDev::unserialize(Checkpoint *cp, const std::string &section)
{
+ UNSERIALIZE_ARRAY(BARSize, 6);
+ UNSERIALIZE_ARRAY(BARAddrs, 6);
UNSERIALIZE_ARRAY(config.data, 64);
+
+ // Add the MMU mappings for the BARs
+ for (int i=0; i < 6; i++) {
+ if (BARAddrs[i] != 0)
+ mmu->add_child((FunctionalMemory *)this,
+ Range<Addr>(BARAddrs[i],
+ BARAddrs[i] +
+ BARSize[i] - 1));
+ }
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index f8192db3c..c0fe47ac4 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,9 +39,17 @@
class PciConfigAll;
class MemoryController;
+
+/**
+ * This class encapulates the first 64 bytes of a singles PCI
+ * devices config space that in configured by the configuration file.
+ */
class PciConfigData : public SimObject
{
public:
+ /**
+ * Constructor to initialize the devices config space to 0.
+ */
PciConfigData(const std::string &name)
: SimObject(name)
{
@@ -50,8 +58,13 @@ class PciConfigData : public SimObject
memset(BARSize, 0, sizeof(BARSize));
}
+ /** The first 64 bytes */
PCIConfig config;
+
+ /** The size of the BARs */
uint32_t BARSize[6];
+
+ /** The addresses of the BARs */
Addr BARAddrs[6];
};
@@ -66,17 +79,50 @@ class PciDev : public DmaDevice
{
protected:
MemoryController *mmu;
+ /** A pointer to the configspace all object that calls
+ * us when a read comes to this particular device/function.
+ */
PciConfigAll *configSpace;
+
+ /**
+ * A pointer to the object that contains the first 64 bytes of
+ * config space
+ */
PciConfigData *configData;
+
+ /** The bus number we are on */
uint32_t busNum;
+
+ /** The device number we have */
uint32_t deviceNum;
+
+ /** The function number */
uint32_t functionNum;
+ /** The current config space. Unlike the PciConfigData this is updated
+ * during simulation while continues to refelect what was in the config file.
+ */
PCIConfig config;
+
+ /** The size of the BARs */
uint32_t BARSize[6];
+
+ /** The current address mapping of the BARs */
Addr BARAddrs[6];
public:
+ /**
+ * Constructor for PCI Dev. This function copies data from the config file
+ * object PCIConfigData and registers the device with a PciConfigAll object.
+ * @param name name of the object
+ * @param mmu a pointer to the memory controller
+ * @param cf a pointer to the config space object that this device need to
+ * register with
+ * @param cd A pointer to the config space values specified in the conig file
+ * @param bus the bus this device is on
+ * @param dev the device id of this device
+ * @param func the function number of this device
+ */
PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf,
PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func);
@@ -87,10 +133,38 @@ class PciDev : public DmaDevice
return No_Fault;
}
+ /**
+ * Write to the PCI config space data that is stored locally. This may be
+ * overridden by the device but at some point it will eventually call this
+ * for normal operations that it does not need to override.
+ * @param offset the offset into config space
+ * @param size the size of the write
+ * @param data the data to write
+ */
virtual void WriteConfig(int offset, int size, uint32_t data);
+
+
+ /**
+ * Read from the PCI config space data that is stored locally. This may be
+ * overridden by the device but at some point it will eventually call this
+ * for normal operations that it does not need to override.
+ * @param offset the offset into config space
+ * @param size the size of the read
+ * @param data pointer to the location where the read value should be stored
+ */
virtual void ReadConfig(int offset, int size, uint8_t *data);
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
diff --git a/dev/pcireg.h b/dev/pcireg.h
index 2921c30be..8e8b7b451 100644
--- a/dev/pcireg.h
+++ b/dev/pcireg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -114,6 +114,11 @@ union PCIConfig {
#define PCI_HEADER_TYPE 0x0E // Header Type ro
#define PCI_BIST 0x0F // Built in self test rw
+// some pci command reg bitfields
+#define PCI_CMD_BME 0x04 // Bus master function enable
+#define PCI_CMD_MSE 0x02 // Memory Space Access enable
+#define PCI_CMD_IOSE 0x01 // I/O space enable
+
// Type 0 PCI offsets
#define PCI0_BASE_ADDR0 0x10 // Base Address 0 rw
#define PCI0_BASE_ADDR1 0x14 // Base Address 1 rw
diff --git a/dev/platform.cc b/dev/platform.cc
index c39849162..8515d543a 100644
--- a/dev/platform.cc
+++ b/dev/platform.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/platform.hh b/dev/platform.hh
index 407f58406..f0e3d291b 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,7 @@ class Platform : public SimObject
virtual ~Platform() {}
virtual void postConsoleInt() = 0;
virtual void clearConsoleInt() = 0;
+ virtual Tick intrFrequency() = 0;
};
#endif // __PLATFORM_HH_
diff --git a/dev/simple_disk.cc b/dev/simple_disk.cc
index aa6ff5b38..19e8683df 100644
--- a/dev/simple_disk.cc
+++ b/dev/simple_disk.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2003 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh
index 935865ba4..3031cdb8b 100644
--- a/dev/simple_disk.hh
+++ b/dev/simple_disk.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2003 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index 8956ee557..1cdd7d726 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,12 @@ Tsunami::Tsunami(const string &name, System *s,
intr_sum_type[i] = 0;
}
+Tick
+Tsunami::intrFrequency()
+{
+ return io->frequency();
+}
+
void
Tsunami::postConsoleInt()
{
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
index f619e4cff..db266d62d 100644
--- a/dev/tsunami.hh
+++ b/dev/tsunami.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
class IdeController;
class TlaserClock;
-class EtherDev;
+class NSGigE;
class TsunamiCChip;
class TsunamiPChip;
class TsunamiIO;
@@ -67,7 +67,7 @@ class Tsunami : public Platform
/** Pointer to the disk controller device */
IdeController *disk_controller;
/** Pointer to the ethernet controller device */
- EtherDev *ethernet;
+ NSGigE *ethernet;
/** Pointer to the Tsunami CChip.
* The chip contains some configuration information and
@@ -95,10 +95,33 @@ class Tsunami : public Platform
Tsunami(const std::string &name, System *s, IntrControl *intctrl,
PciConfigAll *pci, int intrFreq);
+ /**
+ * Return the interrupting frequency to AlphaAccess
+ * @return frequency of RTC interrupts
+ */
+ virtual Tick intrFrequency();
+
+ /**
+ * Cause the cpu to post a serial interrupt to the CPU.
+ */
virtual void postConsoleInt();
+
+ /**
+ * Clear a posted CPU interrupt (id=55)
+ */
virtual void clearConsoleInt();
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index ba49c361b..a64f643a2 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -1,4 +1,30 @@
-/* $Id$ */
+/*
+ * Copyright (c) 2004 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
* Emulation of the Tsunami CChip CSRs
@@ -9,21 +35,23 @@
#include <vector>
#include "base/trace.hh"
-#include "cpu/exec_context.hh"
#include "dev/console.hh"
#include "dev/tsunami_cchip.hh"
#include "dev/tsunamireg.h"
#include "dev/tsunami.hh"
-#include "cpu/intr_control.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
+#include "cpu/intr_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
using namespace std;
TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu)
- : FunctionalMemory(name), addr(a), tsunami(t)
+ MemoryController *mmu, HierParams *hier, Bus* bus)
+ : PioDevice(name), addr(a), tsunami(t)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
@@ -35,6 +63,12 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
RTCInterrupting[i] = false;
}
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &TsunamiCChip::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
drir = 0;
misc = 0;
@@ -68,7 +102,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
case TSDEV_CC_AAR1:
case TSDEV_CC_AAR2:
case TSDEV_CC_AAR3:
- panic("TSDEV_CC_AARx not implemeted\n");
+ *(uint64_t*)data = 0;
return No_Fault;
case TSDEV_CC_DIM0:
*(uint64_t*)data = dim[0];
@@ -131,8 +165,8 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
Fault
TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
{
- DPRINTF(Tsunami, "write - va=%#x size=%d \n",
- req->vaddr, req->size);
+ DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
+ req->vaddr, *(uint64_t*)data, req->size);
Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
@@ -195,6 +229,11 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
}
supportedWrite = true;
}
+
+ // ignore NXMs
+ if (*(uint64_t*)data & 0x10000000)
+ supportedWrite = true;
+
if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
return No_Fault;
case TSDEV_CC_AAR0:
@@ -342,6 +381,13 @@ TsunamiCChip::clearDRIR(uint32_t interrupt)
DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
}
+Tick
+TsunamiCChip::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
+
+
void
TsunamiCChip::serialize(std::ostream &os)
{
@@ -371,6 +417,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
SimObjectParam<Tsunami *> tsunami;
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
@@ -378,13 +426,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
INIT_PARAM(tsunami, "Tsunami"),
INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address")
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
CREATE_SIM_OBJECT(TsunamiCChip)
{
- return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
+ return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus);
}
REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
index adb05a572..a358c98ba 100644
--- a/dev/tsunami_cchip.hh
+++ b/dev/tsunami_cchip.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,24 +33,28 @@
#ifndef __TSUNAMI_CCHIP_HH__
#define __TSUNAMI_CCHIP_HH__
-#include "mem/functional_mem/functional_memory.hh"
#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
/*
* Tsunami CChip
*/
-class TsunamiCChip : public FunctionalMemory
+class TsunamiCChip : public PioDevice
{
private:
+ /** The base address of this device */
Addr addr;
+
+ /** The size of mappad from the above address */
static const Addr size = 0xfff;
protected:
- /**
- * pointer to the tsunami object.
- * This is our access to all the other tsunami
- * devices.
- */
+ /**
+ * pointer to the tsunami object.
+ * This is our access to all the other tsunami
+ * devices.
+ */
Tsunami *tsunami;
/**
@@ -72,24 +76,85 @@ class TsunamiCChip : public FunctionalMemory
*/
uint64_t drir;
+ /**
+ * The MISC register contains the CPU we are currently on
+ * as well as bits to ack RTC and IPI interrupts.
+ */
uint64_t misc;
+ /** Count of the number of pending IPIs on a CPU */
uint64_t ipiInterrupting[Tsunami::Max_CPUs];
+
+ /** Indicator of which CPUs have had an RTC interrupt */
bool RTCInterrupting[Tsunami::Max_CPUs];
public:
+ /**
+ * Initialize the Tsunami CChip by setting all of the
+ * device register to 0.
+ * @param name name of this device.
+ * @param t pointer back to the Tsunami object that we belong to.
+ * @param a address we are mapped at.
+ * @param mmu pointer to the memory controller that sends us events.
+ * @param hier object to store parameters universal the device hierarchy
+ * @param bus The bus that this device is attached to
+ */
TsunamiCChip(const std::string &name, Tsunami *t, Addr a,
- MemoryController *mmu);
+ MemoryController *mmu, HierParams *hier, Bus *bus);
+ /**
+ * Process a read to the CChip.
+ * @param req Contains the address to read from.
+ * @param data A pointer to write the read data to.
+ * @return The fault condition of the access.
+ */
virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+
+ /**
+ * Process a write to the CChip.
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ /**
+ * post an RTC interrupt to the CPU
+ */
void postRTC();
+
+ /**
+ * post an interrupt to the CPU.
+ * @param interrupt the interrupt number to post (0-64)
+ */
void postDRIR(uint32_t interrupt);
+
+ /**
+ * clear an interrupt previously posted to the CPU.
+ * @param interrupt the interrupt number to post (0-64)
+ */
void clearDRIR(uint32_t interrupt);
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __TSUNAMI_CCHIP_HH__
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 2dda86fbc..ea530b3d2 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,15 +37,16 @@
#include <vector>
#include "base/trace.hh"
-#include "cpu/exec_context.hh"
#include "dev/console.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 "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "sim/builder.hh"
#include "dev/tsunami_cchip.hh"
+#include "dev/tsunamireg.h"
+#include "mem/functional_mem/memory_control.hh"
using namespace std;
@@ -75,6 +76,22 @@ TsunamiIO::RTCEvent::description()
return "tsunami RTC 1024Hz interrupt";
}
+void
+TsunamiIO::RTCEvent::serialize(std::ostream &os)
+{
+ Tick time = when();
+ SERIALIZE_SCALAR(time);
+}
+
+void
+TsunamiIO::RTCEvent::unserialize(Checkpoint *cp, const std::string &section)
+{
+ Tick time;
+ UNSERIALIZE_SCALAR(time);
+ reschedule(time);
+}
+
+
// Timer Event for PIT Timers
TsunamiIO::ClockEvent::ClockEvent()
: Event(&mainEventQueue)
@@ -121,12 +138,40 @@ TsunamiIO::ClockEvent::Status()
return status;
}
+void
+TsunamiIO::ClockEvent::serialize(std::ostream &os)
+{
+ Tick time = scheduled() ? when() : 0;
+ SERIALIZE_SCALAR(time);
+ SERIALIZE_SCALAR(status);
+ SERIALIZE_SCALAR(mode);
+ SERIALIZE_SCALAR(interval);
+}
+
+void
+TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string &section)
+{
+ Tick time;
+ UNSERIALIZE_SCALAR(time);
+ UNSERIALIZE_SCALAR(status);
+ UNSERIALIZE_SCALAR(mode);
+ UNSERIALIZE_SCALAR(interval);
+ if (time)
+ schedule(time);
+}
+
TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
- Addr a, MemoryController *mmu)
- : FunctionalMemory(name), addr(a), tsunami(t), rtc(t)
+ Addr a, MemoryController *mmu, HierParams *hier, Bus *bus)
+ : PioDevice(name), addr(a), tsunami(t), rtc(t)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &TsunamiIO::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
// set the back pointer from tsunami to myself
tsunami->io = this;
@@ -243,8 +288,11 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
Fault
TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
{
+
+#if TRACING_ON
uint8_t dt = *(uint8_t*)data;
uint64_t dt64 = dt;
+#endif
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff, dt64);
@@ -375,20 +423,32 @@ TsunamiIO::clearPIC(uint8_t bitvector)
}
}
+Tick
+TsunamiIO::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
+
void
TsunamiIO::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(timerData);
SERIALIZE_SCALAR(uip);
+ SERIALIZE_SCALAR(mask1);
+ SERIALIZE_SCALAR(mask2);
+ SERIALIZE_SCALAR(mode1);
+ SERIALIZE_SCALAR(mode2);
SERIALIZE_SCALAR(picr);
SERIALIZE_SCALAR(picInterrupting);
- Tick time0when = timer0.when();
- Tick time2when = timer2.when();
- Tick rtcwhen = rtc.when();
- SERIALIZE_SCALAR(time0when);
- SERIALIZE_SCALAR(time2when);
- SERIALIZE_SCALAR(rtcwhen);
-
+ SERIALIZE_SCALAR(RTCAddress);
+
+ // Serialize the timers
+ nameOut(os, csprintf("%s.timer0", name()));
+ timer0.serialize(os);
+ nameOut(os, csprintf("%s.timer2", name()));
+ timer2.serialize(os);
+ nameOut(os, csprintf("%s.rtc", name()));
+ rtc.serialize(os);
}
void
@@ -396,17 +456,18 @@ TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(timerData);
UNSERIALIZE_SCALAR(uip);
+ UNSERIALIZE_SCALAR(mask1);
+ UNSERIALIZE_SCALAR(mask2);
+ UNSERIALIZE_SCALAR(mode1);
+ UNSERIALIZE_SCALAR(mode2);
UNSERIALIZE_SCALAR(picr);
UNSERIALIZE_SCALAR(picInterrupting);
- Tick time0when;
- Tick time2when;
- Tick rtcwhen;
- UNSERIALIZE_SCALAR(time0when);
- UNSERIALIZE_SCALAR(time2when);
- UNSERIALIZE_SCALAR(rtcwhen);
- timer0.reschedule(time0when);
- timer2.reschedule(time2when);
- rtc.reschedule(rtcwhen);
+ UNSERIALIZE_SCALAR(RTCAddress);
+
+ // Unserialize the timers
+ timer0.unserialize(cp, csprintf("%s.timer0", section));
+ timer2.unserialize(cp, csprintf("%s.timer2", section));
+ rtc.unserialize(cp, csprintf("%s.rtc", section));
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
@@ -415,6 +476,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
Param<time_t> time;
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
@@ -424,13 +487,16 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
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(addr, "Device Address"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
CREATE_SIM_OBJECT(TsunamiIO)
{
- return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu);
+ return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier,
+ io_bus);
}
REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index 90bef2b86..e6a545689 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,78 +33,173 @@
#ifndef __TSUNAMI_DMA_HH__
#define __TSUNAMI_DMA_HH__
-#define RTC_RATE 1024
-
-#include "mem/functional_mem/functional_memory.hh"
+#include "dev/io_device.hh"
+#include "base/range.hh"
#include "dev/tsunami.hh"
+/** How often the RTC interrupts */
+static const int RTC_RATE = 1024;
+
/*
- * Tsunami I/O device
+ * Tsunami I/O device is a catch all for all the south bridge stuff we care
+ * to implement.
*/
-class TsunamiIO : public FunctionalMemory
+class TsunamiIO : public PioDevice
{
private:
+ /** The base address of this device */
Addr addr;
+
+ /** The size of mappad from the above address */
static const Addr size = 0xff;
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
+ /** 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. This store the
+ * address you are going to be reading from on a read.
+ */
uint8_t RTCAddress;
protected:
+ /**
+ * The ClockEvent is handles the PIT interrupts
+ */
class ClockEvent : public Event
{
protected:
+ /** how often the PIT fires */
Tick interval;
+ /** The mode of the PIT */
uint8_t mode;
+ /** The status of the PIT */
uint8_t status;
public:
+ /**
+ * Just set the mode to 0
+ */
ClockEvent();
+ /**
+ * processs the timer event
+ */
virtual void process();
+
+ /**
+ * Returns a description of this event
+ * @return the description
+ */
virtual const char *description();
+
+ /**
+ * Schedule a timer interrupt to occur sometime in the future.
+ */
void Program(int count);
+
+ /**
+ * Write the mode bits of the PIT.
+ * @param mode the new mode
+ */
void ChangeMode(uint8_t mode);
+
+ /**
+ * The current PIT status.
+ * @return the status of the PIT
+ */
uint8_t Status();
- };
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ /**
+ * Process RTC timer events and generate interrupts appropriately.
+ */
class RTCEvent : public Event
{
protected:
- Tsunami* tsunami;
+ /** A pointer back to tsunami to create interrupt the processor. */
+ Tsunami* tsunami;
public:
- RTCEvent(Tsunami* t);
+ /** RTC Event initializes the RTC event by scheduling an event
+ * RTC_RATE times pre second. */
+ RTCEvent(Tsunami* t);
- virtual void process();
- virtual const char *description();
- };
+ /**
+ * Interrupth the processor and reschedule the event.
+ * */
+ virtual void process();
+
+ /**
+ * Return a description of this event.
+ * @return a description
+ */
+ virtual const char *description();
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ /** uip UpdateInProgess says that the rtc is updating, but we just fake it
+ * by alternating it on every read of the bit since we are going to
+ * override the loop_per_jiffy time that it is trying to use the UIP to
+ * calculate.
+ */
uint8_t uip;
+ /** Mask of the PIC1 */
uint8_t mask1;
+
+ /** Mask of the PIC2 */
uint8_t mask2;
+
+ /** Mode of PIC1. Not used for anything */
uint8_t mode1;
+
+ /** Mode of PIC2. Not used for anything */
uint8_t mode2;
- uint8_t picr; //Raw PIC interrput register, before masking
+ /** Raw PIC interrupt register before masking */
+ uint8_t picr; //Raw PIC interrput register
+
+ /** Is the pic interrupting right now or not. */
bool picInterrupting;
+ /** A pointer to the Tsunami device which be belong to */
Tsunami *tsunami;
- /*
+ /**
* 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;
- /*
+ /**
* 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
@@ -114,27 +209,84 @@ class TsunamiIO : public FunctionalMemory
*/
ClockEvent timer2;
+ /** This is the event used to interrupt the cpu like an RTC. */
RTCEvent rtc;
+ /** The interval is set via two writes to the PIT.
+ * This variable contains a flag as to how many writes have happened, and
+ * the time so far.
+ */
uint32_t timerData;
public:
- uint32_t frequency() const { return RTC_RATE; }
+ /**
+ * Return the freqency of the RTC
+ * @return interrupt rate of the RTC
+ */
+ Tick frequency() const { return RTC_RATE; }
+
+ /**
+ * Initialize all the data for devices supported by Tsunami I/O.
+ * @param name name of this device.
+ * @param t pointer back to the Tsunami object that we belong to.
+ * @param init_time Time (as in seconds since 1970) to set RTC to.
+ * @param a address we are mapped at.
+ * @param mmu pointer to the memory controller that sends us events.
+ */
TsunamiIO(const std::string &name, Tsunami *t, time_t init_time,
- Addr a, MemoryController *mmu);
+ Addr a, MemoryController *mmu, HierParams *hier, Bus *bus);
+ /**
+ * Create the tm struct from seconds since 1970
+ */
void set_time(time_t t);
+ /**
+ * Process a read to one of the devices we are emulating.
+ * @param req Contains the address to read from.
+ * @param data A pointer to write the read data to.
+ * @return The fault condition of the access.
+ */
virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+ /**
+ * Process a write to one of the devices we emulate.
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ /**
+ * Post an PIC interrupt to the CPU via the CChip
+ * @param bitvector interrupt to post.
+ */
void postPIC(uint8_t bitvector);
+
+ /**
+ * Clear a posted interrupt
+ * @param bitvector interrupt to clear
+ */
void clearPIC(uint8_t bitvector);
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __TSUNAMI_IO_HH__
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index dabf6bf40..b1346bb1a 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -1,4 +1,30 @@
-/* $Id$ */
+/*
+ * Copyright (c) 2004 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 PChip (pci)
@@ -9,14 +35,12 @@
#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_pchip.hh"
#include "dev/tsunamireg.h"
#include "dev/tsunami.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh"
@@ -25,8 +49,9 @@
using namespace std;
TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu)
- : FunctionalMemory(name), addr(a), tsunami(t)
+ MemoryController *mmu, HierParams *hier,
+ Bus *bus)
+ : PioDevice(name), addr(a), tsunami(t)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
@@ -36,6 +61,16 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
tba[i] = 0;
}
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &TsunamiPChip::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
+
+ // initialize pchip control register
+ pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
+
//Set back pointer in tsunami
tsunami->pchip = this;
}
@@ -47,8 +82,6 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
req->vaddr, req->size);
Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
-// ExecContext *xc = req->xc;
-// int cpuid = xc->cpu_id;
switch (req->size) {
@@ -91,17 +124,18 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
*(uint64_t*)data = tba[3];
return No_Fault;
case TSDEV_PC_PCTL:
- // might want to change the clock??
- *(uint64_t*)data = 0x00; // try this
+ *(uint64_t*)data = pctl;
return No_Fault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
- panic("PC_PERROR not implemented\n");
+ *(uint64_t*)data = 0x00;
+ return No_Fault;
case TSDEV_PC_PERRMASK:
- panic("PC_PERRMASK not implemented\n");
+ *(uint64_t*)data = 0x00;
+ return No_Fault;
case TSDEV_PC_PERRSET:
panic("PC_PERRSET not implemented\n");
case TSDEV_PC_TLBIV:
@@ -179,15 +213,14 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
tba[3] = *(uint64_t*)data;
return No_Fault;
case TSDEV_PC_PCTL:
- // might want to change the clock??
- //*(uint64_t*)data; // try this
+ pctl = *(uint64_t*)data;
return No_Fault;
case TSDEV_PC_PLAT:
panic("PC_PLAT not implemented\n");
case TSDEV_PC_RES:
panic("PC_RES not implemented\n");
case TSDEV_PC_PERROR:
- panic("PC_PERROR not implemented\n");
+ return No_Fault;
case TSDEV_PC_PERRMASK:
panic("PC_PERRMASK not implemented\n");
case TSDEV_PC_PERRSET:
@@ -235,12 +268,29 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
Addr pteAddr;
Addr dmaAddr;
+#if 0
+ DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
for (int i = 0; i < 4; i++) {
+ DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
+ i, wsba[i], wsm[i]);
+
windowBase = wsba[i];
- windowMask = ~wsm[i] & (0x7ff << 20);
+ windowMask = ~wsm[i] & (ULL(0xfff) << 20);
if ((busAddr & windowMask) == (windowBase & windowMask)) {
+ DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
+ i, windowBase, windowMask, (busAddr & windowMask),
+ (windowBase & windowMask));
+ }
+ }
+#endif
+
+ for (int i = 0; i < 4; i++) {
+
+ windowBase = wsba[i];
+ windowMask = ~wsm[i] & (ULL(0xfff) << 20);
+ if ((busAddr & windowMask) == (windowBase & windowMask)) {
if (wsba[i] & 0x1) { // see if enabled
if (wsba[i] & 0x2) { // see if SG bit is set
@@ -254,8 +304,8 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
to create an address for the SG page
*/
- tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff);
- baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13);
+ tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
+ baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
memcpy((void *)&pteEntry,
@@ -263,10 +313,10 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
physmem->dma_addr(pteAddr, sizeof(uint64_t)),
sizeof(uint64_t));
- dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff);
+ dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
} else {
- baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff;
+ baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
tbaMask = ~baMask;
dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
}
@@ -276,12 +326,14 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
}
}
- return 0;
+ // if no match was found, then return the original address
+ return busAddr;
}
void
TsunamiPChip::serialize(std::ostream &os)
{
+ SERIALIZE_SCALAR(pctl);
SERIALIZE_ARRAY(wsba, 4);
SERIALIZE_ARRAY(wsm, 4);
SERIALIZE_ARRAY(tba, 4);
@@ -290,16 +342,25 @@ TsunamiPChip::serialize(std::ostream &os)
void
TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
{
+ UNSERIALIZE_SCALAR(pctl);
UNSERIALIZE_ARRAY(wsba, 4);
UNSERIALIZE_ARRAY(wsm, 4);
UNSERIALIZE_ARRAY(tba, 4);
}
+Tick
+TsunamiPChip::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
+
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
SimObjectParam<Tsunami *> tsunami;
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
@@ -307,13 +368,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
INIT_PARAM(tsunami, "Tsunami"),
INIT_PARAM(mmu, "Memory Controller"),
- INIT_PARAM(addr, "Device Address")
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
CREATE_SIM_OBJECT(TsunamiPChip)
{
- return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu);
+ return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus);
}
REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh
index 3ed66c54c..af50872a0 100644
--- a/dev/tsunami_pchip.hh
+++ b/dev/tsunami_pchip.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,38 +33,98 @@
#ifndef __TSUNAMI_PCHIP_HH__
#define __TSUNAMI_PCHIP_HH__
-#include "mem/functional_mem/functional_memory.hh"
#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
/*
* Tsunami PChip
*/
-class TsunamiPChip : public FunctionalMemory
+class TsunamiPChip : public PioDevice
{
private:
+ /** The base address of this device */
Addr addr;
+
+ /** The size of mappad from the above address */
static const Addr size = 0xfff;
protected:
+ /**
+ * pointer to the tsunami object.
+ * This is our access to all the other tsunami
+ * devices.
+ */
Tsunami *tsunami;
+ /** Pchip control register */
+ uint64_t pctl;
+
+ /** Window Base addresses */
uint64_t wsba[4];
+
+ /** Window masks */
uint64_t wsm[4];
+
+ /** Translated Base Addresses */
uint64_t tba[4];
public:
+ /**
+ * Register the PChip with the mmu and init all wsba, wsm, and tba to 0
+ * @param name the name of thes device
+ * @param t a pointer to the tsunami device
+ * @param a the address which we respond to
+ * @param mmu the mmu we are to register with
+ * @param hier object to store parameters universal the device hierarchy
+ * @param bus The bus that this device is attached to
+ */
TsunamiPChip(const std::string &name, Tsunami *t, Addr a,
- MemoryController *mmu);
+ MemoryController *mmu, HierParams *hier, Bus *bus);
- // @todo This hack does a quick and dirty translation of the PCI bus address to
- // a valid DMA address. This is described in 10-10 of the Tsunami book, should be fixed
+ /**
+ * Translate a PCI bus address to a memory address for DMA.
+ * @todo Andrew says this needs to be fixed. What's wrong with it?
+ * @param busAddr PCI address to translate.
+ * @return memory system address
+ */
Addr translatePciToDma(Addr busAddr);
+ /**
+ * Process a read to the PChip.
+ * @param req Contains the address to read from.
+ * @param data A pointer to write the read data to.
+ * @return The fault condition of the access.
+ */
virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+ /**
+ * Process a write to the PChip.
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __TSUNAMI_PCHIP_HH__
diff --git a/dev/tsunami_uart.cc b/dev/tsunami_uart.cc
index 6c4c30e7d..84eb80c8a 100644
--- a/dev/tsunami_uart.cc
+++ b/dev/tsunami_uart.cc
@@ -34,17 +34,55 @@ using namespace std;
#define CONS_INT_TX 0x01 // interrupt enable / state bits
#define CONS_INT_RX 0x02
+
+TsunamiUart::IntrEvent::IntrEvent(TsunamiUart *u)
+ : Event(&mainEventQueue), uart(u)
+{
+ DPRINTF(TsunamiUart, "UART Interrupt Event Initilizing\n");
+}
+
+const char *
+TsunamiUart::IntrEvent::description()
+{
+ return "tsunami uart interrupt delay event";
+}
+
+void
+TsunamiUart::IntrEvent::process()
+{
+ if (UART_IER_THRI & uart->IER) {
+ DPRINTF(TsunamiUart, "UART InterEvent, interrupting\n");
+ uart->cons->raiseInt(CONS_INT_TX);
+ }
+ else
+ DPRINTF(TsunamiUart, "UART InterEvent, not interrupting\n");
+
+}
+
+void
+TsunamiUart::IntrEvent::scheduleIntr()
+{
+ DPRINTF(TsunamiUart, "Scheduling IER interrupt\n");
+ if (!scheduled())
+ schedule(curTick + 300);
+ else
+ reschedule(curTick + 300);
+}
+
+
+
TsunamiUart::TsunamiUart(const string &name, SimConsole *c,
MemoryController *mmu, Addr a,
HierParams *hier, Bus *bus)
- : PioDevice(name), addr(a), cons(c), status_store(0), valid_char(false)
+ : PioDevice(name), addr(a), cons(c), status_store(0), valid_char(false),
+ intrEvent(this)
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiUart::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(addr, addr + size - 1);
}
IER = 0;
@@ -74,14 +112,14 @@ TsunamiUart::read(MemReqPtr &req, uint8_t *data)
switch(daddr) {
case 0x5: // Status Register
- {
+ {
int status = cons->intStatus();
if (!valid_char) {
- valid_char = cons->in(next_char);
+ valid_char = cons->in(next_char);
if (!valid_char)
status &= ~CONS_INT_RX;
} else {
- status |= CONS_INT_RX;
+ status |= CONS_INT_RX;
}
if (status_store == 3) {
@@ -101,18 +139,15 @@ TsunamiUart::read(MemReqPtr &req, uint8_t *data)
int reg = (1 << 2) | (1 << 5) | (1 << 6);
if (status & CONS_INT_RX)
reg |= (1 << 0);
- *data = reg;
- return No_Fault;
+ *data = reg;
+ return No_Fault;
}
break;
- }
+ }
case 0x0: // Data register (RX)
-// if (!valid_char)
-// panic("Invalid character");
-
DPRINTF(TsunamiUart, "read data register \'%c\' %#02x\n",
- isprint(next_char) ? next_char : ' ', next_char);
+ isprint(next_char) ? next_char : ' ', next_char);
*data = next_char;
valid_char = false;
@@ -129,7 +164,11 @@ TsunamiUart::read(MemReqPtr &req, uint8_t *data)
*data = 0;
return No_Fault;
case 0x2:
- *data = 0; // This means a 8250 serial port, do we want a 16550?
+ // High two bits need to be clear for an 8250 (simple) serial port
+ // Low bit of IIR is 0 for a pending interrupt, 1 otherwise.
+ int status = cons->intStatus();
+ status = (status & 0x1) | (status >> 1);
+ *data = (~status) & 0x1 ;
return No_Fault;
}
*data = 0;
@@ -178,15 +217,20 @@ TsunamiUart::write(MemReqPtr &req, const uint8_t *data)
ourchar = *(uint64_t *)data;
if ((isprint(ourchar) || iscntrl(ourchar)) && (ourchar != 0x0C))
cons->out(ourchar);
- if (UART_IER_THRI & IER)
- cons->setInt(CONS_INT_TX);
+ cons->clearInt(CONS_INT_TX);
+ intrEvent.scheduleIntr();
return No_Fault;
break;
- case 0x1: // DLM
- DPRINTF(TsunamiUart, "writing to DLM/IER %#x\n", *(uint8_t*)data);
+ case 0x1: // IER
IER = *(uint8_t*)data;
+ DPRINTF(TsunamiUart, "writing to IER [%#x]\n", IER);
if (UART_IER_THRI & IER)
- cons->setInt(CONS_INT_TX);
+ cons->raiseInt(CONS_INT_TX);
+ else {
+ cons->clearInt(CONS_INT_TX);
+ if (intrEvent.scheduled())
+ intrEvent.deschedule();
+ }
return No_Fault;
break;
case 0x4: // MCR
@@ -211,6 +255,14 @@ TsunamiUart::serialize(ostream &os)
SERIALIZE_SCALAR(next_char);
SERIALIZE_SCALAR(valid_char);
SERIALIZE_SCALAR(IER);
+ Tick intrwhen;
+ if (intrEvent.scheduled())
+ intrwhen = intrEvent.when();
+ else
+ intrwhen = 0;
+ SERIALIZE_SCALAR(intrwhen);
+
+
}
void
@@ -220,6 +272,11 @@ TsunamiUart::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(next_char);
UNSERIALIZE_SCALAR(valid_char);
UNSERIALIZE_SCALAR(IER);
+ Tick intrwhen;
+ UNSERIALIZE_SCALAR(intrwhen);
+ if (intrwhen != 0)
+ intrEvent.schedule(intrwhen);
+
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
diff --git a/dev/tsunami_uart.hh b/dev/tsunami_uart.hh
index d57b255ae..14ee42e8b 100644
--- a/dev/tsunami_uart.hh
+++ b/dev/tsunami_uart.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@ class TsunamiUart : public PioDevice
Addr addr;
static const Addr size = 0x8;
+
protected:
SimConsole *cons;
int status_store;
@@ -55,6 +56,19 @@ class TsunamiUart : public PioDevice
bool valid_char;
uint8_t IER;
+ class IntrEvent : public Event
+ {
+ protected:
+ TsunamiUart *uart;
+ public:
+ IntrEvent(TsunamiUart *u);
+ virtual void process();
+ virtual const char *description();
+ void scheduleIntr();
+ };
+
+ IntrEvent intrEvent;
+
public:
TsunamiUart(const string &name, SimConsole *c, MemoryController *mmu,
Addr a, HierParams *hier, Bus *bus);
@@ -66,7 +80,11 @@ class TsunamiUart : public PioDevice
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
- public:
+ /**
+ * Return how long this access will take.
+ * @param req the memory request to calcuate
+ * @return Tick when the request is done
+ */
Tick cacheAccess(MemReqPtr &req);
};
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 927dd60c9..2e4e873a0 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -1,8 +1,35 @@
+/*
+ * Copyright (c) 2004 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.
+ */
#ifndef __TSUNAMIREG_H__
#define __TSUNAMIREG_H__
-#define ALPHA_K0SEG_BASE 0xfffffc0000000000ULL
+#define ALPHA_K0SEG_BASE ULL(0xfffffc0000000000)
// CChip Registers
#define TSDEV_CC_CSR 0x00
@@ -105,15 +132,14 @@
#define RTC_CONTROL_REGISTERD 13 // control register D
#define RTC_REGNUMBER_RTC_CR1 0x6A // control register 1
-#define PCHIP_PCI0_MEMORY ULL(0x10000000000)
-#define PCHIP_PCI0_IO ULL(0x101FC000000)
-#define TSUNAMI_PCI0_MEMORY ALPHA_K0SEG_BASE + PCHIP_PCI0_MEMORY
-#define TSUNAMI_PCI0_IO ALPHA_K0SEG_BASE + PCHIP_PCI0_IO
+#define PCHIP_PCI0_MEMORY ULL(0x00000000000)
+#define PCHIP_PCI0_IO ULL(0x001FC000000)
+#define TSUNAMI_UNCACHABLE_BIT ULL(0x80000000000)
+#define TSUNAMI_PCI0_MEMORY TSUNAMI_UNCACHABLE_BIT + PCHIP_PCI0_MEMORY
+#define TSUNAMI_PCI0_IO TSUNAMI_UNCACHABLE_BIT + PCHIP_PCI0_IO
// UART Defines
-
-
#define UART_IER_THRI 0x02
#define UART_IER_RLSI 0x04