tsunami_pchip.cc revision 857
13691Shsul@eecs.umich.edu/* $Id$ */
23691Shsul@eecs.umich.edu
33691Shsul@eecs.umich.edu/* @file
43691Shsul@eecs.umich.edu * Tsunami PChip (pci)
53691Shsul@eecs.umich.edu */
63691Shsul@eecs.umich.edu
73691Shsul@eecs.umich.edu#include <deque>
83691Shsul@eecs.umich.edu#include <string>
93691Shsul@eecs.umich.edu#include <vector>
103691Shsul@eecs.umich.edu
113691Shsul@eecs.umich.edu#include "base/trace.hh"
123691Shsul@eecs.umich.edu#include "cpu/exec_context.hh"
133691Shsul@eecs.umich.edu#include "dev/console.hh"
143691Shsul@eecs.umich.edu#include "dev/etherdev.hh"
153691Shsul@eecs.umich.edu#include "dev/scsi_ctrl.hh"
163691Shsul@eecs.umich.edu#include "dev/tlaser_clock.hh"
173691Shsul@eecs.umich.edu#include "dev/tsunami_pchip.hh"
183691Shsul@eecs.umich.edu#include "dev/tsunamireg.h"
193691Shsul@eecs.umich.edu#include "dev/tsunami.hh"
203691Shsul@eecs.umich.edu#include "mem/functional_mem/memory_control.hh"
213691Shsul@eecs.umich.edu#include "mem/functional_mem/physical_memory.hh"
223691Shsul@eecs.umich.edu#include "sim/builder.hh"
233691Shsul@eecs.umich.edu#include "sim/system.hh"
243691Shsul@eecs.umich.edu
253691Shsul@eecs.umich.eduusing namespace std;
263691Shsul@eecs.umich.edu
273691Shsul@eecs.umich.eduTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
283691Shsul@eecs.umich.edu                           MemoryController *mmu)
293691Shsul@eecs.umich.edu    : FunctionalMemory(name), addr(a), tsunami(t)
303691Shsul@eecs.umich.edu{
316654Snate@binkert.org    mmu->add_child(this, Range<Addr>(addr, addr + size));
323691Shsul@eecs.umich.edu
333691Shsul@eecs.umich.edu    for (int i = 0; i < 4; i++) {
343691Shsul@eecs.umich.edu        wsba[i] = 0;
359826Sandreas.hansson@arm.com        wsm[i] = 0;
369826Sandreas.hansson@arm.com        tba[i] = 0;
379793Sakash.bagdia@arm.com    }
389827Sakash.bagdia@arm.com
399827Sakash.bagdia@arm.com    //Set back pointer in tsunami
409827Sakash.bagdia@arm.com    tsunami->pchip = this;
419793Sakash.bagdia@arm.com}
429827Sakash.bagdia@arm.com
439827Sakash.bagdia@arm.comFault
449793Sakash.bagdia@arm.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data)
453691Shsul@eecs.umich.edu{
468876Sandreas.hansson@arm.com    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
478876Sandreas.hansson@arm.com            req->vaddr, req->size);
487876Sgblack@eecs.umich.edu
499793Sakash.bagdia@arm.com    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
509793Sakash.bagdia@arm.com//    ExecContext *xc = req->xc;
519793Sakash.bagdia@arm.com//    int cpuid = xc->cpu_id;
529827Sakash.bagdia@arm.com
539827Sakash.bagdia@arm.com    switch (req->size) {
549827Sakash.bagdia@arm.com
559793Sakash.bagdia@arm.com      case sizeof(uint64_t):
569793Sakash.bagdia@arm.com          switch(daddr) {
579827Sakash.bagdia@arm.com              case TSDEV_PC_WSBA0:
589827Sakash.bagdia@arm.com                    *(uint64_t*)data = wsba[0];
599827Sakash.bagdia@arm.com                    return No_Fault;
609793Sakash.bagdia@arm.com              case TSDEV_PC_WSBA1:
618713Sandreas.hansson@arm.com                    *(uint64_t*)data = wsba[1];
628713Sandreas.hansson@arm.com                    return No_Fault;
638713Sandreas.hansson@arm.com              case TSDEV_PC_WSBA2:
649408Sandreas.hansson@arm.com                    *(uint64_t*)data = wsba[2];
658839Sandreas.hansson@arm.com                    return No_Fault;
668839Sandreas.hansson@arm.com              case TSDEV_PC_WSBA3:
673691Shsul@eecs.umich.edu                    *(uint64_t*)data = wsba[3];
689826Sandreas.hansson@arm.com                    return No_Fault;
699826Sandreas.hansson@arm.com              case TSDEV_PC_WSM0:
709826Sandreas.hansson@arm.com                    *(uint64_t*)data = wsm[0];
719826Sandreas.hansson@arm.com                    return No_Fault;
723691Shsul@eecs.umich.edu              case TSDEV_PC_WSM1:
739827Sakash.bagdia@arm.com                    *(uint64_t*)data = wsm[1];
749827Sakash.bagdia@arm.com                    return No_Fault;
759793Sakash.bagdia@arm.com              case TSDEV_PC_WSM2:
769827Sakash.bagdia@arm.com                    *(uint64_t*)data = wsm[2];
779827Sakash.bagdia@arm.com                    return No_Fault;
789827Sakash.bagdia@arm.com              case TSDEV_PC_WSM3:
793691Shsul@eecs.umich.edu                    *(uint64_t*)data = wsm[3];
808876Sandreas.hansson@arm.com                    return No_Fault;
818876Sandreas.hansson@arm.com              case TSDEV_PC_TBA0:
827876Sgblack@eecs.umich.edu                    *(uint64_t*)data = tba[0];
839793Sakash.bagdia@arm.com                    return No_Fault;
849793Sakash.bagdia@arm.com              case TSDEV_PC_TBA1:
859793Sakash.bagdia@arm.com                    *(uint64_t*)data = tba[1];
869827Sakash.bagdia@arm.com                    return No_Fault;
879827Sakash.bagdia@arm.com              case TSDEV_PC_TBA2:
889827Sakash.bagdia@arm.com                    *(uint64_t*)data = tba[2];
899793Sakash.bagdia@arm.com                    return No_Fault;
909793Sakash.bagdia@arm.com              case TSDEV_PC_TBA3:
919827Sakash.bagdia@arm.com                    *(uint64_t*)data = tba[3];
929827Sakash.bagdia@arm.com                    return No_Fault;
939827Sakash.bagdia@arm.com              case TSDEV_PC_PCTL:
949793Sakash.bagdia@arm.com                    // might want to change the clock??
959408Sandreas.hansson@arm.com                    *(uint64_t*)data = 0x00; // try this
968839Sandreas.hansson@arm.com                    return No_Fault;
978839Sandreas.hansson@arm.com              case TSDEV_PC_PLAT:
983691Shsul@eecs.umich.edu                    panic("PC_PLAT not implemented\n");
999826Sandreas.hansson@arm.com              case TSDEV_PC_RES:
1009826Sandreas.hansson@arm.com                    panic("PC_RES not implemented\n");
1019826Sandreas.hansson@arm.com              case TSDEV_PC_PERROR:
1028801Sgblack@eecs.umich.edu                    panic("PC_PERROR not implemented\n");
1033691Shsul@eecs.umich.edu              case TSDEV_PC_PERRMASK:
1043691Shsul@eecs.umich.edu                    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