io_device.cc revision 2521
1955SN/A/*
2955SN/A * Copyright (c) 2006 The Regents of The University of Michigan
31762SN/A * All rights reserved.
4955SN/A *
5955SN/A * Redistribution and use in source and binary forms, with or without
6955SN/A * modification, are permitted provided that the following conditions are
7955SN/A * met: redistributions of source code must retain the above copyright
8955SN/A * notice, this list of conditions and the following disclaimer;
9955SN/A * redistributions in binary form must reproduce the above copyright
10955SN/A * notice, this list of conditions and the following disclaimer in the
11955SN/A * documentation and/or other materials provided with the distribution;
12955SN/A * neither the name of the copyright holders nor the names of its
13955SN/A * contributors may be used to endorse or promote products derived from
14955SN/A * this software without specific prior written permission.
15955SN/A *
16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
282665Ssaidi@eecs.umich.edu
294762Snate@binkert.org#include "dev/io_device.hh"
30955SN/A#include "sim/builder.hh"
315522Snate@binkert.org
326143Snate@binkert.org
334762Snate@binkert.orgPioPort::PioPort(PioDevice *dev, Platform *p)
345522Snate@binkert.org        : device(dev), platform(p)
35955SN/A{ }
365522Snate@binkert.org
37955SN/A
385522Snate@binkert.orgTick
394202Sbinkertn@umich.eduPioPort::recvAtomic(Packet &pkt)
405742Snate@binkert.org{
41955SN/A    return device->recvAtomic(pkt);
424381Sbinkertn@umich.edu}
434381Sbinkertn@umich.edu
448334Snate@binkert.orgvoid
45955SN/APioPort::recvFunctional(Packet &pkt)
46955SN/A{
474202Sbinkertn@umich.edu    device->recvAtomic(pkt);
48955SN/A}
494382Sbinkertn@umich.edu
504382Sbinkertn@umich.eduvoid
514382Sbinkertn@umich.eduPioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
526654Snate@binkert.org{
535517Snate@binkert.org    snoop.clear();
548614Sgblack@eecs.umich.edu    device->addressRanges(resp);
557674Snate@binkert.org}
566143Snate@binkert.org
576143Snate@binkert.org
586143Snate@binkert.orgPacket *
598233Snate@binkert.orgPioPort::recvRetry()
608233Snate@binkert.org{
618233Snate@binkert.org    Packet* pkt = transmitList.front();
628233Snate@binkert.org    transmitList.pop_front();
638233Snate@binkert.org    return pkt;
648334Snate@binkert.org}
658334Snate@binkert.org
668233Snate@binkert.org
678233Snate@binkert.orgvoid
688233Snate@binkert.orgPioPort::SendEvent::process()
698233Snate@binkert.org{
708233Snate@binkert.org    if (port->Port::sendTiming(packet) == Success)
718233Snate@binkert.org        return;
726143Snate@binkert.org
738233Snate@binkert.org    port->transmitList.push_back(&packet);
748233Snate@binkert.org}
758233Snate@binkert.org
766143Snate@binkert.org
776143Snate@binkert.orgbool
786143Snate@binkert.orgPioPort::recvTiming(Packet &pkt)
796143Snate@binkert.org{
808233Snate@binkert.org    device->recvAtomic(pkt);
818233Snate@binkert.org    sendTiming(pkt, pkt.time-pkt.req->time);
828233Snate@binkert.org    return Success;
836143Snate@binkert.org}
848233Snate@binkert.org
858233Snate@binkert.orgPioDevice::~PioDevice()
868233Snate@binkert.org{
878233Snate@binkert.org    if (pioPort)
886143Snate@binkert.org        delete pioPort;
896143Snate@binkert.org}
906143Snate@binkert.org
914762Snate@binkert.org
926143Snate@binkert.orgDmaPort::DmaPort(DmaDevice *dev)
938233Snate@binkert.org        : device(dev)
948233Snate@binkert.org{ }
958233Snate@binkert.org
968233Snate@binkert.orgbool
978233Snate@binkert.orgDmaPort::recvTiming(Packet &pkt)
986143Snate@binkert.org{
998233Snate@binkert.org    completionEvent->schedule(curTick+1);
1008233Snate@binkert.org    completionEvent = NULL;
1018233Snate@binkert.org    return Success;
1028233Snate@binkert.org}
1036143Snate@binkert.org
1046143Snate@binkert.orgDmaDevice::DmaDevice(Params *p)
1056143Snate@binkert.org    : PioDevice(p)
1066143Snate@binkert.org{
1076143Snate@binkert.org    dmaPort = new DmaPort(this);
1086143Snate@binkert.org}
1096143Snate@binkert.org
1106143Snate@binkert.orgvoid
1116143Snate@binkert.orgDmaPort::SendEvent::process()
1127065Snate@binkert.org{
1136143Snate@binkert.org    if (port->Port::sendTiming(packet) == Success)
1148233Snate@binkert.org        return;
1158233Snate@binkert.org
1168233Snate@binkert.org    port->transmitList.push_back(&packet);
1178233Snate@binkert.org}
1188233Snate@binkert.org
1198233Snate@binkert.orgPacket *
1208233Snate@binkert.orgDmaPort::recvRetry()
1218233Snate@binkert.org{
1228233Snate@binkert.org    Packet* pkt = transmitList.front();
1238233Snate@binkert.org    transmitList.pop_front();
1248233Snate@binkert.org    return pkt;
1258233Snate@binkert.org}
1268233Snate@binkert.orgvoid
1278233Snate@binkert.orgDmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
1288233Snate@binkert.org                     Event *event, uint8_t *data)
1298233Snate@binkert.org{
1308233Snate@binkert.org
1318233Snate@binkert.org    assert(event);
1328233Snate@binkert.org
1338233Snate@binkert.org    int prevSize = 0;
1348233Snate@binkert.org    Packet basePkt;
1358233Snate@binkert.org    Request baseReq;
1368233Snate@binkert.org
1378233Snate@binkert.org    basePkt.flags = 0;
1388233Snate@binkert.org    basePkt.coherence = NULL;
1398233Snate@binkert.org    basePkt.senderState = NULL;
1408233Snate@binkert.org    basePkt.src = 0;
1418233Snate@binkert.org    basePkt.dest = 0;
1428233Snate@binkert.org    basePkt.cmd = cmd;
1438233Snate@binkert.org    basePkt.result = Unknown;
1448233Snate@binkert.org    basePkt.req = NULL;
1456143Snate@binkert.org    baseReq.nicReq = true;
1466143Snate@binkert.org    baseReq.time = curTick;
1476143Snate@binkert.org
1486143Snate@binkert.org    completionEvent = event;
1496143Snate@binkert.org
1506143Snate@binkert.org    for (ChunkGenerator gen(addr, size, peerBlockSize());
1516143Snate@binkert.org         !gen.done(); gen.next()) {
1526143Snate@binkert.org            Packet *pkt = new Packet(basePkt);
1536143Snate@binkert.org            Request *req = new Request(baseReq);
1548945Ssteve.reinhardt@amd.com            pkt->addr = gen.addr();
1558233Snate@binkert.org            pkt->size = gen.size();
1568233Snate@binkert.org            pkt->req = req;
1576143Snate@binkert.org            pkt->req->paddr = pkt->addr;
1588945Ssteve.reinhardt@amd.com            pkt->req->size = pkt->size;
1596143Snate@binkert.org            // Increment the data pointer on a write
1606143Snate@binkert.org            pkt->data = data ? data + prevSize : NULL ;
1616143Snate@binkert.org            prevSize += pkt->size;
1626143Snate@binkert.org
1635522Snate@binkert.org            sendDma(*pkt);
1646143Snate@binkert.org    }
1656143Snate@binkert.org}
1666143Snate@binkert.org
1676143Snate@binkert.org
1688233Snate@binkert.orgvoid
1698233Snate@binkert.orgDmaPort::sendDma(Packet &pkt)
1708233Snate@binkert.org{
1716143Snate@binkert.org   // some kind of selction between access methods
1726143Snate@binkert.org   // more work is going to have to be done to make
1736143Snate@binkert.org   // switching actually work
1746143Snate@binkert.org  /* MemState state = device->platform->system->memState;
1755522Snate@binkert.org
1765522Snate@binkert.org   if (state == Timing) {
1775522Snate@binkert.org       if (sendTiming(pkt) == Failure)
1785522Snate@binkert.org           transmitList.push_back(&packet);
1795604Snate@binkert.org   } else if (state == Atomic) {*/
1805604Snate@binkert.org       sendAtomic(pkt);
1816143Snate@binkert.org       completionEvent->schedule(pkt.time - pkt.req->time);
1826143Snate@binkert.org       completionEvent = NULL;
1834762Snate@binkert.org/*   } else if (state == Functional) {
1844762Snate@binkert.org       sendFunctional(pkt);
1856143Snate@binkert.org       // Is this correct???
1866727Ssteve.reinhardt@amd.com       completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
1876727Ssteve.reinhardt@amd.com       completionEvent == NULL;
1886727Ssteve.reinhardt@amd.com   } else
1894762Snate@binkert.org       panic("Unknown memory command state.");
1906143Snate@binkert.org  */
1916143Snate@binkert.org}
1926143Snate@binkert.org
1936143Snate@binkert.orgDmaDevice::~DmaDevice()
1946727Ssteve.reinhardt@amd.com{
1956143Snate@binkert.org    if (dmaPort)
1967674Snate@binkert.org        delete dmaPort;
1977674Snate@binkert.org}
1985604Snate@binkert.org
1996143Snate@binkert.org
2006143Snate@binkert.org