io_device.cc revision 2639:78773954274f
16184SN/A/*
26184SN/A * Copyright (c) 2006 The Regents of The University of Michigan
36184SN/A * All rights reserved.
46184SN/A *
56184SN/A * Redistribution and use in source and binary forms, with or without
66184SN/A * modification, are permitted provided that the following conditions are
76184SN/A * met: redistributions of source code must retain the above copyright
86184SN/A * notice, this list of conditions and the following disclaimer;
96184SN/A * redistributions in binary form must reproduce the above copyright
106184SN/A * notice, this list of conditions and the following disclaimer in the
116184SN/A * documentation and/or other materials provided with the distribution;
126184SN/A * neither the name of the copyright holders nor the names of its
136184SN/A * contributors may be used to endorse or promote products derived from
146184SN/A * this software without specific prior written permission.
156184SN/A *
166184SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176184SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186184SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196184SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206184SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216184SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226184SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236184SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246184SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256184SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266184SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276184SN/A */
286184SN/A
296184SN/A#include "dev/io_device.hh"
306184SN/A#include "sim/builder.hh"
316184SN/A
326184SN/A
336184SN/APioPort::PioPort(PioDevice *dev, Platform *p)
346226Snate@binkert.org        : device(dev), platform(p)
358232Snate@binkert.org{ }
366184SN/A
379480Snilay@cs.wisc.edu
389480Snilay@cs.wisc.eduTick
399480Snilay@cs.wisc.eduPioPort::recvAtomic(Packet *pkt)
409480Snilay@cs.wisc.edu{
419480Snilay@cs.wisc.edu    return device->recvAtomic(pkt);
426184SN/A}
436184SN/A
446184SN/Avoid
456184SN/APioPort::recvFunctional(Packet *pkt)
466184SN/A{
476184SN/A    device->recvAtomic(pkt);
486184SN/A}
496184SN/A
506184SN/Avoid
516184SN/APioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
526184SN/A{
536184SN/A    snoop.clear();
546184SN/A    device->addressRanges(resp);
556184SN/A}
569480Snilay@cs.wisc.edu
576184SN/A
586184SN/APacket *
596184SN/APioPort::recvRetry()
606184SN/A{
616227Snate@binkert.org    Packet* pkt = transmitList.front();
629480Snilay@cs.wisc.edu    transmitList.pop_front();
636184SN/A    return pkt;
649480Snilay@cs.wisc.edu}
656184SN/A
666184SN/A
679480Snilay@cs.wisc.eduvoid
686184SN/APioPort::SendEvent::process()
699480Snilay@cs.wisc.edu{
706184SN/A    if (port->Port::sendTiming(packet) == Success)
716184SN/A        return;
726184SN/A
736184SN/A    port->transmitList.push_back(packet);
746184SN/A}
756184SN/A
766227Snate@binkert.org
776184SN/Abool
786184SN/APioPort::recvTiming(Packet *pkt)
796184SN/A{
806184SN/A    device->recvAtomic(pkt);
818842Smrinmoy.ghosh@arm.com    // turn packet around to go back to requester
829480Snilay@cs.wisc.edu    pkt->dest = pkt->src;
838842Smrinmoy.ghosh@arm.com    sendTiming(pkt, pkt->time - pkt->req->getTime());
848842Smrinmoy.ghosh@arm.com    return Success;
858842Smrinmoy.ghosh@arm.com}
868842Smrinmoy.ghosh@arm.com
878842Smrinmoy.ghosh@arm.comPioDevice::~PioDevice()
888842Smrinmoy.ghosh@arm.com{
896184SN/A    if (pioPort)
909480Snilay@cs.wisc.edu        delete pioPort;
916184SN/A}
926184SN/A
936184SN/Avoid
946184SN/APioDevice::init()
956184SN/A{
969480Snilay@cs.wisc.edu    if (!pioPort)
976184SN/A        panic("Pio port not connected to anything!");
986184SN/A    pioPort->sendStatusChange(Port::RangeChange);
996184SN/A}
1006184SN/A
1019480Snilay@cs.wisc.eduvoid
1026184SN/ABasicPioDevice::addressRanges(AddrRangeList &range_list)
1036184SN/A{
1046184SN/A    assert(pioSize != 0);
1056184SN/A    range_list.clear();
1066184SN/A    range_list.push_back(RangeSize(pioAddr, pioSize));
1076184SN/A}
1086184SN/A
1099480Snilay@cs.wisc.edu
1106184SN/ADmaPort::DmaPort(DmaDevice *dev, Platform *p)
1116184SN/A        : device(dev), platform(p), pendingCount(0)
1129480Snilay@cs.wisc.edu{ }
1136184SN/A
1146184SN/Abool
1156184SN/ADmaPort::recvTiming(Packet *pkt)
1166184SN/A{
1176184SN/A    if (pkt->senderState) {
1186184SN/A        DmaReqState *state;
1196184SN/A        state = (DmaReqState*)pkt->senderState;
1206184SN/A        state->completionEvent->schedule(pkt->time - pkt->req->getTime());
1219480Snilay@cs.wisc.edu        delete pkt->req;
1226184SN/A        delete pkt;
1236184SN/A    }  else {
1246184SN/A        delete pkt->req;
1256184SN/A        delete pkt;
1266184SN/A    }
1276184SN/A
1286184SN/A    return Success;
1299480Snilay@cs.wisc.edu}
1306184SN/A
1316184SN/ADmaDevice::DmaDevice(Params *p)
1329480Snilay@cs.wisc.edu    : PioDevice(p), dmaPort(NULL)
1336184SN/A{ }
1346184SN/A
1359480Snilay@cs.wisc.eduvoid
1366184SN/ADmaPort::SendEvent::process()
1376184SN/A{
1386184SN/A    if (port->Port::sendTiming(packet) == Success)
1396184SN/A        return;
1406184SN/A
1416184SN/A    port->transmitList.push_back(packet);
1426184SN/A}
1436184SN/A
1446184SN/APacket *
1456184SN/ADmaPort::recvRetry()
1466184SN/A{
1476184SN/A    Packet* pkt = transmitList.front();
1486184SN/A    transmitList.pop_front();
1496184SN/A    return pkt;
1506184SN/A}
1516184SN/Avoid
1526184SN/ADmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
1536184SN/A        uint8_t *data)
1549480Snilay@cs.wisc.edu{
1559480Snilay@cs.wisc.edu
1569480Snilay@cs.wisc.edu    assert(event);
1579480Snilay@cs.wisc.edu
1589480Snilay@cs.wisc.edu    int prevSize = 0;
159    Packet basePkt;
160    Request baseReq(false);
161
162    basePkt.flags = 0;
163    basePkt.coherence = NULL;
164    basePkt.senderState = NULL;
165    basePkt.dest = Packet::Broadcast;
166    basePkt.cmd = cmd;
167    basePkt.result = Unknown;
168    basePkt.req = NULL;
169//    baseReq.nicReq = true;
170    baseReq.setTime(curTick);
171
172    for (ChunkGenerator gen(addr, size, peerBlockSize());
173         !gen.done(); gen.next()) {
174            Packet *pkt = new Packet(basePkt);
175            Request *req = new Request(baseReq);
176            pkt->addr = gen.addr();
177            pkt->size = gen.size();
178            pkt->req = req;
179            pkt->req->setPaddr(pkt->addr);
180            pkt->req->setSize(pkt->size);
181            // Increment the data pointer on a write
182            if (data)
183                pkt->dataStatic(data + prevSize) ;
184            prevSize += pkt->size;
185            // Set the last bit of the dma as the final packet for this dma
186            // and set it's completion event.
187            if (prevSize == size) {
188                DmaReqState *state = new DmaReqState(event, true);
189
190                pkt->senderState = (void*)state;
191            }
192            assert(pendingCount >= 0);
193            pendingCount++;
194            sendDma(pkt);
195    }
196    // since this isn't getting used and we want a check to make sure that all
197    // packets had data in them at some point.
198    basePkt.dataStatic((uint8_t*)NULL);
199}
200
201
202void
203DmaPort::sendDma(Packet *pkt)
204{
205   // some kind of selction between access methods
206   // more work is going to have to be done to make
207   // switching actually work
208  /* MemState state = device->platform->system->memState;
209
210   if (state == Timing) {
211       if (sendTiming(pkt) == Failure)
212           transmitList.push_back(&packet);
213    } else if (state == Atomic) {*/
214       sendAtomic(pkt);
215       if (pkt->senderState) {
216           DmaReqState *state = (DmaReqState*)pkt->senderState;
217           state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
218       }
219       pendingCount--;
220       assert(pendingCount >= 0);
221       delete pkt->req;
222       delete pkt;
223
224/*   } else if (state == Functional) {
225       sendFunctional(pkt);
226       // Is this correct???
227       completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
228       completionEvent == NULL;
229   } else
230       panic("Unknown memory command state.");
231  */
232}
233
234DmaDevice::~DmaDevice()
235{
236    if (dmaPort)
237        delete dmaPort;
238}
239
240
241