Updated copyright on Tsunami and kern/linux files.
[gem5.git] / dev / tsunami_pchip.cc
1 /*
2 * Copyright (c) 2004 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 "cpu/exec_context.hh"
39 #include "dev/console.hh"
40 #include "dev/etherdev.hh"
41 #include "dev/scsi_ctrl.hh"
42 #include "dev/tlaser_clock.hh"
43 #include "dev/tsunami_pchip.hh"
44 #include "dev/tsunamireg.h"
45 #include "dev/tsunami.hh"
46 #include "mem/functional_mem/memory_control.hh"
47 #include "mem/functional_mem/physical_memory.hh"
48 #include "sim/builder.hh"
49 #include "sim/system.hh"
50
51 using namespace std;
52
53 TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
54 MemoryController *mmu)
55 : FunctionalMemory(name), addr(a), tsunami(t)
56 {
57 mmu->add_child(this, Range<Addr>(addr, addr + size));
58
59 for (int i = 0; i < 4; i++) {
60 wsba[i] = 0;
61 wsm[i] = 0;
62 tba[i] = 0;
63 }
64
65 //Set back pointer in tsunami
66 tsunami->pchip = this;
67 }
68
69 Fault
70 TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
71 {
72 DPRINTF(Tsunami, "read va=%#x size=%d\n",
73 req->vaddr, req->size);
74
75 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
76
77 switch (req->size) {
78
79 case sizeof(uint64_t):
80 switch(daddr) {
81 case TSDEV_PC_WSBA0:
82 *(uint64_t*)data = wsba[0];
83 return No_Fault;
84 case TSDEV_PC_WSBA1:
85 *(uint64_t*)data = wsba[1];
86 return No_Fault;
87 case TSDEV_PC_WSBA2:
88 *(uint64_t*)data = wsba[2];
89 return No_Fault;
90 case TSDEV_PC_WSBA3:
91 *(uint64_t*)data = wsba[3];
92 return No_Fault;
93 case TSDEV_PC_WSM0:
94 *(uint64_t*)data = wsm[0];
95 return No_Fault;
96 case TSDEV_PC_WSM1:
97 *(uint64_t*)data = wsm[1];
98 return No_Fault;
99 case TSDEV_PC_WSM2:
100 *(uint64_t*)data = wsm[2];
101 return No_Fault;
102 case TSDEV_PC_WSM3:
103 *(uint64_t*)data = wsm[3];
104 return No_Fault;
105 case TSDEV_PC_TBA0:
106 *(uint64_t*)data = tba[0];
107 return No_Fault;
108 case TSDEV_PC_TBA1:
109 *(uint64_t*)data = tba[1];
110 return No_Fault;
111 case TSDEV_PC_TBA2:
112 *(uint64_t*)data = tba[2];
113 return No_Fault;
114 case TSDEV_PC_TBA3:
115 *(uint64_t*)data = tba[3];
116 return No_Fault;
117 case TSDEV_PC_PCTL:
118 // might want to change the clock??
119 *(uint64_t*)data = 0x00; // try this
120 return No_Fault;
121 case TSDEV_PC_PLAT:
122 panic("PC_PLAT not implemented\n");
123 case TSDEV_PC_RES:
124 panic("PC_RES not implemented\n");
125 case TSDEV_PC_PERROR:
126 *(uint64_t*)data = 0x00;
127 return No_Fault;
128 case TSDEV_PC_PERRMASK:
129 *(uint64_t*)data = 0x00;
130 return No_Fault;
131 case TSDEV_PC_PERRSET:
132 panic("PC_PERRSET not implemented\n");
133 case TSDEV_PC_TLBIV:
134 panic("PC_TLBIV not implemented\n");
135 case TSDEV_PC_TLBIA:
136 *(uint64_t*)data = 0x00; // shouldn't be readable, but linux
137 return No_Fault;
138 case TSDEV_PC_PMONCTL:
139 panic("PC_PMONCTL not implemented\n");
140 case TSDEV_PC_PMONCNT:
141 panic("PC_PMONCTN not implemented\n");
142 default:
143 panic("Default in PChip Read reached reading 0x%x\n", daddr);
144
145 } // uint64_t
146
147 break;
148 case sizeof(uint32_t):
149 case sizeof(uint16_t):
150 case sizeof(uint8_t):
151 default:
152 panic("invalid access size(?) for tsunami register!\n\n");
153 }
154 DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
155
156 return No_Fault;
157 }
158
159 Fault
160 TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
161 {
162 DPRINTF(Tsunami, "write - va=%#x size=%d \n",
163 req->vaddr, req->size);
164
165 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
166
167 switch (req->size) {
168
169 case sizeof(uint64_t):
170 switch(daddr) {
171 case TSDEV_PC_WSBA0:
172 wsba[0] = *(uint64_t*)data;
173 return No_Fault;
174 case TSDEV_PC_WSBA1:
175 wsba[1] = *(uint64_t*)data;
176 return No_Fault;
177 case TSDEV_PC_WSBA2:
178 wsba[2] = *(uint64_t*)data;
179 return No_Fault;
180 case TSDEV_PC_WSBA3:
181 wsba[3] = *(uint64_t*)data;
182 return No_Fault;
183 case TSDEV_PC_WSM0:
184 wsm[0] = *(uint64_t*)data;
185 return No_Fault;
186 case TSDEV_PC_WSM1:
187 wsm[1] = *(uint64_t*)data;
188 return No_Fault;
189 case TSDEV_PC_WSM2:
190 wsm[2] = *(uint64_t*)data;
191 return No_Fault;
192 case TSDEV_PC_WSM3:
193 wsm[3] = *(uint64_t*)data;
194 return No_Fault;
195 case TSDEV_PC_TBA0:
196 tba[0] = *(uint64_t*)data;
197 return No_Fault;
198 case TSDEV_PC_TBA1:
199 tba[1] = *(uint64_t*)data;
200 return No_Fault;
201 case TSDEV_PC_TBA2:
202 tba[2] = *(uint64_t*)data;
203 return No_Fault;
204 case TSDEV_PC_TBA3:
205 tba[3] = *(uint64_t*)data;
206 return No_Fault;
207 case TSDEV_PC_PCTL:
208 // might want to change the clock??
209 return No_Fault;
210 case TSDEV_PC_PLAT:
211 panic("PC_PLAT not implemented\n");
212 case TSDEV_PC_RES:
213 panic("PC_RES not implemented\n");
214 case TSDEV_PC_PERROR:
215 return No_Fault;
216 case TSDEV_PC_PERRMASK:
217 panic("PC_PERRMASK not implemented\n");
218 case TSDEV_PC_PERRSET:
219 panic("PC_PERRSET not implemented\n");
220 case TSDEV_PC_TLBIV:
221 panic("PC_TLBIV not implemented\n");
222 case TSDEV_PC_TLBIA:
223 return No_Fault; // value ignored, supposted to invalidate SG TLB
224 case TSDEV_PC_PMONCTL:
225 panic("PC_PMONCTL not implemented\n");
226 case TSDEV_PC_PMONCNT:
227 panic("PC_PMONCTN not implemented\n");
228 default:
229 panic("Default in PChip Read reached reading 0x%x\n", daddr);
230
231 } // uint64_t
232
233 break;
234 case sizeof(uint32_t):
235 case sizeof(uint16_t):
236 case sizeof(uint8_t):
237 default:
238 panic("invalid access size(?) for tsunami register!\n\n");
239 }
240
241 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
242
243 return No_Fault;
244 }
245
246 #define DMA_ADDR_MASK ULL(0x3ffffffff)
247
248 Addr
249 TsunamiPChip::translatePciToDma(Addr busAddr)
250 {
251 // compare the address to the window base registers
252 uint64_t tbaMask = 0;
253 uint64_t baMask = 0;
254
255 uint64_t windowMask = 0;
256 uint64_t windowBase = 0;
257
258 uint64_t pteEntry = 0;
259
260 Addr pteAddr;
261 Addr dmaAddr;
262
263 for (int i = 0; i < 4; i++) {
264 windowBase = wsba[i];
265 windowMask = ~wsm[i] & (0x7ff << 20);
266
267 if ((busAddr & windowMask) == (windowBase & windowMask)) {
268
269
270 if (wsba[i] & 0x1) { // see if enabled
271 if (wsba[i] & 0x2) { // see if SG bit is set
272 /** @todo
273 This currently is faked by just doing a direct
274 read from memory, however, to be realistic, this
275 needs to actually do a bus transaction. The process
276 is explained in the tsunami documentation on page
277 10-12 and basically munges the address to look up a
278 PTE from a table in memory and then uses that mapping
279 to create an address for the SG page
280 */
281
282 tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff);
283 baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13);
284 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
285
286 memcpy((void *)&pteEntry,
287 tsunami->system->
288 physmem->dma_addr(pteAddr, sizeof(uint64_t)),
289 sizeof(uint64_t));
290
291 dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff);
292
293 } else {
294 baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff;
295 tbaMask = ~baMask;
296 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
297 }
298
299 return (dmaAddr & DMA_ADDR_MASK);
300 }
301 }
302 }
303
304 return 0;
305 }
306
307 void
308 TsunamiPChip::serialize(std::ostream &os)
309 {
310 SERIALIZE_ARRAY(wsba, 4);
311 SERIALIZE_ARRAY(wsm, 4);
312 SERIALIZE_ARRAY(tba, 4);
313 }
314
315 void
316 TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
317 {
318 UNSERIALIZE_ARRAY(wsba, 4);
319 UNSERIALIZE_ARRAY(wsm, 4);
320 UNSERIALIZE_ARRAY(tba, 4);
321 }
322
323 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
324
325 SimObjectParam<Tsunami *> tsunami;
326 SimObjectParam<MemoryController *> mmu;
327 Param<Addr> addr;
328
329 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
330
331 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
332
333 INIT_PARAM(tsunami, "Tsunami"),
334 INIT_PARAM(mmu, "Memory Controller"),
335 INIT_PARAM(addr, "Device Address")
336
337 END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
338
339 CREATE_SIM_OBJECT(TsunamiPChip)
340 {
341 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu);
342 }
343
344 REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)