tsunami_pchip.cc revision 3540
1892SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
3892SN/A * All rights reserved.
4892SN/A *
5892SN/A * Redistribution and use in source and binary forms, with or without
6892SN/A * modification, are permitted provided that the following conditions are
7892SN/A * met: redistributions of source code must retain the above copyright
8892SN/A * notice, this list of conditions and the following disclaimer;
9892SN/A * redistributions in binary form must reproduce the above copyright
10892SN/A * notice, this list of conditions and the following disclaimer in the
11892SN/A * documentation and/or other materials provided with the distribution;
12892SN/A * neither the name of the copyright holders nor the names of its
13892SN/A * contributors may be used to endorse or promote products derived from
14892SN/A * this software without specific prior written permission.
15892SN/A *
16892SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17892SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18892SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19892SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20892SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21892SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22892SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23892SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24892SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25892SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26892SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A *
282665SN/A * Authors: Ali Saidi
292665SN/A *          Andrew Schultz
30892SN/A */
31768SN/A
321730SN/A/** @file
33768SN/A * Tsunami PChip (pci)
34768SN/A */
35768SN/A
36768SN/A#include <deque>
37768SN/A#include <string>
38768SN/A#include <vector>
39768SN/A
40768SN/A#include "base/trace.hh"
413540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami_pchip.hh"
423540Sgblack@eecs.umich.edu#include "dev/alpha/tsunamireg.h"
433540Sgblack@eecs.umich.edu#include "dev/alpha/tsunami.hh"
442542SN/A#include "mem/packet.hh"
453348SN/A#include "mem/packet_access.hh"
46768SN/A#include "sim/builder.hh"
47768SN/A#include "sim/system.hh"
48768SN/A
49768SN/Ausing namespace std;
502107SN/A//Should this be AlphaISA?
512107SN/Ausing namespace TheISA;
52768SN/A
532539SN/ATsunamiPChip::TsunamiPChip(Params *p)
542542SN/A: BasicPioDevice(p)
55768SN/A{
562539SN/A    pioSize = 0xfff;
57809SN/A
58835SN/A    for (int i = 0; i < 4; i++) {
59835SN/A        wsba[i] = 0;
60835SN/A        wsm[i] = 0;
61835SN/A        tba[i] = 0;
62835SN/A    }
63768SN/A
64896SN/A    // initialize pchip control register
65896SN/A    pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
66896SN/A
67775SN/A    //Set back pointer in tsunami
682539SN/A    p->tsunami->pchip = this;
692539SN/A}
702539SN/A
712539SN/ATick
723349SN/ATsunamiPChip::read(PacketPtr pkt)
732539SN/A{
742641SN/A    assert(pkt->result == Packet::Unknown);
752641SN/A    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
762539SN/A
772630SN/A    pkt->allocate();
782641SN/A    Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
792641SN/A    assert(pkt->getSize() == sizeof(uint64_t));
802539SN/A
812539SN/A
822641SN/A    DPRINTF(Tsunami, "read  va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
832539SN/A
842539SN/A    switch(daddr) {
852539SN/A      case TSDEV_PC_WSBA0:
862630SN/A            pkt->set(wsba[0]);
872539SN/A            break;
882539SN/A      case TSDEV_PC_WSBA1:
892630SN/A            pkt->set(wsba[1]);
902539SN/A            break;
912539SN/A      case TSDEV_PC_WSBA2:
922630SN/A            pkt->set(wsba[2]);
932539SN/A            break;
942539SN/A      case TSDEV_PC_WSBA3:
952630SN/A            pkt->set(wsba[3]);
962539SN/A            break;
972539SN/A      case TSDEV_PC_WSM0:
982630SN/A            pkt->set(wsm[0]);
992539SN/A            break;
1002539SN/A      case TSDEV_PC_WSM1:
1012630SN/A            pkt->set(wsm[1]);
1022539SN/A            break;
1032539SN/A      case TSDEV_PC_WSM2:
1042630SN/A            pkt->set(wsm[2]);
1052539SN/A            break;
1062539SN/A      case TSDEV_PC_WSM3:
1072630SN/A            pkt->set(wsm[3]);
1082539SN/A            break;
1092539SN/A      case TSDEV_PC_TBA0:
1102630SN/A            pkt->set(tba[0]);
1112539SN/A            break;
1122539SN/A      case TSDEV_PC_TBA1:
1132630SN/A            pkt->set(tba[1]);
1142539SN/A            break;
1152539SN/A      case TSDEV_PC_TBA2:
1162630SN/A            pkt->set(tba[2]);
1172539SN/A            break;
1182542SN/A      case TSDEV_PC_TBA3:
1192630SN/A            pkt->set(tba[3]);
1202539SN/A            break;
1212539SN/A      case TSDEV_PC_PCTL:
1222630SN/A            pkt->set(pctl);
1232539SN/A            break;
1242539SN/A      case TSDEV_PC_PLAT:
1252539SN/A            panic("PC_PLAT not implemented\n");
1262539SN/A      case TSDEV_PC_RES:
1272539SN/A            panic("PC_RES not implemented\n");
1282539SN/A      case TSDEV_PC_PERROR:
1292630SN/A            pkt->set((uint64_t)0x00);
1302539SN/A            break;
1312539SN/A      case TSDEV_PC_PERRMASK:
1322630SN/A            pkt->set((uint64_t)0x00);
1332539SN/A            break;
1342539SN/A      case TSDEV_PC_PERRSET:
1352539SN/A            panic("PC_PERRSET not implemented\n");
1362539SN/A      case TSDEV_PC_TLBIV:
1372539SN/A            panic("PC_TLBIV not implemented\n");
1382539SN/A      case TSDEV_PC_TLBIA:
1392630SN/A            pkt->set((uint64_t)0x00); // shouldn't be readable, but linux
1402539SN/A            break;
1412539SN/A      case TSDEV_PC_PMONCTL:
1422539SN/A            panic("PC_PMONCTL not implemented\n");
1432539SN/A      case TSDEV_PC_PMONCNT:
1442539SN/A            panic("PC_PMONCTN not implemented\n");
1452539SN/A      default:
1462539SN/A          panic("Default in PChip Read reached reading 0x%x\n", daddr);
1472539SN/A    }
1482641SN/A    pkt->result = Packet::Success;
1492539SN/A    return pioDelay;
1502539SN/A
151768SN/A}
152768SN/A
1532542SN/ATick
1543349SN/ATsunamiPChip::write(PacketPtr pkt)
155768SN/A{
1562641SN/A    assert(pkt->result == Packet::Unknown);
1572641SN/A    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
1582641SN/A    Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
159768SN/A
1602641SN/A    assert(pkt->getSize() == sizeof(uint64_t));
161768SN/A
1622641SN/A    DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
163768SN/A
1642539SN/A    switch(daddr) {
1652539SN/A        case TSDEV_PC_WSBA0:
1662630SN/A              wsba[0] = pkt->get<uint64_t>();
1672539SN/A              break;
1682539SN/A        case TSDEV_PC_WSBA1:
1692630SN/A              wsba[1] = pkt->get<uint64_t>();
1702539SN/A              break;
1712539SN/A        case TSDEV_PC_WSBA2:
1722630SN/A              wsba[2] = pkt->get<uint64_t>();
1732539SN/A              break;
1742539SN/A        case TSDEV_PC_WSBA3:
1752630SN/A              wsba[3] = pkt->get<uint64_t>();
1762539SN/A              break;
1772539SN/A        case TSDEV_PC_WSM0:
1782630SN/A              wsm[0] = pkt->get<uint64_t>();
1792539SN/A              break;
1802539SN/A        case TSDEV_PC_WSM1:
1812630SN/A              wsm[1] = pkt->get<uint64_t>();
1822539SN/A              break;
1832539SN/A        case TSDEV_PC_WSM2:
1842630SN/A              wsm[2] = pkt->get<uint64_t>();
1852539SN/A              break;
1862539SN/A        case TSDEV_PC_WSM3:
1872630SN/A              wsm[3] = pkt->get<uint64_t>();
1882539SN/A              break;
1892539SN/A        case TSDEV_PC_TBA0:
1902630SN/A              tba[0] = pkt->get<uint64_t>();
1912539SN/A              break;
1922539SN/A        case TSDEV_PC_TBA1:
1932630SN/A              tba[1] = pkt->get<uint64_t>();
1942539SN/A              break;
1952539SN/A        case TSDEV_PC_TBA2:
1962630SN/A              tba[2] = pkt->get<uint64_t>();
1972539SN/A              break;
1982539SN/A        case TSDEV_PC_TBA3:
1992630SN/A              tba[3] = pkt->get<uint64_t>();
2002539SN/A              break;
2012539SN/A        case TSDEV_PC_PCTL:
2022630SN/A              pctl = pkt->get<uint64_t>();
2032539SN/A              break;
2042539SN/A        case TSDEV_PC_PLAT:
2052539SN/A              panic("PC_PLAT not implemented\n");
2062539SN/A        case TSDEV_PC_RES:
2072539SN/A              panic("PC_RES not implemented\n");
2082539SN/A        case TSDEV_PC_PERROR:
2092539SN/A              break;
2102539SN/A        case TSDEV_PC_PERRMASK:
2112539SN/A              panic("PC_PERRMASK not implemented\n");
2122539SN/A        case TSDEV_PC_PERRSET:
2132539SN/A              panic("PC_PERRSET not implemented\n");
2142539SN/A        case TSDEV_PC_TLBIV:
2152539SN/A              panic("PC_TLBIV not implemented\n");
2162539SN/A        case TSDEV_PC_TLBIA:
2172539SN/A              break; // value ignored, supposted to invalidate SG TLB
2182539SN/A        case TSDEV_PC_PMONCTL:
2192539SN/A              panic("PC_PMONCTL not implemented\n");
2202539SN/A        case TSDEV_PC_PMONCNT:
2212539SN/A              panic("PC_PMONCTN not implemented\n");
2222539SN/A        default:
2232549SN/A            panic("Default in PChip write reached reading 0x%x\n", daddr);
224768SN/A
2252539SN/A    } // uint64_t
226768SN/A
2272641SN/A    pkt->result = Packet::Success;
2282539SN/A    return pioDelay;
229768SN/A}
230768SN/A
231857SN/A#define DMA_ADDR_MASK ULL(0x3ffffffff)
232857SN/A
233835SN/AAddr
234835SN/ATsunamiPChip::translatePciToDma(Addr busAddr)
235835SN/A{
236835SN/A    // compare the address to the window base registers
237857SN/A    uint64_t tbaMask = 0;
238857SN/A    uint64_t baMask = 0;
239857SN/A
240835SN/A    uint64_t windowMask = 0;
241835SN/A    uint64_t windowBase = 0;
242857SN/A
243857SN/A    uint64_t pteEntry = 0;
244857SN/A
245857SN/A    Addr pteAddr;
246835SN/A    Addr dmaAddr;
247835SN/A
248896SN/A#if 0
249896SN/A    DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
250835SN/A    for (int i = 0; i < 4; i++) {
251896SN/A        DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
252896SN/A                i, wsba[i], wsm[i]);
253896SN/A
254835SN/A        windowBase = wsba[i];
255896SN/A        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
256835SN/A
257835SN/A        if ((busAddr & windowMask) == (windowBase & windowMask)) {
258896SN/A            DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
259896SN/A                    i, windowBase, windowMask, (busAddr & windowMask),
260896SN/A                    (windowBase & windowMask));
261896SN/A        }
262896SN/A    }
263896SN/A#endif
264857SN/A
265896SN/A    for (int i = 0; i < 4; i++) {
266896SN/A
267896SN/A        windowBase = wsba[i];
268896SN/A        windowMask = ~wsm[i] & (ULL(0xfff) << 20);
269896SN/A
270896SN/A        if ((busAddr & windowMask) == (windowBase & windowMask)) {
271835SN/A
272835SN/A            if (wsba[i] & 0x1) {   // see if enabled
273857SN/A                if (wsba[i] & 0x2) { // see if SG bit is set
274857SN/A                    /** @todo
275857SN/A                        This currently is faked by just doing a direct
276857SN/A                        read from memory, however, to be realistic, this
277857SN/A                        needs to actually do a bus transaction.  The process
278857SN/A                        is explained in the tsunami documentation on page
279857SN/A                        10-12 and basically munges the address to look up a
280857SN/A                        PTE from a table in memory and then uses that mapping
281857SN/A                        to create an address for the SG page
282857SN/A                    */
283835SN/A
284896SN/A                    tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
285896SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
286857SN/A                    pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
287857SN/A
2882542SN/A                    pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
289857SN/A
290896SN/A                    dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
291857SN/A
292857SN/A                } else {
293896SN/A                    baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
294857SN/A                    tbaMask = ~baMask;
295857SN/A                    dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
296857SN/A                }
297857SN/A
298857SN/A                return (dmaAddr & DMA_ADDR_MASK);
299835SN/A            }
300835SN/A        }
301835SN/A    }
302835SN/A
303896SN/A    // if no match was found, then return the original address
304896SN/A    return busAddr;
305835SN/A}
3062846SN/AAddr
3072846SN/ATsunamiPChip::calcConfigAddr(int bus, int dev, int func)
3082846SN/A{
3092846SN/A    assert(func < 8);
3102846SN/A    assert(dev < 32);
3112846SN/A    assert(bus == 0);
3122846SN/A
3132846SN/A    return TsunamiPciBus0Config | (func << 8) | (dev << 11);
3142846SN/A}
3152846SN/A
3162846SN/A
317835SN/A
318768SN/Avoid
319768SN/ATsunamiPChip::serialize(std::ostream &os)
320768SN/A{
321896SN/A    SERIALIZE_SCALAR(pctl);
322835SN/A    SERIALIZE_ARRAY(wsba, 4);
323835SN/A    SERIALIZE_ARRAY(wsm, 4);
324835SN/A    SERIALIZE_ARRAY(tba, 4);
325768SN/A}
326768SN/A
327768SN/Avoid
328768SN/ATsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
329768SN/A{
330896SN/A    UNSERIALIZE_SCALAR(pctl);
331835SN/A    UNSERIALIZE_ARRAY(wsba, 4);
332835SN/A    UNSERIALIZE_ARRAY(wsm, 4);
333835SN/A    UNSERIALIZE_ARRAY(tba, 4);
334768SN/A}
335768SN/A
336909SN/A
337768SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
338768SN/A
3392539SN/A    Param<Addr> pio_addr;
3402539SN/A    Param<Tick> pio_latency;
3412539SN/A    SimObjectParam<Platform *> platform;
3422539SN/A    SimObjectParam<System *> system;
343775SN/A    SimObjectParam<Tsunami *> tsunami;
344768SN/A
345768SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
346768SN/A
347768SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
348768SN/A
3492539SN/A    INIT_PARAM(pio_addr, "Device Address"),
3502539SN/A    INIT_PARAM(pio_latency, "Programmed IO latency"),
3512539SN/A    INIT_PARAM(platform, "platform"),
3522539SN/A    INIT_PARAM(system, "system object"),
3532539SN/A    INIT_PARAM(tsunami, "Tsunami")
354768SN/A
355768SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
356768SN/A
357768SN/ACREATE_SIM_OBJECT(TsunamiPChip)
358768SN/A{
3592539SN/A    TsunamiPChip::Params *p = new TsunamiPChip::Params;
3602539SN/A    p->name = getInstanceName();
3612539SN/A    p->pio_addr = pio_addr;
3622539SN/A    p->pio_delay = pio_latency;
3632539SN/A    p->platform = platform;
3642539SN/A    p->system = system;
3652539SN/A    p->tsunami = tsunami;
3662539SN/A    return new TsunamiPChip(p);
367768SN/A}
368768SN/A
369768SN/AREGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
370