io_device.cc (8922:17f037ad8918) io_device.cc (8948:e95ee70f876c)
1/*
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
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 * Authors: Ali Saidi
29 * Nathan Binkert
30 */
31
32#include "base/chunk_generator.hh"
33#include "base/trace.hh"
34#include "debug/BusAddrRanges.hh"
35#include "debug/DMA.hh"
36#include "dev/io_device.hh"
37#include "sim/system.hh"
38
39PioPort::PioPort(PioDevice *dev)
40 : SimpleTimingPort(dev->name() + "-pioport", dev), device(dev)
41{
42}
43
44
45Tick
46PioPort::recvAtomic(PacketPtr pkt)
47{
48 return pkt->isRead() ? device->read(pkt) : device->write(pkt);
49}
50
51AddrRangeList
52PioPort::getAddrRanges()
53{
54 return device->getAddrRanges();
55}
56
57
58PioDevice::PioDevice(const Params *p)
59 : MemObject(p), sys(p->system), pioPort(this)
60{}
61
62PioDevice::~PioDevice()
63{
64}
65
66void
67PioDevice::init()
68{
69 if (!pioPort.isConnected())
70 panic("Pio port of %s not connected to anything!", name());
71 pioPort.sendRangeChange();
72}
73
74SlavePort &
75PioDevice::getSlavePort(const std::string &if_name, int idx)
76{
77 if (if_name == "pio") {
78 return pioPort;
79 }
80 return MemObject::getSlavePort(if_name, idx);
81}
82
83unsigned int
84PioDevice::drain(Event *de)
85{
86 unsigned int count;
87 count = pioPort.drain(de);
88 if (count)
89 changeState(Draining);
90 else
91 changeState(Drained);
92 return count;
93}
94
95BasicPioDevice::BasicPioDevice(const Params *p)
96 : PioDevice(p), pioAddr(p->pio_addr), pioSize(0),
97 pioDelay(p->pio_latency)
98{}
99
100AddrRangeList
101BasicPioDevice::getAddrRanges()
102{
103 assert(pioSize != 0);
104 AddrRangeList ranges;
105 DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
106 ranges.push_back(RangeSize(pioAddr, pioSize));
107 return ranges;
108}
109
110
111DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
112 bool recv_snoops)
113 : MasterPort(dev->name() + "-dmaport", dev), device(dev), sys(s),
114 masterId(s->getMasterId(dev->name())),
115 pendingCount(0), actionInProgress(0), drainEvent(NULL),
116 backoffTime(0), minBackoffDelay(min_backoff),
117 maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops),
118 backoffEvent(this)
119{ }
120
121bool
122DmaPort::recvTiming(PacketPtr pkt)
123{
14 * Copyright (c) 2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 * Nathan Binkert
42 */
43
44#include "base/chunk_generator.hh"
45#include "base/trace.hh"
46#include "debug/BusAddrRanges.hh"
47#include "debug/DMA.hh"
48#include "dev/io_device.hh"
49#include "sim/system.hh"
50
51PioPort::PioPort(PioDevice *dev)
52 : SimpleTimingPort(dev->name() + "-pioport", dev), device(dev)
53{
54}
55
56
57Tick
58PioPort::recvAtomic(PacketPtr pkt)
59{
60 return pkt->isRead() ? device->read(pkt) : device->write(pkt);
61}
62
63AddrRangeList
64PioPort::getAddrRanges()
65{
66 return device->getAddrRanges();
67}
68
69
70PioDevice::PioDevice(const Params *p)
71 : MemObject(p), sys(p->system), pioPort(this)
72{}
73
74PioDevice::~PioDevice()
75{
76}
77
78void
79PioDevice::init()
80{
81 if (!pioPort.isConnected())
82 panic("Pio port of %s not connected to anything!", name());
83 pioPort.sendRangeChange();
84}
85
86SlavePort &
87PioDevice::getSlavePort(const std::string &if_name, int idx)
88{
89 if (if_name == "pio") {
90 return pioPort;
91 }
92 return MemObject::getSlavePort(if_name, idx);
93}
94
95unsigned int
96PioDevice::drain(Event *de)
97{
98 unsigned int count;
99 count = pioPort.drain(de);
100 if (count)
101 changeState(Draining);
102 else
103 changeState(Drained);
104 return count;
105}
106
107BasicPioDevice::BasicPioDevice(const Params *p)
108 : PioDevice(p), pioAddr(p->pio_addr), pioSize(0),
109 pioDelay(p->pio_latency)
110{}
111
112AddrRangeList
113BasicPioDevice::getAddrRanges()
114{
115 assert(pioSize != 0);
116 AddrRangeList ranges;
117 DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
118 ranges.push_back(RangeSize(pioAddr, pioSize));
119 return ranges;
120}
121
122
123DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
124 bool recv_snoops)
125 : MasterPort(dev->name() + "-dmaport", dev), device(dev), sys(s),
126 masterId(s->getMasterId(dev->name())),
127 pendingCount(0), actionInProgress(0), drainEvent(NULL),
128 backoffTime(0), minBackoffDelay(min_backoff),
129 maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops),
130 backoffEvent(this)
131{ }
132
133bool
134DmaPort::recvTiming(PacketPtr pkt)
135{
136 assert(pkt->isResponse());
124 if (pkt->wasNacked()) {
125 DPRINTF(DMA, "Received nacked %s addr %#x\n",
126 pkt->cmdString(), pkt->getAddr());
127
128 if (backoffTime < minBackoffDelay)
129 backoffTime = minBackoffDelay;
130 else if (backoffTime < maxBackoffDelay)
131 backoffTime <<= 1;
132
133 device->reschedule(backoffEvent, curTick() + backoffTime, true);
134
135 DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
136
137 pkt->reinitNacked();
138 queueDma(pkt, true);
137 if (pkt->wasNacked()) {
138 DPRINTF(DMA, "Received nacked %s addr %#x\n",
139 pkt->cmdString(), pkt->getAddr());
140
141 if (backoffTime < minBackoffDelay)
142 backoffTime = minBackoffDelay;
143 else if (backoffTime < maxBackoffDelay)
144 backoffTime <<= 1;
145
146 device->reschedule(backoffEvent, curTick() + backoffTime, true);
147
148 DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
149
150 pkt->reinitNacked();
151 queueDma(pkt, true);
139 } else if (pkt->isRequest() && recvSnoops) {
140 return true;
141 } else if (pkt->senderState) {
142 DmaReqState *state;
143 backoffTime >>= 2;
144
145 DPRINTF(DMA, "Received response %s addr %#x size %#x\n",
146 pkt->cmdString(), pkt->getAddr(), pkt->req->getSize());
147 state = dynamic_cast<DmaReqState*>(pkt->senderState);
148 pendingCount--;
149
150 assert(pendingCount >= 0);
151 assert(state);
152
153 // We shouldn't ever get a block in ownership state
154 assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
155
156 state->numBytes += pkt->req->getSize();
157 assert(state->totBytes >= state->numBytes);
158 if (state->totBytes == state->numBytes) {
159 if (state->completionEvent) {
160 if (state->delay)
161 device->schedule(state->completionEvent,
162 curTick() + state->delay);
163 else
164 state->completionEvent->process();
165 }
166 delete state;
167 }
168 delete pkt->req;
169 delete pkt;
170
171 if (pendingCount == 0 && drainEvent) {
172 drainEvent->process();
173 drainEvent = NULL;
174 }
175 } else {
176 panic("Got packet without sender state... huh?\n");
177 }
178
179 return true;
180}
181
182DmaDevice::DmaDevice(const Params *p)
183 : PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay,
184 params()->max_backoff_delay)
185{ }
186
187void
188DmaDevice::init()
189{
190 if (!dmaPort.isConnected())
191 panic("DMA port of %s not connected to anything!", name());
192 PioDevice::init();
193}
194
195unsigned int
196DmaDevice::drain(Event *de)
197{
198 unsigned int count;
199 count = pioPort.drain(de) + dmaPort.drain(de);
200 if (count)
201 changeState(Draining);
202 else
203 changeState(Drained);
204 return count;
205}
206
207unsigned int
208DmaPort::drain(Event *de)
209{
210 if (pendingCount == 0)
211 return 0;
212 drainEvent = de;
213 return 1;
214}
215
216
217void
218DmaPort::recvRetry()
219{
220 assert(transmitList.size());
221 bool result = true;
222 do {
223 PacketPtr pkt = transmitList.front();
224 DPRINTF(DMA, "Retry on %s addr %#x\n",
225 pkt->cmdString(), pkt->getAddr());
226 result = sendTiming(pkt);
227 if (result) {
228 DPRINTF(DMA, "-- Done\n");
229 transmitList.pop_front();
230 inRetry = false;
231 } else {
232 inRetry = true;
233 DPRINTF(DMA, "-- Failed, queued\n");
234 }
235 } while (!backoffTime && result && transmitList.size());
236
237 if (transmitList.size() && backoffTime && !inRetry) {
238 DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime);
239 if (!backoffEvent.scheduled())
240 device->schedule(backoffEvent, backoffTime + curTick());
241 }
242 DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
243 transmitList.size(), backoffTime, inRetry,
244 backoffEvent.scheduled());
245}
246
247
248void
249DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
250 uint8_t *data, Tick delay, Request::Flags flag)
251{
252 assert(device->getState() == SimObject::Running);
253
254 DmaReqState *reqState = new DmaReqState(event, this, size, delay);
255
256
257 DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
258 event ? event->scheduled() : -1 );
259 for (ChunkGenerator gen(addr, size, peerBlockSize());
260 !gen.done(); gen.next()) {
261 Request *req = new Request(gen.addr(), gen.size(), flag, masterId);
262 PacketPtr pkt = new Packet(req, cmd, Packet::Broadcast);
263
264 // Increment the data pointer on a write
265 if (data)
266 pkt->dataStatic(data + gen.complete());
267
268 pkt->senderState = reqState;
269
270 assert(pendingCount >= 0);
271 pendingCount++;
272 DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
273 gen.size());
274 queueDma(pkt);
275 }
276
277}
278
279void
280DmaPort::queueDma(PacketPtr pkt, bool front)
281{
282
283 if (front)
284 transmitList.push_front(pkt);
285 else
286 transmitList.push_back(pkt);
287 sendDma();
288}
289
290
291void
292DmaPort::sendDma()
293{
294 // some kind of selction between access methods
295 // more work is going to have to be done to make
296 // switching actually work
297 assert(transmitList.size());
298 PacketPtr pkt = transmitList.front();
299
300 Enums::MemoryMode state = sys->getMemoryMode();
301 if (state == Enums::timing) {
302 if (backoffEvent.scheduled() || inRetry) {
303 DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
304 return;
305 }
306
307 DPRINTF(DMA, "Attempting to send %s addr %#x\n",
308 pkt->cmdString(), pkt->getAddr());
309
310 bool result;
311 do {
312 result = sendTiming(pkt);
313 if (result) {
314 transmitList.pop_front();
315 DPRINTF(DMA, "-- Done\n");
316 } else {
317 inRetry = true;
318 DPRINTF(DMA, "-- Failed: queued\n");
319 }
320 } while (result && !backoffTime && transmitList.size());
321
322 if (transmitList.size() && backoffTime && !inRetry &&
323 !backoffEvent.scheduled()) {
324 DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
325 backoffTime+curTick());
326 device->schedule(backoffEvent, backoffTime + curTick());
327 }
328 } else if (state == Enums::atomic) {
329 transmitList.pop_front();
330
331 Tick lat;
332 DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
333 pkt->req->getPaddr(), pkt->req->getSize());
334 lat = sendAtomic(pkt);
335 assert(pkt->senderState);
336 DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
337 assert(state);
338 state->numBytes += pkt->req->getSize();
339
340 DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
341 pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
342 state->totBytes,
343 state->completionEvent ? state->completionEvent->scheduled() : 0 );
344
345 if (state->totBytes == state->numBytes) {
346 if (state->completionEvent) {
347 assert(!state->completionEvent->scheduled());
348 device->schedule(state->completionEvent,
349 curTick() + lat + state->delay);
350 }
351 delete state;
352 delete pkt->req;
353 }
354 pendingCount--;
355 assert(pendingCount >= 0);
356 delete pkt;
357
358 if (pendingCount == 0 && drainEvent) {
359 drainEvent->process();
360 drainEvent = NULL;
361 }
362
363 } else
364 panic("Unknown memory command state.");
365}
366
367DmaDevice::~DmaDevice()
368{
369}
370
371
372MasterPort &
373DmaDevice::getMasterPort(const std::string &if_name, int idx)
374{
375 if (if_name == "dma") {
376 return dmaPort;
377 }
378 return PioDevice::getMasterPort(if_name, idx);
379}
380
152 } else if (pkt->senderState) {
153 DmaReqState *state;
154 backoffTime >>= 2;
155
156 DPRINTF(DMA, "Received response %s addr %#x size %#x\n",
157 pkt->cmdString(), pkt->getAddr(), pkt->req->getSize());
158 state = dynamic_cast<DmaReqState*>(pkt->senderState);
159 pendingCount--;
160
161 assert(pendingCount >= 0);
162 assert(state);
163
164 // We shouldn't ever get a block in ownership state
165 assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
166
167 state->numBytes += pkt->req->getSize();
168 assert(state->totBytes >= state->numBytes);
169 if (state->totBytes == state->numBytes) {
170 if (state->completionEvent) {
171 if (state->delay)
172 device->schedule(state->completionEvent,
173 curTick() + state->delay);
174 else
175 state->completionEvent->process();
176 }
177 delete state;
178 }
179 delete pkt->req;
180 delete pkt;
181
182 if (pendingCount == 0 && drainEvent) {
183 drainEvent->process();
184 drainEvent = NULL;
185 }
186 } else {
187 panic("Got packet without sender state... huh?\n");
188 }
189
190 return true;
191}
192
193DmaDevice::DmaDevice(const Params *p)
194 : PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay,
195 params()->max_backoff_delay)
196{ }
197
198void
199DmaDevice::init()
200{
201 if (!dmaPort.isConnected())
202 panic("DMA port of %s not connected to anything!", name());
203 PioDevice::init();
204}
205
206unsigned int
207DmaDevice::drain(Event *de)
208{
209 unsigned int count;
210 count = pioPort.drain(de) + dmaPort.drain(de);
211 if (count)
212 changeState(Draining);
213 else
214 changeState(Drained);
215 return count;
216}
217
218unsigned int
219DmaPort::drain(Event *de)
220{
221 if (pendingCount == 0)
222 return 0;
223 drainEvent = de;
224 return 1;
225}
226
227
228void
229DmaPort::recvRetry()
230{
231 assert(transmitList.size());
232 bool result = true;
233 do {
234 PacketPtr pkt = transmitList.front();
235 DPRINTF(DMA, "Retry on %s addr %#x\n",
236 pkt->cmdString(), pkt->getAddr());
237 result = sendTiming(pkt);
238 if (result) {
239 DPRINTF(DMA, "-- Done\n");
240 transmitList.pop_front();
241 inRetry = false;
242 } else {
243 inRetry = true;
244 DPRINTF(DMA, "-- Failed, queued\n");
245 }
246 } while (!backoffTime && result && transmitList.size());
247
248 if (transmitList.size() && backoffTime && !inRetry) {
249 DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime);
250 if (!backoffEvent.scheduled())
251 device->schedule(backoffEvent, backoffTime + curTick());
252 }
253 DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
254 transmitList.size(), backoffTime, inRetry,
255 backoffEvent.scheduled());
256}
257
258
259void
260DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
261 uint8_t *data, Tick delay, Request::Flags flag)
262{
263 assert(device->getState() == SimObject::Running);
264
265 DmaReqState *reqState = new DmaReqState(event, this, size, delay);
266
267
268 DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
269 event ? event->scheduled() : -1 );
270 for (ChunkGenerator gen(addr, size, peerBlockSize());
271 !gen.done(); gen.next()) {
272 Request *req = new Request(gen.addr(), gen.size(), flag, masterId);
273 PacketPtr pkt = new Packet(req, cmd, Packet::Broadcast);
274
275 // Increment the data pointer on a write
276 if (data)
277 pkt->dataStatic(data + gen.complete());
278
279 pkt->senderState = reqState;
280
281 assert(pendingCount >= 0);
282 pendingCount++;
283 DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
284 gen.size());
285 queueDma(pkt);
286 }
287
288}
289
290void
291DmaPort::queueDma(PacketPtr pkt, bool front)
292{
293
294 if (front)
295 transmitList.push_front(pkt);
296 else
297 transmitList.push_back(pkt);
298 sendDma();
299}
300
301
302void
303DmaPort::sendDma()
304{
305 // some kind of selction between access methods
306 // more work is going to have to be done to make
307 // switching actually work
308 assert(transmitList.size());
309 PacketPtr pkt = transmitList.front();
310
311 Enums::MemoryMode state = sys->getMemoryMode();
312 if (state == Enums::timing) {
313 if (backoffEvent.scheduled() || inRetry) {
314 DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
315 return;
316 }
317
318 DPRINTF(DMA, "Attempting to send %s addr %#x\n",
319 pkt->cmdString(), pkt->getAddr());
320
321 bool result;
322 do {
323 result = sendTiming(pkt);
324 if (result) {
325 transmitList.pop_front();
326 DPRINTF(DMA, "-- Done\n");
327 } else {
328 inRetry = true;
329 DPRINTF(DMA, "-- Failed: queued\n");
330 }
331 } while (result && !backoffTime && transmitList.size());
332
333 if (transmitList.size() && backoffTime && !inRetry &&
334 !backoffEvent.scheduled()) {
335 DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
336 backoffTime+curTick());
337 device->schedule(backoffEvent, backoffTime + curTick());
338 }
339 } else if (state == Enums::atomic) {
340 transmitList.pop_front();
341
342 Tick lat;
343 DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
344 pkt->req->getPaddr(), pkt->req->getSize());
345 lat = sendAtomic(pkt);
346 assert(pkt->senderState);
347 DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
348 assert(state);
349 state->numBytes += pkt->req->getSize();
350
351 DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
352 pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
353 state->totBytes,
354 state->completionEvent ? state->completionEvent->scheduled() : 0 );
355
356 if (state->totBytes == state->numBytes) {
357 if (state->completionEvent) {
358 assert(!state->completionEvent->scheduled());
359 device->schedule(state->completionEvent,
360 curTick() + lat + state->delay);
361 }
362 delete state;
363 delete pkt->req;
364 }
365 pendingCount--;
366 assert(pendingCount >= 0);
367 delete pkt;
368
369 if (pendingCount == 0 && drainEvent) {
370 drainEvent->process();
371 drainEvent = NULL;
372 }
373
374 } else
375 panic("Unknown memory command state.");
376}
377
378DmaDevice::~DmaDevice()
379{
380}
381
382
383MasterPort &
384DmaDevice::getMasterPort(const std::string &if_name, int idx)
385{
386 if (if_name == "dma") {
387 return dmaPort;
388 }
389 return PioDevice::getMasterPort(if_name, idx);
390}
391