tsunami_pchip.cc revision 2542
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 29/** @file 30 * Tsunami PChip (pci) 31 */ 32 33#include <deque> 34#include <string> 35#include <vector> 36 37#include "base/trace.hh" 38#include "dev/tsunami_pchip.hh" 39#include "dev/tsunamireg.h" 40#include "dev/tsunami.hh" 41#include "mem/packet.hh" 42#include "sim/builder.hh" 43#include "sim/system.hh" 44 45using namespace std; 46//Should this be AlphaISA? 47using namespace TheISA; 48 49TsunamiPChip::TsunamiPChip(Params *p) 50: BasicPioDevice(p) 51{ 52 pioSize = 0xfff; 53 54 for (int i = 0; i < 4; i++) { 55 wsba[i] = 0; 56 wsm[i] = 0; 57 tba[i] = 0; 58 } 59 60 // initialize pchip control register 61 pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 62 63 //Set back pointer in tsunami 64 p->tsunami->pchip = this; 65} 66 67Tick 68TsunamiPChip::read(Packet &pkt) 69{ 70 assert(pkt.result == Unknown); 71 assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); 72 73 pkt.time = curTick + pioDelay; 74 Addr daddr = pkt.addr - pioAddr; 75 76 uint64_t *data64; 77 78 if (!pkt.data) { 79 data64 = new uint64_t; 80 pkt.data = (uint8_t*)data64; 81 } else 82 data64 = (uint64_t*)pkt.data; 83 84 DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size); 85 86 switch(daddr) { 87 case TSDEV_PC_WSBA0: 88 *data64 = wsba[0]; 89 break; 90 case TSDEV_PC_WSBA1: 91 *data64 = wsba[1]; 92 break; 93 case TSDEV_PC_WSBA2: 94 *data64 = wsba[2]; 95 break; 96 case TSDEV_PC_WSBA3: 97 *data64 = wsba[3]; 98 break; 99 case TSDEV_PC_WSM0: 100 *data64 = wsm[0]; 101 break; 102 case TSDEV_PC_WSM1: 103 *data64 = wsm[1]; 104 break; 105 case TSDEV_PC_WSM2: 106 *data64 = wsm[2]; 107 break; 108 case TSDEV_PC_WSM3: 109 *data64 = wsm[3]; 110 break; 111 case TSDEV_PC_TBA0: 112 *data64 = tba[0]; 113 break; 114 case TSDEV_PC_TBA1: 115 *data64 = tba[1]; 116 break; 117 case TSDEV_PC_TBA2: 118 *data64 = tba[2]; 119 break; 120 case TSDEV_PC_TBA3: 121 *data64 = tba[3]; 122 break; 123 case TSDEV_PC_PCTL: 124 *data64 = pctl; 125 break; 126 case TSDEV_PC_PLAT: 127 panic("PC_PLAT not implemented\n"); 128 case TSDEV_PC_RES: 129 panic("PC_RES not implemented\n"); 130 case TSDEV_PC_PERROR: 131 *data64 = 0x00; 132 break; 133 case TSDEV_PC_PERRMASK: 134 *data64 = 0x00; 135 break; 136 case TSDEV_PC_PERRSET: 137 panic("PC_PERRSET not implemented\n"); 138 case TSDEV_PC_TLBIV: 139 panic("PC_TLBIV not implemented\n"); 140 case TSDEV_PC_TLBIA: 141 *data64 = 0x00; // shouldn't be readable, but linux 142 break; 143 case TSDEV_PC_PMONCTL: 144 panic("PC_PMONCTL not implemented\n"); 145 case TSDEV_PC_PMONCNT: 146 panic("PC_PMONCTN not implemented\n"); 147 default: 148 panic("Default in PChip Read reached reading 0x%x\n", daddr); 149 } 150 pkt.result = Success; 151 return pioDelay; 152 153} 154 155Tick 156TsunamiPChip::write(Packet &pkt) 157{ 158 pkt.time = curTick + pioDelay; 159 160 assert(pkt.result == Unknown); 161 assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); 162 Addr daddr = pkt.addr - pioAddr; 163 164 uint64_t data64 = *(uint64_t *)pkt.data; 165 assert(pkt.size == sizeof(uint64_t)); 166 167 DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size); 168 169 switch(daddr) { 170 case TSDEV_PC_WSBA0: 171 wsba[0] = data64; 172 break; 173 case TSDEV_PC_WSBA1: 174 wsba[1] = data64; 175 break; 176 case TSDEV_PC_WSBA2: 177 wsba[2] = data64; 178 break; 179 case TSDEV_PC_WSBA3: 180 wsba[3] = data64; 181 break; 182 case TSDEV_PC_WSM0: 183 wsm[0] = data64; 184 break; 185 case TSDEV_PC_WSM1: 186 wsm[1] = data64; 187 break; 188 case TSDEV_PC_WSM2: 189 wsm[2] = data64; 190 break; 191 case TSDEV_PC_WSM3: 192 wsm[3] = data64; 193 break; 194 case TSDEV_PC_TBA0: 195 tba[0] = data64; 196 break; 197 case TSDEV_PC_TBA1: 198 tba[1] = data64; 199 break; 200 case TSDEV_PC_TBA2: 201 tba[2] = data64; 202 break; 203 case TSDEV_PC_TBA3: 204 tba[3] = data64; 205 break; 206 case TSDEV_PC_PCTL: 207 pctl = data64; 208 break; 209 case TSDEV_PC_PLAT: 210 panic("PC_PLAT not implemented\n"); 211 case TSDEV_PC_RES: 212 panic("PC_RES not implemented\n"); 213 case TSDEV_PC_PERROR: 214 break; 215 case TSDEV_PC_PERRMASK: 216 panic("PC_PERRMASK not implemented\n"); 217 case TSDEV_PC_PERRSET: 218 panic("PC_PERRSET not implemented\n"); 219 case TSDEV_PC_TLBIV: 220 panic("PC_TLBIV not implemented\n"); 221 case TSDEV_PC_TLBIA: 222 break; // value ignored, supposted to invalidate SG TLB 223 case TSDEV_PC_PMONCTL: 224 panic("PC_PMONCTL not implemented\n"); 225 case TSDEV_PC_PMONCNT: 226 panic("PC_PMONCTN not implemented\n"); 227 default: 228 panic("Default in PChip Read reached reading 0x%x\n", daddr); 229 230 } // uint64_t 231 232 pkt.result = Success; 233 return pioDelay; 234} 235 236#define DMA_ADDR_MASK ULL(0x3ffffffff) 237 238Addr 239TsunamiPChip::translatePciToDma(Addr busAddr) 240{ 241 // compare the address to the window base registers 242 uint64_t tbaMask = 0; 243 uint64_t baMask = 0; 244 245 uint64_t windowMask = 0; 246 uint64_t windowBase = 0; 247 248 uint64_t pteEntry = 0; 249 250 Addr pteAddr; 251 Addr dmaAddr; 252 253#if 0 254 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 255 for (int i = 0; i < 4; i++) { 256 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 257 i, wsba[i], wsm[i]); 258 259 windowBase = wsba[i]; 260 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 261 262 if ((busAddr & windowMask) == (windowBase & windowMask)) { 263 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 264 i, windowBase, windowMask, (busAddr & windowMask), 265 (windowBase & windowMask)); 266 } 267 } 268#endif 269 270 for (int i = 0; i < 4; i++) { 271 272 windowBase = wsba[i]; 273 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 274 275 if ((busAddr & windowMask) == (windowBase & windowMask)) { 276 277 if (wsba[i] & 0x1) { // see if enabled 278 if (wsba[i] & 0x2) { // see if SG bit is set 279 /** @todo 280 This currently is faked by just doing a direct 281 read from memory, however, to be realistic, this 282 needs to actually do a bus transaction. The process 283 is explained in the tsunami documentation on page 284 10-12 and basically munges the address to look up a 285 PTE from a table in memory and then uses that mapping 286 to create an address for the SG page 287 */ 288 289 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 290 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 291 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 292 293 pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t)); 294 295 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 296 297 } else { 298 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 299 tbaMask = ~baMask; 300 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 301 } 302 303 return (dmaAddr & DMA_ADDR_MASK); 304 } 305 } 306 } 307 308 // if no match was found, then return the original address 309 return busAddr; 310} 311 312void 313TsunamiPChip::serialize(std::ostream &os) 314{ 315 SERIALIZE_SCALAR(pctl); 316 SERIALIZE_ARRAY(wsba, 4); 317 SERIALIZE_ARRAY(wsm, 4); 318 SERIALIZE_ARRAY(tba, 4); 319} 320 321void 322TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 323{ 324 UNSERIALIZE_SCALAR(pctl); 325 UNSERIALIZE_ARRAY(wsba, 4); 326 UNSERIALIZE_ARRAY(wsm, 4); 327 UNSERIALIZE_ARRAY(tba, 4); 328} 329 330 331BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 332 333 Param<Addr> pio_addr; 334 Param<Tick> pio_latency; 335 SimObjectParam<Platform *> platform; 336 SimObjectParam<System *> system; 337 SimObjectParam<Tsunami *> tsunami; 338 339END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 340 341BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 342 343 INIT_PARAM(pio_addr, "Device Address"), 344 INIT_PARAM(pio_latency, "Programmed IO latency"), 345 INIT_PARAM(platform, "platform"), 346 INIT_PARAM(system, "system object"), 347 INIT_PARAM(tsunami, "Tsunami") 348 349END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 350 351CREATE_SIM_OBJECT(TsunamiPChip) 352{ 353 TsunamiPChip::Params *p = new TsunamiPChip::Params; 354 p->name = getInstanceName(); 355 p->pio_addr = pio_addr; 356 p->pio_delay = pio_latency; 357 p->platform = platform; 358 p->system = system; 359 p->tsunami = tsunami; 360 return new TsunamiPChip(p); 361} 362 363REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 364