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