tsunami_pchip.cc revision 9808
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 pkt->allocate(); 76 Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; 77 assert(pkt->getSize() == sizeof(uint64_t)); 78 79 80 DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); 81 82 switch(daddr) { 83 case TSDEV_PC_WSBA0: 84 pkt->set(wsba[0]); 85 break; 86 case TSDEV_PC_WSBA1: 87 pkt->set(wsba[1]); 88 break; 89 case TSDEV_PC_WSBA2: 90 pkt->set(wsba[2]); 91 break; 92 case TSDEV_PC_WSBA3: 93 pkt->set(wsba[3]); 94 break; 95 case TSDEV_PC_WSM0: 96 pkt->set(wsm[0]); 97 break; 98 case TSDEV_PC_WSM1: 99 pkt->set(wsm[1]); 100 break; 101 case TSDEV_PC_WSM2: 102 pkt->set(wsm[2]); 103 break; 104 case TSDEV_PC_WSM3: 105 pkt->set(wsm[3]); 106 break; 107 case TSDEV_PC_TBA0: 108 pkt->set(tba[0]); 109 break; 110 case TSDEV_PC_TBA1: 111 pkt->set(tba[1]); 112 break; 113 case TSDEV_PC_TBA2: 114 pkt->set(tba[2]); 115 break; 116 case TSDEV_PC_TBA3: 117 pkt->set(tba[3]); 118 break; 119 case TSDEV_PC_PCTL: 120 pkt->set(pctl); 121 break; 122 case TSDEV_PC_PLAT: 123 panic("PC_PLAT not implemented\n"); 124 case TSDEV_PC_RES: 125 panic("PC_RES not implemented\n"); 126 case TSDEV_PC_PERROR: 127 pkt->set((uint64_t)0x00); 128 break; 129 case TSDEV_PC_PERRMASK: 130 pkt->set((uint64_t)0x00); 131 break; 132 case TSDEV_PC_PERRSET: 133 panic("PC_PERRSET not implemented\n"); 134 case TSDEV_PC_TLBIV: 135 panic("PC_TLBIV not implemented\n"); 136 case TSDEV_PC_TLBIA: 137 pkt->set((uint64_t)0x00); // shouldn't be readable, but linux 138 break; 139 case TSDEV_PC_PMONCTL: 140 panic("PC_PMONCTL not implemented\n"); 141 case TSDEV_PC_PMONCNT: 142 panic("PC_PMONCTN not implemented\n"); 143 default: 144 panic("Default in PChip Read reached reading 0x%x\n", daddr); 145 } 146 pkt->makeAtomicResponse(); 147 return pioDelay; 148 149} 150 151Tick 152TsunamiPChip::write(PacketPtr pkt) 153{ 154 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 155 Addr daddr = (pkt->getAddr() - pioAddr) >> 6; 156 157 assert(pkt->getSize() == sizeof(uint64_t)); 158 159 DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); 160 161 switch(daddr) { 162 case TSDEV_PC_WSBA0: 163 wsba[0] = pkt->get<uint64_t>(); 164 break; 165 case TSDEV_PC_WSBA1: 166 wsba[1] = pkt->get<uint64_t>(); 167 break; 168 case TSDEV_PC_WSBA2: 169 wsba[2] = pkt->get<uint64_t>(); 170 break; 171 case TSDEV_PC_WSBA3: 172 wsba[3] = pkt->get<uint64_t>(); 173 break; 174 case TSDEV_PC_WSM0: 175 wsm[0] = pkt->get<uint64_t>(); 176 break; 177 case TSDEV_PC_WSM1: 178 wsm[1] = pkt->get<uint64_t>(); 179 break; 180 case TSDEV_PC_WSM2: 181 wsm[2] = pkt->get<uint64_t>(); 182 break; 183 case TSDEV_PC_WSM3: 184 wsm[3] = pkt->get<uint64_t>(); 185 break; 186 case TSDEV_PC_TBA0: 187 tba[0] = pkt->get<uint64_t>(); 188 break; 189 case TSDEV_PC_TBA1: 190 tba[1] = pkt->get<uint64_t>(); 191 break; 192 case TSDEV_PC_TBA2: 193 tba[2] = pkt->get<uint64_t>(); 194 break; 195 case TSDEV_PC_TBA3: 196 tba[3] = pkt->get<uint64_t>(); 197 break; 198 case TSDEV_PC_PCTL: 199 pctl = pkt->get<uint64_t>(); 200 break; 201 case TSDEV_PC_PLAT: 202 panic("PC_PLAT not implemented\n"); 203 case TSDEV_PC_RES: 204 panic("PC_RES not implemented\n"); 205 case TSDEV_PC_PERROR: 206 break; 207 case TSDEV_PC_PERRMASK: 208 panic("PC_PERRMASK not implemented\n"); 209 case TSDEV_PC_PERRSET: 210 panic("PC_PERRSET not implemented\n"); 211 case TSDEV_PC_TLBIV: 212 panic("PC_TLBIV not implemented\n"); 213 case TSDEV_PC_TLBIA: 214 break; // value ignored, supposted to invalidate SG TLB 215 case TSDEV_PC_PMONCTL: 216 panic("PC_PMONCTL not implemented\n"); 217 case TSDEV_PC_PMONCNT: 218 panic("PC_PMONCTN not implemented\n"); 219 default: 220 panic("Default in PChip write reached reading 0x%x\n", daddr); 221 222 } // uint64_t 223 224 pkt->makeAtomicResponse(); 225 return pioDelay; 226} 227 228#define DMA_ADDR_MASK ULL(0x3ffffffff) 229 230Addr 231TsunamiPChip::translatePciToDma(Addr busAddr) 232{ 233 // compare the address to the window base registers 234 uint64_t tbaMask = 0; 235 uint64_t baMask = 0; 236 237 uint64_t windowMask = 0; 238 uint64_t windowBase = 0; 239 240 uint64_t pteEntry = 0; 241 242 Addr pteAddr; 243 Addr dmaAddr; 244 245#if 0 246 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 247 for (int i = 0; i < 4; i++) { 248 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 249 i, wsba[i], wsm[i]); 250 251 windowBase = wsba[i]; 252 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 253 254 if ((busAddr & windowMask) == (windowBase & windowMask)) { 255 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 256 i, windowBase, windowMask, (busAddr & windowMask), 257 (windowBase & windowMask)); 258 } 259 } 260#endif 261 262 for (int i = 0; i < 4; i++) { 263 264 windowBase = wsba[i]; 265 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 266 267 if ((busAddr & windowMask) == (windowBase & windowMask)) { 268 269 if (wsba[i] & 0x1) { // see if enabled 270 if (wsba[i] & 0x2) { // see if SG bit is set 271 /** @todo 272 This currently is faked by just doing a direct 273 read from memory, however, to be realistic, this 274 needs to actually do a bus transaction. The process 275 is explained in the tsunami documentation on page 276 10-12 and basically munges the address to look up a 277 PTE from a table in memory and then uses that mapping 278 to create an address for the SG page 279 */ 280 281 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 282 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 283 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 284 285 sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry, 286 sizeof(uint64_t)); 287 288 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 289 290 } else { 291 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 292 tbaMask = ~baMask; 293 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 294 } 295 296 return (dmaAddr & DMA_ADDR_MASK); 297 } 298 } 299 } 300 301 // if no match was found, then return the original address 302 return busAddr; 303} 304 305Addr 306TsunamiPChip::calcConfigAddr(int bus, int dev, int func) 307{ 308 assert(func < 8); 309 assert(dev < 32); 310 assert(bus == 0); 311 312 return TsunamiPciBus0Config | (func << 8) | (dev << 11); 313} 314 315Addr 316TsunamiPChip::calcIOAddr(Addr addr) 317{ 318 return TSUNAMI_PCI0_IO + addr; 319} 320 321Addr 322TsunamiPChip::calcMemAddr(Addr addr) 323{ 324 return TSUNAMI_PCI0_MEMORY + addr; 325} 326 327void 328TsunamiPChip::serialize(std::ostream &os) 329{ 330 SERIALIZE_SCALAR(pctl); 331 SERIALIZE_ARRAY(wsba, 4); 332 SERIALIZE_ARRAY(wsm, 4); 333 SERIALIZE_ARRAY(tba, 4); 334} 335 336void 337TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 338{ 339 UNSERIALIZE_SCALAR(pctl); 340 UNSERIALIZE_ARRAY(wsba, 4); 341 UNSERIALIZE_ARRAY(wsm, 4); 342 UNSERIALIZE_ARRAY(tba, 4); 343} 344 345 346TsunamiPChip * 347TsunamiPChipParams::create() 348{ 349 return new TsunamiPChip(this); 350} 351