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