tsunami_pchip.cc revision 857
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 //Set back pointer in tsunami 40 tsunami->pchip = this; 41} 42 43Fault 44TsunamiPChip::read(MemReqPtr &req, uint8_t *data) 45{ 46 DPRINTF(Tsunami, "read va=%#x size=%d\n", 47 req->vaddr, req->size); 48 49 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 50// ExecContext *xc = req->xc; 51// int cpuid = xc->cpu_id; 52 53 switch (req->size) { 54 55 case sizeof(uint64_t): 56 switch(daddr) { 57 case TSDEV_PC_WSBA0: 58 *(uint64_t*)data = wsba[0]; 59 return No_Fault; 60 case TSDEV_PC_WSBA1: 61 *(uint64_t*)data = wsba[1]; 62 return No_Fault; 63 case TSDEV_PC_WSBA2: 64 *(uint64_t*)data = wsba[2]; 65 return No_Fault; 66 case TSDEV_PC_WSBA3: 67 *(uint64_t*)data = wsba[3]; 68 return No_Fault; 69 case TSDEV_PC_WSM0: 70 *(uint64_t*)data = wsm[0]; 71 return No_Fault; 72 case TSDEV_PC_WSM1: 73 *(uint64_t*)data = wsm[1]; 74 return No_Fault; 75 case TSDEV_PC_WSM2: 76 *(uint64_t*)data = wsm[2]; 77 return No_Fault; 78 case TSDEV_PC_WSM3: 79 *(uint64_t*)data = wsm[3]; 80 return No_Fault; 81 case TSDEV_PC_TBA0: 82 *(uint64_t*)data = tba[0]; 83 return No_Fault; 84 case TSDEV_PC_TBA1: 85 *(uint64_t*)data = tba[1]; 86 return No_Fault; 87 case TSDEV_PC_TBA2: 88 *(uint64_t*)data = tba[2]; 89 return No_Fault; 90 case TSDEV_PC_TBA3: 91 *(uint64_t*)data = tba[3]; 92 return No_Fault; 93 case TSDEV_PC_PCTL: 94 // might want to change the clock?? 95 *(uint64_t*)data = 0x00; // try this 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 // might want to change the clock?? 183 //*(uint64_t*)data; // try this 184 return No_Fault; 185 case TSDEV_PC_PLAT: 186 panic("PC_PLAT not implemented\n"); 187 case TSDEV_PC_RES: 188 panic("PC_RES not implemented\n"); 189 case TSDEV_PC_PERROR: 190 panic("PC_PERROR not implemented\n"); 191 case TSDEV_PC_PERRMASK: 192 panic("PC_PERRMASK not implemented\n"); 193 case TSDEV_PC_PERRSET: 194 panic("PC_PERRSET not implemented\n"); 195 case TSDEV_PC_TLBIV: 196 panic("PC_TLBIV not implemented\n"); 197 case TSDEV_PC_TLBIA: 198 return No_Fault; // value ignored, supposted to invalidate SG TLB 199 case TSDEV_PC_PMONCTL: 200 panic("PC_PMONCTL not implemented\n"); 201 case TSDEV_PC_PMONCNT: 202 panic("PC_PMONCTN not implemented\n"); 203 default: 204 panic("Default in PChip Read reached reading 0x%x\n", daddr); 205 206 } // uint64_t 207 208 break; 209 case sizeof(uint32_t): 210 case sizeof(uint16_t): 211 case sizeof(uint8_t): 212 default: 213 panic("invalid access size(?) for tsunami register!\n\n"); 214 } 215 216 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 217 218 return No_Fault; 219} 220 221#define DMA_ADDR_MASK ULL(0x3ffffffff) 222 223Addr 224TsunamiPChip::translatePciToDma(Addr busAddr) 225{ 226 // compare the address to the window base registers 227 uint64_t tbaMask = 0; 228 uint64_t baMask = 0; 229 230 uint64_t windowMask = 0; 231 uint64_t windowBase = 0; 232 233 uint64_t pteEntry = 0; 234 235 Addr pteAddr; 236 Addr dmaAddr; 237 238 for (int i = 0; i < 4; i++) { 239 windowBase = wsba[i]; 240 windowMask = ~wsm[i] & (0x7ff << 20); 241 242 if ((busAddr & windowMask) == (windowBase & windowMask)) { 243 244 245 if (wsba[i] & 0x1) { // see if enabled 246 if (wsba[i] & 0x2) { // see if SG bit is set 247 /** @todo 248 This currently is faked by just doing a direct 249 read from memory, however, to be realistic, this 250 needs to actually do a bus transaction. The process 251 is explained in the tsunami documentation on page 252 10-12 and basically munges the address to look up a 253 PTE from a table in memory and then uses that mapping 254 to create an address for the SG page 255 */ 256 257 tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff); 258 baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13); 259 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 260 261 memcpy((void *)&pteEntry, 262 tsunami->system-> 263 physmem->dma_addr(pteAddr, sizeof(uint64_t)), 264 sizeof(uint64_t)); 265 266 dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0xfff); 267 268 } else { 269 baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff; 270 tbaMask = ~baMask; 271 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 272 } 273 274 return (dmaAddr & DMA_ADDR_MASK); 275 } 276 } 277 } 278 279 return 0; 280} 281 282void 283TsunamiPChip::serialize(std::ostream &os) 284{ 285 SERIALIZE_ARRAY(wsba, 4); 286 SERIALIZE_ARRAY(wsm, 4); 287 SERIALIZE_ARRAY(tba, 4); 288} 289 290void 291TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 292{ 293 UNSERIALIZE_ARRAY(wsba, 4); 294 UNSERIALIZE_ARRAY(wsm, 4); 295 UNSERIALIZE_ARRAY(tba, 4); 296} 297 298BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 299 300 SimObjectParam<Tsunami *> tsunami; 301 SimObjectParam<MemoryController *> mmu; 302 Param<Addr> addr; 303 304END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 305 306BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 307 308 INIT_PARAM(tsunami, "Tsunami"), 309 INIT_PARAM(mmu, "Memory Controller"), 310 INIT_PARAM(addr, "Device Address") 311 312END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 313 314CREATE_SIM_OBJECT(TsunamiPChip) 315{ 316 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); 317} 318 319REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 320