tsunami_pchip.cc revision 892
13691Shsul@eecs.umich.edu/* 23691Shsul@eecs.umich.edu * Copyright (c) 2004 The Regents of The University of Michigan 33691Shsul@eecs.umich.edu * All rights reserved. 43691Shsul@eecs.umich.edu * 53691Shsul@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 63691Shsul@eecs.umich.edu * modification, are permitted provided that the following conditions are 73691Shsul@eecs.umich.edu * met: redistributions of source code must retain the above copyright 83691Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 93691Shsul@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 103691Shsul@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 113691Shsul@eecs.umich.edu * documentation and/or other materials provided with the distribution; 123691Shsul@eecs.umich.edu * neither the name of the copyright holders nor the names of its 133691Shsul@eecs.umich.edu * contributors may be used to endorse or promote products derived from 143691Shsul@eecs.umich.edu * this software without specific prior written permission. 153691Shsul@eecs.umich.edu * 163691Shsul@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173691Shsul@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183691Shsul@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193691Shsul@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203691Shsul@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213691Shsul@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223691Shsul@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233691Shsul@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243691Shsul@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253691Shsul@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263691Shsul@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273691Shsul@eecs.umich.edu */ 283691Shsul@eecs.umich.edu 293691Shsul@eecs.umich.edu/* @file 303691Shsul@eecs.umich.edu * Tsunami PChip (pci) 3111682Sandreas.hansson@arm.com */ 3213916Sodanrc@yahoo.com.br 333691Shsul@eecs.umich.edu#include <deque> 3413950Sodanrc@yahoo.com.br#include <string> 3513950Sodanrc@yahoo.com.br#include <vector> 3613916Sodanrc@yahoo.com.br 379793Sakash.bagdia@arm.com#include "base/trace.hh" 389827Sakash.bagdia@arm.com#include "cpu/exec_context.hh" 399827Sakash.bagdia@arm.com#include "dev/console.hh" 409827Sakash.bagdia@arm.com#include "dev/etherdev.hh" 419793Sakash.bagdia@arm.com#include "dev/scsi_ctrl.hh" 429827Sakash.bagdia@arm.com#include "dev/tlaser_clock.hh" 439827Sakash.bagdia@arm.com#include "dev/tsunami_pchip.hh" 449793Sakash.bagdia@arm.com#include "dev/tsunamireg.h" 453691Shsul@eecs.umich.edu#include "dev/tsunami.hh" 468876Sandreas.hansson@arm.com#include "mem/functional_mem/memory_control.hh" 478876Sandreas.hansson@arm.com#include "mem/functional_mem/physical_memory.hh" 487876Sgblack@eecs.umich.edu#include "sim/builder.hh" 499793Sakash.bagdia@arm.com#include "sim/system.hh" 509793Sakash.bagdia@arm.com 519793Sakash.bagdia@arm.comusing namespace std; 529827Sakash.bagdia@arm.com 539827Sakash.bagdia@arm.comTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 549827Sakash.bagdia@arm.com MemoryController *mmu) 559793Sakash.bagdia@arm.com : FunctionalMemory(name), addr(a), tsunami(t) 569793Sakash.bagdia@arm.com{ 579827Sakash.bagdia@arm.com mmu->add_child(this, Range<Addr>(addr, addr + size)); 589827Sakash.bagdia@arm.com 599827Sakash.bagdia@arm.com for (int i = 0; i < 4; i++) { 609793Sakash.bagdia@arm.com wsba[i] = 0; 618713Sandreas.hansson@arm.com wsm[i] = 0; 628713Sandreas.hansson@arm.com tba[i] = 0; 638713Sandreas.hansson@arm.com } 649408Sandreas.hansson@arm.com 658839Sandreas.hansson@arm.com //Set back pointer in tsunami 668839Sandreas.hansson@arm.com tsunami->pchip = this; 673691Shsul@eecs.umich.edu} 689826Sandreas.hansson@arm.com 699826Sandreas.hansson@arm.comFault 709826Sandreas.hansson@arm.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 7113950Sodanrc@yahoo.com.br{ 7213950Sodanrc@yahoo.com.br DPRINTF(Tsunami, "read va=%#x size=%d\n", 7313916Sodanrc@yahoo.com.br req->vaddr, req->size); 749827Sakash.bagdia@arm.com 759827Sakash.bagdia@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 769793Sakash.bagdia@arm.com 779827Sakash.bagdia@arm.com switch (req->size) { 789827Sakash.bagdia@arm.com 799827Sakash.bagdia@arm.com case sizeof(uint64_t): 803691Shsul@eecs.umich.edu switch(daddr) { 818876Sandreas.hansson@arm.com case TSDEV_PC_WSBA0: 828876Sandreas.hansson@arm.com *(uint64_t*)data = wsba[0]; 837876Sgblack@eecs.umich.edu return No_Fault; 849793Sakash.bagdia@arm.com case TSDEV_PC_WSBA1: 859793Sakash.bagdia@arm.com *(uint64_t*)data = wsba[1]; 869793Sakash.bagdia@arm.com return No_Fault; 879827Sakash.bagdia@arm.com case TSDEV_PC_WSBA2: 889827Sakash.bagdia@arm.com *(uint64_t*)data = wsba[2]; 899827Sakash.bagdia@arm.com return No_Fault; 909793Sakash.bagdia@arm.com case TSDEV_PC_WSBA3: 919793Sakash.bagdia@arm.com *(uint64_t*)data = wsba[3]; 929827Sakash.bagdia@arm.com return No_Fault; 939827Sakash.bagdia@arm.com case TSDEV_PC_WSM0: 949827Sakash.bagdia@arm.com *(uint64_t*)data = wsm[0]; 959793Sakash.bagdia@arm.com return No_Fault; 969408Sandreas.hansson@arm.com case TSDEV_PC_WSM1: 978839Sandreas.hansson@arm.com *(uint64_t*)data = wsm[1]; 988839Sandreas.hansson@arm.com return No_Fault; 993691Shsul@eecs.umich.edu case TSDEV_PC_WSM2: 1009826Sandreas.hansson@arm.com *(uint64_t*)data = wsm[2]; 1019826Sandreas.hansson@arm.com return No_Fault; 1029826Sandreas.hansson@arm.com case TSDEV_PC_WSM3: 10313950Sodanrc@yahoo.com.br *(uint64_t*)data = wsm[3]; 1043691Shsul@eecs.umich.edu return No_Fault; 1053691Shsul@eecs.umich.edu case TSDEV_PC_TBA0: 106 *(uint64_t*)data = tba[0]; 107 return No_Fault; 108 case TSDEV_PC_TBA1: 109 *(uint64_t*)data = tba[1]; 110 return No_Fault; 111 case TSDEV_PC_TBA2: 112 *(uint64_t*)data = tba[2]; 113 return No_Fault; 114 case TSDEV_PC_TBA3: 115 *(uint64_t*)data = tba[3]; 116 return No_Fault; 117 case TSDEV_PC_PCTL: 118 // might want to change the clock?? 119 *(uint64_t*)data = 0x00; // try this 120 return No_Fault; 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 *(uint64_t*)data = 0x00; 127 return No_Fault; 128 case TSDEV_PC_PERRMASK: 129 *(uint64_t*)data = 0x00; 130 return No_Fault; 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 *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 137 return No_Fault; 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 } // uint64_t 146 147 break; 148 case sizeof(uint32_t): 149 case sizeof(uint16_t): 150 case sizeof(uint8_t): 151 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