tsunami_pchip.cc revision 3846
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 */ 35768SN/A 36768SN/A#include <deque> 37768SN/A#include <string> 38768SN/A#include <vector> 39768SN/A 40768SN/A#include "base/trace.hh" 413540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_pchip.hh" 423540Sgblack@eecs.umich.edu#include "dev/alpha/tsunamireg.h" 433540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami.hh" 442542SN/A#include "mem/packet.hh" 453348SN/A#include "mem/packet_access.hh" 46768SN/A#include "sim/builder.hh" 47768SN/A#include "sim/system.hh" 48768SN/A 49768SN/Ausing namespace std; 502107SN/A//Should this be AlphaISA? 512107SN/Ausing namespace TheISA; 52768SN/A 532539SN/ATsunamiPChip::TsunamiPChip(Params *p) 542542SN/A: BasicPioDevice(p) 55768SN/A{ 563846Shsul@eecs.umich.edu pioSize = 0x1000; 57809SN/A 58835SN/A for (int i = 0; i < 4; i++) { 59835SN/A wsba[i] = 0; 60835SN/A wsm[i] = 0; 61835SN/A tba[i] = 0; 62835SN/A } 63768SN/A 64896SN/A // initialize pchip control register 65896SN/A pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 66896SN/A 67775SN/A //Set back pointer in tsunami 682539SN/A p->tsunami->pchip = this; 692539SN/A} 702539SN/A 712539SN/ATick 723349SN/ATsunamiPChip::read(PacketPtr pkt) 732539SN/A{ 742641SN/A assert(pkt->result == Packet::Unknown); 752641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 762539SN/A 772630SN/A pkt->allocate(); 782641SN/A Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; 792641SN/A assert(pkt->getSize() == sizeof(uint64_t)); 802539SN/A 812539SN/A 822641SN/A DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); 832539SN/A 842539SN/A switch(daddr) { 852539SN/A case TSDEV_PC_WSBA0: 862630SN/A pkt->set(wsba[0]); 872539SN/A break; 882539SN/A case TSDEV_PC_WSBA1: 892630SN/A pkt->set(wsba[1]); 902539SN/A break; 912539SN/A case TSDEV_PC_WSBA2: 922630SN/A pkt->set(wsba[2]); 932539SN/A break; 942539SN/A case TSDEV_PC_WSBA3: 952630SN/A pkt->set(wsba[3]); 962539SN/A break; 972539SN/A case TSDEV_PC_WSM0: 982630SN/A pkt->set(wsm[0]); 992539SN/A break; 1002539SN/A case TSDEV_PC_WSM1: 1012630SN/A pkt->set(wsm[1]); 1022539SN/A break; 1032539SN/A case TSDEV_PC_WSM2: 1042630SN/A pkt->set(wsm[2]); 1052539SN/A break; 1062539SN/A case TSDEV_PC_WSM3: 1072630SN/A pkt->set(wsm[3]); 1082539SN/A break; 1092539SN/A case TSDEV_PC_TBA0: 1102630SN/A pkt->set(tba[0]); 1112539SN/A break; 1122539SN/A case TSDEV_PC_TBA1: 1132630SN/A pkt->set(tba[1]); 1142539SN/A break; 1152539SN/A case TSDEV_PC_TBA2: 1162630SN/A pkt->set(tba[2]); 1172539SN/A break; 1182542SN/A case TSDEV_PC_TBA3: 1192630SN/A pkt->set(tba[3]); 1202539SN/A break; 1212539SN/A case TSDEV_PC_PCTL: 1222630SN/A pkt->set(pctl); 1232539SN/A break; 1242539SN/A case TSDEV_PC_PLAT: 1252539SN/A panic("PC_PLAT not implemented\n"); 1262539SN/A case TSDEV_PC_RES: 1272539SN/A panic("PC_RES not implemented\n"); 1282539SN/A case TSDEV_PC_PERROR: 1292630SN/A pkt->set((uint64_t)0x00); 1302539SN/A break; 1312539SN/A case TSDEV_PC_PERRMASK: 1322630SN/A pkt->set((uint64_t)0x00); 1332539SN/A break; 1342539SN/A case TSDEV_PC_PERRSET: 1352539SN/A panic("PC_PERRSET not implemented\n"); 1362539SN/A case TSDEV_PC_TLBIV: 1372539SN/A panic("PC_TLBIV not implemented\n"); 1382539SN/A case TSDEV_PC_TLBIA: 1392630SN/A pkt->set((uint64_t)0x00); // shouldn't be readable, but linux 1402539SN/A break; 1412539SN/A case TSDEV_PC_PMONCTL: 1422539SN/A panic("PC_PMONCTL not implemented\n"); 1432539SN/A case TSDEV_PC_PMONCNT: 1442539SN/A panic("PC_PMONCTN not implemented\n"); 1452539SN/A default: 1462539SN/A panic("Default in PChip Read reached reading 0x%x\n", daddr); 1472539SN/A } 1482641SN/A pkt->result = Packet::Success; 1492539SN/A return pioDelay; 1502539SN/A 151768SN/A} 152768SN/A 1532542SN/ATick 1543349SN/ATsunamiPChip::write(PacketPtr pkt) 155768SN/A{ 1562641SN/A assert(pkt->result == Packet::Unknown); 1572641SN/A assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1582641SN/A Addr daddr = (pkt->getAddr() - pioAddr) >> 6; 159768SN/A 1602641SN/A assert(pkt->getSize() == sizeof(uint64_t)); 161768SN/A 1622641SN/A DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); 163768SN/A 1642539SN/A switch(daddr) { 1652539SN/A case TSDEV_PC_WSBA0: 1662630SN/A wsba[0] = pkt->get<uint64_t>(); 1672539SN/A break; 1682539SN/A case TSDEV_PC_WSBA1: 1692630SN/A wsba[1] = pkt->get<uint64_t>(); 1702539SN/A break; 1712539SN/A case TSDEV_PC_WSBA2: 1722630SN/A wsba[2] = pkt->get<uint64_t>(); 1732539SN/A break; 1742539SN/A case TSDEV_PC_WSBA3: 1752630SN/A wsba[3] = pkt->get<uint64_t>(); 1762539SN/A break; 1772539SN/A case TSDEV_PC_WSM0: 1782630SN/A wsm[0] = pkt->get<uint64_t>(); 1792539SN/A break; 1802539SN/A case TSDEV_PC_WSM1: 1812630SN/A wsm[1] = pkt->get<uint64_t>(); 1822539SN/A break; 1832539SN/A case TSDEV_PC_WSM2: 1842630SN/A wsm[2] = pkt->get<uint64_t>(); 1852539SN/A break; 1862539SN/A case TSDEV_PC_WSM3: 1872630SN/A wsm[3] = pkt->get<uint64_t>(); 1882539SN/A break; 1892539SN/A case TSDEV_PC_TBA0: 1902630SN/A tba[0] = pkt->get<uint64_t>(); 1912539SN/A break; 1922539SN/A case TSDEV_PC_TBA1: 1932630SN/A tba[1] = pkt->get<uint64_t>(); 1942539SN/A break; 1952539SN/A case TSDEV_PC_TBA2: 1962630SN/A tba[2] = pkt->get<uint64_t>(); 1972539SN/A break; 1982539SN/A case TSDEV_PC_TBA3: 1992630SN/A tba[3] = pkt->get<uint64_t>(); 2002539SN/A break; 2012539SN/A case TSDEV_PC_PCTL: 2022630SN/A pctl = pkt->get<uint64_t>(); 2032539SN/A break; 2042539SN/A case TSDEV_PC_PLAT: 2052539SN/A panic("PC_PLAT not implemented\n"); 2062539SN/A case TSDEV_PC_RES: 2072539SN/A panic("PC_RES not implemented\n"); 2082539SN/A case TSDEV_PC_PERROR: 2092539SN/A break; 2102539SN/A case TSDEV_PC_PERRMASK: 2112539SN/A panic("PC_PERRMASK not implemented\n"); 2122539SN/A case TSDEV_PC_PERRSET: 2132539SN/A panic("PC_PERRSET not implemented\n"); 2142539SN/A case TSDEV_PC_TLBIV: 2152539SN/A panic("PC_TLBIV not implemented\n"); 2162539SN/A case TSDEV_PC_TLBIA: 2172539SN/A break; // value ignored, supposted to invalidate SG TLB 2182539SN/A case TSDEV_PC_PMONCTL: 2192539SN/A panic("PC_PMONCTL not implemented\n"); 2202539SN/A case TSDEV_PC_PMONCNT: 2212539SN/A panic("PC_PMONCTN not implemented\n"); 2222539SN/A default: 2232549SN/A panic("Default in PChip write reached reading 0x%x\n", daddr); 224768SN/A 2252539SN/A } // uint64_t 226768SN/A 2272641SN/A pkt->result = Packet::Success; 2282539SN/A return pioDelay; 229768SN/A} 230768SN/A 231857SN/A#define DMA_ADDR_MASK ULL(0x3ffffffff) 232857SN/A 233835SN/AAddr 234835SN/ATsunamiPChip::translatePciToDma(Addr busAddr) 235835SN/A{ 236835SN/A // compare the address to the window base registers 237857SN/A uint64_t tbaMask = 0; 238857SN/A uint64_t baMask = 0; 239857SN/A 240835SN/A uint64_t windowMask = 0; 241835SN/A uint64_t windowBase = 0; 242857SN/A 243857SN/A uint64_t pteEntry = 0; 244857SN/A 245857SN/A Addr pteAddr; 246835SN/A Addr dmaAddr; 247835SN/A 248896SN/A#if 0 249896SN/A DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 250835SN/A for (int i = 0; i < 4; i++) { 251896SN/A DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 252896SN/A i, wsba[i], wsm[i]); 253896SN/A 254835SN/A windowBase = wsba[i]; 255896SN/A windowMask = ~wsm[i] & (ULL(0xfff) << 20); 256835SN/A 257835SN/A if ((busAddr & windowMask) == (windowBase & windowMask)) { 258896SN/A DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 259896SN/A i, windowBase, windowMask, (busAddr & windowMask), 260896SN/A (windowBase & windowMask)); 261896SN/A } 262896SN/A } 263896SN/A#endif 264857SN/A 265896SN/A for (int i = 0; i < 4; i++) { 266896SN/A 267896SN/A windowBase = wsba[i]; 268896SN/A windowMask = ~wsm[i] & (ULL(0xfff) << 20); 269896SN/A 270896SN/A if ((busAddr & windowMask) == (windowBase & windowMask)) { 271835SN/A 272835SN/A if (wsba[i] & 0x1) { // see if enabled 273857SN/A if (wsba[i] & 0x2) { // see if SG bit is set 274857SN/A /** @todo 275857SN/A This currently is faked by just doing a direct 276857SN/A read from memory, however, to be realistic, this 277857SN/A needs to actually do a bus transaction. The process 278857SN/A is explained in the tsunami documentation on page 279857SN/A 10-12 and basically munges the address to look up a 280857SN/A PTE from a table in memory and then uses that mapping 281857SN/A to create an address for the SG page 282857SN/A */ 283835SN/A 284896SN/A tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 285896SN/A baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 286857SN/A pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 287857SN/A 2882542SN/A pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t)); 289857SN/A 290896SN/A dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 291857SN/A 292857SN/A } else { 293896SN/A baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 294857SN/A tbaMask = ~baMask; 295857SN/A dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 296857SN/A } 297857SN/A 298857SN/A return (dmaAddr & DMA_ADDR_MASK); 299835SN/A } 300835SN/A } 301835SN/A } 302835SN/A 303896SN/A // if no match was found, then return the original address 304896SN/A return busAddr; 305835SN/A} 3062846SN/AAddr 3072846SN/ATsunamiPChip::calcConfigAddr(int bus, int dev, int func) 3082846SN/A{ 3092846SN/A assert(func < 8); 3102846SN/A assert(dev < 32); 3112846SN/A assert(bus == 0); 3122846SN/A 3132846SN/A return TsunamiPciBus0Config | (func << 8) | (dev << 11); 3142846SN/A} 3152846SN/A 3162846SN/A 317835SN/A 318768SN/Avoid 319768SN/ATsunamiPChip::serialize(std::ostream &os) 320768SN/A{ 321896SN/A SERIALIZE_SCALAR(pctl); 322835SN/A SERIALIZE_ARRAY(wsba, 4); 323835SN/A SERIALIZE_ARRAY(wsm, 4); 324835SN/A SERIALIZE_ARRAY(tba, 4); 325768SN/A} 326768SN/A 327768SN/Avoid 328768SN/ATsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 329768SN/A{ 330896SN/A UNSERIALIZE_SCALAR(pctl); 331835SN/A UNSERIALIZE_ARRAY(wsba, 4); 332835SN/A UNSERIALIZE_ARRAY(wsm, 4); 333835SN/A UNSERIALIZE_ARRAY(tba, 4); 334768SN/A} 335768SN/A 336909SN/A 337768SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 338768SN/A 3392539SN/A Param<Addr> pio_addr; 3402539SN/A Param<Tick> pio_latency; 3412539SN/A SimObjectParam<Platform *> platform; 3422539SN/A SimObjectParam<System *> system; 343775SN/A SimObjectParam<Tsunami *> tsunami; 344768SN/A 345768SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 346768SN/A 347768SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 348768SN/A 3492539SN/A INIT_PARAM(pio_addr, "Device Address"), 3502539SN/A INIT_PARAM(pio_latency, "Programmed IO latency"), 3512539SN/A INIT_PARAM(platform, "platform"), 3522539SN/A INIT_PARAM(system, "system object"), 3532539SN/A INIT_PARAM(tsunami, "Tsunami") 354768SN/A 355768SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 356768SN/A 357768SN/ACREATE_SIM_OBJECT(TsunamiPChip) 358768SN/A{ 3592539SN/A TsunamiPChip::Params *p = new TsunamiPChip::Params; 3602539SN/A p->name = getInstanceName(); 3612539SN/A p->pio_addr = pio_addr; 3622539SN/A p->pio_delay = pio_latency; 3632539SN/A p->platform = platform; 3642539SN/A p->system = system; 3652539SN/A p->tsunami = tsunami; 3662539SN/A return new TsunamiPChip(p); 367768SN/A} 368768SN/A 369768SN/AREGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 370