diff options
Diffstat (limited to 'dev')
63 files changed, 0 insertions, 18866 deletions
diff --git a/dev/alpha_access.h b/dev/alpha_access.h deleted file mode 100644 index 5a1df6f39..000000000 --- a/dev/alpha_access.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __ALPHA_ACCESS_H__ -#define __ALPHA_ACCESS_H__ - -/** @file - * System Console Memory Mapped Register Definition - */ - -#define ALPHA_ACCESS_VERSION (1305) - -#ifdef CONSOLE -typedef unsigned uint32_t; -typedef unsigned long uint64_t; -#endif - -// This structure hacked up from simos -struct AlphaAccess -{ - uint32_t last_offset; // 00: must be first field - uint32_t version; // 04: - uint32_t numCPUs; // 08: - uint32_t intrClockFrequency; // 0C: Hz - uint64_t cpuClock; // 10: MHz - uint64_t mem_size; // 18: - - // Loaded kernel - uint64_t kernStart; // 20: - uint64_t kernEnd; // 28: - uint64_t entryPoint; // 30: - - // console disk stuff - uint64_t diskUnit; // 38: - uint64_t diskCount; // 40: - uint64_t diskPAddr; // 48: - uint64_t diskBlock; // 50: - uint64_t diskOperation; // 58: - - // console simple output stuff - uint64_t outputChar; // 60: Placeholder for output - uint64_t inputChar; // 68: Placeholder for input - - // MP boot - uint64_t cpuStack[64]; // 70: -}; - -#endif // __ALPHA_ACCESS_H__ diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc deleted file mode 100644 index 6ca5e3a06..000000000 --- a/dev/alpha_console.cc +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Alpha Console Definition - */ - -#include <cstddef> -#include <cstdio> -#include <string> - -#include "arch/alpha/system.hh" -#include "base/inifile.hh" -#include "base/str.hh" -#include "base/trace.hh" -#include "cpu/base.hh" -#include "cpu/exec_context.hh" -#include "dev/alpha_console.hh" -#include "dev/simconsole.hh" -#include "dev/simple_disk.hh" -#include "dev/tsunami_io.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" -#include "sim/sim_object.hh" - -using namespace std; -using namespace AlphaISA; - -AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d, - AlphaSystem *s, BaseCPU *c, Platform *p, - MemoryController *mmu, Addr a, - HierParams *hier, Bus *pio_bus) - : PioDevice(name, p), disk(d), console(cons), system(s), cpu(c), addr(a) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &AlphaConsole::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } - - alphaAccess = new Access; - alphaAccess->last_offset = size - 1; - - alphaAccess->version = ALPHA_ACCESS_VERSION; - alphaAccess->diskUnit = 1; - - alphaAccess->diskCount = 0; - alphaAccess->diskPAddr = 0; - alphaAccess->diskBlock = 0; - alphaAccess->diskOperation = 0; - alphaAccess->outputChar = 0; - alphaAccess->inputChar = 0; - bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack)); - - system->setAlphaAccess(addr); -} - -void -AlphaConsole::startup() -{ - alphaAccess->numCPUs = system->getNumCPUs(); - alphaAccess->kernStart = system->getKernelStart(); - alphaAccess->kernEnd = system->getKernelEnd(); - alphaAccess->entryPoint = system->getKernelEntry(); - alphaAccess->mem_size = system->physmem->size(); - alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz - alphaAccess->intrClockFrequency = platform->intrFrequency(); -} - -Fault -AlphaConsole::read(MemReqPtr &req, uint8_t *data) -{ - memset(data, 0, req->size); - - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - - switch (req->size) - { - case sizeof(uint32_t): - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - *(uint32_t*)data); - switch (daddr) - { - case offsetof(AlphaAccess, last_offset): - *(uint32_t*)data = alphaAccess->last_offset; - break; - case offsetof(AlphaAccess, version): - *(uint32_t*)data = alphaAccess->version; - break; - case offsetof(AlphaAccess, numCPUs): - *(uint32_t*)data = alphaAccess->numCPUs; - break; - case offsetof(AlphaAccess, intrClockFrequency): - *(uint32_t*)data = alphaAccess->intrClockFrequency; - break; - default: - // Old console code read in everyting as a 32bit int - *(uint32_t*)data = *(uint32_t*)(consoleData + daddr); - - } - break; - case sizeof(uint64_t): - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - *(uint64_t*)data); - switch (daddr) - { - case offsetof(AlphaAccess, inputChar): - *(uint64_t*)data = console->console_in(); - break; - case offsetof(AlphaAccess, cpuClock): - *(uint64_t*)data = alphaAccess->cpuClock; - break; - case offsetof(AlphaAccess, mem_size): - *(uint64_t*)data = alphaAccess->mem_size; - break; - case offsetof(AlphaAccess, kernStart): - *(uint64_t*)data = alphaAccess->kernStart; - break; - case offsetof(AlphaAccess, kernEnd): - *(uint64_t*)data = alphaAccess->kernEnd; - break; - case offsetof(AlphaAccess, entryPoint): - *(uint64_t*)data = alphaAccess->entryPoint; - break; - case offsetof(AlphaAccess, diskUnit): - *(uint64_t*)data = alphaAccess->diskUnit; - break; - case offsetof(AlphaAccess, diskCount): - *(uint64_t*)data = alphaAccess->diskCount; - break; - case offsetof(AlphaAccess, diskPAddr): - *(uint64_t*)data = alphaAccess->diskPAddr; - break; - case offsetof(AlphaAccess, diskBlock): - *(uint64_t*)data = alphaAccess->diskBlock; - break; - case offsetof(AlphaAccess, diskOperation): - *(uint64_t*)data = alphaAccess->diskOperation; - break; - case offsetof(AlphaAccess, outputChar): - *(uint64_t*)data = alphaAccess->outputChar; - break; - default: - int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / - sizeof(alphaAccess->cpuStack[0]); - - if (cpunum >= 0 && cpunum < 64) - *(uint64_t*)data = alphaAccess->cpuStack[cpunum]; - else - panic("Unknown 64bit access, %#x\n", daddr); - } - break; - default: - return genMachineCheckFault(); - } - - return NoFault; -} - -Fault -AlphaConsole::write(MemReqPtr &req, const uint8_t *data) -{ - uint64_t val; - - switch (req->size) { - case sizeof(uint32_t): - val = *(uint32_t *)data; - break; - - case sizeof(uint64_t): - val = *(uint64_t *)data; - break; - default: - return genMachineCheckFault(); - } - - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - ExecContext *other_xc; - - switch (daddr) { - case offsetof(AlphaAccess, diskUnit): - alphaAccess->diskUnit = val; - break; - - case offsetof(AlphaAccess, diskCount): - alphaAccess->diskCount = val; - break; - - case offsetof(AlphaAccess, diskPAddr): - alphaAccess->diskPAddr = val; - break; - - case offsetof(AlphaAccess, diskBlock): - alphaAccess->diskBlock = val; - break; - - case offsetof(AlphaAccess, diskOperation): - if (val == 0x13) - disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock, - alphaAccess->diskCount); - else - panic("Invalid disk operation!"); - - break; - - case offsetof(AlphaAccess, outputChar): - console->out((char)(val & 0xff)); - break; - - other_xc->activate(); //Start the cpu - break; - - default: - int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / - sizeof(alphaAccess->cpuStack[0]); - warn("%d: Trying to launch CPU number %d!", curTick, cpunum); - assert(val > 0 && "Must not access primary cpu"); - if (cpunum >= 0 && cpunum < 64) - alphaAccess->cpuStack[cpunum] = val; - else - panic("Unknown 64bit access, %#x\n", daddr); - } - - return NoFault; -} - -Tick -AlphaConsole::cacheAccess(MemReqPtr &req) -{ - return curTick + 1000; -} - -void -AlphaConsole::Access::serialize(ostream &os) -{ - SERIALIZE_SCALAR(last_offset); - SERIALIZE_SCALAR(version); - SERIALIZE_SCALAR(numCPUs); - SERIALIZE_SCALAR(mem_size); - SERIALIZE_SCALAR(cpuClock); - SERIALIZE_SCALAR(intrClockFrequency); - SERIALIZE_SCALAR(kernStart); - SERIALIZE_SCALAR(kernEnd); - SERIALIZE_SCALAR(entryPoint); - SERIALIZE_SCALAR(diskUnit); - SERIALIZE_SCALAR(diskCount); - SERIALIZE_SCALAR(diskPAddr); - SERIALIZE_SCALAR(diskBlock); - SERIALIZE_SCALAR(diskOperation); - SERIALIZE_SCALAR(outputChar); - SERIALIZE_SCALAR(inputChar); - SERIALIZE_ARRAY(cpuStack,64); -} - -void -AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(last_offset); - UNSERIALIZE_SCALAR(version); - UNSERIALIZE_SCALAR(numCPUs); - UNSERIALIZE_SCALAR(mem_size); - UNSERIALIZE_SCALAR(cpuClock); - UNSERIALIZE_SCALAR(intrClockFrequency); - UNSERIALIZE_SCALAR(kernStart); - UNSERIALIZE_SCALAR(kernEnd); - UNSERIALIZE_SCALAR(entryPoint); - UNSERIALIZE_SCALAR(diskUnit); - UNSERIALIZE_SCALAR(diskCount); - UNSERIALIZE_SCALAR(diskPAddr); - UNSERIALIZE_SCALAR(diskBlock); - UNSERIALIZE_SCALAR(diskOperation); - UNSERIALIZE_SCALAR(outputChar); - UNSERIALIZE_SCALAR(inputChar); - UNSERIALIZE_ARRAY(cpuStack, 64); -} - -void -AlphaConsole::serialize(ostream &os) -{ - alphaAccess->serialize(os); -} - -void -AlphaConsole::unserialize(Checkpoint *cp, const std::string §ion) -{ - alphaAccess->unserialize(cp, section); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) - - SimObjectParam<SimConsole *> sim_console; - SimObjectParam<SimpleDisk *> disk; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<AlphaSystem *> system; - SimObjectParam<BaseCPU *> cpu; - SimObjectParam<Platform *> platform; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - -END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) - -BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole) - - INIT_PARAM(sim_console, "The Simulator Console"), - INIT_PARAM(disk, "Simple Disk"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(system, "system object"), - INIT_PARAM(cpu, "Processor"), - INIT_PARAM(platform, "platform"), - INIT_PARAM(pio_bus, "The IO Bus to attach to"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) - -END_INIT_SIM_OBJECT_PARAMS(AlphaConsole) - -CREATE_SIM_OBJECT(AlphaConsole) -{ - return new AlphaConsole(getInstanceName(), sim_console, disk, - system, cpu, platform, mmu, addr, hier, pio_bus); -} - -REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole) diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh deleted file mode 100644 index f63c6ad7e..000000000 --- a/dev/alpha_console.hh +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * System Console Interface - */ - -#ifndef __ALPHA_CONSOLE_HH__ -#define __ALPHA_CONSOLE_HH__ - -#include "base/range.hh" -#include "dev/alpha_access.h" -#include "dev/io_device.hh" -#include "sim/host.hh" -#include "sim/sim_object.hh" - -class BaseCPU; -class SimConsole; -class AlphaSystem; -class SimpleDisk; -class MemoryController; - -/** - * Memory mapped interface to the system console. This device - * represents a shared data region between the OS Kernel and the - * System Console. - * - * The system console is a small standalone program that is initially - * run when the system boots. It contains the necessary code to - * access the boot disk, to read/write from the console, and to pass - * boot parameters to the kernel. - * - * This version of the system console is very different from the one - * that would be found in a real system. Many of the functions use - * some sort of backdoor to get their job done. For example, reading - * from the boot device on a real system would require a minimal - * device driver to access the disk controller, but since we have a - * simulator here, we are able to bypass the disk controller and - * access the disk image directly. There are also some things like - * reading the kernel off the disk image into memory that are normally - * taken care of by the console that are now taken care of by the - * simulator. - * - * These shortcuts are acceptable since the system console is - * primarily used doing boot before the kernel has loaded its device - * drivers. - */ -class AlphaConsole : public PioDevice -{ - protected: - struct Access : public AlphaAccess - { - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - union { - Access *alphaAccess; - uint8_t *consoleData; - }; - - /** the disk must be accessed from the console */ - SimpleDisk *disk; - - /** the system console (the terminal) is accessable from the console */ - SimConsole *console; - - /** a pointer to the system we are running in */ - AlphaSystem *system; - - /** a pointer to the CPU boot cpu */ - BaseCPU *cpu; - - Addr addr; - static const Addr size = sizeof(struct AlphaAccess); - - public: - /** Standard Constructor */ - AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d, - AlphaSystem *s, BaseCPU *c, Platform *platform, - MemoryController *mmu, Addr addr, - HierParams *hier, Bus *pio_bus); - - virtual void startup(); - - /** - * memory mapped reads and writes - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - /** - * standard serialization routines for checkpointing - */ - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - - public: - Tick cacheAccess(MemReqPtr &req); -}; - -#endif // __ALPHA_CONSOLE_HH__ diff --git a/dev/baddev.cc b/dev/baddev.cc deleted file mode 100644 index 87d683a5d..000000000 --- a/dev/baddev.cc +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * BadDevice implemenation - */ - -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "cpu/exec_context.hh" -#include "dev/baddev.hh" -#include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -using namespace TheISA; - -BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, const string &devicename) - : PioDevice(name, NULL), addr(a), devname(devicename) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name, hier, pio_bus, this, - &BadDevice::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } - -} - -Fault -BadDevice::read(MemReqPtr &req, uint8_t *data) -{ - - panic("Device %s not imlpmented\n", devname); - return NoFault; -} - -Fault -BadDevice::write(MemReqPtr &req, const uint8_t *data) -{ - panic("Device %s not imlpmented\n", devname); - return NoFault; -} - -Tick -BadDevice::cacheAccess(MemReqPtr &req) -{ - return curTick; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice) - - SimObjectParam<Platform *> platform; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - Param<string> devicename; - -END_DECLARE_SIM_OBJECT_PARAMS(BadDevice) - -BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice) - - INIT_PARAM(platform, "Platform"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - 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, hier, pio_bus, - devicename); -} - -REGISTER_SIM_OBJECT("BadDevice", BadDevice) diff --git a/dev/baddev.hh b/dev/baddev.hh deleted file mode 100644 index 189f28331..000000000 --- a/dev/baddev.hh +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * This devices just panics when touched. For example if you have a - * kernel that touches the frame buffer which isn't allowed. - */ - -#ifndef __DEV_BADDEV_HH__ -#define __DEV_BADDEV_HH__ - -#include "base/range.hh" -#include "dev/io_device.hh" - -class MemoryController; - -/** - * BadDevice - * This device just panics when accessed. It is supposed to warn - * the user that the kernel they are running has unsupported - * options (i.e. frame buffer) - */ -class BadDevice : public PioDevice -{ - private: - Addr addr; - static const Addr size = 0xf; - - std::string devname; - - public: - /** - * 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, - 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 // __DEV_BADDEV_HH__ diff --git a/dev/disk_image.cc b/dev/disk_image.cc deleted file mode 100644 index 447c54697..000000000 --- a/dev/disk_image.cc +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Disk Image Definitions - */ - -#include <sys/types.h> -#include <sys/uio.h> -#include <errno.h> -#include <unistd.h> - -#include <cstdio> -#include <cstring> -#include <fstream> -#include <string> - -#include "base/callback.hh" -#include "base/misc.hh" -#include "base/trace.hh" -#include "dev/disk_image.hh" -#include "sim/builder.hh" -#include "sim/sim_exit.hh" -#include "sim/byteswap.hh" - -using namespace std; - -//////////////////////////////////////////////////////////////////////// -// -// Raw Disk image -// -RawDiskImage::RawDiskImage(const string &name, const string &filename, - bool rd_only) - : DiskImage(name), disk_size(0) -{ open(filename, rd_only); } - -RawDiskImage::~RawDiskImage() -{ close(); } - -void -RawDiskImage::open(const string &filename, bool rd_only) -{ - if (!filename.empty()) { - initialized = true; - readonly = rd_only; - file = filename; - - ios::openmode mode = ios::in | ios::binary; - if (!readonly) - mode |= ios::out; - stream.open(file.c_str(), mode); - if (!stream.is_open()) - panic("Error opening %s", filename); - } -} - -void -RawDiskImage::close() -{ - stream.close(); -} - -off_t -RawDiskImage::size() const -{ - if (disk_size == 0) { - if (!stream.is_open()) - panic("file not open!\n"); - stream.seekg(0, ios::end); - disk_size = stream.tellg(); - } - - return disk_size / SectorSize; -} - -off_t -RawDiskImage::read(uint8_t *data, off_t offset) const -{ - if (!initialized) - panic("RawDiskImage not initialized"); - - if (!stream.is_open()) - panic("file not open!\n"); - - if (stream.seekg(offset * SectorSize, ios::beg) < 0) - panic("Could not seek to location in file"); - - streampos pos = stream.tellg(); - stream.read((char *)data, SectorSize); - - DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset); - DDUMP(DiskImageRead, data, SectorSize); - - return stream.tellg() - pos; -} - -off_t -RawDiskImage::write(const uint8_t *data, off_t offset) -{ - if (!initialized) - panic("RawDiskImage not initialized"); - - if (readonly) - panic("Cannot write to a read only disk image"); - - if (!stream.is_open()) - panic("file not open!\n"); - - if (stream.seekp(offset * SectorSize, ios::beg) < 0) - panic("Could not seek to location in file"); - - DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset); - DDUMP(DiskImageWrite, data, SectorSize); - - streampos pos = stream.tellp(); - stream.write((const char *)data, SectorSize); - return stream.tellp() - pos; -} - -DEFINE_SIM_OBJECT_CLASS_NAME("DiskImage", DiskImage) - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage) - - Param<string> image_file; - Param<bool> read_only; - -END_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage) - -BEGIN_INIT_SIM_OBJECT_PARAMS(RawDiskImage) - - INIT_PARAM(image_file, "disk image file"), - INIT_PARAM_DFLT(read_only, "read only image", false) - -END_INIT_SIM_OBJECT_PARAMS(RawDiskImage) - - -CREATE_SIM_OBJECT(RawDiskImage) -{ - return new RawDiskImage(getInstanceName(), image_file, read_only); -} - -REGISTER_SIM_OBJECT("RawDiskImage", RawDiskImage) - -//////////////////////////////////////////////////////////////////////// -// -// Copy on Write Disk image -// -const int CowDiskImage::VersionMajor = 1; -const int CowDiskImage::VersionMinor = 0; - -CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size) - : DiskImage(name), child(kid), table(NULL) -{ init(hash_size); } - -class CowDiskCallback : public Callback -{ - private: - CowDiskImage *image; - - public: - CowDiskCallback(CowDiskImage *i) : image(i) {} - void process() { image->save(); delete this; } -}; - -CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size, - const string &file, bool read_only) - : DiskImage(name), filename(file), child(kid), table(NULL) -{ - if (!open(filename)) { - assert(!read_only && "why have a non-existent read only file?"); - init(hash_size); - } - - if (!read_only) - registerExitCallback(new CowDiskCallback(this)); -} - -CowDiskImage::~CowDiskImage() -{ - SectorTable::iterator i = table->begin(); - SectorTable::iterator end = table->end(); - - while (i != end) { - delete (*i).second; - ++i; - } -} - -void -SafeRead(ifstream &stream, void *data, int count) -{ - stream.read((char *)data, count); - if (!stream.is_open()) - panic("file not open"); - - if (stream.eof()) - panic("premature end-of-file"); - - if (stream.bad() || stream.fail()) - panic("error reading cowdisk image"); -} - -template<class T> -void -SafeRead(ifstream &stream, T &data) -{ - SafeRead(stream, &data, sizeof(data)); -} - -template<class T> -void -SafeReadSwap(ifstream &stream, T &data) -{ - SafeRead(stream, &data, sizeof(data)); - data = letoh(data); //is this the proper byte order conversion? -} - -bool -CowDiskImage::open(const string &file) -{ - ifstream stream(file.c_str()); - if (!stream.is_open()) - return false; - - if (stream.fail() || stream.bad()) - panic("Error opening %s", file); - - uint64_t magic; - SafeRead(stream, magic); - - if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0) - panic("Could not open %s: Invalid magic", file); - - uint32_t major, minor; - SafeReadSwap(stream, major); - SafeReadSwap(stream, minor); - - if (major != VersionMajor && minor != VersionMinor) - panic("Could not open %s: invalid version %d.%d != %d.%d", - file, major, minor, VersionMajor, VersionMinor); - - uint64_t sector_count; - SafeReadSwap(stream, sector_count); - table = new SectorTable(sector_count); - - - for (uint64_t i = 0; i < sector_count; i++) { - uint64_t offset; - SafeReadSwap(stream, offset); - - Sector *sector = new Sector; - SafeRead(stream, sector, sizeof(Sector)); - - assert(table->find(offset) == table->end()); - (*table)[offset] = sector; - } - - stream.close(); - - initialized = true; - return true; -} - -void -CowDiskImage::init(int hash_size) -{ - table = new SectorTable(hash_size); - - initialized = true; -} - -void -SafeWrite(ofstream &stream, const void *data, int count) -{ - stream.write((const char *)data, count); - if (!stream.is_open()) - panic("file not open"); - - if (stream.eof()) - panic("premature end-of-file"); - - if (stream.bad() || stream.fail()) - panic("error reading cowdisk image"); -} - -template<class T> -void -SafeWrite(ofstream &stream, const T &data) -{ - SafeWrite(stream, &data, sizeof(data)); -} - -template<class T> -void -SafeWriteSwap(ofstream &stream, const T &data) -{ - T swappeddata = letoh(data); //is this the proper byte order conversion? - SafeWrite(stream, &swappeddata, sizeof(data)); -} -void -CowDiskImage::save() -{ - save(filename); -} - -void -CowDiskImage::save(const string &file) -{ - if (!initialized) - panic("RawDiskImage not initialized"); - - ofstream stream(file.c_str()); - if (!stream.is_open() || stream.fail() || stream.bad()) - panic("Error opening %s", file); - - uint64_t magic; - memcpy(&magic, "COWDISK!", sizeof(magic)); - SafeWrite(stream, magic); - - SafeWriteSwap(stream, (uint32_t)VersionMajor); - SafeWriteSwap(stream, (uint32_t)VersionMinor); - SafeWriteSwap(stream, (uint64_t)table->size()); - - uint64_t size = table->size(); - SectorTable::iterator iter = table->begin(); - SectorTable::iterator end = table->end(); - - for (uint64_t i = 0; i < size; i++) { - if (iter == end) - panic("Incorrect Table Size during save of COW disk image"); - - SafeWriteSwap(stream, (uint64_t)(*iter).first); - SafeWrite(stream, (*iter).second->data, sizeof(Sector)); - ++iter; - } - - stream.close(); -} - -void -CowDiskImage::writeback() -{ - SectorTable::iterator i = table->begin(); - SectorTable::iterator end = table->end(); - - while (i != end) { - child->write((*i).second->data, (*i).first); - ++i; - } -} - -off_t -CowDiskImage::size() const -{ return child->size(); } - -off_t -CowDiskImage::read(uint8_t *data, off_t offset) const -{ - if (!initialized) - panic("CowDiskImage not initialized"); - - if (offset > size()) - panic("access out of bounds"); - - SectorTable::const_iterator i = table->find(offset); - if (i == table->end()) - return child->read(data, offset); - else { - memcpy(data, (*i).second->data, SectorSize); - DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset); - DDUMP(DiskImageRead, data, SectorSize); - return SectorSize; - } -} - -off_t -CowDiskImage::write(const uint8_t *data, off_t offset) -{ - if (!initialized) - panic("RawDiskImage not initialized"); - - if (offset > size()) - panic("access out of bounds"); - - SectorTable::iterator i = table->find(offset); - if (i == table->end()) { - Sector *sector = new Sector; - memcpy(sector, data, SectorSize); - table->insert(make_pair(offset, sector)); - } else { - memcpy((*i).second->data, data, SectorSize); - } - - DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset); - DDUMP(DiskImageWrite, data, SectorSize); - - return SectorSize; -} - -void -CowDiskImage::serialize(ostream &os) -{ - string cowFilename = name() + ".cow"; - SERIALIZE_SCALAR(cowFilename); - save(Checkpoint::dir() + "/" + cowFilename); -} - -void -CowDiskImage::unserialize(Checkpoint *cp, const string §ion) -{ - string cowFilename; - UNSERIALIZE_SCALAR(cowFilename); - cowFilename = cp->cptDir + "/" + cowFilename; - open(cowFilename); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage) - - SimObjectParam<DiskImage *> child; - Param<string> image_file; - Param<int> table_size; - Param<bool> read_only; - -END_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage) - -BEGIN_INIT_SIM_OBJECT_PARAMS(CowDiskImage) - - INIT_PARAM(child, "child image"), - INIT_PARAM_DFLT(image_file, "disk image file", ""), - INIT_PARAM_DFLT(table_size, "initial table size", 65536), - INIT_PARAM_DFLT(read_only, "don't write back to the copy-on-write file", - true) - -END_INIT_SIM_OBJECT_PARAMS(CowDiskImage) - - -CREATE_SIM_OBJECT(CowDiskImage) -{ - if (((string)image_file).empty()) - return new CowDiskImage(getInstanceName(), child, table_size); - else - return new CowDiskImage(getInstanceName(), child, table_size, - image_file, read_only); -} - -REGISTER_SIM_OBJECT("CowDiskImage", CowDiskImage) diff --git a/dev/disk_image.hh b/dev/disk_image.hh deleted file mode 100644 index 648aa20c6..000000000 --- a/dev/disk_image.hh +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Disk Image Interfaces - */ - -#ifndef __DISK_IMAGE_HH__ -#define __DISK_IMAGE_HH__ - -#include <fstream> - -#include "base/hashmap.hh" -#include "sim/sim_object.hh" - -#define SectorSize (512) - -/** - * Basic interface for accessing a disk image. - */ -class DiskImage : public SimObject -{ - protected: - bool initialized; - - public: - DiskImage(const std::string &name) : SimObject(name), initialized(false) {} - virtual ~DiskImage() {} - - virtual off_t size() const = 0; - - virtual off_t read(uint8_t *data, off_t offset) const = 0; - virtual off_t write(const uint8_t *data, off_t offset) = 0; -}; - -/** - * Specialization for accessing a raw disk image - */ -class RawDiskImage : public DiskImage -{ - protected: - mutable std::fstream stream; - std::string file; - bool readonly; - mutable off_t disk_size; - - public: - RawDiskImage(const std::string &name, const std::string &filename, - bool rd_only); - ~RawDiskImage(); - - void close(); - void open(const std::string &filename, bool rd_only = false); - - virtual off_t size() const; - - virtual off_t read(uint8_t *data, off_t offset) const; - virtual off_t write(const uint8_t *data, off_t offset); -}; - -/** - * Specialization for accessing a copy-on-write disk image layer. - * A copy-on-write(COW) layer must be stacked on top of another disk - * image layer this layer can be another CowDiskImage, or a - * RawDiskImage. - * - * This object is designed to provide a mechanism for persistant - * changes to a main disk image, or to provide a place for temporary - * changes to the image to take place that later may be thrown away. - */ -class CowDiskImage : public DiskImage -{ - public: - static const int VersionMajor; - static const int VersionMinor; - - protected: - struct Sector { - uint8_t data[SectorSize]; - }; - typedef m5::hash_map<uint64_t, Sector *> SectorTable; - - protected: - std::string filename; - DiskImage *child; - SectorTable *table; - - public: - CowDiskImage(const std::string &name, DiskImage *kid, int hash_size); - CowDiskImage(const std::string &name, DiskImage *kid, int hash_size, - const std::string &filename, bool read_only); - ~CowDiskImage(); - - void init(int hash_size); - bool open(const std::string &file); - void save(); - void save(const std::string &file); - void writeback(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - - virtual off_t size() const; - - virtual off_t read(uint8_t *data, off_t offset) const; - virtual off_t write(const uint8_t *data, off_t offset); -}; - -#endif // __DISK_IMAGE_HH__ diff --git a/dev/etherbus.cc b/dev/etherbus.cc deleted file mode 100644 index c6b131e8e..000000000 --- a/dev/etherbus.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device module for modelling an ethernet hub - */ - -#include <cmath> -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "dev/etherbus.hh" -#include "dev/etherdump.hh" -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "sim/builder.hh" -#include "sim/root.hh" - -using namespace std; - -EtherBus::EtherBus(const string &name, double speed, bool loop, - EtherDump *packet_dump) - : SimObject(name), ticksPerByte(speed), loopback(loop), - event(&mainEventQueue, this), sender(0), dump(packet_dump) -{ -} - -void -EtherBus::txDone() -{ - devlist_t::iterator i = devlist.begin(); - devlist_t::iterator end = devlist.end(); - - DPRINTF(Ethernet, "ethernet packet received: length=%d\n", packet->length); - DDUMP(EthernetData, packet->data, packet->length); - - while (i != end) { - if (loopback || *i != sender) - (*i)->sendPacket(packet); - ++i; - } - - sender->sendDone(); - - if (dump) - dump->dump(packet); - - sender = 0; - packet = 0; -} - -void -EtherBus::reg(EtherInt *dev) -{ devlist.push_back(dev); } - -bool -EtherBus::send(EtherInt *sndr, PacketPtr &pkt) -{ - if (busy()) { - DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick); - return false; - } - - DPRINTF(Ethernet, "ethernet packet sent: length=%d\n", pkt->length); - DDUMP(EthernetData, pkt->data, pkt->length); - - packet = pkt; - sender = sndr; - int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0); - DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", - delay, ticksPerByte); - event.schedule(curTick + delay); - - return true; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherBus) - - Param<bool> loopback; - Param<double> speed; - SimObjectParam<EtherDump *> packet_dump; - -END_DECLARE_SIM_OBJECT_PARAMS(EtherBus) - -BEGIN_INIT_SIM_OBJECT_PARAMS(EtherBus) - - INIT_PARAM(loopback, "send the packet back to the sending interface"), - INIT_PARAM(speed, "bus speed in ticks per byte"), - INIT_PARAM(packet_dump, "object to dump network packets to") - -END_INIT_SIM_OBJECT_PARAMS(EtherBus) - -CREATE_SIM_OBJECT(EtherBus) -{ - return new EtherBus(getInstanceName(), speed, loopback, packet_dump); -} - -REGISTER_SIM_OBJECT("EtherBus", EtherBus) diff --git a/dev/etherbus.hh b/dev/etherbus.hh deleted file mode 100644 index ca859d85f..000000000 --- a/dev/etherbus.hh +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device module for modelling an ethernet hub - */ - -#ifndef __ETHERBUS_H__ -#define __ETHERBUS_H__ - -#include "sim/eventq.hh" -#include "dev/etherpkt.hh" -#include "sim/sim_object.hh" - -class EtherDump; -class EtherInt; -class EtherBus : public SimObject -{ - protected: - typedef std::list<EtherInt *> devlist_t; - devlist_t devlist; - double ticksPerByte; - bool loopback; - - protected: - class DoneEvent : public Event - { - protected: - EtherBus *bus; - - public: - DoneEvent(EventQueue *q, EtherBus *b) - : Event(q), bus(b) {} - virtual void process() { bus->txDone(); } - virtual const char *description() { return "ethernet bus completion"; } - }; - - DoneEvent event; - PacketPtr packet; - EtherInt *sender; - EtherDump *dump; - - public: - EtherBus(const std::string &name, double speed, bool loopback, - EtherDump *dump); - virtual ~EtherBus() {} - - void txDone(); - void reg(EtherInt *dev); - bool busy() const { return (bool)packet; } - bool send(EtherInt *sender, PacketPtr &packet); -}; - -#endif // __ETHERBUS_H__ diff --git a/dev/etherdump.cc b/dev/etherdump.cc deleted file mode 100644 index d8a51fc5b..000000000 --- a/dev/etherdump.cc +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Simple object for creating a simple pcap style packet trace - */ - -#include <sys/time.h> - -#include <algorithm> -#include <string> - -#include "base/misc.hh" -#include "base/output.hh" -#include "dev/etherdump.hh" -#include "sim/builder.hh" -#include "sim/root.hh" - -using std::string; - -EtherDump::EtherDump(const string &name, const string &file, int max) - : SimObject(name), stream(file.c_str()), maxlen(max) -{ -} - -#define DLT_EN10MB 1 // Ethernet (10Mb) -#define TCPDUMP_MAGIC 0xa1b2c3d4 -#define PCAP_VERSION_MAJOR 2 -#define PCAP_VERSION_MINOR 4 - -struct pcap_file_header { - uint32_t magic; - uint16_t version_major; - uint16_t version_minor; - int32_t thiszone; // gmt to local correction - uint32_t sigfigs; // accuracy of timestamps - uint32_t snaplen; // max length saved portion of each pkt - uint32_t linktype; // data link type (DLT_*) -}; - -struct pcap_pkthdr { - uint32_t seconds; - uint32_t microseconds; - uint32_t caplen; // length of portion present - uint32_t len; // length this packet (off wire) -}; - -void -EtherDump::init() -{ - curtime = time(NULL); - struct pcap_file_header hdr; - hdr.magic = TCPDUMP_MAGIC; - hdr.version_major = PCAP_VERSION_MAJOR; - hdr.version_minor = PCAP_VERSION_MINOR; - - hdr.thiszone = -5 * 3600; - hdr.snaplen = 1500; - hdr.sigfigs = 0; - hdr.linktype = DLT_EN10MB; - - stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr)); - - /* - * output an empty packet with the current time so that we know - * when the simulation began. This allows us to correlate packets - * to sim_cycles. - */ - pcap_pkthdr pkthdr; - pkthdr.seconds = curtime; - pkthdr.microseconds = 0; - pkthdr.caplen = 0; - pkthdr.len = 0; - stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr)); - - stream.flush(); -} - -void -EtherDump::dumpPacket(PacketPtr &packet) -{ - pcap_pkthdr pkthdr; - pkthdr.seconds = curtime + (curTick / Clock::Int::s); - pkthdr.microseconds = (curTick / Clock::Int::us) % ULL(1000000); - pkthdr.caplen = std::min(packet->length, maxlen); - pkthdr.len = packet->length; - stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr)); - stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen); - stream.flush(); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump) - - Param<string> file; - Param<int> maxlen; - -END_DECLARE_SIM_OBJECT_PARAMS(EtherDump) - -BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump) - - INIT_PARAM(file, "file to dump packets to"), - INIT_PARAM(maxlen, "max portion of packet data to dump") - -END_INIT_SIM_OBJECT_PARAMS(EtherDump) - -CREATE_SIM_OBJECT(EtherDump) -{ - return new EtherDump(getInstanceName(), simout.resolve(file), maxlen); -} - -REGISTER_SIM_OBJECT("EtherDump", EtherDump) diff --git a/dev/etherdump.hh b/dev/etherdump.hh deleted file mode 100644 index 149192cd7..000000000 --- a/dev/etherdump.hh +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Simple object for creating a simple pcap style packet trace - */ - -#ifndef __ETHERDUMP_H__ -#define __ETHERDUMP_H__ - -#include <fstream> -#include "dev/etherpkt.hh" -#include "sim/sim_object.hh" - -/* - * Simple object for creating a simple pcap style packet trace - */ -class EtherDump : public SimObject -{ - private: - std::ofstream stream; - const int maxlen; - void dumpPacket(PacketPtr &packet); - void init(); - - Tick curtime; - - public: - EtherDump(const std::string &name, const std::string &file, int max); - - inline void dump(PacketPtr &pkt) { dumpPacket(pkt); } -}; - -#endif // __ETHERDUMP_H__ diff --git a/dev/etherint.cc b/dev/etherint.cc deleted file mode 100644 index 8fb047373..000000000 --- a/dev/etherint.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "dev/etherint.hh" -#include "base/misc.hh" -#include "sim/param.hh" -#include "sim/sim_object.hh" - -void -EtherInt::setPeer(EtherInt *p) -{ - if (peer && peer != p) - panic("You cannot change the peer once it is set.\n" - "Current peer=%s Desired peer=%s", peer->name(), p->name()); - - peer = p; -} - -DEFINE_SIM_OBJECT_CLASS_NAME("EtherInt", EtherInt) - diff --git a/dev/etherint.hh b/dev/etherint.hh deleted file mode 100644 index e397846ae..000000000 --- a/dev/etherint.hh +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Class representing the actual interface between two ethernet - * components. - */ - -#ifndef __DEV_ETHERINT_HH__ -#define __DEV_ETHERINT_HH__ - -#include <string> - -#include "dev/etherpkt.hh" -#include "sim/sim_object.hh" - -/* - * Class representing the actual interface between two ethernet - * components. These components are intended to attach to another - * ethernet interface on one side and whatever device on the other. - */ -class EtherInt : public SimObject -{ - protected: - EtherInt *peer; - - public: - EtherInt(const std::string &name) : SimObject(name), peer(NULL) {} - virtual ~EtherInt() {} - - void setPeer(EtherInt *p); - - void recvDone() { peer->sendDone(); } - virtual void sendDone() = 0; - - bool sendPacket(PacketPtr packet) - { return peer ? peer->recvPacket(packet) : true; } - virtual bool recvPacket(PacketPtr packet) = 0; -}; - -#endif // __DEV_ETHERINT_HH__ diff --git a/dev/etherlink.cc b/dev/etherlink.cc deleted file mode 100644 index f68332926..000000000 --- a/dev/etherlink.cc +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device module for modelling a fixed bandwidth full duplex ethernet link - */ - -#include <cmath> -#include <deque> -#include <string> -#include <vector> - -#include "base/random.hh" -#include "base/trace.hh" -#include "dev/etherdump.hh" -#include "dev/etherint.hh" -#include "dev/etherlink.hh" -#include "dev/etherpkt.hh" -#include "sim/builder.hh" -#include "sim/serialize.hh" -#include "sim/system.hh" -#include "sim/root.hh" - -using namespace std; - -EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, - double rate, Tick delay, Tick delayVar, EtherDump *dump) - : SimObject(name) -{ - link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); - link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); - - interface[0] = new Interface(name + ".int0", link[0], link[1]); - interface[1] = new Interface(name + ".int1", link[1], link[0]); - - interface[0]->setPeer(peer0); - peer0->setPeer(interface[0]); - interface[1]->setPeer(peer1); - peer1->setPeer(interface[1]); -} - -EtherLink::~EtherLink() -{ - delete link[0]; - delete link[1]; - - delete interface[0]; - delete interface[1]; -} - -EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) - : EtherInt(name), txlink(tx) -{ - tx->setTxInt(this); - rx->setRxInt(this); -} - -EtherLink::Link::Link(const string &name, EtherLink *p, int num, - double rate, Tick delay, Tick delay_var, EtherDump *d) - : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), - ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), - doneEvent(this) -{ } - -void -EtherLink::serialize(ostream &os) -{ - link[0]->serialize("link0", os); - link[1]->serialize("link1", os); -} - -void -EtherLink::unserialize(Checkpoint *cp, const string §ion) -{ - link[0]->unserialize("link0", cp, section); - link[1]->unserialize("link1", cp, section); -} - -void -EtherLink::Link::txComplete(PacketPtr packet) -{ - DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); - DDUMP(EthernetData, packet->data, packet->length); - rxint->sendPacket(packet); -} - -class LinkDelayEvent : public Event -{ - protected: - EtherLink::Link *link; - PacketPtr packet; - - public: - // non-scheduling version for createForUnserialize() - LinkDelayEvent(); - LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); - - void process(); - - virtual void serialize(ostream &os); - virtual void unserialize(Checkpoint *cp, const string §ion); - static Serializable *createForUnserialize(Checkpoint *cp, - const string §ion); -}; - -void -EtherLink::Link::txDone() -{ - if (dump) - dump->dump(packet); - - if (linkDelay > 0) { - DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); - new LinkDelayEvent(this, packet, curTick + linkDelay); - } else { - txComplete(packet); - } - - packet = 0; - assert(!busy()); - - txint->sendDone(); -} - -bool -EtherLink::Link::transmit(PacketPtr pkt) -{ - if (busy()) { - DPRINTF(Ethernet, "packet not sent, link busy\n"); - return false; - } - - DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); - DDUMP(EthernetData, pkt->data, pkt->length); - - packet = pkt; - Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); - if (delayVar != 0) { - Random<Tick> var; - delay += var.uniform(0, delayVar); - } - DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", - delay, ticksPerByte); - doneEvent.schedule(curTick + delay); - - return true; -} - -void -EtherLink::Link::serialize(const string &base, ostream &os) -{ - bool packet_exists = packet; - paramOut(os, base + ".packet_exists", packet_exists); - if (packet_exists) - packet->serialize(base + ".packet", os); - - bool event_scheduled = doneEvent.scheduled(); - paramOut(os, base + ".event_scheduled", event_scheduled); - if (event_scheduled) { - Tick event_time = doneEvent.when(); - paramOut(os, base + ".event_time", event_time); - } - -} - -void -EtherLink::Link::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - bool packet_exists; - paramIn(cp, section, base + ".packet_exists", packet_exists); - if (packet_exists) { - packet = new PacketData(16384); - packet->unserialize(base + ".packet", cp, section); - } - - bool event_scheduled; - paramIn(cp, section, base + ".event_scheduled", event_scheduled); - if (event_scheduled) { - Tick event_time; - paramIn(cp, section, base + ".event_time", event_time); - doneEvent.schedule(event_time); - } -} - -LinkDelayEvent::LinkDelayEvent() - : Event(&mainEventQueue), link(NULL) -{ - setFlags(AutoSerialize); - setFlags(AutoDelete); -} - -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) - : Event(&mainEventQueue), link(l), packet(p) -{ - setFlags(AutoSerialize); - setFlags(AutoDelete); - schedule(when); -} - -void -LinkDelayEvent::process() -{ - link->txComplete(packet); -} - -void -LinkDelayEvent::serialize(ostream &os) -{ - paramOut(os, "type", string("LinkDelayEvent")); - Event::serialize(os); - - EtherLink *parent = link->parent; - bool number = link->number; - SERIALIZE_OBJPTR(parent); - SERIALIZE_SCALAR(number); - - packet->serialize("packet", os); -} - - -void -LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) -{ - Event::unserialize(cp, section); - - EtherLink *parent; - bool number; - UNSERIALIZE_OBJPTR(parent); - UNSERIALIZE_SCALAR(number); - - link = parent->link[number]; - - packet = new PacketData(16384); - packet->unserialize("packet", cp, section); -} - - -Serializable * -LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) -{ - return new LinkDelayEvent(); -} - -REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) - - SimObjectParam<EtherInt *> int1; - SimObjectParam<EtherInt *> int2; - Param<double> speed; - Param<Tick> delay; - Param<Tick> delay_var; - SimObjectParam<EtherDump *> dump; - -END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) - -BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) - - INIT_PARAM(int1, "interface 1"), - INIT_PARAM(int2, "interface 2"), - INIT_PARAM(speed, "link speed in bits per second"), - INIT_PARAM(delay, "transmit delay of packets in us"), - INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), - INIT_PARAM(dump, "object to dump network packets to") - -END_INIT_SIM_OBJECT_PARAMS(EtherLink) - -CREATE_SIM_OBJECT(EtherLink) -{ - return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, - dump); -} - -REGISTER_SIM_OBJECT("EtherLink", EtherLink) diff --git a/dev/etherlink.hh b/dev/etherlink.hh deleted file mode 100644 index 305007d9e..000000000 --- a/dev/etherlink.hh +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device module for modelling a fixed bandwidth full duplex ethernet link - */ - -#ifndef __DEV_ETHERLINK_HH__ -#define __DEV_ETHERLINK_HH__ - -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "sim/eventq.hh" -#include "sim/host.hh" -#include "sim/sim_object.hh" - -class EtherDump; -class Checkpoint; -/* - * Model for a fixed bandwidth full duplex ethernet link - */ -class EtherLink : public SimObject -{ - protected: - class Interface; - - friend class LinkDelayEvent; - /* - * Model for a single uni-directional link - */ - class Link - { - protected: - std::string objName; - - EtherLink *parent; - int number; - - Interface *txint; - Interface *rxint; - - double ticksPerByte; - Tick linkDelay; - Tick delayVar; - EtherDump *dump; - - protected: - /* - * Transfer is complete - */ - PacketPtr packet; - void txDone(); - typedef EventWrapper<Link, &Link::txDone> DoneEvent; - friend void DoneEvent::process(); - DoneEvent doneEvent; - - friend class LinkDelayEvent; - void txComplete(PacketPtr packet); - - public: - Link(const std::string &name, EtherLink *p, int num, - double rate, Tick delay, Tick delay_var, EtherDump *dump); - ~Link() {} - - const std::string name() const { return objName; } - - bool busy() const { return (bool)packet; } - bool transmit(PacketPtr packet); - - void setTxInt(Interface *i) { assert(!txint); txint = i; } - void setRxInt(Interface *i) { assert(!rxint); rxint = i; } - - void serialize(const std::string &base, std::ostream &os); - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - - /* - * Interface at each end of the link - */ - class Interface : public EtherInt - { - private: - Link *txlink; - - public: - Interface(const std::string &name, Link *txlink, Link *rxlink); - bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); } - void sendDone() { peer->sendDone(); } - }; - - Link *link[2]; - EtherInt *interface[2]; - - public: - EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1, - double rate, Tick delay, Tick delayVar, EtherDump *dump); - virtual ~EtherLink(); - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - -}; - -#endif // __ETHERLINK_HH__ diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc deleted file mode 100644 index 44dbd7c18..000000000 --- a/dev/etherpkt.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <iostream> - -#include "base/misc.hh" -#include "dev/etherpkt.hh" -#include "sim/serialize.hh" - -using namespace std; - -void -PacketData::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".length", length); - paramOut(os, base + ".slack", slack); - arrayParamOut(os, base + ".data", data, length); -} - -void -PacketData::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".length", length); - paramIn(cp, section, base + ".slack", slack); - if (length) - arrayParamIn(cp, section, base + ".data", data, length); -} diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh deleted file mode 100644 index cb9022d72..000000000 --- a/dev/etherpkt.hh +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Reference counted class containing ethernet packet data - */ - -#ifndef __ETHERPKT_HH__ -#define __ETHERPKT_HH__ - -#include <iosfwd> -#include <memory> -#include <assert.h> - -#include "base/refcnt.hh" -#include "sim/host.hh" - -/* - * Reference counted class containing ethernet packet data - */ -class Checkpoint; -class PacketData : public RefCounted -{ - public: - /* - * Pointer to packet data will be deleted - */ - uint8_t *data; - - /* - * Length of the current packet - */ - int length; - - /* - * Extra space taken up by the packet in whatever data structure - * it is in. - * - * NOTE: This can only be use by *one* data structure at a time! - */ - int slack; - - public: - PacketData() : data(NULL), length(0), slack(0) { } - explicit PacketData(size_t size) - : data(new uint8_t[size]), length(0), slack(0) { } - PacketData(std::auto_ptr<uint8_t> d, int l, int s = 0) - : data(d.release()), length(l), slack(s) { } - ~PacketData() { if (data) delete [] data; } - - public: - void serialize(const std::string &base, std::ostream &os); - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); -}; - -typedef RefCountingPtr<PacketData> PacketPtr; - -#endif // __ETHERPKT_HH__ diff --git a/dev/ethertap.cc b/dev/ethertap.cc deleted file mode 100644 index 7589991ef..000000000 --- a/dev/ethertap.cc +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Interface to connect a simulated ethernet device to the real world - */ - -#if defined(__OpenBSD__) || defined(__APPLE__) -#include <sys/param.h> -#endif -#include <netinet/in.h> - -#include <unistd.h> - -#include <deque> -#include <string> - -#include "base/misc.hh" -#include "base/pollevent.hh" -#include "base/socket.hh" -#include "base/trace.hh" -#include "dev/etherdump.hh" -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "dev/ethertap.hh" -#include "sim/builder.hh" - -using namespace std; - -/** - */ -class TapListener -{ - protected: - /** - */ - class Event : public PollEvent - { - protected: - TapListener *listener; - - public: - Event(TapListener *l, int fd, int e) - : PollEvent(fd, e), listener(l) {} - - virtual void process(int revent) { listener->accept(); } - }; - - friend class Event; - Event *event; - - protected: - ListenSocket listener; - EtherTap *tap; - int port; - - public: - TapListener(EtherTap *t, int p) - : event(NULL), tap(t), port(p) {} - ~TapListener() { if (event) delete event; } - - void accept(); - void listen(); -}; - -void -TapListener::listen() -{ - while (!listener.listen(port, true)) { - DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port); - port++; - } - - ccprintf(cerr, "Listening for tap connection on port %d\n", port); - event = new Event(this, listener.getfd(), POLLIN|POLLERR); - pollQueue.schedule(event); -} - -void -TapListener::accept() -{ - if (!listener.islistening()) - panic("TapListener(accept): cannot accept if we're not listening!"); - - int sfd = listener.accept(true); - if (sfd != -1) - tap->attach(sfd); -} - -/** - */ -class TapEvent : public PollEvent -{ - protected: - EtherTap *tap; - - public: - TapEvent(EtherTap *_tap, int fd, int e) - : PollEvent(fd, e), tap(_tap) {} - virtual void process(int revent) { tap->process(revent); } -}; - -EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz) - : EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d), - txEvent(this) -{ - buffer = new char[buflen]; - listener = new TapListener(this, port); - listener->listen(); -} - -EtherTap::~EtherTap() -{ - if (event) - delete event; - if (buffer) - delete [] buffer; - - delete listener; -} - -void -EtherTap::attach(int fd) -{ - if (socket != -1) - close(fd); - - buffer_offset = 0; - data_len = 0; - socket = fd; - DPRINTF(Ethernet, "EtherTap attached\n"); - event = new TapEvent(this, socket, POLLIN|POLLERR); - pollQueue.schedule(event); -} - -void -EtherTap::detach() -{ - DPRINTF(Ethernet, "EtherTap detached\n"); - delete event; - event = 0; - close(socket); - socket = -1; -} - -bool -EtherTap::recvPacket(PacketPtr packet) -{ - if (dump) - dump->dump(packet); - - DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length); - DDUMP(EthernetData, packet->data, packet->length); - u_int32_t len = htonl(packet->length); - write(socket, &len, sizeof(len)); - write(socket, packet->data, packet->length); - - recvDone(); - - return true; -} - -void -EtherTap::sendDone() -{} - -void -EtherTap::process(int revent) -{ - if (revent & POLLERR) { - detach(); - return; - } - - char *data = buffer + sizeof(u_int32_t); - if (!(revent & POLLIN)) - return; - - if (buffer_offset < data_len + sizeof(u_int32_t)) { - int len = read(socket, buffer + buffer_offset, buflen - buffer_offset); - if (len == 0) { - detach(); - return; - } - - buffer_offset += len; - - if (data_len == 0) - data_len = ntohl(*(u_int32_t *)buffer); - - DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d " - "data_len=%d\n", len, buffer_offset, data_len); - } - - while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) { - PacketPtr packet; - packet = new PacketData(data_len); - packet->length = data_len; - memcpy(packet->data, data, data_len); - - buffer_offset -= data_len + sizeof(u_int32_t); - assert(buffer_offset >= 0); - if (buffer_offset > 0) { - memmove(buffer, data + data_len, buffer_offset); - data_len = ntohl(*(u_int32_t *)buffer); - } else - data_len = 0; - - DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length); - DDUMP(EthernetData, packet->data, packet->length); - if (!sendPacket(packet)) { - DPRINTF(Ethernet, "bus busy...buffer for retransmission\n"); - packetBuffer.push(packet); - if (!txEvent.scheduled()) - txEvent.schedule(curTick + retryTime); - } else if (dump) { - dump->dump(packet); - } - } -} - -void -EtherTap::retransmit() -{ - if (packetBuffer.empty()) - return; - - PacketPtr packet = packetBuffer.front(); - if (sendPacket(packet)) { - if (dump) - dump->dump(packet); - DPRINTF(Ethernet, "EtherTap retransmit\n"); - packetBuffer.front() = NULL; - packetBuffer.pop(); - } - - if (!packetBuffer.empty() && !txEvent.scheduled()) - txEvent.schedule(curTick + retryTime); -} - -//===================================================================== - -void -EtherTap::serialize(ostream &os) -{ - SERIALIZE_SCALAR(socket); - SERIALIZE_SCALAR(buflen); - uint8_t *buffer = (uint8_t *)this->buffer; - SERIALIZE_ARRAY(buffer, buflen); - SERIALIZE_SCALAR(buffer_offset); - SERIALIZE_SCALAR(data_len); - - bool tapevent_present = false; - if (event) { - tapevent_present = true; - SERIALIZE_SCALAR(tapevent_present); - event->serialize(os); - } - else { - SERIALIZE_SCALAR(tapevent_present); - } -} - -void -EtherTap::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(socket); - UNSERIALIZE_SCALAR(buflen); - uint8_t *buffer = (uint8_t *)this->buffer; - UNSERIALIZE_ARRAY(buffer, buflen); - UNSERIALIZE_SCALAR(buffer_offset); - UNSERIALIZE_SCALAR(data_len); - - bool tapevent_present; - UNSERIALIZE_SCALAR(tapevent_present); - if (tapevent_present) { - event = new TapEvent(this, socket, POLLIN|POLLERR); - - event->unserialize(cp,section); - - if (event->queued()) { - pollQueue.schedule(event); - } - } -} - -//===================================================================== - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap) - - SimObjectParam<EtherInt *> peer; - SimObjectParam<EtherDump *> dump; - Param<unsigned> port; - Param<unsigned> bufsz; - -END_DECLARE_SIM_OBJECT_PARAMS(EtherTap) - -BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap) - - INIT_PARAM_DFLT(peer, "peer interface", NULL), - INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL), - INIT_PARAM_DFLT(port, "tap port", 3500), - INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000) - -END_INIT_SIM_OBJECT_PARAMS(EtherTap) - - -CREATE_SIM_OBJECT(EtherTap) -{ - EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz); - - if (peer) { - tap->setPeer(peer); - peer->setPeer(tap); - } - - return tap; -} - -REGISTER_SIM_OBJECT("EtherTap", EtherTap) diff --git a/dev/ethertap.hh b/dev/ethertap.hh deleted file mode 100644 index 069ba734f..000000000 --- a/dev/ethertap.hh +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Interface to connect a simulated ethernet device to the real world - */ - -#ifndef __ETHERTAP_HH__ -#define __ETHERTAP_HH__ - -#include <queue> -#include <string> - -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "sim/eventq.hh" -#include "base/pollevent.hh" -#include "sim/sim_object.hh" - -class TapEvent; -class TapListener; - -/* - * Interface to connect a simulated ethernet device to the real world - */ -class EtherTap : public EtherInt -{ - protected: - friend class TapEvent; - TapEvent *event; - - protected: - friend class TapListener; - TapListener *listener; - int socket; - char *buffer; - int buflen; - int32_t buffer_offset; - int32_t data_len; - - EtherDump *dump; - - void attach(int fd); - void detach(); - - protected: - std::string device; - std::queue<PacketPtr> packetBuffer; - - void process(int revent); - void enqueue(PacketData *packet); - void retransmit(); - - /* - */ - class TxEvent : public Event - { - protected: - EtherTap *tap; - - public: - TxEvent(EtherTap *_tap) - : Event(&mainEventQueue), tap(_tap) {} - void process() { tap->retransmit(); } - virtual const char *description() { return "retransmit event"; } - }; - - friend class TxEvent; - TxEvent txEvent; - - public: - EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz); - virtual ~EtherTap(); - - virtual bool recvPacket(PacketPtr packet); - virtual void sendDone(); - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -#endif // __ETHERTAP_HH__ diff --git a/dev/ide_atareg.h b/dev/ide_atareg.h deleted file mode 100644 index 5320529c8..000000000 --- a/dev/ide_atareg.h +++ /dev/null @@ -1,276 +0,0 @@ -/* $OpenBSD: atareg.h,v 1.12 2004/09/24 07:15:22 grange Exp $ */ -/* $NetBSD: atareg.h,v 1.5 1999/01/18 20:06:24 bouyer Exp $ */ - -/* - * Copyright (c) 1998, 2001 Manuel Bouyer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Manuel Bouyer. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _DEV_ATA_ATAREG_H_ -#define _DEV_ATA_ATAREG_H_ - -#if defined(linux) -#include <endian.h> -#else -#include <machine/endian.h> -#endif - -#define ATA_BYTE_ORDER LITTLE_ENDIAN - -/* - * Drive parameter structure for ATA/ATAPI. - * Bit fields: WDC_* : common to ATA/ATAPI - * ATA_* : ATA only - * ATAPI_* : ATAPI only. - */ -struct ataparams { - /* drive info */ - uint16_t atap_config; /* 0: general configuration */ -#define WDC_CFG_ATAPI_MASK 0xc000 -#define WDC_CFG_ATAPI 0x8000 -#define ATA_CFG_REMOVABLE 0x0080 -#define ATA_CFG_FIXED 0x0040 -#define ATAPI_CFG_TYPE_MASK 0x1f00 -#define ATAPI_CFG_TYPE(x) (((x) & ATAPI_CFG_TYPE_MASK) >> 8) -#define ATAPI_CFG_TYPE_DIRECT 0x00 -#define ATAPI_CFG_TYPE_SEQUENTIAL 0x01 -#define ATAPI_CFG_TYPE_CDROM 0x05 -#define ATAPI_CFG_TYPE_OPTICAL 0x07 -#define ATAPI_CFG_TYPE_NODEVICE 0x1F -#define ATAPI_CFG_REMOV 0x0080 -#define ATAPI_CFG_DRQ_MASK 0x0060 -#define ATAPI_CFG_STD_DRQ 0x0000 -#define ATAPI_CFG_IRQ_DRQ 0x0020 -#define ATAPI_CFG_ACCEL_DRQ 0x0040 -#define ATAPI_CFG_CMD_MASK 0x0003 -#define ATAPI_CFG_CMD_12 0x0000 -#define ATAPI_CFG_CMD_16 0x0001 -/* words 1-9 are ATA only */ - uint16_t atap_cylinders; /* 1: # of non-removable cylinders */ - uint16_t __reserved1; - uint16_t atap_heads; /* 3: # of heads */ - uint16_t __retired1[2]; /* 4-5: # of unform. bytes/track */ - uint16_t atap_sectors; /* 6: # of sectors */ - uint16_t __retired2[3]; - - uint8_t atap_serial[20]; /* 10-19: serial number */ - uint16_t __retired3[2]; - uint16_t __obsolete1; - uint8_t atap_revision[8]; /* 23-26: firmware revision */ - uint8_t atap_model[40]; /* 27-46: model number */ - uint16_t atap_multi; /* 47: maximum sectors per irq (ATA) */ - uint16_t __reserved2; - uint8_t atap_vendor; /* 49: vendor */ - uint8_t atap_capabilities1; /* 49: capability flags */ -#define WDC_CAP_IORDY 0x0800 -#define WDC_CAP_IORDY_DSBL 0x0400 -#define WDC_CAP_LBA 0x0200 -#define WDC_CAP_DMA 0x0100 -#define ATA_CAP_STBY 0x2000 -#define ATAPI_CAP_INTERL_DMA 0x8000 -#define ATAPI_CAP_CMD_QUEUE 0x4000 -#define ATAPI_CAP_OVERLP 0x2000 -#define ATAPI_CAP_ATA_RST 0x1000 - uint16_t atap_capabilities2; /* 50: capability flags (ATA) */ -#if ATA_BYTE_ORDER == LITTLE_ENDIAN - uint8_t __junk2; - uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */ - uint8_t __junk3; - uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */ -#else - uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */ - uint8_t __junk2; - uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */ - uint8_t __junk3; -#endif - uint16_t atap_extensions; /* 53: extensions supported */ -#define WDC_EXT_UDMA_MODES 0x0004 -#define WDC_EXT_MODES 0x0002 -#define WDC_EXT_GEOM 0x0001 -/* words 54-62 are ATA only */ - uint16_t atap_curcylinders; /* 54: current logical cylinders */ - uint16_t atap_curheads; /* 55: current logical heads */ - uint16_t atap_cursectors; /* 56: current logical sectors/tracks */ - uint16_t atap_curcapacity[2]; /* 57-58: current capacity */ - uint8_t atap_curmulti; /* 59: current multi-sector setting */ - uint8_t atap_curmulti_valid; /* 59: current multi-sector setting */ -#define WDC_MULTI_VALID 0x0100 -#define WDC_MULTI_MASK 0x00ff - uint32_t atap_capacity; /* 60-61: total capacity (LBA only) */ - uint16_t __retired4; -#if ATA_BYTE_ORDER == LITTLE_ENDIAN - uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */ - uint8_t atap_dmamode_act; /* multiword DMA mode active */ - uint8_t atap_piomode_supp; /* 64: PIO mode supported */ - uint8_t __junk4; -#else - uint8_t atap_dmamode_act; /* multiword DMA mode active */ - uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */ - uint8_t __junk4; - uint8_t atap_piomode_supp; /* 64: PIO mode supported */ -#endif - uint16_t atap_dmatiming_mimi; /* 65: minimum DMA cycle time */ - uint16_t atap_dmatiming_recom; /* 66: recommended DMA cycle time */ - uint16_t atap_piotiming; /* 67: mini PIO cycle time without FC */ - uint16_t atap_piotiming_iordy; /* 68: mini PIO cycle time with IORDY FC */ - uint16_t __reserved3[2]; -/* words 71-72 are ATAPI only */ - uint16_t atap_pkt_br; /* 71: time (ns) to bus release */ - uint16_t atap_pkt_bsyclr; /* 72: tme to clear BSY after service */ - uint16_t __reserved4[2]; - uint16_t atap_queuedepth; /* 75: */ -#define WDC_QUEUE_DEPTH_MASK 0x1f - uint16_t atap_sata_caps; /* 76: SATA capabilities */ -#define SATA_SIGNAL_GEN1 0x0002 /* SATA Gen-1 signaling speed */ -#define SATA_SIGNAL_GEN2 0x0004 /* SATA Gen-2 signaling speed */ -#define SATA_NATIVE_CMDQ 0x0100 /* native command queuing */ -#define SATA_HOST_PWR_MGMT 0x0200 /* power management (host) */ - uint16_t atap_sata_reserved; /* 77: reserved */ - uint16_t atap_sata_features_supp;/* 78: SATA features supported */ -#define SATA_NONZERO_OFFSETS 0x0002 /* non-zero buffer offsets */ -#define SATA_DMA_SETUP_AUTO 0x0004 /* DMA setup auto-activate */ -#define SATA_DRIVE_PWR_MGMT 0x0008 /* power management (device) */ - uint16_t atap_sata_features_en; /* 79: SATA features enabled */ - uint16_t atap_ata_major; /* 80: Major version number */ -#define WDC_VER_ATA1 0x0002 -#define WDC_VER_ATA2 0x0004 -#define WDC_VER_ATA3 0x0008 -#define WDC_VER_ATA4 0x0010 -#define WDC_VER_ATA5 0x0020 -#define WDC_VER_ATA6 0x0040 -#define WDC_VER_ATA7 0x0080 -#define WDC_VER_ATA8 0x0100 -#define WDC_VER_ATA9 0x0200 -#define WDC_VER_ATA10 0x0400 -#define WDC_VER_ATA11 0x0800 -#define WDC_VER_ATA12 0x1000 -#define WDC_VER_ATA13 0x2000 -#define WDC_VER_ATA14 0x4000 - uint16_t atap_ata_minor; /* 81: Minor version number */ - uint16_t atap_cmd_set1; /* 82: command set supported */ -#define WDC_CMD1_NOP 0x4000 -#define WDC_CMD1_RB 0x2000 -#define WDC_CMD1_WB 0x1000 -#define WDC_CMD1_HPA 0x0400 -#define WDC_CMD1_DVRST 0x0200 -#define WDC_CMD1_SRV 0x0100 -#define WDC_CMD1_RLSE 0x0080 -#define WDC_CMD1_AHEAD 0x0040 -#define WDC_CMD1_CACHE 0x0020 -#define WDC_CMD1_PKT 0x0010 -#define WDC_CMD1_PM 0x0008 -#define WDC_CMD1_REMOV 0x0004 -#define WDC_CMD1_SEC 0x0002 -#define WDC_CMD1_SMART 0x0001 - uint16_t atap_cmd_set2; /* 83: command set supported */ -#define ATAPI_CMD2_FCE 0x2000 /* Flush Cache Ext supported */ -#define ATAPI_CMD2_FC 0x1000 /* Flush Cache supported */ -#define ATAPI_CMD2_DCO 0x0800 /* Device Configuration Overlay supported */ -#define ATAPI_CMD2_48AD 0x0400 /* 48bit address supported */ -#define ATAPI_CMD2_AAM 0x0200 /* Automatic Acoustic Management supported */ -#define ATAPI_CMD2_SM 0x0100 /* Set Max security extension supported */ -#define ATAPI_CMD2_SF 0x0040 /* Set Features subcommand required */ -#define ATAPI_CMD2_PUIS 0x0020 /* Power up in standby supported */ -#define WDC_CMD2_RMSN 0x0010 -#define ATA_CMD2_APM 0x0008 -#define ATA_CMD2_CFA 0x0004 -#define ATA_CMD2_RWQ 0x0002 -#define WDC_CMD2_DM 0x0001 /* Download Microcode supported */ - uint16_t atap_cmd_ext; /* 84: command/features supp. ext. */ -#define ATAPI_CMDE_MSER 0x0004 /* Media serial number supported */ -#define ATAPI_CMDE_TEST 0x0002 /* SMART self-test supported */ -#define ATAPI_CMDE_SLOG 0x0001 /* SMART error logging supported */ - uint16_t atap_cmd1_en; /* 85: cmd/features enabled */ -/* bits are the same as atap_cmd_set1 */ - uint16_t atap_cmd2_en; /* 86: cmd/features enabled */ -/* bits are the same as atap_cmd_set2 */ - uint16_t atap_cmd_def; /* 87: cmd/features default */ -/* bits are NOT the same as atap_cmd_ext */ -#if ATA_BYTE_ORDER == LITTLE_ENDIAN - uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */ - uint8_t atap_udmamode_act; /* Ultra-DMA mode active */ -#else - uint8_t atap_udmamode_act; /* Ultra-DMA mode active */ - uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */ -#endif -/* 89-92 are ATA-only */ - uint16_t atap_seu_time; /* 89: Sec. Erase Unit compl. time */ - uint16_t atap_eseu_time; /* 90: Enhanced SEU compl. time */ - uint16_t atap_apm_val; /* 91: current APM value */ - uint16_t atap_mpasswd_rev; /* 92: Master Password revision */ - uint16_t atap_hwreset_res; /* 93: Hardware reset value */ -#define ATA_HWRES_CBLID 0x2000 /* CBLID above Vih */ -#define ATA_HWRES_D1_PDIAG 0x0800 /* Device 1 PDIAG detect OK */ -#define ATA_HWRES_D1_CSEL 0x0400 /* Device 1 used CSEL for address */ -#define ATA_HWRES_D1_JUMP 0x0200 /* Device 1 jumpered to address */ -#define ATA_HWRES_D0_SEL 0x0040 /* Device 0 responds when Dev 1 selected */ -#define ATA_HWRES_D0_DASP 0x0020 /* Device 0 DASP detect OK */ -#define ATA_HWRES_D0_PDIAG 0x0010 /* Device 0 PDIAG detect OK */ -#define ATA_HWRES_D0_DIAG 0x0008 /* Device 0 diag OK */ -#define ATA_HWRES_D0_CSEL 0x0004 /* Device 0 used CSEL for address */ -#define ATA_HWRES_D0_JUMP 0x0002 /* Device 0 jumpered to address */ -#if ATA_BYTE_ORDER == LITTLE_ENDIAN - uint8_t atap_acoustic_val; /* 94: Current acoustic level */ - uint8_t atap_acoustic_def; /* recommended level */ -#else - uint8_t atap_acoustic_def; /* recommended level */ - uint8_t atap_acoustic_val; /* 94: Current acoustic level */ -#endif - uint16_t __reserved6[5]; /* 95-99: reserved */ - uint16_t atap_max_lba[4]; /* 100-103: Max. user LBA add */ - uint16_t __reserved7[23]; /* 104-126: reserved */ - uint16_t atap_rmsn_supp; /* 127: remov. media status notif. */ -#define WDC_RMSN_SUPP_MASK 0x0003 -#define WDC_RMSN_SUPP 0x0001 - uint16_t atap_sec_st; /* 128: security status */ -#define WDC_SEC_LEV_MAX 0x0100 -#define WDC_SEC_ESE_SUPP 0x0020 -#define WDC_SEC_EXP 0x0010 -#define WDC_SEC_FROZEN 0x0008 -#define WDC_SEC_LOCKED 0x0004 -#define WDC_SEC_EN 0x0002 -#define WDC_SEC_SUPP 0x0001 - uint16_t __reserved8[31]; /* 129-159: vendor specific */ - uint16_t atap_cfa_power; /* 160: CFA powermode */ -#define ATAPI_CFA_MAX_MASK 0x0FFF -#define ATAPI_CFA_MODE1_DIS 0x1000 /* CFA Mode 1 Disabled */ -#define ATAPI_CFA_MODE1_REQ 0x2000 /* CFA Mode 1 Required */ -#define ATAPI_CFA_WORD160 0x8000 /* Word 160 supported */ - uint16_t __reserved9[15]; /* 161-175: reserved for CFA */ - uint8_t atap_media_serial[60]; /* 176-205: media serial number */ - uint16_t __reserved10[49]; /* 206-254: reserved */ -#if ATA_BYTE_ORDER == LITTLE_ENDIAN - uint8_t atap_signature; /* 255: Signature */ - uint8_t atap_checksum; /* Checksum */ -#else - uint8_t atap_checksum; /* Checksum */ - uint8_t atap_signature; /* 255: Signature */ -#endif -}; - -#undef ATA_BYTE_ORDER -#endif /* !_DEV_ATA_ATAREG_H_ */ diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc deleted file mode 100644 index 05c756f04..000000000 --- a/dev/ide_ctrl.cc +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <cstddef> -#include <cstdlib> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "cpu/intr_control.hh" -#include "dev/ide_ctrl.hh" -#include "dev/ide_disk.hh" -#include "dev/pciconfigall.hh" -#include "dev/pcireg.h" -#include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" -#include "sim/sim_object.hh" - -using namespace std; -using namespace TheISA; - -//// -// Initialization and destruction -//// - -IdeController::IdeController(Params *p) - : PciDev(p) -{ - // initialize the PIO interface addresses - pri_cmd_addr = 0; - pri_cmd_size = BARSize[0]; - - pri_ctrl_addr = 0; - pri_ctrl_size = BARSize[1]; - - sec_cmd_addr = 0; - sec_cmd_size = BARSize[2]; - - sec_ctrl_addr = 0; - sec_ctrl_size = BARSize[3]; - - // initialize the bus master interface (BMI) address to be configured - // via PCI - bmi_addr = 0; - bmi_size = BARSize[4]; - - // zero out all of the registers - memset(bmi_regs.data, 0, sizeof(bmi_regs)); - memset(config_regs.data, 0, sizeof(config_regs.data)); - - // setup initial values - // enable both channels - config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN); - config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN); - bmi_regs.bmis0 = DMA1CAP | DMA0CAP; - bmi_regs.bmis1 = DMA1CAP | DMA0CAP; - - // reset all internal variables - io_enabled = false; - bm_enabled = false; - memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); - - pioInterface = NULL; - dmaInterface = NULL; - // create the PIO and DMA interfaces - if (params()->pio_bus) { - pioInterface = newPioInterface(name() + ".pio", params()->hier, - params()->pio_bus, this, - &IdeController::cacheAccess); - pioLatency = params()->pio_latency * params()->pio_bus->clockRate; - } - - if (params()->dma_bus) { - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - params()->dma_bus, - params()->dma_bus, 1, true); - } - - // setup the disks attached to controller - memset(disks, 0, sizeof(disks)); - dev[0] = 0; - dev[1] = 0; - - if (params()->disks.size() > 3) - panic("IDE controllers support a maximum of 4 devices attached!\n"); - - for (int i = 0; i < params()->disks.size(); i++) { - disks[i] = params()->disks[i]; - disks[i]->setController(this, dmaInterface); - } -} - -IdeController::~IdeController() -{ - for (int i = 0; i < 4; i++) - if (disks[i]) - delete disks[i]; -} - -//// -// Utility functions -/// - -void -IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, - IdeRegType ®_type) -{ - offset = addr; - - if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) { - offset -= pri_cmd_addr; - reg_type = COMMAND_BLOCK; - channel = PRIMARY; - } else if (addr >= pri_ctrl_addr && - addr < (pri_ctrl_addr + pri_ctrl_size)) { - offset -= pri_ctrl_addr; - reg_type = CONTROL_BLOCK; - channel = PRIMARY; - } else if (addr >= sec_cmd_addr && - addr < (sec_cmd_addr + sec_cmd_size)) { - offset -= sec_cmd_addr; - reg_type = COMMAND_BLOCK; - channel = SECONDARY; - } else if (addr >= sec_ctrl_addr && - addr < (sec_ctrl_addr + sec_ctrl_size)) { - offset -= sec_ctrl_addr; - reg_type = CONTROL_BLOCK; - channel = SECONDARY; - } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) { - offset -= bmi_addr; - reg_type = BMI_BLOCK; - channel = (offset < BMIC1) ? PRIMARY : SECONDARY; - } else { - panic("IDE controller access to invalid address: %#x\n", addr); - } -} - -int -IdeController::getDisk(IdeChannel channel) -{ - int disk = 0; - uint8_t *devBit = &dev[0]; - - if (channel == SECONDARY) { - disk += 2; - devBit = &dev[1]; - } - - disk += *devBit; - - assert(*devBit == 0 || *devBit == 1); - - return disk; -} - -int -IdeController::getDisk(IdeDisk *diskPtr) -{ - for (int i = 0; i < 4; i++) { - if ((long)diskPtr == (long)disks[i]) - return i; - } - return -1; -} - -bool -IdeController::isDiskSelected(IdeDisk *diskPtr) -{ - for (int i = 0; i < 4; i++) { - if ((long)diskPtr == (long)disks[i]) { - // is disk is on primary or secondary channel - int channel = i/2; - // is disk the master or slave - int devID = i%2; - - return (dev[channel] == devID); - } - } - panic("Unable to find disk by pointer!!\n"); -} - -//// -// Command completion -//// - -void -IdeController::setDmaComplete(IdeDisk *disk) -{ - int diskNum = getDisk(disk); - - if (diskNum < 0) - panic("Unable to find disk based on pointer %#x\n", disk); - - if (diskNum < 2) { - // clear the start/stop bit in the command register - bmi_regs.bmic0 &= ~SSBM; - // clear the bus master active bit in the status register - bmi_regs.bmis0 &= ~BMIDEA; - // set the interrupt bit - bmi_regs.bmis0 |= IDEINTS; - } else { - // clear the start/stop bit in the command register - bmi_regs.bmic1 &= ~SSBM; - // clear the bus master active bit in the status register - bmi_regs.bmis1 &= ~BMIDEA; - // set the interrupt bit - bmi_regs.bmis1 |= IDEINTS; - } -} - -//// -// Bus timing and bus access functions -//// - -Tick -IdeController::cacheAccess(MemReqPtr &req) -{ - // @todo Add more accurate timing to cache access - return curTick + pioLatency; -} - -//// -// Read and write handling -//// - -void -IdeController::readConfig(int offset, int size, uint8_t *data) -{ - int config_offset; - - if (offset < PCI_DEVICE_SPECIFIC) { - PciDev::readConfig(offset, size, data); - } else if (offset >= IDE_CTRL_CONF_START && - (offset + size) <= IDE_CTRL_CONF_END) { - - config_offset = offset - IDE_CTRL_CONF_START; - - switch (size) { - case sizeof(uint8_t): - *data = config_regs.data[config_offset]; - break; - case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset]; - break; - case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset]; - break; - default: - panic("Invalid PCI configuration read size!\n"); - } - - - - } else { - panic("Read of unimplemented PCI config. register: %x\n", offset); - } - switch (size) { - case sizeof(uint8_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, (uint32_t)*data); - break; - case sizeof(uint16_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, *(uint16_t*)data); - break; - case sizeof(uint32_t): - DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", - offset, size, *(uint32_t*)data); - break; - default: - panic("Invalid PCI configuration read size!\n"); - } - -} - -void -IdeController::writeConfig(int offset, int size, const uint8_t *data) -{ - int config_offset; - - if (offset < PCI_DEVICE_SPECIFIC) { - PciDev::writeConfig(offset, size, data); - } else if (offset >= IDE_CTRL_CONF_START && - (offset + size) <= IDE_CTRL_CONF_END) { - - config_offset = offset - IDE_CTRL_CONF_START; - - switch(size) { - case sizeof(uint8_t): - config_regs.data[config_offset] = *data; - break; - case sizeof(uint16_t): - *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data; - break; - case sizeof(uint32_t): - *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data; - break; - default: - panic("Invalid PCI configuration write size!\n"); - } - } else { - panic("Write of unimplemented PCI config. register: %x\n", offset); - } - - switch(size) { - case sizeof(uint8_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, (uint32_t)*data); - break; - case sizeof(uint16_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, *(uint16_t*)data); - break; - case sizeof(uint32_t): - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n", - offset, size, *(uint32_t*)data); - break; - default: - panic("Invalid PCI configuration write size!\n"); - } - - // Catch the writes to specific PCI registers that have side affects - // (like updating the PIO ranges) - switch (offset) { - case PCI_COMMAND: - if (letoh(config.command) & PCI_CMD_IOSE) - io_enabled = true; - else - io_enabled = false; - - if (letoh(config.command) & PCI_CMD_BME) - bm_enabled = true; - else - bm_enabled = false; - break; - - case PCI0_BASE_ADDR0: - if (BARAddrs[0] != 0) { - pri_cmd_addr = BARAddrs[0]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(pri_cmd_addr, - pri_cmd_size)); - - pri_cmd_addr &= EV5::PAddrUncachedMask; - } - break; - - case PCI0_BASE_ADDR1: - if (BARAddrs[1] != 0) { - pri_ctrl_addr = BARAddrs[1]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, - pri_ctrl_size)); - - pri_ctrl_addr &= EV5::PAddrUncachedMask; - } - break; - - case PCI0_BASE_ADDR2: - if (BARAddrs[2] != 0) { - sec_cmd_addr = BARAddrs[2]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(sec_cmd_addr, - sec_cmd_size)); - - sec_cmd_addr &= EV5::PAddrUncachedMask; - } - break; - - case PCI0_BASE_ADDR3: - if (BARAddrs[3] != 0) { - sec_ctrl_addr = BARAddrs[3]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, - sec_ctrl_size)); - - sec_ctrl_addr &= EV5::PAddrUncachedMask; - } - break; - - case PCI0_BASE_ADDR4: - if (BARAddrs[4] != 0) { - bmi_addr = BARAddrs[4]; - if (pioInterface) - pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size)); - - bmi_addr &= EV5::PAddrUncachedMask; - } - break; - } -} - -Fault -IdeController::read(MemReqPtr &req, uint8_t *data) -{ - Addr offset; - IdeChannel channel; - IdeRegType reg_type; - int disk; - - parseAddr(req->paddr, offset, channel, reg_type); - - if (!io_enabled) - return NoFault; - - switch (reg_type) { - case BMI_BLOCK: - switch (req->size) { - case sizeof(uint8_t): - *data = bmi_regs.data[offset]; - break; - case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset]; - break; - case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset]; - break; - default: - panic("IDE read of BMI reg invalid size: %#x\n", req->size); - } - break; - - case COMMAND_BLOCK: - case CONTROL_BLOCK: - disk = getDisk(channel); - - if (disks[disk] == NULL) - break; - - switch (offset) { - case DATA_OFFSET: - switch (req->size) { - case sizeof(uint16_t): - disks[disk]->read(offset, reg_type, data); - break; - - case sizeof(uint32_t): - disks[disk]->read(offset, reg_type, data); - disks[disk]->read(offset, reg_type, &data[2]); - break; - - default: - panic("IDE read of data reg invalid size: %#x\n", req->size); - } - break; - default: - if (req->size == sizeof(uint8_t)) { - disks[disk]->read(offset, reg_type, data); - } else - panic("IDE read of command reg of invalid size: %#x\n", req->size); - } - break; - default: - panic("IDE controller read of unknown register block type!\n"); - } - - if (req->size == 1) - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, (uint32_t)*data); - else if (req->size == 2) - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint16_t*)data); - else - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint32_t*)data); - - return NoFault; -} - -Fault -IdeController::write(MemReqPtr &req, const uint8_t *data) -{ - Addr offset; - IdeChannel channel; - IdeRegType reg_type; - int disk; - uint8_t oldVal, newVal; - - parseAddr(req->paddr, offset, channel, reg_type); - - if (!io_enabled) - return NoFault; - - switch (reg_type) { - case BMI_BLOCK: - if (!bm_enabled) - return NoFault; - - switch (offset) { - // Bus master IDE command register - case BMIC1: - case BMIC0: - if (req->size != sizeof(uint8_t)) - panic("Invalid BMIC write size: %x\n", req->size); - - // select the current disk based on DEV bit - disk = getDisk(channel); - - oldVal = bmi_regs.chan[channel].bmic; - newVal = *data; - - // if a DMA transfer is in progress, R/W control cannot change - if (oldVal & SSBM) { - if ((oldVal & RWCON) ^ (newVal & RWCON)) { - (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; - } - } - - // see if the start/stop bit is being changed - if ((oldVal & SSBM) ^ (newVal & SSBM)) { - if (oldVal & SSBM) { - // stopping DMA transfer - DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); - - // clear the BMIDEA bit - bmi_regs.chan[channel].bmis = - bmi_regs.chan[channel].bmis & ~BMIDEA; - - if (disks[disk] == NULL) - panic("DMA stop for disk %d which does not exist\n", - disk); - - // inform the disk of the DMA transfer abort - disks[disk]->abortDma(); - } else { - // starting DMA transfer - DPRINTF(IdeCtrl, "Starting DMA transfer\n"); - - // set the BMIDEA bit - bmi_regs.chan[channel].bmis = - bmi_regs.chan[channel].bmis | BMIDEA; - - if (disks[disk] == NULL) - panic("DMA start for disk %d which does not exist\n", - disk); - - // inform the disk of the DMA transfer start - disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp)); - } - } - - // update the register value - bmi_regs.chan[channel].bmic = newVal; - break; - - // Bus master IDE status register - case BMIS0: - case BMIS1: - if (req->size != sizeof(uint8_t)) - panic("Invalid BMIS write size: %x\n", req->size); - - oldVal = bmi_regs.chan[channel].bmis; - newVal = *data; - - // the BMIDEA bit is RO - newVal |= (oldVal & BMIDEA); - - // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each - if ((oldVal & IDEINTS) && (newVal & IDEINTS)) - newVal &= ~IDEINTS; // clear the interrupt? - else - (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; - - if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) - newVal &= ~IDEDMAE; - else - (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; - - bmi_regs.chan[channel].bmis = newVal; - break; - - // Bus master IDE descriptor table pointer register - case BMIDTP0: - case BMIDTP1: - { - if (req->size != sizeof(uint32_t)) - panic("Invalid BMIDTP write size: %x\n", req->size); - - uint32_t host_data = letoh(*(uint32_t*)data); - host_data &= ~0x3; - bmi_regs.chan[channel].bmidtp = htole(host_data); - } - break; - - default: - if (req->size != sizeof(uint8_t) && - req->size != sizeof(uint16_t) && - req->size != sizeof(uint32_t)) - panic("IDE controller write of invalid write size: %x\n", - req->size); - - // do a default copy of data into the registers - memcpy(&bmi_regs.data[offset], data, req->size); - } - break; - case COMMAND_BLOCK: - if (offset == IDE_SELECT_OFFSET) { - uint8_t *devBit = &dev[channel]; - *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0; - } - // fall-through ok! - case CONTROL_BLOCK: - disk = getDisk(channel); - - if (disks[disk] == NULL) - break; - - switch (offset) { - case DATA_OFFSET: - switch (req->size) { - case sizeof(uint16_t): - disks[disk]->write(offset, reg_type, data); - break; - - case sizeof(uint32_t): - disks[disk]->write(offset, reg_type, data); - disks[disk]->write(offset, reg_type, &data[2]); - break; - default: - panic("IDE write of data reg invalid size: %#x\n", req->size); - } - break; - default: - if (req->size == sizeof(uint8_t)) { - disks[disk]->write(offset, reg_type, data); - } else - panic("IDE write of command reg of invalid size: %#x\n", req->size); - } - break; - default: - panic("IDE controller write of unknown register block type!\n"); - } - if (req->size == 1) - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, (uint32_t)*data); - else if (req->size == 2) - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint16_t*)data); - else - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, *(uint32_t*)data); - - return NoFault; -} - -//// -// Serialization -//// - -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); - SERIALIZE_SCALAR(pri_ctrl_addr); - SERIALIZE_SCALAR(pri_ctrl_size); - SERIALIZE_SCALAR(sec_cmd_addr); - SERIALIZE_SCALAR(sec_cmd_size); - SERIALIZE_SCALAR(sec_ctrl_addr); - SERIALIZE_SCALAR(sec_ctrl_size); - SERIALIZE_SCALAR(bmi_addr); - SERIALIZE_SCALAR(bmi_size); - - // Serialize registers - SERIALIZE_ARRAY(bmi_regs.data, - sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); - SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); - SERIALIZE_ARRAY(config_regs.data, - sizeof(config_regs.data) / sizeof(config_regs.data[0])); - - // Serialize internal state - SERIALIZE_SCALAR(io_enabled); - SERIALIZE_SCALAR(bm_enabled); - SERIALIZE_ARRAY(cmd_in_progress, - sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); -} - -void -IdeController::unserialize(Checkpoint *cp, const std::string §ion) -{ - // Unserialize the PciDev base class - PciDev::unserialize(cp, section); - - // Unserialize register addresses and sizes - UNSERIALIZE_SCALAR(pri_cmd_addr); - UNSERIALIZE_SCALAR(pri_cmd_size); - UNSERIALIZE_SCALAR(pri_ctrl_addr); - UNSERIALIZE_SCALAR(pri_ctrl_size); - UNSERIALIZE_SCALAR(sec_cmd_addr); - UNSERIALIZE_SCALAR(sec_cmd_size); - UNSERIALIZE_SCALAR(sec_ctrl_addr); - UNSERIALIZE_SCALAR(sec_ctrl_size); - UNSERIALIZE_SCALAR(bmi_addr); - UNSERIALIZE_SCALAR(bmi_size); - - // Unserialize registers - UNSERIALIZE_ARRAY(bmi_regs.data, - sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); - UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); - UNSERIALIZE_ARRAY(config_regs.data, - sizeof(config_regs.data) / sizeof(config_regs.data[0])); - - // Unserialize internal state - UNSERIALIZE_SCALAR(io_enabled); - UNSERIALIZE_SCALAR(bm_enabled); - UNSERIALIZE_ARRAY(cmd_in_progress, - sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); - - if (pioInterface) { - pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size)); - pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size)); - pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size)); - pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size)); - pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size)); - } -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) - - Param<Addr> addr; - SimObjectVectorParam<IdeDisk *> disks; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<PciConfigAll *> configspace; - SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; - Param<uint32_t> pci_bus; - Param<uint32_t> pci_dev; - Param<uint32_t> pci_func; - SimObjectParam<Bus *> pio_bus; - SimObjectParam<Bus *> dma_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - -END_DECLARE_SIM_OBJECT_PARAMS(IdeController) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) - - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(disks, "IDE disks attached to this controller"), - INIT_PARAM(mmu, "Memory controller"), - INIT_PARAM(configspace, "PCI Configspace"), - INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform pointer"), - INIT_PARAM(pci_bus, "PCI bus ID"), - INIT_PARAM(pci_dev, "PCI device number"), - INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) - -END_INIT_SIM_OBJECT_PARAMS(IdeController) - -CREATE_SIM_OBJECT(IdeController) -{ - IdeController::Params *params = new IdeController::Params; - params->name = getInstanceName(); - params->mmu = mmu; - params->configSpace = configspace; - params->configData = configdata; - params->plat = platform; - params->busNum = pci_bus; - params->deviceNum = pci_dev; - params->functionNum = pci_func; - - params->disks = disks; - params->pio_bus = pio_bus; - params->dma_bus = dma_bus; - params->pio_latency = pio_latency; - params->hier = hier; - return new IdeController(params); -} - -REGISTER_SIM_OBJECT("IdeController", IdeController) - -#endif //DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh deleted file mode 100644 index 0fbaf9207..000000000 --- a/dev/ide_ctrl.hh +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Simple PCI IDE controller with bus mastering capability and UDMA - * modeled after controller in the Intel PIIX4 chip - */ - -#ifndef __IDE_CTRL_HH__ -#define __IDE_CTRL_HH__ - -#include "dev/pcidev.hh" -#include "dev/pcireg.h" -#include "dev/io_device.hh" - -#define BMIC0 0x0 // Bus master IDE command register -#define BMIS0 0x2 // Bus master IDE status register -#define BMIDTP0 0x4 // Bus master IDE descriptor table pointer register -#define BMIC1 0x8 // Bus master IDE command register -#define BMIS1 0xa // Bus master IDE status register -#define BMIDTP1 0xc // Bus master IDE descriptor table pointer register - -// Bus master IDE command register bit fields -#define RWCON 0x08 // Bus master read/write control -#define SSBM 0x01 // Start/stop bus master - -// Bus master IDE status register bit fields -#define DMA1CAP 0x40 // Drive 1 DMA capable -#define DMA0CAP 0x20 // Drive 0 DMA capable -#define IDEINTS 0x04 // IDE Interrupt Status -#define IDEDMAE 0x02 // IDE DMA error -#define BMIDEA 0x01 // Bus master IDE active - -// IDE Command byte fields -#define IDE_SELECT_OFFSET (6) -#define IDE_SELECT_DEV_BIT 0x10 - -#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET -#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET - -// IDE Timing Register bit fields -#define IDETIM_DECODE_EN 0x8000 - -// PCI device specific register byte offsets -#define IDE_CTRL_CONF_START 0x40 -#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs)) - - -enum IdeRegType { - COMMAND_BLOCK, - CONTROL_BLOCK, - BMI_BLOCK -}; - -class BaseInterface; -class Bus; -class HierParams; -class IdeDisk; -class IntrControl; -class PciConfigAll; -class PhysicalMemory; -class Platform; - -/** - * Device model for an Intel PIIX4 IDE controller - */ - -class IdeController : public PciDev -{ - friend class IdeDisk; - - enum IdeChannel { - PRIMARY = 0, - SECONDARY = 1 - }; - - private: - /** Primary command block registers */ - Addr pri_cmd_addr; - Addr pri_cmd_size; - /** Primary control block registers */ - Addr pri_ctrl_addr; - Addr pri_ctrl_size; - /** Secondary command block registers */ - Addr sec_cmd_addr; - Addr sec_cmd_size; - /** Secondary control block registers */ - Addr sec_ctrl_addr; - Addr sec_ctrl_size; - /** Bus master interface (BMI) registers */ - Addr bmi_addr; - Addr bmi_size; - - private: - /** Registers used for bus master interface */ - union { - uint8_t data[16]; - - struct { - uint8_t bmic0; - uint8_t reserved_0; - uint8_t bmis0; - uint8_t reserved_1; - uint32_t bmidtp0; - uint8_t bmic1; - uint8_t reserved_2; - uint8_t bmis1; - uint8_t reserved_3; - uint32_t bmidtp1; - }; - - struct { - uint8_t bmic; - uint8_t reserved_4; - uint8_t bmis; - uint8_t reserved_5; - uint32_t bmidtp; - } chan[2]; - - } bmi_regs; - /** Shadows of the device select bit */ - uint8_t dev[2]; - /** Registers used in device specific PCI configuration */ - union { - uint8_t data[22]; - - struct { - uint16_t idetim0; - uint16_t idetim1; - uint8_t sidetim; - uint8_t reserved_0[3]; - uint8_t udmactl; - uint8_t reserved_1; - uint16_t udmatim; - uint8_t reserved_2[8]; - uint16_t ideconfig; - }; - } config_regs; - - // Internal management variables - bool io_enabled; - bool bm_enabled; - bool cmd_in_progress[4]; - - private: - /** IDE disks connected to controller */ - IdeDisk *disks[4]; - - private: - /** Parse the access address to pass on to device */ - void parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, - IdeRegType ®_type); - - /** Select the disk based on the channel and device bit */ - int getDisk(IdeChannel channel); - - /** Select the disk based on a pointer */ - int getDisk(IdeDisk *diskPtr); - - public: - /** See if a disk is selected based on its pointer */ - bool isDiskSelected(IdeDisk *diskPtr); - - public: - struct Params : public PciDev::Params - { - /** Array of disk objects */ - std::vector<IdeDisk *> disks; - Bus *pio_bus; - Bus *dma_bus; - Tick pio_latency; - HierParams *hier; - }; - const Params *params() const { return (const Params *)_params; } - - public: - IdeController(Params *p); - ~IdeController(); - - virtual void writeConfig(int offset, int size, const uint8_t *data); - virtual void readConfig(int offset, int size, uint8_t *data); - - void setDmaComplete(IdeDisk *disk); - - /** - * Read a done field for a given target. - * @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 the mmapped I/O control registers. - * @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 §ion); - - /** - * 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 deleted file mode 100644 index c13556ed6..000000000 --- a/dev/ide_disk.cc +++ /dev/null @@ -1,1286 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Device model implementation for an IDE disk - */ - -#include <cerrno> -#include <cstring> -#include <deque> -#include <string> - -#include "base/cprintf.hh" // csprintf -#include "base/trace.hh" -#include "dev/disk_image.hh" -#include "dev/ide_disk.hh" -#include "dev/ide_ctrl.hh" -#include "dev/tsunami.hh" -#include "dev/tsunami_pchip.hh" -#include "mem/functional/physical.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "sim/builder.hh" -#include "sim/sim_object.hh" -#include "sim/root.hh" -#include "arch/isa_traits.hh" - -using namespace std; -using namespace TheISA; - -IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, - int id, Tick delay) - : SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay), - dmaTransferEvent(this), dmaReadWaitEvent(this), - dmaWriteWaitEvent(this), dmaPrdReadEvent(this), - dmaReadEvent(this), dmaWriteEvent(this) -{ - // Reset the device state - reset(id); - - // fill out the drive ID structure - memset(&driveID, 0, sizeof(struct ataparams)); - - // Calculate LBA and C/H/S values - uint16_t cylinders; - uint8_t heads; - uint8_t sectors; - - uint32_t lba_size = image->size(); - if (lba_size >= 16383*16*63) { - cylinders = 16383; - heads = 16; - sectors = 63; - } else { - if (lba_size >= 63) - sectors = 63; - else - sectors = lba_size; - - if ((lba_size / sectors) >= 16) - heads = 16; - else - heads = (lba_size / sectors); - - cylinders = lba_size / (heads * sectors); - } - - // Setup the model name - strncpy((char *)driveID.atap_model, "5MI EDD si k", - sizeof(driveID.atap_model)); - // Set the maximum multisector transfer size - driveID.atap_multi = MAX_MULTSECT; - // IORDY supported, IORDY disabled, LBA enabled, DMA enabled - driveID.atap_capabilities1 = 0x7; - // UDMA support, EIDE support - driveID.atap_extensions = 0x6; - // Setup default C/H/S settings - driveID.atap_cylinders = cylinders; - driveID.atap_sectors = sectors; - driveID.atap_heads = heads; - // Setup the current multisector transfer size - driveID.atap_curmulti = MAX_MULTSECT; - driveID.atap_curmulti_valid = 0x1; - // Number of sectors on disk - driveID.atap_capacity = lba_size; - // Multiword DMA mode 2 and below supported - driveID.atap_dmamode_supp = 0x400; - // Set PIO mode 4 and 3 supported - driveID.atap_piomode_supp = 0x3; - // Set DMA mode 4 and below supported - driveID.atap_udmamode_supp = 0x1f; - // Statically set hardware config word - driveID.atap_hwreset_res = 0x4001; - - //arbitrary for now... - driveID.atap_ata_major = WDC_VER_ATA7; -} - -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; - - if (id == DEV0) { - devState = Device_Idle_S; - devID = DEV0; - } else if (id == DEV1) { - devState = Device_Idle_NS; - devID = DEV1; - } else { - panic("Invalid device ID: %#x\n", id); - } - - // set the device ready bit - status = STATUS_DRDY_BIT; - - /* The error register must be set to 0x1 on start-up to - indicate that no diagnostic error was detected */ - cmdReg.error = 0x1; -} - -//// -// Utility functions -//// - -bool -IdeDisk::isDEVSelect() -{ - return ctrl->isDiskSelected(this); -} - -Addr -IdeDisk::pciToDma(Addr pciAddr) -{ - if (ctrl) - return ctrl->plat->pciToDma(pciAddr); - else - panic("Access to unset controller!\n"); -} - -uint32_t -IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft) -{ - uint32_t bytesInPage = 0; - - // First calculate how many bytes could be in the page - if (bytesLeft > TheISA::PageBytes) - bytesInPage = TheISA::PageBytes; - else - bytesInPage = bytesLeft; - - // Next, see if we have crossed a page boundary, and adjust - Addr upperBound = curAddr + bytesInPage; - Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes; - - assert(upperBound >= curAddr && "DMA read wraps around address space!\n"); - - if (upperBound >= pageBound) - bytesInPage = pageBound - curAddr; - - return bytesInPage; -} - -//// -// Device registers read/write -//// - -void -IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data) -{ - DevAction_t action = ACT_NONE; - - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - // Data transfers occur two bytes at a time - case DATA_OFFSET: - *(uint16_t*)data = cmdReg.data; - action = ACT_DATA_READ_SHORT; - break; - case ERROR_OFFSET: - *data = cmdReg.error; - break; - case NSECTOR_OFFSET: - *data = cmdReg.sec_count; - break; - case SECTOR_OFFSET: - *data = cmdReg.sec_num; - break; - case LCYL_OFFSET: - *data = cmdReg.cyl_low; - break; - case HCYL_OFFSET: - *data = cmdReg.cyl_high; - break; - case DRIVE_OFFSET: - *data = cmdReg.drive; - break; - case STATUS_OFFSET: - *data = status; - action = ACT_STAT_READ; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); - } - break; - case CONTROL_BLOCK: - if (offset == ALTSTAT_OFFSET) - *data = status; - else - panic("Invalid IDE control register offset: %#x\n", offset); - break; - default: - panic("Unknown register block!\n"); - } - - if (action != ACT_NONE) - updateState(action); -} - -void -IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data) -{ - DevAction_t action = ACT_NONE; - - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - case DATA_OFFSET: - cmdReg.data = *(uint16_t*)data; - action = ACT_DATA_WRITE_SHORT; - break; - case FEATURES_OFFSET: - break; - case NSECTOR_OFFSET: - cmdReg.sec_count = *data; - break; - case SECTOR_OFFSET: - cmdReg.sec_num = *data; - break; - case LCYL_OFFSET: - cmdReg.cyl_low = *data; - break; - case HCYL_OFFSET: - cmdReg.cyl_high = *data; - break; - case DRIVE_OFFSET: - cmdReg.drive = *data; - action = ACT_SELECT_WRITE; - break; - case COMMAND_OFFSET: - cmdReg.command = *data; - action = ACT_CMD_WRITE; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); - } - break; - case CONTROL_BLOCK: - if (offset == CONTROL_OFFSET) { - 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; - } - else - panic("Invalid IDE control register offset: %#x\n", offset); - break; - default: - panic("Unknown register block!\n"); - } - - if (action != ACT_NONE) - updateState(action); -} - -//// -// Perform DMA transactions -//// - -void -IdeDisk::doDmaTransfer() -{ - if (dmaState != Dma_Transfer || devState != Transfer_Data_Dma) - panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n", - dmaState, devState); - - // first read the current PRD - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - dmaInterface->doDMA(Read, curPrdAddr, sizeof(PrdEntry_t), curTick, - &dmaPrdReadEvent); - } else { - dmaPrdReadDone(); - } -} - -void -IdeDisk::dmaPrdReadDone() -{ - // actually copy the PRD from physical memory - memcpy((void *)&curPrd.entry, - physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)), - 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); - - // the prd pointer has already been translated, so just do an increment - curPrdAddr = curPrdAddr + sizeof(PrdEntry_t); - - if (dmaRead) - doDmaRead(); - else - doDmaWrite(); -} - -void -IdeDisk::regStats() -{ - using namespace Stats; - dmaReadFullPages - .name(name() + ".dma_read_full_pages") - .desc("Number of full page size DMA reads (not PRD).") - ; - dmaReadBytes - .name(name() + ".dma_read_bytes") - .desc("Number of bytes transfered via DMA reads (not PRD).") - ; - dmaReadTxs - .name(name() + ".dma_read_txs") - .desc("Number of DMA read transactions (not PRD).") - ; - - dmaWriteFullPages - .name(name() + ".dma_write_full_pages") - .desc("Number of full page size DMA writes.") - ; - dmaWriteBytes - .name(name() + ".dma_write_bytes") - .desc("Number of bytes transfered via DMA writes.") - ; - dmaWriteTxs - .name(name() + ".dma_write_txs") - .desc("Number of DMA write transactions.") - ; -} - -void -IdeDisk::doDmaRead() -{ - /** @todo we need to figure out what the delay actually will be */ - Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); - - DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n", - diskDelay, totalDiskDelay); - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); - - uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(), - (uint32_t)curPrd.getByteCount()); - - dmaInterfaceBytes = bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaReadFullPages++; - dmaReadBytes += bytesInPage; - dmaReadTxs++; - dmaInterface->doDMA(Read, dmaAddr, bytesInPage, - curTick + totalDiskDelay, &dmaReadEvent); - } else { - // schedule dmaReadEvent with sectorDelay (dmaReadDone) - dmaReadEvent.schedule(curTick + totalDiskDelay); - } -} - -void -IdeDisk::dmaReadDone() -{ - - Addr curAddr = 0, dmaAddr = 0; - uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0; - - // continue to use the DMA interface until all pages are read - if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) { - // see if the interface is busy - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaReadEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes; - curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes; - dmaAddr = pciToDma(curAddr); - - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); - dmaInterfaceBytes += bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaReadFullPages++; - dmaReadBytes += bytesInPage; - dmaReadTxs++; - - dmaInterface->doDMA(Read, dmaAddr, bytesInPage, - curTick, &dmaReadEvent); - - return; - } - - // set initial address - curAddr = curPrd.getBaseAddr(); - - // clear out the data buffer - memset(dataBuffer, 0, MAX_DMA_SIZE); - - // read the data from memory via DMA into a data buffer - while (bytesWritten < curPrd.getByteCount()) { - if (cmdBytesLeft <= 0) - panic("DMA data is larger than # of sectors specified\n"); - - dmaAddr = pciToDma(curAddr); - - // calculate how many bytes are in the current page - bytesLeft = curPrd.getByteCount() - bytesWritten; - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); - - // copy the data from memory into the data buffer - memcpy((void *)(dataBuffer + bytesWritten), - physmem->dma_addr(dmaAddr, bytesInPage), - bytesInPage); - - curAddr += bytesInPage; - bytesWritten += bytesInPage; - cmdBytesLeft -= bytesInPage; - } - - // write the data to the disk image - for (bytesWritten = 0; - bytesWritten < curPrd.getByteCount(); - bytesWritten += SectorSize) { - - writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); - } - - // check for the EOT - if (curPrd.getEOT()) { - assert(cmdBytesLeft == 0); - dmaState = Dma_Idle; - updateState(ACT_DMA_DONE); - } else { - doDmaTransfer(); - } -} - -void -IdeDisk::doDmaWrite() -{ - /** @todo we need to figure out what the delay actually will be */ - Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); - - DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n", - diskDelay, totalDiskDelay); - - if (dmaInterface) { - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); - - uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(), - (uint32_t)curPrd.getByteCount()); - - dmaInterfaceBytes = bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaWriteFullPages++; - dmaWriteBytes += bytesInPage; - dmaWriteTxs++; - - dmaInterface->doDMA(WriteInvalidate, dmaAddr, - bytesInPage, curTick + totalDiskDelay, - &dmaWriteEvent); - } else { - // schedule event with disk delay (dmaWriteDone) - dmaWriteEvent.schedule(curTick + totalDiskDelay); - } -} - -void -IdeDisk::dmaWriteDone() -{ - Addr curAddr = 0, pageAddr = 0, dmaAddr = 0; - uint32_t bytesRead = 0, bytesInPage = 0; - - // continue to use the DMA interface until all pages are read - if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) { - // see if the interface is busy - if (dmaInterface->busy()) { - // reschedule after waiting period - dmaWriteEvent.schedule(curTick + DMA_BACKOFF_PERIOD); - return; - } - - uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes; - curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes; - dmaAddr = pciToDma(curAddr); - - bytesInPage = bytesInDmaPage(curAddr, bytesLeft); - dmaInterfaceBytes += bytesInPage; - - if (bytesInPage == TheISA::VMPageSize) - dmaWriteFullPages++; - dmaWriteBytes += bytesInPage; - dmaWriteTxs++; - - dmaInterface->doDMA(WriteInvalidate, dmaAddr, - bytesInPage, curTick, - &dmaWriteEvent); - - return; - } - - // setup the initial page and DMA address - curAddr = curPrd.getBaseAddr(); - pageAddr = TheISA::TruncPage(curAddr); - dmaAddr = pciToDma(curAddr); - - // clear out the data buffer - memset(dataBuffer, 0, MAX_DMA_SIZE); - - while (bytesRead < curPrd.getByteCount()) { - // see if we have crossed into a new page - if (pageAddr != TheISA::TruncPage(curAddr)) { - // write the data to memory - memcpy(physmem->dma_addr(dmaAddr, bytesInPage), - (void *)(dataBuffer + (bytesRead - bytesInPage)), - bytesInPage); - - // update the DMA address and page address - pageAddr = TheISA::TruncPage(curAddr); - dmaAddr = pciToDma(curAddr); - - bytesInPage = 0; - } - - if (cmdBytesLeft <= 0) - panic("DMA requested data is larger than # sectors specified\n"); - - readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead)); - - curAddr += SectorSize; - bytesRead += SectorSize; - bytesInPage += SectorSize; - cmdBytesLeft -= SectorSize; - } - - // write the last page worth read to memory - if (bytesInPage != 0) { - memcpy(physmem->dma_addr(dmaAddr, bytesInPage), - (void *)(dataBuffer + (bytesRead - bytesInPage)), - bytesInPage); - } - - // check for the EOT - if (curPrd.getEOT()) { - assert(cmdBytesLeft == 0); - dmaState = Dma_Idle; - updateState(ACT_DMA_DONE); - } else { - doDmaTransfer(); - } -} - -//// -// Disk utility routines -/// - -void -IdeDisk::readDisk(uint32_t sector, uint8_t *data) -{ - uint32_t bytesRead = image->read(data, sector); - - if (bytesRead != SectorSize) - panic("Can't read from %s. Only %d of %d read. errno=%d\n", - name(), bytesRead, SectorSize, errno); -} - -void -IdeDisk::writeDisk(uint32_t sector, uint8_t *data) -{ - uint32_t bytesWritten = image->write(data, sector); - - if (bytesWritten != SectorSize) - panic("Can't write to %s. Only %d of %d written. errno=%d\n", - name(), bytesWritten, SectorSize, errno); -} - -//// -// Setup and handle commands -//// - -void -IdeDisk::startDma(const uint32_t &prdTableBase) -{ - if (dmaState != Dma_Start) - panic("Inconsistent DMA state, should be in Dma_Start!\n"); - - if (devState != Transfer_Data_Dma) - panic("Inconsistent device state for DMA start!\n"); - - // PRD base address is given by bits 31:2 - curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3))); - - dmaState = Dma_Transfer; - - // schedule dma transfer (doDmaTransfer) - dmaTransferEvent.schedule(curTick + 1); -} - -void -IdeDisk::abortDma() -{ - if (dmaState == Dma_Idle) - panic("Inconsistent DMA state, should be Start or Transfer!"); - - if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma) - panic("Inconsistent device state, should be Transfer or Prepare!\n"); - - updateState(ACT_CMD_ERROR); -} - -void -IdeDisk::startCommand() -{ - DevAction_t action = ACT_NONE; - uint32_t size = 0; - dmaRead = false; - - // Decode commands - switch (cmdReg.command) { - // Supported non-data commands - case WDSF_READ_NATIVE_MAX: - size = image->size() - 1; - cmdReg.sec_num = (size & 0xff); - cmdReg.cyl_low = ((size & 0xff00) >> 8); - cmdReg.cyl_high = ((size & 0xff0000) >> 16); - cmdReg.head = ((size & 0xf000000) >> 24); - - devState = Command_Execution; - action = ACT_CMD_COMPLETE; - break; - - case WDCC_RECAL: - case WDCC_IDP: - case WDCC_STANDBY_IMMED: - case WDCC_FLUSHCACHE: - case WDSF_VERIFY: - case WDSF_SEEK: - case SET_FEATURES: - case WDCC_SETMULTI: - devState = Command_Execution; - action = ACT_CMD_COMPLETE; - break; - - // Supported PIO data-in commands - case WDCC_IDENTIFY: - cmdBytes = cmdBytesLeft = sizeof(struct ataparams); - devState = Prepare_Data_In; - action = ACT_DATA_READY; - break; - - case WDCC_READMULTI: - case WDCC_READ: - if (!(cmdReg.drive & DRIVE_LBA_BIT)) - panic("Attempt to perform CHS access, only supports LBA\n"); - - if (cmdReg.sec_count == 0) - cmdBytes = cmdBytesLeft = (256 * SectorSize); - else - cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize); - - curSector = getLBABase(); - - /** @todo make this a scheduled event to simulate disk delay */ - devState = Prepare_Data_In; - action = ACT_DATA_READY; - break; - - // Supported PIO data-out commands - case WDCC_WRITEMULTI: - case WDCC_WRITE: - if (!(cmdReg.drive & DRIVE_LBA_BIT)) - panic("Attempt to perform CHS access, only supports LBA\n"); - - if (cmdReg.sec_count == 0) - cmdBytes = cmdBytesLeft = (256 * SectorSize); - else - cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize); - - curSector = getLBABase(); - - devState = Prepare_Data_Out; - action = ACT_DATA_READY; - break; - - // Supported DMA commands - case WDCC_WRITEDMA: - dmaRead = true; // a write to the disk is a DMA read from memory - case WDCC_READDMA: - if (!(cmdReg.drive & DRIVE_LBA_BIT)) - panic("Attempt to perform CHS access, only supports LBA\n"); - - if (cmdReg.sec_count == 0) - cmdBytes = cmdBytesLeft = (256 * SectorSize); - else - cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize); - - curSector = getLBABase(); - - devState = Prepare_Data_Dma; - action = ACT_DMA_READY; - break; - - default: - panic("Unsupported ATA command: %#x\n", cmdReg.command); - } - - if (action != ACT_NONE) { - // set the BSY bit - status |= STATUS_BSY_BIT; - // clear the DRQ bit - status &= ~STATUS_DRQ_BIT; - // clear the DF bit - status &= ~STATUS_DF_BIT; - - updateState(action); - } -} - -//// -// Handle setting and clearing interrupts -//// - -void -IdeDisk::intrPost() -{ - DPRINTF(IdeDisk, "Posting Interrupt\n"); - if (intrPending) - panic("Attempt to post an interrupt with one pending\n"); - - intrPending = true; - - // talk to controller to set interrupt - if (ctrl) { - ctrl->bmi_regs.bmis0 |= IDEINTS; - ctrl->intrPost(); - } -} - -void -IdeDisk::intrClear() -{ - DPRINTF(IdeDisk, "Clearing Interrupt\n"); - if (!intrPending) - panic("Attempt to clear a non-pending interrupt\n"); - - intrPending = false; - - // talk to controller to clear interrupt - if (ctrl) - ctrl->intrClear(); -} - -//// -// Manage the device internal state machine -//// - -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 (action == ACT_SELECT_WRITE && !isDEVSelect()) { - devState = Device_Idle_NS; - } else if (action == ACT_CMD_WRITE) { - startCommand(); - } - - break; - - case Device_Idle_SI: - if (action == ACT_SELECT_WRITE && !isDEVSelect()) { - devState = Device_Idle_NS; - intrClear(); - } else if (action == ACT_STAT_READ || isIENSet()) { - devState = Device_Idle_S; - intrClear(); - } else if (action == ACT_CMD_WRITE) { - intrClear(); - startCommand(); - } - - break; - - case Device_Idle_NS: - if (action == ACT_SELECT_WRITE && isDEVSelect()) { - if (!isIENSet() && intrPending) { - devState = Device_Idle_SI; - intrPost(); - } - if (isIENSet() || !intrPending) { - devState = Device_Idle_S; - } - } - break; - - case Command_Execution: - if (action == ACT_CMD_COMPLETE) { - // clear the BSY bit - setComplete(); - - if (!isIENSet()) { - devState = Device_Idle_SI; - intrPost(); - } else { - devState = Device_Idle_S; - } - } - break; - - case Prepare_Data_In: - if (action == ACT_CMD_ERROR) { - // clear the BSY bit - setComplete(); - - if (!isIENSet()) { - devState = Device_Idle_SI; - intrPost(); - } else { - devState = Device_Idle_S; - } - } else if (action == ACT_DATA_READY) { - // clear the BSY bit - status &= ~STATUS_BSY_BIT; - // set the DRQ bit - status |= STATUS_DRQ_BIT; - - // copy the data into the data buffer - if (cmdReg.command == WDCC_IDENTIFY) { - // Reset the drqBytes for this block - drqBytesLeft = sizeof(struct ataparams); - - memcpy((void *)dataBuffer, (void *)&driveID, - sizeof(struct ataparams)); - } else { - // Reset the drqBytes for this block - drqBytesLeft = SectorSize; - - readDisk(curSector++, dataBuffer); - } - - // put the first two bytes into the data register - memcpy((void *)&cmdReg.data, (void *)dataBuffer, - sizeof(uint16_t)); - - if (!isIENSet()) { - devState = Data_Ready_INTRQ_In; - intrPost(); - } else { - devState = Transfer_Data_In; - } - } - break; - - case Data_Ready_INTRQ_In: - if (action == ACT_STAT_READ) { - devState = Transfer_Data_In; - intrClear(); - } - break; - - case Transfer_Data_In: - if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) { - if (action == ACT_DATA_READ_BYTE) { - panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n"); - } else { - drqBytesLeft -= 2; - cmdBytesLeft -= 2; - - // copy next short into data registers - if (drqBytesLeft) - memcpy((void *)&cmdReg.data, - (void *)&dataBuffer[SectorSize - drqBytesLeft], - sizeof(uint16_t)); - } - - if (drqBytesLeft == 0) { - if (cmdBytesLeft == 0) { - // Clear the BSY bit - setComplete(); - devState = Device_Idle_S; - } else { - devState = Prepare_Data_In; - // 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); - } - } - } - break; - - case Prepare_Data_Out: - if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) { - // clear the BSY bit - setComplete(); - - if (!isIENSet()) { - devState = Device_Idle_SI; - intrPost(); - } else { - devState = Device_Idle_S; - } - } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) { - // clear the BSY bit - status &= ~STATUS_BSY_BIT; - // set the DRQ bit - status |= STATUS_DRQ_BIT; - - // clear the data buffer to get it ready for writes - memset(dataBuffer, 0, MAX_DMA_SIZE); - - // reset the drqBytes for this block - drqBytesLeft = SectorSize; - - if (cmdBytesLeft == cmdBytes || isIENSet()) { - devState = Transfer_Data_Out; - } else { - devState = Data_Ready_INTRQ_Out; - intrPost(); - } - } - break; - - case Data_Ready_INTRQ_Out: - if (action == ACT_STAT_READ) { - devState = Transfer_Data_Out; - intrClear(); - } - break; - - case Transfer_Data_Out: - if (action == ACT_DATA_WRITE_BYTE || - action == ACT_DATA_WRITE_SHORT) { - - if (action == ACT_DATA_READ_BYTE) { - panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n"); - } else { - // copy the latest short into the data buffer - memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft], - (void *)&cmdReg.data, - sizeof(uint16_t)); - - drqBytesLeft -= 2; - cmdBytesLeft -= 2; - } - - if (drqBytesLeft == 0) { - // copy the block to the disk - writeDisk(curSector++, dataBuffer); - - // set the BSY bit - status |= STATUS_BSY_BIT; - // set the seek bit - status |= STATUS_SEEK_BIT; - // clear the 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; - - case Prepare_Data_Dma: - if (action == ACT_CMD_ERROR) { - // clear the BSY bit - setComplete(); - - if (!isIENSet()) { - devState = Device_Idle_SI; - intrPost(); - } else { - devState = Device_Idle_S; - } - } else if (action == ACT_DMA_READY) { - // clear the BSY bit - status &= ~STATUS_BSY_BIT; - // set the DRQ bit - status |= STATUS_DRQ_BIT; - - devState = Transfer_Data_Dma; - - if (dmaState != Dma_Idle) - panic("Inconsistent DMA state, should be Dma_Idle\n"); - - dmaState = Dma_Start; - // wait for the write to the DMA start bit - } - break; - - case Transfer_Data_Dma: - if (action == ACT_CMD_ERROR || action == ACT_DMA_DONE) { - // clear the BSY bit - setComplete(); - // set the seek bit - status |= STATUS_SEEK_BIT; - // clear the controller state for DMA transfer - ctrl->setDmaComplete(this); - - if (!isIENSet()) { - devState = Device_Idle_SI; - intrPost(); - } else { - devState = Device_Idle_S; - } - } - break; - - default: - panic("Unknown IDE device state: %#x\n", devState); - } -} - -void -IdeDisk::serialize(ostream &os) -{ - // Check all outstanding events to see if they are scheduled - // these are all mutually exclusive - Tick reschedule = 0; - Events_t event = None; - - int eventCount = 0; - - if (dmaTransferEvent.scheduled()) { - reschedule = dmaTransferEvent.when(); - event = Transfer; - eventCount++; - } - if (dmaReadWaitEvent.scheduled()) { - reschedule = dmaReadWaitEvent.when(); - event = ReadWait; - eventCount++; - } - if (dmaWriteWaitEvent.scheduled()) { - reschedule = dmaWriteWaitEvent.when(); - event = WriteWait; - eventCount++; - } - if (dmaPrdReadEvent.scheduled()) { - reschedule = dmaPrdReadEvent.when(); - event = PrdRead; - eventCount++; - } - if (dmaReadEvent.scheduled()) { - reschedule = dmaReadEvent.when(); - event = DmaRead; - eventCount++; - } - if (dmaWriteEvent.scheduled()) { - reschedule = dmaWriteEvent.when(); - event = DmaWrite; - eventCount++; - } - - assert(eventCount <= 1); - - SERIALIZE_SCALAR(reschedule); - SERIALIZE_ENUM(event); - - // Serialize device registers - SERIALIZE_SCALAR(cmdReg.data); - SERIALIZE_SCALAR(cmdReg.sec_count); - SERIALIZE_SCALAR(cmdReg.sec_num); - SERIALIZE_SCALAR(cmdReg.cyl_low); - SERIALIZE_SCALAR(cmdReg.cyl_high); - SERIALIZE_SCALAR(cmdReg.drive); - SERIALIZE_SCALAR(cmdReg.command); - SERIALIZE_SCALAR(status); - SERIALIZE_SCALAR(nIENBit); - SERIALIZE_SCALAR(devID); - - // Serialize the PRD related information - SERIALIZE_SCALAR(curPrd.entry.baseAddr); - SERIALIZE_SCALAR(curPrd.entry.byteCount); - SERIALIZE_SCALAR(curPrd.entry.endOfTable); - SERIALIZE_SCALAR(curPrdAddr); - - // Serialize current transfer related information - SERIALIZE_SCALAR(cmdBytesLeft); - SERIALIZE_SCALAR(cmdBytes); - SERIALIZE_SCALAR(drqBytesLeft); - SERIALIZE_SCALAR(curSector); - SERIALIZE_SCALAR(dmaRead); - SERIALIZE_SCALAR(dmaInterfaceBytes); - SERIALIZE_SCALAR(intrPending); - SERIALIZE_ENUM(devState); - SERIALIZE_ENUM(dmaState); - SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE); -} - -void -IdeDisk::unserialize(Checkpoint *cp, const string §ion) -{ - // Reschedule events that were outstanding - // these are all mutually exclusive - Tick reschedule = 0; - Events_t event = None; - - UNSERIALIZE_SCALAR(reschedule); - UNSERIALIZE_ENUM(event); - - switch (event) { - case None : break; - case Transfer : dmaTransferEvent.schedule(reschedule); break; - case ReadWait : dmaReadWaitEvent.schedule(reschedule); break; - case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break; - case PrdRead : dmaPrdReadEvent.schedule(reschedule); break; - case DmaRead : dmaReadEvent.schedule(reschedule); break; - case DmaWrite : dmaWriteEvent.schedule(reschedule); break; - } - - // Unserialize device registers - UNSERIALIZE_SCALAR(cmdReg.data); - UNSERIALIZE_SCALAR(cmdReg.sec_count); - UNSERIALIZE_SCALAR(cmdReg.sec_num); - UNSERIALIZE_SCALAR(cmdReg.cyl_low); - UNSERIALIZE_SCALAR(cmdReg.cyl_high); - UNSERIALIZE_SCALAR(cmdReg.drive); - UNSERIALIZE_SCALAR(cmdReg.command); - UNSERIALIZE_SCALAR(status); - UNSERIALIZE_SCALAR(nIENBit); - UNSERIALIZE_SCALAR(devID); - - // Unserialize the PRD related information - UNSERIALIZE_SCALAR(curPrd.entry.baseAddr); - UNSERIALIZE_SCALAR(curPrd.entry.byteCount); - UNSERIALIZE_SCALAR(curPrd.entry.endOfTable); - UNSERIALIZE_SCALAR(curPrdAddr); - - // Unserialize current transfer related information - UNSERIALIZE_SCALAR(cmdBytes); - UNSERIALIZE_SCALAR(cmdBytesLeft); - UNSERIALIZE_SCALAR(drqBytesLeft); - UNSERIALIZE_SCALAR(curSector); - UNSERIALIZE_SCALAR(dmaRead); - UNSERIALIZE_SCALAR(dmaInterfaceBytes); - UNSERIALIZE_SCALAR(intrPending); - UNSERIALIZE_ENUM(devState); - UNSERIALIZE_ENUM(dmaState); - UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE); -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -enum DriveID { master, slave }; -static const char *DriveID_strings[] = { "master", "slave" }; -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) - - SimObjectParam<DiskImage *> image; - SimObjectParam<PhysicalMemory *> physmem; - SimpleEnumParam<DriveID> driveID; - Param<int> delay; - -END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk) - - INIT_PARAM(image, "Disk image"), - INIT_PARAM(physmem, "Physical memory"), - INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings), - INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1) - -END_INIT_SIM_OBJECT_PARAMS(IdeDisk) - - -CREATE_SIM_OBJECT(IdeDisk) -{ - return new IdeDisk(getInstanceName(), image, physmem, driveID, delay); -} - -REGISTER_SIM_OBJECT("IdeDisk", IdeDisk) - -#endif //DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh deleted file mode 100644 index 402ae44ee..000000000 --- a/dev/ide_disk.hh +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Device model for an IDE disk - */ - -#ifndef __IDE_DISK_HH__ -#define __IDE_DISK_HH__ - -#include "base/statistics.hh" -#include "dev/disk_image.hh" -#include "dev/ide_atareg.h" -#include "dev/ide_ctrl.hh" -#include "dev/ide_wdcreg.h" -#include "dev/io_device.hh" -#include "sim/eventq.hh" - -#define DMA_BACKOFF_PERIOD 200 - -#define MAX_DMA_SIZE (131072) // 128K -#define MAX_MULTSECT (128) - -#define PRD_BASE_MASK 0xfffffffe -#define PRD_COUNT_MASK 0xfffe -#define PRD_EOT_MASK 0x8000 - -typedef struct PrdEntry { - uint32_t baseAddr; - uint16_t byteCount; - uint16_t endOfTable; -} PrdEntry_t; - -class PrdTableEntry { - public: - PrdEntry_t entry; - - uint32_t getBaseAddr() - { - return (entry.baseAddr & PRD_BASE_MASK); - } - - uint32_t getByteCount() - { - return ((entry.byteCount == 0) ? MAX_DMA_SIZE : - (entry.byteCount & PRD_COUNT_MASK)); - } - - uint16_t getEOT() - { - return (entry.endOfTable & PRD_EOT_MASK); - } -}; - -#define DATA_OFFSET (0) -#define ERROR_OFFSET (1) -#define FEATURES_OFFSET (1) -#define NSECTOR_OFFSET (2) -#define SECTOR_OFFSET (3) -#define LCYL_OFFSET (4) -#define HCYL_OFFSET (5) -#define SELECT_OFFSET (6) -#define DRIVE_OFFSET (6) -#define STATUS_OFFSET (7) -#define COMMAND_OFFSET (7) - -#define CONTROL_OFFSET (2) -#define ALTSTAT_OFFSET (2) - -#define SELECT_DEV_BIT 0x10 -#define CONTROL_RST_BIT 0x04 -#define CONTROL_IEN_BIT 0x02 -#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) -#define DEV1 (1) - -typedef struct CommandReg { - uint16_t data; - uint8_t error; - uint8_t sec_count; - uint8_t sec_num; - uint8_t cyl_low; - uint8_t cyl_high; - union { - uint8_t drive; - uint8_t head; - }; - uint8_t command; -} CommandReg_t; - -typedef enum Events { - None = 0, - Transfer, - ReadWait, - WriteWait, - PrdRead, - DmaRead, - DmaWrite -} Events_t; - -typedef enum DevAction { - ACT_NONE = 0, - ACT_CMD_WRITE, - ACT_CMD_COMPLETE, - ACT_CMD_ERROR, - ACT_SELECT_WRITE, - ACT_STAT_READ, - ACT_DATA_READY, - ACT_DATA_READ_BYTE, - ACT_DATA_READ_SHORT, - ACT_DATA_WRITE_BYTE, - ACT_DATA_WRITE_SHORT, - ACT_DMA_READY, - ACT_DMA_DONE, - ACT_SRST_SET, - ACT_SRST_CLEAR -} DevAction_t; - -typedef enum DevState { - // Device idle - Device_Idle_S = 0, - Device_Idle_SI, - Device_Idle_NS, - - // Software reset - Device_Srst, - - // Non-data commands - Command_Execution, - - // PIO data-in (data to host) - Prepare_Data_In, - Data_Ready_INTRQ_In, - Transfer_Data_In, - - // PIO data-out (data from host) - Prepare_Data_Out, - Data_Ready_INTRQ_Out, - Transfer_Data_Out, - - // DMA protocol - Prepare_Data_Dma, - Transfer_Data_Dma -} DevState_t; - -typedef enum DmaState { - Dma_Idle = 0, - Dma_Start, - Dma_Transfer -} DmaState_t; - -class PhysicalMemory; -class IdeController; - -/** - * IDE Disk device model - */ -class IdeDisk : public SimObject -{ - protected: - /** The IDE controller for this disk. */ - IdeController *ctrl; - /** The DMA interface to use for transfers */ - DMAInterface<Bus> *dmaInterface; - /** The image that contains the data of this disk. */ - DiskImage *image; - /** Pointer to physical memory for DMA transfers */ - PhysicalMemory *physmem; - - protected: - /** The disk delay in microseconds. */ - int diskDelay; - - private: - /** Drive identification structure for this disk */ - struct ataparams 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 */ - uint32_t drqBytesLeft; - /** Current sector in access */ - uint32_t curSector; - /** Command block registers */ - CommandReg_t cmdReg; - /** Status register */ - uint8_t status; - /** Interrupt enable bit */ - bool nIENBit; - /** Device state */ - DevState_t devState; - /** Dma state */ - DmaState_t dmaState; - /** Dma transaction is a read */ - bool dmaRead; - /** PRD table base address */ - uint32_t curPrdAddr; - /** PRD entry */ - PrdTableEntry curPrd; - /** Number of bytes transfered by DMA interface for current transfer */ - uint32_t dmaInterfaceBytes; - /** Device ID (master=0/slave=1) */ - int devID; - /** Interrupt pending */ - bool intrPending; - - Stats::Scalar<> dmaReadFullPages; - Stats::Scalar<> dmaReadBytes; - Stats::Scalar<> dmaReadTxs; - Stats::Scalar<> dmaWriteFullPages; - Stats::Scalar<> dmaWriteBytes; - Stats::Scalar<> dmaWriteTxs; - - public: - /** - * Create and initialize this Disk. - * @param name The name of this disk. - * @param img The disk image of this disk. - * @param phys Pointer to physical memory - * @param id The disk ID (master=0/slave=1) - * @param disk_delay The disk delay in milliseconds - */ - IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys, - int id, Tick disk_delay); - - /** - * Delete the data buffer. - */ - ~IdeDisk(); - - /** - * Reset the device state - */ - void reset(int id); - - /** - * Register statistics. - */ - void regStats(); - - - /** - * Set the controller for this device - * @param c The IDE controller - */ - void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) { - if (ctrl) panic("Cannot change the controller once set!\n"); - ctrl = c; - dmaInterface = dmaIntr; - } - - // Device register read/write - void read(const Addr &offset, IdeRegType regtype, uint8_t *data); - void write(const Addr &offset, IdeRegType regtype, const uint8_t *data); - - // Start/abort functions - void startDma(const uint32_t &prdTableBase); - void abortDma(); - - private: - void startCommand(); - - // Interrupt management - void intrPost(); - void intrClear(); - - // DMA stuff - void doDmaTransfer(); - friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>; - EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent; - - void doDmaRead(); - friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>; - EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent; - - void doDmaWrite(); - friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>; - EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent; - - void dmaPrdReadDone(); - friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>; - EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent; - - void dmaReadDone(); - friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>; - EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent; - - void dmaWriteDone(); - friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>; - EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent; - - // Disk image read/write - void readDisk(uint32_t sector, uint8_t *data); - void writeDisk(uint32_t sector, uint8_t *data); - - // State machine management - void updateState(DevAction_t action); - - // Utility functions - bool isBSYSet() { return (status & STATUS_BSY_BIT); } - bool isIENSet() { return nIENBit; } - bool isDEVSelect(); - - void setComplete() - { - // clear out the status byte - status = 0; - // set the DRDY bit - status |= STATUS_DRDY_BIT; - // set the SEEK bit - status |= STATUS_SEEK_BIT; - } - - uint32_t getLBABase() - { - return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) | - (cmdReg.cyl_low << 8) | (cmdReg.sec_num)); - } - - inline Addr pciToDma(Addr pciAddr); - - uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - void serialize(std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint to use. - * @param section The section name describing this object. - */ - void unserialize(Checkpoint *cp, const std::string §ion); -}; - - -#endif // __IDE_DISK_HH__ diff --git a/dev/ide_wdcreg.h b/dev/ide_wdcreg.h deleted file mode 100644 index ed7475ec8..000000000 --- a/dev/ide_wdcreg.h +++ /dev/null @@ -1,197 +0,0 @@ -/* $OpenBSD: wdcreg.h,v 1.13 2004/09/24 07:05:44 grange Exp $ */ -/* $NetBSD: wdcreg.h,v 1.22 1999/03/07 14:02:54 bouyer Exp $ */ - -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)wdreg.h 7.1 (Berkeley) 5/9/91 - */ - -#ifndef _DEV_IC_WDCREG_H_ -#define _DEV_IC_WDCREG_H_ - -/* - * Controller register (wdr_ctlr) - */ -#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */ -#define WDCTL_RST 0x04 /* reset the controller */ -#define WDCTL_IDS 0x02 /* disable controller interrupts */ - -/* - * Status bits. - */ -#define WDCS_BSY 0x80 /* busy */ -#define WDCS_DRDY 0x40 /* drive ready */ -#define WDCS_DWF 0x20 /* drive write fault */ -#define WDCS_DSC 0x10 /* drive seek complete */ -#define WDCS_DRQ 0x08 /* data request */ -#define WDCS_CORR 0x04 /* corrected data */ -#define WDCS_IDX 0x02 /* index */ -#define WDCS_ERR 0x01 /* error */ -#define WDCS_BITS "\020\010BSY\007DRDY\006DWF\005DSC\004DRQ\003CORR\002IDX\001ERR" - -/* - * Error bits. - */ -#define WDCE_BBK 0x80 /* bad block detected */ -#define WDCE_CRC 0x80 /* CRC error (Ultra-DMA only) */ -#define WDCE_UNC 0x40 /* uncorrectable data error */ -#define WDCE_MC 0x20 /* media changed */ -#define WDCE_IDNF 0x10 /* id not found */ -#define WDCE_MCR 0x08 /* media change requested */ -#define WDCE_ABRT 0x04 /* aborted command */ -#define WDCE_TK0NF 0x02 /* track 0 not found */ -#define WDCE_AMNF 0x01 /* address mark not found */ - -/* - * Commands for Disk Controller. - */ -#define WDCC_NOP 0x00 /* NOP - Always fail with "aborted command" */ -#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */ - -#define WDCC_READ 0x20 /* disk read code */ -#define WDCC_WRITE 0x30 /* disk write code */ -#define WDCC__LONG 0x02 /* modifier -- access ecc bytes */ -#define WDCC__NORETRY 0x01 /* modifier -- no retrys */ - -#define WDCC_FORMAT 0x50 /* disk format code */ -#define WDCC_DIAGNOSE 0x90 /* controller diagnostic */ -#define WDCC_IDP 0x91 /* initialize drive parameters */ - -#define WDCC_READMULTI 0xc4 /* read multiple */ -#define WDCC_WRITEMULTI 0xc5 /* write multiple */ -#define WDCC_SETMULTI 0xc6 /* set multiple mode */ - -#define WDCC_READDMA 0xc8 /* read with DMA */ -#define WDCC_WRITEDMA 0xca /* write with DMA */ - -#define WDCC_ACKMC 0xdb /* acknowledge media change */ -#define WDCC_LOCK 0xde /* lock drawer */ -#define WDCC_UNLOCK 0xdf /* unlock drawer */ - -#define WDCC_FLUSHCACHE 0xe7 /* Flush cache */ -#define WDCC_IDENTIFY 0xec /* read parameters from controller */ -#define SET_FEATURES 0xef /* set features */ - -#define WDCC_IDLE 0xe3 /* set idle timer & enter idle mode */ -#define WDCC_IDLE_IMMED 0xe1 /* enter idle mode */ -#define WDCC_SLEEP 0xe6 /* enter sleep mode */ -#define WDCC_STANDBY 0xe2 /* set standby timer & enter standby mode */ -#define WDCC_STANDBY_IMMED 0xe0 /* enter standby mode */ -#define WDCC_CHECK_PWR 0xe5 /* check power mode */ - -#define WDCC_READ_EXT 0x24 /* read 48-bit addressing */ -#define WDCC_WRITE_EXT 0x34 /* write 48-bit addressing */ - -#define WDCC_READMULTI_EXT 0x29 /* read multiple 48-bit addressing */ -#define WDCC_WRITEMULTI_EXT 0x39 /* write multiple 48-bit addressing */ - -#define WDCC_READDMA_EXT 0x25 /* read 48-bit addressing with DMA */ -#define WDCC_WRITEDMA_EXT 0x35 /* write 48-bit addressing with DMA */ - -#define WDCC_FLUSHCACHE_EXT 0xea /* 48-bit addressing flush cache */ - -/* Subcommands for SET_FEATURES (features register ) */ -#define WDSF_8BIT_PIO_EN 0x01 /* Enable 8bit PIO (CFA featureset) */ -#define WDSF_EN_WR_CACHE 0x02 -#define WDSF_SET_MODE 0x03 -#define WDSF_REASSIGN_EN 0x04 /* Obsolete in ATA-6 */ -#define WDSF_APM_EN 0x05 /* Enable Adv. Power Management */ -#define WDSF_PUIS_EN 0x06 /* Enable Power-Up In Standby */ -#define WDSF_PUIS_SPINUP 0x07 /* Power-Up In Standby spin-up */ -#define WDSF_CFA_MODE1_EN 0x0A /* Enable CFA power mode 1 */ -#define WDSF_RMSN_DS 0x31 /* Disable Removable Media Status */ -#define WDSF_RETRY_DS 0x33 /* Obsolete in ATA-6 */ -#define WDSF_AAM_EN 0x42 /* Enable Autom. Acoustic Management */ -#define WDSF_SET_CACHE_SGMT 0x54 /* Obsolete in ATA-6 */ -#define WDSF_READAHEAD_DS 0x55 /* Disable read look-ahead */ -#define WDSF_RLSE_EN 0x5D /* Enable release interrupt */ -#define WDSF_SRV_EN 0x5E /* Enable SERVICE interrupt */ -#define WDSF_POD_DS 0x66 -#define WDSF_ECC_DS 0x77 -#define WDSF_8BIT_PIO_DS 0x81 /* Disable 8bit PIO (CFA featureset) */ -#define WDSF_WRITE_CACHE_DS 0x82 -#define WDSF_REASSIGN_DS 0x84 -#define WDSF_APM_DS 0x85 /* Disable Adv. Power Management */ -#define WDSF_PUIS_DS 0x86 /* Disable Power-Up In Standby */ -#define WDSF_ECC_EN 0x88 -#define WDSF_CFA_MODE1_DS 0x8A /* Disable CFA power mode 1 */ -#define WDSF_RMSN_EN 0x95 /* Enable Removable Media Status */ -#define WDSF_RETRY_EN 0x99 /* Obsolete in ATA-6 */ -#define WDSF_SET_CURRENT 0x9A /* Obsolete in ATA-6 */ -#define WDSF_READAHEAD_EN 0xAA -#define WDSF_PREFETCH_SET 0xAB /* Obsolete in ATA-6 */ -#define WDSF_AAM_DS 0xC2 /* Disable Autom. Acoustic Management */ -#define WDSF_POD_EN 0xCC -#define WDSF_RLSE_DS 0xDD /* Disable release interrupt */ -#define WDSF_SRV_DS 0xDE /* Disable SERVICE interrupt */ -#define WDSF_READ_NATIVE_MAX 0xF8 -#define WDSF_SEEK 0x70 -#define WDSF_VERIFY 0x40 - -/* parameters uploaded to device/heads register */ -#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */ -#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */ -#define WDSD_LBA 0x40 /* logical block addressing */ - -/* Commands for ATAPI devices */ -#define ATAPI_CHECK_POWER_MODE 0xe5 -#define ATAPI_EXEC_DRIVE_DIAGS 0x90 -#define ATAPI_IDLE_IMMEDIATE 0xe1 -#define ATAPI_NOP 0x00 -#define ATAPI_PKT_CMD 0xa0 -#define ATAPI_IDENTIFY_DEVICE 0xa1 -#define ATAPI_SOFT_RESET 0x08 -#define ATAPI_DEVICE_RESET 0x08 /* ATA/ATAPI-5 name for soft reset */ -#define ATAPI_SLEEP 0xe6 -#define ATAPI_STANDBY_IMMEDIATE 0xe0 -#define ATAPI_SMART 0xB0 /* SMART operations */ -#define ATAPI_SETMAX 0xF9 /* Set Max Address */ -#define ATAPI_WRITEEXT 0x34 /* Write sectors Ext */ -#define ATAPI_SETMAXEXT 0x37 /* Set Max Address Ext */ -#define ATAPI_WRITEMULTIEXT 0x39 /* Write Multi Ext */ - -/* Bytes used by ATAPI_PACKET_COMMAND ( feature register) */ -#define ATAPI_PKT_CMD_FTRE_DMA 0x01 -#define ATAPI_PKT_CMD_FTRE_OVL 0x02 - -/* ireason */ -#define WDCI_CMD 0x01 /* command(1) or data(0) */ -#define WDCI_IN 0x02 /* transfer to(1) or from(0) the host */ -#define WDCI_RELEASE 0x04 /* bus released until completion */ - -#define PHASE_CMDOUT (WDCS_DRQ | WDCI_CMD) -#define PHASE_DATAIN (WDCS_DRQ | WDCI_IN) -#define PHASE_DATAOUT WDCS_DRQ -#define PHASE_COMPLETED (WDCI_IN | WDCI_CMD) -#define PHASE_ABORTED 0 - -#endif /* !_DEV_IC_WDCREG_H_ */ diff --git a/dev/io_device.cc b/dev/io_device.cc deleted file mode 100644 index 6ab876ab8..000000000 --- a/dev/io_device.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "dev/io_device.hh" -#include "mem/bus/base_interface.hh" -#include "mem/bus/dma_interface.hh" -#include "sim/builder.hh" - -PioDevice::PioDevice(const std::string &name, Platform *p) - : FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0) -{} - -PioDevice::~PioDevice() -{ - if (pioInterface) - delete pioInterface; -} - -DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice) - -DmaDevice::DmaDevice(const std::string &name, Platform *p) - : PioDevice(name, p), dmaInterface(NULL) -{} - -DmaDevice::~DmaDevice() -{ - if (dmaInterface) - delete dmaInterface; -} - -DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice) - diff --git a/dev/io_device.hh b/dev/io_device.hh deleted file mode 100644 index bcfd062b9..000000000 --- a/dev/io_device.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DEV_IO_DEVICE_HH__ -#define __DEV_IO_DEVICE_HH__ - -#include "mem/functional/functional.hh" - -class BaseInterface; -class Bus; -class HierParams; -class Platform; -template <class BusType> class DMAInterface; - -class PioDevice : public FunctionalMemory -{ - protected: - Platform *platform; - BaseInterface *pioInterface; - Tick pioLatency; - - public: - PioDevice(const std::string &name, Platform *p); - virtual ~PioDevice(); -}; - -class DmaDevice : public PioDevice -{ - protected: - DMAInterface<Bus> *dmaInterface; - - public: - DmaDevice(const std::string &name, Platform *p); - virtual ~DmaDevice(); -}; - -#endif // __DEV_IO_DEVICE_HH__ diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc deleted file mode 100644 index 2afebbded..000000000 --- a/dev/isa_fake.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Isa Fake Device implementation - */ - -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "cpu/exec_context.hh" -#include "dev/isa_fake.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -using namespace TheISA; - -IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Addr size) - : PioDevice(name, NULL), addr(a) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &IsaFake::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - } -} - -Fault -IsaFake::read(MemReqPtr &req, uint8_t *data) -{ - DPRINTF(Tsunami, "read va=%#x size=%d\n", - req->vaddr, req->size); - -#if TRACING_ON - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; -#endif - - switch (req->size) { - - case sizeof(uint64_t): - *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL; - return NoFault; - case sizeof(uint32_t): - *(uint32_t*)data = 0xFFFFFFFF; - return NoFault; - case sizeof(uint16_t): - *(uint16_t*)data = 0xFFFF; - return NoFault; - case sizeof(uint8_t): - *(uint8_t*)data = 0xFF; - return NoFault; - - default: - panic("invalid access size(?) for PCI configspace!\n"); - } - DPRINTFN("Isa FakeSMC ERROR: read daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; -} - -Fault -IsaFake::write(MemReqPtr &req, const uint8_t *data) -{ - DPRINTF(Tsunami, "write - va=%#x size=%d \n", - req->vaddr, req->size); - - //:Addr daddr = (req->paddr & addr_mask) >> 6; - - return NoFault; -} - -Tick -IsaFake::cacheAccess(MemReqPtr &req) -{ - return curTick; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake) - - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - Param<Addr> size; - -END_DECLARE_SIM_OBJECT_PARAMS(IsaFake) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake) - - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(size, "Size of address range", 0x8) - -END_INIT_SIM_OBJECT_PARAMS(IsaFake) - -CREATE_SIM_OBJECT(IsaFake) -{ - return new IsaFake(getInstanceName(), addr, mmu, hier, pio_bus, size); -} - -REGISTER_SIM_OBJECT("IsaFake", IsaFake) diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh deleted file mode 100644 index 73e40c681..000000000 --- a/dev/isa_fake.hh +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Declaration of a fake device. - */ - -#ifndef __ISA_FAKE_HH__ -#define __ISA_FAKE_HH__ - -#include "dev/tsunami.hh" -#include "base/range.hh" -#include "dev/io_device.hh" - -class MemoryController; - -/** - * IsaFake is a device that returns -1 on all reads and - * accepts all writes. It is meant to be placed at an address range - * so that an mcheck doesn't occur when an os probes a piece of hw - * that doesn't exist (e.g. UARTs1-3). - */ -class IsaFake : public PioDevice -{ - private: - /** The address in memory that we respond to */ - Addr addr; - - public: - /** - * The constructor for Tsunmami Fake just registers itself with the MMU. - * @param name name of this device. - * @param a address to respond to. - * @param mmu the mmu we register with. - * @param size number of addresses to respond to - */ - IsaFake(const std::string &name, Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Addr size = 0x8); - - /** - * This read always returns -1. - * @param req The memory request. - * @param data Where to put the data. - */ - virtual Fault read(MemReqPtr &req, uint8_t *data); - - /** - * All writes are simply ignored. - * @param req The memory request. - * @param data the data to not write. - */ - 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 // __ISA_FAKE_HH__ diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc deleted file mode 100644 index ed8c794f9..000000000 --- a/dev/ns_gige.cc +++ /dev/null @@ -1,3105 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Device module for modelling the National Semiconductor - * DP83820 ethernet controller. Does not support priority queueing - */ -#include <cstdio> -#include <deque> -#include <string> - -#include "base/inet.hh" -#include "cpu/exec_context.hh" -#include "dev/etherlink.hh" -#include "dev/ns_gige.hh" -#include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" -#include "sim/debug.hh" -#include "sim/host.hh" -#include "sim/stats.hh" -#include "arch/vtophys.hh" - -const char *NsRxStateStrings[] = -{ - "rxIdle", - "rxDescRefr", - "rxDescRead", - "rxFifoBlock", - "rxFragWrite", - "rxDescWrite", - "rxAdvance" -}; - -const char *NsTxStateStrings[] = -{ - "txIdle", - "txDescRefr", - "txDescRead", - "txFifoBlock", - "txFragRead", - "txDescWrite", - "txAdvance" -}; - -const char *NsDmaState[] = -{ - "dmaIdle", - "dmaReading", - "dmaWriting", - "dmaReadWaiting", - "dmaWriteWaiting" -}; - -using namespace std; -using namespace Net; -using namespace TheISA; - -/////////////////////////////////////////////////////////////////////// -// -// NSGigE PCI Device -// -NSGigE::NSGigE(Params *p) - : PciDev(p), ioEnable(false), - txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), - txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), - txXferLen(0), rxXferLen(0), clock(p->clock), - txState(txIdle), txEnable(false), CTDD(false), - txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), - rxEnable(false), CRDD(false), rxPktBytes(0), - rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), - eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), - txDmaReadEvent(this), txDmaWriteEvent(this), - dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), - txDelay(p->tx_delay), rxDelay(p->rx_delay), - rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), - txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), - acceptMulticast(false), acceptUnicast(false), - acceptPerfect(false), acceptArp(false), multicastHashEnable(false), - physmem(p->pmem), intrTick(0), cpuPendingIntr(false), - intrEvent(0), interface(0) -{ - if (p->pio_bus) { - pioInterface = newPioInterface(name() + ".pio", p->hier, - p->pio_bus, this, - &NSGigE::cacheAccess); - pioLatency = p->pio_latency * p->pio_bus->clockRate; - } - - if (p->header_bus) { - if (p->payload_bus) - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - p->header_bus, - p->payload_bus, 1, - p->dma_no_allocate); - else - dmaInterface = new DMAInterface<Bus>(name() + ".dma", - p->header_bus, - p->header_bus, 1, - p->dma_no_allocate); - } else if (p->payload_bus) - panic("Must define a header bus if defining a payload bus"); - - intrDelay = p->intr_delay; - dmaReadDelay = p->dma_read_delay; - dmaWriteDelay = p->dma_write_delay; - dmaReadFactor = p->dma_read_factor; - dmaWriteFactor = p->dma_write_factor; - - regsReset(); - memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); - - memset(&rxDesc32, 0, sizeof(rxDesc32)); - memset(&txDesc32, 0, sizeof(txDesc32)); - memset(&rxDesc64, 0, sizeof(rxDesc64)); - memset(&txDesc64, 0, sizeof(txDesc64)); -} - -NSGigE::~NSGigE() -{} - -void -NSGigE::regStats() -{ - txBytes - .name(name() + ".txBytes") - .desc("Bytes Transmitted") - .prereq(txBytes) - ; - - rxBytes - .name(name() + ".rxBytes") - .desc("Bytes Received") - .prereq(rxBytes) - ; - - txPackets - .name(name() + ".txPackets") - .desc("Number of Packets Transmitted") - .prereq(txBytes) - ; - - rxPackets - .name(name() + ".rxPackets") - .desc("Number of Packets Received") - .prereq(rxBytes) - ; - - txIpChecksums - .name(name() + ".txIpChecksums") - .desc("Number of tx IP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxIpChecksums - .name(name() + ".rxIpChecksums") - .desc("Number of rx IP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - txTcpChecksums - .name(name() + ".txTcpChecksums") - .desc("Number of tx TCP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxTcpChecksums - .name(name() + ".rxTcpChecksums") - .desc("Number of rx TCP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - txUdpChecksums - .name(name() + ".txUdpChecksums") - .desc("Number of tx UDP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxUdpChecksums - .name(name() + ".rxUdpChecksums") - .desc("Number of rx UDP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - descDmaReads - .name(name() + ".descDMAReads") - .desc("Number of descriptors the device read w/ DMA") - .precision(0) - ; - - descDmaWrites - .name(name() + ".descDMAWrites") - .desc("Number of descriptors the device wrote w/ DMA") - .precision(0) - ; - - descDmaRdBytes - .name(name() + ".descDmaReadBytes") - .desc("number of descriptor bytes read w/ DMA") - .precision(0) - ; - - descDmaWrBytes - .name(name() + ".descDmaWriteBytes") - .desc("number of descriptor bytes write w/ DMA") - .precision(0) - ; - - txBandwidth - .name(name() + ".txBandwidth") - .desc("Transmit Bandwidth (bits/s)") - .precision(0) - .prereq(txBytes) - ; - - rxBandwidth - .name(name() + ".rxBandwidth") - .desc("Receive Bandwidth (bits/s)") - .precision(0) - .prereq(rxBytes) - ; - - totBandwidth - .name(name() + ".totBandwidth") - .desc("Total Bandwidth (bits/s)") - .precision(0) - .prereq(totBytes) - ; - - totPackets - .name(name() + ".totPackets") - .desc("Total Packets") - .precision(0) - .prereq(totBytes) - ; - - totBytes - .name(name() + ".totBytes") - .desc("Total Bytes") - .precision(0) - .prereq(totBytes) - ; - - totPacketRate - .name(name() + ".totPPS") - .desc("Total Tranmission Rate (packets/s)") - .precision(0) - .prereq(totBytes) - ; - - txPacketRate - .name(name() + ".txPPS") - .desc("Packet Tranmission Rate (packets/s)") - .precision(0) - .prereq(txBytes) - ; - - rxPacketRate - .name(name() + ".rxPPS") - .desc("Packet Reception Rate (packets/s)") - .precision(0) - .prereq(rxBytes) - ; - - postedSwi - .name(name() + ".postedSwi") - .desc("number of software interrupts posted to CPU") - .precision(0) - ; - - totalSwi - .name(name() + ".totalSwi") - .desc("total number of Swi written to ISR") - .precision(0) - ; - - coalescedSwi - .name(name() + ".coalescedSwi") - .desc("average number of Swi's coalesced into each post") - .precision(0) - ; - - postedRxIdle - .name(name() + ".postedRxIdle") - .desc("number of rxIdle interrupts posted to CPU") - .precision(0) - ; - - totalRxIdle - .name(name() + ".totalRxIdle") - .desc("total number of RxIdle written to ISR") - .precision(0) - ; - - coalescedRxIdle - .name(name() + ".coalescedRxIdle") - .desc("average number of RxIdle's coalesced into each post") - .precision(0) - ; - - postedRxOk - .name(name() + ".postedRxOk") - .desc("number of RxOk interrupts posted to CPU") - .precision(0) - ; - - totalRxOk - .name(name() + ".totalRxOk") - .desc("total number of RxOk written to ISR") - .precision(0) - ; - - coalescedRxOk - .name(name() + ".coalescedRxOk") - .desc("average number of RxOk's coalesced into each post") - .precision(0) - ; - - postedRxDesc - .name(name() + ".postedRxDesc") - .desc("number of RxDesc interrupts posted to CPU") - .precision(0) - ; - - totalRxDesc - .name(name() + ".totalRxDesc") - .desc("total number of RxDesc written to ISR") - .precision(0) - ; - - coalescedRxDesc - .name(name() + ".coalescedRxDesc") - .desc("average number of RxDesc's coalesced into each post") - .precision(0) - ; - - postedTxOk - .name(name() + ".postedTxOk") - .desc("number of TxOk interrupts posted to CPU") - .precision(0) - ; - - totalTxOk - .name(name() + ".totalTxOk") - .desc("total number of TxOk written to ISR") - .precision(0) - ; - - coalescedTxOk - .name(name() + ".coalescedTxOk") - .desc("average number of TxOk's coalesced into each post") - .precision(0) - ; - - postedTxIdle - .name(name() + ".postedTxIdle") - .desc("number of TxIdle interrupts posted to CPU") - .precision(0) - ; - - totalTxIdle - .name(name() + ".totalTxIdle") - .desc("total number of TxIdle written to ISR") - .precision(0) - ; - - coalescedTxIdle - .name(name() + ".coalescedTxIdle") - .desc("average number of TxIdle's coalesced into each post") - .precision(0) - ; - - postedTxDesc - .name(name() + ".postedTxDesc") - .desc("number of TxDesc interrupts posted to CPU") - .precision(0) - ; - - totalTxDesc - .name(name() + ".totalTxDesc") - .desc("total number of TxDesc written to ISR") - .precision(0) - ; - - coalescedTxDesc - .name(name() + ".coalescedTxDesc") - .desc("average number of TxDesc's coalesced into each post") - .precision(0) - ; - - postedRxOrn - .name(name() + ".postedRxOrn") - .desc("number of RxOrn posted to CPU") - .precision(0) - ; - - totalRxOrn - .name(name() + ".totalRxOrn") - .desc("total number of RxOrn written to ISR") - .precision(0) - ; - - coalescedRxOrn - .name(name() + ".coalescedRxOrn") - .desc("average number of RxOrn's coalesced into each post") - .precision(0) - ; - - coalescedTotal - .name(name() + ".coalescedTotal") - .desc("average number of interrupts coalesced into each post") - .precision(0) - ; - - postedInterrupts - .name(name() + ".postedInterrupts") - .desc("number of posts to CPU") - .precision(0) - ; - - droppedPackets - .name(name() + ".droppedPackets") - .desc("number of packets dropped") - .precision(0) - ; - - coalescedSwi = totalSwi / postedInterrupts; - coalescedRxIdle = totalRxIdle / postedInterrupts; - coalescedRxOk = totalRxOk / postedInterrupts; - coalescedRxDesc = totalRxDesc / postedInterrupts; - coalescedTxOk = totalTxOk / postedInterrupts; - coalescedTxIdle = totalTxIdle / postedInterrupts; - coalescedTxDesc = totalTxDesc / postedInterrupts; - coalescedRxOrn = totalRxOrn / postedInterrupts; - - coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + - totalTxOk + totalTxIdle + totalTxDesc + - totalRxOrn) / postedInterrupts; - - txBandwidth = txBytes * Stats::constant(8) / simSeconds; - rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; - totBandwidth = txBandwidth + rxBandwidth; - totBytes = txBytes + rxBytes; - totPackets = txPackets + rxPackets; - - txPacketRate = txPackets / simSeconds; - rxPacketRate = rxPackets / simSeconds; -} - -/** - * This is to read the PCI general configuration registers - */ -void -NSGigE::readConfig(int offset, int size, uint8_t *data) -{ - if (offset < PCI_DEVICE_SPECIFIC) - PciDev::readConfig(offset, size, data); - else - panic("Device specific PCI config space not implemented!\n"); -} - -/** - * This is to write to the PCI general configuration registers - */ -void -NSGigE::writeConfig(int offset, int size, const uint8_t* data) -{ - if (offset < PCI_DEVICE_SPECIFIC) - PciDev::writeConfig(offset, size, data); - else - 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 PCI settings, but i - // put in the IO to double check, an assertion will fail if we - // need to properly implement it - case PCI_COMMAND: - if (config.data[offset] & PCI_CMD_IOSE) - ioEnable = true; - else - ioEnable = false; - -#if 0 - if (config.data[offset] & PCI_CMD_BME) { - bmEnabled = true; - } - else { - bmEnabled = false; - } - - if (config.data[offset] & PCI_CMD_MSE) { - memEnable = true; - } - else { - memEnable = false; - } -#endif - break; - - case PCI0_BASE_ADDR0: - if (BARAddrs[0] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - - BARAddrs[0] &= EV5::PAddrUncachedMask; - } - break; - case PCI0_BASE_ADDR1: - if (BARAddrs[1] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); - - BARAddrs[1] &= EV5::PAddrUncachedMask; - } - break; - } -} - -/** - * This reads the device registers, which are detailed in the NS83820 - * spec sheet - */ -Fault -NSGigE::read(MemReqPtr &req, uint8_t *data) -{ - assert(ioEnable); - - //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", - daddr, req->paddr, req->vaddr, req->size); - - - // there are some reserved registers, you can see ns_gige_reg.h and - // the spec sheet for details - if (daddr > LAST && daddr <= RESERVED) { - panic("Accessing reserved register"); - } else if (daddr > RESERVED && daddr <= 0x3FC) { - readConfig(daddr & 0xff, req->size, data); - return NoFault; - } else if (daddr >= MIB_START && daddr <= MIB_END) { - // don't implement all the MIB's. hopefully the kernel - // doesn't actually DEPEND upon their values - // MIB are just hardware stats keepers - uint32_t ® = *(uint32_t *) data; - reg = 0; - return NoFault; - } else if (daddr > 0x3FC) - panic("Something is messed up!\n"); - - switch (req->size) { - case sizeof(uint32_t): - { - uint32_t ® = *(uint32_t *)data; - uint16_t rfaddr; - - switch (daddr) { - case CR: - reg = regs.command; - //these are supposed to be cleared on a read - reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); - break; - - case CFGR: - reg = regs.config; - break; - - case MEAR: - reg = regs.mear; - break; - - case PTSCR: - reg = regs.ptscr; - break; - - case ISR: - reg = regs.isr; - devIntrClear(ISR_ALL); - break; - - case IMR: - reg = regs.imr; - break; - - case IER: - reg = regs.ier; - break; - - case IHR: - reg = regs.ihr; - break; - - case TXDP: - reg = regs.txdp; - break; - - case TXDP_HI: - reg = regs.txdp_hi; - break; - - case TX_CFG: - reg = regs.txcfg; - break; - - case GPIOR: - reg = regs.gpior; - break; - - case RXDP: - reg = regs.rxdp; - break; - - case RXDP_HI: - reg = regs.rxdp_hi; - break; - - case RX_CFG: - reg = regs.rxcfg; - break; - - case PQCR: - reg = regs.pqcr; - break; - - case WCSR: - reg = regs.wcsr; - break; - - case PCR: - reg = regs.pcr; - break; - - // see the spec sheet for how RFCR and RFDR work - // basically, you write to RFCR to tell the machine - // what you want to do next, then you act upon RFDR, - // and the device will be prepared b/c of what you - // wrote to RFCR - case RFCR: - reg = regs.rfcr; - break; - - case RFDR: - rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); - switch (rfaddr) { - // Read from perfect match ROM octets - case 0x000: - reg = rom.perfectMatch[1]; - reg = reg << 8; - reg += rom.perfectMatch[0]; - break; - case 0x002: - reg = rom.perfectMatch[3] << 8; - reg += rom.perfectMatch[2]; - break; - case 0x004: - reg = rom.perfectMatch[5] << 8; - reg += rom.perfectMatch[4]; - break; - default: - // Read filter hash table - if (rfaddr >= FHASH_ADDR && - rfaddr < FHASH_ADDR + FHASH_SIZE) { - - // Only word-aligned reads supported - if (rfaddr % 2) - panic("unaligned read from filter hash table!"); - - reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; - reg += rom.filterHash[rfaddr - FHASH_ADDR]; - break; - } - - panic("reading RFDR for something other than pattern" - " matching or hashing! %#x\n", rfaddr); - } - break; - - case SRR: - reg = regs.srr; - break; - - case MIBC: - reg = regs.mibc; - reg &= ~(MIBC_MIBS | MIBC_ACLR); - break; - - case VRCR: - reg = regs.vrcr; - break; - - case VTCR: - reg = regs.vtcr; - break; - - case VDR: - reg = regs.vdr; - break; - - case CCSR: - reg = regs.ccsr; - break; - - case TBICR: - reg = regs.tbicr; - break; - - case TBISR: - reg = regs.tbisr; - break; - - case TANAR: - reg = regs.tanar; - break; - - case TANLPAR: - reg = regs.tanlpar; - break; - - case TANER: - reg = regs.taner; - break; - - case TESR: - reg = regs.tesr; - break; - - case M5REG: - reg = 0; - if (params()->rx_thread) - reg |= M5REG_RX_THREAD; - if (params()->tx_thread) - reg |= M5REG_TX_THREAD; - if (params()->rss) - reg |= M5REG_RSS; - break; - - default: - panic("reading unimplemented register: addr=%#x", daddr); - } - - DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", - daddr, reg, reg); - } - break; - - default: - panic("accessing register with invalid size: addr=%#x, size=%d", - daddr, req->size); - } - - return NoFault; -} - -Fault -NSGigE::write(MemReqPtr &req, const uint8_t *data) -{ - assert(ioEnable); - - Addr daddr = req->paddr & 0xfff; - DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", - daddr, req->paddr, req->vaddr, req->size); - - if (daddr > LAST && daddr <= RESERVED) { - panic("Accessing reserved register"); - } else if (daddr > RESERVED && daddr <= 0x3FC) { - writeConfig(daddr & 0xff, req->size, data); - return NoFault; - } else if (daddr > 0x3FC) - panic("Something is messed up!\n"); - - if (req->size == sizeof(uint32_t)) { - uint32_t reg = *(uint32_t *)data; - uint16_t rfaddr; - - DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); - - switch (daddr) { - case CR: - regs.command = reg; - if (reg & CR_TXD) { - txEnable = false; - } else if (reg & CR_TXE) { - txEnable = true; - - // the kernel is enabling the transmit machine - if (txState == txIdle) - txKick(); - } - - if (reg & CR_RXD) { - rxEnable = false; - } else if (reg & CR_RXE) { - rxEnable = true; - - if (rxState == rxIdle) - rxKick(); - } - - if (reg & CR_TXR) - txReset(); - - if (reg & CR_RXR) - rxReset(); - - if (reg & CR_SWI) - devIntrPost(ISR_SWI); - - if (reg & CR_RST) { - txReset(); - rxReset(); - - regsReset(); - } - break; - - case CFGR: - if (reg & CFGR_LNKSTS || - reg & CFGR_SPDSTS || - reg & CFGR_DUPSTS || - reg & CFGR_RESERVED || - reg & CFGR_T64ADDR || - reg & CFGR_PCI64_DET) - - // First clear all writable bits - regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | - CFGR_RESERVED | CFGR_T64ADDR | - CFGR_PCI64_DET; - // Now set the appropriate writable bits - regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | - CFGR_RESERVED | CFGR_T64ADDR | - CFGR_PCI64_DET); - -// all these #if 0's are because i don't THINK the kernel needs to -// have these implemented. if there is a problem relating to one of -// these, you may need to add functionality in. - if (reg & CFGR_TBI_EN) ; - if (reg & CFGR_MODE_1000) ; - - if (reg & CFGR_AUTO_1000) - panic("CFGR_AUTO_1000 not implemented!\n"); - - if (reg & CFGR_PINT_DUPSTS || - reg & CFGR_PINT_LNKSTS || - reg & CFGR_PINT_SPDSTS) - ; - - if (reg & CFGR_TMRTEST) ; - if (reg & CFGR_MRM_DIS) ; - if (reg & CFGR_MWI_DIS) ; - - if (reg & CFGR_T64ADDR) ; - // panic("CFGR_T64ADDR is read only register!\n"); - - if (reg & CFGR_PCI64_DET) - panic("CFGR_PCI64_DET is read only register!\n"); - - if (reg & CFGR_DATA64_EN) ; - if (reg & CFGR_M64ADDR) ; - if (reg & CFGR_PHY_RST) ; - if (reg & CFGR_PHY_DIS) ; - - if (reg & CFGR_EXTSTS_EN) - extstsEnable = true; - else - extstsEnable = false; - - if (reg & CFGR_REQALG) ; - if (reg & CFGR_SB) ; - if (reg & CFGR_POW) ; - if (reg & CFGR_EXD) ; - if (reg & CFGR_PESEL) ; - if (reg & CFGR_BROM_DIS) ; - if (reg & CFGR_EXT_125) ; - if (reg & CFGR_BEM) ; - break; - - case MEAR: - // Clear writable bits - regs.mear &= MEAR_EEDO; - // Set appropriate writable bits - regs.mear |= reg & ~MEAR_EEDO; - - // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) - // even though it could get it through RFDR - if (reg & MEAR_EESEL) { - // Rising edge of clock - if (reg & MEAR_EECLK && !eepromClk) - eepromKick(); - } - else { - eepromState = eepromStart; - regs.mear &= ~MEAR_EEDI; - } - - eepromClk = reg & MEAR_EECLK; - - // since phy is completely faked, MEAR_MD* don't matter - if (reg & MEAR_MDIO) ; - if (reg & MEAR_MDDIR) ; - if (reg & MEAR_MDC) ; - break; - - case PTSCR: - regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); - // these control BISTs for various parts of chip - we - // don't care or do just fake that the BIST is done - if (reg & PTSCR_RBIST_EN) - regs.ptscr |= PTSCR_RBIST_DONE; - if (reg & PTSCR_EEBIST_EN) - regs.ptscr &= ~PTSCR_EEBIST_EN; - if (reg & PTSCR_EELOAD_EN) - regs.ptscr &= ~PTSCR_EELOAD_EN; - break; - - case ISR: /* writing to the ISR has no effect */ - panic("ISR is a read only register!\n"); - - case IMR: - regs.imr = reg; - devIntrChangeMask(); - break; - - case IER: - regs.ier = reg; - break; - - case IHR: - regs.ihr = reg; - /* not going to implement real interrupt holdoff */ - break; - - case TXDP: - regs.txdp = (reg & 0xFFFFFFFC); - assert(txState == txIdle); - CTDD = false; - break; - - case TXDP_HI: - regs.txdp_hi = reg; - break; - - case TX_CFG: - regs.txcfg = reg; -#if 0 - if (reg & TX_CFG_CSI) ; - if (reg & TX_CFG_HBI) ; - if (reg & TX_CFG_MLB) ; - if (reg & TX_CFG_ATP) ; - if (reg & TX_CFG_ECRETRY) { - /* - * this could easily be implemented, but considering - * the network is just a fake pipe, wouldn't make - * sense to do this - */ - } - - if (reg & TX_CFG_BRST_DIS) ; -#endif - -#if 0 - /* we handle our own DMA, ignore the kernel's exhortations */ - if (reg & TX_CFG_MXDMA) ; -#endif - - // also, we currently don't care about fill/drain - // thresholds though this may change in the future with - // more realistic networks or a driver which changes it - // according to feedback - - break; - - case GPIOR: - // Only write writable bits - regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN - | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; - regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN - | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); - /* these just control general purpose i/o pins, don't matter */ - break; - - case RXDP: - regs.rxdp = reg; - CRDD = false; - break; - - case RXDP_HI: - regs.rxdp_hi = reg; - break; - - case RX_CFG: - regs.rxcfg = reg; -#if 0 - if (reg & RX_CFG_AEP) ; - if (reg & RX_CFG_ARP) ; - if (reg & RX_CFG_STRIPCRC) ; - if (reg & RX_CFG_RX_RD) ; - if (reg & RX_CFG_ALP) ; - if (reg & RX_CFG_AIRL) ; - - /* we handle our own DMA, ignore what kernel says about it */ - if (reg & RX_CFG_MXDMA) ; - - //also, we currently don't care about fill/drain thresholds - //though this may change in the future with more realistic - //networks or a driver which changes it according to feedback - if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; -#endif - break; - - case PQCR: - /* there is no priority queueing used in the linux 2.6 driver */ - regs.pqcr = reg; - break; - - case WCSR: - /* not going to implement wake on LAN */ - regs.wcsr = reg; - break; - - case PCR: - /* not going to implement pause control */ - regs.pcr = reg; - break; - - case RFCR: - regs.rfcr = reg; - - rxFilterEnable = (reg & RFCR_RFEN) ? true : false; - acceptBroadcast = (reg & RFCR_AAB) ? true : false; - acceptMulticast = (reg & RFCR_AAM) ? true : false; - acceptUnicast = (reg & RFCR_AAU) ? true : false; - acceptPerfect = (reg & RFCR_APM) ? true : false; - acceptArp = (reg & RFCR_AARP) ? true : false; - multicastHashEnable = (reg & RFCR_MHEN) ? true : false; - -#if 0 - if (reg & RFCR_APAT) - panic("RFCR_APAT not implemented!\n"); -#endif - if (reg & RFCR_UHEN) - panic("Unicast hash filtering not used by drivers!\n"); - - if (reg & RFCR_ULM) - panic("RFCR_ULM not implemented!\n"); - - break; - - case RFDR: - rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); - switch (rfaddr) { - case 0x000: - rom.perfectMatch[0] = (uint8_t)reg; - rom.perfectMatch[1] = (uint8_t)(reg >> 8); - break; - case 0x002: - rom.perfectMatch[2] = (uint8_t)reg; - rom.perfectMatch[3] = (uint8_t)(reg >> 8); - break; - case 0x004: - rom.perfectMatch[4] = (uint8_t)reg; - rom.perfectMatch[5] = (uint8_t)(reg >> 8); - break; - default: - - if (rfaddr >= FHASH_ADDR && - rfaddr < FHASH_ADDR + FHASH_SIZE) { - - // Only word-aligned writes supported - if (rfaddr % 2) - panic("unaligned write to filter hash table!"); - - rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; - rom.filterHash[rfaddr - FHASH_ADDR + 1] - = (uint8_t)(reg >> 8); - break; - } - panic("writing RFDR for something other than pattern matching\ - or hashing! %#x\n", rfaddr); - } - - case BRAR: - regs.brar = reg; - break; - - case BRDR: - panic("the driver never uses BRDR, something is wrong!\n"); - - case SRR: - panic("SRR is read only register!\n"); - - case MIBC: - panic("the driver never uses MIBC, something is wrong!\n"); - - case VRCR: - regs.vrcr = reg; - break; - - case VTCR: - regs.vtcr = reg; - break; - - case VDR: - panic("the driver never uses VDR, something is wrong!\n"); - - case CCSR: - /* not going to implement clockrun stuff */ - regs.ccsr = reg; - break; - - case TBICR: - regs.tbicr = reg; - if (reg & TBICR_MR_LOOPBACK) - panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); - - if (reg & TBICR_MR_AN_ENABLE) { - regs.tanlpar = regs.tanar; - regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); - } - -#if 0 - if (reg & TBICR_MR_RESTART_AN) ; -#endif - - break; - - case TBISR: - panic("TBISR is read only register!\n"); - - case TANAR: - // Only write the writable bits - regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; - regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); - - // Pause capability unimplemented -#if 0 - if (reg & TANAR_PS2) ; - if (reg & TANAR_PS1) ; -#endif - - break; - - case TANLPAR: - panic("this should only be written to by the fake phy!\n"); - - case TANER: - panic("TANER is read only register!\n"); - - case TESR: - regs.tesr = reg; - break; - - default: - panic("invalid register access daddr=%#x", daddr); - } - } else { - panic("Invalid Request Size"); - } - - return NoFault; -} - -void -NSGigE::devIntrPost(uint32_t interrupts) -{ - if (interrupts & ISR_RESERVE) - panic("Cannot set a reserved interrupt"); - - if (interrupts & ISR_NOIMPL) - warn("interrupt not implemented %#x\n", interrupts); - - interrupts &= ISR_IMPL; - regs.isr |= interrupts; - - if (interrupts & regs.imr) { - if (interrupts & ISR_SWI) { - totalSwi++; - } - if (interrupts & ISR_RXIDLE) { - totalRxIdle++; - } - if (interrupts & ISR_RXOK) { - totalRxOk++; - } - if (interrupts & ISR_RXDESC) { - totalRxDesc++; - } - if (interrupts & ISR_TXOK) { - totalTxOk++; - } - if (interrupts & ISR_TXIDLE) { - totalTxIdle++; - } - if (interrupts & ISR_TXDESC) { - totalTxDesc++; - } - if (interrupts & ISR_RXORN) { - totalRxOrn++; - } - } - - DPRINTF(EthernetIntr, - "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", - interrupts, regs.isr, regs.imr); - - if ((regs.isr & regs.imr)) { - Tick when = curTick; - if ((regs.isr & regs.imr & ISR_NODELAY) == 0) - when += intrDelay; - cpuIntrPost(when); - } -} - -/* writing this interrupt counting stats inside this means that this function - is now limited to being used to clear all interrupts upon the kernel - reading isr and servicing. just telling you in case you were thinking - of expanding use. -*/ -void -NSGigE::devIntrClear(uint32_t interrupts) -{ - if (interrupts & ISR_RESERVE) - panic("Cannot clear a reserved interrupt"); - - if (regs.isr & regs.imr & ISR_SWI) { - postedSwi++; - } - if (regs.isr & regs.imr & ISR_RXIDLE) { - postedRxIdle++; - } - if (regs.isr & regs.imr & ISR_RXOK) { - postedRxOk++; - } - if (regs.isr & regs.imr & ISR_RXDESC) { - postedRxDesc++; - } - if (regs.isr & regs.imr & ISR_TXOK) { - postedTxOk++; - } - if (regs.isr & regs.imr & ISR_TXIDLE) { - postedTxIdle++; - } - if (regs.isr & regs.imr & ISR_TXDESC) { - postedTxDesc++; - } - if (regs.isr & regs.imr & ISR_RXORN) { - postedRxOrn++; - } - - if (regs.isr & regs.imr & ISR_IMPL) - postedInterrupts++; - - interrupts &= ~ISR_NOIMPL; - regs.isr &= ~interrupts; - - DPRINTF(EthernetIntr, - "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", - interrupts, regs.isr, regs.imr); - - if (!(regs.isr & regs.imr)) - cpuIntrClear(); -} - -void -NSGigE::devIntrChangeMask() -{ - DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", - regs.isr, regs.imr, regs.isr & regs.imr); - - if (regs.isr & regs.imr) - cpuIntrPost(curTick); - else - cpuIntrClear(); -} - -void -NSGigE::cpuIntrPost(Tick when) -{ - // If the interrupt you want to post is later than an interrupt - // already scheduled, just let it post in the coming one and don't - // schedule another. - // HOWEVER, must be sure that the scheduled intrTick is in the - // future (this was formerly the source of a bug) - /** - * @todo this warning should be removed and the intrTick code should - * be fixed. - */ - assert(when >= curTick); - assert(intrTick >= curTick || intrTick == 0); - if (when > intrTick && intrTick != 0) { - DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", - intrTick); - return; - } - - intrTick = when; - if (intrTick < curTick) { - debug_break(); - intrTick = curTick; - } - - DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", - intrTick); - - if (intrEvent) - intrEvent->squash(); - intrEvent = new IntrEvent(this, true); - intrEvent->schedule(intrTick); -} - -void -NSGigE::cpuInterrupt() -{ - assert(intrTick == curTick); - - // Whether or not there's a pending interrupt, we don't care about - // it anymore - intrEvent = 0; - intrTick = 0; - - // Don't send an interrupt if there's already one - if (cpuPendingIntr) { - DPRINTF(EthernetIntr, - "would send an interrupt now, but there's already pending\n"); - } else { - // Send interrupt - cpuPendingIntr = true; - - DPRINTF(EthernetIntr, "posting interrupt\n"); - intrPost(); - } -} - -void -NSGigE::cpuIntrClear() -{ - if (!cpuPendingIntr) - return; - - if (intrEvent) { - intrEvent->squash(); - intrEvent = 0; - } - - intrTick = 0; - - cpuPendingIntr = false; - - DPRINTF(EthernetIntr, "clearing interrupt\n"); - intrClear(); -} - -bool -NSGigE::cpuIntrPending() const -{ return cpuPendingIntr; } - -void -NSGigE::txReset() -{ - - DPRINTF(Ethernet, "transmit reset\n"); - - CTDD = false; - txEnable = false;; - txFragPtr = 0; - assert(txDescCnt == 0); - txFifo.clear(); - txState = txIdle; - assert(txDmaState == dmaIdle); -} - -void -NSGigE::rxReset() -{ - DPRINTF(Ethernet, "receive reset\n"); - - CRDD = false; - assert(rxPktBytes == 0); - rxEnable = false; - rxFragPtr = 0; - assert(rxDescCnt == 0); - assert(rxDmaState == dmaIdle); - rxFifo.clear(); - rxState = rxIdle; -} - -void -NSGigE::regsReset() -{ - memset(®s, 0, sizeof(regs)); - regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); - regs.mear = 0x12; - regs.txcfg = 0x120; // set drain threshold to 1024 bytes and - // fill threshold to 32 bytes - regs.rxcfg = 0x4; // set drain threshold to 16 bytes - regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 - regs.mibc = MIBC_FRZ; - regs.vdr = 0x81; // set the vlan tag type to 802.1q - regs.tesr = 0xc000; // TBI capable of both full and half duplex - regs.brar = 0xffffffff; - - extstsEnable = false; - acceptBroadcast = false; - acceptMulticast = false; - acceptUnicast = false; - acceptPerfect = false; - acceptArp = false; -} - -void -NSGigE::rxDmaReadCopy() -{ - assert(rxDmaState == dmaReading); - - physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); - rxDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - DDUMP(EthernetDMA, rxDmaData, rxDmaLen); -} - -bool -NSGigE::doRxDmaRead() -{ - assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); - rxDmaState = dmaReading; - - if (dmaInterface && !rxDmaFree) { - if (dmaInterface->busy()) - rxDmaState = dmaReadWaiting; - else - dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, - &rxDmaReadEvent, true); - return true; - } - - if (dmaReadDelay == 0 && dmaReadFactor == 0) { - rxDmaReadCopy(); - return false; - } - - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - rxDmaReadEvent.schedule(start); - return true; -} - -void -NSGigE::rxDmaReadDone() -{ - assert(rxDmaState == dmaReading); - rxDmaReadCopy(); - - // If the transmit state machine has a pending DMA, let it go first - if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) - txKick(); - - rxKick(); -} - -void -NSGigE::rxDmaWriteCopy() -{ - assert(rxDmaState == dmaWriting); - - physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); - rxDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - DDUMP(EthernetDMA, rxDmaData, rxDmaLen); -} - -bool -NSGigE::doRxDmaWrite() -{ - assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); - rxDmaState = dmaWriting; - - if (dmaInterface && !rxDmaFree) { - if (dmaInterface->busy()) - rxDmaState = dmaWriteWaiting; - else - dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, - &rxDmaWriteEvent, true); - return true; - } - - if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { - rxDmaWriteCopy(); - return false; - } - - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - rxDmaWriteEvent.schedule(start); - return true; -} - -void -NSGigE::rxDmaWriteDone() -{ - assert(rxDmaState == dmaWriting); - rxDmaWriteCopy(); - - // If the transmit state machine has a pending DMA, let it go first - if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) - txKick(); - - rxKick(); -} - -void -NSGigE::rxKick() -{ - bool is64bit = (bool)(regs.config & CFGR_M64ADDR); - - DPRINTF(EthernetSM, - "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", - NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); - - Addr link, bufptr; - uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; - uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; - - next: - if (clock) { - if (rxKickTick > curTick) { - DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", - rxKickTick); - - goto exit; - } - - // Go to the next state machine clock tick. - rxKickTick = curTick + cycles(1); - } - - switch(rxDmaState) { - case dmaReadWaiting: - if (doRxDmaRead()) - goto exit; - break; - case dmaWriteWaiting: - if (doRxDmaWrite()) - goto exit; - break; - default: - break; - } - - link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; - bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; - - // see state machine from spec for details - // the way this works is, if you finish work on one state and can - // go directly to another, you do that through jumping to the - // label "next". however, if you have intermediate work, like DMA - // so that you can't go to the next state yet, you go to exit and - // exit the loop. however, when the DMA is done it will trigger - // an event and come back to this loop. - switch (rxState) { - case rxIdle: - if (!rxEnable) { - DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); - goto exit; - } - - if (CRDD) { - rxState = rxDescRefr; - - rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = - is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; - rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); - rxDmaFree = dmaDescFree; - - descDmaReads++; - descDmaRdBytes += rxDmaLen; - - if (doRxDmaRead()) - goto exit; - } else { - rxState = rxDescRead; - - rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; - rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); - rxDmaFree = dmaDescFree; - - descDmaReads++; - descDmaRdBytes += rxDmaLen; - - if (doRxDmaRead()) - goto exit; - } - break; - - case rxDescRefr: - if (rxDmaState != dmaIdle) - goto exit; - - rxState = rxAdvance; - break; - - case rxDescRead: - if (rxDmaState != dmaIdle) - goto exit; - - DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", - regs.rxdp & 0x3fffffff); - DPRINTF(EthernetDesc, - "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", - link, bufptr, cmdsts, extsts); - - if (cmdsts & CMDSTS_OWN) { - devIntrPost(ISR_RXIDLE); - rxState = rxIdle; - goto exit; - } else { - rxState = rxFifoBlock; - rxFragPtr = bufptr; - rxDescCnt = cmdsts & CMDSTS_LEN_MASK; - } - break; - - case rxFifoBlock: - if (!rxPacket) { - /** - * @todo in reality, we should be able to start processing - * the packet as it arrives, and not have to wait for the - * full packet ot be in the receive fifo. - */ - if (rxFifo.empty()) - goto exit; - - DPRINTF(EthernetSM, "****processing receive of new packet****\n"); - - // If we don't have a packet, grab a new one from the fifo. - rxPacket = rxFifo.front(); - rxPktBytes = rxPacket->length; - rxPacketBufPtr = rxPacket->data; - -#if TRACING_ON - if (DTRACE(Ethernet)) { - IpPtr ip(rxPacket); - if (ip) { - DPRINTF(Ethernet, "ID is %d\n", ip->id()); - TcpPtr tcp(ip); - if (tcp) { - DPRINTF(Ethernet, - "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", - tcp->sport(), tcp->dport(), tcp->seq(), - tcp->ack()); - } - } - } -#endif - - // sanity check - i think the driver behaves like this - assert(rxDescCnt >= rxPktBytes); - rxFifo.pop(); - } - - - // dont' need the && rxDescCnt > 0 if driver sanity check - // above holds - if (rxPktBytes > 0) { - rxState = rxFragWrite; - // don't need min<>(rxPktBytes,rxDescCnt) if above sanity - // check holds - rxXferLen = rxPktBytes; - - rxDmaAddr = rxFragPtr & 0x3fffffff; - rxDmaData = rxPacketBufPtr; - rxDmaLen = rxXferLen; - rxDmaFree = dmaDataFree; - - if (doRxDmaWrite()) - goto exit; - - } else { - rxState = rxDescWrite; - - //if (rxPktBytes == 0) { /* packet is done */ - assert(rxPktBytes == 0); - DPRINTF(EthernetSM, "done with receiving packet\n"); - - cmdsts |= CMDSTS_OWN; - cmdsts &= ~CMDSTS_MORE; - cmdsts |= CMDSTS_OK; - cmdsts &= 0xffff0000; - cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE - -#if 0 - /* - * all the driver uses these are for its own stats keeping - * which we don't care about, aren't necessary for - * functionality and doing this would just slow us down. - * if they end up using this in a later version for - * functional purposes, just undef - */ - if (rxFilterEnable) { - cmdsts &= ~CMDSTS_DEST_MASK; - const EthAddr &dst = rxFifoFront()->dst(); - if (dst->unicast()) - cmdsts |= CMDSTS_DEST_SELF; - if (dst->multicast()) - cmdsts |= CMDSTS_DEST_MULTI; - if (dst->broadcast()) - cmdsts |= CMDSTS_DEST_MASK; - } -#endif - - IpPtr ip(rxPacket); - if (extstsEnable && ip) { - extsts |= EXTSTS_IPPKT; - rxIpChecksums++; - if (cksum(ip) != 0) { - DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); - extsts |= EXTSTS_IPERR; - } - TcpPtr tcp(ip); - UdpPtr udp(ip); - if (tcp) { - extsts |= EXTSTS_TCPPKT; - rxTcpChecksums++; - if (cksum(tcp) != 0) { - DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); - extsts |= EXTSTS_TCPERR; - - } - } else if (udp) { - extsts |= EXTSTS_UDPPKT; - rxUdpChecksums++; - if (cksum(udp) != 0) { - DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); - extsts |= EXTSTS_UDPERR; - } - } - } - 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(EthernetDesc, - "rxDesc: addr=%08x writeback cmdsts extsts\n", - regs.rxdp & 0x3fffffff); - DPRINTF(EthernetDesc, - "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", - link, bufptr, cmdsts, extsts); - - rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = &cmdsts; - if (is64bit) { - rxDmaAddr += offsetof(ns_desc64, cmdsts); - rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); - } else { - rxDmaAddr += offsetof(ns_desc32, cmdsts); - rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); - } - rxDmaFree = dmaDescFree; - - descDmaWrites++; - descDmaWrBytes += rxDmaLen; - - if (doRxDmaWrite()) - goto exit; - } - break; - - case rxFragWrite: - if (rxDmaState != dmaIdle) - goto exit; - - rxPacketBufPtr += rxXferLen; - rxFragPtr += rxXferLen; - rxPktBytes -= rxXferLen; - - rxState = rxFifoBlock; - break; - - case rxDescWrite: - if (rxDmaState != dmaIdle) - goto exit; - - assert(cmdsts & CMDSTS_OWN); - - assert(rxPacket == 0); - devIntrPost(ISR_RXOK); - - if (cmdsts & CMDSTS_INTR) - devIntrPost(ISR_RXDESC); - - if (!rxEnable) { - DPRINTF(EthernetSM, "Halting the RX state machine\n"); - rxState = rxIdle; - goto exit; - } else - rxState = rxAdvance; - break; - - case rxAdvance: - if (link == 0) { - devIntrPost(ISR_RXIDLE); - rxState = rxIdle; - CRDD = true; - goto exit; - } else { - if (rxDmaState != dmaIdle) - goto exit; - rxState = rxDescRead; - regs.rxdp = link; - CRDD = false; - - rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; - rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); - rxDmaFree = dmaDescFree; - - if (doRxDmaRead()) - goto exit; - } - break; - - default: - panic("Invalid rxState!"); - } - - DPRINTF(EthernetSM, "entering next rxState=%s\n", - NsRxStateStrings[rxState]); - goto next; - - exit: - /** - * @todo do we want to schedule a future kick? - */ - DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", - NsRxStateStrings[rxState]); - - if (clock && !rxKickEvent.scheduled()) - rxKickEvent.schedule(rxKickTick); -} - -void -NSGigE::transmit() -{ - if (txFifo.empty()) { - DPRINTF(Ethernet, "nothing to transmit\n"); - return; - } - - DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", - txFifo.size()); - if (interface->sendPacket(txFifo.front())) { -#if TRACING_ON - if (DTRACE(Ethernet)) { - IpPtr ip(txFifo.front()); - if (ip) { - DPRINTF(Ethernet, "ID is %d\n", ip->id()); - TcpPtr tcp(ip); - if (tcp) { - DPRINTF(Ethernet, - "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", - tcp->sport(), tcp->dport(), tcp->seq(), - tcp->ack()); - } - } - } -#endif - - DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); - txBytes += txFifo.front()->length; - txPackets++; - - DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", - txFifo.avail()); - txFifo.pop(); - - /* - * normally do a writeback of the descriptor here, and ONLY - * after that is done, send this interrupt. but since our - * stuff never actually fails, just do this interrupt here, - * otherwise the code has to stray from this nice format. - * besides, it's functionally the same. - */ - devIntrPost(ISR_TXOK); - } - - if (!txFifo.empty() && !txEvent.scheduled()) { - DPRINTF(Ethernet, "reschedule transmit\n"); - txEvent.schedule(curTick + retryTime); - } -} - -void -NSGigE::txDmaReadCopy() -{ - assert(txDmaState == dmaReading); - - physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); - txDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", - txDmaAddr, txDmaLen); - DDUMP(EthernetDMA, txDmaData, txDmaLen); -} - -bool -NSGigE::doTxDmaRead() -{ - assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); - txDmaState = dmaReading; - - if (dmaInterface && !txDmaFree) { - if (dmaInterface->busy()) - txDmaState = dmaReadWaiting; - else - dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, - &txDmaReadEvent, true); - return true; - } - - if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { - txDmaReadCopy(); - return false; - } - - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - txDmaReadEvent.schedule(start); - return true; -} - -void -NSGigE::txDmaReadDone() -{ - assert(txDmaState == dmaReading); - txDmaReadCopy(); - - // If the receive state machine has a pending DMA, let it go first - if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) - rxKick(); - - txKick(); -} - -void -NSGigE::txDmaWriteCopy() -{ - assert(txDmaState == dmaWriting); - - physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); - txDmaState = dmaIdle; - - DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", - txDmaAddr, txDmaLen); - DDUMP(EthernetDMA, txDmaData, txDmaLen); -} - -bool -NSGigE::doTxDmaWrite() -{ - assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); - txDmaState = dmaWriting; - - if (dmaInterface && !txDmaFree) { - if (dmaInterface->busy()) - txDmaState = dmaWriteWaiting; - else - dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, - &txDmaWriteEvent, true); - return true; - } - - if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { - txDmaWriteCopy(); - return false; - } - - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - txDmaWriteEvent.schedule(start); - return true; -} - -void -NSGigE::txDmaWriteDone() -{ - assert(txDmaState == dmaWriting); - txDmaWriteCopy(); - - // If the receive state machine has a pending DMA, let it go first - if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) - rxKick(); - - txKick(); -} - -void -NSGigE::txKick() -{ - bool is64bit = (bool)(regs.config & CFGR_M64ADDR); - - DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", - NsTxStateStrings[txState], is64bit ? 64 : 32); - - Addr link, bufptr; - uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; - uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; - - next: - if (clock) { - if (txKickTick > curTick) { - DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", - txKickTick); - goto exit; - } - - // Go to the next state machine clock tick. - txKickTick = curTick + cycles(1); - } - - switch(txDmaState) { - case dmaReadWaiting: - if (doTxDmaRead()) - goto exit; - break; - case dmaWriteWaiting: - if (doTxDmaWrite()) - goto exit; - break; - default: - break; - } - - link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; - bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; - switch (txState) { - case txIdle: - if (!txEnable) { - DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); - goto exit; - } - - if (CTDD) { - txState = txDescRefr; - - txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = - is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; - txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); - txDmaFree = dmaDescFree; - - descDmaReads++; - descDmaRdBytes += txDmaLen; - - if (doTxDmaRead()) - goto exit; - - } else { - txState = txDescRead; - - txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; - txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); - txDmaFree = dmaDescFree; - - descDmaReads++; - descDmaRdBytes += txDmaLen; - - if (doTxDmaRead()) - goto exit; - } - break; - - case txDescRefr: - if (txDmaState != dmaIdle) - goto exit; - - txState = txAdvance; - break; - - case txDescRead: - if (txDmaState != dmaIdle) - goto exit; - - DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", - regs.txdp & 0x3fffffff); - DPRINTF(EthernetDesc, - "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", - link, bufptr, cmdsts, extsts); - - if (cmdsts & CMDSTS_OWN) { - txState = txFifoBlock; - txFragPtr = bufptr; - txDescCnt = cmdsts & CMDSTS_LEN_MASK; - } else { - devIntrPost(ISR_TXIDLE); - txState = txIdle; - goto exit; - } - break; - - case txFifoBlock: - if (!txPacket) { - DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); - txPacket = new PacketData(16384); - txPacketBufPtr = txPacket->data; - } - - if (txDescCnt == 0) { - DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); - if (cmdsts & CMDSTS_MORE) { - DPRINTF(EthernetSM, "there are more descriptors to come\n"); - txState = txDescWrite; - - cmdsts &= ~CMDSTS_OWN; - - txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = &cmdsts; - if (is64bit) { - txDmaAddr += offsetof(ns_desc64, cmdsts); - txDmaLen = sizeof(txDesc64.cmdsts); - } else { - txDmaAddr += offsetof(ns_desc32, cmdsts); - txDmaLen = sizeof(txDesc32.cmdsts); - } - txDmaFree = dmaDescFree; - - if (doTxDmaWrite()) - goto exit; - - } else { /* this packet is totally done */ - DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); - /* deal with the the packet that just finished */ - if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { - IpPtr ip(txPacket); - if (extsts & EXTSTS_UDPPKT) { - UdpPtr udp(ip); - udp->sum(0); - udp->sum(cksum(udp)); - txUdpChecksums++; - } else if (extsts & EXTSTS_TCPPKT) { - TcpPtr tcp(ip); - tcp->sum(0); - tcp->sum(cksum(tcp)); - txTcpChecksums++; - } - if (extsts & EXTSTS_IPPKT) { - ip->sum(0); - ip->sum(cksum(ip)); - txIpChecksums++; - } - } - - txPacket->length = txPacketBufPtr - txPacket->data; - // this is just because the receive can't handle a - // packet bigger want to make sure - if (txPacket->length > 1514) - panic("transmit packet too large, %s > 1514\n", - txPacket->length); - -#ifndef NDEBUG - bool success = -#endif - txFifo.push(txPacket); - assert(success); - - /* - * this following section is not tqo spec, but - * functionally shouldn't be any different. normally, - * the chip will wait til the transmit has occurred - * before writing back the descriptor because it has - * to wait to see that it was successfully transmitted - * to decide whether to set CMDSTS_OK or not. - * however, in the simulator since it is always - * successfully transmitted, and writing it exactly to - * spec would complicate the code, we just do it here - */ - - cmdsts &= ~CMDSTS_OWN; - cmdsts |= CMDSTS_OK; - - DPRINTF(EthernetDesc, - "txDesc writeback: cmdsts=%08x extsts=%08x\n", - cmdsts, extsts); - - txDmaFree = dmaDescFree; - txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = &cmdsts; - if (is64bit) { - txDmaAddr += offsetof(ns_desc64, cmdsts); - txDmaLen = - sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); - } else { - txDmaAddr += offsetof(ns_desc32, cmdsts); - txDmaLen = - sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); - } - - descDmaWrites++; - descDmaWrBytes += txDmaLen; - - transmit(); - txPacket = 0; - - if (!txEnable) { - DPRINTF(EthernetSM, "halting TX state machine\n"); - txState = txIdle; - goto exit; - } else - txState = txAdvance; - - if (doTxDmaWrite()) - goto exit; - } - } else { - DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); - if (!txFifo.full()) { - txState = txFragRead; - - /* - * The number of bytes transferred is either whatever - * is left in the descriptor (txDescCnt), or if there - * is not enough room in the fifo, just whatever room - * is left in the fifo - */ - txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); - - txDmaAddr = txFragPtr & 0x3fffffff; - txDmaData = txPacketBufPtr; - txDmaLen = txXferLen; - txDmaFree = dmaDataFree; - - if (doTxDmaRead()) - goto exit; - } else { - txState = txFifoBlock; - transmit(); - - goto exit; - } - - } - break; - - case txFragRead: - if (txDmaState != dmaIdle) - goto exit; - - txPacketBufPtr += txXferLen; - txFragPtr += txXferLen; - txDescCnt -= txXferLen; - txFifo.reserve(txXferLen); - - txState = txFifoBlock; - break; - - case txDescWrite: - if (txDmaState != dmaIdle) - goto exit; - - if (cmdsts & CMDSTS_INTR) - devIntrPost(ISR_TXDESC); - - if (!txEnable) { - DPRINTF(EthernetSM, "halting TX state machine\n"); - txState = txIdle; - goto exit; - } else - txState = txAdvance; - break; - - case txAdvance: - if (link == 0) { - devIntrPost(ISR_TXIDLE); - txState = txIdle; - goto exit; - } else { - if (txDmaState != dmaIdle) - goto exit; - txState = txDescRead; - regs.txdp = link; - CTDD = false; - - txDmaAddr = link & 0x3fffffff; - txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; - txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); - txDmaFree = dmaDescFree; - - if (doTxDmaRead()) - goto exit; - } - break; - - default: - panic("invalid state"); - } - - DPRINTF(EthernetSM, "entering next txState=%s\n", - NsTxStateStrings[txState]); - goto next; - - exit: - /** - * @todo do we want to schedule a future kick? - */ - DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", - NsTxStateStrings[txState]); - - if (clock && !txKickEvent.scheduled()) - txKickEvent.schedule(txKickTick); -} - -/** - * Advance the EEPROM state machine - * Called on rising edge of EEPROM clock bit in MEAR - */ -void -NSGigE::eepromKick() -{ - switch (eepromState) { - - case eepromStart: - - // Wait for start bit - if (regs.mear & MEAR_EEDI) { - // Set up to get 2 opcode bits - eepromState = eepromGetOpcode; - eepromBitsToRx = 2; - eepromOpcode = 0; - } - break; - - case eepromGetOpcode: - eepromOpcode <<= 1; - eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; - --eepromBitsToRx; - - // Done getting opcode - if (eepromBitsToRx == 0) { - if (eepromOpcode != EEPROM_READ) - panic("only EEPROM reads are implemented!"); - - // Set up to get address - eepromState = eepromGetAddress; - eepromBitsToRx = 6; - eepromAddress = 0; - } - break; - - case eepromGetAddress: - eepromAddress <<= 1; - eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; - --eepromBitsToRx; - - // Done getting address - if (eepromBitsToRx == 0) { - - if (eepromAddress >= EEPROM_SIZE) - panic("EEPROM read access out of range!"); - - switch (eepromAddress) { - - case EEPROM_PMATCH2_ADDR: - eepromData = rom.perfectMatch[5]; - eepromData <<= 8; - eepromData += rom.perfectMatch[4]; - break; - - case EEPROM_PMATCH1_ADDR: - eepromData = rom.perfectMatch[3]; - eepromData <<= 8; - eepromData += rom.perfectMatch[2]; - break; - - case EEPROM_PMATCH0_ADDR: - eepromData = rom.perfectMatch[1]; - eepromData <<= 8; - eepromData += rom.perfectMatch[0]; - break; - - default: - panic("FreeBSD driver only uses EEPROM to read PMATCH!"); - } - // Set up to read data - eepromState = eepromRead; - eepromBitsToRx = 16; - - // Clear data in bit - regs.mear &= ~MEAR_EEDI; - } - break; - - case eepromRead: - // Clear Data Out bit - regs.mear &= ~MEAR_EEDO; - // Set bit to value of current EEPROM bit - regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; - - eepromData <<= 1; - --eepromBitsToRx; - - // All done - if (eepromBitsToRx == 0) { - eepromState = eepromStart; - } - break; - - default: - panic("invalid EEPROM state"); - } - -} - -void -NSGigE::transferDone() -{ - if (txFifo.empty()) { - DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); - return; - } - - DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - - if (txEvent.scheduled()) - txEvent.reschedule(curTick + cycles(1)); - else - txEvent.schedule(curTick + cycles(1)); -} - -bool -NSGigE::rxFilter(const PacketPtr &packet) -{ - EthPtr eth = packet; - bool drop = true; - string type; - - const EthAddr &dst = eth->dst(); - if (dst.unicast()) { - // If we're accepting all unicast addresses - if (acceptUnicast) - drop = false; - - // If we make a perfect match - if (acceptPerfect && dst == rom.perfectMatch) - drop = false; - - if (acceptArp && eth->type() == ETH_TYPE_ARP) - drop = false; - - } else if (dst.broadcast()) { - // if we're accepting broadcasts - if (acceptBroadcast) - drop = false; - - } else if (dst.multicast()) { - // if we're accepting all multicasts - if (acceptMulticast) - drop = false; - - // Multicast hashing faked - all packets accepted - if (multicastHashEnable) - drop = false; - } - - if (drop) { - DPRINTF(Ethernet, "rxFilter drop\n"); - DDUMP(EthernetData, packet->data, packet->length); - } - - return drop; -} - -bool -NSGigE::recvPacket(PacketPtr packet) -{ - rxBytes += packet->length; - rxPackets++; - - DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", - rxFifo.avail()); - - if (!rxEnable) { - DPRINTF(Ethernet, "receive disabled...packet dropped\n"); - return true; - } - - if (!rxFilterEnable) { - DPRINTF(Ethernet, - "receive packet filtering disabled . . . packet dropped\n"); - return true; - } - - if (rxFilter(packet)) { - DPRINTF(Ethernet, "packet filtered...dropped\n"); - return true; - } - - if (rxFifo.avail() < packet->length) { -#if TRACING_ON - IpPtr ip(packet); - TcpPtr tcp(ip); - if (ip) { - DPRINTF(Ethernet, - "packet won't fit in receive buffer...pkt ID %d dropped\n", - ip->id()); - if (tcp) { - DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); - } - } -#endif - droppedPackets++; - devIntrPost(ISR_RXORN); - return false; - } - - rxFifo.push(packet); - - rxKick(); - return true; -} - -//===================================================================== -// -// -void -NSGigE::serialize(ostream &os) -{ - // Serialize the PciDev base class - PciDev::serialize(os); - - /* - * Finalize any DMA events now. - */ - if (rxDmaReadEvent.scheduled()) - rxDmaReadCopy(); - if (rxDmaWriteEvent.scheduled()) - rxDmaWriteCopy(); - if (txDmaReadEvent.scheduled()) - txDmaReadCopy(); - if (txDmaWriteEvent.scheduled()) - txDmaWriteCopy(); - - /* - * Serialize the device registers - */ - SERIALIZE_SCALAR(regs.command); - SERIALIZE_SCALAR(regs.config); - SERIALIZE_SCALAR(regs.mear); - SERIALIZE_SCALAR(regs.ptscr); - SERIALIZE_SCALAR(regs.isr); - SERIALIZE_SCALAR(regs.imr); - SERIALIZE_SCALAR(regs.ier); - SERIALIZE_SCALAR(regs.ihr); - SERIALIZE_SCALAR(regs.txdp); - SERIALIZE_SCALAR(regs.txdp_hi); - SERIALIZE_SCALAR(regs.txcfg); - SERIALIZE_SCALAR(regs.gpior); - SERIALIZE_SCALAR(regs.rxdp); - SERIALIZE_SCALAR(regs.rxdp_hi); - SERIALIZE_SCALAR(regs.rxcfg); - SERIALIZE_SCALAR(regs.pqcr); - SERIALIZE_SCALAR(regs.wcsr); - SERIALIZE_SCALAR(regs.pcr); - SERIALIZE_SCALAR(regs.rfcr); - SERIALIZE_SCALAR(regs.rfdr); - SERIALIZE_SCALAR(regs.brar); - SERIALIZE_SCALAR(regs.brdr); - SERIALIZE_SCALAR(regs.srr); - SERIALIZE_SCALAR(regs.mibc); - SERIALIZE_SCALAR(regs.vrcr); - SERIALIZE_SCALAR(regs.vtcr); - SERIALIZE_SCALAR(regs.vdr); - SERIALIZE_SCALAR(regs.ccsr); - SERIALIZE_SCALAR(regs.tbicr); - SERIALIZE_SCALAR(regs.tbisr); - SERIALIZE_SCALAR(regs.tanar); - SERIALIZE_SCALAR(regs.tanlpar); - SERIALIZE_SCALAR(regs.taner); - SERIALIZE_SCALAR(regs.tesr); - - SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); - SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); - - SERIALIZE_SCALAR(ioEnable); - - /* - * Serialize the data Fifos - */ - rxFifo.serialize("rxFifo", os); - txFifo.serialize("txFifo", os); - - /* - * Serialize the various helper variables - */ - bool txPacketExists = txPacket; - SERIALIZE_SCALAR(txPacketExists); - if (txPacketExists) { - txPacket->length = txPacketBufPtr - txPacket->data; - txPacket->serialize("txPacket", os); - uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); - SERIALIZE_SCALAR(txPktBufPtr); - } - - bool rxPacketExists = rxPacket; - SERIALIZE_SCALAR(rxPacketExists); - if (rxPacketExists) { - rxPacket->serialize("rxPacket", os); - uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); - SERIALIZE_SCALAR(rxPktBufPtr); - } - - SERIALIZE_SCALAR(txXferLen); - SERIALIZE_SCALAR(rxXferLen); - - /* - * Serialize Cached Descriptors - */ - SERIALIZE_SCALAR(rxDesc64.link); - SERIALIZE_SCALAR(rxDesc64.bufptr); - SERIALIZE_SCALAR(rxDesc64.cmdsts); - SERIALIZE_SCALAR(rxDesc64.extsts); - SERIALIZE_SCALAR(txDesc64.link); - SERIALIZE_SCALAR(txDesc64.bufptr); - SERIALIZE_SCALAR(txDesc64.cmdsts); - SERIALIZE_SCALAR(txDesc64.extsts); - SERIALIZE_SCALAR(rxDesc32.link); - SERIALIZE_SCALAR(rxDesc32.bufptr); - SERIALIZE_SCALAR(rxDesc32.cmdsts); - SERIALIZE_SCALAR(rxDesc32.extsts); - SERIALIZE_SCALAR(txDesc32.link); - SERIALIZE_SCALAR(txDesc32.bufptr); - SERIALIZE_SCALAR(txDesc32.cmdsts); - SERIALIZE_SCALAR(txDesc32.extsts); - SERIALIZE_SCALAR(extstsEnable); - - /* - * Serialize tx state machine - */ - int txState = this->txState; - SERIALIZE_SCALAR(txState); - SERIALIZE_SCALAR(txEnable); - SERIALIZE_SCALAR(CTDD); - SERIALIZE_SCALAR(txFragPtr); - SERIALIZE_SCALAR(txDescCnt); - int txDmaState = this->txDmaState; - SERIALIZE_SCALAR(txDmaState); - SERIALIZE_SCALAR(txKickTick); - - /* - * Serialize rx state machine - */ - int rxState = this->rxState; - SERIALIZE_SCALAR(rxState); - SERIALIZE_SCALAR(rxEnable); - SERIALIZE_SCALAR(CRDD); - SERIALIZE_SCALAR(rxPktBytes); - SERIALIZE_SCALAR(rxFragPtr); - SERIALIZE_SCALAR(rxDescCnt); - int rxDmaState = this->rxDmaState; - SERIALIZE_SCALAR(rxDmaState); - SERIALIZE_SCALAR(rxKickTick); - - /* - * Serialize EEPROM state machine - */ - int eepromState = this->eepromState; - SERIALIZE_SCALAR(eepromState); - SERIALIZE_SCALAR(eepromClk); - SERIALIZE_SCALAR(eepromBitsToRx); - SERIALIZE_SCALAR(eepromOpcode); - SERIALIZE_SCALAR(eepromAddress); - SERIALIZE_SCALAR(eepromData); - - /* - * If there's a pending transmit, store the time so we can - * reschedule it later - */ - Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; - 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); - SERIALIZE_SCALAR(multicastHashEnable); - - /* - * Keep track of pending interrupt status. - */ - SERIALIZE_SCALAR(intrTick); - SERIALIZE_SCALAR(cpuPendingIntr); - Tick intrEventTick = 0; - if (intrEvent) - intrEventTick = intrEvent->when(); - SERIALIZE_SCALAR(intrEventTick); - -} - -void -NSGigE::unserialize(Checkpoint *cp, const std::string §ion) -{ - // Unserialize the PciDev base class - PciDev::unserialize(cp, section); - - UNSERIALIZE_SCALAR(regs.command); - UNSERIALIZE_SCALAR(regs.config); - UNSERIALIZE_SCALAR(regs.mear); - UNSERIALIZE_SCALAR(regs.ptscr); - UNSERIALIZE_SCALAR(regs.isr); - UNSERIALIZE_SCALAR(regs.imr); - UNSERIALIZE_SCALAR(regs.ier); - UNSERIALIZE_SCALAR(regs.ihr); - UNSERIALIZE_SCALAR(regs.txdp); - UNSERIALIZE_SCALAR(regs.txdp_hi); - UNSERIALIZE_SCALAR(regs.txcfg); - UNSERIALIZE_SCALAR(regs.gpior); - UNSERIALIZE_SCALAR(regs.rxdp); - UNSERIALIZE_SCALAR(regs.rxdp_hi); - UNSERIALIZE_SCALAR(regs.rxcfg); - UNSERIALIZE_SCALAR(regs.pqcr); - UNSERIALIZE_SCALAR(regs.wcsr); - UNSERIALIZE_SCALAR(regs.pcr); - UNSERIALIZE_SCALAR(regs.rfcr); - UNSERIALIZE_SCALAR(regs.rfdr); - UNSERIALIZE_SCALAR(regs.brar); - UNSERIALIZE_SCALAR(regs.brdr); - UNSERIALIZE_SCALAR(regs.srr); - UNSERIALIZE_SCALAR(regs.mibc); - UNSERIALIZE_SCALAR(regs.vrcr); - UNSERIALIZE_SCALAR(regs.vtcr); - UNSERIALIZE_SCALAR(regs.vdr); - UNSERIALIZE_SCALAR(regs.ccsr); - UNSERIALIZE_SCALAR(regs.tbicr); - UNSERIALIZE_SCALAR(regs.tbisr); - UNSERIALIZE_SCALAR(regs.tanar); - UNSERIALIZE_SCALAR(regs.tanlpar); - UNSERIALIZE_SCALAR(regs.taner); - UNSERIALIZE_SCALAR(regs.tesr); - - UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); - UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); - - UNSERIALIZE_SCALAR(ioEnable); - - /* - * unserialize the data fifos - */ - rxFifo.unserialize("rxFifo", cp, section); - txFifo.unserialize("txFifo", cp, section); - - /* - * unserialize the various helper variables - */ - bool txPacketExists; - UNSERIALIZE_SCALAR(txPacketExists); - if (txPacketExists) { - txPacket = new PacketData(16384); - txPacket->unserialize("txPacket", cp, 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 PacketData(16384); - rxPacket->unserialize("rxPacket", cp, section); - uint32_t rxPktBufPtr; - UNSERIALIZE_SCALAR(rxPktBufPtr); - rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; - } else - rxPacket = 0; - - UNSERIALIZE_SCALAR(txXferLen); - UNSERIALIZE_SCALAR(rxXferLen); - - /* - * Unserialize Cached Descriptors - */ - UNSERIALIZE_SCALAR(rxDesc64.link); - UNSERIALIZE_SCALAR(rxDesc64.bufptr); - UNSERIALIZE_SCALAR(rxDesc64.cmdsts); - UNSERIALIZE_SCALAR(rxDesc64.extsts); - UNSERIALIZE_SCALAR(txDesc64.link); - UNSERIALIZE_SCALAR(txDesc64.bufptr); - UNSERIALIZE_SCALAR(txDesc64.cmdsts); - UNSERIALIZE_SCALAR(txDesc64.extsts); - UNSERIALIZE_SCALAR(rxDesc32.link); - UNSERIALIZE_SCALAR(rxDesc32.bufptr); - UNSERIALIZE_SCALAR(rxDesc32.cmdsts); - UNSERIALIZE_SCALAR(rxDesc32.extsts); - UNSERIALIZE_SCALAR(txDesc32.link); - UNSERIALIZE_SCALAR(txDesc32.bufptr); - UNSERIALIZE_SCALAR(txDesc32.cmdsts); - UNSERIALIZE_SCALAR(txDesc32.extsts); - UNSERIALIZE_SCALAR(extstsEnable); - - /* - * unserialize tx state machine - */ - int txState; - UNSERIALIZE_SCALAR(txState); - this->txState = (TxState) txState; - UNSERIALIZE_SCALAR(txEnable); - UNSERIALIZE_SCALAR(CTDD); - UNSERIALIZE_SCALAR(txFragPtr); - UNSERIALIZE_SCALAR(txDescCnt); - int txDmaState; - UNSERIALIZE_SCALAR(txDmaState); - this->txDmaState = (DmaState) txDmaState; - UNSERIALIZE_SCALAR(txKickTick); - if (txKickTick) - txKickEvent.schedule(txKickTick); - - /* - * unserialize rx state machine - */ - int rxState; - UNSERIALIZE_SCALAR(rxState); - this->rxState = (RxState) rxState; - UNSERIALIZE_SCALAR(rxEnable); - UNSERIALIZE_SCALAR(CRDD); - UNSERIALIZE_SCALAR(rxPktBytes); - UNSERIALIZE_SCALAR(rxFragPtr); - UNSERIALIZE_SCALAR(rxDescCnt); - int rxDmaState; - UNSERIALIZE_SCALAR(rxDmaState); - this->rxDmaState = (DmaState) rxDmaState; - UNSERIALIZE_SCALAR(rxKickTick); - if (rxKickTick) - rxKickEvent.schedule(rxKickTick); - - /* - * Unserialize EEPROM state machine - */ - int eepromState; - UNSERIALIZE_SCALAR(eepromState); - this->eepromState = (EEPROMState) eepromState; - UNSERIALIZE_SCALAR(eepromClk); - UNSERIALIZE_SCALAR(eepromBitsToRx); - UNSERIALIZE_SCALAR(eepromOpcode); - UNSERIALIZE_SCALAR(eepromAddress); - UNSERIALIZE_SCALAR(eepromData); - - /* - * If there's a pending transmit, reschedule it now - */ - Tick transmitTick; - UNSERIALIZE_SCALAR(transmitTick); - if (transmitTick) - 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); - UNSERIALIZE_SCALAR(multicastHashEnable); - - /* - * Keep track of pending interrupt status. - */ - UNSERIALIZE_SCALAR(intrTick); - UNSERIALIZE_SCALAR(cpuPendingIntr); - Tick intrEventTick; - UNSERIALIZE_SCALAR(intrEventTick); - if (intrEventTick) { - intrEvent = new IntrEvent(this, true); - intrEvent->schedule(intrEventTick); - } - - /* - * re-add addrRanges to bus bridges - */ - if (pioInterface) { - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); - } -} - -Tick -NSGigE::cacheAccess(MemReqPtr &req) -{ - DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", - req->paddr, req->paddr & 0xfff); - - return curTick + pioLatency; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) - - SimObjectParam<EtherInt *> peer; - SimObjectParam<NSGigE *> device; - -END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) - -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(NSGigEInt) - -CREATE_SIM_OBJECT(NSGigEInt) -{ - NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); - - EtherInt *p = (EtherInt *)peer; - if (p) { - dev_int->setPeer(p); - p->setPeer(dev_int); - } - - return dev_int; -} - -REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) - - Param<Tick> clock; - - Param<Addr> addr; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<PhysicalMemory *> physmem; - SimObjectParam<PciConfigAll *> configspace; - SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; - Param<uint32_t> pci_bus; - Param<uint32_t> pci_dev; - Param<uint32_t> pci_func; - - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; - SimObjectParam<Bus*> dma_bus; - SimObjectParam<Bus*> payload_bus; - Param<bool> dma_desc_free; - Param<bool> dma_data_free; - Param<Tick> dma_read_delay; - Param<Tick> dma_write_delay; - Param<Tick> dma_read_factor; - Param<Tick> dma_write_factor; - Param<bool> dma_no_allocate; - Param<Tick> pio_latency; - Param<Tick> intr_delay; - - Param<Tick> rx_delay; - Param<Tick> tx_delay; - Param<uint32_t> rx_fifo_size; - Param<uint32_t> tx_fifo_size; - - Param<bool> rx_filter; - Param<string> hardware_address; - Param<bool> rx_thread; - Param<bool> tx_thread; - Param<bool> rss; - -END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) - -BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) - - INIT_PARAM(clock, "State machine processor frequency"), - - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM(configspace, "PCI Configspace"), - INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform"), - INIT_PARAM(pci_bus, "PCI bus"), - INIT_PARAM(pci_dev, "PCI device number"), - INIT_PARAM(pci_func, "PCI function code"), - - INIT_PARAM(hier, "Hierarchy global variables"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), - INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), - INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), - INIT_PARAM(dma_data_free, "DMA of Data is free"), - INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), - INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), - INIT_PARAM(dma_read_factor, "multiplier for dma reads"), - INIT_PARAM(dma_write_factor, "multiplier for dma writes"), - INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), - INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), - INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), - - INIT_PARAM(rx_delay, "Receive Delay"), - INIT_PARAM(tx_delay, "Transmit Delay"), - INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), - INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), - - INIT_PARAM(rx_filter, "Enable Receive Filter"), - INIT_PARAM(hardware_address, "Ethernet Hardware Address"), - INIT_PARAM(rx_thread, ""), - INIT_PARAM(tx_thread, ""), - INIT_PARAM(rss, "") - -END_INIT_SIM_OBJECT_PARAMS(NSGigE) - - -CREATE_SIM_OBJECT(NSGigE) -{ - NSGigE::Params *params = new NSGigE::Params; - - params->name = getInstanceName(); - - params->clock = clock; - - params->mmu = mmu; - params->pmem = physmem; - params->configSpace = configspace; - params->configData = configdata; - params->plat = platform; - params->busNum = pci_bus; - params->deviceNum = pci_dev; - params->functionNum = pci_func; - - params->hier = hier; - params->pio_bus = pio_bus; - params->header_bus = dma_bus; - params->payload_bus = payload_bus; - params->dma_desc_free = dma_desc_free; - params->dma_data_free = dma_data_free; - params->dma_read_delay = dma_read_delay; - params->dma_write_delay = dma_write_delay; - params->dma_read_factor = dma_read_factor; - params->dma_write_factor = dma_write_factor; - params->dma_no_allocate = dma_no_allocate; - params->pio_latency = pio_latency; - params->intr_delay = intr_delay; - - params->rx_delay = rx_delay; - params->tx_delay = tx_delay; - params->rx_fifo_size = rx_fifo_size; - params->tx_fifo_size = tx_fifo_size; - - params->rx_filter = rx_filter; - params->eaddr = hardware_address; - params->rx_thread = rx_thread; - params->tx_thread = tx_thread; - params->rss = rss; - - return new NSGigE(params); -} - -REGISTER_SIM_OBJECT("NSGigE", NSGigE) diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh deleted file mode 100644 index 59c55056e..000000000 --- a/dev/ns_gige.hh +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Device module for modelling the National Semiconductor - * DP83820 ethernet controller - */ - -#ifndef __DEV_NS_GIGE_HH__ -#define __DEV_NS_GIGE_HH__ - -#include "base/inet.hh" -#include "base/statistics.hh" -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "dev/io_device.hh" -#include "dev/ns_gige_reg.h" -#include "dev/pcidev.hh" -#include "dev/pktfifo.hh" -#include "mem/bus/bus.hh" -#include "sim/eventq.hh" - -// Hash filtering constants -const uint16_t FHASH_ADDR = 0x100; -const uint16_t FHASH_SIZE = 0x100; - -// EEPROM constants -const uint8_t EEPROM_READ = 0x2; -const uint8_t EEPROM_SIZE = 64; // Size in words of NSC93C46 EEPROM -const uint8_t EEPROM_PMATCH2_ADDR = 0xA; // EEPROM Address of PMATCH word 2 -const uint8_t EEPROM_PMATCH1_ADDR = 0xB; // EEPROM Address of PMATCH word 1 -const uint8_t EEPROM_PMATCH0_ADDR = 0xC; // EEPROM Address of PMATCH word 0 - -/** - * Ethernet device registers - */ -struct dp_regs { - uint32_t command; - uint32_t config; - uint32_t mear; - uint32_t ptscr; - uint32_t isr; - uint32_t imr; - uint32_t ier; - uint32_t ihr; - uint32_t txdp; - uint32_t txdp_hi; - uint32_t txcfg; - uint32_t gpior; - uint32_t rxdp; - uint32_t rxdp_hi; - uint32_t rxcfg; - uint32_t pqcr; - uint32_t wcsr; - uint32_t pcr; - uint32_t rfcr; - uint32_t rfdr; - uint32_t brar; - uint32_t brdr; - uint32_t srr; - uint32_t mibc; - uint32_t vrcr; - uint32_t vtcr; - uint32_t vdr; - uint32_t ccsr; - uint32_t tbicr; - uint32_t tbisr; - uint32_t tanar; - uint32_t tanlpar; - uint32_t taner; - uint32_t tesr; -}; - -struct dp_rom { - /** - * for perfect match memory. - * the linux driver doesn't use any other ROM - */ - uint8_t perfectMatch[ETH_ADDR_LEN]; - - /** - * for hash table memory. - * used by the freebsd driver - */ - uint8_t filterHash[FHASH_SIZE]; -}; - -class NSGigEInt; -class PhysicalMemory; -class BaseInterface; -class HierParams; -class Bus; -class PciConfigAll; - -/** - * NS DP83820 Ethernet device model - */ -class NSGigE : public PciDev -{ - public: - /** Transmit State Machine states */ - enum TxState - { - txIdle, - txDescRefr, - txDescRead, - txFifoBlock, - txFragRead, - txDescWrite, - txAdvance - }; - - /** Receive State Machine States */ - enum RxState - { - rxIdle, - rxDescRefr, - rxDescRead, - rxFifoBlock, - rxFragWrite, - rxDescWrite, - rxAdvance - }; - - enum DmaState - { - dmaIdle, - dmaReading, - dmaWriting, - dmaReadWaiting, - dmaWriteWaiting - }; - - /** EEPROM State Machine States */ - enum EEPROMState - { - eepromStart, - eepromGetOpcode, - eepromGetAddress, - eepromRead - }; - - private: - Addr addr; - static const Addr size = sizeof(dp_regs); - - protected: - /** device register file */ - dp_regs regs; - dp_rom rom; - - /** pci settings */ - bool ioEnable; -#if 0 - bool memEnable; - bool bmEnable; -#endif - - /*** BASIC STRUCTURES FOR TX/RX ***/ - /* Data FIFOs */ - PacketFifo txFifo; - PacketFifo rxFifo; - - /** various helper vars */ - PacketPtr txPacket; - PacketPtr rxPacket; - uint8_t *txPacketBufPtr; - uint8_t *rxPacketBufPtr; - uint32_t txXferLen; - uint32_t rxXferLen; - bool rxDmaFree; - bool txDmaFree; - - /** DescCaches */ - ns_desc32 txDesc32; - ns_desc32 rxDesc32; - ns_desc64 txDesc64; - ns_desc64 rxDesc64; - - /* state machine cycle time */ - Tick clock; - inline Tick cycles(int numCycles) const { return numCycles * clock; } - - /* tx State Machine */ - TxState txState; - bool txEnable; - - /** Current Transmit Descriptor Done */ - bool CTDD; - /** halt the tx state machine after next packet */ - bool txHalt; - /** ptr to the next byte in the current fragment */ - Addr txFragPtr; - /** count of bytes remaining in the current descriptor */ - uint32_t txDescCnt; - DmaState txDmaState; - - /** rx State Machine */ - RxState rxState; - bool rxEnable; - - /** Current Receive Descriptor Done */ - bool CRDD; - /** num of bytes in the current packet being drained from rxDataFifo */ - uint32_t rxPktBytes; - /** halt the rx state machine after current packet */ - bool rxHalt; - /** ptr to the next byte in current fragment */ - Addr rxFragPtr; - /** count of bytes remaining in the current descriptor */ - uint32_t rxDescCnt; - DmaState rxDmaState; - - bool extstsEnable; - - /** EEPROM State Machine */ - EEPROMState eepromState; - bool eepromClk; - uint8_t eepromBitsToRx; - uint8_t eepromOpcode; - uint8_t eepromAddress; - uint16_t eepromData; - - protected: - Tick dmaReadDelay; - Tick dmaWriteDelay; - - Tick dmaReadFactor; - Tick dmaWriteFactor; - - void *rxDmaData; - Addr rxDmaAddr; - int rxDmaLen; - bool doRxDmaRead(); - bool doRxDmaWrite(); - void rxDmaReadCopy(); - void rxDmaWriteCopy(); - - void *txDmaData; - Addr txDmaAddr; - int txDmaLen; - bool doTxDmaRead(); - bool doTxDmaWrite(); - void txDmaReadCopy(); - void txDmaWriteCopy(); - - void rxDmaReadDone(); - friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>; - EventWrapper<NSGigE, &NSGigE::rxDmaReadDone> rxDmaReadEvent; - - void rxDmaWriteDone(); - friend class EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone>; - EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone> rxDmaWriteEvent; - - void txDmaReadDone(); - friend class EventWrapper<NSGigE, &NSGigE::txDmaReadDone>; - EventWrapper<NSGigE, &NSGigE::txDmaReadDone> txDmaReadEvent; - - void txDmaWriteDone(); - friend class EventWrapper<NSGigE, &NSGigE::txDmaWriteDone>; - EventWrapper<NSGigE, &NSGigE::txDmaWriteDone> txDmaWriteEvent; - - bool dmaDescFree; - bool dmaDataFree; - - protected: - Tick txDelay; - Tick rxDelay; - - void txReset(); - void rxReset(); - void regsReset(); - - void rxKick(); - Tick rxKickTick; - typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent; - friend void RxKickEvent::process(); - RxKickEvent rxKickEvent; - - void txKick(); - Tick txKickTick; - typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent; - friend void TxKickEvent::process(); - TxKickEvent txKickEvent; - - void eepromKick(); - - /** - * Retransmit event - */ - void transmit(); - void txEventTransmit() - { - transmit(); - if (txState == txFifoBlock) - txKick(); - } - typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent; - friend void TxEvent::process(); - TxEvent txEvent; - - void txDump() const; - void rxDump() const; - - /** - * receive address filter - */ - bool rxFilterEnable; - bool rxFilter(const PacketPtr &packet); - bool acceptBroadcast; - bool acceptMulticast; - bool acceptUnicast; - bool acceptPerfect; - bool acceptArp; - bool multicastHashEnable; - - PhysicalMemory *physmem; - - /** - * Interrupt management - */ - void devIntrPost(uint32_t interrupts); - void devIntrClear(uint32_t interrupts); - void devIntrChangeMask(); - - Tick intrDelay; - Tick intrTick; - bool cpuPendingIntr; - void cpuIntrPost(Tick when); - void cpuInterrupt(); - void cpuIntrClear(); - - typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent; - friend void IntrEvent::process(); - IntrEvent *intrEvent; - NSGigEInt *interface; - - public: - struct Params : public PciDev::Params - { - PhysicalMemory *pmem; - HierParams *hier; - Bus *pio_bus; - Bus *header_bus; - Bus *payload_bus; - Tick clock; - Tick intr_delay; - Tick tx_delay; - Tick rx_delay; - 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; - bool rx_filter; - Net::EthAddr eaddr; - uint32_t tx_fifo_size; - uint32_t rx_fifo_size; - bool rx_thread; - bool tx_thread; - bool rss; - bool dma_no_allocate; - }; - - NSGigE(Params *params); - ~NSGigE(); - const Params *params() const { return (const Params *)_params; } - - virtual void writeConfig(int offset, int size, const uint8_t *data); - virtual void readConfig(int offset, int size, uint8_t *data); - - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - bool cpuIntrPending() const; - void cpuIntrAck() { cpuIntrClear(); } - - bool recvPacket(PacketPtr packet); - void transferDone(); - - void setInterface(NSGigEInt *i) { assert(!interface); interface = i; } - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - - public: - void regStats(); - - private: - Stats::Scalar<> txBytes; - Stats::Scalar<> rxBytes; - Stats::Scalar<> txPackets; - Stats::Scalar<> rxPackets; - Stats::Scalar<> txIpChecksums; - Stats::Scalar<> rxIpChecksums; - Stats::Scalar<> txTcpChecksums; - Stats::Scalar<> rxTcpChecksums; - Stats::Scalar<> txUdpChecksums; - Stats::Scalar<> rxUdpChecksums; - Stats::Scalar<> descDmaReads; - Stats::Scalar<> descDmaWrites; - Stats::Scalar<> descDmaRdBytes; - Stats::Scalar<> descDmaWrBytes; - Stats::Formula totBandwidth; - Stats::Formula totPackets; - Stats::Formula totBytes; - Stats::Formula totPacketRate; - Stats::Formula txBandwidth; - Stats::Formula rxBandwidth; - Stats::Formula txPacketRate; - Stats::Formula rxPacketRate; - Stats::Scalar<> postedSwi; - Stats::Formula coalescedSwi; - Stats::Scalar<> totalSwi; - Stats::Scalar<> postedRxIdle; - Stats::Formula coalescedRxIdle; - Stats::Scalar<> totalRxIdle; - Stats::Scalar<> postedRxOk; - Stats::Formula coalescedRxOk; - Stats::Scalar<> totalRxOk; - Stats::Scalar<> postedRxDesc; - Stats::Formula coalescedRxDesc; - Stats::Scalar<> totalRxDesc; - Stats::Scalar<> postedTxOk; - Stats::Formula coalescedTxOk; - Stats::Scalar<> totalTxOk; - Stats::Scalar<> postedTxIdle; - Stats::Formula coalescedTxIdle; - Stats::Scalar<> totalTxIdle; - Stats::Scalar<> postedTxDesc; - Stats::Formula coalescedTxDesc; - Stats::Scalar<> totalTxDesc; - Stats::Scalar<> postedRxOrn; - Stats::Formula coalescedRxOrn; - Stats::Scalar<> totalRxOrn; - Stats::Formula coalescedTotal; - Stats::Scalar<> postedInterrupts; - Stats::Scalar<> droppedPackets; - - public: - Tick cacheAccess(MemReqPtr &req); -}; - -/* - * Ethernet Interface for an Ethernet Device - */ -class NSGigEInt : public EtherInt -{ - private: - NSGigE *dev; - - public: - NSGigEInt(const std::string &name, NSGigE *d) - : EtherInt(name), dev(d) { dev->setInterface(this); } - - virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } - virtual void sendDone() { dev->transferDone(); } -}; - -#endif // __DEV_NS_GIGE_HH__ diff --git a/dev/ns_gige_reg.h b/dev/ns_gige_reg.h deleted file mode 100644 index 5f6fa2cc5..000000000 --- a/dev/ns_gige_reg.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Ethernet device register definitions for the National - * Semiconductor DP83820 Ethernet controller - */ - -#ifndef __DEV_NS_GIGE_REG_H__ -#define __DEV_NS_GIGE_REG_H__ - -/* Device Register Address Map */ -#define CR 0x00 -#define CFGR 0x04 -#define MEAR 0x08 -#define PTSCR 0x0c -#define ISR 0x10 -#define IMR 0x14 -#define IER 0x18 -#define IHR 0x1c -#define TXDP 0x20 -#define TXDP_HI 0x24 -#define TX_CFG 0x28 -#define GPIOR 0x2c -#define RXDP 0x30 -#define RXDP_HI 0x34 -#define RX_CFG 0x38 -#define PQCR 0x3c -#define WCSR 0x40 -#define PCR 0x44 -#define RFCR 0x48 -#define RFDR 0x4c -#define BRAR 0x50 -#define BRDR 0x54 -#define SRR 0x58 -#define MIBC 0x5c -#define MIB_START 0x60 -#define MIB_END 0x88 -#define VRCR 0xbc -#define VTCR 0xc0 -#define VDR 0xc4 -#define CCSR 0xcc -#define TBICR 0xe0 -#define TBISR 0xe4 -#define TANAR 0xe8 -#define TANLPAR 0xec -#define TANER 0xf0 -#define TESR 0xf4 -#define M5REG 0xf8 -#define LAST 0xf8 -#define RESERVED 0xfc - -/* Chip Command Register */ -#define CR_TXE 0x00000001 -#define CR_TXD 0x00000002 -#define CR_RXE 0x00000004 -#define CR_RXD 0x00000008 -#define CR_TXR 0x00000010 -#define CR_RXR 0x00000020 -#define CR_SWI 0x00000080 -#define CR_RST 0x00000100 - -/* configuration register */ -#define CFGR_LNKSTS 0x80000000 -#define CFGR_SPDSTS 0x60000000 -#define CFGR_SPDSTS1 0x40000000 -#define CFGR_SPDSTS0 0x20000000 -#define CFGR_DUPSTS 0x10000000 -#define CFGR_TBI_EN 0x01000000 -#define CFGR_RESERVED 0x0e000000 -#define CFGR_MODE_1000 0x00400000 -#define CFGR_AUTO_1000 0x00200000 -#define CFGR_PINT_CTL 0x001c0000 -#define CFGR_PINT_DUPSTS 0x00100000 -#define CFGR_PINT_LNKSTS 0x00080000 -#define CFGR_PINT_SPDSTS 0x00040000 -#define CFGR_TMRTEST 0x00020000 -#define CFGR_MRM_DIS 0x00010000 -#define CFGR_MWI_DIS 0x00008000 -#define CFGR_T64ADDR 0x00004000 -#define CFGR_PCI64_DET 0x00002000 -#define CFGR_DATA64_EN 0x00001000 -#define CFGR_M64ADDR 0x00000800 -#define CFGR_PHY_RST 0x00000400 -#define CFGR_PHY_DIS 0x00000200 -#define CFGR_EXTSTS_EN 0x00000100 -#define CFGR_REQALG 0x00000080 -#define CFGR_SB 0x00000040 -#define CFGR_POW 0x00000020 -#define CFGR_EXD 0x00000010 -#define CFGR_PESEL 0x00000008 -#define CFGR_BROM_DIS 0x00000004 -#define CFGR_EXT_125 0x00000002 -#define CFGR_BEM 0x00000001 - -/* EEPROM access register */ -#define MEAR_EEDI 0x00000001 -#define MEAR_EEDO 0x00000002 -#define MEAR_EECLK 0x00000004 -#define MEAR_EESEL 0x00000008 -#define MEAR_MDIO 0x00000010 -#define MEAR_MDDIR 0x00000020 -#define MEAR_MDC 0x00000040 - -/* PCI test control register */ -#define PTSCR_EEBIST_FAIL 0x00000001 -#define PTSCR_EEBIST_EN 0x00000002 -#define PTSCR_EELOAD_EN 0x00000004 -#define PTSCR_RBIST_FAIL 0x000001b8 -#define PTSCR_RBIST_DONE 0x00000200 -#define PTSCR_RBIST_EN 0x00000400 -#define PTSCR_RBIST_RST 0x00002000 -#define PTSCR_RBIST_RDONLY 0x000003f9 - -/* interrupt status register */ -#define ISR_RESERVE 0x80000000 -#define ISR_TXDESC3 0x40000000 -#define ISR_TXDESC2 0x20000000 -#define ISR_TXDESC1 0x10000000 -#define ISR_TXDESC0 0x08000000 -#define ISR_RXDESC3 0x04000000 -#define ISR_RXDESC2 0x02000000 -#define ISR_RXDESC1 0x01000000 -#define ISR_RXDESC0 0x00800000 -#define ISR_TXRCMP 0x00400000 -#define ISR_RXRCMP 0x00200000 -#define ISR_DPERR 0x00100000 -#define ISR_SSERR 0x00080000 -#define ISR_RMABT 0x00040000 -#define ISR_RTABT 0x00020000 -#define ISR_RXSOVR 0x00010000 -#define ISR_HIBINT 0x00008000 -#define ISR_PHY 0x00004000 -#define ISR_PME 0x00002000 -#define ISR_SWI 0x00001000 -#define ISR_MIB 0x00000800 -#define ISR_TXURN 0x00000400 -#define ISR_TXIDLE 0x00000200 -#define ISR_TXERR 0x00000100 -#define ISR_TXDESC 0x00000080 -#define ISR_TXOK 0x00000040 -#define ISR_RXORN 0x00000020 -#define ISR_RXIDLE 0x00000010 -#define ISR_RXEARLY 0x00000008 -#define ISR_RXERR 0x00000004 -#define ISR_RXDESC 0x00000002 -#define ISR_RXOK 0x00000001 -#define ISR_ALL 0x7FFFFFFF -#define ISR_DELAY (ISR_TXIDLE|ISR_TXDESC|ISR_TXOK| \ - ISR_RXIDLE|ISR_RXDESC|ISR_RXOK) -#define ISR_NODELAY (ISR_ALL & ~ISR_DELAY) -#define ISR_IMPL (ISR_SWI|ISR_TXIDLE|ISR_TXDESC|ISR_TXOK|ISR_RXORN| \ - ISR_RXIDLE|ISR_RXDESC|ISR_RXOK) -#define ISR_NOIMPL (ISR_ALL & ~ISR_IMPL) - -/* transmit configuration register */ -#define TX_CFG_CSI 0x80000000 -#define TX_CFG_HBI 0x40000000 -#define TX_CFG_MLB 0x20000000 -#define TX_CFG_ATP 0x10000000 -#define TX_CFG_ECRETRY 0x00800000 -#define TX_CFG_BRST_DIS 0x00080000 -#define TX_CFG_MXDMA1024 0x00000000 -#define TX_CFG_MXDMA512 0x00700000 -#define TX_CFG_MXDMA256 0x00600000 -#define TX_CFG_MXDMA128 0x00500000 -#define TX_CFG_MXDMA64 0x00400000 -#define TX_CFG_MXDMA32 0x00300000 -#define TX_CFG_MXDMA16 0x00200000 -#define TX_CFG_MXDMA8 0x00100000 -#define TX_CFG_MXDMA 0x00700000 - -#define TX_CFG_FLTH_MASK 0x0000ff00 -#define TX_CFG_DRTH_MASK 0x000000ff - -/*general purpose I/O control register */ -#define GPIOR_UNUSED 0xffff8000 -#define GPIOR_GP5_IN 0x00004000 -#define GPIOR_GP4_IN 0x00002000 -#define GPIOR_GP3_IN 0x00001000 -#define GPIOR_GP2_IN 0x00000800 -#define GPIOR_GP1_IN 0x00000400 -#define GPIOR_GP5_OE 0x00000200 -#define GPIOR_GP4_OE 0x00000100 -#define GPIOR_GP3_OE 0x00000080 -#define GPIOR_GP2_OE 0x00000040 -#define GPIOR_GP1_OE 0x00000020 -#define GPIOR_GP5_OUT 0x00000010 -#define GPIOR_GP4_OUT 0x00000008 -#define GPIOR_GP3_OUT 0x00000004 -#define GPIOR_GP2_OUT 0x00000002 -#define GPIOR_GP1_OUT 0x00000001 - -/* receive configuration register */ -#define RX_CFG_AEP 0x80000000 -#define RX_CFG_ARP 0x40000000 -#define RX_CFG_STRIPCRC 0x20000000 -#define RX_CFG_RX_FD 0x10000000 -#define RX_CFG_ALP 0x08000000 -#define RX_CFG_AIRL 0x04000000 -#define RX_CFG_MXDMA512 0x00700000 -#define RX_CFG_MXDMA 0x00700000 -#define RX_CFG_DRTH 0x0000003e -#define RX_CFG_DRTH0 0x00000002 - -/* pause control status register */ -#define PCR_PSEN (1 << 31) -#define PCR_PS_MCAST (1 << 30) -#define PCR_PS_DA (1 << 29) -#define PCR_STHI_8 (3 << 23) -#define PCR_STLO_4 (1 << 23) -#define PCR_FFHI_8K (3 << 21) -#define PCR_FFLO_4K (1 << 21) -#define PCR_PAUSE_CNT 0xFFFE - -/*receive filter/match control register */ -#define RFCR_RFEN 0x80000000 -#define RFCR_AAB 0x40000000 -#define RFCR_AAM 0x20000000 -#define RFCR_AAU 0x10000000 -#define RFCR_APM 0x08000000 -#define RFCR_APAT 0x07800000 -#define RFCR_APAT3 0x04000000 -#define RFCR_APAT2 0x02000000 -#define RFCR_APAT1 0x01000000 -#define RFCR_APAT0 0x00800000 -#define RFCR_AARP 0x00400000 -#define RFCR_MHEN 0x00200000 -#define RFCR_UHEN 0x00100000 -#define RFCR_ULM 0x00080000 -#define RFCR_RFADDR 0x000003ff - -/* receive filter/match data register */ -#define RFDR_BMASK 0x00030000 -#define RFDR_RFDATA0 0x000000ff -#define RFDR_RFDATA1 0x0000ff00 - -/* management information base control register */ -#define MIBC_MIBS 0x00000008 -#define MIBC_ACLR 0x00000004 -#define MIBC_FRZ 0x00000002 -#define MIBC_WRN 0x00000001 - -/* VLAN/IP receive control register */ -#define VRCR_RUDPE 0x00000080 -#define VRCR_RTCPE 0x00000040 -#define VRCR_RIPE 0x00000020 -#define VRCR_IPEN 0x00000010 -#define VRCR_DUTF 0x00000008 -#define VRCR_DVTF 0x00000004 -#define VRCR_VTREN 0x00000002 -#define VRCR_VTDEN 0x00000001 - -/* VLAN/IP transmit control register */ -#define VTCR_PPCHK 0x00000008 -#define VTCR_GCHK 0x00000004 -#define VTCR_VPPTI 0x00000002 -#define VTCR_VGTI 0x00000001 - -/* Clockrun Control/Status Register */ -#define CCSR_CLKRUN_EN 0x00000001 - -/* TBI control register */ -#define TBICR_MR_LOOPBACK 0x00004000 -#define TBICR_MR_AN_ENABLE 0x00001000 -#define TBICR_MR_RESTART_AN 0x00000200 - -/* TBI status register */ -#define TBISR_MR_LINK_STATUS 0x00000020 -#define TBISR_MR_AN_COMPLETE 0x00000004 - -/* TBI auto-negotiation advertisement register */ -#define TANAR_NP 0x00008000 -#define TANAR_RF2 0x00002000 -#define TANAR_RF1 0x00001000 -#define TANAR_PS2 0x00000100 -#define TANAR_PS1 0x00000080 -#define TANAR_HALF_DUP 0x00000040 -#define TANAR_FULL_DUP 0x00000020 -#define TANAR_UNUSED 0x00000E1F - -/* M5 control register */ -#define M5REG_RESERVED 0xfffffffc -#define M5REG_RSS 0x00000004 -#define M5REG_RX_THREAD 0x00000002 -#define M5REG_TX_THREAD 0x00000001 - -struct ns_desc32 { - uint32_t link; /* link field to next descriptor in linked list */ - uint32_t bufptr; /* pointer to the first fragment or buffer */ - uint32_t cmdsts; /* command/status field */ - uint32_t extsts; /* extended status field for VLAN and IP info */ -}; - -struct ns_desc64 { - uint64_t link; /* link field to next descriptor in linked list */ - uint64_t bufptr; /* pointer to the first fragment or buffer */ - uint32_t cmdsts; /* command/status field */ - uint32_t extsts; /* extended status field for VLAN and IP info */ -}; - -/* cmdsts flags for descriptors */ -#define CMDSTS_OWN 0x80000000 -#define CMDSTS_MORE 0x40000000 -#define CMDSTS_INTR 0x20000000 -#define CMDSTS_ERR 0x10000000 -#define CMDSTS_OK 0x08000000 -#define CMDSTS_LEN_MASK 0x0000ffff - -#define CMDSTS_DEST_MASK 0x01800000 -#define CMDSTS_DEST_SELF 0x00800000 -#define CMDSTS_DEST_MULTI 0x01000000 - -/* extended flags for descriptors */ -#define EXTSTS_UDPERR 0x00400000 -#define EXTSTS_UDPPKT 0x00200000 -#define EXTSTS_TCPERR 0x00100000 -#define EXTSTS_TCPPKT 0x00080000 -#define EXTSTS_IPERR 0x00040000 -#define EXTSTS_IPPKT 0x00020000 - - -/* speed status */ -#define SPDSTS_POLARITY (CFGR_SPDSTS1 | CFGR_SPDSTS0 | CFGR_DUPSTS | (lnksts ? CFGR_LNKSTS : 0)) - -#endif /* __DEV_NS_GIGE_REG_H__ */ diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc deleted file mode 100644 index d55084fa5..000000000 --- a/dev/pciconfigall.cc +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * PCI Configspace implementation - */ - -#include <deque> -#include <string> -#include <vector> -#include <bitset> - -#include "base/trace.hh" -#include "dev/pciconfigall.hh" -#include "dev/pcidev.hh" -#include "dev/pcireg.h" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -using namespace TheISA; - -PciConfigAll::PciConfigAll(const string &name, - Addr a, MemoryController *mmu, - HierParams *hier, Bus *pio_bus, Tick pio_latency) - : PioDevice(name, NULL), addr(a) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &PciConfigAll::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } - - // 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++) - devices[x][y] = NULL; -} - -// If two interrupts share the same line largely bad things will happen. -// Since we don't track how many times an interrupt was set and correspondingly -// cleared two devices on the same interrupt line and assert and deassert each -// others interrupt "line". Interrupts will not work correctly. -void -PciConfigAll::startup() -{ - bitset<256> intLines; - PciDev *tempDev; - uint8_t intline; - - for (int x = 0; x < MAX_PCI_DEV; x++) { - for (int y = 0; y < MAX_PCI_FUNC; y++) { - if (devices[x][y] != NULL) { - tempDev = devices[x][y]; - intline = tempDev->interruptLine(); - if (intLines.test(intline)) - warn("Interrupt line %#X is used multiple times" - "(You probably want to fix this).\n", (uint32_t)intline); - else - intLines.set(intline); - } // devices != NULL - } // PCI_FUNC - } // PCI_DEV - -} - -Fault -PciConfigAll::read(MemReqPtr &req, uint8_t *data) -{ - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", - req->vaddr, daddr, req->size); - - int device = (daddr >> 11) & 0x1F; - int func = (daddr >> 8) & 0x7; - int reg = daddr & 0xFF; - - if (devices[device][func] == NULL) { - switch (req->size) { - // case sizeof(uint64_t): - // *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF; - // return NoFault; - case sizeof(uint32_t): - *(uint32_t*)data = 0xFFFFFFFF; - return NoFault; - case sizeof(uint16_t): - *(uint16_t*)data = 0xFFFF; - return NoFault; - case sizeof(uint8_t): - *(uint8_t*)data = 0xFF; - return NoFault; - default: - panic("invalid access size(?) for PCI configspace!\n"); - } - } else { - switch (req->size) { - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - devices[device][func]->readConfig(reg, req->size, data); - return NoFault; - default: - panic("invalid access size(?) for PCI configspace!\n"); - } - } - - DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n", - daddr, req->size); - - return NoFault; -} - -Fault -PciConfigAll::write(MemReqPtr &req, const uint8_t *data) -{ - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - int device = (daddr >> 11) & 0x1F; - int func = (daddr >> 8) & 0x7; - int reg = daddr & 0xFF; - - if (devices[device][func] == NULL) - panic("Attempting to write to config space on non-existant device\n"); - else if (req->size != sizeof(uint8_t) && - req->size != sizeof(uint16_t) && - req->size != sizeof(uint32_t)) - panic("invalid access size(?) for PCI configspace!\n"); - - DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n", - req->vaddr, req->size, *(uint32_t*)data); - - devices[device][func]->writeConfig(reg, req->size, data); - - return NoFault; -} - -void -PciConfigAll::serialize(std::ostream &os) -{ - /* - * 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 §ion) -{ - /* - * 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 + pioLatency; -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) - - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - Param<Addr> mask; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - -END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) - -BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll) - - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mask, "Address Mask"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) - -END_INIT_SIM_OBJECT_PARAMS(PciConfigAll) - -CREATE_SIM_OBJECT(PciConfigAll) -{ - return new PciConfigAll(getInstanceName(), addr, mmu, hier, pio_bus, - pio_latency); -} - -REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll) - -#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh deleted file mode 100644 index c6a0241d8..000000000 --- a/dev/pciconfigall.hh +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * @file - * PCI Config space implementation. - */ - -#ifndef __PCICONFIGALL_HH__ -#define __PCICONFIGALL_HH__ - -#include "dev/pcireg.h" -#include "base/range.hh" -#include "dev/io_device.hh" - - -static const uint32_t MAX_PCI_DEV = 32; -static const uint32_t MAX_PCI_FUNC = 8; - -class PciDev; -class MemoryController; - -/** - * PCI Config Space - * All of PCI config space needs to return -1 on Tsunami, except - * the devices that exist. This device maps the entire bus config - * space and passes the requests on to TsunamiPCIDev devices as - * appropriate. - */ -class PciConfigAll : public PioDevice -{ - private: - Addr addr; - static const Addr size = 0xffffff; - - /** - * Pointers to all the devices that are registered with this - * particular config space. - */ - PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC]; - - public: - /** - * 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 *pio_bus, Tick pio_latency); - - - /** - * 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); - - /** - * Start up function to check if more than one person is using an interrupt line - * and print a warning if such a case exists - */ - virtual void startup(); - - /** - * 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 §ion); - - /** - * 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 deleted file mode 100644 index a05ee3803..000000000 --- a/dev/pcidev.cc +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * A single PCI device configuration space entry. - */ - -#include <list> -#include <sstream> -#include <string> -#include <vector> - -#include "base/inifile.hh" -#include "base/misc.hh" -#include "base/str.hh" // for to_number -#include "base/trace.hh" -#include "dev/pcidev.hh" -#include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" -#include "sim/param.hh" -#include "sim/root.hh" -#include "dev/tsunamireg.h" - -using namespace std; - -PciDev::PciDev(Params *p) - : DmaDevice(p->name, p->plat), _params(p), plat(p->plat), - configData(p->configData) -{ - // copy the config data from the PciConfigData object - if (configData) { - memcpy(config.data, configData->config.data, sizeof(config.data)); - memcpy(BARSize, configData->BARSize, sizeof(BARSize)); - memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs)); - } else - panic("NULL pointer to configuration data"); - - // Setup pointer in config space to point to this entry - if (p->configSpace->deviceExists(p->deviceNum, p->functionNum)) - panic("Two PCI devices occuping same dev: %#x func: %#x", - p->deviceNum, p->functionNum); - else - p->configSpace->registerDevice(p->deviceNum, p->functionNum, this); -} - -Fault -PciDev::read(MemReqPtr &req, uint8_t *data) -{ return NoFault; } - -Fault -PciDev::write(MemReqPtr &req, const uint8_t *data) -{ return NoFault; } - -Fault -PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -Fault -PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ panic("not implemented"); } - -void -PciDev::readConfig(int offset, int size, uint8_t *data) -{ - if (offset >= PCI_DEVICE_SPECIFIC) - panic("Device specific PCI config space not implemented!\n"); - - switch(size) { - case sizeof(uint8_t): - *data = config.data[offset]; - break; - case sizeof(uint16_t): - *(uint16_t*)data = *(uint16_t*)&config.data[offset]; - break; - case sizeof(uint32_t): - *(uint32_t*)data = *(uint32_t*)&config.data[offset]; - break; - default: - panic("Invalid PCI configuration read size!\n"); - } - - DPRINTF(PCIDEV, - "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", - params()->deviceNum, params()->functionNum, offset, size, - *(uint32_t*)data); -} - -void -PciDev::writeConfig(int offset, int size, const uint8_t *data) -{ - if (offset >= PCI_DEVICE_SPECIFIC) - panic("Device specific PCI config space not implemented!\n"); - - uint8_t &data8 = *(uint8_t*)data; - uint16_t &data16 = *(uint16_t*)data; - uint32_t &data32 = *(uint32_t*)data; - - DPRINTF(PCIDEV, - "write device: %#x function: %#x reg: %#x size: %d data: %#x\n", - params()->deviceNum, params()->functionNum, offset, size, data32); - - switch (size) { - case sizeof(uint8_t): // 1-byte access - switch (offset) { - case PCI0_INTERRUPT_LINE: - config.interruptLine = data8; - case PCI_CACHE_LINE_SIZE: - config.cacheLineSize = data8; - case PCI_LATENCY_TIMER: - config.latencyTimer = data8; - break; - /* Do nothing for these read-only registers */ - case PCI0_INTERRUPT_PIN: - case PCI0_MINIMUM_GRANT: - case PCI0_MAXIMUM_LATENCY: - case PCI_CLASS_CODE: - case PCI_REVISION_ID: - break; - default: - panic("writing to a read only register"); - } - break; - - case sizeof(uint16_t): // 2-byte access - switch (offset) { - case PCI_COMMAND: - config.command = data16; - case PCI_STATUS: - config.status = data16; - case PCI_CACHE_LINE_SIZE: - config.cacheLineSize = data16; - break; - default: - panic("writing to a read only register"); - } - break; - - case sizeof(uint32_t): // 4-byte access - switch (offset) { - case PCI0_BASE_ADDR0: - case PCI0_BASE_ADDR1: - case PCI0_BASE_ADDR2: - case PCI0_BASE_ADDR3: - case PCI0_BASE_ADDR4: - case PCI0_BASE_ADDR5: - - uint32_t barnum, bar_mask; - Addr base_addr, base_size, space_base; - - barnum = BAR_NUMBER(offset); - - if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) { - bar_mask = BAR_IO_MASK; - space_base = TSUNAMI_PCI0_IO; - } else { - bar_mask = BAR_MEM_MASK; - space_base = TSUNAMI_PCI0_MEMORY; - } - - // Writing 0xffffffff to a BAR tells the card to set the - // value of the bar to size of memory it needs - if (letoh(data32) == 0xffffffff) { - // This is I/O Space, bottom two bits are read only - - config.baseAddr[barnum] = letoh( - (~(BARSize[barnum] - 1) & ~bar_mask) | - (letoh(config.baseAddr[barnum]) & bar_mask)); - } else { - MemoryController *mmu = params()->mmu; - - config.baseAddr[barnum] = letoh( - (letoh(data32) & ~bar_mask) | - (letoh(config.baseAddr[barnum]) & bar_mask)); - - if (letoh(config.baseAddr[barnum]) & ~bar_mask) { - base_addr = (letoh(data32) & ~bar_mask) + space_base; - base_size = BARSize[barnum]; - - // It's never been set - if (BARAddrs[barnum] == 0) - mmu->add_child((FunctionalMemory *)this, - RangeSize(base_addr, base_size)); - else - mmu->update_child((FunctionalMemory *)this, - RangeSize(BARAddrs[barnum], base_size), - RangeSize(base_addr, base_size)); - - BARAddrs[barnum] = base_addr; - } - } - break; - - case PCI0_ROM_BASE_ADDR: - if (letoh(data32) == 0xfffffffe) - config.expansionROM = htole((uint32_t)0xffffffff); - else - config.expansionROM = data32; - break; - - case PCI_COMMAND: - // This could also clear some of the error bits in the Status - // register. However they should never get set, so lets ignore - // it for now - config.command = data16; - break; - - default: - DPRINTF(PCIDEV, "Writing to a read only register"); - } - break; - - default: - panic("invalid access size"); - } -} - -void -PciDev::serialize(ostream &os) -{ - SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); - SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); - SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); -} - -void -PciDev::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); - UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); - UNSERIALIZE_ARRAY(config.data, - sizeof(config.data) / sizeof(config.data[0])); - - // Add the MMU mappings for the BARs - for (int i=0; i < 6; i++) { - if (BARAddrs[i] != 0) - params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i])); - } -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) - - Param<uint16_t> VendorID; - Param<uint16_t> DeviceID; - Param<uint16_t> Command; - Param<uint16_t> Status; - Param<uint8_t> Revision; - Param<uint8_t> ProgIF; - Param<uint8_t> SubClassCode; - Param<uint8_t> ClassCode; - Param<uint8_t> CacheLineSize; - Param<uint8_t> LatencyTimer; - Param<uint8_t> HeaderType; - Param<uint8_t> BIST; - Param<uint32_t> BAR0; - Param<uint32_t> BAR1; - Param<uint32_t> BAR2; - Param<uint32_t> BAR3; - Param<uint32_t> BAR4; - Param<uint32_t> BAR5; - Param<uint32_t> CardbusCIS; - Param<uint16_t> SubsystemVendorID; - Param<uint16_t> SubsystemID; - Param<uint32_t> ExpansionROM; - Param<uint8_t> InterruptLine; - Param<uint8_t> InterruptPin; - Param<uint8_t> MinimumGrant; - Param<uint8_t> MaximumLatency; - Param<uint32_t> BAR0Size; - Param<uint32_t> BAR1Size; - Param<uint32_t> BAR2Size; - Param<uint32_t> BAR3Size; - Param<uint32_t> BAR4Size; - Param<uint32_t> BAR5Size; - -END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) - -BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData) - - INIT_PARAM(VendorID, "Vendor ID"), - INIT_PARAM(DeviceID, "Device ID"), - INIT_PARAM_DFLT(Command, "Command Register", 0x00), - INIT_PARAM_DFLT(Status, "Status Register", 0x00), - INIT_PARAM_DFLT(Revision, "Device Revision", 0x00), - INIT_PARAM_DFLT(ProgIF, "Programming Interface", 0x00), - INIT_PARAM(SubClassCode, "Sub-Class Code"), - INIT_PARAM(ClassCode, "Class Code"), - INIT_PARAM_DFLT(CacheLineSize, "System Cacheline Size", 0x00), - INIT_PARAM_DFLT(LatencyTimer, "PCI Latency Timer", 0x00), - INIT_PARAM_DFLT(HeaderType, "PCI Header Type", 0x00), - INIT_PARAM_DFLT(BIST, "Built In Self Test", 0x00), - INIT_PARAM_DFLT(BAR0, "Base Address Register 0", 0x00), - INIT_PARAM_DFLT(BAR1, "Base Address Register 1", 0x00), - INIT_PARAM_DFLT(BAR2, "Base Address Register 2", 0x00), - INIT_PARAM_DFLT(BAR3, "Base Address Register 3", 0x00), - INIT_PARAM_DFLT(BAR4, "Base Address Register 4", 0x00), - INIT_PARAM_DFLT(BAR5, "Base Address Register 5", 0x00), - INIT_PARAM_DFLT(CardbusCIS, "Cardbus Card Information Structure", 0x00), - INIT_PARAM_DFLT(SubsystemVendorID, "Subsystem Vendor ID", 0x00), - INIT_PARAM_DFLT(SubsystemID, "Subsystem ID", 0x00), - INIT_PARAM_DFLT(ExpansionROM, "Expansion ROM Base Address Register", 0x00), - INIT_PARAM(InterruptLine, "Interrupt Line Register"), - INIT_PARAM(InterruptPin, "Interrupt Pin Register"), - INIT_PARAM_DFLT(MinimumGrant, "Minimum Grant", 0x00), - INIT_PARAM_DFLT(MaximumLatency, "Maximum Latency", 0x00), - INIT_PARAM_DFLT(BAR0Size, "Base Address Register 0 Size", 0x00), - INIT_PARAM_DFLT(BAR1Size, "Base Address Register 1 Size", 0x00), - INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00), - INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00), - INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00), - INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00) - -END_INIT_SIM_OBJECT_PARAMS(PciConfigData) - -CREATE_SIM_OBJECT(PciConfigData) -{ - PciConfigData *data = new PciConfigData(getInstanceName()); - - data->config.vendor = htole(VendorID); - data->config.device = htole(DeviceID); - data->config.command = htole(Command); - data->config.status = htole(Status); - data->config.revision = htole(Revision); - data->config.progIF = htole(ProgIF); - data->config.subClassCode = htole(SubClassCode); - data->config.classCode = htole(ClassCode); - data->config.cacheLineSize = htole(CacheLineSize); - data->config.latencyTimer = htole(LatencyTimer); - data->config.headerType = htole(HeaderType); - data->config.bist = htole(BIST); - - data->config.baseAddr0 = htole(BAR0); - data->config.baseAddr1 = htole(BAR1); - data->config.baseAddr2 = htole(BAR2); - data->config.baseAddr3 = htole(BAR3); - data->config.baseAddr4 = htole(BAR4); - data->config.baseAddr5 = htole(BAR5); - data->config.cardbusCIS = htole(CardbusCIS); - data->config.subsystemVendorID = htole(SubsystemVendorID); - data->config.subsystemID = htole(SubsystemVendorID); - data->config.expansionROM = htole(ExpansionROM); - data->config.interruptLine = htole(InterruptLine); - data->config.interruptPin = htole(InterruptPin); - data->config.minimumGrant = htole(MinimumGrant); - data->config.maximumLatency = htole(MaximumLatency); - - data->BARSize[0] = BAR0Size; - data->BARSize[1] = BAR1Size; - data->BARSize[2] = BAR2Size; - data->BARSize[3] = BAR3Size; - data->BARSize[4] = BAR4Size; - data->BARSize[5] = BAR5Size; - - return data; -} - -REGISTER_SIM_OBJECT("PciConfigData", PciConfigData) - -#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pcidev.hh b/dev/pcidev.hh deleted file mode 100644 index bdfc6b932..000000000 --- a/dev/pcidev.hh +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Interface for devices using PCI configuration - */ - -#ifndef __DEV_PCIDEV_HH__ -#define __DEV_PCIDEV_HH__ - -#include "dev/io_device.hh" -#include "dev/pcireg.h" -#include "dev/platform.hh" - -#define BAR_IO_MASK 0x3 -#define BAR_MEM_MASK 0xF -#define BAR_IO_SPACE_BIT 0x1 -#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) -#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); - -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) - { - memset(config.data, 0, sizeof(config.data)); - memset(BARAddrs, 0, sizeof(BARAddrs)); - 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]; -}; - -/** - * PCI device, base implemnation is only config space. - * Each device is connected to a PCIConfigSpace device - * which returns -1 for everything but the pcidevs that - * register with it. This object registers with the PCIConfig space - * object. - */ -class PciDev : public DmaDevice -{ - public: - struct Params - { - std::string name; - Platform *plat; - 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; - }; - - protected: - Params *_params; - - public: - const Params *params() const { return _params; } - - protected: - /** The current config space. Unlike the PciConfigData this is - * updated during simulation while continues to reflect 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]; - - bool - isBAR(Addr addr, int bar) const - { - assert(bar >= 0 && bar < 6); - return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; - } - - int - getBAR(Addr addr) - { - for (int i = 0; i <= 5; ++i) - if (isBAR(addr, i)) - return i; - - return -1; - } - - bool - getBAR(Addr paddr, Addr &daddr, int &bar) - { - int b = getBAR(paddr); - if (b < 0) - return false; - - daddr = paddr - BARAddrs[b]; - bar = b; - return true; - } - - protected: - Platform *plat; - PciConfigData *configData; - - public: - Addr pciToDma(Addr pciAddr) const - { return plat->pciToDma(pciAddr); } - - void - intrPost() - { plat->postPciInt(configData->config.interruptLine); } - - void - intrClear() - { plat->clearPciInt(configData->config.interruptLine); } - - uint8_t - interruptLine() - { return configData->config.interruptLine; } - - public: - /** - * Constructor for PCI Dev. This function copies data from the - * config file object PCIConfigData and registers the device with - * a PciConfigAll object. - */ - PciDev(Params *params); - - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - public: - /** - * Implement the read/write as BAR accesses - */ - Fault readBar(MemReqPtr &req, uint8_t *data); - Fault writeBar(MemReqPtr &req, const uint8_t *data); - - public: - /** - * Read from a specific BAR - */ - virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data); - virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data); - - public: - /** - * Write to a specific BAR - */ - virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data); - virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data); - - public: - /** - * 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, const uint8_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 §ion); -}; - -inline Fault -PciDev::readBar(MemReqPtr &req, uint8_t *data) -{ - using namespace TheISA; - if (isBAR(req->paddr, 0)) - return readBar0(req, req->paddr - BARAddrs[0], data); - if (isBAR(req->paddr, 1)) - return readBar1(req, req->paddr - BARAddrs[1], data); - if (isBAR(req->paddr, 2)) - return readBar2(req, req->paddr - BARAddrs[2], data); - if (isBAR(req->paddr, 3)) - return readBar3(req, req->paddr - BARAddrs[3], data); - if (isBAR(req->paddr, 4)) - return readBar4(req, req->paddr - BARAddrs[4], data); - if (isBAR(req->paddr, 5)) - return readBar5(req, req->paddr - BARAddrs[5], data); - return genMachineCheckFault(); -} - -inline Fault -PciDev::writeBar(MemReqPtr &req, const uint8_t *data) -{ - using namespace TheISA; - if (isBAR(req->paddr, 0)) - return writeBar0(req, req->paddr - BARAddrs[0], data); - if (isBAR(req->paddr, 1)) - return writeBar1(req, req->paddr - BARAddrs[1], data); - if (isBAR(req->paddr, 2)) - return writeBar2(req, req->paddr - BARAddrs[2], data); - if (isBAR(req->paddr, 3)) - return writeBar3(req, req->paddr - BARAddrs[3], data); - if (isBAR(req->paddr, 4)) - return writeBar4(req, req->paddr - BARAddrs[4], data); - if (isBAR(req->paddr, 5)) - return writeBar5(req, req->paddr - BARAddrs[5], data); - return genMachineCheckFault(); -} - -#endif // __DEV_PCIDEV_HH__ diff --git a/dev/pcireg.h b/dev/pcireg.h deleted file mode 100644 index 9d2737c20..000000000 --- a/dev/pcireg.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device register definitions for a device's PCI config space - */ - -#ifndef __PCIREG_H__ -#define __PCIREG_H__ - -#include <sys/types.h> - -union PCIConfig { - uint8_t data[64]; - - struct { - uint16_t vendor; - uint16_t device; - uint16_t command; - uint16_t status; - uint8_t revision; - uint8_t progIF; - uint8_t subClassCode; - uint8_t classCode; - uint8_t cacheLineSize; - uint8_t latencyTimer; - uint8_t headerType; - uint8_t bist; - union { - uint32_t baseAddr[6]; - - struct { - uint32_t baseAddr0; - uint32_t baseAddr1; - uint32_t baseAddr2; - uint32_t baseAddr3; - uint32_t baseAddr4; - uint32_t baseAddr5; - }; - }; - uint32_t cardbusCIS; - uint16_t subsystemVendorID; - uint16_t subsystemID; - uint32_t expansionROM; - uint32_t reserved0; - uint32_t reserved1; - uint8_t interruptLine; - uint8_t interruptPin; - uint8_t minimumGrant; - uint8_t maximumLatency; - }; -}; - -// Common PCI offsets -#define PCI_VENDOR_ID 0x00 // Vendor ID ro -#define PCI_DEVICE_ID 0x02 // Device ID ro -#define PCI_COMMAND 0x04 // Command rw -#define PCI_STATUS 0x06 // Status rw -#define PCI_REVISION_ID 0x08 // Revision ID ro -#define PCI_CLASS_CODE 0x09 // Class Code ro -#define PCI_SUB_CLASS_CODE 0x0A // Sub Class Code ro -#define PCI_BASE_CLASS_CODE 0x0B // Base Class Code ro -#define PCI_CACHE_LINE_SIZE 0x0C // Cache Line Size ro+ -#define PCI_LATENCY_TIMER 0x0D // Latency Timer ro+ -#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 -#define PCI0_BASE_ADDR2 0x18 // Base Address 2 rw -#define PCI0_BASE_ADDR3 0x1C // Base Address 3 rw -#define PCI0_BASE_ADDR4 0x20 // Base Address 4 rw -#define PCI0_BASE_ADDR5 0x24 // Base Address 5 rw -#define PCI0_CIS 0x28 // CardBus CIS Pointer ro -#define PCI0_SUB_VENDOR_ID 0x2C // Sub-Vendor ID ro -#define PCI0_SUB_SYSTEM_ID 0x2E // Sub-System ID ro -#define PCI0_ROM_BASE_ADDR 0x30 // Expansion ROM Base Address rw -#define PCI0_RESERVED0 0x34 -#define PCI0_RESERVED1 0x38 -#define PCI0_INTERRUPT_LINE 0x3C // Interrupt Line rw -#define PCI0_INTERRUPT_PIN 0x3D // Interrupt Pin ro -#define PCI0_MINIMUM_GRANT 0x3E // Maximum Grant ro -#define PCI0_MAXIMUM_LATENCY 0x3F // Maximum Latency ro - -// Type 1 PCI offsets -#define PCI1_BASE_ADDR0 0x10 // Base Address 0 rw -#define PCI1_BASE_ADDR1 0x14 // Base Address 1 rw -#define PCI1_PRI_BUS_NUM 0x18 // Primary Bus Number rw -#define PCI1_SEC_BUS_NUM 0x19 // Secondary Bus Number rw -#define PCI1_SUB_BUS_NUM 0x1A // Subordinate Bus Number rw -#define PCI1_SEC_LAT_TIMER 0x1B // Secondary Latency Timer ro+ -#define PCI1_IO_BASE 0x1C // I/O Base rw -#define PCI1_IO_LIMIT 0x1D // I/O Limit rw -#define PCI1_SECONDARY_STATUS 0x1E // Secondary Status rw -#define PCI1_MEM_BASE 0x20 // Memory Base rw -#define PCI1_MEM_LIMIT 0x22 // Memory Limit rw -#define PCI1_PRF_MEM_BASE 0x24 // Prefetchable Memory Base rw -#define PCI1_PRF_MEM_LIMIT 0x26 // Prefetchable Memory Limit rw -#define PCI1_PRF_BASE_UPPER 0x28 // Prefetchable Base Upper 32 rw -#define PCI1_PRF_LIMIT_UPPER 0x2C // Prefetchable Limit Upper 32 rw -#define PCI1_IO_BASE_UPPER 0x30 // I/O Base Upper 16 bits rw -#define PCI1_IO_LIMIT_UPPER 0x32 // I/O Limit Upper 16 bits rw -#define PCI1_RESERVED 0x34 // Reserved ro -#define PCI1_ROM_BASE_ADDR 0x38 // Expansion ROM Base Address rw -#define PCI1_INTR_LINE 0x3C // Interrupt Line rw -#define PCI1_INTR_PIN 0x3D // Interrupt Pin ro -#define PCI1_BRIDGE_CTRL 0x3E // Bridge Control rw - -// Device specific offsets -#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes - -// Some Vendor IDs -#define PCI_VENDOR_DEC 0x1011 -#define PCI_VENDOR_NCR 0x101A -#define PCI_VENDOR_QLOGIC 0x1077 -#define PCI_VENDOR_SIMOS 0x1291 - -// Some Product IDs -#define PCI_PRODUCT_DEC_PZA 0x0008 -#define PCI_PRODUCT_NCR_810 0x0001 -#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 -#define PCI_PRODUCT_SIMOS_SIMOS 0x1291 -#define PCI_PRODUCT_SIMOS_ETHER 0x1292 - -#endif // __PCIREG_H__ diff --git a/dev/pitreg.h b/dev/pitreg.h deleted file mode 100644 index 5fe1cf03f..000000000 --- a/dev/pitreg.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Device register definitions for a device's PCI config space - */ - -#ifndef __PITREG_H__ -#define __PITREG_H__ - -#include <sys/types.h> - -// Control Word Format - -#define PIT_SEL_SHFT 0x6 -#define PIT_RW_SHFT 0x4 -#define PIT_MODE_SHFT 0x1 -#define PIT_BCD_SHFT 0x0 - -#define PIT_SEL_MASK 0x3 -#define PIT_RW_MASK 0x3 -#define PIT_MODE_MASK 0x7 -#define PIT_BCD_MASK 0x1 - -#define GET_CTRL_FIELD(x, s, m) (((x) >> s) & m) -#define GET_CTRL_SEL(x) GET_CTRL_FIELD(x, PIT_SEL_SHFT, PIT_SEL_MASK) -#define GET_CTRL_RW(x) GET_CTRL_FIELD(x, PIT_RW_SHFT, PIT_RW_MASK) -#define GET_CTRL_MODE(x) GET_CTRL_FIELD(x, PIT_MODE_SHFT, PIT_MODE_MASK) -#define GET_CTRL_BCD(x) GET_CTRL_FIELD(x, PIT_BCD_SHFT, PIT_BCD_MASK) - -#define PIT_READ_BACK 0x3 - -#define PIT_RW_LATCH_COMMAND 0x0 -#define PIT_RW_LSB_ONLY 0x1 -#define PIT_RW_MSB_ONLY 0x2 -#define PIT_RW_16BIT 0x3 - -#define PIT_MODE_INTTC 0x0 -#define PIT_MODE_ONESHOT 0x1 -#define PIT_MODE_RATEGEN 0x2 -#define PIT_MODE_SQWAVE 0x3 -#define PIT_MODE_SWSTROBE 0x4 -#define PIT_MODE_HWSTROBE 0x5 - -#define PIT_BCD_FALSE 0x0 -#define PIT_BCD_TRUE 0x1 - -#endif // __PITREG_H__ diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc deleted file mode 100644 index 639009be9..000000000 --- a/dev/pktfifo.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "base/misc.hh" -#include "dev/pktfifo.hh" - -using namespace std; - -bool -PacketFifo::copyout(void *dest, int offset, int len) -{ - char *data = (char *)dest; - if (offset + len >= size()) - return false; - - list<PacketPtr>::iterator p = fifo.begin(); - list<PacketPtr>::iterator end = fifo.end(); - while (len > 0) { - while (offset >= (*p)->length) { - offset -= (*p)->length; - ++p; - } - - if (p == end) - panic("invalid fifo"); - - int size = min((*p)->length - offset, len); - memcpy(data, (*p)->data, size); - offset = 0; - len -= size; - data += size; - ++p; - } - - return true; -} - - -void -PacketFifo::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".size", _size); - paramOut(os, base + ".maxsize", _maxsize); - paramOut(os, base + ".reserved", _reserved); - paramOut(os, base + ".packets", fifo.size()); - - int i = 0; - list<PacketPtr>::iterator p = fifo.begin(); - list<PacketPtr>::iterator end = fifo.end(); - while (p != end) { - (*p)->serialize(csprintf("%s.packet%d", base, i), os); - ++p; - ++i; - } -} - -void -PacketFifo::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".size", _size); -// paramIn(cp, section, base + ".maxsize", _maxsize); - paramIn(cp, section, base + ".reserved", _reserved); - int fifosize; - paramIn(cp, section, base + ".packets", fifosize); - - fifo.clear(); - - for (int i = 0; i < fifosize; ++i) { - PacketPtr p = new PacketData(16384); - p->unserialize(csprintf("%s.packet%d", base, i), cp, section); - fifo.push_back(p); - } -} diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh deleted file mode 100644 index e245840a8..000000000 --- a/dev/pktfifo.hh +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DEV_PKTFIFO_HH__ -#define __DEV_PKTFIFO_HH__ - -#include <iosfwd> -#include <list> -#include <string> - -#include "dev/etherpkt.hh" -#include "sim/serialize.hh" - -class Checkpoint; -class PacketFifo -{ - public: - typedef std::list<PacketPtr> fifo_list; - typedef fifo_list::iterator iterator; - - protected: - std::list<PacketPtr> fifo; - int _maxsize; - int _size; - int _reserved; - - public: - explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {} - virtual ~PacketFifo() {} - - int packets() const { return fifo.size(); } - int maxsize() const { return _maxsize; } - int size() const { return _size; } - int reserved() const { return _reserved; } - int avail() const { return _maxsize - _size - _reserved; } - bool empty() const { return size() <= 0; } - bool full() const { return avail() <= 0; } - - int reserve(int len = 0) - { - _reserved += len; - assert(avail() >= 0); - return _reserved; - } - - iterator begin() { return fifo.begin(); } - iterator end() { return fifo.end(); } - - PacketPtr front() { return fifo.front(); } - - bool push(PacketPtr ptr) - { - assert(ptr->length); - assert(_reserved <= ptr->length); - assert(ptr->slack == 0); - if (avail() < ptr->length - _reserved) - return false; - - _size += ptr->length; - fifo.push_back(ptr); - _reserved = 0; - return true; - } - - void pop() - { - if (empty()) - return; - - PacketPtr &packet = fifo.front(); - _size -= packet->length; - _size -= packet->slack; - packet->slack = 0; - packet = NULL; - fifo.pop_front(); - } - - void clear() - { - for (iterator i = begin(); i != end(); ++i) - (*i)->slack = 0; - fifo.clear(); - _size = 0; - _reserved = 0; - } - - void remove(iterator i) - { - PacketPtr &packet = *i; - if (i != fifo.begin()) { - iterator prev = i; - --prev; - assert(prev != fifo.end()); - (*prev)->slack += packet->length; - } else { - _size -= packet->length; - _size -= packet->slack; - } - - packet->slack = 0; - packet = NULL; - fifo.erase(i); - } - - bool copyout(void *dest, int offset, int len); - - int countPacketsBefore(iterator end) - { - iterator i = fifo.begin(); - int count = 0; - - while (i != end) { - ++count; - ++i; - } - - return count; - } - - int countPacketsAfter(iterator i) - { - iterator end = fifo.end(); - int count = 0; - - while (i != end) { - ++count; - ++i; - } - - return count; - } - - -/** - * Serialization stuff - */ - public: - void serialize(const std::string &base, std::ostream &os); - void unserialize(const std::string &base, - Checkpoint *cp, const std::string §ion); -}; - -#endif // __DEV_PKTFIFO_HH__ diff --git a/dev/platform.cc b/dev/platform.cc deleted file mode 100644 index 5b667b12c..000000000 --- a/dev/platform.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "dev/platform.hh" -#include "sim/builder.hh" -#include "sim/sim_exit.hh" - -using namespace std; -using namespace TheISA; - -Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci) - : SimObject(name), intrctrl(intctrl), pciconfig(pci) -{ -} - -Platform::~Platform() -{ -} - -void -Platform::postPciInt(int line) -{ - panic("No PCI interrupt support in platform."); -} - -void -Platform::clearPciInt(int line) -{ - panic("No PCI interrupt support in platform."); -} - -Addr -Platform::pciToDma(Addr pciAddr) const -{ - panic("No PCI dma support in platform."); -} - -DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform) - diff --git a/dev/platform.hh b/dev/platform.hh deleted file mode 100644 index 1ee645454..000000000 --- a/dev/platform.hh +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * Generic interface for platforms - */ - -#ifndef __DEV_PLATFORM_HH__ -#define __DEV_PLATFORM_HH__ - -#include "sim/sim_object.hh" -#include "arch/isa_traits.hh" - -class PciConfigAll; -class IntrControl; -class SimConsole; -class Uart; - -class Platform : public SimObject -{ - public: - /** Pointer to the interrupt controller */ - IntrControl *intrctrl; - - /** Pointer to the PCI configuration space */ - PciConfigAll *pciconfig; - - /** Pointer to the UART, set by the uart */ - Uart *uart; - - public: - Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci); - virtual ~Platform(); - virtual void postConsoleInt() = 0; - virtual void clearConsoleInt() = 0; - virtual Tick intrFrequency() = 0; - virtual void postPciInt(int line); - virtual void clearPciInt(int line); - virtual Addr pciToDma(Addr pciAddr) const; -}; - -#endif // __DEV_PLATFORM_HH__ diff --git a/dev/rtcreg.h b/dev/rtcreg.h deleted file mode 100644 index 5025a0e95..000000000 --- a/dev/rtcreg.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define RTC_SEC 0x00 -#define RTC_SEC_ALRM 0x01 -#define RTC_MIN 0x02 -#define RTC_MIN_ALRM 0x03 -#define RTC_HR 0x04 -#define RTC_HR_ALRM 0x05 -#define RTC_DOW 0x06 -#define RTC_DOM 0x07 -#define RTC_MON 0x08 -#define RTC_YEAR 0x09 - -#define RTC_STAT_REGA 0x0A -#define RTCA_1024HZ 0x06 /* 1024Hz periodic interrupt frequency */ -#define RTCA_32768HZ 0x20 /* 22-stage divider, 32.768KHz timebase */ -#define RTCA_UIP 0x80 /* 1 = date and time update in progress */ - -#define RTC_STAT_REGB 0x0B -#define RTCB_DST 0x01 /* USA Daylight Savings Time enable */ -#define RTCB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */ -#define RTCB_BIN 0x04 /* 0 = BCD, 1 = Binary coded time */ -#define RTCB_SQWE 0x08 /* 1 = output sqare wave at SQW pin */ -#define RTCB_UPDT_IE 0x10 /* 1 = enable update-ended interrupt */ -#define RTCB_ALRM_IE 0x20 /* 1 = enable alarm interrupt */ -#define RTCB_PRDC_IE 0x40 /* 1 = enable periodic clock interrupt */ -#define RTCB_NO_UPDT 0x80 /* stop clock updates */ - -#define RTC_STAT_REGC 0x0C -#define RTC_STAT_REGD 0x0D - diff --git a/dev/simconsole.cc b/dev/simconsole.cc deleted file mode 100644 index b818e61f4..000000000 --- a/dev/simconsole.cc +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Implements the user interface to a serial console - */ - -#include <sys/ioctl.h> -#include <sys/termios.h> -#include <sys/types.h> -#include <errno.h> -#include <poll.h> -#include <unistd.h> - -#include <iostream> -#include <fstream> -#include <sstream> -#include <string> - -#include "base/misc.hh" -#include "base/output.hh" -#include "base/socket.hh" -#include "base/trace.hh" -#include "dev/platform.hh" -#include "dev/simconsole.hh" -#include "dev/uart.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" - -using namespace std; - -//////////////////////////////////////////////////////////////////////// -// -// - -SimConsole::Event::Event(SimConsole *c, int fd, int e) - : PollEvent(fd, e), cons(c) -{ -} - -void -SimConsole::Event::process(int revent) -{ - if (revent & POLLIN) - cons->data(); - else if (revent & POLLNVAL) - cons->detach(); -} - -SimConsole::SimConsole(const string &name, ostream *os, int num) - : SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1), - listener(NULL), txbuf(16384), rxbuf(16384), outfile(os) -#if TRACING_ON == 1 - , linebuf(16384) -#endif -{ - if (outfile) - outfile->setf(ios::unitbuf); -} - -SimConsole::~SimConsole() -{ - close(); -} - -void -SimConsole::close() -{ - if (in_fd != -1) - ::close(in_fd); - - if (out_fd != in_fd && out_fd != -1) - ::close(out_fd); -} - -void -SimConsole::attach(int in, int out, ConsoleListener *l) -{ - in_fd = in; - out_fd = out; - listener = l; - - event = new Event(this, in, POLLIN); - pollQueue.schedule(event); - - stringstream stream; - ccprintf(stream, "==== m5 slave console: Console %d ====", number); - - // we need an actual carriage return followed by a newline for the - // terminal - stream << "\r\n"; - - write((const uint8_t *)stream.str().c_str(), stream.str().size()); - - - DPRINTFN("attach console %d\n", number); - - txbuf.readall(out); -} - -void -SimConsole::detach() -{ - close(); - in_fd = -1; - out_fd = -1; - - pollQueue.remove(event); - - if (listener) { - listener->add(this); - listener = NULL; - } - - DPRINTFN("detach console %d\n", number); -} - -void -SimConsole::data() -{ - uint8_t buf[1024]; - int len; - - len = read(buf, sizeof(buf)); - if (len) { - rxbuf.write((char *)buf, len); - // Inform the UART there is data available - uart->dataAvailable(); - } -} - -size_t -SimConsole::read(uint8_t *buf, size_t len) -{ - if (in_fd < 0) - panic("Console not properly attached.\n"); - - size_t ret; - do { - ret = ::read(in_fd, buf, len); - } while (ret == -1 && errno == EINTR); - - - if (ret < 0) - DPRINTFN("Read failed.\n"); - - if (ret <= 0) { - detach(); - return 0; - } - - return ret; -} - -// Console output. -size_t -SimConsole::write(const uint8_t *buf, size_t len) -{ - if (out_fd < 0) - panic("Console not properly attached.\n"); - - size_t ret; - for (;;) { - ret = ::write(out_fd, buf, len); - - if (ret >= 0) - break; - - if (errno != EINTR) - detach(); - } - - return ret; -} - -#define MORE_PENDING (ULL(1) << 61) -#define RECEIVE_SUCCESS (ULL(0) << 62) -#define RECEIVE_NONE (ULL(2) << 62) -#define RECEIVE_ERROR (ULL(3) << 62) - -bool -SimConsole::in(uint8_t &c) -{ - bool empty, ret; - - empty = rxbuf.empty(); - ret = !empty; - if (!empty) { - rxbuf.read((char *)&c, 1); - empty = rxbuf.empty(); - } - - DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d, return: %d\n", - isprint(c) ? c : ' ', c, !empty, ret); - - return ret; -} - -uint64_t -SimConsole::console_in() -{ - uint8_t c; - uint64_t value; - - if (in(c)) { - value = RECEIVE_SUCCESS | c; - if (!rxbuf.empty()) - value |= MORE_PENDING; - } else { - value = RECEIVE_NONE; - } - - DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value); - - return value; -} - -void -SimConsole::out(char c) -{ -#if TRACING_ON == 1 - if (DTRACE(Console)) { - static char last = '\0'; - - if (c != '\n' && c != '\r' || - last != '\n' && last != '\r') { - if (c == '\n' || c == '\r') { - int size = linebuf.size(); - char *buffer = new char[size + 1]; - linebuf.read(buffer, size); - buffer[size] = '\0'; - DPRINTF(Console, "%s\n", buffer); - delete [] buffer; - } else { - linebuf.write(c); - } - } - - last = c; - } -#endif - - txbuf.write(c); - - if (out_fd >= 0) - write(c); - - if (outfile) - outfile->write(&c, 1); - - DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n", - isprint(c) ? c : ' ', (int)c); - -} - - -void -SimConsole::serialize(ostream &os) -{ -} - -void -SimConsole::unserialize(Checkpoint *cp, const std::string §ion) -{ -} - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole) - - SimObjectParam<ConsoleListener *> listener; - SimObjectParam<IntrControl *> intr_control; - Param<string> output; - Param<bool> append_name; - Param<int> number; - -END_DECLARE_SIM_OBJECT_PARAMS(SimConsole) - -BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole) - - INIT_PARAM(listener, "console listener"), - INIT_PARAM(intr_control, "interrupt controller"), - INIT_PARAM(output, "file to dump output to"), - INIT_PARAM_DFLT(append_name, "append name() to filename", true), - INIT_PARAM_DFLT(number, "console number", 0) - -END_INIT_SIM_OBJECT_PARAMS(SimConsole) - -CREATE_SIM_OBJECT(SimConsole) -{ - string filename = output; - ostream *stream = NULL; - - if (!filename.empty()) { - if (append_name) - filename += "." + getInstanceName(); - stream = simout.find(filename); - } - - SimConsole *console = new SimConsole(getInstanceName(), stream, number); - ((ConsoleListener *)listener)->add(console); - - return console; -} - -REGISTER_SIM_OBJECT("SimConsole", SimConsole) - -//////////////////////////////////////////////////////////////////////// -// -// - -ConsoleListener::ConsoleListener(const string &name) - : SimObject(name), event(NULL) -{} - -ConsoleListener::~ConsoleListener() -{ - if (event) - delete event; -} - -void -ConsoleListener::Event::process(int revent) -{ - listener->accept(); -} - -/////////////////////////////////////////////////////////////////////// -// socket creation and console attach -// - -void -ConsoleListener::listen(int port) -{ - while (!listener.listen(port, true)) { - DPRINTF(Console, - ": can't bind address console port %d inuse PID %d\n", - port, getpid()); - port++; - } - - ccprintf(cerr, "Listening for console connection on port %d\n", port); - - event = new Event(this, listener.getfd(), POLLIN); - pollQueue.schedule(event); -} - -void -ConsoleListener::add(SimConsole *cons) -{ ConsoleList.push_back(cons);} - -void -ConsoleListener::accept() -{ - if (!listener.islistening()) - panic("%s: cannot accept a connection if not listening!", name()); - - int sfd = listener.accept(true); - if (sfd != -1) { - iter_t i = ConsoleList.begin(); - iter_t end = ConsoleList.end(); - if (i == end) { - close(sfd); - } else { - (*i)->attach(sfd, this); - i = ConsoleList.erase(i); - } - } -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener) - - Param<int> port; - -END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener) - -BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener) - - INIT_PARAM_DFLT(port, "listen port", 3456) - -END_INIT_SIM_OBJECT_PARAMS(ConsoleListener) - -CREATE_SIM_OBJECT(ConsoleListener) -{ - ConsoleListener *listener = new ConsoleListener(getInstanceName()); - listener->listen(port); - - return listener; -} - -REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener) diff --git a/dev/simconsole.hh b/dev/simconsole.hh deleted file mode 100644 index cf0641f9e..000000000 --- a/dev/simconsole.hh +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * User Console Interface - */ - -#ifndef __CONSOLE_HH__ -#define __CONSOLE_HH__ - -#include <iostream> - -#include "base/circlebuf.hh" -#include "cpu/intr_control.hh" -#include "base/pollevent.hh" -#include "base/socket.hh" -#include "sim/sim_object.hh" - -class ConsoleListener; -class Uart; - -class SimConsole : public SimObject -{ - public: - Uart *uart; - - protected: - class Event : public PollEvent - { - protected: - SimConsole *cons; - - public: - Event(SimConsole *c, int fd, int e); - void process(int revent); - }; - - friend class Event; - Event *event; - - protected: - int number; - int in_fd; - int out_fd; - ConsoleListener *listener; - - public: - SimConsole(const std::string &name, std::ostream *os, int num); - ~SimConsole(); - - protected: - CircleBuf txbuf; - CircleBuf rxbuf; - std::ostream *outfile; -#if TRACING_ON == 1 - CircleBuf linebuf; -#endif - - public: - /////////////////////// - // Terminal Interface - - void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); } - void attach(int in, int out, ConsoleListener *l = NULL); - void detach(); - - void data(); - - void close(); - void read(uint8_t &c) { read(&c, 1); } - size_t read(uint8_t *buf, size_t len); - void write(uint8_t c) { write(&c, 1); } - size_t write(const uint8_t *buf, size_t len); - - public: - ///////////////// - // OS interface - - // Get a character from the console. - bool in(uint8_t &value); - - // get a character from the console in the console specific format - // corresponds to GETC: - // retval<63:61> - // 000: success: character received - // 001: success: character received, more pending - // 100: failure: no character ready - // 110: failure: character received with error - // 111: failure: character received with error, more pending - // retval<31:0> - // character read from console - // - // Interrupts are cleared when the buffer is empty. - uint64_t console_in(); - - // Send a character to the console - void out(char c); - - //Ask the console if data is available - bool dataAvailable() { return !rxbuf.empty(); } - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -class ConsoleListener : public SimObject -{ - protected: - class Event : public PollEvent - { - protected: - ConsoleListener *listener; - - public: - Event(ConsoleListener *l, int fd, int e) - : PollEvent(fd, e), listener(l) {} - void process(int revent); - }; - - friend class Event; - Event *event; - - typedef std::list<SimConsole *> list_t; - typedef list_t::iterator iter_t; - list_t ConsoleList; - - protected: - ListenSocket listener; - - public: - ConsoleListener(const std::string &name); - ~ConsoleListener(); - - void add(SimConsole *cons); - - void accept(); - void listen(int port); -}; - -#endif // __CONSOLE_HH__ diff --git a/dev/simple_disk.cc b/dev/simple_disk.cc deleted file mode 100644 index b8c5d44ab..000000000 --- a/dev/simple_disk.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Simple disk interface for the system console - */ - -#include <sys/types.h> -#include <sys/uio.h> -#include <fcntl.h> -#include <unistd.h> - -#include <cstring> -#include <string> - -#include "base/misc.hh" -#include "base/trace.hh" -#include "dev/disk_image.hh" -#include "dev/simple_disk.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" - -using namespace std; - -SimpleDisk::SimpleDisk(const string &name, PhysicalMemory *pmem, - DiskImage *img) - : SimObject(name), physmem(pmem), image(img) -{} - -SimpleDisk::~SimpleDisk() -{} - - -void -SimpleDisk::read(Addr addr, baddr_t block, int count) const -{ - uint8_t *data = physmem->dma_addr(addr, count); - if (!data) - panic("dma out of range! read addr=%#x count=%d\n", addr, count); - - if (count & (SectorSize - 1)) - panic("Not reading a multiple of a sector (count = %d)", count); - - for (int i = 0, j = 0; i < count; i += SectorSize, j++) - image->read(data + i, block + j); - - DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count); - DDUMP(SimpleDiskData, data, count); -} - -void -SimpleDisk::write(Addr addr, baddr_t block, int count) -{ - panic("unimplemented!\n"); - -#if 0 - uint8_t *data = physmem->dma_addr(addr, count); - if (!data) - panic("dma out of range! write addr=%#x count=%d\n", addr, count); - - image->write(data, block, count); -#endif -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk) - - SimObjectParam<PhysicalMemory *> physmem; - SimObjectParam<DiskImage *> disk; - -END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk) - -BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk) - - INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM(disk, "Disk Image") - -END_INIT_SIM_OBJECT_PARAMS(SimpleDisk) - -CREATE_SIM_OBJECT(SimpleDisk) -{ - return new SimpleDisk(getInstanceName(), physmem, disk); -} - -REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk) diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh deleted file mode 100644 index 57f81c5a9..000000000 --- a/dev/simple_disk.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* @file - * Simple disk interface for the system console - */ - -#ifndef __DEV_SIMPLE_DISK_HH__ -#define __DEV_SIMPLE_DISK_HH__ - -#include "sim/sim_object.hh" -#include "arch/isa_traits.hh" - -class DiskImage; -class PhysicalMemory; - -/* - * Trivial interface to a disk image used by the System Console - */ -class SimpleDisk : public SimObject -{ - public: - typedef uint64_t baddr_t; - - protected: - PhysicalMemory *physmem; - DiskImage *image; - - public: - SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img); - ~SimpleDisk(); - - void read(Addr addr, baddr_t block, int count) const; - void write(Addr addr, baddr_t block, int count); -}; - -#endif // __DEV_SIMPLE_DISK_HH__ diff --git a/dev/sinic.cc b/dev/sinic.cc deleted file mode 100644 index 0853717ba..000000000 --- a/dev/sinic.cc +++ /dev/null @@ -1,1905 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <cstdio> -#include <deque> -#include <string> - -#include "base/inet.hh" -#include "cpu/exec_context.hh" -#include "cpu/intr_control.hh" -#include "dev/etherlink.hh" -#include "dev/sinic.hh" -#include "dev/pciconfigall.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/dma_interface.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" -#include "sim/debug.hh" -#include "sim/eventq.hh" -#include "sim/host.hh" -#include "sim/stats.hh" -#include "arch/vtophys.hh" - -using namespace Net; -using namespace TheISA; - -namespace Sinic { - -const char *RxStateStrings[] = -{ - "rxIdle", - "rxFifoBlock", - "rxBeginCopy", - "rxCopy", - "rxCopyDone" -}; - -const char *TxStateStrings[] = -{ - "txIdle", - "txFifoBlock", - "txBeginCopy", - "txCopy", - "txCopyDone" -}; - - -/////////////////////////////////////////////////////////////////////// -// -// Sinic PCI Device -// -Base::Base(Params *p) - : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock), - intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false), - cpuPendingIntr(false), intrEvent(0), interface(NULL) -{ -} - -Device::Device(Params *p) - : Base(p), plat(p->plat), physmem(p->physmem), rxUnique(0), txUnique(0), - virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count), - rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), - rxKickTick(0), txKickTick(0), - txEvent(this), rxDmaEvent(this), txDmaEvent(this), - dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), - dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor) -{ - reset(); - - if (p->pio_bus) { - pioInterface = newPioInterface(p->name + ".pio", p->hier, p->pio_bus, - this, &Device::cacheAccess); - pioLatency = p->pio_latency * p->pio_bus->clockRate; - } - - if (p->header_bus) { - if (p->payload_bus) - dmaInterface = new DMAInterface<Bus>(p->name + ".dma", - p->header_bus, - p->payload_bus, 1, - p->dma_no_allocate); - else - dmaInterface = new DMAInterface<Bus>(p->name + ".dma", - p->header_bus, - p->header_bus, 1, - p->dma_no_allocate); - } else if (p->payload_bus) - panic("must define a header bus if defining a payload bus"); -} - -Device::~Device() -{} - -void -Device::regStats() -{ - rxBytes - .name(name() + ".rxBytes") - .desc("Bytes Received") - .prereq(rxBytes) - ; - - rxBandwidth - .name(name() + ".rxBandwidth") - .desc("Receive Bandwidth (bits/s)") - .precision(0) - .prereq(rxBytes) - ; - - rxPackets - .name(name() + ".rxPackets") - .desc("Number of Packets Received") - .prereq(rxBytes) - ; - - rxPacketRate - .name(name() + ".rxPPS") - .desc("Packet Reception Rate (packets/s)") - .precision(0) - .prereq(rxBytes) - ; - - rxIpPackets - .name(name() + ".rxIpPackets") - .desc("Number of IP Packets Received") - .prereq(rxBytes) - ; - - rxTcpPackets - .name(name() + ".rxTcpPackets") - .desc("Number of Packets Received") - .prereq(rxBytes) - ; - - rxUdpPackets - .name(name() + ".rxUdpPackets") - .desc("Number of UDP Packets Received") - .prereq(rxBytes) - ; - - rxIpChecksums - .name(name() + ".rxIpChecksums") - .desc("Number of rx IP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - rxTcpChecksums - .name(name() + ".rxTcpChecksums") - .desc("Number of rx TCP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - rxUdpChecksums - .name(name() + ".rxUdpChecksums") - .desc("Number of rx UDP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - totBandwidth - .name(name() + ".totBandwidth") - .desc("Total Bandwidth (bits/s)") - .precision(0) - .prereq(totBytes) - ; - - totPackets - .name(name() + ".totPackets") - .desc("Total Packets") - .precision(0) - .prereq(totBytes) - ; - - totBytes - .name(name() + ".totBytes") - .desc("Total Bytes") - .precision(0) - .prereq(totBytes) - ; - - totPacketRate - .name(name() + ".totPPS") - .desc("Total Tranmission Rate (packets/s)") - .precision(0) - .prereq(totBytes) - ; - - txBytes - .name(name() + ".txBytes") - .desc("Bytes Transmitted") - .prereq(txBytes) - ; - - txBandwidth - .name(name() + ".txBandwidth") - .desc("Transmit Bandwidth (bits/s)") - .precision(0) - .prereq(txBytes) - ; - - txPackets - .name(name() + ".txPackets") - .desc("Number of Packets Transmitted") - .prereq(txBytes) - ; - - txPacketRate - .name(name() + ".txPPS") - .desc("Packet Tranmission Rate (packets/s)") - .precision(0) - .prereq(txBytes) - ; - - txIpPackets - .name(name() + ".txIpPackets") - .desc("Number of IP Packets Transmitted") - .prereq(txBytes) - ; - - txTcpPackets - .name(name() + ".txTcpPackets") - .desc("Number of TCP Packets Transmitted") - .prereq(txBytes) - ; - - txUdpPackets - .name(name() + ".txUdpPackets") - .desc("Number of Packets Transmitted") - .prereq(txBytes) - ; - - txIpChecksums - .name(name() + ".txIpChecksums") - .desc("Number of tx IP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - txTcpChecksums - .name(name() + ".txTcpChecksums") - .desc("Number of tx TCP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - txUdpChecksums - .name(name() + ".txUdpChecksums") - .desc("Number of tx UDP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - txBandwidth = txBytes * Stats::constant(8) / simSeconds; - rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; - totBandwidth = txBandwidth + rxBandwidth; - totBytes = txBytes + rxBytes; - totPackets = txPackets + rxPackets; - txPacketRate = txPackets / simSeconds; - rxPacketRate = rxPackets / simSeconds; -} - -/** - * This is to write to the PCI general configuration registers - */ -void -Device::writeConfig(int offset, int size, const uint8_t *data) -{ - switch (offset) { - case PCI0_BASE_ADDR0: - // Need to catch writes to BARs to update the PIO interface - PciDev::writeConfig(offset, size, data); - if (BARAddrs[0] != 0) { - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - - BARAddrs[0] &= EV5::PAddrUncachedMask; - } - break; - - default: - PciDev::writeConfig(offset, size, data); - } -} - -void -Device::prepareIO(int cpu, int index) -{ - int size = virtualRegs.size(); - if (index > size) - panic("Trying to access a vnic that doesn't exist %d > %d\n", - index, size); -} - -void -Device::prepareRead(int cpu, int index) -{ - using namespace Regs; - prepareIO(cpu, index); - - VirtualReg &vnic = virtualRegs[index]; - - // update rx registers - uint64_t rxdone = vnic.RxDone; - rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr)); - rxdone = set_RxDone_Empty(rxdone, rxFifo.empty()); - rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark); - rxdone = set_RxDone_NotHigh(rxdone, rxLow); - regs.RxData = vnic.RxData; - regs.RxDone = rxdone; - regs.RxWait = rxdone; - - // update tx regsiters - uint64_t txdone = vnic.TxDone; - txdone = set_TxDone_Packets(txdone, txFifo.packets()); - txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy); - txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark); - regs.TxData = vnic.TxData; - regs.TxDone = txdone; - regs.TxWait = txdone; -} - -void -Device::prepareWrite(int cpu, int index) -{ - prepareIO(cpu, index); -} - -/** - * I/O read of device register - */ -Fault -Device::read(MemReqPtr &req, uint8_t *data) -{ - assert(config.command & PCI_CMD_MSE); - Fault fault = readBar(req, data); - - if (fault && fault->isMachineCheckFault()) { - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); - - return genMachineCheckFault(); - } - - return fault; -} - -Fault -Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) -{ - int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff; - Addr index = daddr >> Regs::VirtualShift; - Addr raddr = daddr & Regs::VirtualMask; - - if (!regValid(raddr)) - panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - cpu, index, daddr, req->paddr, req->vaddr, req->size); - - const Regs::Info &info = regInfo(raddr); - if (!info.read) - panic("read %s (write only): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); - - if (req->size != info.size) - panic("read %s (invalid size): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); - - prepareRead(cpu, index); - - uint64_t value = 0; - if (req->size == 4) { - uint32_t ® = *(uint32_t *)data; - reg = regData32(raddr); - value = reg; - } - - if (req->size == 8) { - uint64_t ® = *(uint64_t *)data; - reg = regData64(raddr); - value = reg; - } - - DPRINTF(EthernetPIO, - "read %s: cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d val=%#x\n", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size, - value); - - // reading the interrupt status register has the side effect of - // clearing it - if (raddr == Regs::IntrStatus) - devIntrClear(); - - return NoFault; -} - -/** - * IPR read of device register - */ -Fault -Device::iprRead(Addr daddr, int cpu, uint64_t &result) -{ - if (!regValid(daddr)) - panic("invalid address: da=%#x", daddr); - - const Regs::Info &info = regInfo(daddr); - if (!info.read) - panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr); - - DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n", - info.name, cpu, daddr); - - prepareRead(cpu, 0); - - if (info.size == 4) - result = regData32(daddr); - - if (info.size == 8) - result = regData64(daddr); - - DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n", - info.name, cpu, result); - - return NoFault; -} - -/** - * I/O write of device register - */ -Fault -Device::write(MemReqPtr &req, const uint8_t *data) -{ - assert(config.command & PCI_CMD_MSE); - Fault fault = writeBar(req, data); - - if (fault && fault->isMachineCheckFault()) { - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); - - return genMachineCheckFault(); - } - - return fault; -} - -Fault -Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) -{ - int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff; - Addr index = daddr >> Regs::VirtualShift; - Addr raddr = daddr & Regs::VirtualMask; - - if (!regValid(raddr)) - panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d", - cpu, daddr, req->paddr, req->vaddr, req->size); - - const Regs::Info &info = regInfo(raddr); - if (!info.write) - panic("write %s (read only): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); - - if (req->size != info.size) - panic("write %s (invalid size): " - "cpu=%d vnic=%d da=%#x pa=%#x va=%#x size=%d", - info.name, cpu, index, daddr, req->paddr, req->vaddr, req->size); - - uint32_t reg32 = *(uint32_t *)data; - uint64_t reg64 = *(uint64_t *)data; - VirtualReg &vnic = virtualRegs[index]; - - DPRINTF(EthernetPIO, - "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n", - info.name, index, cpu, info.size == 4 ? reg32 : reg64, daddr, - req->paddr, req->vaddr, req->size); - - prepareWrite(cpu, index); - - switch (raddr) { - case Regs::Config: - changeConfig(reg32); - break; - - case Regs::Command: - command(reg32); - break; - - case Regs::IntrStatus: - devIntrClear(regs.IntrStatus & reg32); - break; - - case Regs::IntrMask: - devIntrChangeMask(reg32); - break; - - case Regs::RxData: - if (Regs::get_RxDone_Busy(vnic.RxDone)) - panic("receive machine busy with another request! rxState=%s", - RxStateStrings[rxState]); - - vnic.rxUnique = rxUnique++; - vnic.RxDone = Regs::RxDone_Busy; - vnic.RxData = reg64; - - if (Regs::get_RxData_Vaddr(reg64)) { - Addr vaddr = Regs::get_RxData_Addr(reg64); - Addr paddr = vtophys(req->xc, vaddr); - DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): " - "vaddr=%#x, paddr=%#x\n", - index, vnic.rxUnique, vaddr, paddr); - - vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr); - } else { - DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n", - index, vnic.rxUnique); - } - - if (vnic.rxPacket == rxFifo.end()) { - DPRINTF(EthernetPIO, "request new packet...appending to rxList\n"); - rxList.push_back(index); - } else { - DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n"); - rxBusy.push_back(index); - } - - if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) { - rxState = rxFifoBlock; - rxKick(); - } - break; - - case Regs::TxData: - if (Regs::get_TxDone_Busy(vnic.TxDone)) - panic("transmit machine busy with another request! txState=%s", - TxStateStrings[txState]); - - vnic.txUnique = txUnique++; - vnic.TxDone = Regs::TxDone_Busy; - vnic.TxData = reg64; - - if (Regs::get_TxData_Vaddr(reg64)) { - Addr vaddr = Regs::get_TxData_Addr(reg64); - Addr paddr = vtophys(req->xc, vaddr); - DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): " - "vaddr=%#x, paddr=%#x\n", - index, vnic.txUnique, vaddr, paddr); - - vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr); - } else { - DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n", - index, vnic.txUnique); - } - - if (txList.empty() || txList.front() != index) - txList.push_back(index); - if (txEnable && txState == txIdle && txList.front() == index) { - txState = txFifoBlock; - txKick(); - } - break; - } - - return NoFault; -} - -void -Device::devIntrPost(uint32_t interrupts) -{ - if ((interrupts & Regs::Intr_Res)) - panic("Cannot set a reserved interrupt"); - - regs.IntrStatus |= interrupts; - - DPRINTF(EthernetIntr, - "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n", - interrupts, regs.IntrStatus, regs.IntrMask); - - interrupts = regs.IntrStatus & regs.IntrMask; - - // Intr_RxHigh is special, we only signal it if we've emptied the fifo - // and then filled it above the high watermark - if (rxEmpty) - rxEmpty = false; - else - interrupts &= ~Regs::Intr_RxHigh; - - // Intr_TxLow is special, we only signal it if we've filled up the fifo - // and then dropped below the low watermark - if (txFull) - txFull = false; - else - interrupts &= ~Regs::Intr_TxLow; - - if (interrupts) { - Tick when = curTick; - if ((interrupts & Regs::Intr_NoDelay) == 0) - when += intrDelay; - cpuIntrPost(when); - } -} - -void -Device::devIntrClear(uint32_t interrupts) -{ - if ((interrupts & Regs::Intr_Res)) - panic("Cannot clear a reserved interrupt"); - - regs.IntrStatus &= ~interrupts; - - DPRINTF(EthernetIntr, - "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n", - interrupts, regs.IntrStatus, regs.IntrMask); - - if (!(regs.IntrStatus & regs.IntrMask)) - cpuIntrClear(); -} - -void -Device::devIntrChangeMask(uint32_t newmask) -{ - if (regs.IntrMask == newmask) - return; - - regs.IntrMask = newmask; - - DPRINTF(EthernetIntr, - "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n", - regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask); - - if (regs.IntrStatus & regs.IntrMask) - cpuIntrPost(curTick); - else - cpuIntrClear(); -} - -void -Base::cpuIntrPost(Tick when) -{ - // If the interrupt you want to post is later than an interrupt - // already scheduled, just let it post in the coming one and don't - // schedule another. - // HOWEVER, must be sure that the scheduled intrTick is in the - // future (this was formerly the source of a bug) - /** - * @todo this warning should be removed and the intrTick code should - * be fixed. - */ - assert(when >= curTick); - assert(intrTick >= curTick || intrTick == 0); - if (!cpuIntrEnable) { - DPRINTF(EthernetIntr, "interrupts not enabled.\n", - intrTick); - return; - } - - if (when > intrTick && intrTick != 0) { - DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", - intrTick); - return; - } - - intrTick = when; - if (intrTick < curTick) { - debug_break(); - intrTick = curTick; - } - - DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", - intrTick); - - if (intrEvent) - intrEvent->squash(); - intrEvent = new IntrEvent(this, true); - intrEvent->schedule(intrTick); -} - -void -Base::cpuInterrupt() -{ - assert(intrTick == curTick); - - // Whether or not there's a pending interrupt, we don't care about - // it anymore - intrEvent = 0; - intrTick = 0; - - // Don't send an interrupt if there's already one - if (cpuPendingIntr) { - DPRINTF(EthernetIntr, - "would send an interrupt now, but there's already pending\n"); - } else { - // Send interrupt - cpuPendingIntr = true; - - DPRINTF(EthernetIntr, "posting interrupt\n"); - intrPost(); - } -} - -void -Base::cpuIntrClear() -{ - if (!cpuPendingIntr) - return; - - if (intrEvent) { - intrEvent->squash(); - intrEvent = 0; - } - - intrTick = 0; - - cpuPendingIntr = false; - - DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); - intrClear(); -} - -bool -Base::cpuIntrPending() const -{ return cpuPendingIntr; } - -void -Device::changeConfig(uint32_t newconf) -{ - uint32_t changed = regs.Config ^ newconf; - if (!changed) - return; - - regs.Config = newconf; - - if ((changed & Regs::Config_IntEn)) { - cpuIntrEnable = regs.Config & Regs::Config_IntEn; - if (cpuIntrEnable) { - if (regs.IntrStatus & regs.IntrMask) - cpuIntrPost(curTick); - } else { - cpuIntrClear(); - } - } - - if ((changed & Regs::Config_TxEn)) { - txEnable = regs.Config & Regs::Config_TxEn; - if (txEnable) - txKick(); - } - - if ((changed & Regs::Config_RxEn)) { - rxEnable = regs.Config & Regs::Config_RxEn; - if (rxEnable) - rxKick(); - } -} - -void -Device::command(uint32_t command) -{ - if (command & Regs::Command_Intr) - devIntrPost(Regs::Intr_Soft); - - if (command & Regs::Command_Reset) - reset(); -} - -void -Device::reset() -{ - using namespace Regs; - - memset(®s, 0, sizeof(regs)); - - regs.Config = 0; - if (params()->rx_thread) - regs.Config |= Config_RxThread; - if (params()->tx_thread) - regs.Config |= Config_TxThread; - if (params()->rss) - regs.Config |= Config_RSS; - if (params()->zero_copy) - regs.Config |= Config_ZeroCopy; - if (params()->delay_copy) - regs.Config |= Config_DelayCopy; - if (params()->virtual_addr) - regs.Config |= Config_Vaddr; - - if (params()->delay_copy && params()->zero_copy) - panic("Can't delay copy and zero copy"); - - regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow; - regs.RxMaxCopy = params()->rx_max_copy; - regs.TxMaxCopy = params()->tx_max_copy; - regs.RxMaxIntr = params()->rx_max_intr; - regs.VirtualCount = params()->virtual_count; - regs.RxFifoSize = params()->rx_fifo_size; - regs.TxFifoSize = params()->tx_fifo_size; - regs.RxFifoMark = params()->rx_fifo_threshold; - regs.TxFifoMark = params()->tx_fifo_threshold; - regs.HwAddr = params()->eaddr; - - rxList.clear(); - rxBusy.clear(); - rxActive = -1; - txList.clear(); - - rxState = rxIdle; - txState = txIdle; - - rxFifo.clear(); - rxFifoPtr = rxFifo.end(); - txFifo.clear(); - rxEmpty = false; - rxLow = true; - txFull = false; - - int size = virtualRegs.size(); - virtualRegs.clear(); - virtualRegs.resize(size); - for (int i = 0; i < size; ++i) - virtualRegs[i].rxPacket = rxFifo.end(); -} - -void -Device::rxDmaCopy() -{ - assert(rxState == rxCopy); - rxState = rxCopyDone; - DPRINTF(EthernetDMA, "begin rx dma write paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); - DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n", - rxDmaAddr, rxDmaLen); - DDUMP(EthernetData, rxDmaData, rxDmaLen); -} - -void -Device::rxDmaDone() -{ - rxDmaCopy(); - - // If the transmit state machine has a pending DMA, let it go first - if (txState == txBeginCopy) - txKick(); - - rxKick(); -} - -void -Device::rxKick() -{ - VirtualReg *vnic = NULL; - - DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n", - RxStateStrings[rxState], rxFifo.size()); - - if (rxKickTick > curTick) { - DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n", - rxKickTick); - return; - } - - next: - if (rxState == rxIdle) - goto exit; - - if (rxActive == -1) { - if (rxState != rxFifoBlock) - panic("no active vnic while in state %s", RxStateStrings[rxState]); - - DPRINTF(EthernetSM, "processing rxState=%s\n", - RxStateStrings[rxState]); - } else { - vnic = &virtualRegs[rxActive]; - DPRINTF(EthernetSM, - "processing rxState=%s for vnic %d (rxunique %d)\n", - RxStateStrings[rxState], rxActive, vnic->rxUnique); - } - - switch (rxState) { - case rxFifoBlock: - if (DTRACE(EthernetSM)) { - PacketFifo::iterator end = rxFifo.end(); - int size = virtualRegs.size(); - for (int i = 0; i < size; ++i) { - VirtualReg *vn = &virtualRegs[i]; - if (vn->rxPacket != end && - !Regs::get_RxDone_Busy(vn->RxDone)) { - DPRINTF(EthernetSM, - "vnic %d (rxunique %d), has outstanding packet %d\n", - i, vn->rxUnique, - rxFifo.countPacketsBefore(vn->rxPacket)); - } - } - } - - if (!rxBusy.empty()) { - rxActive = rxBusy.front(); - rxBusy.pop_front(); - vnic = &virtualRegs[rxActive]; - - if (vnic->rxPacket == rxFifo.end()) - panic("continuing vnic without packet\n"); - - DPRINTF(EthernetSM, - "continue processing for vnic %d (rxunique %d)\n", - rxActive, vnic->rxUnique); - - rxState = rxBeginCopy; - - break; - } - - if (rxFifoPtr == rxFifo.end()) { - DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n"); - goto exit; - } - - if (rxList.empty()) - panic("Not idle, but nothing to do!"); - - assert(!rxFifo.empty()); - - rxActive = rxList.front(); - rxList.pop_front(); - vnic = &virtualRegs[rxActive]; - - DPRINTF(EthernetSM, - "processing new packet for vnic %d (rxunique %d)\n", - rxActive, vnic->rxUnique); - - // Grab a new packet from the fifo. - vnic->rxPacket = rxFifoPtr++; - vnic->rxPacketOffset = 0; - vnic->rxPacketBytes = (*vnic->rxPacket)->length; - assert(vnic->rxPacketBytes); - - vnic->rxDoneData = 0; - /* scope for variables */ { - IpPtr ip(*vnic->rxPacket); - if (ip) { - DPRINTF(Ethernet, "ID is %d\n", ip->id()); - vnic->rxDoneData |= Regs::RxDone_IpPacket; - rxIpChecksums++; - if (cksum(ip) != 0) { - DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); - vnic->rxDoneData |= Regs::RxDone_IpError; - } - TcpPtr tcp(ip); - UdpPtr udp(ip); - if (tcp) { - DPRINTF(Ethernet, - "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", - tcp->sport(), tcp->dport(), tcp->seq(), - tcp->ack()); - vnic->rxDoneData |= Regs::RxDone_TcpPacket; - rxTcpChecksums++; - if (cksum(tcp) != 0) { - DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); - vnic->rxDoneData |= Regs::RxDone_TcpError; - } - } else if (udp) { - vnic->rxDoneData |= Regs::RxDone_UdpPacket; - rxUdpChecksums++; - if (cksum(udp) != 0) { - DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); - vnic->rxDoneData |= Regs::RxDone_UdpError; - } - } - } - } - rxState = rxBeginCopy; - break; - - case rxBeginCopy: - if (dmaInterface && dmaInterface->busy()) - goto exit; - - rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData)); - rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData), - vnic->rxPacketBytes); - rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset; - rxState = rxCopy; - - if (rxDmaAddr == 1LL) { - rxState = rxCopyDone; - break; - } - - if (dmaInterface) { - dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, - curTick, &rxDmaEvent, true); - goto exit; - } - - if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { - Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; - Tick start = curTick + dmaWriteDelay + factor; - rxDmaEvent.schedule(start); - goto exit; - } - - rxDmaCopy(); - break; - - case rxCopy: - DPRINTF(EthernetSM, "receive machine still copying\n"); - goto exit; - - case rxCopyDone: - vnic->RxDone = vnic->rxDoneData; - vnic->RxDone |= Regs::RxDone_Complete; - - if (vnic->rxPacketBytes == rxDmaLen) { - // Packet is complete. Indicate how many bytes were copied - vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen); - - DPRINTF(EthernetSM, - "rxKick: packet complete on vnic %d (rxunique %d)\n", - rxActive, vnic->rxUnique); - rxFifo.remove(vnic->rxPacket); - vnic->rxPacket = rxFifo.end(); - } else { - vnic->rxPacketBytes -= rxDmaLen; - vnic->rxPacketOffset += rxDmaLen; - vnic->RxDone |= Regs::RxDone_More; - vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, - vnic->rxPacketBytes); - DPRINTF(EthernetSM, - "rxKick: packet not complete on vnic %d (rxunique %d): " - "%d bytes left\n", - rxActive, vnic->rxUnique, vnic->rxPacketBytes); - } - - rxActive = -1; - rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock; - - if (rxFifo.empty()) { - devIntrPost(Regs::Intr_RxEmpty); - rxEmpty = true; - } - - if (rxFifo.size() < params()->rx_fifo_low_mark) - rxLow = true; - - if (rxFifo.size() > params()->rx_fifo_threshold) - rxLow = false; - - devIntrPost(Regs::Intr_RxDMA); - break; - - default: - panic("Invalid rxState!"); - } - - DPRINTF(EthernetSM, "entering next rxState=%s\n", - RxStateStrings[rxState]); - - goto next; - - exit: - /** - * @todo do we want to schedule a future kick? - */ - DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", - RxStateStrings[rxState]); -} - -void -Device::txDmaCopy() -{ - assert(txState == txCopy); - txState = txCopyDone; - physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); - DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", - txDmaAddr, txDmaLen); - DDUMP(EthernetData, txDmaData, txDmaLen); -} - -void -Device::txDmaDone() -{ - txDmaCopy(); - - // If the receive state machine has a pending DMA, let it go first - if (rxState == rxBeginCopy) - rxKick(); - - txKick(); -} - -void -Device::transmit() -{ - if (txFifo.empty()) { - DPRINTF(Ethernet, "nothing to transmit\n"); - return; - } - - uint32_t interrupts; - PacketPtr packet = txFifo.front(); - if (!interface->sendPacket(packet)) { - DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", - txFifo.avail()); - goto reschedule; - } - - txFifo.pop(); -#if TRACING_ON - if (DTRACE(Ethernet)) { - IpPtr ip(packet); - if (ip) { - DPRINTF(Ethernet, "ID is %d\n", ip->id()); - TcpPtr tcp(ip); - if (tcp) { - DPRINTF(Ethernet, - "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", - tcp->sport(), tcp->dport(), tcp->seq(), - tcp->ack()); - } - } - } -#endif - - DDUMP(EthernetData, packet->data, packet->length); - txBytes += packet->length; - txPackets++; - - DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", - txFifo.avail()); - - interrupts = Regs::Intr_TxPacket; - if (txFifo.size() < regs.TxFifoMark) - interrupts |= Regs::Intr_TxLow; - devIntrPost(interrupts); - - reschedule: - if (!txFifo.empty() && !txEvent.scheduled()) { - DPRINTF(Ethernet, "reschedule transmit\n"); - txEvent.schedule(curTick + retryTime); - } -} - -void -Device::txKick() -{ - VirtualReg *vnic; - DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n", - TxStateStrings[txState], txFifo.size()); - - if (txKickTick > curTick) { - DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n", - txKickTick); - return; - } - - next: - if (txState == txIdle) - goto exit; - - assert(!txList.empty()); - vnic = &virtualRegs[txList.front()]; - - switch (txState) { - case txFifoBlock: - assert(Regs::get_TxDone_Busy(vnic->TxDone)); - if (!txPacket) { - // Grab a new packet from the fifo. - txPacket = new PacketData(16384); - txPacketOffset = 0; - } - - if (txFifo.avail() - txPacket->length < - Regs::get_TxData_Len(vnic->TxData)) { - DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n"); - goto exit; - } - - txState = txBeginCopy; - break; - - case txBeginCopy: - if (dmaInterface && dmaInterface->busy()) - goto exit; - - txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(vnic->TxData)); - txDmaLen = Regs::get_TxData_Len(vnic->TxData); - txDmaData = txPacket->data + txPacketOffset; - txState = txCopy; - - if (dmaInterface) { - dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, - curTick, &txDmaEvent, true); - goto exit; - } - - if (dmaReadDelay != 0 || dmaReadFactor != 0) { - Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; - Tick start = curTick + dmaReadDelay + factor; - txDmaEvent.schedule(start); - goto exit; - } - - txDmaCopy(); - break; - - case txCopy: - DPRINTF(EthernetSM, "transmit machine still copying\n"); - goto exit; - - case txCopyDone: - vnic->TxDone = txDmaLen | Regs::TxDone_Complete; - txPacket->length += txDmaLen; - if ((vnic->TxData & Regs::TxData_More)) { - txPacketOffset += txDmaLen; - txState = txIdle; - devIntrPost(Regs::Intr_TxDMA); - break; - } - - assert(txPacket->length <= txFifo.avail()); - if ((vnic->TxData & Regs::TxData_Checksum)) { - IpPtr ip(txPacket); - if (ip) { - TcpPtr tcp(ip); - if (tcp) { - tcp->sum(0); - tcp->sum(cksum(tcp)); - txTcpChecksums++; - } - - UdpPtr udp(ip); - if (udp) { - udp->sum(0); - udp->sum(cksum(udp)); - txUdpChecksums++; - } - - ip->sum(0); - ip->sum(cksum(ip)); - txIpChecksums++; - } - } - - txFifo.push(txPacket); - if (txFifo.avail() < regs.TxMaxCopy) { - devIntrPost(Regs::Intr_TxFull); - txFull = true; - } - txPacket = 0; - transmit(); - txList.pop_front(); - txState = txList.empty() ? txIdle : txFifoBlock; - devIntrPost(Regs::Intr_TxDMA); - break; - - default: - panic("Invalid txState!"); - } - - DPRINTF(EthernetSM, "entering next txState=%s\n", - TxStateStrings[txState]); - - goto next; - - exit: - /** - * @todo do we want to schedule a future kick? - */ - DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", - TxStateStrings[txState]); -} - -void -Device::transferDone() -{ - if (txFifo.empty()) { - DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); - return; - } - - DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - - if (txEvent.scheduled()) - txEvent.reschedule(curTick + cycles(1)); - else - txEvent.schedule(curTick + cycles(1)); -} - -bool -Device::rxFilter(const PacketPtr &packet) -{ - if (!Regs::get_Config_Filter(regs.Config)) - return false; - - panic("receive filter not implemented\n"); - bool drop = true; - -#if 0 - string type; - - EthHdr *eth = packet->eth(); - if (eth->unicast()) { - // If we're accepting all unicast addresses - if (acceptUnicast) - drop = false; - - // If we make a perfect match - if (acceptPerfect && params->eaddr == eth.dst()) - drop = false; - - if (acceptArp && eth->type() == ETH_TYPE_ARP) - drop = false; - - } else if (eth->broadcast()) { - // if we're accepting broadcasts - if (acceptBroadcast) - drop = false; - - } else if (eth->multicast()) { - // if we're accepting all multicasts - if (acceptMulticast) - drop = false; - - } - - if (drop) { - DPRINTF(Ethernet, "rxFilter drop\n"); - DDUMP(EthernetData, packet->data, packet->length); - } -#endif - return drop; -} - -bool -Device::recvPacket(PacketPtr packet) -{ - rxBytes += packet->length; - rxPackets++; - - DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n", - rxFifo.avail()); - - if (!rxEnable) { - DPRINTF(Ethernet, "receive disabled...packet dropped\n"); - return true; - } - - if (rxFilter(packet)) { - DPRINTF(Ethernet, "packet filtered...dropped\n"); - return true; - } - - if (rxFifo.size() >= regs.RxFifoMark) - devIntrPost(Regs::Intr_RxHigh); - - if (!rxFifo.push(packet)) { - DPRINTF(Ethernet, - "packet will not fit in receive buffer...packet dropped\n"); - return false; - } - - // If we were at the last element, back up one ot go to the new - // last element of the list. - if (rxFifoPtr == rxFifo.end()) - --rxFifoPtr; - - devIntrPost(Regs::Intr_RxPacket); - rxKick(); - return true; -} - -//===================================================================== -// -// -void -Base::serialize(ostream &os) -{ - // Serialize the PciDev base class - PciDev::serialize(os); - - SERIALIZE_SCALAR(rxEnable); - SERIALIZE_SCALAR(txEnable); - SERIALIZE_SCALAR(cpuIntrEnable); - - /* - * Keep track of pending interrupt status. - */ - SERIALIZE_SCALAR(intrTick); - SERIALIZE_SCALAR(cpuPendingIntr); - Tick intrEventTick = 0; - if (intrEvent) - intrEventTick = intrEvent->when(); - SERIALIZE_SCALAR(intrEventTick); -} - -void -Base::unserialize(Checkpoint *cp, const std::string §ion) -{ - // Unserialize the PciDev base class - PciDev::unserialize(cp, section); - - UNSERIALIZE_SCALAR(rxEnable); - UNSERIALIZE_SCALAR(txEnable); - UNSERIALIZE_SCALAR(cpuIntrEnable); - - /* - * Keep track of pending interrupt status. - */ - UNSERIALIZE_SCALAR(intrTick); - UNSERIALIZE_SCALAR(cpuPendingIntr); - Tick intrEventTick; - UNSERIALIZE_SCALAR(intrEventTick); - if (intrEventTick) { - intrEvent = new IntrEvent(this, true); - intrEvent->schedule(intrEventTick); - } -} - -void -Device::serialize(ostream &os) -{ - int count; - - // Serialize the PciDev base class - Base::serialize(os); - - if (rxState == rxCopy) - panic("can't serialize with an in flight dma request rxState=%s", - RxStateStrings[rxState]); - - if (txState == txCopy) - panic("can't serialize with an in flight dma request txState=%s", - TxStateStrings[txState]); - - /* - * Serialize the device registers - */ - SERIALIZE_SCALAR(regs.Config); - SERIALIZE_SCALAR(regs.IntrStatus); - SERIALIZE_SCALAR(regs.IntrMask); - SERIALIZE_SCALAR(regs.RxMaxCopy); - SERIALIZE_SCALAR(regs.TxMaxCopy); - SERIALIZE_SCALAR(regs.RxMaxIntr); - SERIALIZE_SCALAR(regs.VirtualCount); - SERIALIZE_SCALAR(regs.RxData); - SERIALIZE_SCALAR(regs.RxDone); - SERIALIZE_SCALAR(regs.TxData); - SERIALIZE_SCALAR(regs.TxDone); - - /* - * Serialize the virtual nic state - */ - int virtualRegsSize = virtualRegs.size(); - SERIALIZE_SCALAR(virtualRegsSize); - for (int i = 0; i < virtualRegsSize; ++i) { - VirtualReg *vnic = &virtualRegs[i]; - - string reg = csprintf("vnic%d", i); - paramOut(os, reg + ".RxData", vnic->RxData); - paramOut(os, reg + ".RxDone", vnic->RxDone); - paramOut(os, reg + ".TxData", vnic->TxData); - paramOut(os, reg + ".TxDone", vnic->TxDone); - - bool rxPacketExists = vnic->rxPacket != rxFifo.end(); - paramOut(os, reg + ".rxPacketExists", rxPacketExists); - if (rxPacketExists) { - int rxPacket = 0; - PacketFifo::iterator i = rxFifo.begin(); - while (i != vnic->rxPacket) { - assert(i != rxFifo.end()); - ++i; - ++rxPacket; - } - - paramOut(os, reg + ".rxPacket", rxPacket); - paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset); - paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes); - } - paramOut(os, reg + ".rxDoneData", vnic->rxDoneData); - } - - int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr); - SERIALIZE_SCALAR(rxFifoPtr); - - SERIALIZE_SCALAR(rxActive); - - VirtualList::iterator i, end; - for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i) - paramOut(os, csprintf("rxList%d", count++), *i); - int rxListSize = count; - SERIALIZE_SCALAR(rxListSize); - - for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i) - paramOut(os, csprintf("rxBusy%d", count++), *i); - int rxBusySize = count; - SERIALIZE_SCALAR(rxBusySize); - - for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i) - paramOut(os, csprintf("txList%d", count++), *i); - int txListSize = count; - SERIALIZE_SCALAR(txListSize); - - /* - * Serialize rx state machine - */ - int rxState = this->rxState; - SERIALIZE_SCALAR(rxState); - SERIALIZE_SCALAR(rxEmpty); - SERIALIZE_SCALAR(rxLow); - rxFifo.serialize("rxFifo", os); - - /* - * Serialize tx state machine - */ - int txState = this->txState; - SERIALIZE_SCALAR(txState); - SERIALIZE_SCALAR(txFull); - txFifo.serialize("txFifo", os); - bool txPacketExists = txPacket; - SERIALIZE_SCALAR(txPacketExists); - if (txPacketExists) { - txPacket->serialize("txPacket", os); - SERIALIZE_SCALAR(txPacketOffset); - SERIALIZE_SCALAR(txPacketBytes); - } - - /* - * If there's a pending transmit, store the time so we can - * reschedule it later - */ - Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; - SERIALIZE_SCALAR(transmitTick); -} - -void -Device::unserialize(Checkpoint *cp, const std::string §ion) -{ - // Unserialize the PciDev base class - Base::unserialize(cp, section); - - /* - * Unserialize the device registers - */ - UNSERIALIZE_SCALAR(regs.Config); - UNSERIALIZE_SCALAR(regs.IntrStatus); - UNSERIALIZE_SCALAR(regs.IntrMask); - UNSERIALIZE_SCALAR(regs.RxMaxCopy); - UNSERIALIZE_SCALAR(regs.TxMaxCopy); - UNSERIALIZE_SCALAR(regs.RxMaxIntr); - UNSERIALIZE_SCALAR(regs.VirtualCount); - UNSERIALIZE_SCALAR(regs.RxData); - UNSERIALIZE_SCALAR(regs.RxDone); - UNSERIALIZE_SCALAR(regs.TxData); - UNSERIALIZE_SCALAR(regs.TxDone); - - UNSERIALIZE_SCALAR(rxActive); - - int rxListSize; - UNSERIALIZE_SCALAR(rxListSize); - rxList.clear(); - for (int i = 0; i < rxListSize; ++i) { - int value; - paramIn(cp, section, csprintf("rxList%d", i), value); - rxList.push_back(value); - } - - int rxBusySize; - UNSERIALIZE_SCALAR(rxBusySize); - rxBusy.clear(); - for (int i = 0; i < rxBusySize; ++i) { - int value; - paramIn(cp, section, csprintf("rxBusy%d", i), value); - rxBusy.push_back(value); - } - - int txListSize; - UNSERIALIZE_SCALAR(txListSize); - txList.clear(); - for (int i = 0; i < txListSize; ++i) { - int value; - paramIn(cp, section, csprintf("txList%d", i), value); - txList.push_back(value); - } - - /* - * Unserialize rx state machine - */ - int rxState; - UNSERIALIZE_SCALAR(rxState); - UNSERIALIZE_SCALAR(rxEmpty); - UNSERIALIZE_SCALAR(rxLow); - this->rxState = (RxState) rxState; - rxFifo.unserialize("rxFifo", cp, section); - - int rxFifoPtr; - UNSERIALIZE_SCALAR(rxFifoPtr); - this->rxFifoPtr = rxFifo.begin(); - for (int i = 0; i < rxFifoPtr; ++i) - ++this->rxFifoPtr; - - /* - * Unserialize tx state machine - */ - int txState; - UNSERIALIZE_SCALAR(txState); - UNSERIALIZE_SCALAR(txFull); - this->txState = (TxState) txState; - txFifo.unserialize("txFifo", cp, section); - bool txPacketExists; - UNSERIALIZE_SCALAR(txPacketExists); - txPacket = 0; - if (txPacketExists) { - txPacket = new PacketData(16384); - txPacket->unserialize("txPacket", cp, section); - UNSERIALIZE_SCALAR(txPacketOffset); - UNSERIALIZE_SCALAR(txPacketBytes); - } - - /* - * unserialize the virtual nic registers/state - * - * this must be done after the unserialization of the rxFifo - * because the packet iterators depend on the fifo being populated - */ - int virtualRegsSize; - UNSERIALIZE_SCALAR(virtualRegsSize); - virtualRegs.clear(); - virtualRegs.resize(virtualRegsSize); - for (int i = 0; i < virtualRegsSize; ++i) { - VirtualReg *vnic = &virtualRegs[i]; - string reg = csprintf("vnic%d", i); - - paramIn(cp, section, reg + ".RxData", vnic->RxData); - paramIn(cp, section, reg + ".RxDone", vnic->RxDone); - paramIn(cp, section, reg + ".TxData", vnic->TxData); - paramIn(cp, section, reg + ".TxDone", vnic->TxDone); - - vnic->rxUnique = rxUnique++; - vnic->txUnique = txUnique++; - - bool rxPacketExists; - paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists); - if (rxPacketExists) { - int rxPacket; - paramIn(cp, section, reg + ".rxPacket", rxPacket); - vnic->rxPacket = rxFifo.begin(); - while (rxPacket--) - ++vnic->rxPacket; - - paramIn(cp, section, reg + ".rxPacketOffset", - vnic->rxPacketOffset); - paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes); - } else { - vnic->rxPacket = rxFifo.end(); - } - paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData); - } - - /* - * If there's a pending transmit, reschedule it now - */ - Tick transmitTick; - UNSERIALIZE_SCALAR(transmitTick); - if (transmitTick) - txEvent.schedule(curTick + transmitTick); - - /* - * re-add addrRanges to bus bridges - */ - if (pioInterface) - pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); -} - -Tick -Device::cacheAccess(MemReqPtr &req) -{ - Addr daddr; - int bar; - if (!getBAR(req->paddr, daddr, bar)) - panic("address does not map to a BAR pa=%#x va=%#x size=%d", - req->paddr, req->vaddr, req->size); - - DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n", - req->cmd.toString(), req->paddr, bar, daddr); - - return curTick + pioLatency; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) - - SimObjectParam<EtherInt *> peer; - SimObjectParam<Device *> device; - -END_DECLARE_SIM_OBJECT_PARAMS(Interface) - -BEGIN_INIT_SIM_OBJECT_PARAMS(Interface) - - INIT_PARAM_DFLT(peer, "peer interface", NULL), - INIT_PARAM(device, "Ethernet device of this interface") - -END_INIT_SIM_OBJECT_PARAMS(Interface) - -CREATE_SIM_OBJECT(Interface) -{ - Interface *dev_int = new Interface(getInstanceName(), device); - - EtherInt *p = (EtherInt *)peer; - if (p) { - dev_int->setPeer(p); - p->setPeer(dev_int); - } - - return dev_int; -} - -REGISTER_SIM_OBJECT("SinicInt", Interface) - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) - - Param<Tick> clock; - - Param<Addr> addr; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<PhysicalMemory *> physmem; - SimObjectParam<PciConfigAll *> configspace; - SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; - Param<uint32_t> pci_bus; - Param<uint32_t> pci_dev; - Param<uint32_t> pci_func; - - SimObjectParam<HierParams *> hier; - SimObjectParam<Bus*> pio_bus; - SimObjectParam<Bus*> dma_bus; - SimObjectParam<Bus*> payload_bus; - Param<Tick> dma_read_delay; - Param<Tick> dma_read_factor; - Param<Tick> dma_write_delay; - Param<Tick> dma_write_factor; - Param<bool> dma_no_allocate; - Param<Tick> pio_latency; - Param<Tick> intr_delay; - - Param<Tick> rx_delay; - Param<Tick> tx_delay; - Param<uint32_t> rx_max_copy; - Param<uint32_t> tx_max_copy; - Param<uint32_t> rx_max_intr; - Param<uint32_t> rx_fifo_size; - Param<uint32_t> tx_fifo_size; - Param<uint32_t> rx_fifo_threshold; - Param<uint32_t> rx_fifo_low_mark; - Param<uint32_t> tx_fifo_high_mark; - Param<uint32_t> tx_fifo_threshold; - - Param<bool> rx_filter; - Param<string> hardware_address; - Param<bool> rx_thread; - Param<bool> tx_thread; - Param<bool> rss; - Param<uint32_t> virtual_count; - Param<bool> zero_copy; - Param<bool> delay_copy; - Param<bool> virtual_addr; - -END_DECLARE_SIM_OBJECT_PARAMS(Device) - -BEGIN_INIT_SIM_OBJECT_PARAMS(Device) - - INIT_PARAM(clock, "State machine cycle time"), - - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM(configspace, "PCI Configspace"), - INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(platform, "Platform"), - INIT_PARAM(pci_bus, "PCI bus"), - INIT_PARAM(pci_dev, "PCI device number"), - INIT_PARAM(pci_func, "PCI function code"), - - INIT_PARAM(hier, "Hierarchy global variables"), - INIT_PARAM(pio_bus, ""), - INIT_PARAM(dma_bus, ""), - INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), - INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), - INIT_PARAM(dma_read_factor, "multiplier for dma reads"), - INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), - INIT_PARAM(dma_write_factor, "multiplier for dma writes"), - INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), - INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), - INIT_PARAM(intr_delay, "Interrupt Delay"), - - INIT_PARAM(rx_delay, "Receive Delay"), - INIT_PARAM(tx_delay, "Transmit Delay"), - INIT_PARAM(rx_max_copy, "rx max copy"), - INIT_PARAM(tx_max_copy, "rx max copy"), - INIT_PARAM(rx_max_intr, "rx max intr"), - INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), - INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), - INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"), - INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"), - INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"), - INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"), - - INIT_PARAM(rx_filter, "Enable Receive Filter"), - INIT_PARAM(hardware_address, "Ethernet Hardware Address"), - INIT_PARAM(rx_thread, ""), - INIT_PARAM(tx_thread, ""), - INIT_PARAM(rss, ""), - INIT_PARAM(virtual_count, ""), - INIT_PARAM(zero_copy, ""), - INIT_PARAM(delay_copy, ""), - INIT_PARAM(virtual_addr, "") - -END_INIT_SIM_OBJECT_PARAMS(Device) - - -CREATE_SIM_OBJECT(Device) -{ - Device::Params *params = new Device::Params; - - params->name = getInstanceName(); - - params->clock = clock; - - params->mmu = mmu; - params->physmem = physmem; - params->configSpace = configspace; - params->configData = configdata; - params->plat = platform; - params->busNum = pci_bus; - params->deviceNum = pci_dev; - params->functionNum = pci_func; - - params->hier = hier; - params->pio_bus = pio_bus; - params->header_bus = dma_bus; - params->payload_bus = payload_bus; - params->dma_read_delay = dma_read_delay; - params->dma_read_factor = dma_read_factor; - params->dma_write_delay = dma_write_delay; - params->dma_write_factor = dma_write_factor; - params->dma_no_allocate = dma_no_allocate; - params->pio_latency = pio_latency; - params->intr_delay = intr_delay; - - params->tx_delay = tx_delay; - params->rx_delay = rx_delay; - params->rx_max_copy = rx_max_copy; - params->tx_max_copy = tx_max_copy; - params->rx_max_intr = rx_max_intr; - params->rx_fifo_size = rx_fifo_size; - params->tx_fifo_size = tx_fifo_size; - params->rx_fifo_threshold = rx_fifo_threshold; - params->rx_fifo_low_mark = rx_fifo_low_mark; - params->tx_fifo_high_mark = tx_fifo_high_mark; - params->tx_fifo_threshold = tx_fifo_threshold; - - params->rx_filter = rx_filter; - params->eaddr = hardware_address; - params->rx_thread = rx_thread; - params->tx_thread = tx_thread; - params->rss = rss; - params->virtual_count = virtual_count; - params->zero_copy = zero_copy; - params->delay_copy = delay_copy; - params->virtual_addr = virtual_addr; - - return new Device(params); -} - -REGISTER_SIM_OBJECT("Sinic", Device) - -/* namespace Sinic */ } diff --git a/dev/sinic.hh b/dev/sinic.hh deleted file mode 100644 index 892b3ab69..000000000 --- a/dev/sinic.hh +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DEV_SINIC_HH__ -#define __DEV_SINIC_HH__ - -#include "base/inet.hh" -#include "base/statistics.hh" -#include "dev/etherint.hh" -#include "dev/etherpkt.hh" -#include "dev/io_device.hh" -#include "dev/pcidev.hh" -#include "dev/pktfifo.hh" -#include "dev/sinicreg.hh" -#include "mem/bus/bus.hh" -#include "sim/eventq.hh" - -namespace Sinic { - -class Interface; -class Base : public PciDev -{ - protected: - bool rxEnable; - bool txEnable; - Tick clock; - inline Tick cycles(int numCycles) const { return numCycles * clock; } - - protected: - Tick intrDelay; - Tick intrTick; - bool cpuIntrEnable; - bool cpuPendingIntr; - void cpuIntrPost(Tick when); - void cpuInterrupt(); - void cpuIntrClear(); - - typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent; - friend void IntrEvent::process(); - IntrEvent *intrEvent; - Interface *interface; - - bool cpuIntrPending() const; - void cpuIntrAck() { cpuIntrClear(); } - -/** - * Serialization stuff - */ - public: - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - -/** - * Construction/Destruction/Parameters - */ - public: - struct Params : public PciDev::Params - { - Tick clock; - Tick intr_delay; - }; - - Base(Params *p); -}; - -class Device : public Base -{ - protected: - Platform *plat; - PhysicalMemory *physmem; - - protected: - /** Receive State Machine States */ - enum RxState { - rxIdle, - rxFifoBlock, - rxBeginCopy, - rxCopy, - rxCopyDone - }; - - /** Transmit State Machine states */ - enum TxState { - txIdle, - txFifoBlock, - txBeginCopy, - txCopy, - txCopyDone - }; - - /** device register file */ - struct { - uint32_t Config; // 0x00 - uint32_t Command; // 0x04 - uint32_t IntrStatus; // 0x08 - uint32_t IntrMask; // 0x0c - uint32_t RxMaxCopy; // 0x10 - uint32_t TxMaxCopy; // 0x14 - uint32_t RxMaxIntr; // 0x18 - uint32_t VirtualCount; // 0x1c - uint32_t RxFifoSize; // 0x20 - uint32_t TxFifoSize; // 0x24 - uint32_t RxFifoMark; // 0x28 - uint32_t TxFifoMark; // 0x2c - uint64_t RxData; // 0x30 - uint64_t RxDone; // 0x38 - uint64_t RxWait; // 0x40 - uint64_t TxData; // 0x48 - uint64_t TxDone; // 0x50 - uint64_t TxWait; // 0x58 - uint64_t HwAddr; // 0x60 - } regs; - - struct VirtualReg { - uint64_t RxData; - uint64_t RxDone; - uint64_t TxData; - uint64_t TxDone; - - PacketFifo::iterator rxPacket; - int rxPacketOffset; - int rxPacketBytes; - uint64_t rxDoneData; - - Counter rxUnique; - Counter txUnique; - - VirtualReg() - : RxData(0), RxDone(0), TxData(0), TxDone(0), - rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0) - { } - }; - typedef std::vector<VirtualReg> VirtualRegs; - typedef std::list<int> VirtualList; - Counter rxUnique; - Counter txUnique; - VirtualRegs virtualRegs; - VirtualList rxList; - VirtualList rxBusy; - int rxActive; - VirtualList txList; - - uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); } - uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); } - uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); } - - private: - Addr addr; - static const Addr size = Regs::Size; - - protected: - RxState rxState; - PacketFifo rxFifo; - PacketFifo::iterator rxFifoPtr; - bool rxEmpty; - bool rxLow; - Addr rxDmaAddr; - uint8_t *rxDmaData; - int rxDmaLen; - - TxState txState; - PacketFifo txFifo; - bool txFull; - PacketPtr txPacket; - int txPacketOffset; - int txPacketBytes; - Addr txDmaAddr; - uint8_t *txDmaData; - int txDmaLen; - - protected: - void reset(); - - void rxKick(); - Tick rxKickTick; - typedef EventWrapper<Device, &Device::rxKick> RxKickEvent; - friend void RxKickEvent::process(); - - void txKick(); - Tick txKickTick; - typedef EventWrapper<Device, &Device::txKick> TxKickEvent; - friend void TxKickEvent::process(); - - /** - * Retransmit event - */ - void transmit(); - void txEventTransmit() - { - transmit(); - if (txState == txFifoBlock) - txKick(); - } - typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent; - friend void TxEvent::process(); - TxEvent txEvent; - - void txDump() const; - void rxDump() const; - - /** - * receive address filter - */ - bool rxFilter(const PacketPtr &packet); - -/** - * device configuration - */ - void changeConfig(uint32_t newconfig); - void command(uint32_t command); - -/** - * device ethernet interface - */ - public: - bool recvPacket(PacketPtr packet); - void transferDone(); - void setInterface(Interface *i) { assert(!interface); interface = i; } - -/** - * DMA parameters - */ - protected: - void rxDmaCopy(); - void rxDmaDone(); - friend class EventWrapper<Device, &Device::rxDmaDone>; - EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent; - - void txDmaCopy(); - void txDmaDone(); - friend class EventWrapper<Device, &Device::txDmaDone>; - EventWrapper<Device, &Device::txDmaDone> txDmaEvent; - - Tick dmaReadDelay; - Tick dmaReadFactor; - Tick dmaWriteDelay; - Tick dmaWriteFactor; - -/** - * Interrupt management - */ - protected: - void devIntrPost(uint32_t interrupts); - void devIntrClear(uint32_t interrupts = Regs::Intr_All); - void devIntrChangeMask(uint32_t newmask); - -/** - * PCI Configuration interface - */ - public: - virtual void writeConfig(int offset, int size, const uint8_t *data); - -/** - * Memory Interface - */ - public: - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - void prepareIO(int cpu, int index); - void prepareRead(int cpu, int index); - void prepareWrite(int cpu, int index); - Fault iprRead(Addr daddr, int cpu, uint64_t &result); - Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data); - Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data); - Tick cacheAccess(MemReqPtr &req); - -/** - * Statistics - */ - private: - Stats::Scalar<> rxBytes; - Stats::Formula rxBandwidth; - Stats::Scalar<> rxPackets; - Stats::Formula rxPacketRate; - Stats::Scalar<> rxIpPackets; - Stats::Scalar<> rxTcpPackets; - Stats::Scalar<> rxUdpPackets; - Stats::Scalar<> rxIpChecksums; - Stats::Scalar<> rxTcpChecksums; - Stats::Scalar<> rxUdpChecksums; - - Stats::Scalar<> txBytes; - Stats::Formula txBandwidth; - Stats::Formula totBandwidth; - Stats::Formula totPackets; - Stats::Formula totBytes; - Stats::Formula totPacketRate; - Stats::Scalar<> txPackets; - Stats::Formula txPacketRate; - Stats::Scalar<> txIpPackets; - Stats::Scalar<> txTcpPackets; - Stats::Scalar<> txUdpPackets; - Stats::Scalar<> txIpChecksums; - Stats::Scalar<> txTcpChecksums; - Stats::Scalar<> txUdpChecksums; - - public: - virtual void regStats(); - -/** - * Serialization stuff - */ - public: - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - -/** - * Construction/Destruction/Parameters - */ - public: - struct Params : public Base::Params - { - IntrControl *i; - PhysicalMemory *pmem; - Tick tx_delay; - Tick rx_delay; - HierParams *hier; - Bus *pio_bus; - Bus *header_bus; - Bus *payload_bus; - Tick pio_latency; - PhysicalMemory *physmem; - IntrControl *intctrl; - bool rx_filter; - Net::EthAddr eaddr; - uint32_t rx_max_copy; - uint32_t tx_max_copy; - uint32_t rx_max_intr; - uint32_t rx_fifo_size; - uint32_t tx_fifo_size; - uint32_t rx_fifo_threshold; - uint32_t rx_fifo_low_mark; - uint32_t tx_fifo_high_mark; - uint32_t tx_fifo_threshold; - Tick dma_read_delay; - Tick dma_read_factor; - Tick dma_write_delay; - Tick dma_write_factor; - bool dma_no_allocate; - bool rx_thread; - bool tx_thread; - bool rss; - uint32_t virtual_count; - bool zero_copy; - bool delay_copy; - bool virtual_addr; - }; - - protected: - const Params *params() const { return (const Params *)_params; } - - public: - Device(Params *params); - ~Device(); -}; - -/* - * Ethernet Interface for an Ethernet Device - */ -class Interface : public EtherInt -{ - private: - Device *dev; - - public: - Interface(const std::string &name, Device *d) - : EtherInt(name), dev(d) { dev->setInterface(this); } - - virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } - virtual void sendDone() { dev->transferDone(); } -}; - -/* namespace Sinic */ } - -#endif // __DEV_SINIC_HH__ diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh deleted file mode 100644 index d41eb5b16..000000000 --- a/dev/sinicreg.hh +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DEV_SINICREG_HH__ -#define __DEV_SINICREG_HH__ - -#define __SINIC_REG32(NAME, VAL) static const uint32_t NAME = (VAL) -#define __SINIC_REG64(NAME, VAL) static const uint64_t NAME = (VAL) - -#define __SINIC_VAL32(NAME, OFFSET, WIDTH) \ - static const uint32_t NAME##_width = WIDTH; \ - static const uint32_t NAME##_offset = OFFSET; \ - static const uint32_t NAME##_mask = (1 << WIDTH) - 1; \ - static const uint32_t NAME = ((1 << WIDTH) - 1) << OFFSET; \ - static inline uint32_t get_##NAME(uint32_t reg) \ - { return (reg & NAME) >> OFFSET; } \ - static inline uint32_t set_##NAME(uint32_t reg, uint32_t val) \ - { return (reg & ~NAME) | ((val << OFFSET) & NAME); } - -#define __SINIC_VAL64(NAME, OFFSET, WIDTH) \ - static const uint64_t NAME##_width = WIDTH; \ - static const uint64_t NAME##_offset = OFFSET; \ - static const uint64_t NAME##_mask = (ULL(1) << WIDTH) - 1; \ - static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \ - static inline uint64_t get_##NAME(uint64_t reg) \ - { return (reg & NAME) >> OFFSET; } \ - static inline uint64_t set_##NAME(uint64_t reg, uint64_t val) \ - { return (reg & ~NAME) | ((val << OFFSET) & NAME); } - -namespace Sinic { -namespace Regs { - -static const int VirtualShift = 8; -static const int VirtualMask = 0xff; - -// Registers -__SINIC_REG32(Config, 0x00); // 32: configuration register -__SINIC_REG32(Command, 0x04); // 32: command register -__SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status -__SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask -__SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy -__SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy -__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt -__SINIC_REG32(VirtualCount, 0x1c); // 32: number of virutal NICs -__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes -__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes -__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark -__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark -__SINIC_REG32(RxData, 0x30); // 64: receive data -__SINIC_REG32(RxDone, 0x38); // 64: receive done -__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait) -__SINIC_REG32(TxData, 0x48); // 64: transmit data -__SINIC_REG32(TxDone, 0x50); // 64: transmit done -__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait) -__SINIC_REG32(HwAddr, 0x60); // 64: mac address -__SINIC_REG32(Size, 0x68); // register addres space size - -// Config register bits -__SINIC_VAL32(Config_ZeroCopy, 12, 1); // enable zero copy -__SINIC_VAL32(Config_DelayCopy,11, 1); // enable delayed copy -__SINIC_VAL32(Config_RSS, 10, 1); // enable receive side scaling -__SINIC_VAL32(Config_RxThread, 9, 1); // enable receive threads -__SINIC_VAL32(Config_TxThread, 8, 1); // enable transmit thread -__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter -__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging -__SINIC_VAL32(Config_Vaddr, 5, 1); // enable virtual addressing -__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors -__SINIC_VAL32(Config_Poll, 3, 1); // enable polling -__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts -__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit -__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive - -// Command register bits -__SINIC_VAL32(Command_Intr, 1, 1); // software interrupt -__SINIC_VAL32(Command_Reset, 0, 1); // reset chip - -// Interrupt register bits -__SINIC_VAL32(Intr_Soft, 8, 1); // software interrupt -__SINIC_VAL32(Intr_TxLow, 7, 1); // tx fifo dropped below watermark -__SINIC_VAL32(Intr_TxFull, 6, 1); // tx fifo full -__SINIC_VAL32(Intr_TxDMA, 5, 1); // tx dma completed w/ interrupt -__SINIC_VAL32(Intr_TxPacket, 4, 1); // packet transmitted -__SINIC_VAL32(Intr_RxHigh, 3, 1); // rx fifo above high watermark -__SINIC_VAL32(Intr_RxEmpty, 2, 1); // rx fifo empty -__SINIC_VAL32(Intr_RxDMA, 1, 1); // rx dma completed w/ interrupt -__SINIC_VAL32(Intr_RxPacket, 0, 1); // packet received -__SINIC_REG32(Intr_All, 0x01ff); // all valid interrupts -__SINIC_REG32(Intr_NoDelay, 0x01cc); // interrupts that aren't coalesced -__SINIC_REG32(Intr_Res, ~0x01ff); // reserved interrupt bits - -// RX Data Description -__SINIC_VAL64(RxData_Vaddr, 60, 1); // Addr is virtual -__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 256k -__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB - -// TX Data Description -__SINIC_VAL64(TxData_More, 63, 1); // Packet not complete (will dma more) -__SINIC_VAL64(TxData_Checksum, 62, 1); // do checksum -__SINIC_VAL64(TxData_Vaddr, 60, 1); // Addr is virtual -__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 256k -__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB - -// RX Done/Busy Information -__SINIC_VAL64(RxDone_Packets, 32, 16); // number of packets in rx fifo -__SINIC_VAL64(RxDone_Busy, 31, 1); // receive dma busy copying -__SINIC_VAL64(RxDone_Complete, 30, 1); // valid data (packet complete) -__SINIC_VAL64(RxDone_More, 29, 1); // Packet has more data (dma again) -__SINIC_VAL64(RxDone_Empty, 28, 1); // rx fifo is empty -__SINIC_VAL64(RxDone_High, 27, 1); // rx fifo is above the watermark -__SINIC_VAL64(RxDone_NotHigh, 26, 1); // rxfifo never hit the high watermark -__SINIC_VAL64(RxDone_TcpError, 25, 1); // TCP packet error (bad checksum) -__SINIC_VAL64(RxDone_UdpError, 24, 1); // UDP packet error (bad checksum) -__SINIC_VAL64(RxDone_IpError, 23, 1); // IP packet error (bad checksum) -__SINIC_VAL64(RxDone_TcpPacket, 22, 1); // this is a TCP packet -__SINIC_VAL64(RxDone_UdpPacket, 21, 1); // this is a UDP packet -__SINIC_VAL64(RxDone_IpPacket, 20, 1); // this is an IP packet -__SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k - -// TX Done/Busy Information -__SINIC_VAL64(TxDone_Packets, 32, 16); // number of packets in tx fifo -__SINIC_VAL64(TxDone_Busy, 31, 1); // transmit dma busy copying -__SINIC_VAL64(TxDone_Complete, 30, 1); // valid data (packet complete) -__SINIC_VAL64(TxDone_Full, 29, 1); // tx fifo is full -__SINIC_VAL64(TxDone_Low, 28, 1); // tx fifo is below the watermark -__SINIC_VAL64(TxDone_Res0, 27, 1); // reserved -__SINIC_VAL64(TxDone_Res1, 26, 1); // reserved -__SINIC_VAL64(TxDone_Res2, 25, 1); // reserved -__SINIC_VAL64(TxDone_Res3, 24, 1); // reserved -__SINIC_VAL64(TxDone_Res4, 23, 1); // reserved -__SINIC_VAL64(TxDone_Res5, 22, 1); // reserved -__SINIC_VAL64(TxDone_Res6, 21, 1); // reserved -__SINIC_VAL64(TxDone_Res7, 20, 1); // reserved -__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k - -struct Info -{ - uint8_t size; - bool read; - bool write; - const char *name; -}; - -/* namespace Regs */ } - -inline const Regs::Info& -regInfo(Addr daddr) -{ - static Regs::Info invalid = { 0, false, false, "invalid" }; - static Regs::Info info [] = { - { 4, true, true, "Config" }, - { 4, false, true, "Command" }, - { 4, true, true, "IntrStatus" }, - { 4, true, true, "IntrMask" }, - { 4, true, false, "RxMaxCopy" }, - { 4, true, false, "TxMaxCopy" }, - { 4, true, false, "RxMaxIntr" }, - { 4, true, false, "VirtualCount" }, - { 4, true, false, "RxFifoSize" }, - { 4, true, false, "TxFifoSize" }, - { 4, true, false, "RxFifoMark" }, - { 4, true, false, "TxFifoMark" }, - { 8, true, true, "RxData" }, - invalid, - { 8, true, false, "RxDone" }, - invalid, - { 8, true, false, "RxWait" }, - invalid, - { 8, true, true, "TxData" }, - invalid, - { 8, true, false, "TxDone" }, - invalid, - { 8, true, false, "TxWait" }, - invalid, - { 8, true, false, "HwAddr" }, - invalid, - }; - - return info[daddr / 4]; -} - -inline bool -regValid(Addr daddr) -{ - if (daddr > Regs::Size) - return false; - - if (regInfo(daddr).size == 0) - return false; - - return true; -} - -/* namespace Sinic */ } - -#endif // __DEV_SINICREG_HH__ diff --git a/dev/tsunami.cc b/dev/tsunami.cc deleted file mode 100644 index 58fc7434e..000000000 --- a/dev/tsunami.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Implementation of Tsunami platform. - */ - -#include <deque> -#include <string> -#include <vector> - -#include "cpu/intr_control.hh" -#include "dev/simconsole.hh" -#include "dev/ide_ctrl.hh" -#include "dev/tsunami_cchip.hh" -#include "dev/tsunami_pchip.hh" -#include "dev/tsunami_io.hh" -#include "dev/tsunami.hh" -#include "dev/pciconfigall.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -//Should this be AlphaISA? -using namespace TheISA; - -Tsunami::Tsunami(const string &name, System *s, IntrControl *ic, - PciConfigAll *pci) - : Platform(name, ic, pci), system(s) -{ - // set the back pointer from the system to myself - system->platform = this; - - for (int i = 0; i < Tsunami::Max_CPUs; i++) - intr_sum_type[i] = 0; -} - -Tick -Tsunami::intrFrequency() -{ - return io->frequency(); -} - -void -Tsunami::postConsoleInt() -{ - io->postPIC(0x10); -} - -void -Tsunami::clearConsoleInt() -{ - io->clearPIC(0x10); -} - -void -Tsunami::postPciInt(int line) -{ - cchip->postDRIR(line); -} - -void -Tsunami::clearPciInt(int line) -{ - cchip->clearDRIR(line); -} - -Addr -Tsunami::pciToDma(Addr pciAddr) const -{ - return pchip->translatePciToDma(pciAddr); -} - -void -Tsunami::serialize(std::ostream &os) -{ - SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs); -} - -void -Tsunami::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami) - - SimObjectParam<System *> system; - SimObjectParam<IntrControl *> intrctrl; - SimObjectParam<PciConfigAll *> pciconfig; - -END_DECLARE_SIM_OBJECT_PARAMS(Tsunami) - -BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami) - - INIT_PARAM(system, "system"), - INIT_PARAM(intrctrl, "interrupt controller"), - INIT_PARAM(pciconfig, "PCI configuration") - -END_INIT_SIM_OBJECT_PARAMS(Tsunami) - -CREATE_SIM_OBJECT(Tsunami) -{ - return new Tsunami(getInstanceName(), system, intrctrl, pciconfig); -} - -REGISTER_SIM_OBJECT("Tsunami", Tsunami) diff --git a/dev/tsunami.hh b/dev/tsunami.hh deleted file mode 100644 index 7fd91d5b2..000000000 --- a/dev/tsunami.hh +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * Declaration of top level class for the Tsunami chipset. This class just - * retains pointers to all its children so the children can communicate. - */ - -#ifndef __DEV_TSUNAMI_HH__ -#define __DEV_TSUNAMI_HH__ - -#include "dev/platform.hh" - -class IdeController; -class TlaserClock; -class NSGigE; -class TsunamiCChip; -class TsunamiPChip; -class TsunamiIO; -class PciConfigAll; -class System; - -/** - * Top level class for Tsunami Chipset emulation. - * This structure just contains pointers to all the - * children so the children can commnicate to do the - * read work - */ - -class Tsunami : public Platform -{ - public: - /** Max number of CPUs in a Tsunami */ - static const int Max_CPUs = 64; - - /** Pointer to the system */ - System *system; - - /** Pointer to the TsunamiIO device which has the RTC */ - TsunamiIO *io; - - /** Pointer to the Tsunami CChip. - * The chip contains some configuration information and - * all the interrupt mask and status registers - */ - TsunamiCChip *cchip; - - /** Pointer to the Tsunami PChip. - * The pchip is the interface to the PCI bus, in our case - * it does not have to do much. - */ - TsunamiPChip *pchip; - - int intr_sum_type[Tsunami::Max_CPUs]; - int ipi_pending[Tsunami::Max_CPUs]; - - public: - /** - * Constructor for the Tsunami Class. - * @param name name of the object - * @param intrctrl pointer to the interrupt controller - */ - Tsunami(const std::string &name, System *s, IntrControl *intctrl, - PciConfigAll *pci); - - /** - * 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(); - - /** - * Cause the chipset to post a cpi interrupt to the CPU. - */ - virtual void postPciInt(int line); - - /** - * Clear a posted PCI->CPU interrupt - */ - virtual void clearPciInt(int line); - - virtual Addr pciToDma(Addr pciAddr) const; - - /** - * 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 §ion); -}; - -#endif // __DEV_TSUNAMI_HH__ diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc deleted file mode 100644 index 2649fe27a..000000000 --- a/dev/tsunami_cchip.cc +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Emulation of the Tsunami CChip CSRs - */ - -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "dev/tsunami_cchip.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/memory_control.hh" -#include "cpu/exec_context.hh" -#include "cpu/intr_control.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -//Should this be AlphaISA? -using namespace TheISA; - -TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, - Bus* pio_bus, Tick pio_latency) - : PioDevice(name, t), addr(a), tsunami(t) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiCChip::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } - - drir = 0; - ipint = 0; - itint = 0; - - for (int x = 0; x < Tsunami::Max_CPUs; x++) - { - dim[x] = 0; - dir[x] = 0; - } - - //Put back pointer in tsunami - tsunami->cchip = this; -} - -Fault -TsunamiCChip::read(MemReqPtr &req, uint8_t *data) -{ - DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); - - Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - ExecContext *xc = req->xc; - - switch (req->size) { - - case sizeof(uint64_t): - if (daddr & TSDEV_CC_BDIMS) - { - *(uint64_t*)data = dim[(daddr >> 4) & 0x3F]; - return NoFault; - } - - if (daddr & TSDEV_CC_BDIRS) - { - *(uint64_t*)data = dir[(daddr >> 4) & 0x3F]; - return NoFault; - } - - switch(regnum) { - case TSDEV_CC_CSR: - *(uint64_t*)data = 0x0; - return NoFault; - case TSDEV_CC_MTR: - panic("TSDEV_CC_MTR not implemeted\n"); - return NoFault; - case TSDEV_CC_MISC: - *(uint64_t*)data = (ipint << 8) & 0xF | - (itint << 4) & 0xF | - (xc->readCpuId() & 0x3); - return NoFault; - case TSDEV_CC_AAR0: - case TSDEV_CC_AAR1: - case TSDEV_CC_AAR2: - case TSDEV_CC_AAR3: - *(uint64_t*)data = 0; - return NoFault; - case TSDEV_CC_DIM0: - *(uint64_t*)data = dim[0]; - return NoFault; - case TSDEV_CC_DIM1: - *(uint64_t*)data = dim[1]; - return NoFault; - case TSDEV_CC_DIM2: - *(uint64_t*)data = dim[2]; - return NoFault; - case TSDEV_CC_DIM3: - *(uint64_t*)data = dim[3]; - return NoFault; - case TSDEV_CC_DIR0: - *(uint64_t*)data = dir[0]; - return NoFault; - case TSDEV_CC_DIR1: - *(uint64_t*)data = dir[1]; - return NoFault; - case TSDEV_CC_DIR2: - *(uint64_t*)data = dir[2]; - return NoFault; - case TSDEV_CC_DIR3: - *(uint64_t*)data = dir[3]; - return NoFault; - case TSDEV_CC_DRIR: - *(uint64_t*)data = drir; - return NoFault; - case TSDEV_CC_PRBEN: - panic("TSDEV_CC_PRBEN not implemented\n"); - return NoFault; - case TSDEV_CC_IIC0: - case TSDEV_CC_IIC1: - case TSDEV_CC_IIC2: - case TSDEV_CC_IIC3: - panic("TSDEV_CC_IICx not implemented\n"); - return NoFault; - case TSDEV_CC_MPR0: - case TSDEV_CC_MPR1: - case TSDEV_CC_MPR2: - case TSDEV_CC_MPR3: - panic("TSDEV_CC_MPRx not implemented\n"); - return NoFault; - case TSDEV_CC_IPIR: - *(uint64_t*)data = ipint; - return NoFault; - case TSDEV_CC_ITIR: - *(uint64_t*)data = itint; - return NoFault; - default: - panic("default in cchip read reached, accessing 0x%x\n"); - } // uint64_t - - break; - case sizeof(uint32_t): - if (regnum == TSDEV_CC_DRIR) { - warn("accessing DRIR with 32 bit read, " - "hopefully your just reading this for timing"); - *(uint32_t*)data = drir; - } else - panic("invalid access size(?) for tsunami register!\n"); - return NoFault; - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n"); - } - DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size); - - return NoFault; -} - -Fault -TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) -{ - DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n", - req->vaddr, *(uint64_t*)data, req->size); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - - bool supportedWrite = false; - - switch (req->size) { - - case sizeof(uint64_t): - if (daddr & TSDEV_CC_BDIMS) - { - int number = (daddr >> 4) & 0x3F; - - uint64_t bitvector; - uint64_t olddim; - uint64_t olddir; - - olddim = dim[number]; - olddir = dir[number]; - dim[number] = *(uint64_t*)data; - dir[number] = dim[number] & drir; - for(int x = 0; x < Tsunami::Max_CPUs; x++) - { - bitvector = ULL(1) << x; - // Figure out which bits have changed - if ((dim[number] & bitvector) != (olddim & bitvector)) - { - // The bit is now set and it wasn't before (set) - if((dim[number] & bitvector) && (dir[number] & bitvector)) - { - tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in posting dir" - " interrupt to cpu %d\n", number); - } - else if ((olddir & bitvector) && - !(dir[number] & bitvector)) - { - // The bit was set and now its now clear and - // we were interrupting on that bit before - tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in clear" - " dir interrupt to cpu %d\n", number); - - } - - - } - } - return NoFault; - } - - switch(regnum) { - case TSDEV_CC_CSR: - panic("TSDEV_CC_CSR write\n"); - return NoFault; - case TSDEV_CC_MTR: - panic("TSDEV_CC_MTR write not implemented\n"); - return NoFault; - case TSDEV_CC_MISC: - uint64_t ipreq; - ipreq = (*(uint64_t*)data >> 12) & 0xF; - //If it is bit 12-15, this is an IPI post - if (ipreq) { - reqIPI(ipreq); - supportedWrite = true; - } - - //If it is bit 8-11, this is an IPI clear - uint64_t ipintr; - ipintr = (*(uint64_t*)data >> 8) & 0xF; - if (ipintr) { - clearIPI(ipintr); - supportedWrite = true; - } - - //If it is the 4-7th bit, clear the RTC interrupt - uint64_t itintr; - itintr = (*(uint64_t*)data >> 4) & 0xF; - if (itintr) { - clearITI(itintr); - supportedWrite = true; - } - - // ignore NXMs - if (*(uint64_t*)data & 0x10000000) - supportedWrite = true; - - if(!supportedWrite) - panic("TSDEV_CC_MISC write not implemented\n"); - - return NoFault; - case TSDEV_CC_AAR0: - case TSDEV_CC_AAR1: - case TSDEV_CC_AAR2: - case TSDEV_CC_AAR3: - panic("TSDEV_CC_AARx write not implemeted\n"); - return NoFault; - case TSDEV_CC_DIM0: - case TSDEV_CC_DIM1: - case TSDEV_CC_DIM2: - case TSDEV_CC_DIM3: - int number; - if(regnum == TSDEV_CC_DIM0) - number = 0; - else if(regnum == TSDEV_CC_DIM1) - number = 1; - else if(regnum == TSDEV_CC_DIM2) - number = 2; - else - number = 3; - - uint64_t bitvector; - uint64_t olddim; - uint64_t olddir; - - olddim = dim[number]; - olddir = dir[number]; - dim[number] = *(uint64_t*)data; - dir[number] = dim[number] & drir; - for(int x = 0; x < 64; x++) - { - bitvector = ULL(1) << x; - // Figure out which bits have changed - if ((dim[number] & bitvector) != (olddim & bitvector)) - { - // The bit is now set and it wasn't before (set) - if((dim[number] & bitvector) && (dir[number] & bitvector)) - { - tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); - } - else if ((olddir & bitvector) && - !(dir[number] & bitvector)) - { - // The bit was set and now its now clear and - // we were interrupting on that bit before - tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x); - DPRINTF(Tsunami, "dim write resulting in clear" - " dir interrupt to cpu %d\n", - x); - - } - - - } - } - return NoFault; - case TSDEV_CC_DIR0: - case TSDEV_CC_DIR1: - case TSDEV_CC_DIR2: - case TSDEV_CC_DIR3: - panic("TSDEV_CC_DIR write not implemented\n"); - case TSDEV_CC_DRIR: - panic("TSDEV_CC_DRIR write not implemented\n"); - case TSDEV_CC_PRBEN: - panic("TSDEV_CC_PRBEN write not implemented\n"); - case TSDEV_CC_IIC0: - case TSDEV_CC_IIC1: - case TSDEV_CC_IIC2: - case TSDEV_CC_IIC3: - panic("TSDEV_CC_IICx write not implemented\n"); - case TSDEV_CC_MPR0: - case TSDEV_CC_MPR1: - case TSDEV_CC_MPR2: - case TSDEV_CC_MPR3: - panic("TSDEV_CC_MPRx write not implemented\n"); - case TSDEV_CC_IPIR: - clearIPI(*(uint64_t*)data); - return NoFault; - case TSDEV_CC_ITIR: - clearITI(*(uint64_t*)data); - return NoFault; - case TSDEV_CC_IPIQ: - reqIPI(*(uint64_t*)data); - return NoFault; - default: - panic("default in cchip read reached, accessing 0x%x\n"); - } - - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n"); - } - - DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; -} - -void -TsunamiCChip::clearIPI(uint64_t ipintr) -{ - int numcpus = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(numcpus <= Tsunami::Max_CPUs); - - if (ipintr) { - for (int cpunum=0; cpunum < numcpus; cpunum++) { - // Check each cpu bit - uint64_t cpumask = ULL(1) << cpunum; - if (ipintr & cpumask) { - // Check if there is a pending ipi - if (ipint & cpumask) { - ipint &= ~cpumask; - tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0); - DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum); - } - else - warn("clear IPI for CPU=%d, but NO IPI\n", cpunum); - } - } - } - else - panic("Big IPI Clear, but not processors indicated\n"); -} - -void -TsunamiCChip::clearITI(uint64_t itintr) -{ - int numcpus = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(numcpus <= Tsunami::Max_CPUs); - - if (itintr) { - for (int i=0; i < numcpus; i++) { - uint64_t cpumask = ULL(1) << i; - if (itintr & cpumask & itint) { - tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0); - itint &= ~cpumask; - DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i); - } - } - } - else - panic("Big ITI Clear, but not processors indicated\n"); -} - -void -TsunamiCChip::reqIPI(uint64_t ipreq) -{ - int numcpus = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(numcpus <= Tsunami::Max_CPUs); - - if (ipreq) { - for (int cpunum=0; cpunum < numcpus; cpunum++) { - // Check each cpu bit - uint64_t cpumask = ULL(1) << cpunum; - if (ipreq & cpumask) { - // Check if there is already an ipi (bits 8:11) - if (!(ipint & cpumask)) { - ipint |= cpumask; - tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0); - DPRINTF(IPI, "send IPI cpu=%d\n", cpunum); - } - else - warn("post IPI for CPU=%d, but IPI already\n", cpunum); - } - } - } - else - panic("Big IPI Request, but not processors indicated\n"); -} - - -void -TsunamiCChip::postRTC() -{ - int size = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(size <= Tsunami::Max_CPUs); - - for (int i = 0; i < size; i++) { - uint64_t cpumask = ULL(1) << i; - if (!(cpumask & itint)) { - itint |= cpumask; - tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0); - DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i); - } - } - -} - -void -TsunamiCChip::postDRIR(uint32_t interrupt) -{ - uint64_t bitvector = ULL(1) << interrupt; - uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(size <= Tsunami::Max_CPUs); - drir |= bitvector; - - for(int i=0; i < size; i++) { - dir[i] = dim[i] & drir; - if (dim[i] & bitvector) { - tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt); - DPRINTF(Tsunami, "posting dir interrupt to cpu %d," - "interrupt %d\n",i, interrupt); - } - } -} - -void -TsunamiCChip::clearDRIR(uint32_t interrupt) -{ - uint64_t bitvector = ULL(1) << interrupt; - uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); - assert(size <= Tsunami::Max_CPUs); - - if (drir & bitvector) - { - drir &= ~bitvector; - for(int i=0; i < size; i++) { - if (dir[i] & bitvector) { - tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt); - DPRINTF(Tsunami, "clearing dir interrupt to cpu %d," - "interrupt %d\n",i, interrupt); - - } - dir[i] = dim[i] & drir; - } - } - else - DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt); -} - -Tick -TsunamiCChip::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - - -void -TsunamiCChip::serialize(std::ostream &os) -{ - SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); - SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); - SERIALIZE_SCALAR(ipint); - SERIALIZE_SCALAR(itint); - SERIALIZE_SCALAR(drir); -} - -void -TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); - UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); - UNSERIALIZE_SCALAR(ipint); - UNSERIALIZE_SCALAR(itint); - UNSERIALIZE_SCALAR(drir); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) - - SimObjectParam<Tsunami *> tsunami; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - -END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) - -BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) - - INIT_PARAM(tsunami, "Tsunami"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - 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, hier, - pio_bus, pio_latency); -} - -REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh deleted file mode 100644 index d88ad375f..000000000 --- a/dev/tsunami_cchip.hh +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Emulation of the Tsunami CChip CSRs - */ - -#ifndef __TSUNAMI_CCHIP_HH__ -#define __TSUNAMI_CCHIP_HH__ - -#include "dev/tsunami.hh" -#include "base/range.hh" -#include "dev/io_device.hh" - -class MemoryController; - -/** - * Tsunami CChip CSR Emulation. This device includes all the interrupt - * handling code for the chipset. - */ -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 = 0xfffffff; - - protected: - /** - * pointer to the tsunami object. - * This is our access to all the other tsunami - * devices. - */ - Tsunami *tsunami; - - /** - * The dims are device interrupt mask registers. - * One exists for each CPU, the DRIR X DIM = DIR - */ - uint64_t dim[Tsunami::Max_CPUs]; - - /** - * The dirs are device interrupt registers. - * One exists for each CPU, the DRIR X DIM = DIR - */ - uint64_t dir[Tsunami::Max_CPUs]; - - /** - * This register contains bits for each PCI interrupt - * that can occur. - */ - uint64_t drir; - - /** Indicator of which CPUs have an IPI interrupt */ - uint64_t ipint; - - /** Indicator of which CPUs have an RTC interrupt */ - uint64_t itint; - - 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, HierParams *hier, Bus *pio_bus, - Tick pio_latency); - - /** - * 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); - - /** - * post an ipi interrupt to the CPU. - * @param ipintr the cpu number to clear(bitvector) - */ - void clearIPI(uint64_t ipintr); - - /** - * clear a timer interrupt previously posted to the CPU. - * @param itintr the cpu number to clear(bitvector) - */ - void clearITI(uint64_t itintr); - - /** - * request an interrupt be posted to the CPU. - * @param ipreq the cpu number to interrupt(bitvector) - */ - void reqIPI(uint64_t ipreq); - - - /** - * 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 §ion); - - /** - * 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 deleted file mode 100644 index e66d6653b..000000000 --- a/dev/tsunami_io.cc +++ /dev/null @@ -1,719 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Tsunami I/O including PIC, PIT, RTC, DMA - */ - -#include <sys/time.h> - -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.hh" -#include "dev/tsunami_io.hh" -#include "dev/tsunami.hh" -#include "dev/pitreg.h" -#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 "dev/rtcreg.h" -#include "mem/functional/memory_control.hh" - -using namespace std; -//Should this be AlphaISA? -using namespace TheISA; - -TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i) - : _name(name), event(t, i), addr(0) -{ - memset(clock_data, 0, sizeof(clock_data)); - stat_regA = RTCA_32768HZ | RTCA_1024HZ; - stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; -} - -void -TsunamiIO::RTC::set_time(time_t t) -{ - struct tm tm; - gmtime_r(&t, &tm); - - sec = tm.tm_sec; - min = tm.tm_min; - hour = tm.tm_hour; - wday = tm.tm_wday + 1; - mday = tm.tm_mday; - mon = tm.tm_mon + 1; - year = tm.tm_year; - - DPRINTFN("Real-time clock set to %s", asctime(&tm)); -} - -void -TsunamiIO::RTC::writeAddr(const uint8_t *data) -{ - if (*data <= RTC_STAT_REGD) - addr = *data; - else - panic("RTC addresses over 0xD are not implemented.\n"); -} - -void -TsunamiIO::RTC::writeData(const uint8_t *data) -{ - if (addr < RTC_STAT_REGA) - clock_data[addr] = *data; - else { - switch (addr) { - case RTC_STAT_REGA: - if (*data != (RTCA_32768HZ | RTCA_1024HZ)) - panic("Unimplemented RTC register A value write!\n"); - stat_regA = *data; - break; - case RTC_STAT_REGB: - if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) - panic("Write to RTC reg B bits that are not implemented!\n"); - - if (*data & RTCB_PRDC_IE) { - if (!event.scheduled()) - event.scheduleIntr(); - } else { - if (event.scheduled()) - event.deschedule(); - } - stat_regB = *data; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - panic("RTC status registers C and D are not implemented.\n"); - break; - } - } -} - -void -TsunamiIO::RTC::readData(uint8_t *data) -{ - if (addr < RTC_STAT_REGA) - *data = clock_data[addr]; - else { - switch (addr) { - case RTC_STAT_REGA: - // toggle UIP bit for linux - stat_regA ^= RTCA_UIP; - *data = stat_regA; - break; - case RTC_STAT_REGB: - *data = stat_regB; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - *data = 0x00; - break; - } - } -} - -void -TsunamiIO::RTC::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".addr", addr); - arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); - paramOut(os, base + ".stat_regA", stat_regA); - paramOut(os, base + ".stat_regB", stat_regB); -} - -void -TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".addr", addr); - arrayParamIn(cp, section, base + ".clock_data", clock_data, - sizeof(clock_data)); - paramIn(cp, section, base + ".stat_regA", stat_regA); - paramIn(cp, section, base + ".stat_regB", stat_regB); - - // We're not unserializing the event here, but we need to - // rescehedule the event since curTick was moved forward by the - // checkpoint - event.reschedule(curTick + event.interval); -} - -TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) - : Event(&mainEventQueue), tsunami(t), interval(i) -{ - DPRINTF(MC146818, "RTC Event Initilizing\n"); - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::scheduleIntr() -{ - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::process() -{ - DPRINTF(MC146818, "RTC Timer Interrupt\n"); - schedule(curTick + interval); - //Actually interrupt the processor here - tsunami->cchip->postRTC(); -} - -const char * -TsunamiIO::RTC::RTCEvent::description() -{ - return "tsunami RTC interrupt"; -} - -TsunamiIO::PITimer::PITimer(const string &name) - : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), - counter2(name + ".counter2") -{ - counter[0] = &counter0; - counter[1] = &counter0; - counter[2] = &counter0; -} - -void -TsunamiIO::PITimer::writeControl(const uint8_t *data) -{ - int rw; - int sel; - - sel = GET_CTRL_SEL(*data); - - if (sel == PIT_READ_BACK) - panic("PITimer Read-Back Command is not implemented.\n"); - - rw = GET_CTRL_RW(*data); - - if (rw == PIT_RW_LATCH_COMMAND) - counter[sel]->latchCount(); - else { - counter[sel]->setRW(rw); - counter[sel]->setMode(GET_CTRL_MODE(*data)); - counter[sel]->setBCD(GET_CTRL_BCD(*data)); - } -} - -void -TsunamiIO::PITimer::serialize(const string &base, ostream &os) -{ - // serialize the counters - counter0.serialize(base + ".counter0", os); - counter1.serialize(base + ".counter1", os); - counter2.serialize(base + ".counter2", os); -} - -void -TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - // unserialze the counters - counter0.unserialize(base + ".counter0", cp, section); - counter1.unserialize(base + ".counter1", cp, section); - counter2.unserialize(base + ".counter2", cp, section); -} - -TsunamiIO::PITimer::Counter::Counter(const string &name) - : _name(name), event(this), count(0), latched_count(0), period(0), - mode(0), output_high(false), latch_on(false), read_byte(LSB), - write_byte(LSB) -{ - -} - -void -TsunamiIO::PITimer::Counter::latchCount() -{ - // behave like a real latch - if(!latch_on) { - latch_on = true; - read_byte = LSB; - latched_count = count; - } -} - -void -TsunamiIO::PITimer::Counter::read(uint8_t *data) -{ - if (latch_on) { - switch (read_byte) { - case LSB: - read_byte = MSB; - *data = (uint8_t)latched_count; - break; - case MSB: - read_byte = LSB; - latch_on = false; - *data = latched_count >> 8; - break; - } - } else { - switch (read_byte) { - case LSB: - read_byte = MSB; - *data = (uint8_t)count; - break; - case MSB: - read_byte = LSB; - *data = count >> 8; - break; - } - } -} - -void -TsunamiIO::PITimer::Counter::write(const uint8_t *data) -{ - switch (write_byte) { - case LSB: - count = (count & 0xFF00) | *data; - - if (event.scheduled()) - event.deschedule(); - output_high = false; - write_byte = MSB; - break; - - case MSB: - count = (count & 0x00FF) | (*data << 8); - period = count; - - if (period > 0) { - DPRINTF(Tsunami, "Timer set to curTick + %d\n", - count * event.interval); - event.schedule(curTick + count * event.interval); - } - write_byte = LSB; - break; - } -} - -void -TsunamiIO::PITimer::Counter::setRW(int rw_val) -{ - if (rw_val != PIT_RW_16BIT) - panic("Only LSB/MSB read/write is implemented.\n"); -} - -void -TsunamiIO::PITimer::Counter::setMode(int mode_val) -{ - if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && - mode_val != PIT_MODE_SQWAVE) - panic("PIT mode %#x is not implemented: \n", mode_val); - - mode = mode_val; -} - -void -TsunamiIO::PITimer::Counter::setBCD(int bcd_val) -{ - if (bcd_val != PIT_BCD_FALSE) - panic("PITimer does not implement BCD counts.\n"); -} - -bool -TsunamiIO::PITimer::Counter::outputHigh() -{ - return output_high; -} - -void -TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".count", count); - paramOut(os, base + ".latched_count", latched_count); - paramOut(os, base + ".period", period); - paramOut(os, base + ".mode", mode); - paramOut(os, base + ".output_high", output_high); - paramOut(os, base + ".latch_on", latch_on); - paramOut(os, base + ".read_byte", read_byte); - paramOut(os, base + ".write_byte", write_byte); - - Tick event_tick = 0; - if (event.scheduled()) - event_tick = event.when(); - paramOut(os, base + ".event_tick", event_tick); -} - -void -TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".count", count); - paramIn(cp, section, base + ".latched_count", latched_count); - paramIn(cp, section, base + ".period", period); - paramIn(cp, section, base + ".mode", mode); - paramIn(cp, section, base + ".output_high", output_high); - paramIn(cp, section, base + ".latch_on", latch_on); - paramIn(cp, section, base + ".read_byte", read_byte); - paramIn(cp, section, base + ".write_byte", write_byte); - - Tick event_tick; - paramIn(cp, section, base + ".event_tick", event_tick); - if (event_tick) - event.schedule(event_tick); -} - -TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) - : Event(&mainEventQueue) -{ - interval = (Tick)(Clock::Float::s / 1193180.0); - counter = c_ptr; -} - -void -TsunamiIO::PITimer::Counter::CounterEvent::process() -{ - DPRINTF(Tsunami, "Timer Interrupt\n"); - switch (counter->mode) { - case PIT_MODE_INTTC: - counter->output_high = true; - case PIT_MODE_RATEGEN: - case PIT_MODE_SQWAVE: - break; - default: - panic("Unimplemented PITimer mode.\n"); - } -} - -const char * -TsunamiIO::PITimer::Counter::CounterEvent::description() -{ - return "tsunami 8254 Interval timer"; -} - -TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, - Addr a, MemoryController *mmu, HierParams *hier, - Bus *pio_bus, Tick pio_latency, Tick ci) - : PioDevice(name, t), addr(a), clockInterval(ci), tsunami(t), - pitimer(name + "pitimer"), rtc(name + ".rtc", t, ci) -{ - mmu->add_child(this, RangeSize(addr, size)); - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiIO::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } - - // set the back pointer from tsunami to myself - tsunami->io = this; - - timerData = 0; - rtc.set_time(init_time == 0 ? time(NULL) : init_time); - picr = 0; - picInterrupting = false; -} - -Tick -TsunamiIO::frequency() const -{ - return Clock::Frequency / clockInterval; -} - -Fault -TsunamiIO::read(MemReqPtr &req, uint8_t *data) -{ - DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", - req->vaddr, req->size, req->vaddr & 0xfff); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - - switch(req->size) { - case sizeof(uint8_t): - switch(daddr) { - // PIC1 mask read - case TSDEV_PIC1_MASK: - *(uint8_t*)data = ~mask1; - return NoFault; - case TSDEV_PIC2_MASK: - *(uint8_t*)data = ~mask2; - return NoFault; - case TSDEV_PIC1_ISR: - // !!! If this is modified 64bit case needs to be too - // Pal code has to do a 64 bit physical read because there is - // no load physical byte instruction - *(uint8_t*)data = picr; - return NoFault; - case TSDEV_PIC2_ISR: - // PIC2 not implemnted... just return 0 - *(uint8_t*)data = 0x00; - return NoFault; - case TSDEV_TMR0_DATA: - pitimer.counter0.read(data); - return NoFault; - case TSDEV_TMR1_DATA: - pitimer.counter1.read(data); - return NoFault; - case TSDEV_TMR2_DATA: - pitimer.counter2.read(data); - return NoFault; - case TSDEV_RTC_DATA: - rtc.readData(data); - return NoFault; - case TSDEV_CTRL_PORTB: - if (pitimer.counter2.outputHigh()) - *data = PORTB_SPKR_HIGH; - else - *data = 0x00; - return NoFault; - default: - panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); - } - case sizeof(uint16_t): - case sizeof(uint32_t): - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PIC1_ISR: - // !!! If this is modified 8bit case needs to be too - // Pal code has to do a 64 bit physical read because there is - // no load physical byte instruction - *(uint64_t*)data = (uint64_t)picr; - return NoFault; - default: - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); - } - - default: - panic("I/O Read - invalid size - va %#x size %d\n", - req->vaddr, req->size); - } - panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); - - return NoFault; -} - -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); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); - - switch(req->size) { - case sizeof(uint8_t): - switch(daddr) { - case TSDEV_PIC1_MASK: - mask1 = ~(*(uint8_t*)data); - if ((picr & mask1) && !picInterrupting) { - picInterrupting = true; - tsunami->cchip->postDRIR(55); - DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); - } - if ((!(picr & mask1)) && picInterrupting) { - picInterrupting = false; - tsunami->cchip->clearDRIR(55); - DPRINTF(Tsunami, "clearing pic interrupt\n"); - } - return NoFault; - case TSDEV_PIC2_MASK: - mask2 = *(uint8_t*)data; - //PIC2 Not implemented to interrupt - return NoFault; - case TSDEV_PIC1_ACK: - // clear the interrupt on the PIC - picr &= ~(1 << (*(uint8_t*)data & 0xF)); - if (!(picr & mask1)) - tsunami->cchip->clearDRIR(55); - return NoFault; - case TSDEV_DMA1_CMND: - return NoFault; - case TSDEV_DMA2_CMND: - return NoFault; - case TSDEV_DMA1_MMASK: - return NoFault; - case TSDEV_DMA2_MMASK: - return NoFault; - case TSDEV_PIC2_ACK: - return NoFault; - case TSDEV_DMA1_RESET: - return NoFault; - case TSDEV_DMA2_RESET: - return NoFault; - case TSDEV_DMA1_MODE: - mode1 = *(uint8_t*)data; - return NoFault; - case TSDEV_DMA2_MODE: - mode2 = *(uint8_t*)data; - return NoFault; - case TSDEV_DMA1_MASK: - case TSDEV_DMA2_MASK: - return NoFault; - case TSDEV_TMR0_DATA: - pitimer.counter0.write(data); - return NoFault; - case TSDEV_TMR1_DATA: - pitimer.counter1.write(data); - return NoFault; - case TSDEV_TMR2_DATA: - pitimer.counter2.write(data); - return NoFault; - case TSDEV_TMR_CTRL: - pitimer.writeControl(data); - return NoFault; - case TSDEV_RTC_ADDR: - rtc.writeAddr(data); - return NoFault; - case TSDEV_KBD: - return NoFault; - case TSDEV_RTC_DATA: - rtc.writeData(data); - return NoFault; - case TSDEV_CTRL_PORTB: - // System Control Port B not implemented - return NoFault; - default: - panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data); - } - case sizeof(uint16_t): - case sizeof(uint32_t): - case sizeof(uint64_t): - default: - panic("I/O Write - invalid size - va %#x size %d\n", - req->vaddr, req->size); - } - - - return NoFault; -} - -void -TsunamiIO::postPIC(uint8_t bitvector) -{ - //PIC2 Is not implemented, because nothing of interest there - picr |= bitvector; - if (picr & mask1) { - tsunami->cchip->postDRIR(55); - DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); - } -} - -void -TsunamiIO::clearPIC(uint8_t bitvector) -{ - //PIC2 Is not implemented, because nothing of interest there - picr &= ~bitvector; - if (!(picr & mask1)) { - tsunami->cchip->clearDRIR(55); - DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); - } -} - -Tick -TsunamiIO::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - -void -TsunamiIO::serialize(ostream &os) -{ - SERIALIZE_SCALAR(timerData); - SERIALIZE_SCALAR(mask1); - SERIALIZE_SCALAR(mask2); - SERIALIZE_SCALAR(mode1); - SERIALIZE_SCALAR(mode2); - SERIALIZE_SCALAR(picr); - SERIALIZE_SCALAR(picInterrupting); - - // Serialize the timers - pitimer.serialize("pitimer", os); - rtc.serialize("rtc", os); -} - -void -TsunamiIO::unserialize(Checkpoint *cp, const string §ion) -{ - UNSERIALIZE_SCALAR(timerData); - UNSERIALIZE_SCALAR(mask1); - UNSERIALIZE_SCALAR(mask2); - UNSERIALIZE_SCALAR(mode1); - UNSERIALIZE_SCALAR(mode2); - UNSERIALIZE_SCALAR(picr); - UNSERIALIZE_SCALAR(picInterrupting); - - // Unserialize the timers - pitimer.unserialize("pitimer", cp, section); - rtc.unserialize("rtc", cp, section); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) - - SimObjectParam<Tsunami *> tsunami; - Param<time_t> time; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - Param<Tick> frequency; - -END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) - -BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) - - INIT_PARAM(tsunami, "Tsunami"), - INIT_PARAM(time, "System time to use (0 for actual time"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM(pio_bus, "The IO Bus to attach to"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM(frequency, "clock interrupt frequency") - -END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) - -CREATE_SIM_OBJECT(TsunamiIO) -{ - return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier, - pio_bus, pio_latency, frequency); -} - -REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh deleted file mode 100644 index b024ecd14..000000000 --- a/dev/tsunami_io.hh +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Tsunami I/O Space mapping including RTC/timer interrupts - */ - -#ifndef __DEV_TSUNAMI_IO_HH__ -#define __DEV_TSUNAMI_IO_HH__ - -#include "dev/io_device.hh" -#include "base/range.hh" -#include "dev/tsunami.hh" -#include "sim/eventq.hh" - -class MemoryController; - -/** - * Tsunami I/O device is a catch all for all the south bridge stuff we care - * to implement. - */ -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; - - protected: - /** Real-Time Clock (MC146818) */ - class RTC - { - private: - /** Event for RTC periodic interrupt */ - struct RTCEvent : public Event - { - /** A pointer back to tsunami to create interrupt the processor. */ - Tsunami* tsunami; - Tick interval; - - RTCEvent(Tsunami* t, Tick i); - - /** Schedule the RTC periodic interrupt */ - void scheduleIntr(); - - /** Event process to occur at interrupt*/ - virtual void process(); - - /** Event description */ - virtual const char *description(); - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - /** RTC periodic interrupt event */ - RTCEvent event; - - /** Current RTC register address/index */ - int addr; - - /** Data for real-time clock function */ - union { - uint8_t clock_data[10]; - - struct { - uint8_t sec; - uint8_t sec_alrm; - uint8_t min; - uint8_t min_alrm; - uint8_t hour; - uint8_t hour_alrm; - uint8_t wday; - uint8_t mday; - uint8_t mon; - uint8_t year; - }; - }; - - /** RTC status register A */ - uint8_t stat_regA; - - /** RTC status register B */ - uint8_t stat_regB; - - public: - RTC(const std::string &name, Tsunami* t, Tick i); - - /** Set the initial RTC time/date */ - void set_time(time_t t); - - /** RTC address port: write address of RTC RAM data to access */ - void writeAddr(const uint8_t *data); - - /** RTC write data */ - void writeData(const uint8_t *data); - - /** RTC read data */ - void readData(uint8_t *data); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - - /** Programmable Interval Timer (Intel 8254) */ - class PITimer - { - /** Counter element for PIT */ - class Counter - { - /** Event for counter interrupt */ - class CounterEvent : public Event - { - private: - /** Pointer back to Counter */ - Counter* counter; - Tick interval; - - public: - CounterEvent(Counter*); - - /** Event process */ - virtual void process(); - - /** Event description */ - virtual const char *description(); - - friend class Counter; - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - CounterEvent event; - - /** Current count value */ - uint16_t count; - - /** Latched count */ - uint16_t latched_count; - - /** Interrupt period */ - uint16_t period; - - /** Current mode of operation */ - uint8_t mode; - - /** Output goes high when the counter reaches zero */ - bool output_high; - - /** State of the count latch */ - bool latch_on; - - /** Set of values for read_byte and write_byte */ - enum {LSB, MSB}; - - /** Determine which byte of a 16-bit count value to read/write */ - uint8_t read_byte, write_byte; - - public: - Counter(const std::string &name); - - /** Latch the current count (if one is not already latched) */ - void latchCount(); - - /** Set the read/write mode */ - void setRW(int rw_val); - - /** Set operational mode */ - void setMode(int mode_val); - - /** Set count encoding */ - void setBCD(int bcd_val); - - /** Read a count byte */ - void read(uint8_t *data); - - /** Write a count byte */ - void write(const uint8_t *data); - - /** Is the output high? */ - bool outputHigh(); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - /** PIT has three seperate counters */ - Counter *counter[3]; - - public: - /** Public way to access individual counters (avoid array accesses) */ - Counter counter0; - Counter counter1; - Counter counter2; - - PITimer(const std::string &name); - - /** Write control word */ - void writeControl(const uint8_t* data); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - - /** 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; - - /** Raw PIC interrupt register before masking */ - uint8_t picr; //Raw PIC interrput register - - /** Is the pic interrupting right now or not. */ - bool picInterrupting; - - Tick clockInterval; - - /** A pointer to the Tsunami device which be belong to */ - Tsunami *tsunami; - - /** Intel 8253 Periodic Interval Timer */ - PITimer pitimer; - - RTC 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. - */ - uint16_t timerData; - - public: - /** - * Return the freqency of the RTC - * @return interrupt rate of the RTC - */ - Tick frequency() const; - - /** - * 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, HierParams *hier, Bus *pio_bus, - Tick pio_latency, Tick ci); - - /** - * 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 §ion); - - Tick cacheAccess(MemReqPtr &req); -}; - -#endif // __DEV_TSUNAMI_IO_HH__ diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc deleted file mode 100644 index 46efc3dfe..000000000 --- a/dev/tsunami_pchip.cc +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Tsunami PChip (pci) - */ - -#include <deque> -#include <string> -#include <vector> - -#include "base/trace.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/memory_control.hh" -#include "mem/functional/physical.hh" -#include "sim/builder.hh" -#include "sim/system.hh" - -using namespace std; -//Should this be AlphaISA? -using namespace TheISA; - -TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, - MemoryController *mmu, HierParams *hier, - Bus *pio_bus, Tick pio_latency) - : PioDevice(name, t), addr(a), tsunami(t) -{ - mmu->add_child(this, RangeSize(addr, size)); - - for (int i = 0; i < 4; i++) { - wsba[i] = 0; - wsm[i] = 0; - tba[i] = 0; - } - - if (pio_bus) { - pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, - &TsunamiPChip::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * pio_bus->clockRate; - } - - - // initialize pchip control register - pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); - - //Set back pointer in tsunami - tsunami->pchip = this; -} - -Fault -TsunamiPChip::read(MemReqPtr &req, uint8_t *data) -{ - DPRINTF(Tsunami, "read va=%#x size=%d\n", - req->vaddr, req->size); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - - switch (req->size) { - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PC_WSBA0: - *(uint64_t*)data = wsba[0]; - return NoFault; - case TSDEV_PC_WSBA1: - *(uint64_t*)data = wsba[1]; - return NoFault; - case TSDEV_PC_WSBA2: - *(uint64_t*)data = wsba[2]; - return NoFault; - case TSDEV_PC_WSBA3: - *(uint64_t*)data = wsba[3]; - return NoFault; - case TSDEV_PC_WSM0: - *(uint64_t*)data = wsm[0]; - return NoFault; - case TSDEV_PC_WSM1: - *(uint64_t*)data = wsm[1]; - return NoFault; - case TSDEV_PC_WSM2: - *(uint64_t*)data = wsm[2]; - return NoFault; - case TSDEV_PC_WSM3: - *(uint64_t*)data = wsm[3]; - return NoFault; - case TSDEV_PC_TBA0: - *(uint64_t*)data = tba[0]; - return NoFault; - case TSDEV_PC_TBA1: - *(uint64_t*)data = tba[1]; - return NoFault; - case TSDEV_PC_TBA2: - *(uint64_t*)data = tba[2]; - return NoFault; - case TSDEV_PC_TBA3: - *(uint64_t*)data = tba[3]; - return NoFault; - case TSDEV_PC_PCTL: - *(uint64_t*)data = pctl; - return NoFault; - case TSDEV_PC_PLAT: - panic("PC_PLAT not implemented\n"); - case TSDEV_PC_RES: - panic("PC_RES not implemented\n"); - case TSDEV_PC_PERROR: - *(uint64_t*)data = 0x00; - return NoFault; - case TSDEV_PC_PERRMASK: - *(uint64_t*)data = 0x00; - return NoFault; - case TSDEV_PC_PERRSET: - panic("PC_PERRSET not implemented\n"); - case TSDEV_PC_TLBIV: - panic("PC_TLBIV not implemented\n"); - case TSDEV_PC_TLBIA: - *(uint64_t*)data = 0x00; // shouldn't be readable, but linux - return NoFault; - case TSDEV_PC_PMONCTL: - panic("PC_PMONCTL not implemented\n"); - case TSDEV_PC_PMONCNT: - panic("PC_PMONCTN not implemented\n"); - default: - panic("Default in PChip Read reached reading 0x%x\n", daddr); - - } // uint64_t - - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n\n"); - } - DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; -} - -Fault -TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) -{ - DPRINTF(Tsunami, "write - va=%#x size=%d \n", - req->vaddr, req->size); - - Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; - - switch (req->size) { - - case sizeof(uint64_t): - switch(daddr) { - case TSDEV_PC_WSBA0: - wsba[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA1: - wsba[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA2: - wsba[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSBA3: - wsba[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM0: - wsm[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM1: - wsm[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM2: - wsm[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_WSM3: - wsm[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA0: - tba[0] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA1: - tba[1] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA2: - tba[2] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_TBA3: - tba[3] = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_PCTL: - pctl = *(uint64_t*)data; - return NoFault; - case TSDEV_PC_PLAT: - panic("PC_PLAT not implemented\n"); - case TSDEV_PC_RES: - panic("PC_RES not implemented\n"); - case TSDEV_PC_PERROR: - return NoFault; - case TSDEV_PC_PERRMASK: - panic("PC_PERRMASK not implemented\n"); - case TSDEV_PC_PERRSET: - panic("PC_PERRSET not implemented\n"); - case TSDEV_PC_TLBIV: - panic("PC_TLBIV not implemented\n"); - case TSDEV_PC_TLBIA: - return NoFault; // value ignored, supposted to invalidate SG TLB - case TSDEV_PC_PMONCTL: - panic("PC_PMONCTL not implemented\n"); - case TSDEV_PC_PMONCNT: - panic("PC_PMONCTN not implemented\n"); - default: - panic("Default in PChip Read reached reading 0x%x\n", daddr); - - } // uint64_t - - break; - case sizeof(uint32_t): - case sizeof(uint16_t): - case sizeof(uint8_t): - default: - panic("invalid access size(?) for tsunami register!\n\n"); - } - - DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - - return NoFault; -} - -#define DMA_ADDR_MASK ULL(0x3ffffffff) - -Addr -TsunamiPChip::translatePciToDma(Addr busAddr) -{ - // compare the address to the window base registers - uint64_t tbaMask = 0; - uint64_t baMask = 0; - - uint64_t windowMask = 0; - uint64_t windowBase = 0; - - uint64_t pteEntry = 0; - - 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] & (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 - /** @todo - This currently is faked by just doing a direct - read from memory, however, to be realistic, this - needs to actually do a bus transaction. The process - is explained in the tsunami documentation on page - 10-12 and basically munges the address to look up a - PTE from a table in memory and then uses that mapping - to create an address for the SG page - */ - - 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, - tsunami->system-> - physmem->dma_addr(pteAddr, sizeof(uint64_t)), - sizeof(uint64_t)); - - dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); - - } else { - baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); - tbaMask = ~baMask; - dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); - } - - return (dmaAddr & DMA_ADDR_MASK); - } - } - } - - // 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); -} - -void -TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(pctl); - UNSERIALIZE_ARRAY(wsba, 4); - UNSERIALIZE_ARRAY(wsm, 4); - UNSERIALIZE_ARRAY(tba, 4); -} - -Tick -TsunamiPChip::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) - - SimObjectParam<Tsunami *> tsunami; - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - -END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) - -BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) - - INIT_PARAM(tsunami, "Tsunami"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - 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, hier, - pio_bus, pio_latency); -} - -REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh deleted file mode 100644 index c1d95431b..000000000 --- a/dev/tsunami_pchip.hh +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Tsunami PCI interface CSRs - */ - -#ifndef __TSUNAMI_PCHIP_HH__ -#define __TSUNAMI_PCHIP_HH__ - -#include "dev/tsunami.hh" -#include "base/range.hh" -#include "dev/io_device.hh" - -class MemoryController; - -/** - * A very simple implementation of the Tsunami PCI interface chips. - */ -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, HierParams *hier, Bus *pio_bus, - Tick pio_latency); - - /** - * 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 §ion); - - /** - * 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/tsunamireg.h b/dev/tsunamireg.h deleted file mode 100644 index a10259900..000000000 --- a/dev/tsunamireg.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * List of Tsunami CSRs - */ - -#ifndef __TSUNAMIREG_H__ -#define __TSUNAMIREG_H__ - -#define ALPHA_K0SEG_BASE ULL(0xfffffc0000000000) - -// CChip Registers -#define TSDEV_CC_CSR 0x00 -#define TSDEV_CC_MTR 0x01 -#define TSDEV_CC_MISC 0x02 - -#define TSDEV_CC_AAR0 0x04 -#define TSDEV_CC_AAR1 0x05 -#define TSDEV_CC_AAR2 0x06 -#define TSDEV_CC_AAR3 0x07 -#define TSDEV_CC_DIM0 0x08 -#define TSDEV_CC_DIM1 0x09 -#define TSDEV_CC_DIR0 0x0A -#define TSDEV_CC_DIR1 0x0B -#define TSDEV_CC_DRIR 0x0C -#define TSDEV_CC_PRBEN 0x0D -#define TSDEV_CC_IIC0 0x0E -#define TSDEV_CC_IIC1 0x0F -#define TSDEV_CC_MPR0 0x10 -#define TSDEV_CC_MPR1 0x11 -#define TSDEV_CC_MPR2 0x12 -#define TSDEV_CC_MPR3 0x13 - -#define TSDEV_CC_DIM2 0x18 -#define TSDEV_CC_DIM3 0x19 -#define TSDEV_CC_DIR2 0x1A -#define TSDEV_CC_DIR3 0x1B -#define TSDEV_CC_IIC2 0x1C -#define TSDEV_CC_IIC3 0x1D - -// BigTsunami Registers -#define TSDEV_CC_BDIMS 0x1000000 -#define TSDEV_CC_BDIRS 0x2000000 -#define TSDEV_CC_IPIQ 0x20 //0xf01a000800 -#define TSDEV_CC_IPIR 0x21 //0xf01a000840 -#define TSDEV_CC_ITIR 0x22 //0xf01a000880 - - -// PChip Registers -#define TSDEV_PC_WSBA0 0x00 -#define TSDEV_PC_WSBA1 0x01 -#define TSDEV_PC_WSBA2 0x02 -#define TSDEV_PC_WSBA3 0x03 -#define TSDEV_PC_WSM0 0x04 -#define TSDEV_PC_WSM1 0x05 -#define TSDEV_PC_WSM2 0x06 -#define TSDEV_PC_WSM3 0x07 -#define TSDEV_PC_TBA0 0x08 -#define TSDEV_PC_TBA1 0x09 -#define TSDEV_PC_TBA2 0x0A -#define TSDEV_PC_TBA3 0x0B -#define TSDEV_PC_PCTL 0x0C -#define TSDEV_PC_PLAT 0x0D -#define TSDEV_PC_RES 0x0E -#define TSDEV_PC_PERROR 0x0F -#define TSDEV_PC_PERRMASK 0x10 -#define TSDEV_PC_PERRSET 0x11 -#define TSDEV_PC_TLBIV 0x12 -#define TSDEV_PC_TLBIA 0x13 -#define TSDEV_PC_PMONCTL 0x14 -#define TSDEV_PC_PMONCNT 0x15 - -#define TSDEV_PC_SPST 0x20 - - -// DChip Registers -#define TSDEV_DC_DSC 0x20 -#define TSDEV_DC_STR 0x21 -#define TSDEV_DC_DREV 0x22 -#define TSDEV_DC_DSC2 0x23 - -// I/O Ports -#define TSDEV_PIC1_MASK 0x21 -#define TSDEV_PIC2_MASK 0xA1 -#define TSDEV_PIC1_ISR 0x20 -#define TSDEV_PIC2_ISR 0xA0 -#define TSDEV_PIC1_ACK 0x20 -#define TSDEV_PIC2_ACK 0xA0 -#define TSDEV_DMA1_RESET 0x0D -#define TSDEV_DMA2_RESET 0xDA -#define TSDEV_DMA1_MODE 0x0B -#define TSDEV_DMA2_MODE 0xD6 -#define TSDEV_DMA1_MASK 0x0A -#define TSDEV_DMA2_MASK 0xD4 -#define TSDEV_CTRL_PORTB 0x61 -#define TSDEV_TMR0_DATA 0x40 -#define TSDEV_TMR1_DATA 0x41 -#define TSDEV_TMR2_DATA 0x42 -#define TSDEV_TMR_CTRL 0x43 -#define TSDEV_KBD 0x64 -#define TSDEV_DMA1_CMND 0x08 -#define TSDEV_DMA1_STAT TSDEV_DMA1_CMND -#define TSDEV_DMA2_CMND 0xD0 -#define TSDEV_DMA2_STAT TSDEV_DMA2_CMND -#define TSDEV_DMA1_MMASK 0x0F -#define TSDEV_DMA2_MMASK 0xDE - -/* Added for keyboard accesses */ -#define TSDEV_KBD 0x64 - -/* Added for ATA PCI DMA */ -#define ATA_PCI_DMA 0x00 -#define ATA_PCI_DMA2 0x02 -#define ATA_PCI_DMA3 0x16 -#define ATA_PCI_DMA4 0x17 -#define ATA_PCI_DMA5 0x1a -#define ATA_PCI_DMA6 0x11 -#define ATA_PCI_DMA7 0x14 - -#define TSDEV_RTC_ADDR 0x70 -#define TSDEV_RTC_DATA 0x71 - -#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_RDI 0x01 -#define UART_IER_THRI 0x02 -#define UART_IER_RLSI 0x04 - - -#define UART_LSR_TEMT 0x40 -#define UART_LSR_THRE 0x20 -#define UART_LSR_DR 0x01 - -#define UART_MCR_LOOP 0x10 - -// System Control PortB Status Bits -#define PORTB_SPKR_HIGH 0x20 - -#endif // __TSUNAMIREG_H__ diff --git a/dev/uart.cc b/dev/uart.cc deleted file mode 100644 index b2eeb8e9f..000000000 --- a/dev/uart.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Implements a 8250 UART - */ - -#include <string> -#include <vector> - -#include "base/inifile.hh" -#include "base/str.hh" // for to_number -#include "base/trace.hh" -#include "dev/simconsole.hh" -#include "dev/uart.hh" -#include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" - -using namespace std; - -Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, - Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p) - : PioDevice(name, p), addr(a), size(s), cons(c) -{ - mmu->add_child(this, RangeSize(addr, size)); - - - if (bus) { - pioInterface = newPioInterface(name, hier, bus, this, - &Uart::cacheAccess); - pioInterface->addAddrRange(RangeSize(addr, size)); - pioLatency = pio_latency * bus->clockRate; - } - - status = 0; - - // set back pointers - cons->uart = this; - platform->uart = this; -} - -Tick -Uart::cacheAccess(MemReqPtr &req) -{ - return curTick + pioLatency; -} - -DEFINE_SIM_OBJECT_CLASS_NAME("Uart", Uart) - diff --git a/dev/uart.hh b/dev/uart.hh deleted file mode 100644 index 78b1dc68e..000000000 --- a/dev/uart.hh +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Base class for UART - */ - -#ifndef __UART_HH__ -#define __UART_HH__ - -#include "base/range.hh" -#include "dev/io_device.hh" - -class SimConsole; -class MemoryController; -class Platform; - -const int RX_INT = 0x1; -const int TX_INT = 0x2; - - -class Uart : public PioDevice -{ - - protected: - int status; - Addr addr; - Addr size; - SimConsole *cons; - - public: - Uart(const std::string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *bus, Tick pio_latency, - Platform *p); - - virtual Fault read(MemReqPtr &req, uint8_t *data) = 0; - virtual Fault write(MemReqPtr &req, const uint8_t *data) = 0; - - - /** - * Inform the uart that there is data available. - */ - virtual void dataAvailable() = 0; - - - /** - * Return if we have an interrupt pending - * @return interrupt status - */ - bool intStatus() { return status ? true : false; } - - /** - * 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 // __UART_HH__ diff --git a/dev/uart8250.cc b/dev/uart8250.cc deleted file mode 100644 index 65bccee86..000000000 --- a/dev/uart8250.cc +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (c) 2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Implements a 8250 UART - */ - -#include <string> -#include <vector> - -#include "base/inifile.hh" -#include "base/str.hh" // for to_number -#include "base/trace.hh" -#include "dev/simconsole.hh" -#include "dev/uart8250.hh" -#include "dev/platform.hh" -#include "mem/bus/bus.hh" -#include "mem/bus/pio_interface.hh" -#include "mem/bus/pio_interface_impl.hh" -#include "mem/functional/memory_control.hh" -#include "sim/builder.hh" - -using namespace std; -using namespace TheISA; - -Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit) - : Event(&mainEventQueue), uart(u) -{ - DPRINTF(Uart, "UART Interrupt Event Initilizing\n"); - intrBit = bit; -} - -const char * -Uart8250::IntrEvent::description() -{ - return "uart interrupt delay event"; -} - -void -Uart8250::IntrEvent::process() -{ - if (intrBit & uart->IER) { - DPRINTF(Uart, "UART InterEvent, interrupting\n"); - uart->platform->postConsoleInt(); - uart->status |= intrBit; - } - else - DPRINTF(Uart, "UART InterEvent, not interrupting\n"); - -} - -/* The linux serial driver (8250.c about line 1182) loops reading from - * the device until the device reports it has no more data to - * read. After a maximum of 255 iterations the code prints "serial8250 - * too much work for irq X," and breaks out of the loop. Since the - * simulated system is so much slower than the actual system, if a - * user is typing on the keyboard it is very easy for them to provide - * input at a fast enough rate to not allow the loop to exit and thus - * the error to be printed. This magic number provides a delay between - * the time the UART receives a character to send to the simulated - * system and the time it actually notifies the system it has a - * character to send to alleviate this problem. --Ali - */ -void -Uart8250::IntrEvent::scheduleIntr() -{ - static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 450); - DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit, - curTick + interval); - if (!scheduled()) - schedule(curTick + interval); - else - reschedule(curTick + interval); -} - - -Uart8250::Uart8250(const string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *pio_bus, - Tick pio_latency, Platform *p) - : Uart(name, c, mmu, a, s, hier, pio_bus, pio_latency, p), - txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT) -{ - IER = 0; - DLAB = 0; - LCR = 0; - MCR = 0; - -} - -Fault -Uart8250::read(MemReqPtr &req, uint8_t *data) -{ - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - DPRINTF(Uart, " read register %#x\n", daddr); - - assert(req->size == 1); - - switch (daddr) { - case 0x0: - if (!(LCR & 0x80)) { // read byte - if (cons->dataAvailable()) - cons->in(*data); - else { - *(uint8_t*)data = 0; - // A limited amount of these are ok. - DPRINTF(Uart, "empty read of RX register\n"); - } - status &= ~RX_INT; - platform->clearConsoleInt(); - - if (cons->dataAvailable() && (IER & UART_IER_RDI)) - rxIntrEvent.scheduleIntr(); - } else { // dll divisor latch - ; - } - break; - case 0x1: - if (!(LCR & 0x80)) { // Intr Enable Register(IER) - *(uint8_t*)data = IER; - } else { // DLM divisor latch MSB - ; - } - break; - case 0x2: // Intr Identification Register (IIR) - DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); - - if (status & RX_INT) /* Rx data interrupt has a higher priority */ - *(uint8_t*)data = IIR_RXID; - else if (status & TX_INT) - *(uint8_t*)data = IIR_TXID; - else - *(uint8_t*)data = IIR_NOPEND; - - //Tx interrupts are cleared on IIR reads - status &= ~TX_INT; - break; - case 0x3: // Line Control Register (LCR) - *(uint8_t*)data = LCR; - break; - case 0x4: // Modem Control Register (MCR) - break; - case 0x5: // Line Status Register (LSR) - uint8_t lsr; - lsr = 0; - // check if there are any bytes to be read - if (cons->dataAvailable()) - lsr = UART_LSR_DR; - lsr |= UART_LSR_TEMT | UART_LSR_THRE; - *(uint8_t*)data = lsr; - break; - case 0x6: // Modem Status Register (MSR) - *(uint8_t*)data = 0; - break; - case 0x7: // Scratch Register (SCR) - *(uint8_t*)data = 0; // doesn't exist with at 8250. - break; - default: - panic("Tried to access a UART port that doesn't exist\n"); - break; - } - - return NoFault; - -} - -Fault -Uart8250::write(MemReqPtr &req, const uint8_t *data) -{ - Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); - - DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data); - - switch (daddr) { - case 0x0: - if (!(LCR & 0x80)) { // write byte - cons->out(*(uint8_t *)data); - platform->clearConsoleInt(); - status &= ~TX_INT; - if (UART_IER_THRI & IER) - txIntrEvent.scheduleIntr(); - } else { // dll divisor latch - ; - } - break; - case 0x1: - if (!(LCR & 0x80)) { // Intr Enable Register(IER) - IER = *(uint8_t*)data; - if (UART_IER_THRI & IER) - { - DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n"); - txIntrEvent.scheduleIntr(); - } - else - { - DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n"); - if (txIntrEvent.scheduled()) - txIntrEvent.deschedule(); - if (status & TX_INT) - platform->clearConsoleInt(); - status &= ~TX_INT; - } - - if ((UART_IER_RDI & IER) && cons->dataAvailable()) { - DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); - rxIntrEvent.scheduleIntr(); - } else { - DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n"); - if (rxIntrEvent.scheduled()) - rxIntrEvent.deschedule(); - if (status & RX_INT) - platform->clearConsoleInt(); - status &= ~RX_INT; - } - } else { // DLM divisor latch MSB - ; - } - break; - case 0x2: // FIFO Control Register (FCR) - break; - case 0x3: // Line Control Register (LCR) - LCR = *(uint8_t*)data; - break; - case 0x4: // Modem Control Register (MCR) - if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A)) - MCR = 0x9A; - break; - case 0x7: // Scratch Register (SCR) - // We are emulating a 8250 so we don't have a scratch reg - break; - default: - panic("Tried to access a UART port that doesn't exist\n"); - break; - } - return NoFault; -} - -void -Uart8250::dataAvailable() -{ - // if the kernel wants an interrupt when we have data - if (IER & UART_IER_RDI) - { - platform->postConsoleInt(); - status |= RX_INT; - } - -} - - - -void -Uart8250::serialize(ostream &os) -{ - SERIALIZE_SCALAR(status); - SERIALIZE_SCALAR(IER); - SERIALIZE_SCALAR(DLAB); - SERIALIZE_SCALAR(LCR); - SERIALIZE_SCALAR(MCR); - Tick rxintrwhen; - if (rxIntrEvent.scheduled()) - rxintrwhen = rxIntrEvent.when(); - else - rxintrwhen = 0; - Tick txintrwhen; - if (txIntrEvent.scheduled()) - txintrwhen = txIntrEvent.when(); - else - txintrwhen = 0; - SERIALIZE_SCALAR(rxintrwhen); - SERIALIZE_SCALAR(txintrwhen); -} - -void -Uart8250::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(status); - UNSERIALIZE_SCALAR(IER); - UNSERIALIZE_SCALAR(DLAB); - UNSERIALIZE_SCALAR(LCR); - UNSERIALIZE_SCALAR(MCR); - Tick rxintrwhen; - Tick txintrwhen; - UNSERIALIZE_SCALAR(rxintrwhen); - UNSERIALIZE_SCALAR(txintrwhen); - if (rxintrwhen != 0) - rxIntrEvent.schedule(rxintrwhen); - if (txintrwhen != 0) - txIntrEvent.schedule(txintrwhen); -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart8250) - - SimObjectParam<SimConsole *> console; - SimObjectParam<MemoryController *> mmu; - SimObjectParam<Platform *> platform; - Param<Addr> addr; - Param<Addr> size; - SimObjectParam<Bus*> pio_bus; - Param<Tick> pio_latency; - SimObjectParam<HierParams *> hier; - - -END_DECLARE_SIM_OBJECT_PARAMS(Uart8250) - -BEGIN_INIT_SIM_OBJECT_PARAMS(Uart8250) - - INIT_PARAM(console, "The console"), - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(platform, "Pointer to platfrom"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(size, "Device size", 0x8), - INIT_PARAM(pio_bus, ""), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) - -END_INIT_SIM_OBJECT_PARAMS(Uart8250) - -CREATE_SIM_OBJECT(Uart8250) -{ - return new Uart8250(getInstanceName(), console, mmu, addr, size, hier, - pio_bus, pio_latency, platform); -} - -REGISTER_SIM_OBJECT("Uart8250", Uart8250) diff --git a/dev/uart8250.hh b/dev/uart8250.hh deleted file mode 100644 index 63d1da3cf..000000000 --- a/dev/uart8250.hh +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * Defines a 8250 UART - */ - -#ifndef __TSUNAMI_UART_HH__ -#define __TSUNAMI_UART_HH__ - -#include "dev/tsunamireg.h" -#include "base/range.hh" -#include "dev/io_device.hh" -#include "dev/uart.hh" - - -/* UART8250 Interrupt ID Register - * bit 0 Interrupt Pending 0 = true, 1 = false - * bit 2:1 ID of highest priority interrupt - * bit 7:3 zeroes - */ -#define IIR_NOPEND 0x1 - -// Interrupt IDs -#define IIR_MODEM 0x00 /* Modem Status (lowest priority) */ -#define IIR_TXID 0x02 /* Tx Data */ -#define IIR_RXID 0x04 /* Rx Data */ -#define IIR_LINE 0x06 /* Rx Line Status (highest priority)*/ - -class SimConsole; -class MemoryController; -class Platform; - -class Uart8250 : public Uart -{ - - - protected: - uint8_t IER, DLAB, LCR, MCR; - - class IntrEvent : public Event - { - protected: - Uart8250 *uart; - int intrBit; - public: - IntrEvent(Uart8250 *u, int bit); - virtual void process(); - virtual const char *description(); - void scheduleIntr(); - }; - - IntrEvent txIntrEvent; - IntrEvent rxIntrEvent; - - public: - Uart8250(const std::string &name, SimConsole *c, MemoryController *mmu, - Addr a, Addr s, HierParams *hier, Bus *pio_bus, Tick pio_latency, - Platform *p); - - virtual Fault read(MemReqPtr &req, uint8_t *data); - virtual Fault write(MemReqPtr &req, const uint8_t *data); - - - /** - * Inform the uart that there is data available. - */ - virtual void dataAvailable(); - - - /** - * Return if we have an interrupt pending - * @return interrupt status - */ - virtual bool intStatus() { return status ? true : false; } - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - -}; - -#endif // __TSUNAMI_UART_HH__ |