1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "dev/io_device.hh" 30#include "sim/builder.hh" 31 32 33PioPort::PioPort(PioDevice *dev, Platform *p) 34 : Port(dev->name() + "-pioport"), device(dev), platform(p) 35{ } 36 37 38Tick 39PioPort::recvAtomic(Packet *pkt) 40{ 41 return device->recvAtomic(pkt); 42} 43 44void 45PioPort::recvFunctional(Packet *pkt) 46{ 47 device->recvAtomic(pkt); 48} 49 50void 51PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 52{ 53 snoop.clear(); 54 device->addressRanges(resp); 55} 56 57 58Packet * 59PioPort::recvRetry() 60{ 61 Packet* pkt = transmitList.front(); 62 transmitList.pop_front(); 63 return pkt; 64} 65 66 67void 68PioPort::SendEvent::process() 69{
|
70 if (port->Port::sendTiming(packet) == Success)
|
70 if (port->Port::sendTiming(packet)) |
71 return; 72 73 port->transmitList.push_back(packet); 74} 75 76 77bool 78PioPort::recvTiming(Packet *pkt) 79{ 80 device->recvAtomic(pkt); 81 // turn packet around to go back to requester
|
82 pkt->dest = pkt->src;
|
82 pkt->makeTimingResponse(); |
83 sendTiming(pkt, pkt->time - pkt->req->getTime());
|
84 return Success;
|
84 return true; |
85} 86 87PioDevice::~PioDevice() 88{ 89 if (pioPort) 90 delete pioPort; 91} 92 93void 94PioDevice::init() 95{ 96 if (!pioPort) 97 panic("Pio port not connected to anything!"); 98 pioPort->sendStatusChange(Port::RangeChange); 99} 100 101void 102BasicPioDevice::addressRanges(AddrRangeList &range_list) 103{ 104 assert(pioSize != 0); 105 range_list.clear(); 106 range_list.push_back(RangeSize(pioAddr, pioSize)); 107} 108 109 110DmaPort::DmaPort(DmaDevice *dev, Platform *p) 111 : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) 112{ } 113 114bool 115DmaPort::recvTiming(Packet *pkt) 116{ 117 if (pkt->senderState) { 118 DmaReqState *state;
|
119 state = (DmaReqState*)pkt->senderState;
|
119 state = dynamic_cast<DmaReqState*>(pkt->senderState); |
120 state->completionEvent->schedule(pkt->time - pkt->req->getTime()); 121 delete pkt->req; 122 delete pkt; 123 } else { 124 delete pkt->req; 125 delete pkt; 126 } 127
|
128 return Success;
|
128 return Packet::Success; |
129} 130 131DmaDevice::DmaDevice(Params *p) 132 : PioDevice(p), dmaPort(NULL) 133{ } 134 135void 136DmaPort::SendEvent::process() 137{
|
138 if (port->Port::sendTiming(packet) == Success)
|
138 if (port->Port::sendTiming(packet)) |
139 return; 140 141 port->transmitList.push_back(packet); 142} 143 144Packet * 145DmaPort::recvRetry() 146{ 147 Packet* pkt = transmitList.front(); 148 transmitList.pop_front(); 149 return pkt; 150}
|
151 152 |
153void
|
152DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
153 uint8_t *data)
|
154DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 155 uint8_t *data) |
156{
|
155
|
157 assert(event); 158 159 int prevSize = 0;
|
159 Packet basePkt;
160 Request baseReq(false);
|
160
|
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
|
161 for (ChunkGenerator gen(addr, size, peerBlockSize()); 162 !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);
|
163 Request *req = new Request(false); 164 req->setPaddr(gen.addr()); 165 req->setSize(gen.size()); 166 req->setTime(curTick); 167 Packet *pkt = new Packet(req, cmd, Packet::Broadcast); 168 |
169 // Increment the data pointer on a write 170 if (data) 171 pkt->dataStatic(data + prevSize) ;
|
184 prevSize += pkt->size;
|
172 173 prevSize += gen.size(); 174 |
175 // Set the last bit of the dma as the final packet for this dma 176 // and set it's completion event. 177 if (prevSize == size) {
|
188 DmaReqState *state = new DmaReqState(event, true);
189
190 pkt->senderState = (void*)state;
|
178 pkt->senderState = new DmaReqState(event, true); |
179 } 180 assert(pendingCount >= 0); 181 pendingCount++; 182 sendDma(pkt); 183 }
|
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);
|
184} 185 186 187void 188DmaPort::sendDma(Packet *pkt) 189{ 190 // some kind of selction between access methods 191 // more work is going to have to be done to make 192 // switching actually work 193 /* MemState state = device->platform->system->memState; 194 195 if (state == Timing) {
|
211 if (sendTiming(pkt) == Failure)
|
196 if (!sendTiming(pkt)) |
197 transmitList.push_back(&packet); 198 } else if (state == Atomic) {*/ 199 sendAtomic(pkt); 200 if (pkt->senderState) {
|
216 DmaReqState *state = (DmaReqState*)pkt->senderState;
|
201 DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); |
202 state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1); 203 } 204 pendingCount--; 205 assert(pendingCount >= 0); 206 delete pkt->req; 207 delete pkt; 208 209/* } else if (state == Functional) { 210 sendFunctional(pkt); 211 // Is this correct??? 212 completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime); 213 completionEvent == NULL; 214 } else 215 panic("Unknown memory command state."); 216 */ 217} 218 219DmaDevice::~DmaDevice() 220{ 221 if (dmaPort) 222 delete dmaPort; 223} 224 225
|