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 &section)
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