X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=dev%2Ftsunami_pchip.cc;h=706daf9dc395bb9a7d51fd229881bea80bc73d2e;hb=466284b5d29ad0d44c1b020353cf7521be2b90de;hp=aadcf998ff3ef339327216e3a6dae44e097a6b16;hpb=3ccc0b1f968e3efaeccda65e06f862c899678312;p=gem5.git diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index aadcf998f..706daf9dc 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -1,6 +1,32 @@ -/* $Id$ */ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -/* @file +/** @file * Tsunami PChip (pci) */ @@ -9,110 +35,117 @@ #include #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/functional_mem/memory_control.hh" +#include "mem/bus/bus.hh" +#include "mem/bus/pio_interface.hh" +#include "mem/bus/pio_interface_impl.hh" +#include "mem/functional/memory_control.hh" +#include "mem/functional/physical.hh" #include "sim/builder.hh" #include "sim/system.hh" using namespace std; +//Should this be AlphaISA? +using namespace TheISA; -TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, - Addr addr, Addr mask, MemoryController *mmu) - : MmapDevice(name, addr, mask, mmu), tsunami(t) +TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, + MemoryController *mmu, HierParams *hier, + Bus *pio_bus, Tick pio_latency) + : PioDevice(name, t), addr(a), tsunami(t) { - wsba0 = 0; - wsba1 = 0; - wsba2 = 0; - wsba3 = 0; - wsm0 = 0; - wsm1 = 0; - wsm2 = 0; - wsm3 = 0; - tba0 = 0; - tba1 = 0; - tba2 = 0; - tba3 = 0; + mmu->add_child(this, RangeSize(addr, size)); + + for (int i = 0; i < 4; i++) { + wsba[i] = 0; + wsm[i] = 0; + tba[i] = 0; + } + + if (pio_bus) { + pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, + &TsunamiPChip::cacheAccess); + pioInterface->addAddrRange(RangeSize(addr, size)); + pioLatency = pio_latency * pio_bus->clockRate; + } + + + // initialize pchip control register + pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); //Set back pointer in tsunami tsunami->pchip = this; } -Fault -TsunamiPChip::read(MemReqPtr req, uint8_t *data) +Fault * +TsunamiPChip::read(MemReqPtr &req, uint8_t *data) { DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); - Addr daddr = (req->paddr & addr_mask) >> 6; -// ExecContext *xc = req->xc; -// int cpuid = xc->cpu_id; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; switch (req->size) { case sizeof(uint64_t): switch(daddr) { case TSDEV_PC_WSBA0: - *(uint64_t*)data = wsba0; - return No_Fault; + *(uint64_t*)data = wsba[0]; + return NoFault; case TSDEV_PC_WSBA1: - *(uint64_t*)data = wsba1; - return No_Fault; + *(uint64_t*)data = wsba[1]; + return NoFault; case TSDEV_PC_WSBA2: - *(uint64_t*)data = wsba2; - return No_Fault; + *(uint64_t*)data = wsba[2]; + return NoFault; case TSDEV_PC_WSBA3: - *(uint64_t*)data = wsba3; - return No_Fault; + *(uint64_t*)data = wsba[3]; + return NoFault; case TSDEV_PC_WSM0: - *(uint64_t*)data = wsm0; - return No_Fault; + *(uint64_t*)data = wsm[0]; + return NoFault; case TSDEV_PC_WSM1: - *(uint64_t*)data = wsm1; - return No_Fault; + *(uint64_t*)data = wsm[1]; + return NoFault; case TSDEV_PC_WSM2: - *(uint64_t*)data = wsm2; - return No_Fault; + *(uint64_t*)data = wsm[2]; + return NoFault; case TSDEV_PC_WSM3: - *(uint64_t*)data = wsm3; - return No_Fault; + *(uint64_t*)data = wsm[3]; + return NoFault; case TSDEV_PC_TBA0: - *(uint64_t*)data = tba0; - return No_Fault; + *(uint64_t*)data = tba[0]; + return NoFault; case TSDEV_PC_TBA1: - *(uint64_t*)data = tba1; - return No_Fault; + *(uint64_t*)data = tba[1]; + return NoFault; case TSDEV_PC_TBA2: - *(uint64_t*)data = tba2; - return No_Fault; + *(uint64_t*)data = tba[2]; + return NoFault; case TSDEV_PC_TBA3: - *(uint64_t*)data = tba3; - return No_Fault; + *(uint64_t*)data = tba[3]; + return NoFault; case TSDEV_PC_PCTL: - // might want to change the clock?? - *(uint64_t*)data = 0x00; // try this - return No_Fault; + *(uint64_t*)data = pctl; + return NoFault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); case TSDEV_PC_RES: panic("PC_RES not implemented\n"); case TSDEV_PC_PERROR: - panic("PC_PERROR not implemented\n"); + *(uint64_t*)data = 0x00; + return NoFault; case TSDEV_PC_PERRMASK: - panic("PC_PERRMASK not implemented\n"); + *(uint64_t*)data = 0x00; + return NoFault; case TSDEV_PC_PERRSET: panic("PC_PERRSET not implemented\n"); case TSDEV_PC_TLBIV: panic("PC_TLBIV not implemented\n"); case TSDEV_PC_TLBIA: *(uint64_t*)data = 0x00; // shouldn't be readable, but linux - return No_Fault; + return NoFault; case TSDEV_PC_PMONCTL: panic("PC_PMONCTL not implemented\n"); case TSDEV_PC_PMONCNT: @@ -131,67 +164,66 @@ TsunamiPChip::read(MemReqPtr req, uint8_t *data) } DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; } -Fault -TsunamiPChip::write(MemReqPtr req, const uint8_t *data) +Fault * +TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) { DPRINTF(Tsunami, "write - va=%#x size=%d \n", req->vaddr, req->size); - Addr daddr = (req->paddr & addr_mask) >> 6; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; switch (req->size) { case sizeof(uint64_t): switch(daddr) { case TSDEV_PC_WSBA0: - wsba0 = *(uint64_t*)data; - return No_Fault; + wsba[0] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSBA1: - wsba1 = *(uint64_t*)data; - return No_Fault; + wsba[1] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSBA2: - wsba2 = *(uint64_t*)data; - return No_Fault; + wsba[2] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSBA3: - wsba3 = *(uint64_t*)data; - return No_Fault; + wsba[3] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSM0: - wsm0 = *(uint64_t*)data; - return No_Fault; + wsm[0] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSM1: - wsm1 = *(uint64_t*)data; - return No_Fault; + wsm[1] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSM2: - wsm2 = *(uint64_t*)data; - return No_Fault; + wsm[2] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_WSM3: - wsm3 = *(uint64_t*)data; - return No_Fault; + wsm[3] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_TBA0: - tba0 = *(uint64_t*)data; - return No_Fault; + tba[0] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_TBA1: - tba1 = *(uint64_t*)data; - return No_Fault; + tba[1] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_TBA2: - tba2 = *(uint64_t*)data; - return No_Fault; + tba[2] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_TBA3: - tba3 = *(uint64_t*)data; - return No_Fault; + tba[3] = *(uint64_t*)data; + return NoFault; case TSDEV_PC_PCTL: - // might want to change the clock?? - //*(uint64_t*)data; // try this - return No_Fault; + pctl = *(uint64_t*)data; + return NoFault; case TSDEV_PC_PLAT: panic("PC_PLAT not implemented\n"); case TSDEV_PC_RES: panic("PC_RES not implemented\n"); case TSDEV_PC_PERROR: - panic("PC_PERROR not implemented\n"); + return NoFault; case TSDEV_PC_PERRMASK: panic("PC_PERRMASK not implemented\n"); case TSDEV_PC_PERRSET: @@ -199,7 +231,7 @@ TsunamiPChip::write(MemReqPtr req, const uint8_t *data) case TSDEV_PC_TLBIV: panic("PC_TLBIV not implemented\n"); case TSDEV_PC_TLBIA: - return No_Fault; // value ignored, supposted to invalidate SG TLB + return NoFault; // value ignored, supposted to invalidate SG TLB case TSDEV_PC_PMONCTL: panic("PC_PMONCTL not implemented\n"); case TSDEV_PC_PMONCNT: @@ -219,19 +251,110 @@ TsunamiPChip::write(MemReqPtr req, const uint8_t *data) DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); - return No_Fault; + return NoFault; +} + +#define DMA_ADDR_MASK ULL(0x3ffffffff) + +Addr +TsunamiPChip::translatePciToDma(Addr busAddr) +{ + // compare the address to the window base registers + uint64_t tbaMask = 0; + uint64_t baMask = 0; + + uint64_t windowMask = 0; + uint64_t windowBase = 0; + + uint64_t pteEntry = 0; + + Addr pteAddr; + Addr dmaAddr; + +#if 0 + DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); + for (int i = 0; i < 4; i++) { + DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", + i, wsba[i], wsm[i]); + + windowBase = wsba[i]; + windowMask = ~wsm[i] & (ULL(0xfff) << 20); + + if ((busAddr & windowMask) == (windowBase & windowMask)) { + DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", + i, windowBase, windowMask, (busAddr & windowMask), + (windowBase & windowMask)); + } + } +#endif + + for (int i = 0; i < 4; i++) { + + windowBase = wsba[i]; + windowMask = ~wsm[i] & (ULL(0xfff) << 20); + + if ((busAddr & windowMask) == (windowBase & windowMask)) { + + if (wsba[i] & 0x1) { // see if enabled + if (wsba[i] & 0x2) { // see if SG bit is set + /** @todo + This currently is faked by just doing a direct + read from memory, however, to be realistic, this + needs to actually do a bus transaction. The process + is explained in the tsunami documentation on page + 10-12 and basically munges the address to look up a + PTE from a table in memory and then uses that mapping + to create an address for the SG page + */ + + tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); + baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); + pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); + + memcpy((void *)&pteEntry, + tsunami->system-> + physmem->dma_addr(pteAddr, sizeof(uint64_t)), + sizeof(uint64_t)); + + dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); + + } else { + baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); + tbaMask = ~baMask; + dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); + } + + return (dmaAddr & DMA_ADDR_MASK); + } + } + } + + // if no match was found, then return the original address + return busAddr; } void TsunamiPChip::serialize(std::ostream &os) { - // code should be written + SERIALIZE_SCALAR(pctl); + SERIALIZE_ARRAY(wsba, 4); + SERIALIZE_ARRAY(wsm, 4); + SERIALIZE_ARRAY(tba, 4); } void TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) { - //code should be written + UNSERIALIZE_SCALAR(pctl); + UNSERIALIZE_ARRAY(wsba, 4); + UNSERIALIZE_ARRAY(wsm, 4); + UNSERIALIZE_ARRAY(tba, 4); +} + +Tick +TsunamiPChip::cacheAccess(MemReqPtr &req) +{ + return curTick + pioLatency; } BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) @@ -239,7 +362,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) SimObjectParam tsunami; SimObjectParam mmu; Param addr; - Param mask; + SimObjectParam pio_bus; + Param pio_latency; + SimObjectParam hier; END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) @@ -248,13 +373,16 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) INIT_PARAM(tsunami, "Tsunami"), INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(addr, "Device Address"), - INIT_PARAM(mask, "Address Mask") + INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) CREATE_SIM_OBJECT(TsunamiPChip) { - return new TsunamiPChip(getInstanceName(), tsunami, addr, mask, mmu); + return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, + pio_bus, pio_latency); } REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)