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