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