tsunami_pchip.cc revision 1762
1892SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
3892SN/A * All rights reserved.
4892SN/A *
5892SN/A * Redistribution and use in source and binary forms, with or without
6892SN/A * modification, are permitted provided that the following conditions are
7892SN/A * met: redistributions of source code must retain the above copyright
8892SN/A * notice, this list of conditions and the following disclaimer;
9892SN/A * redistributions in binary form must reproduce the above copyright
10892SN/A * notice, this list of conditions and the following disclaimer in the
11892SN/A * documentation and/or other materials provided with the distribution;
12892SN/A * neither the name of the copyright holders nor the names of its
13892SN/A * contributors may be used to endorse or promote products derived from
14892SN/A * this software without specific prior written permission.
15892SN/A *
16892SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17892SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18892SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19892SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20892SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21892SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22892SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23892SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24892SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25892SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26892SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A */
282665SN/A
292665SN/A/** @file
30892SN/A * Tsunami PChip (pci)
31767SN/A */
321730SN/A
33798SN/A#include <deque>
34767SN/A#include <string>
35767SN/A#include <vector>
36767SN/A
37767SN/A#include "base/trace.hh"
38767SN/A#include "dev/tsunami_pchip.hh"
39767SN/A#include "dev/tsunamireg.h"
402432SN/A#include "dev/tsunami.hh"
41767SN/A#include "mem/bus/bus.hh"
423348SN/A#include "mem/bus/pio_interface.hh"
433348SN/A#include "mem/bus/pio_interface_impl.hh"
443540Sgblack@eecs.umich.edu#include "mem/functional/memory_control.hh"
453540Sgblack@eecs.umich.edu#include "mem/functional/physical.hh"
463540Sgblack@eecs.umich.edu#include "sim/builder.hh"
473348SN/A#include "sim/system.hh"
483348SN/A
492523SN/Ausing namespace std;
504762Snate@binkert.org
51767SN/ATsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
52767SN/A                           MemoryController *mmu, HierParams *hier,
53767SN/A                           Bus *bus, Tick pio_latency)
542107SN/A    : PioDevice(name, t), addr(a), tsunami(t)
552107SN/A{
56767SN/A    mmu->add_child(this, RangeSize(addr, size));
574762Snate@binkert.org
582523SN/A    for (int i = 0; i < 4; i++) {
59767SN/A        wsba[i] = 0;
603846Shsul@eecs.umich.edu        wsm[i] = 0;
61909SN/A        tba[i] = 0;
62767SN/A    }
631290SN/A
641290SN/A    if (bus) {
651290SN/A        pioInterface = newPioInterface(name, hier, bus, this,
661290SN/A                                      &TsunamiPChip::cacheAccess);
671290SN/A        pioInterface->addAddrRange(RangeSize(addr, size));
681290SN/A        pioLatency = pio_latency * bus->clockRate;
691290SN/A    }
701290SN/A
71775SN/A
72775SN/A    // initialize pchip control register
73775SN/A    pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
74767SN/A
75767SN/A    //Set back pointer in tsunami
762523SN/A    tsunami->pchip = this;
773349SN/A}
78767SN/A
792641SN/AFault
80767SN/ATsunamiPChip::read(MemReqPtr &req, uint8_t *data)
812641SN/A{
822641SN/A    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
831290SN/A            req->vaddr, req->size);
842641SN/A
852641SN/A    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
86767SN/A
872630SN/A    switch (req->size) {
882641SN/A
89767SN/A      case sizeof(uint64_t):
90767SN/A          switch(daddr) {
913875Sbinkertn@umich.edu              case TSDEV_PC_WSBA0:
923875Sbinkertn@umich.edu                    *(uint64_t*)data = wsba[0];
931290SN/A                    return No_Fault;
941290SN/A              case TSDEV_PC_WSBA1:
952630SN/A                    *(uint64_t*)data = wsba[1];
962523SN/A                    return No_Fault;
971290SN/A              case TSDEV_PC_WSBA2:
981290SN/A                    *(uint64_t*)data = wsba[2];
991290SN/A                    return No_Fault;
1001290SN/A              case TSDEV_PC_WSBA3:
1012630SN/A                    *(uint64_t*)data = wsba[3];
1022523SN/A                    return No_Fault;
1031290SN/A              case TSDEV_PC_WSM0:
1041290SN/A                    *(uint64_t*)data = wsm[0];
1051290SN/A                    return No_Fault;
106767SN/A              case TSDEV_PC_WSM1:
1072630SN/A                    *(uint64_t*)data = wsm[1];
1082523SN/A                    return No_Fault;
109767SN/A              case TSDEV_PC_WSM2:
110767SN/A                    *(uint64_t*)data = wsm[2];
1112523SN/A                    return No_Fault;
112767SN/A              case TSDEV_PC_WSM3:
1132630SN/A                    *(uint64_t*)data = wsm[3];
1142630SN/A                    return No_Fault;
1152523SN/A              case TSDEV_PC_TBA0:
116767SN/A                    *(uint64_t*)data = tba[0];
117767SN/A                    return No_Fault;
118767SN/A              case TSDEV_PC_TBA1:
119767SN/A                    *(uint64_t*)data = tba[1];
1202630SN/A                    return No_Fault;
1212523SN/A              case TSDEV_PC_TBA2:
122767SN/A                    *(uint64_t*)data = tba[2];
1232630SN/A                    return No_Fault;
1242523SN/A              case TSDEV_PC_TBA3:
125767SN/A                    *(uint64_t*)data = tba[3];
1262630SN/A                    return No_Fault;
1272523SN/A              case TSDEV_PC_PCTL:
128767SN/A                    *(uint64_t*)data = pctl;
1292630SN/A                    return No_Fault;
1302523SN/A              case TSDEV_PC_PLAT:
131767SN/A                    panic("PC_PLAT not implemented\n");
1322630SN/A              case TSDEV_PC_RES:
1332523SN/A                    panic("PC_RES not implemented\n");
134767SN/A              case TSDEV_PC_PERROR:
1352630SN/A                    *(uint64_t*)data = 0x00;
1362523SN/A                    return No_Fault;
137767SN/A              case TSDEV_PC_PERRMASK:
1382630SN/A                    *(uint64_t*)data = 0x00;
1392523SN/A                    return No_Fault;
140767SN/A              case TSDEV_PC_PERRSET:
1412630SN/A                    panic("PC_PERRSET not implemented\n");
1422523SN/A              case TSDEV_PC_TLBIV:
143767SN/A                    panic("PC_TLBIV not implemented\n");
1442630SN/A              case TSDEV_PC_TLBIA:
1452523SN/A                    *(uint64_t*)data = 0x00; // shouldn't be readable, but linux
146767SN/A                    return No_Fault;
1472630SN/A              case TSDEV_PC_PMONCTL:
1482523SN/A                    panic("PC_PMONCTL not implemented\n");
149767SN/A              case TSDEV_PC_PMONCNT:
150767SN/A                    panic("PC_PMONCTN not implemented\n");
1512523SN/A              default:
152767SN/A                  panic("Default in PChip Read reached reading 0x%x\n", daddr);
153767SN/A
154767SN/A           } // uint64_t
155767SN/A
156767SN/A      break;
1572523SN/A      case sizeof(uint32_t):
158767SN/A      case sizeof(uint16_t):
159767SN/A      case sizeof(uint8_t):
160767SN/A      default:
161767SN/A        panic("invalid access size(?) for tsunami register!\n\n");
162767SN/A    }
1632523SN/A    DPRINTFN("Tsunami PChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
1641290SN/A
1652630SN/A    return No_Fault;
1662523SN/A}
1671290SN/A
1682630SN/AFault
1692523SN/ATsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
170768SN/A{
171768SN/A    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
172767SN/A            req->vaddr, req->size);
173767SN/A
174767SN/A    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
175767SN/A
176767SN/A    switch (req->size) {
177767SN/A
178767SN/A      case sizeof(uint64_t):
179768SN/A          switch(daddr) {
180767SN/A              case TSDEV_PC_WSBA0:
1812549SN/A                    wsba[0] = *(uint64_t*)data;
1822641SN/A                    return No_Fault;
183767SN/A              case TSDEV_PC_WSBA1:
1842641SN/A                    wsba[1] = *(uint64_t*)data;
1852523SN/A                    return No_Fault;
186767SN/A              case TSDEV_PC_WSBA2:
187767SN/A                    wsba[2] = *(uint64_t*)data;
1882523SN/A                    return No_Fault;
1893349SN/A              case TSDEV_PC_WSBA3:
190767SN/A                    wsba[3] = *(uint64_t*)data;
1912641SN/A                    return No_Fault;
1922641SN/A              case TSDEV_PC_WSM0:
1932641SN/A                    wsm[0] = *(uint64_t*)data;
1942539SN/A                    return No_Fault;
1952523SN/A              case TSDEV_PC_WSM1:
1962641SN/A                    wsm[1] = *(uint64_t*)data;
1972523SN/A                    return No_Fault;
1982641SN/A              case TSDEV_PC_WSM2:
199767SN/A                    wsm[2] = *(uint64_t*)data;
200830SN/A                    return No_Fault;
201830SN/A              case TSDEV_PC_WSM3:
202767SN/A                    wsm[3] = *(uint64_t*)data;
2032539SN/A                    return No_Fault;
2042539SN/A              case TSDEV_PC_TBA0:
2052539SN/A                    tba[0] = *(uint64_t*)data;
2061290SN/A                    return No_Fault;
2072539SN/A              case TSDEV_PC_TBA1:
2082539SN/A                    tba[1] = *(uint64_t*)data;
2092539SN/A                    return No_Fault;
2101290SN/A              case TSDEV_PC_TBA2:
2112539SN/A                    tba[2] = *(uint64_t*)data;
2122539SN/A                    return No_Fault;
2132630SN/A              case TSDEV_PC_TBA3:
2142539SN/A                    tba[3] = *(uint64_t*)data;
2152539SN/A                    return No_Fault;
2162539SN/A              case TSDEV_PC_PCTL:
2172539SN/A                    pctl = *(uint64_t*)data;
2182539SN/A                    return No_Fault;
2192539SN/A              case TSDEV_PC_PLAT:
2202539SN/A                    panic("PC_PLAT not implemented\n");
2212539SN/A              case TSDEV_PC_RES:
2222539SN/A                    panic("PC_RES not implemented\n");
2232539SN/A              case TSDEV_PC_PERROR:
2242539SN/A                    return No_Fault;
2252539SN/A              case TSDEV_PC_PERRMASK:
2262539SN/A                    panic("PC_PERRMASK not implemented\n");
2272539SN/A              case TSDEV_PC_PERRSET:
2282539SN/A                    panic("PC_PERRSET not implemented\n");
2292539SN/A              case TSDEV_PC_TLBIV:
2302539SN/A                    panic("PC_TLBIV not implemented\n");
2312539SN/A              case TSDEV_PC_TLBIA:
2322539SN/A                    return No_Fault; // value ignored, supposted to invalidate SG TLB
2332539SN/A              case TSDEV_PC_PMONCTL:
2342539SN/A                    panic("PC_PMONCTL not implemented\n");
2352539SN/A              case TSDEV_PC_PMONCNT:
2361290SN/A                    panic("PC_PMONCTN not implemented\n");
2371074SN/A              default:
2381074SN/A                  panic("Default in PChip Read reached reading 0x%x\n", daddr);
2392539SN/A
2402539SN/A           } // uint64_t
2412539SN/A
2422539SN/A      break;
2432539SN/A      case sizeof(uint32_t):
2442539SN/A      case sizeof(uint16_t):
2452539SN/A      case sizeof(uint8_t):
2462539SN/A      default:
2472539SN/A        panic("invalid access size(?) for tsunami register!\n\n");
2482539SN/A    }
2492539SN/A
2502630SN/A    DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
2512539SN/A
2522539SN/A    return No_Fault;
2532539SN/A}
2542539SN/A
2552539SN/A#define DMA_ADDR_MASK ULL(0x3ffffffff)
2562539SN/A
2572539SN/AAddr
2582539SN/ATsunamiPChip::translatePciToDma(Addr busAddr)
2592630SN/A{
2602539SN/A    // compare the address to the window base registers
2612539SN/A    uint64_t tbaMask = 0;
2622539SN/A    uint64_t baMask = 0;
2632539SN/A
2642539SN/A    uint64_t windowMask = 0;
2652539SN/A    uint64_t windowBase = 0;
2662539SN/A
2672630SN/A    uint64_t pteEntry = 0;
2682539SN/A
2692539SN/A    Addr pteAddr;
2702539SN/A    Addr dmaAddr;
2712539SN/A
2722539SN/A#if 0
2732539SN/A    DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
2742630SN/A    for (int i = 0; i < 4; i++) {
2752539SN/A        DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
2762539SN/A                i, wsba[i], wsm[i]);
2772539SN/A
2782539SN/A        windowBase = wsba[i];
2792539SN/A        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
2802549SN/A
2812539SN/A        if ((busAddr & windowMask) == (windowBase & windowMask)) {
2822539SN/A            DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
2832539SN/A                    i, windowBase, windowMask, (busAddr & windowMask),
2842539SN/A                    (windowBase & windowMask));
2852539SN/A        }
2862539SN/A    }
2872539SN/A#endif
2882539SN/A
2892539SN/A    for (int i = 0; i < 4; i++) {
2902539SN/A
2912539SN/A        windowBase = wsba[i];
2922539SN/A        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
2932539SN/A
2942539SN/A        if ((busAddr & windowMask) == (windowBase & windowMask)) {
2952539SN/A
2962539SN/A            if (wsba[i] & 0x1) {   // see if enabled
2972539SN/A                if (wsba[i] & 0x2) { // see if SG bit is set
2982539SN/A                    /** @todo
2992539SN/A                        This currently is faked by just doing a direct
3002539SN/A                        read from memory, however, to be realistic, this
3012539SN/A                        needs to actually do a bus transaction.  The process
3022539SN/A                        is explained in the tsunami documentation on page
3032539SN/A                        10-12 and basically munges the address to look up a
3042539SN/A                        PTE from a table in memory and then uses that mapping
3052539SN/A                        to create an address for the SG page
3062630SN/A                    */
3072539SN/A
3082539SN/A                    tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
3092539SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
3102539SN/A                    pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
3112539SN/A
3122539SN/A                    memcpy((void *)&pteEntry,
3132539SN/A                           tsunami->system->
3142539SN/A                           physmem->dma_addr(pteAddr, sizeof(uint64_t)),
3152539SN/A                           sizeof(uint64_t));
3162539SN/A
3172539SN/A                    dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
3182539SN/A
3192539SN/A                } else {
3202539SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
3212539SN/A                    tbaMask = ~baMask;
3222539SN/A                    dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
3232539SN/A                }
3242539SN/A
3252539SN/A                return (dmaAddr & DMA_ADDR_MASK);
3262539SN/A            }
3272539SN/A        }
3282539SN/A    }
3292539SN/A
3302539SN/A    // if no match was found, then return the original address
3312539SN/A    return busAddr;
3322539SN/A}
3332539SN/A
3341074SN/Avoid
3352539SN/ATsunamiPChip::serialize(std::ostream &os)
3362539SN/A{
3372539SN/A    SERIALIZE_SCALAR(pctl);
3382539SN/A    SERIALIZE_ARRAY(wsba, 4);
3392539SN/A    SERIALIZE_ARRAY(wsm, 4);
3402539SN/A    SERIALIZE_ARRAY(tba, 4);
3412539SN/A}
3422539SN/A
3432539SN/Avoid
3442539SN/ATsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
3452539SN/A{
3462539SN/A    UNSERIALIZE_SCALAR(pctl);
3472539SN/A    UNSERIALIZE_ARRAY(wsba, 4);
3482539SN/A    UNSERIALIZE_ARRAY(wsm, 4);
3492539SN/A    UNSERIALIZE_ARRAY(tba, 4);
3502539SN/A}
3512539SN/A
3522539SN/ATick
3532539SN/ATsunamiPChip::cacheAccess(MemReqPtr &req)
3542539SN/A{
3552539SN/A    return curTick + pioLatency;
3562630SN/A}
3572539SN/A
3582539SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
3592630SN/A
3602539SN/A    SimObjectParam<Tsunami *> tsunami;
3612539SN/A    SimObjectParam<MemoryController *> mmu;
3622630SN/A    Param<Addr> addr;
3632539SN/A    SimObjectParam<Bus*> io_bus;
3642539SN/A    Param<Tick> pio_latency;
3652539SN/A    SimObjectParam<HierParams *> hier;
3662539SN/A
3672539SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
3682641SN/A
3692539SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
370767SN/A
371767SN/A    INIT_PARAM(tsunami, "Tsunami"),
372767SN/A    INIT_PARAM(mmu, "Memory Controller"),
3731290SN/A    INIT_PARAM(addr, "Device Address"),
3741290SN/A    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
3754103Ssaidi@eecs.umich.edu    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
3761290SN/A    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
3771290SN/A
3781290SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
3791290SN/A
3801290SN/ACREATE_SIM_OBJECT(TsunamiPChip)
3811290SN/A{
3821290SN/A    return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier,
3831290SN/A                            io_bus, pio_latency);
3841290SN/A}
3851290SN/A
3861290SN/AREGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
3871290SN/A