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