tsunami_pchip.cc revision 2542
15882Snate@binkert.org/*
25882Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan
35882Snate@binkert.org * All rights reserved.
45882Snate@binkert.org *
55882Snate@binkert.org * Redistribution and use in source and binary forms, with or without
65882Snate@binkert.org * modification, are permitted provided that the following conditions are
75882Snate@binkert.org * met: redistributions of source code must retain the above copyright
85882Snate@binkert.org * notice, this list of conditions and the following disclaimer;
95882Snate@binkert.org * redistributions in binary form must reproduce the above copyright
105882Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
115882Snate@binkert.org * documentation and/or other materials provided with the distribution;
125882Snate@binkert.org * neither the name of the copyright holders nor the names of its
135882Snate@binkert.org * contributors may be used to endorse or promote products derived from
145882Snate@binkert.org * this software without specific prior written permission.
155882Snate@binkert.org *
165882Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175882Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185882Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195882Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205882Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215882Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225882Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235882Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245882Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255882Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265882Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275882Snate@binkert.org */
285882Snate@binkert.org
295882Snate@binkert.org/** @file
305882Snate@binkert.org * Tsunami PChip (pci)
3111793Sbrandon.potter@amd.com */
3211793Sbrandon.potter@amd.com
335882Snate@binkert.org#include <deque>
345882Snate@binkert.org#include <string>
355882Snate@binkert.org#include <vector>
368232Snate@binkert.org
378229Snate@binkert.org#include "base/trace.hh"
388229Snate@binkert.org#include "dev/tsunami_pchip.hh"
395882Snate@binkert.org#include "dev/tsunamireg.h"
4012334Sgabeblack@google.com#include "dev/tsunami.hh"
418232Snate@binkert.org#include "mem/packet.hh"
428232Snate@binkert.org#include "sim/builder.hh"
435882Snate@binkert.org#include "sim/system.hh"
448231Snate@binkert.org
458231Snate@binkert.orgusing namespace std;
468232Snate@binkert.org//Should this be AlphaISA?
478232Snate@binkert.orgusing namespace TheISA;
488232Snate@binkert.org
498232Snate@binkert.orgTsunamiPChip::TsunamiPChip(Params *p)
508232Snate@binkert.org: BasicPioDevice(p)
515882Snate@binkert.org{
528231Snate@binkert.org    pioSize = 0xfff;
535882Snate@binkert.org
545882Snate@binkert.org    for (int i = 0; i < 4; i++) {
555882Snate@binkert.org        wsba[i] = 0;
565882Snate@binkert.org        wsm[i] = 0;
578231Snate@binkert.org        tba[i] = 0;
585882Snate@binkert.org    }
595882Snate@binkert.org
608231Snate@binkert.org    // initialize pchip control register
618232Snate@binkert.org    pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
628232Snate@binkert.org
638232Snate@binkert.org    //Set back pointer in tsunami
648232Snate@binkert.org    p->tsunami->pchip = this;
658232Snate@binkert.org}
668232Snate@binkert.org
678232Snate@binkert.orgTick
688232Snate@binkert.orgTsunamiPChip::read(Packet &pkt)
698232Snate@binkert.org{
708232Snate@binkert.org    assert(pkt.result == Unknown);
718232Snate@binkert.org    assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
7211153SCurtis.Dunham@arm.com
7311153SCurtis.Dunham@arm.com    pkt.time = curTick + pioDelay;
748232Snate@binkert.org    Addr daddr = pkt.addr - pioAddr;
758232Snate@binkert.org
768232Snate@binkert.org    uint64_t *data64;
778232Snate@binkert.org
788232Snate@binkert.org    if (!pkt.data) {
798232Snate@binkert.org        data64 = new uint64_t;
808232Snate@binkert.org        pkt.data = (uint8_t*)data64;
818232Snate@binkert.org    } else
828232Snate@binkert.org        data64 = (uint64_t*)pkt.data;
838232Snate@binkert.org
848232Snate@binkert.org    DPRINTF(Tsunami, "read  va=%#x size=%d\n", pkt.addr, pkt.size);
858232Snate@binkert.org
868232Snate@binkert.org    switch(daddr) {
878232Snate@binkert.org      case TSDEV_PC_WSBA0:
888232Snate@binkert.org            *data64 = wsba[0];
898232Snate@binkert.org            break;
908232Snate@binkert.org      case TSDEV_PC_WSBA1:
918232Snate@binkert.org            *data64 = wsba[1];
928232Snate@binkert.org            break;
938232Snate@binkert.org      case TSDEV_PC_WSBA2:
948232Snate@binkert.org            *data64 = wsba[2];
958232Snate@binkert.org            break;
968232Snate@binkert.org      case TSDEV_PC_WSBA3:
978232Snate@binkert.org            *data64 = wsba[3];
988232Snate@binkert.org            break;
998232Snate@binkert.org      case TSDEV_PC_WSM0:
1008232Snate@binkert.org            *data64 = wsm[0];
10111153SCurtis.Dunham@arm.com            break;
10211153SCurtis.Dunham@arm.com      case TSDEV_PC_WSM1:
10311153SCurtis.Dunham@arm.com            *data64 = wsm[1];
10411153SCurtis.Dunham@arm.com            break;
10511153SCurtis.Dunham@arm.com      case TSDEV_PC_WSM2:
10611153SCurtis.Dunham@arm.com            *data64 = wsm[2];
10711153SCurtis.Dunham@arm.com            break;
10811153SCurtis.Dunham@arm.com      case TSDEV_PC_WSM3:
10911153SCurtis.Dunham@arm.com            *data64 = wsm[3];
11011153SCurtis.Dunham@arm.com            break;
11111153SCurtis.Dunham@arm.com      case TSDEV_PC_TBA0:
11211153SCurtis.Dunham@arm.com            *data64 = tba[0];
11311153SCurtis.Dunham@arm.com            break;
11411153SCurtis.Dunham@arm.com      case TSDEV_PC_TBA1:
11511153SCurtis.Dunham@arm.com            *data64 = tba[1];
11611153SCurtis.Dunham@arm.com            break;
1178232Snate@binkert.org      case TSDEV_PC_TBA2:
1188232Snate@binkert.org            *data64 = tba[2];
11911153SCurtis.Dunham@arm.com            break;
12011153SCurtis.Dunham@arm.com      case TSDEV_PC_TBA3:
1218232Snate@binkert.org            *data64 = tba[3];
1228232Snate@binkert.org            break;
1238232Snate@binkert.org      case TSDEV_PC_PCTL:
1248232Snate@binkert.org            *data64 = pctl;
1258232Snate@binkert.org            break;
12611153SCurtis.Dunham@arm.com      case TSDEV_PC_PLAT:
12711153SCurtis.Dunham@arm.com            panic("PC_PLAT not implemented\n");
1288232Snate@binkert.org      case TSDEV_PC_RES:
1298232Snate@binkert.org            panic("PC_RES not implemented\n");
1308232Snate@binkert.org      case TSDEV_PC_PERROR:
1318232Snate@binkert.org            *data64 = 0x00;
1328232Snate@binkert.org            break;
1338232Snate@binkert.org      case TSDEV_PC_PERRMASK:
1348232Snate@binkert.org            *data64 = 0x00;
1358232Snate@binkert.org            break;
1368232Snate@binkert.org      case TSDEV_PC_PERRSET:
1378232Snate@binkert.org            panic("PC_PERRSET not implemented\n");
1388232Snate@binkert.org      case TSDEV_PC_TLBIV:
1398232Snate@binkert.org            panic("PC_TLBIV not implemented\n");
1408232Snate@binkert.org      case TSDEV_PC_TLBIA:
1418232Snate@binkert.org            *data64 = 0x00; // shouldn't be readable, but linux
1428232Snate@binkert.org            break;
1438232Snate@binkert.org      case TSDEV_PC_PMONCTL:
1448232Snate@binkert.org            panic("PC_PMONCTL not implemented\n");
1458232Snate@binkert.org      case TSDEV_PC_PMONCNT:
1468232Snate@binkert.org            panic("PC_PMONCTN not implemented\n");
1478232Snate@binkert.org      default:
1488232Snate@binkert.org          panic("Default in PChip Read reached reading 0x%x\n", daddr);
1498232Snate@binkert.org    }
1508232Snate@binkert.org    pkt.result = Success;
1518232Snate@binkert.org    return pioDelay;
1528232Snate@binkert.org
1538699Ssteve.reinhardt@amd.com}
1548232Snate@binkert.org
1558232Snate@binkert.orgTick
1568232Snate@binkert.orgTsunamiPChip::write(Packet &pkt)
1578232Snate@binkert.org{
1588232Snate@binkert.org    pkt.time = curTick + pioDelay;
1598232Snate@binkert.org
1608232Snate@binkert.org    assert(pkt.result == Unknown);
1618232Snate@binkert.org    assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
1628232Snate@binkert.org    Addr daddr = pkt.addr - pioAddr;
1638232Snate@binkert.org
1648232Snate@binkert.org    uint64_t data64 = *(uint64_t *)pkt.data;
1658232Snate@binkert.org    assert(pkt.size == sizeof(uint64_t));
1668232Snate@binkert.org
1678232Snate@binkert.org    DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size);
1688232Snate@binkert.org
1698232Snate@binkert.org    switch(daddr) {
1708232Snate@binkert.org        case TSDEV_PC_WSBA0:
1718232Snate@binkert.org              wsba[0] = data64;
1728232Snate@binkert.org              break;
1738232Snate@binkert.org        case TSDEV_PC_WSBA1:
1748232Snate@binkert.org              wsba[1] = data64;
1758231Snate@binkert.org              break;
1768232Snate@binkert.org        case TSDEV_PC_WSBA2:
1778232Snate@binkert.org              wsba[2] = data64;
1788232Snate@binkert.org              break;
1798232Snate@binkert.org        case TSDEV_PC_WSBA3:
1808232Snate@binkert.org              wsba[3] = data64;
1818232Snate@binkert.org              break;
1828232Snate@binkert.org        case TSDEV_PC_WSM0:
1838232Snate@binkert.org              wsm[0] = data64;
1848232Snate@binkert.org              break;
1858232Snate@binkert.org        case TSDEV_PC_WSM1:
1868232Snate@binkert.org              wsm[1] = data64;
1878232Snate@binkert.org              break;
1888232Snate@binkert.org        case TSDEV_PC_WSM2:
1898232Snate@binkert.org              wsm[2] = data64;
1908232Snate@binkert.org              break;
1918232Snate@binkert.org        case TSDEV_PC_WSM3:
1928232Snate@binkert.org              wsm[3] = data64;
1938232Snate@binkert.org              break;
1948232Snate@binkert.org        case TSDEV_PC_TBA0:
1958232Snate@binkert.org              tba[0] = data64;
1968232Snate@binkert.org              break;
1978232Snate@binkert.org        case TSDEV_PC_TBA1:
1988232Snate@binkert.org              tba[1] = data64;
1998232Snate@binkert.org              break;
2008232Snate@binkert.org        case TSDEV_PC_TBA2:
2018232Snate@binkert.org              tba[2] = data64;
202              break;
203        case TSDEV_PC_TBA3:
204              tba[3] = data64;
205              break;
206        case TSDEV_PC_PCTL:
207              pctl = data64;
208              break;
209        case TSDEV_PC_PLAT:
210              panic("PC_PLAT not implemented\n");
211        case TSDEV_PC_RES:
212              panic("PC_RES not implemented\n");
213        case TSDEV_PC_PERROR:
214              break;
215        case TSDEV_PC_PERRMASK:
216              panic("PC_PERRMASK not implemented\n");
217        case TSDEV_PC_PERRSET:
218              panic("PC_PERRSET not implemented\n");
219        case TSDEV_PC_TLBIV:
220              panic("PC_TLBIV not implemented\n");
221        case TSDEV_PC_TLBIA:
222              break; // value ignored, supposted to invalidate SG TLB
223        case TSDEV_PC_PMONCTL:
224              panic("PC_PMONCTL not implemented\n");
225        case TSDEV_PC_PMONCNT:
226              panic("PC_PMONCTN not implemented\n");
227        default:
228            panic("Default in PChip Read reached reading 0x%x\n", daddr);
229
230    } // uint64_t
231
232    pkt.result = Success;
233    return pioDelay;
234}
235
236#define DMA_ADDR_MASK ULL(0x3ffffffff)
237
238Addr
239TsunamiPChip::translatePciToDma(Addr busAddr)
240{
241    // compare the address to the window base registers
242    uint64_t tbaMask = 0;
243    uint64_t baMask = 0;
244
245    uint64_t windowMask = 0;
246    uint64_t windowBase = 0;
247
248    uint64_t pteEntry = 0;
249
250    Addr pteAddr;
251    Addr dmaAddr;
252
253#if 0
254    DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
255    for (int i = 0; i < 4; i++) {
256        DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
257                i, wsba[i], wsm[i]);
258
259        windowBase = wsba[i];
260        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
261
262        if ((busAddr & windowMask) == (windowBase & windowMask)) {
263            DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
264                    i, windowBase, windowMask, (busAddr & windowMask),
265                    (windowBase & windowMask));
266        }
267    }
268#endif
269
270    for (int i = 0; i < 4; i++) {
271
272        windowBase = wsba[i];
273        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
274
275        if ((busAddr & windowMask) == (windowBase & windowMask)) {
276
277            if (wsba[i] & 0x1) {   // see if enabled
278                if (wsba[i] & 0x2) { // see if SG bit is set
279                    /** @todo
280                        This currently is faked by just doing a direct
281                        read from memory, however, to be realistic, this
282                        needs to actually do a bus transaction.  The process
283                        is explained in the tsunami documentation on page
284                        10-12 and basically munges the address to look up a
285                        PTE from a table in memory and then uses that mapping
286                        to create an address for the SG page
287                    */
288
289                    tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
290                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
291                    pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
292
293                    pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
294
295                    dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
296
297                } else {
298                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
299                    tbaMask = ~baMask;
300                    dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
301                }
302
303                return (dmaAddr & DMA_ADDR_MASK);
304            }
305        }
306    }
307
308    // if no match was found, then return the original address
309    return busAddr;
310}
311
312void
313TsunamiPChip::serialize(std::ostream &os)
314{
315    SERIALIZE_SCALAR(pctl);
316    SERIALIZE_ARRAY(wsba, 4);
317    SERIALIZE_ARRAY(wsm, 4);
318    SERIALIZE_ARRAY(tba, 4);
319}
320
321void
322TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
323{
324    UNSERIALIZE_SCALAR(pctl);
325    UNSERIALIZE_ARRAY(wsba, 4);
326    UNSERIALIZE_ARRAY(wsm, 4);
327    UNSERIALIZE_ARRAY(tba, 4);
328}
329
330
331BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
332
333    Param<Addr> pio_addr;
334    Param<Tick> pio_latency;
335    SimObjectParam<Platform *> platform;
336    SimObjectParam<System *> system;
337    SimObjectParam<Tsunami *> tsunami;
338
339END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
340
341BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
342
343    INIT_PARAM(pio_addr, "Device Address"),
344    INIT_PARAM(pio_latency, "Programmed IO latency"),
345    INIT_PARAM(platform, "platform"),
346    INIT_PARAM(system, "system object"),
347    INIT_PARAM(tsunami, "Tsunami")
348
349END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
350
351CREATE_SIM_OBJECT(TsunamiPChip)
352{
353    TsunamiPChip::Params *p = new TsunamiPChip::Params;
354    p->name = getInstanceName();
355    p->pio_addr = pio_addr;
356    p->pio_delay = pio_latency;
357    p->platform = platform;
358    p->system = system;
359    p->tsunami = tsunami;
360    return new TsunamiPChip(p);
361}
362
363REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
364