tsunami_pchip.cc revision 896
1/* $Id$ */ 2 3/* @file 4 * Tsunami PChip (pci) 5 */ 6 7#include <deque> 8#include <string> 9#include <vector> 10 11#include "base/trace.hh" 12#include "cpu/exec_context.hh" 13#include "dev/console.hh" 14#include "dev/etherdev.hh" 15#include "dev/scsi_ctrl.hh" 16#include "dev/tlaser_clock.hh" 17#include "dev/tsunami_pchip.hh" 18#include "dev/tsunamireg.h" 19#include "dev/tsunami.hh" 20#include "mem/functional_mem/memory_control.hh" 21#include "mem/functional_mem/physical_memory.hh" 22#include "sim/builder.hh" 23#include "sim/system.hh" 24 25using namespace std; 26 27TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 28 MemoryController *mmu) 29 : FunctionalMemory(name), addr(a), tsunami(t) 30{ 31 mmu->add_child(this, Range<Addr>(addr, addr + size)); 32 33 for (int i = 0; i < 4; i++) { 34 wsba[i] = 0; 35 wsm[i] = 0; 36 tba[i] = 0; 37 } 38 39 // initialize pchip control register 40 pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 41 42 //Set back pointer in tsunami 43 tsunami->pchip = this; 44} 45 46Fault 47TsunamiPChip::read(MemReqPtr &req, uint8_t *data) 48{ 49 DPRINTF(Tsunami, "read va=%#x size=%d\n", 50 req->vaddr, req->size); 51 52 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 53 54 switch (req->size) { 55 56 case sizeof(uint64_t): 57 switch(daddr) { 58 case TSDEV_PC_WSBA0: 59 *(uint64_t*)data = wsba[0]; 60 return No_Fault; 61 case TSDEV_PC_WSBA1: 62 *(uint64_t*)data = wsba[1]; 63 return No_Fault; 64 case TSDEV_PC_WSBA2: 65 *(uint64_t*)data = wsba[2]; 66 return No_Fault; 67 case TSDEV_PC_WSBA3: 68 *(uint64_t*)data = wsba[3]; 69 return No_Fault; 70 case TSDEV_PC_WSM0: 71 *(uint64_t*)data = wsm[0]; 72 return No_Fault; 73 case TSDEV_PC_WSM1: 74 *(uint64_t*)data = wsm[1]; 75 return No_Fault; 76 case TSDEV_PC_WSM2: 77 *(uint64_t*)data = wsm[2]; 78 return No_Fault; 79 case TSDEV_PC_WSM3: 80 *(uint64_t*)data = wsm[3]; 81 return No_Fault; 82 case TSDEV_PC_TBA0: 83 *(uint64_t*)data = tba[0]; 84 return No_Fault; 85 case TSDEV_PC_TBA1: 86 *(uint64_t*)data = tba[1]; 87 return No_Fault; 88 case TSDEV_PC_TBA2: 89 *(uint64_t*)data = tba[2]; 90 return No_Fault; 91 case TSDEV_PC_TBA3: 92 *(uint64_t*)data = tba[3]; 93 return No_Fault; 94 case TSDEV_PC_PCTL: 95 *(uint64_t*)data = pctl; 96 return No_Fault; 97 case TSDEV_PC_PLAT: 98 panic("PC_PLAT not implemented\n"); 99 case TSDEV_PC_RES: 100 panic("PC_RES not implemented\n"); 101 case TSDEV_PC_PERROR: 102 panic("PC_PERROR not implemented\n"); 103 case TSDEV_PC_PERRMASK: 104 panic("PC_PERRMASK not implemented\n"); 105 case TSDEV_PC_PERRSET: 106 panic("PC_PERRSET not implemented\n"); 107 case TSDEV_PC_TLBIV: 108 panic("PC_TLBIV not implemented\n"); 109 case TSDEV_PC_TLBIA: 110 *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 111 return No_Fault; 112 case TSDEV_PC_PMONCTL: 113 panic("PC_PMONCTL not implemented\n"); 114 case TSDEV_PC_PMONCNT: 115 panic("PC_PMONCTN not implemented\n"); 116 default: 117 panic("Default in PChip Read reached reading 0x%x\n", daddr); 118 119 } // uint64_t 120 121 break; 122 case sizeof(uint32_t): 123 case sizeof(uint16_t): 124 case sizeof(uint8_t): 125 default: 126 panic("invalid access size(?) for tsunami register!\n\n"); 127 } 128 DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 129 130 return No_Fault; 131} 132 133Fault 134TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 135{ 136 DPRINTF(Tsunami, "write - va=%#x size=%d \n", 137 req->vaddr, req->size); 138 139 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 140 141 switch (req->size) { 142 143 case sizeof(uint64_t): 144 switch(daddr) { 145 case TSDEV_PC_WSBA0: 146 wsba[0] = *(uint64_t*)data; 147 return No_Fault; 148 case TSDEV_PC_WSBA1: 149 wsba[1] = *(uint64_t*)data; 150 return No_Fault; 151 case TSDEV_PC_WSBA2: 152 wsba[2] = *(uint64_t*)data; 153 return No_Fault; 154 case TSDEV_PC_WSBA3: 155 wsba[3] = *(uint64_t*)data; 156 return No_Fault; 157 case TSDEV_PC_WSM0: 158 wsm[0] = *(uint64_t*)data; 159 return No_Fault; 160 case TSDEV_PC_WSM1: 161 wsm[1] = *(uint64_t*)data; 162 return No_Fault; 163 case TSDEV_PC_WSM2: 164 wsm[2] = *(uint64_t*)data; 165 return No_Fault; 166 case TSDEV_PC_WSM3: 167 wsm[3] = *(uint64_t*)data; 168 return No_Fault; 169 case TSDEV_PC_TBA0: 170 tba[0] = *(uint64_t*)data; 171 return No_Fault; 172 case TSDEV_PC_TBA1: 173 tba[1] = *(uint64_t*)data; 174 return No_Fault; 175 case TSDEV_PC_TBA2: 176 tba[2] = *(uint64_t*)data; 177 return No_Fault; 178 case TSDEV_PC_TBA3: 179 tba[3] = *(uint64_t*)data; 180 return No_Fault; 181 case TSDEV_PC_PCTL: 182 pctl = *(uint64_t*)data; 183 return No_Fault; 184 case TSDEV_PC_PLAT: 185 panic("PC_PLAT not implemented\n"); 186 case TSDEV_PC_RES: 187 panic("PC_RES not implemented\n"); 188 case TSDEV_PC_PERROR: 189 panic("PC_PERROR not implemented\n"); 190 case TSDEV_PC_PERRMASK: 191 panic("PC_PERRMASK not implemented\n"); 192 case TSDEV_PC_PERRSET: 193 panic("PC_PERRSET not implemented\n"); 194 case TSDEV_PC_TLBIV: 195 panic("PC_TLBIV not implemented\n"); 196 case TSDEV_PC_TLBIA: 197 return No_Fault; // value ignored, supposted to invalidate SG TLB 198 case TSDEV_PC_PMONCTL: 199 panic("PC_PMONCTL not implemented\n"); 200 case TSDEV_PC_PMONCNT: 201 panic("PC_PMONCTN not implemented\n"); 202 default: 203 panic("Default in PChip Read reached reading 0x%x\n", daddr); 204 205 } // uint64_t 206 207 break; 208 case sizeof(uint32_t): 209 case sizeof(uint16_t): 210 case sizeof(uint8_t): 211 default: 212 panic("invalid access size(?) for tsunami register!\n\n"); 213 } 214 215 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 216 217 return No_Fault; 218} 219 220#define DMA_ADDR_MASK ULL(0x3ffffffff) 221 222Addr 223TsunamiPChip::translatePciToDma(Addr busAddr) 224{ 225 // compare the address to the window base registers 226 uint64_t tbaMask = 0; 227 uint64_t baMask = 0; 228 229 uint64_t windowMask = 0; 230 uint64_t windowBase = 0; 231 232 uint64_t pteEntry = 0; 233 234 Addr pteAddr; 235 Addr dmaAddr; 236 237#if 0 238 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 239 for (int i = 0; i < 4; i++) { 240 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 241 i, wsba[i], wsm[i]); 242 243 windowBase = wsba[i]; 244 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 245 246 if ((busAddr & windowMask) == (windowBase & windowMask)) { 247 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 248 i, windowBase, windowMask, (busAddr & windowMask), 249 (windowBase & windowMask)); 250 } 251 } 252#endif 253 254 for (int i = 0; i < 4; i++) { 255 256 windowBase = wsba[i]; 257 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 258 259 if ((busAddr & windowMask) == (windowBase & windowMask)) { 260 261 if (wsba[i] & 0x1) { // see if enabled 262 if (wsba[i] & 0x2) { // see if SG bit is set 263 /** @todo 264 This currently is faked by just doing a direct 265 read from memory, however, to be realistic, this 266 needs to actually do a bus transaction. The process 267 is explained in the tsunami documentation on page 268 10-12 and basically munges the address to look up a 269 PTE from a table in memory and then uses that mapping 270 to create an address for the SG page 271 */ 272 273 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 274 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 275 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 276 277 memcpy((void *)&pteEntry, 278 tsunami->system-> 279 physmem->dma_addr(pteAddr, sizeof(uint64_t)), 280 sizeof(uint64_t)); 281 282 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 283 284 } else { 285 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 286 tbaMask = ~baMask; 287 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 288 } 289 290 return (dmaAddr & DMA_ADDR_MASK); 291 } 292 } 293 } 294 295 // if no match was found, then return the original address 296 return busAddr; 297} 298 299void 300TsunamiPChip::serialize(std::ostream &os) 301{ 302 SERIALIZE_SCALAR(pctl); 303 SERIALIZE_ARRAY(wsba, 4); 304 SERIALIZE_ARRAY(wsm, 4); 305 SERIALIZE_ARRAY(tba, 4); 306} 307 308void 309TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 310{ 311 UNSERIALIZE_SCALAR(pctl); 312 UNSERIALIZE_ARRAY(wsba, 4); 313 UNSERIALIZE_ARRAY(wsm, 4); 314 UNSERIALIZE_ARRAY(tba, 4); 315} 316 317BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 318 319 SimObjectParam<Tsunami *> tsunami; 320 SimObjectParam<MemoryController *> mmu; 321 Param<Addr> addr; 322 323END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 324 325BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 326 327 INIT_PARAM(tsunami, "Tsunami"), 328 INIT_PARAM(mmu, "Memory Controller"), 329 INIT_PARAM(addr, "Device Address") 330 331END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 332 333CREATE_SIM_OBJECT(TsunamiPChip) 334{ 335 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); 336} 337 338REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 339