tsunami_pchip.cc revision 892
14120Sgblack@eecs.umich.edu/*
211274Sshingarov@labware.com * Copyright (c) 2004 The Regents of The University of Michigan
310600Sgabeblack@google.com * All rights reserved.
44120Sgblack@eecs.umich.edu *
54120Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
64120Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77087Snate@binkert.org * met: redistributions of source code must retain the above copyright
87087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117087Snate@binkert.org * documentation and/or other materials provided with the distribution;
127087Snate@binkert.org * neither the name of the copyright holders nor the names of its
137087Snate@binkert.org * contributors may be used to endorse or promote products derived from
147087Snate@binkert.org * this software without specific prior written permission.
154120Sgblack@eecs.umich.edu *
167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257087Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274120Sgblack@eecs.umich.edu */
284120Sgblack@eecs.umich.edu
294120Sgblack@eecs.umich.edu/* @file
304120Sgblack@eecs.umich.edu * Tsunami PChip (pci)
314120Sgblack@eecs.umich.edu */
324120Sgblack@eecs.umich.edu
334120Sgblack@eecs.umich.edu#include <deque>
344120Sgblack@eecs.umich.edu#include <string>
354120Sgblack@eecs.umich.edu#include <vector>
364120Sgblack@eecs.umich.edu
374120Sgblack@eecs.umich.edu#include "base/trace.hh"
384120Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
394120Sgblack@eecs.umich.edu#include "dev/console.hh"
4011274Sshingarov@labware.com#include "dev/etherdev.hh"
414120Sgblack@eecs.umich.edu#include "dev/scsi_ctrl.hh"
424120Sgblack@eecs.umich.edu#include "dev/tlaser_clock.hh"
434120Sgblack@eecs.umich.edu#include "dev/tsunami_pchip.hh"
444120Sgblack@eecs.umich.edu#include "dev/tsunamireg.h"
454120Sgblack@eecs.umich.edu#include "dev/tsunami.hh"
4610600Sgabeblack@google.com#include "mem/functional_mem/memory_control.hh"
4710600Sgabeblack@google.com#include "mem/functional_mem/physical_memory.hh"
484144Sgblack@eecs.umich.edu#include "sim/builder.hh"
494144Sgblack@eecs.umich.edu#include "sim/system.hh"
504144Sgblack@eecs.umich.edu
514144Sgblack@eecs.umich.eduusing namespace std;
524144Sgblack@eecs.umich.edu
534120Sgblack@eecs.umich.eduTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
544120Sgblack@eecs.umich.edu                           MemoryController *mmu)
554120Sgblack@eecs.umich.edu    : FunctionalMemory(name), addr(a), tsunami(t)
5610600Sgabeblack@google.com{
5710600Sgabeblack@google.com    mmu->add_child(this, Range<Addr>(addr, addr + size));
5811274Sshingarov@labware.com
5911274Sshingarov@labware.com    for (int i = 0; i < 4; i++) {
6011274Sshingarov@labware.com        wsba[i] = 0;
6111274Sshingarov@labware.com        wsm[i] = 0;
6210600Sgabeblack@google.com        tba[i] = 0;
6311274Sshingarov@labware.com    }
6411274Sshingarov@labware.com
6511274Sshingarov@labware.com    //Set back pointer in tsunami
6611274Sshingarov@labware.com    tsunami->pchip = this;
6711274Sshingarov@labware.com}
6811274Sshingarov@labware.com
6911274Sshingarov@labware.comFault
7011274Sshingarov@labware.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data)
7111274Sshingarov@labware.com{
7211274Sshingarov@labware.com    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
7311274Sshingarov@labware.com            req->vaddr, req->size);
7411274Sshingarov@labware.com
7511274Sshingarov@labware.com    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
7611274Sshingarov@labware.com
7711274Sshingarov@labware.com    switch (req->size) {
7811274Sshingarov@labware.com
7911274Sshingarov@labware.com      case sizeof(uint64_t):
8011274Sshingarov@labware.com          switch(daddr) {
8111274Sshingarov@labware.com              case TSDEV_PC_WSBA0:
8211274Sshingarov@labware.com                    *(uint64_t*)data = wsba[0];
8311274Sshingarov@labware.com                    return No_Fault;
8411274Sshingarov@labware.com              case TSDEV_PC_WSBA1:
8511274Sshingarov@labware.com                    *(uint64_t*)data = wsba[1];
8611274Sshingarov@labware.com                    return No_Fault;
8711274Sshingarov@labware.com              case TSDEV_PC_WSBA2:
8812031Sgabeblack@google.com                    *(uint64_t*)data = wsba[2];
8912031Sgabeblack@google.com                    return No_Fault;
9012031Sgabeblack@google.com              case TSDEV_PC_WSBA3:
9112031Sgabeblack@google.com                    *(uint64_t*)data = wsba[3];
9212031Sgabeblack@google.com                    return No_Fault;
9310600Sgabeblack@google.com              case TSDEV_PC_WSM0:
9410600Sgabeblack@google.com                    *(uint64_t*)data = wsm[0];
9511274Sshingarov@labware.com                    return No_Fault;
9610600Sgabeblack@google.com              case TSDEV_PC_WSM1:
9711274Sshingarov@labware.com                    *(uint64_t*)data = wsm[1];
9811274Sshingarov@labware.com                    return No_Fault;
9912073Smatthiashille8@gmail.com              case TSDEV_PC_WSM2:
10011274Sshingarov@labware.com                    *(uint64_t*)data = wsm[2];
10111274Sshingarov@labware.com                    return No_Fault;
10211274Sshingarov@labware.com              case TSDEV_PC_WSM3:
10311274Sshingarov@labware.com                    *(uint64_t*)data = wsm[3];
10411274Sshingarov@labware.com                    return No_Fault;
10511274Sshingarov@labware.com              case TSDEV_PC_TBA0:
10611274Sshingarov@labware.com                    *(uint64_t*)data = tba[0];
10711274Sshingarov@labware.com                    return No_Fault;
10811274Sshingarov@labware.com              case TSDEV_PC_TBA1:
10911274Sshingarov@labware.com                    *(uint64_t*)data = tba[1];
11011274Sshingarov@labware.com                    return No_Fault;
11111274Sshingarov@labware.com              case TSDEV_PC_TBA2:
11211274Sshingarov@labware.com                    *(uint64_t*)data = tba[2];
11311274Sshingarov@labware.com                    return No_Fault;
11411274Sshingarov@labware.com              case TSDEV_PC_TBA3:
11511274Sshingarov@labware.com                    *(uint64_t*)data = tba[3];
11611274Sshingarov@labware.com                    return No_Fault;
11711274Sshingarov@labware.com              case TSDEV_PC_PCTL:
11811274Sshingarov@labware.com                    // might want to change the clock??
11911274Sshingarov@labware.com                    *(uint64_t*)data = 0x00; // try this
12011274Sshingarov@labware.com                    return No_Fault;
12111274Sshingarov@labware.com              case TSDEV_PC_PLAT:
12211274Sshingarov@labware.com                    panic("PC_PLAT not implemented\n");
12311274Sshingarov@labware.com              case TSDEV_PC_RES:
12411274Sshingarov@labware.com                    panic("PC_RES not implemented\n");
12511274Sshingarov@labware.com              case TSDEV_PC_PERROR:
12611274Sshingarov@labware.com                    *(uint64_t*)data = 0x00;
12711274Sshingarov@labware.com                    return No_Fault;
12811274Sshingarov@labware.com              case TSDEV_PC_PERRMASK:
12911274Sshingarov@labware.com                    *(uint64_t*)data = 0x00;
13011274Sshingarov@labware.com                    return No_Fault;
13111274Sshingarov@labware.com              case TSDEV_PC_PERRSET:
13211274Sshingarov@labware.com                    panic("PC_PERRSET not implemented\n");
13311274Sshingarov@labware.com              case TSDEV_PC_TLBIV:
13411274Sshingarov@labware.com                    panic("PC_TLBIV not implemented\n");
13512031Sgabeblack@google.com              case TSDEV_PC_TLBIA:
13612031Sgabeblack@google.com                    *(uint64_t*)data = 0x00; // shouldn't be readable, but linux
13712031Sgabeblack@google.com                    return No_Fault;
13812031Sgabeblack@google.com              case TSDEV_PC_PMONCTL:
13912031Sgabeblack@google.com                    panic("PC_PMONCTL not implemented\n");
14010600Sgabeblack@google.com              case TSDEV_PC_PMONCNT:
14110600Sgabeblack@google.com                    panic("PC_PMONCTN not implemented\n");
14212031Sgabeblack@google.com              default:
14312031Sgabeblack@google.com                  panic("Default in PChip Read reached reading 0x%x\n", daddr);
14412031Sgabeblack@google.com
14511274Sshingarov@labware.com           } // uint64_t
14612449Sgabeblack@google.com
14711274Sshingarov@labware.com      break;
14810600Sgabeblack@google.com      case sizeof(uint32_t):
14911274Sshingarov@labware.com      case sizeof(uint16_t):
1504120Sgblack@eecs.umich.edu      case sizeof(uint8_t):
1514120Sgblack@eecs.umich.edu      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
159Fault
160TsunamiPChip::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
248Addr
249TsunamiPChip::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
307void
308TsunamiPChip::serialize(std::ostream &os)
309{
310    SERIALIZE_ARRAY(wsba, 4);
311    SERIALIZE_ARRAY(wsm, 4);
312    SERIALIZE_ARRAY(tba, 4);
313}
314
315void
316TsunamiPChip::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
323BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
324
325    SimObjectParam<Tsunami *> tsunami;
326    SimObjectParam<MemoryController *> mmu;
327    Param<Addr> addr;
328
329END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
330
331BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
332
333    INIT_PARAM(tsunami, "Tsunami"),
334    INIT_PARAM(mmu, "Memory Controller"),
335    INIT_PARAM(addr, "Device Address")
336
337END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
338
339CREATE_SIM_OBJECT(TsunamiPChip)
340{
341    return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu);
342}
343
344REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
345