tsunami_pchip.cc revision 892
14120Sgblack@eecs.umich.edu/* 211274Sshingarov@labware.com * Copyright (c) 2004 The Regents of The University of Michigan 310600Sgabeblack@google.com * All rights reserved. 44120Sgblack@eecs.umich.edu * 54120Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64120Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 137087Snate@binkert.org * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 154120Sgblack@eecs.umich.edu * 167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257087Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274120Sgblack@eecs.umich.edu */ 284120Sgblack@eecs.umich.edu 294120Sgblack@eecs.umich.edu/* @file 304120Sgblack@eecs.umich.edu * Tsunami PChip (pci) 314120Sgblack@eecs.umich.edu */ 324120Sgblack@eecs.umich.edu 334120Sgblack@eecs.umich.edu#include <deque> 344120Sgblack@eecs.umich.edu#include <string> 354120Sgblack@eecs.umich.edu#include <vector> 364120Sgblack@eecs.umich.edu 374120Sgblack@eecs.umich.edu#include "base/trace.hh" 384120Sgblack@eecs.umich.edu#include "cpu/exec_context.hh" 394120Sgblack@eecs.umich.edu#include "dev/console.hh" 4011274Sshingarov@labware.com#include "dev/etherdev.hh" 414120Sgblack@eecs.umich.edu#include "dev/scsi_ctrl.hh" 424120Sgblack@eecs.umich.edu#include "dev/tlaser_clock.hh" 434120Sgblack@eecs.umich.edu#include "dev/tsunami_pchip.hh" 444120Sgblack@eecs.umich.edu#include "dev/tsunamireg.h" 454120Sgblack@eecs.umich.edu#include "dev/tsunami.hh" 4610600Sgabeblack@google.com#include "mem/functional_mem/memory_control.hh" 4710600Sgabeblack@google.com#include "mem/functional_mem/physical_memory.hh" 484144Sgblack@eecs.umich.edu#include "sim/builder.hh" 494144Sgblack@eecs.umich.edu#include "sim/system.hh" 504144Sgblack@eecs.umich.edu 514144Sgblack@eecs.umich.eduusing namespace std; 524144Sgblack@eecs.umich.edu 534120Sgblack@eecs.umich.eduTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 544120Sgblack@eecs.umich.edu MemoryController *mmu) 554120Sgblack@eecs.umich.edu : FunctionalMemory(name), addr(a), tsunami(t) 5610600Sgabeblack@google.com{ 5710600Sgabeblack@google.com mmu->add_child(this, Range<Addr>(addr, addr + size)); 5811274Sshingarov@labware.com 5911274Sshingarov@labware.com for (int i = 0; i < 4; i++) { 6011274Sshingarov@labware.com wsba[i] = 0; 6111274Sshingarov@labware.com wsm[i] = 0; 6210600Sgabeblack@google.com tba[i] = 0; 6311274Sshingarov@labware.com } 6411274Sshingarov@labware.com 6511274Sshingarov@labware.com //Set back pointer in tsunami 6611274Sshingarov@labware.com tsunami->pchip = this; 6711274Sshingarov@labware.com} 6811274Sshingarov@labware.com 6911274Sshingarov@labware.comFault 7011274Sshingarov@labware.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 7111274Sshingarov@labware.com{ 7211274Sshingarov@labware.com DPRINTF(Tsunami, "read va=%#x size=%d\n", 7311274Sshingarov@labware.com req->vaddr, req->size); 7411274Sshingarov@labware.com 7511274Sshingarov@labware.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 7611274Sshingarov@labware.com 7711274Sshingarov@labware.com switch (req->size) { 7811274Sshingarov@labware.com 7911274Sshingarov@labware.com case sizeof(uint64_t): 8011274Sshingarov@labware.com switch(daddr) { 8111274Sshingarov@labware.com case TSDEV_PC_WSBA0: 8211274Sshingarov@labware.com *(uint64_t*)data = wsba[0]; 8311274Sshingarov@labware.com return No_Fault; 8411274Sshingarov@labware.com case TSDEV_PC_WSBA1: 8511274Sshingarov@labware.com *(uint64_t*)data = wsba[1]; 8611274Sshingarov@labware.com return No_Fault; 8711274Sshingarov@labware.com case TSDEV_PC_WSBA2: 8812031Sgabeblack@google.com *(uint64_t*)data = wsba[2]; 8912031Sgabeblack@google.com return No_Fault; 9012031Sgabeblack@google.com case TSDEV_PC_WSBA3: 9112031Sgabeblack@google.com *(uint64_t*)data = wsba[3]; 9212031Sgabeblack@google.com return No_Fault; 9310600Sgabeblack@google.com case TSDEV_PC_WSM0: 9410600Sgabeblack@google.com *(uint64_t*)data = wsm[0]; 9511274Sshingarov@labware.com return No_Fault; 9610600Sgabeblack@google.com case TSDEV_PC_WSM1: 9711274Sshingarov@labware.com *(uint64_t*)data = wsm[1]; 9811274Sshingarov@labware.com return No_Fault; 9912073Smatthiashille8@gmail.com case TSDEV_PC_WSM2: 10011274Sshingarov@labware.com *(uint64_t*)data = wsm[2]; 10111274Sshingarov@labware.com return No_Fault; 10211274Sshingarov@labware.com case TSDEV_PC_WSM3: 10311274Sshingarov@labware.com *(uint64_t*)data = wsm[3]; 10411274Sshingarov@labware.com return No_Fault; 10511274Sshingarov@labware.com case TSDEV_PC_TBA0: 10611274Sshingarov@labware.com *(uint64_t*)data = tba[0]; 10711274Sshingarov@labware.com return No_Fault; 10811274Sshingarov@labware.com case TSDEV_PC_TBA1: 10911274Sshingarov@labware.com *(uint64_t*)data = tba[1]; 11011274Sshingarov@labware.com return No_Fault; 11111274Sshingarov@labware.com case TSDEV_PC_TBA2: 11211274Sshingarov@labware.com *(uint64_t*)data = tba[2]; 11311274Sshingarov@labware.com return No_Fault; 11411274Sshingarov@labware.com case TSDEV_PC_TBA3: 11511274Sshingarov@labware.com *(uint64_t*)data = tba[3]; 11611274Sshingarov@labware.com return No_Fault; 11711274Sshingarov@labware.com case TSDEV_PC_PCTL: 11811274Sshingarov@labware.com // might want to change the clock?? 11911274Sshingarov@labware.com *(uint64_t*)data = 0x00; // try this 12011274Sshingarov@labware.com return No_Fault; 12111274Sshingarov@labware.com case TSDEV_PC_PLAT: 12211274Sshingarov@labware.com panic("PC_PLAT not implemented\n"); 12311274Sshingarov@labware.com case TSDEV_PC_RES: 12411274Sshingarov@labware.com panic("PC_RES not implemented\n"); 12511274Sshingarov@labware.com case TSDEV_PC_PERROR: 12611274Sshingarov@labware.com *(uint64_t*)data = 0x00; 12711274Sshingarov@labware.com return No_Fault; 12811274Sshingarov@labware.com case TSDEV_PC_PERRMASK: 12911274Sshingarov@labware.com *(uint64_t*)data = 0x00; 13011274Sshingarov@labware.com return No_Fault; 13111274Sshingarov@labware.com case TSDEV_PC_PERRSET: 13211274Sshingarov@labware.com panic("PC_PERRSET not implemented\n"); 13311274Sshingarov@labware.com case TSDEV_PC_TLBIV: 13411274Sshingarov@labware.com panic("PC_TLBIV not implemented\n"); 13512031Sgabeblack@google.com case TSDEV_PC_TLBIA: 13612031Sgabeblack@google.com *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 13712031Sgabeblack@google.com return No_Fault; 13812031Sgabeblack@google.com case TSDEV_PC_PMONCTL: 13912031Sgabeblack@google.com panic("PC_PMONCTL not implemented\n"); 14010600Sgabeblack@google.com case TSDEV_PC_PMONCNT: 14110600Sgabeblack@google.com panic("PC_PMONCTN not implemented\n"); 14212031Sgabeblack@google.com default: 14312031Sgabeblack@google.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 14412031Sgabeblack@google.com 14511274Sshingarov@labware.com } // uint64_t 14612449Sgabeblack@google.com 14711274Sshingarov@labware.com break; 14810600Sgabeblack@google.com case sizeof(uint32_t): 14911274Sshingarov@labware.com case sizeof(uint16_t): 1504120Sgblack@eecs.umich.edu case sizeof(uint8_t): 1514120Sgblack@eecs.umich.edu default: 152 panic("invalid access size(?) for tsunami register!\n\n"); 153 } 154 DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 155 156 return No_Fault; 157} 158 159Fault 160TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 161{ 162 DPRINTF(Tsunami, "write - va=%#x size=%d \n", 163 req->vaddr, req->size); 164 165 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 166 167 switch (req->size) { 168 169 case sizeof(uint64_t): 170 switch(daddr) { 171 case TSDEV_PC_WSBA0: 172 wsba[0] = *(uint64_t*)data; 173 return No_Fault; 174 case TSDEV_PC_WSBA1: 175 wsba[1] = *(uint64_t*)data; 176 return No_Fault; 177 case TSDEV_PC_WSBA2: 178 wsba[2] = *(uint64_t*)data; 179 return No_Fault; 180 case TSDEV_PC_WSBA3: 181 wsba[3] = *(uint64_t*)data; 182 return No_Fault; 183 case TSDEV_PC_WSM0: 184 wsm[0] = *(uint64_t*)data; 185 return No_Fault; 186 case TSDEV_PC_WSM1: 187 wsm[1] = *(uint64_t*)data; 188 return No_Fault; 189 case TSDEV_PC_WSM2: 190 wsm[2] = *(uint64_t*)data; 191 return No_Fault; 192 case TSDEV_PC_WSM3: 193 wsm[3] = *(uint64_t*)data; 194 return No_Fault; 195 case TSDEV_PC_TBA0: 196 tba[0] = *(uint64_t*)data; 197 return No_Fault; 198 case TSDEV_PC_TBA1: 199 tba[1] = *(uint64_t*)data; 200 return No_Fault; 201 case TSDEV_PC_TBA2: 202 tba[2] = *(uint64_t*)data; 203 return No_Fault; 204 case TSDEV_PC_TBA3: 205 tba[3] = *(uint64_t*)data; 206 return No_Fault; 207 case TSDEV_PC_PCTL: 208 // might want to change the clock?? 209 return No_Fault; 210 case TSDEV_PC_PLAT: 211 panic("PC_PLAT not implemented\n"); 212 case TSDEV_PC_RES: 213 panic("PC_RES not implemented\n"); 214 case TSDEV_PC_PERROR: 215 return No_Fault; 216 case TSDEV_PC_PERRMASK: 217 panic("PC_PERRMASK not implemented\n"); 218 case TSDEV_PC_PERRSET: 219 panic("PC_PERRSET not implemented\n"); 220 case TSDEV_PC_TLBIV: 221 panic("PC_TLBIV not implemented\n"); 222 case TSDEV_PC_TLBIA: 223 return No_Fault; // value ignored, supposted to invalidate SG TLB 224 case TSDEV_PC_PMONCTL: 225 panic("PC_PMONCTL not implemented\n"); 226 case TSDEV_PC_PMONCNT: 227 panic("PC_PMONCTN not implemented\n"); 228 default: 229 panic("Default in PChip Read reached reading 0x%x\n", daddr); 230 231 } // uint64_t 232 233 break; 234 case sizeof(uint32_t): 235 case sizeof(uint16_t): 236 case sizeof(uint8_t): 237 default: 238 panic("invalid access size(?) for tsunami register!\n\n"); 239 } 240 241 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 242 243 return No_Fault; 244} 245 246#define DMA_ADDR_MASK ULL(0x3ffffffff) 247 248Addr 249TsunamiPChip::translatePciToDma(Addr busAddr) 250{ 251 // compare the address to the window base registers 252 uint64_t tbaMask = 0; 253 uint64_t baMask = 0; 254 255 uint64_t windowMask = 0; 256 uint64_t windowBase = 0; 257 258 uint64_t pteEntry = 0; 259 260 Addr pteAddr; 261 Addr dmaAddr; 262 263 for (int i = 0; i < 4; i++) { 264 windowBase = wsba[i]; 265 windowMask = ~wsm[i] & (0x7ff << 20); 266 267 if ((busAddr & windowMask) == (windowBase & windowMask)) { 268 269 270 if (wsba[i] & 0x1) { // see if enabled 271 if (wsba[i] & 0x2) { // see if SG bit is set 272 /** @todo 273 This currently is faked by just doing a direct 274 read from memory, however, to be realistic, this 275 needs to actually do a bus transaction. The process 276 is explained in the tsunami documentation on page 277 10-12 and basically munges the address to look up a 278 PTE from a table in memory and then uses that mapping 279 to create an address for the SG page 280 */ 281 282 tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff); 283 baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13); 284 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 285 286 memcpy((void *)&pteEntry, 287 tsunami->system-> 288 physmem->dma_addr(pteAddr, sizeof(uint64_t)), 289 sizeof(uint64_t)); 290 291 dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff); 292 293 } else { 294 baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff; 295 tbaMask = ~baMask; 296 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 297 } 298 299 return (dmaAddr & DMA_ADDR_MASK); 300 } 301 } 302 } 303 304 return 0; 305} 306 307void 308TsunamiPChip::serialize(std::ostream &os) 309{ 310 SERIALIZE_ARRAY(wsba, 4); 311 SERIALIZE_ARRAY(wsm, 4); 312 SERIALIZE_ARRAY(tba, 4); 313} 314 315void 316TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 317{ 318 UNSERIALIZE_ARRAY(wsba, 4); 319 UNSERIALIZE_ARRAY(wsm, 4); 320 UNSERIALIZE_ARRAY(tba, 4); 321} 322 323BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 324 325 SimObjectParam<Tsunami *> tsunami; 326 SimObjectParam<MemoryController *> mmu; 327 Param<Addr> addr; 328 329END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 330 331BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 332 333 INIT_PARAM(tsunami, "Tsunami"), 334 INIT_PARAM(mmu, "Memory Controller"), 335 INIT_PARAM(addr, "Device Address") 336 337END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 338 339CREATE_SIM_OBJECT(TsunamiPChip) 340{ 341 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); 342} 343 344REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 345