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 * Authors: Ali Saidi
292665SN/A *          Andrew Schultz
30892SN/A */
31768SN/A
321730SN/A/** @file
33768SN/A * Tsunami PChip (pci)
34768SN/A */
3511244Sandreas.sandberg@arm.com#include "dev/alpha/tsunami_pchip.hh"
36768SN/A
37768SN/A#include <deque>
38768SN/A#include <string>
39768SN/A#include <vector>
40768SN/A
41768SN/A#include "base/trace.hh"
426658Snate@binkert.org#include "config/the_isa.hh"
438232Snate@binkert.org#include "debug/Tsunami.hh"
448229Snate@binkert.org#include "dev/alpha/tsunami.hh"
4511244Sandreas.sandberg@arm.com#include "dev/alpha/tsunami_cchip.hh"
463540Sgblack@eecs.umich.edu#include "dev/alpha/tsunamireg.h"
4711260Sandreas.sandberg@arm.com#include "dev/pci/device.hh"
482542SN/A#include "mem/packet.hh"
493348SN/A#include "mem/packet_access.hh"
50768SN/A#include "sim/system.hh"
51768SN/A
52768SN/Ausing namespace std;
532107SN/A//Should this be AlphaISA?
542107SN/Ausing namespace TheISA;
55768SN/A
564762Snate@binkert.orgTsunamiPChip::TsunamiPChip(const Params *p)
5711244Sandreas.sandberg@arm.com    : GenericPciHost(p),
5811244Sandreas.sandberg@arm.com      pioRange(RangeSize(p->pio_addr, 0x1000)),
5911244Sandreas.sandberg@arm.com      pioDelay(p->pio_latency)
60768SN/A{
61835SN/A    for (int i = 0; i < 4; i++) {
62835SN/A        wsba[i] = 0;
63835SN/A        wsm[i] = 0;
64835SN/A        tba[i] = 0;
65835SN/A    }
66768SN/A
67896SN/A    // initialize pchip control register
68896SN/A    pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
69896SN/A
70775SN/A    //Set back pointer in tsunami
712539SN/A    p->tsunami->pchip = this;
722539SN/A}
732539SN/A
742539SN/ATick
753349SN/ATsunamiPChip::read(PacketPtr pkt)
762539SN/A{
7711244Sandreas.sandberg@arm.com    // We only need to handle our own configuration registers, pass
7811244Sandreas.sandberg@arm.com    // unknown addresses to the generic code.
7911244Sandreas.sandberg@arm.com    if (!pioRange.contains(pkt->getAddr()))
8011244Sandreas.sandberg@arm.com        return GenericPciHost::read(pkt);
812539SN/A
8211244Sandreas.sandberg@arm.com    Addr daddr = (pkt->getAddr() - pioRange.start()) >> 6;;
832641SN/A    assert(pkt->getSize() == sizeof(uint64_t));
842539SN/A
852539SN/A
862641SN/A    DPRINTF(Tsunami, "read  va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
872539SN/A
882539SN/A    switch(daddr) {
892539SN/A      case TSDEV_PC_WSBA0:
9013232Sgabeblack@google.com            pkt->setLE(wsba[0]);
912539SN/A            break;
922539SN/A      case TSDEV_PC_WSBA1:
9313232Sgabeblack@google.com            pkt->setLE(wsba[1]);
942539SN/A            break;
952539SN/A      case TSDEV_PC_WSBA2:
9613232Sgabeblack@google.com            pkt->setLE(wsba[2]);
972539SN/A            break;
982539SN/A      case TSDEV_PC_WSBA3:
9913232Sgabeblack@google.com            pkt->setLE(wsba[3]);
1002539SN/A            break;
1012539SN/A      case TSDEV_PC_WSM0:
10213232Sgabeblack@google.com            pkt->setLE(wsm[0]);
1032539SN/A            break;
1042539SN/A      case TSDEV_PC_WSM1:
10513232Sgabeblack@google.com            pkt->setLE(wsm[1]);
1062539SN/A            break;
1072539SN/A      case TSDEV_PC_WSM2:
10813232Sgabeblack@google.com            pkt->setLE(wsm[2]);
1092539SN/A            break;
1102539SN/A      case TSDEV_PC_WSM3:
11113232Sgabeblack@google.com            pkt->setLE(wsm[3]);
1122539SN/A            break;
1132539SN/A      case TSDEV_PC_TBA0:
11413232Sgabeblack@google.com            pkt->setLE(tba[0]);
1152539SN/A            break;
1162539SN/A      case TSDEV_PC_TBA1:
11713232Sgabeblack@google.com            pkt->setLE(tba[1]);
1182539SN/A            break;
1192539SN/A      case TSDEV_PC_TBA2:
12013232Sgabeblack@google.com            pkt->setLE(tba[2]);
1212539SN/A            break;
1222542SN/A      case TSDEV_PC_TBA3:
12313232Sgabeblack@google.com            pkt->setLE(tba[3]);
1242539SN/A            break;
1252539SN/A      case TSDEV_PC_PCTL:
12613232Sgabeblack@google.com            pkt->setLE(pctl);
1272539SN/A            break;
1282539SN/A      case TSDEV_PC_PLAT:
1292539SN/A            panic("PC_PLAT not implemented\n");
1302539SN/A      case TSDEV_PC_RES:
1312539SN/A            panic("PC_RES not implemented\n");
1322539SN/A      case TSDEV_PC_PERROR:
13313232Sgabeblack@google.com            pkt->setLE((uint64_t)0x00);
1342539SN/A            break;
1352539SN/A      case TSDEV_PC_PERRMASK:
13613232Sgabeblack@google.com            pkt->setLE((uint64_t)0x00);
1372539SN/A            break;
1382539SN/A      case TSDEV_PC_PERRSET:
1392539SN/A            panic("PC_PERRSET not implemented\n");
1402539SN/A      case TSDEV_PC_TLBIV:
1412539SN/A            panic("PC_TLBIV not implemented\n");
1422539SN/A      case TSDEV_PC_TLBIA:
14313232Sgabeblack@google.com            pkt->setLE((uint64_t)0x00); // shouldn't be readable, but linux
1442539SN/A            break;
1452539SN/A      case TSDEV_PC_PMONCTL:
1462539SN/A            panic("PC_PMONCTL not implemented\n");
1472539SN/A      case TSDEV_PC_PMONCNT:
1482539SN/A            panic("PC_PMONCTN not implemented\n");
1492539SN/A      default:
1502539SN/A          panic("Default in PChip Read reached reading 0x%x\n", daddr);
1512539SN/A    }
15211244Sandreas.sandberg@arm.com
1534870Sstever@eecs.umich.edu    pkt->makeAtomicResponse();
1542539SN/A    return pioDelay;
1552539SN/A
156768SN/A}
157768SN/A
1582542SN/ATick
1593349SN/ATsunamiPChip::write(PacketPtr pkt)
160768SN/A{
16111244Sandreas.sandberg@arm.com    // We only need to handle our own configuration registers, pass
16211244Sandreas.sandberg@arm.com    // unknown addresses to the generic code.
16311244Sandreas.sandberg@arm.com    if (!pioRange.contains(pkt->getAddr()))
16411244Sandreas.sandberg@arm.com        return GenericPciHost::write(pkt);
16511244Sandreas.sandberg@arm.com
16611244Sandreas.sandberg@arm.com    Addr daddr = (pkt->getAddr() - pioRange.start()) >> 6;
167768SN/A
1682641SN/A    assert(pkt->getSize() == sizeof(uint64_t));
169768SN/A
1702641SN/A    DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
171768SN/A
1722539SN/A    switch(daddr) {
1732539SN/A        case TSDEV_PC_WSBA0:
17413232Sgabeblack@google.com              wsba[0] = pkt->getLE<uint64_t>();
1752539SN/A              break;
1762539SN/A        case TSDEV_PC_WSBA1:
17713232Sgabeblack@google.com              wsba[1] = pkt->getLE<uint64_t>();
1782539SN/A              break;
1792539SN/A        case TSDEV_PC_WSBA2:
18013232Sgabeblack@google.com              wsba[2] = pkt->getLE<uint64_t>();
1812539SN/A              break;
1822539SN/A        case TSDEV_PC_WSBA3:
18313232Sgabeblack@google.com              wsba[3] = pkt->getLE<uint64_t>();
1842539SN/A              break;
1852539SN/A        case TSDEV_PC_WSM0:
18613232Sgabeblack@google.com              wsm[0] = pkt->getLE<uint64_t>();
1872539SN/A              break;
1882539SN/A        case TSDEV_PC_WSM1:
18913232Sgabeblack@google.com              wsm[1] = pkt->getLE<uint64_t>();
1902539SN/A              break;
1912539SN/A        case TSDEV_PC_WSM2:
19213232Sgabeblack@google.com              wsm[2] = pkt->getLE<uint64_t>();
1932539SN/A              break;
1942539SN/A        case TSDEV_PC_WSM3:
19513232Sgabeblack@google.com              wsm[3] = pkt->getLE<uint64_t>();
1962539SN/A              break;
1972539SN/A        case TSDEV_PC_TBA0:
19813232Sgabeblack@google.com              tba[0] = pkt->getLE<uint64_t>();
1992539SN/A              break;
2002539SN/A        case TSDEV_PC_TBA1:
20113232Sgabeblack@google.com              tba[1] = pkt->getLE<uint64_t>();
2022539SN/A              break;
2032539SN/A        case TSDEV_PC_TBA2:
20413232Sgabeblack@google.com              tba[2] = pkt->getLE<uint64_t>();
2052539SN/A              break;
2062539SN/A        case TSDEV_PC_TBA3:
20713232Sgabeblack@google.com              tba[3] = pkt->getLE<uint64_t>();
2082539SN/A              break;
2092539SN/A        case TSDEV_PC_PCTL:
21013232Sgabeblack@google.com              pctl = pkt->getLE<uint64_t>();
2112539SN/A              break;
2122539SN/A        case TSDEV_PC_PLAT:
2132539SN/A              panic("PC_PLAT not implemented\n");
2142539SN/A        case TSDEV_PC_RES:
2152539SN/A              panic("PC_RES not implemented\n");
2162539SN/A        case TSDEV_PC_PERROR:
2172539SN/A              break;
2182539SN/A        case TSDEV_PC_PERRMASK:
2192539SN/A              panic("PC_PERRMASK not implemented\n");
2202539SN/A        case TSDEV_PC_PERRSET:
2212539SN/A              panic("PC_PERRSET not implemented\n");
2222539SN/A        case TSDEV_PC_TLBIV:
2232539SN/A              panic("PC_TLBIV not implemented\n");
2242539SN/A        case TSDEV_PC_TLBIA:
2252539SN/A              break; // value ignored, supposted to invalidate SG TLB
2262539SN/A        case TSDEV_PC_PMONCTL:
2272539SN/A              panic("PC_PMONCTL not implemented\n");
2282539SN/A        case TSDEV_PC_PMONCNT:
2292539SN/A              panic("PC_PMONCTN not implemented\n");
2302539SN/A        default:
2312549SN/A            panic("Default in PChip write reached reading 0x%x\n", daddr);
232768SN/A
2332539SN/A    } // uint64_t
234768SN/A
2354870Sstever@eecs.umich.edu    pkt->makeAtomicResponse();
2362539SN/A    return pioDelay;
237768SN/A}
238768SN/A
23911244Sandreas.sandberg@arm.com
24011244Sandreas.sandberg@arm.comAddrRangeList
24111244Sandreas.sandberg@arm.comTsunamiPChip::getAddrRanges() const
24211244Sandreas.sandberg@arm.com{
24311244Sandreas.sandberg@arm.com    return AddrRangeList({
24411244Sandreas.sandberg@arm.com            RangeSize(confBase, confSize),
24511244Sandreas.sandberg@arm.com            pioRange
24611244Sandreas.sandberg@arm.com        });
24711244Sandreas.sandberg@arm.com}
24811244Sandreas.sandberg@arm.com
24911244Sandreas.sandberg@arm.com
250857SN/A#define DMA_ADDR_MASK ULL(0x3ffffffff)
251857SN/A
252835SN/AAddr
25311244Sandreas.sandberg@arm.comTsunamiPChip::dmaAddr(const PciBusAddr &dev, Addr busAddr) const
254835SN/A{
255835SN/A    // compare the address to the window base registers
256857SN/A    uint64_t tbaMask = 0;
257857SN/A    uint64_t baMask = 0;
258857SN/A
259835SN/A    uint64_t windowMask = 0;
260835SN/A    uint64_t windowBase = 0;
261857SN/A
262857SN/A    uint64_t pteEntry = 0;
263857SN/A
264857SN/A    Addr pteAddr;
265835SN/A    Addr dmaAddr;
266835SN/A
267896SN/A    for (int i = 0; i < 4; i++) {
268896SN/A
269896SN/A        windowBase = wsba[i];
270896SN/A        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
271896SN/A
272896SN/A        if ((busAddr & windowMask) == (windowBase & windowMask)) {
273835SN/A
274835SN/A            if (wsba[i] & 0x1) {   // see if enabled
275857SN/A                if (wsba[i] & 0x2) { // see if SG bit is set
276857SN/A                    /** @todo
277857SN/A                        This currently is faked by just doing a direct
278857SN/A                        read from memory, however, to be realistic, this
279857SN/A                        needs to actually do a bus transaction.  The process
280857SN/A                        is explained in the tsunami documentation on page
281857SN/A                        10-12 and basically munges the address to look up a
282857SN/A                        PTE from a table in memory and then uses that mapping
283857SN/A                        to create an address for the SG page
284857SN/A                    */
285835SN/A
28614010Sgabeblack@google.com                    tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) |
28714010Sgabeblack@google.com                                ULL(0x3ff));
288896SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
289857SN/A                    pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
290857SN/A
29114010Sgabeblack@google.com                    sys->physProxy.readBlob(pteAddr, &pteEntry,
2928853Sandreas.hansson@arm.com                                            sizeof(uint64_t));
293857SN/A
29414010Sgabeblack@google.com                    dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) |
29514010Sgabeblack@google.com                              (busAddr & ULL(0x1fff));
296857SN/A
297857SN/A                } else {
298896SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
299857SN/A                    tbaMask = ~baMask;
300857SN/A                    dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
301857SN/A                }
302857SN/A
303857SN/A                return (dmaAddr & DMA_ADDR_MASK);
304835SN/A            }
305835SN/A        }
306835SN/A    }
307835SN/A
308896SN/A    // if no match was found, then return the original address
309896SN/A    return busAddr;
310835SN/A}
3115834Sgblack@eecs.umich.edu
312768SN/Avoid
31310905Sandreas.sandberg@arm.comTsunamiPChip::serialize(CheckpointOut &cp) const
314768SN/A{
315896SN/A    SERIALIZE_SCALAR(pctl);
316835SN/A    SERIALIZE_ARRAY(wsba, 4);
317835SN/A    SERIALIZE_ARRAY(wsm, 4);
318835SN/A    SERIALIZE_ARRAY(tba, 4);
319768SN/A}
320768SN/A
321768SN/Avoid
32210905Sandreas.sandberg@arm.comTsunamiPChip::unserialize(CheckpointIn &cp)
323768SN/A{
324896SN/A    UNSERIALIZE_SCALAR(pctl);
325835SN/A    UNSERIALIZE_ARRAY(wsba, 4);
326835SN/A    UNSERIALIZE_ARRAY(wsm, 4);
327835SN/A    UNSERIALIZE_ARRAY(tba, 4);
328768SN/A}
329768SN/A
330909SN/A
3314762Snate@binkert.orgTsunamiPChip *
3324762Snate@binkert.orgTsunamiPChipParams::create()
333768SN/A{
3344762Snate@binkert.org    return new TsunamiPChip(this);
335768SN/A}
336