Changes to untemplate StaticInst and StaticInstPtr, change the isa to a namespace...
[gem5.git] / dev / tsunami_pchip.cc
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /** @file
30 * Tsunami PChip (pci)
31 */
32
33 #include <deque>
34 #include <string>
35 #include <vector>
36
37 #include "base/trace.hh"
38 #include "dev/tsunami_pchip.hh"
39 #include "dev/tsunamireg.h"
40 #include "dev/tsunami.hh"
41 #include "mem/bus/bus.hh"
42 #include "mem/bus/pio_interface.hh"
43 #include "mem/bus/pio_interface_impl.hh"
44 #include "mem/functional/memory_control.hh"
45 #include "mem/functional/physical.hh"
46 #include "sim/builder.hh"
47 #include "sim/system.hh"
48
49 using namespace std;
50 //Should this be AlphaISA?
51 using namespace TheISA;
52
53 TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
54 MemoryController *mmu, HierParams *hier,
55 Bus *pio_bus, Tick pio_latency)
56 : PioDevice(name, t), addr(a), tsunami(t)
57 {
58 mmu->add_child(this, RangeSize(addr, size));
59
60 for (int i = 0; i < 4; i++) {
61 wsba[i] = 0;
62 wsm[i] = 0;
63 tba[i] = 0;
64 }
65
66 if (pio_bus) {
67 pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
68 &TsunamiPChip::cacheAccess);
69 pioInterface->addAddrRange(RangeSize(addr, size));
70 pioLatency = pio_latency * pio_bus->clockRate;
71 }
72
73
74 // initialize pchip control register
75 pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
76
77 //Set back pointer in tsunami
78 tsunami->pchip = this;
79 }
80
81 Fault *
82 TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
83 {
84 DPRINTF(Tsunami, "read va=%#x size=%d\n",
85 req->vaddr, req->size);
86
87 Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
88
89 switch (req->size) {
90
91 case sizeof(uint64_t):
92 switch(daddr) {
93 case TSDEV_PC_WSBA0:
94 *(uint64_t*)data = wsba[0];
95 return NoFault;
96 case TSDEV_PC_WSBA1:
97 *(uint64_t*)data = wsba[1];
98 return NoFault;
99 case TSDEV_PC_WSBA2:
100 *(uint64_t*)data = wsba[2];
101 return NoFault;
102 case TSDEV_PC_WSBA3:
103 *(uint64_t*)data = wsba[3];
104 return NoFault;
105 case TSDEV_PC_WSM0:
106 *(uint64_t*)data = wsm[0];
107 return NoFault;
108 case TSDEV_PC_WSM1:
109 *(uint64_t*)data = wsm[1];
110 return NoFault;
111 case TSDEV_PC_WSM2:
112 *(uint64_t*)data = wsm[2];
113 return NoFault;
114 case TSDEV_PC_WSM3:
115 *(uint64_t*)data = wsm[3];
116 return NoFault;
117 case TSDEV_PC_TBA0:
118 *(uint64_t*)data = tba[0];
119 return NoFault;
120 case TSDEV_PC_TBA1:
121 *(uint64_t*)data = tba[1];
122 return NoFault;
123 case TSDEV_PC_TBA2:
124 *(uint64_t*)data = tba[2];
125 return NoFault;
126 case TSDEV_PC_TBA3:
127 *(uint64_t*)data = tba[3];
128 return NoFault;
129 case TSDEV_PC_PCTL:
130 *(uint64_t*)data = pctl;
131 return NoFault;
132 case TSDEV_PC_PLAT:
133 panic("PC_PLAT not implemented\n");
134 case TSDEV_PC_RES:
135 panic("PC_RES not implemented\n");
136 case TSDEV_PC_PERROR:
137 *(uint64_t*)data = 0x00;
138 return NoFault;
139 case TSDEV_PC_PERRMASK:
140 *(uint64_t*)data = 0x00;
141 return NoFault;
142 case TSDEV_PC_PERRSET:
143 panic("PC_PERRSET not implemented\n");
144 case TSDEV_PC_TLBIV:
145 panic("PC_TLBIV not implemented\n");
146 case TSDEV_PC_TLBIA:
147 *(uint64_t*)data = 0x00; // shouldn't be readable, but linux
148 return NoFault;
149 case TSDEV_PC_PMONCTL:
150 panic("PC_PMONCTL not implemented\n");
151 case TSDEV_PC_PMONCNT:
152 panic("PC_PMONCTN not implemented\n");
153 default:
154 panic("Default in PChip Read reached reading 0x%x\n", daddr);
155
156 } // uint64_t
157
158 break;
159 case sizeof(uint32_t):
160 case sizeof(uint16_t):
161 case sizeof(uint8_t):
162 default:
163 panic("invalid access size(?) for tsunami register!\n\n");
164 }
165 DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
166
167 return NoFault;
168 }
169
170 Fault *
171 TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
172 {
173 DPRINTF(Tsunami, "write - va=%#x size=%d \n",
174 req->vaddr, req->size);
175
176 Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
177
178 switch (req->size) {
179
180 case sizeof(uint64_t):
181 switch(daddr) {
182 case TSDEV_PC_WSBA0:
183 wsba[0] = *(uint64_t*)data;
184 return NoFault;
185 case TSDEV_PC_WSBA1:
186 wsba[1] = *(uint64_t*)data;
187 return NoFault;
188 case TSDEV_PC_WSBA2:
189 wsba[2] = *(uint64_t*)data;
190 return NoFault;
191 case TSDEV_PC_WSBA3:
192 wsba[3] = *(uint64_t*)data;
193 return NoFault;
194 case TSDEV_PC_WSM0:
195 wsm[0] = *(uint64_t*)data;
196 return NoFault;
197 case TSDEV_PC_WSM1:
198 wsm[1] = *(uint64_t*)data;
199 return NoFault;
200 case TSDEV_PC_WSM2:
201 wsm[2] = *(uint64_t*)data;
202 return NoFault;
203 case TSDEV_PC_WSM3:
204 wsm[3] = *(uint64_t*)data;
205 return NoFault;
206 case TSDEV_PC_TBA0:
207 tba[0] = *(uint64_t*)data;
208 return NoFault;
209 case TSDEV_PC_TBA1:
210 tba[1] = *(uint64_t*)data;
211 return NoFault;
212 case TSDEV_PC_TBA2:
213 tba[2] = *(uint64_t*)data;
214 return NoFault;
215 case TSDEV_PC_TBA3:
216 tba[3] = *(uint64_t*)data;
217 return NoFault;
218 case TSDEV_PC_PCTL:
219 pctl = *(uint64_t*)data;
220 return NoFault;
221 case TSDEV_PC_PLAT:
222 panic("PC_PLAT not implemented\n");
223 case TSDEV_PC_RES:
224 panic("PC_RES not implemented\n");
225 case TSDEV_PC_PERROR:
226 return NoFault;
227 case TSDEV_PC_PERRMASK:
228 panic("PC_PERRMASK not implemented\n");
229 case TSDEV_PC_PERRSET:
230 panic("PC_PERRSET not implemented\n");
231 case TSDEV_PC_TLBIV:
232 panic("PC_TLBIV not implemented\n");
233 case TSDEV_PC_TLBIA:
234 return NoFault; // value ignored, supposted to invalidate SG TLB
235 case TSDEV_PC_PMONCTL:
236 panic("PC_PMONCTL not implemented\n");
237 case TSDEV_PC_PMONCNT:
238 panic("PC_PMONCTN not implemented\n");
239 default:
240 panic("Default in PChip Read reached reading 0x%x\n", daddr);
241
242 } // uint64_t
243
244 break;
245 case sizeof(uint32_t):
246 case sizeof(uint16_t):
247 case sizeof(uint8_t):
248 default:
249 panic("invalid access size(?) for tsunami register!\n\n");
250 }
251
252 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
253
254 return NoFault;
255 }
256
257 #define DMA_ADDR_MASK ULL(0x3ffffffff)
258
259 Addr
260 TsunamiPChip::translatePciToDma(Addr busAddr)
261 {
262 // compare the address to the window base registers
263 uint64_t tbaMask = 0;
264 uint64_t baMask = 0;
265
266 uint64_t windowMask = 0;
267 uint64_t windowBase = 0;
268
269 uint64_t pteEntry = 0;
270
271 Addr pteAddr;
272 Addr dmaAddr;
273
274 #if 0
275 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
276 for (int i = 0; i < 4; i++) {
277 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
278 i, wsba[i], wsm[i]);
279
280 windowBase = wsba[i];
281 windowMask = ~wsm[i] & (ULL(0xfff) << 20);
282
283 if ((busAddr & windowMask) == (windowBase & windowMask)) {
284 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
285 i, windowBase, windowMask, (busAddr & windowMask),
286 (windowBase & windowMask));
287 }
288 }
289 #endif
290
291 for (int i = 0; i < 4; i++) {
292
293 windowBase = wsba[i];
294 windowMask = ~wsm[i] & (ULL(0xfff) << 20);
295
296 if ((busAddr & windowMask) == (windowBase & windowMask)) {
297
298 if (wsba[i] & 0x1) { // see if enabled
299 if (wsba[i] & 0x2) { // see if SG bit is set
300 /** @todo
301 This currently is faked by just doing a direct
302 read from memory, however, to be realistic, this
303 needs to actually do a bus transaction. The process
304 is explained in the tsunami documentation on page
305 10-12 and basically munges the address to look up a
306 PTE from a table in memory and then uses that mapping
307 to create an address for the SG page
308 */
309
310 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
311 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
312 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
313
314 memcpy((void *)&pteEntry,
315 tsunami->system->
316 physmem->dma_addr(pteAddr, sizeof(uint64_t)),
317 sizeof(uint64_t));
318
319 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
320
321 } else {
322 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
323 tbaMask = ~baMask;
324 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
325 }
326
327 return (dmaAddr & DMA_ADDR_MASK);
328 }
329 }
330 }
331
332 // if no match was found, then return the original address
333 return busAddr;
334 }
335
336 void
337 TsunamiPChip::serialize(std::ostream &os)
338 {
339 SERIALIZE_SCALAR(pctl);
340 SERIALIZE_ARRAY(wsba, 4);
341 SERIALIZE_ARRAY(wsm, 4);
342 SERIALIZE_ARRAY(tba, 4);
343 }
344
345 void
346 TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
347 {
348 UNSERIALIZE_SCALAR(pctl);
349 UNSERIALIZE_ARRAY(wsba, 4);
350 UNSERIALIZE_ARRAY(wsm, 4);
351 UNSERIALIZE_ARRAY(tba, 4);
352 }
353
354 Tick
355 TsunamiPChip::cacheAccess(MemReqPtr &req)
356 {
357 return curTick + pioLatency;
358 }
359
360 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
361
362 SimObjectParam<Tsunami *> tsunami;
363 SimObjectParam<MemoryController *> mmu;
364 Param<Addr> addr;
365 SimObjectParam<Bus*> pio_bus;
366 Param<Tick> pio_latency;
367 SimObjectParam<HierParams *> hier;
368
369 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
370
371 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
372
373 INIT_PARAM(tsunami, "Tsunami"),
374 INIT_PARAM(mmu, "Memory Controller"),
375 INIT_PARAM(addr, "Device Address"),
376 INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL),
377 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
378 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
379
380 END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
381
382 CREATE_SIM_OBJECT(TsunamiPChip)
383 {
384 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier,
385 pio_bus, pio_latency);
386 }
387
388 REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)