tsunami_pchip.cc revision 892
1/* 2 * Copyright (c) 2004 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 "cpu/exec_context.hh" 39#include "dev/console.hh" 40#include "dev/etherdev.hh" 41#include "dev/scsi_ctrl.hh" 42#include "dev/tlaser_clock.hh" 43#include "dev/tsunami_pchip.hh" 44#include "dev/tsunamireg.h" 45#include "dev/tsunami.hh" 46#include "mem/functional_mem/memory_control.hh" 47#include "mem/functional_mem/physical_memory.hh" 48#include "sim/builder.hh" 49#include "sim/system.hh" 50 51using namespace std; 52 53TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 54 MemoryController *mmu) 55 : FunctionalMemory(name), addr(a), tsunami(t) 56{ 57 mmu->add_child(this, Range<Addr>(addr, addr + size)); 58 59 for (int i = 0; i < 4; i++) { 60 wsba[i] = 0; 61 wsm[i] = 0; 62 tba[i] = 0; 63 } 64 65 //Set back pointer in tsunami 66 tsunami->pchip = this; 67} 68 69Fault 70TsunamiPChip::read(MemReqPtr &req, uint8_t *data) 71{ 72 DPRINTF(Tsunami, "read va=%#x size=%d\n", 73 req->vaddr, req->size); 74 75 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 76 77 switch (req->size) { 78 79 case sizeof(uint64_t): 80 switch(daddr) { 81 case TSDEV_PC_WSBA0: 82 *(uint64_t*)data = wsba[0]; 83 return No_Fault; 84 case TSDEV_PC_WSBA1: 85 *(uint64_t*)data = wsba[1]; 86 return No_Fault; 87 case TSDEV_PC_WSBA2: 88 *(uint64_t*)data = wsba[2]; 89 return No_Fault; 90 case TSDEV_PC_WSBA3: 91 *(uint64_t*)data = wsba[3]; 92 return No_Fault; 93 case TSDEV_PC_WSM0: 94 *(uint64_t*)data = wsm[0]; 95 return No_Fault; 96 case TSDEV_PC_WSM1: 97 *(uint64_t*)data = wsm[1]; 98 return No_Fault; 99 case TSDEV_PC_WSM2: 100 *(uint64_t*)data = wsm[2]; 101 return No_Fault; 102 case TSDEV_PC_WSM3: 103 *(uint64_t*)data = wsm[3]; 104 return No_Fault; 105 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