tsunami_pchip.cc revision 896
112922Sgabeblack@google.com/* $Id$ */ 212922Sgabeblack@google.com 312922Sgabeblack@google.com/* @file 412922Sgabeblack@google.com * Tsunami PChip (pci) 512922Sgabeblack@google.com */ 612922Sgabeblack@google.com 712922Sgabeblack@google.com#include <deque> 812922Sgabeblack@google.com#include <string> 912922Sgabeblack@google.com#include <vector> 1012922Sgabeblack@google.com 1112922Sgabeblack@google.com#include "base/trace.hh" 1212922Sgabeblack@google.com#include "cpu/exec_context.hh" 1312922Sgabeblack@google.com#include "dev/console.hh" 1412922Sgabeblack@google.com#include "dev/etherdev.hh" 1512922Sgabeblack@google.com#include "dev/scsi_ctrl.hh" 1612922Sgabeblack@google.com#include "dev/tlaser_clock.hh" 1712922Sgabeblack@google.com#include "dev/tsunami_pchip.hh" 1812922Sgabeblack@google.com#include "dev/tsunamireg.h" 1912922Sgabeblack@google.com#include "dev/tsunami.hh" 2012922Sgabeblack@google.com#include "mem/functional_mem/memory_control.hh" 2112922Sgabeblack@google.com#include "mem/functional_mem/physical_memory.hh" 2212922Sgabeblack@google.com#include "sim/builder.hh" 2312922Sgabeblack@google.com#include "sim/system.hh" 2412922Sgabeblack@google.com 2512922Sgabeblack@google.comusing namespace std; 2612922Sgabeblack@google.com 2712922Sgabeblack@google.comTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 2812922Sgabeblack@google.com MemoryController *mmu) 2912922Sgabeblack@google.com : FunctionalMemory(name), addr(a), tsunami(t) 3012922Sgabeblack@google.com{ 3112922Sgabeblack@google.com mmu->add_child(this, Range<Addr>(addr, addr + size)); 3212922Sgabeblack@google.com 3312922Sgabeblack@google.com for (int i = 0; i < 4; i++) { 3412922Sgabeblack@google.com wsba[i] = 0; 3512922Sgabeblack@google.com wsm[i] = 0; 3612922Sgabeblack@google.com tba[i] = 0; 3712922Sgabeblack@google.com } 3812922Sgabeblack@google.com 3912922Sgabeblack@google.com // initialize pchip control register 4012922Sgabeblack@google.com pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 4112922Sgabeblack@google.com 4212922Sgabeblack@google.com //Set back pointer in tsunami 4312922Sgabeblack@google.com tsunami->pchip = this; 4412922Sgabeblack@google.com} 4512922Sgabeblack@google.com 4612922Sgabeblack@google.comFault 4712922Sgabeblack@google.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 4812922Sgabeblack@google.com{ 4912922Sgabeblack@google.com DPRINTF(Tsunami, "read va=%#x size=%d\n", 5012922Sgabeblack@google.com req->vaddr, req->size); 5112922Sgabeblack@google.com 5212922Sgabeblack@google.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 5312922Sgabeblack@google.com 5412922Sgabeblack@google.com switch (req->size) { 5512922Sgabeblack@google.com 5612922Sgabeblack@google.com case sizeof(uint64_t): 5712922Sgabeblack@google.com switch(daddr) { 5812922Sgabeblack@google.com case TSDEV_PC_WSBA0: 5912922Sgabeblack@google.com *(uint64_t*)data = wsba[0]; 6012922Sgabeblack@google.com return No_Fault; 6112922Sgabeblack@google.com case TSDEV_PC_WSBA1: 6212922Sgabeblack@google.com *(uint64_t*)data = wsba[1]; 6312922Sgabeblack@google.com return No_Fault; 6412922Sgabeblack@google.com case TSDEV_PC_WSBA2: 6512922Sgabeblack@google.com *(uint64_t*)data = wsba[2]; 6612922Sgabeblack@google.com return No_Fault; 6712922Sgabeblack@google.com case TSDEV_PC_WSBA3: 6812922Sgabeblack@google.com *(uint64_t*)data = wsba[3]; 6912922Sgabeblack@google.com return No_Fault; 7012922Sgabeblack@google.com case TSDEV_PC_WSM0: 7112922Sgabeblack@google.com *(uint64_t*)data = wsm[0]; 7212922Sgabeblack@google.com return No_Fault; 7312922Sgabeblack@google.com case TSDEV_PC_WSM1: 7412922Sgabeblack@google.com *(uint64_t*)data = wsm[1]; 7512922Sgabeblack@google.com return No_Fault; 7612922Sgabeblack@google.com case TSDEV_PC_WSM2: 7712922Sgabeblack@google.com *(uint64_t*)data = wsm[2]; 7812922Sgabeblack@google.com return No_Fault; 7912922Sgabeblack@google.com case TSDEV_PC_WSM3: 8012922Sgabeblack@google.com *(uint64_t*)data = wsm[3]; 8112922Sgabeblack@google.com return No_Fault; 8212922Sgabeblack@google.com case TSDEV_PC_TBA0: 8312922Sgabeblack@google.com *(uint64_t*)data = tba[0]; 8412922Sgabeblack@google.com return No_Fault; 8512922Sgabeblack@google.com case TSDEV_PC_TBA1: 8612922Sgabeblack@google.com *(uint64_t*)data = tba[1]; 8712922Sgabeblack@google.com return No_Fault; 8812922Sgabeblack@google.com case TSDEV_PC_TBA2: 8912922Sgabeblack@google.com *(uint64_t*)data = tba[2]; 9012922Sgabeblack@google.com return No_Fault; 9112922Sgabeblack@google.com case TSDEV_PC_TBA3: 9212922Sgabeblack@google.com *(uint64_t*)data = tba[3]; 9312922Sgabeblack@google.com return No_Fault; 9412922Sgabeblack@google.com case TSDEV_PC_PCTL: 9512922Sgabeblack@google.com *(uint64_t*)data = pctl; 9612922Sgabeblack@google.com return No_Fault; 9712922Sgabeblack@google.com case TSDEV_PC_PLAT: 9812922Sgabeblack@google.com panic("PC_PLAT not implemented\n"); 9912922Sgabeblack@google.com case TSDEV_PC_RES: 10012922Sgabeblack@google.com panic("PC_RES not implemented\n"); 10112922Sgabeblack@google.com case TSDEV_PC_PERROR: 10212922Sgabeblack@google.com panic("PC_PERROR not implemented\n"); 10312922Sgabeblack@google.com case TSDEV_PC_PERRMASK: 10412922Sgabeblack@google.com panic("PC_PERRMASK not implemented\n"); 10512922Sgabeblack@google.com case TSDEV_PC_PERRSET: 10612922Sgabeblack@google.com panic("PC_PERRSET not implemented\n"); 10712922Sgabeblack@google.com case TSDEV_PC_TLBIV: 10812922Sgabeblack@google.com panic("PC_TLBIV not implemented\n"); 10912922Sgabeblack@google.com case TSDEV_PC_TLBIA: 11012922Sgabeblack@google.com *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 11112922Sgabeblack@google.com return No_Fault; 11212922Sgabeblack@google.com case TSDEV_PC_PMONCTL: 11312922Sgabeblack@google.com panic("PC_PMONCTL not implemented\n"); 11412922Sgabeblack@google.com case TSDEV_PC_PMONCNT: 11512922Sgabeblack@google.com panic("PC_PMONCTN not implemented\n"); 11612922Sgabeblack@google.com default: 11712922Sgabeblack@google.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 11812922Sgabeblack@google.com 11912922Sgabeblack@google.com } // uint64_t 12012922Sgabeblack@google.com 12112922Sgabeblack@google.com break; 12212922Sgabeblack@google.com case sizeof(uint32_t): 12312922Sgabeblack@google.com case sizeof(uint16_t): 12412922Sgabeblack@google.com case sizeof(uint8_t): 12512922Sgabeblack@google.com default: 12612922Sgabeblack@google.com panic("invalid access size(?) for tsunami register!\n\n"); 12712922Sgabeblack@google.com } 12812922Sgabeblack@google.com DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 12912922Sgabeblack@google.com 13012922Sgabeblack@google.com return No_Fault; 13112922Sgabeblack@google.com} 13212922Sgabeblack@google.com 13312922Sgabeblack@google.comFault 13412922Sgabeblack@google.comTsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 13512922Sgabeblack@google.com{ 13612922Sgabeblack@google.com DPRINTF(Tsunami, "write - va=%#x size=%d \n", 13712922Sgabeblack@google.com req->vaddr, req->size); 13812922Sgabeblack@google.com 13912922Sgabeblack@google.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 14012922Sgabeblack@google.com 14112922Sgabeblack@google.com switch (req->size) { 14212922Sgabeblack@google.com 14312922Sgabeblack@google.com case sizeof(uint64_t): 14412922Sgabeblack@google.com switch(daddr) { 14512922Sgabeblack@google.com case TSDEV_PC_WSBA0: 14612922Sgabeblack@google.com wsba[0] = *(uint64_t*)data; 14712922Sgabeblack@google.com return No_Fault; 14812922Sgabeblack@google.com case TSDEV_PC_WSBA1: 14912922Sgabeblack@google.com wsba[1] = *(uint64_t*)data; 15012922Sgabeblack@google.com return No_Fault; 15112922Sgabeblack@google.com case TSDEV_PC_WSBA2: 15212922Sgabeblack@google.com wsba[2] = *(uint64_t*)data; 15312922Sgabeblack@google.com return No_Fault; 15412922Sgabeblack@google.com case TSDEV_PC_WSBA3: 15512922Sgabeblack@google.com wsba[3] = *(uint64_t*)data; 15612922Sgabeblack@google.com return No_Fault; 15712922Sgabeblack@google.com case TSDEV_PC_WSM0: 15812922Sgabeblack@google.com wsm[0] = *(uint64_t*)data; 15912922Sgabeblack@google.com return No_Fault; 16012922Sgabeblack@google.com case TSDEV_PC_WSM1: 16112922Sgabeblack@google.com wsm[1] = *(uint64_t*)data; 16212922Sgabeblack@google.com return No_Fault; 16312922Sgabeblack@google.com case TSDEV_PC_WSM2: 16412922Sgabeblack@google.com wsm[2] = *(uint64_t*)data; 16512922Sgabeblack@google.com return No_Fault; 16612922Sgabeblack@google.com case TSDEV_PC_WSM3: 16712922Sgabeblack@google.com wsm[3] = *(uint64_t*)data; 16812922Sgabeblack@google.com return No_Fault; 16912922Sgabeblack@google.com case TSDEV_PC_TBA0: 17012922Sgabeblack@google.com tba[0] = *(uint64_t*)data; 17112922Sgabeblack@google.com return No_Fault; 17212922Sgabeblack@google.com case TSDEV_PC_TBA1: 17312922Sgabeblack@google.com tba[1] = *(uint64_t*)data; 17412922Sgabeblack@google.com return No_Fault; 17512922Sgabeblack@google.com case TSDEV_PC_TBA2: 17612922Sgabeblack@google.com tba[2] = *(uint64_t*)data; 17712922Sgabeblack@google.com return No_Fault; 17812922Sgabeblack@google.com case TSDEV_PC_TBA3: 17912922Sgabeblack@google.com tba[3] = *(uint64_t*)data; 18012922Sgabeblack@google.com return No_Fault; 18112922Sgabeblack@google.com case TSDEV_PC_PCTL: 18212922Sgabeblack@google.com pctl = *(uint64_t*)data; 18312922Sgabeblack@google.com return No_Fault; 18412922Sgabeblack@google.com case TSDEV_PC_PLAT: 18512922Sgabeblack@google.com panic("PC_PLAT not implemented\n"); 18612922Sgabeblack@google.com case TSDEV_PC_RES: 18712922Sgabeblack@google.com panic("PC_RES not implemented\n"); 18812922Sgabeblack@google.com case TSDEV_PC_PERROR: 18912922Sgabeblack@google.com panic("PC_PERROR not implemented\n"); 19012922Sgabeblack@google.com case TSDEV_PC_PERRMASK: 19112922Sgabeblack@google.com panic("PC_PERRMASK not implemented\n"); 19212922Sgabeblack@google.com case TSDEV_PC_PERRSET: 19312922Sgabeblack@google.com panic("PC_PERRSET not implemented\n"); 19412922Sgabeblack@google.com case TSDEV_PC_TLBIV: 19512922Sgabeblack@google.com panic("PC_TLBIV not implemented\n"); 19612922Sgabeblack@google.com case TSDEV_PC_TLBIA: 19712922Sgabeblack@google.com return No_Fault; // value ignored, supposted to invalidate SG TLB 19812922Sgabeblack@google.com case TSDEV_PC_PMONCTL: 19912922Sgabeblack@google.com panic("PC_PMONCTL not implemented\n"); 20012922Sgabeblack@google.com case TSDEV_PC_PMONCNT: 20112922Sgabeblack@google.com panic("PC_PMONCTN not implemented\n"); 20212922Sgabeblack@google.com default: 20312922Sgabeblack@google.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 20412922Sgabeblack@google.com 20512922Sgabeblack@google.com } // uint64_t 20612922Sgabeblack@google.com 20712922Sgabeblack@google.com break; 20812922Sgabeblack@google.com case sizeof(uint32_t): 20912922Sgabeblack@google.com case sizeof(uint16_t): 21012922Sgabeblack@google.com case sizeof(uint8_t): 21112922Sgabeblack@google.com default: 21212922Sgabeblack@google.com panic("invalid access size(?) for tsunami register!\n\n"); 21312922Sgabeblack@google.com } 21412922Sgabeblack@google.com 21512922Sgabeblack@google.com DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 21612922Sgabeblack@google.com 21712922Sgabeblack@google.com return No_Fault; 21812922Sgabeblack@google.com} 21912922Sgabeblack@google.com 22012922Sgabeblack@google.com#define DMA_ADDR_MASK ULL(0x3ffffffff) 22112922Sgabeblack@google.com 22212922Sgabeblack@google.comAddr 22312922Sgabeblack@google.comTsunamiPChip::translatePciToDma(Addr busAddr) 22412922Sgabeblack@google.com{ 22512922Sgabeblack@google.com // compare the address to the window base registers 22612922Sgabeblack@google.com uint64_t tbaMask = 0; 22712922Sgabeblack@google.com uint64_t baMask = 0; 22812922Sgabeblack@google.com 22912922Sgabeblack@google.com uint64_t windowMask = 0; 23012922Sgabeblack@google.com uint64_t windowBase = 0; 23112922Sgabeblack@google.com 23212922Sgabeblack@google.com uint64_t pteEntry = 0; 23312922Sgabeblack@google.com 23412922Sgabeblack@google.com Addr pteAddr; 23512922Sgabeblack@google.com Addr dmaAddr; 23612922Sgabeblack@google.com 23712922Sgabeblack@google.com#if 0 23812922Sgabeblack@google.com DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 23912922Sgabeblack@google.com for (int i = 0; i < 4; i++) { 24012922Sgabeblack@google.com DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 24112922Sgabeblack@google.com i, wsba[i], wsm[i]); 24212922Sgabeblack@google.com 24312922Sgabeblack@google.com windowBase = wsba[i]; 24412922Sgabeblack@google.com windowMask = ~wsm[i] & (ULL(0xfff) << 20); 24512922Sgabeblack@google.com 24612922Sgabeblack@google.com if ((busAddr & windowMask) == (windowBase & windowMask)) { 24712922Sgabeblack@google.com DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 24812922Sgabeblack@google.com i, windowBase, windowMask, (busAddr & windowMask), 24912922Sgabeblack@google.com (windowBase & windowMask)); 25012922Sgabeblack@google.com } 25112922Sgabeblack@google.com } 25212922Sgabeblack@google.com#endif 25312922Sgabeblack@google.com 25412922Sgabeblack@google.com for (int i = 0; i < 4; i++) { 25512922Sgabeblack@google.com 25612922Sgabeblack@google.com windowBase = wsba[i]; 25712922Sgabeblack@google.com windowMask = ~wsm[i] & (ULL(0xfff) << 20); 25812922Sgabeblack@google.com 25912922Sgabeblack@google.com if ((busAddr & windowMask) == (windowBase & windowMask)) { 26012922Sgabeblack@google.com 26112922Sgabeblack@google.com if (wsba[i] & 0x1) { // see if enabled 26212922Sgabeblack@google.com if (wsba[i] & 0x2) { // see if SG bit is set 26312922Sgabeblack@google.com /** @todo 26412922Sgabeblack@google.com This currently is faked by just doing a direct 26512922Sgabeblack@google.com read from memory, however, to be realistic, this 26612922Sgabeblack@google.com needs to actually do a bus transaction. The process 26712922Sgabeblack@google.com is explained in the tsunami documentation on page 26812922Sgabeblack@google.com 10-12 and basically munges the address to look up a 26912922Sgabeblack@google.com PTE from a table in memory and then uses that mapping 27012922Sgabeblack@google.com to create an address for the SG page 27112922Sgabeblack@google.com */ 27212922Sgabeblack@google.com 27312922Sgabeblack@google.com tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 27412922Sgabeblack@google.com baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 27512922Sgabeblack@google.com pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 27612922Sgabeblack@google.com 27712922Sgabeblack@google.com memcpy((void *)&pteEntry, 27812922Sgabeblack@google.com tsunami->system-> 27912922Sgabeblack@google.com physmem->dma_addr(pteAddr, sizeof(uint64_t)), 28012922Sgabeblack@google.com sizeof(uint64_t)); 28112922Sgabeblack@google.com 28212922Sgabeblack@google.com dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 28312922Sgabeblack@google.com 28412922Sgabeblack@google.com } else { 28512922Sgabeblack@google.com baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 28612922Sgabeblack@google.com tbaMask = ~baMask; 28712922Sgabeblack@google.com dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 28812922Sgabeblack@google.com } 28912922Sgabeblack@google.com 29012922Sgabeblack@google.com return (dmaAddr & DMA_ADDR_MASK); 29112922Sgabeblack@google.com } 29212922Sgabeblack@google.com } 29312922Sgabeblack@google.com } 29412922Sgabeblack@google.com 29512922Sgabeblack@google.com // if no match was found, then return the original address 29612922Sgabeblack@google.com return busAddr; 29712922Sgabeblack@google.com} 29812922Sgabeblack@google.com 29912922Sgabeblack@google.comvoid 30012922Sgabeblack@google.comTsunamiPChip::serialize(std::ostream &os) 30112922Sgabeblack@google.com{ 30212922Sgabeblack@google.com SERIALIZE_SCALAR(pctl); 30312922Sgabeblack@google.com SERIALIZE_ARRAY(wsba, 4); 30412922Sgabeblack@google.com SERIALIZE_ARRAY(wsm, 4); 30512922Sgabeblack@google.com SERIALIZE_ARRAY(tba, 4); 30612922Sgabeblack@google.com} 30712922Sgabeblack@google.com 30812922Sgabeblack@google.comvoid 30912922Sgabeblack@google.comTsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 31012922Sgabeblack@google.com{ 31112922Sgabeblack@google.com UNSERIALIZE_SCALAR(pctl); 31212922Sgabeblack@google.com UNSERIALIZE_ARRAY(wsba, 4); 31312922Sgabeblack@google.com UNSERIALIZE_ARRAY(wsm, 4); 31412922Sgabeblack@google.com UNSERIALIZE_ARRAY(tba, 4); 31512922Sgabeblack@google.com} 31612922Sgabeblack@google.com 31712922Sgabeblack@google.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 31812922Sgabeblack@google.com 31912922Sgabeblack@google.com SimObjectParam<Tsunami *> tsunami; 32012922Sgabeblack@google.com SimObjectParam<MemoryController *> mmu; 32112922Sgabeblack@google.com Param<Addr> addr; 32212922Sgabeblack@google.com 32312922Sgabeblack@google.comEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 32412922Sgabeblack@google.com 32512922Sgabeblack@google.comBEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 32612922Sgabeblack@google.com 32712922Sgabeblack@google.com INIT_PARAM(tsunami, "Tsunami"), 32812922Sgabeblack@google.com INIT_PARAM(mmu, "Memory Controller"), 32912922Sgabeblack@google.com INIT_PARAM(addr, "Device Address") 33012922Sgabeblack@google.com 33112922Sgabeblack@google.comEND_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 33212922Sgabeblack@google.com 33312922Sgabeblack@google.comCREATE_SIM_OBJECT(TsunamiPChip) 334{ 335 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); 336} 337 338REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 339