tsunami_pchip.cc revision 10905
1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Andrew Schultz 30 */ 31 32/** @file 33 * Tsunami PChip (pci) 34 */ 35 36#include <deque> 37#include <string> 38#include <vector> 39 40#include "base/trace.hh" 41#include "config/the_isa.hh" 42#include "debug/Tsunami.hh" 43#include "dev/alpha/tsunami.hh" 44#include "dev/alpha/tsunami_pchip.hh" 45#include "dev/alpha/tsunamireg.h" 46#include "mem/packet.hh" 47#include "mem/packet_access.hh" 48#include "sim/system.hh" 49 50using namespace std; 51//Should this be AlphaISA? 52using namespace TheISA; 53 54TsunamiPChip::TsunamiPChip(const Params *p) 55 : BasicPioDevice(p, 0x1000) 56{ 57 for (int i = 0; i < 4; i++) { 58 wsba[i] = 0; 59 wsm[i] = 0; 60 tba[i] = 0; 61 } 62 63 // initialize pchip control register 64 pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 65 66 //Set back pointer in tsunami 67 p->tsunami->pchip = this; 68} 69 70Tick 71TsunamiPChip::read(PacketPtr pkt) 72{ 73 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 74 75 Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; 76 assert(pkt->getSize() == sizeof(uint64_t)); 77 78 79 DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); 80 81 switch(daddr) { 82 case TSDEV_PC_WSBA0: 83 pkt->set(wsba[0]); 84 break; 85 case TSDEV_PC_WSBA1: 86 pkt->set(wsba[1]); 87 break; 88 case TSDEV_PC_WSBA2: 89 pkt->set(wsba[2]); 90 break; 91 case TSDEV_PC_WSBA3: 92 pkt->set(wsba[3]); 93 break; 94 case TSDEV_PC_WSM0: 95 pkt->set(wsm[0]); 96 break; 97 case TSDEV_PC_WSM1: 98 pkt->set(wsm[1]); 99 break; 100 case TSDEV_PC_WSM2: 101 pkt->set(wsm[2]); 102 break; 103 case TSDEV_PC_WSM3: 104 pkt->set(wsm[3]); 105 break; 106 case TSDEV_PC_TBA0: 107 pkt->set(tba[0]); 108 break; 109 case TSDEV_PC_TBA1: 110 pkt->set(tba[1]); 111 break; 112 case TSDEV_PC_TBA2: 113 pkt->set(tba[2]); 114 break; 115 case TSDEV_PC_TBA3: 116 pkt->set(tba[3]); 117 break; 118 case TSDEV_PC_PCTL: 119 pkt->set(pctl); 120 break; 121 case TSDEV_PC_PLAT: 122 panic("PC_PLAT not implemented\n"); 123 case TSDEV_PC_RES: 124 panic("PC_RES not implemented\n"); 125 case TSDEV_PC_PERROR: 126 pkt->set((uint64_t)0x00); 127 break; 128 case TSDEV_PC_PERRMASK: 129 pkt->set((uint64_t)0x00); 130 break; 131 case TSDEV_PC_PERRSET: 132 panic("PC_PERRSET not implemented\n"); 133 case TSDEV_PC_TLBIV: 134 panic("PC_TLBIV not implemented\n"); 135 case TSDEV_PC_TLBIA: 136 pkt->set((uint64_t)0x00); // shouldn't be readable, but linux 137 break; 138 case TSDEV_PC_PMONCTL: 139 panic("PC_PMONCTL not implemented\n"); 140 case TSDEV_PC_PMONCNT: 141 panic("PC_PMONCTN not implemented\n"); 142 default: 143 panic("Default in PChip Read reached reading 0x%x\n", daddr); 144 } 145 pkt->makeAtomicResponse(); 146 return pioDelay; 147 148} 149 150Tick 151TsunamiPChip::write(PacketPtr pkt) 152{ 153 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 154 Addr daddr = (pkt->getAddr() - pioAddr) >> 6; 155 156 assert(pkt->getSize() == sizeof(uint64_t)); 157 158 DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); 159 160 switch(daddr) { 161 case TSDEV_PC_WSBA0: 162 wsba[0] = pkt->get<uint64_t>(); 163 break; 164 case TSDEV_PC_WSBA1: 165 wsba[1] = pkt->get<uint64_t>(); 166 break; 167 case TSDEV_PC_WSBA2: 168 wsba[2] = pkt->get<uint64_t>(); 169 break; 170 case TSDEV_PC_WSBA3: 171 wsba[3] = pkt->get<uint64_t>(); 172 break; 173 case TSDEV_PC_WSM0: 174 wsm[0] = pkt->get<uint64_t>(); 175 break; 176 case TSDEV_PC_WSM1: 177 wsm[1] = pkt->get<uint64_t>(); 178 break; 179 case TSDEV_PC_WSM2: 180 wsm[2] = pkt->get<uint64_t>(); 181 break; 182 case TSDEV_PC_WSM3: 183 wsm[3] = pkt->get<uint64_t>(); 184 break; 185 case TSDEV_PC_TBA0: 186 tba[0] = pkt->get<uint64_t>(); 187 break; 188 case TSDEV_PC_TBA1: 189 tba[1] = pkt->get<uint64_t>(); 190 break; 191 case TSDEV_PC_TBA2: 192 tba[2] = pkt->get<uint64_t>(); 193 break; 194 case TSDEV_PC_TBA3: 195 tba[3] = pkt->get<uint64_t>(); 196 break; 197 case TSDEV_PC_PCTL: 198 pctl = pkt->get<uint64_t>(); 199 break; 200 case TSDEV_PC_PLAT: 201 panic("PC_PLAT not implemented\n"); 202 case TSDEV_PC_RES: 203 panic("PC_RES not implemented\n"); 204 case TSDEV_PC_PERROR: 205 break; 206 case TSDEV_PC_PERRMASK: 207 panic("PC_PERRMASK not implemented\n"); 208 case TSDEV_PC_PERRSET: 209 panic("PC_PERRSET not implemented\n"); 210 case TSDEV_PC_TLBIV: 211 panic("PC_TLBIV not implemented\n"); 212 case TSDEV_PC_TLBIA: 213 break; // value ignored, supposted to invalidate SG TLB 214 case TSDEV_PC_PMONCTL: 215 panic("PC_PMONCTL not implemented\n"); 216 case TSDEV_PC_PMONCNT: 217 panic("PC_PMONCTN not implemented\n"); 218 default: 219 panic("Default in PChip write reached reading 0x%x\n", daddr); 220 221 } // uint64_t 222 223 pkt->makeAtomicResponse(); 224 return pioDelay; 225} 226 227#define DMA_ADDR_MASK ULL(0x3ffffffff) 228 229Addr 230TsunamiPChip::translatePciToDma(Addr busAddr) 231{ 232 // compare the address to the window base registers 233 uint64_t tbaMask = 0; 234 uint64_t baMask = 0; 235 236 uint64_t windowMask = 0; 237 uint64_t windowBase = 0; 238 239 uint64_t pteEntry = 0; 240 241 Addr pteAddr; 242 Addr dmaAddr; 243 244#if 0 245 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 246 for (int i = 0; i < 4; i++) { 247 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 248 i, wsba[i], wsm[i]); 249 250 windowBase = wsba[i]; 251 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 252 253 if ((busAddr & windowMask) == (windowBase & windowMask)) { 254 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 255 i, windowBase, windowMask, (busAddr & windowMask), 256 (windowBase & windowMask)); 257 } 258 } 259#endif 260 261 for (int i = 0; i < 4; i++) { 262 263 windowBase = wsba[i]; 264 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 265 266 if ((busAddr & windowMask) == (windowBase & windowMask)) { 267 268 if (wsba[i] & 0x1) { // see if enabled 269 if (wsba[i] & 0x2) { // see if SG bit is set 270 /** @todo 271 This currently is faked by just doing a direct 272 read from memory, however, to be realistic, this 273 needs to actually do a bus transaction. The process 274 is explained in the tsunami documentation on page 275 10-12 and basically munges the address to look up a 276 PTE from a table in memory and then uses that mapping 277 to create an address for the SG page 278 */ 279 280 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 281 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 282 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 283 284 sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry, 285 sizeof(uint64_t)); 286 287 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 288 289 } else { 290 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 291 tbaMask = ~baMask; 292 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 293 } 294 295 return (dmaAddr & DMA_ADDR_MASK); 296 } 297 } 298 } 299 300 // if no match was found, then return the original address 301 return busAddr; 302} 303 304Addr 305TsunamiPChip::calcConfigAddr(int bus, int dev, int func) 306{ 307 assert(func < 8); 308 assert(dev < 32); 309 assert(bus == 0); 310 311 return TsunamiPciBus0Config | (func << 8) | (dev << 11); 312} 313 314Addr 315TsunamiPChip::calcIOAddr(Addr addr) 316{ 317 return TSUNAMI_PCI0_IO + addr; 318} 319 320Addr 321TsunamiPChip::calcMemAddr(Addr addr) 322{ 323 return TSUNAMI_PCI0_MEMORY + addr; 324} 325 326void 327TsunamiPChip::serialize(CheckpointOut &cp) const 328{ 329 SERIALIZE_SCALAR(pctl); 330 SERIALIZE_ARRAY(wsba, 4); 331 SERIALIZE_ARRAY(wsm, 4); 332 SERIALIZE_ARRAY(tba, 4); 333} 334 335void 336TsunamiPChip::unserialize(CheckpointIn &cp) 337{ 338 UNSERIALIZE_SCALAR(pctl); 339 UNSERIALIZE_ARRAY(wsba, 4); 340 UNSERIALIZE_ARRAY(wsm, 4); 341 UNSERIALIZE_ARRAY(tba, 4); 342} 343 344 345TsunamiPChip * 346TsunamiPChipParams::create() 347{ 348 return new TsunamiPChip(this); 349} 350