manual merge of linux_system and makefile
[gem5.git] / dev / tsunami_pchip.cc
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
25 using namespace std;
26
27 TsunamiPChip::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
43 Fault
44 TsunamiPChip::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
133 Fault
134 TsunamiPChip::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
223 Addr
224 TsunamiPChip::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 & 0x1fff);
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
282 void
283 TsunamiPChip::serialize(std::ostream &os)
284 {
285 SERIALIZE_ARRAY(wsba, 4);
286 SERIALIZE_ARRAY(wsm, 4);
287 SERIALIZE_ARRAY(tba, 4);
288 }
289
290 void
291 TsunamiPChip::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
298 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
299
300 SimObjectParam<Tsunami *> tsunami;
301 SimObjectParam<MemoryController *> mmu;
302 Param<Addr> addr;
303
304 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
305
306 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
307
308 INIT_PARAM(tsunami, "Tsunami"),
309 INIT_PARAM(mmu, "Memory Controller"),
310 INIT_PARAM(addr, "Device Address")
311
312 END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
313
314 CREATE_SIM_OBJECT(TsunamiPChip)
315 {
316 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu);
317 }
318
319 REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)