io_device.cc (8949:3fa1ee293096) io_device.cc (8975:7f36d4436074)
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 *
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
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 *
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)
134DmaPort::recvTimingResp(PacketPtr pkt)
135{
135{
136 assert(pkt->isResponse());
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);
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());
136 if (pkt->wasNacked()) {
137 DPRINTF(DMA, "Received nacked %s addr %#x\n",
138 pkt->cmdString(), pkt->getAddr());
139
140 if (backoffTime < minBackoffDelay)
141 backoffTime = minBackoffDelay;
142 else if (backoffTime < maxBackoffDelay)
143 backoffTime <<= 1;
144
145 device->reschedule(backoffEvent, curTick() + backoffTime, true);
146
147 DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
148
149 pkt->reinitNacked();
150 queueDma(pkt, true);
151 } else if (pkt->senderState) {
152 DmaReqState *state;
153 backoffTime >>= 2;
154
155 DPRINTF(DMA, "Received response %s addr %#x size %#x\n",
156 pkt->cmdString(), pkt->getAddr(), pkt->req->getSize());
157 state = dynamic_cast<DmaReqState*>(pkt->senderState);
158 pendingCount--;
159
160 assert(pendingCount >= 0);
161 assert(state);
162
163 // We shouldn't ever get a block in ownership state
164 assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
165
166 state->numBytes += pkt->req->getSize();
167 assert(state->totBytes >= state->numBytes);
168 if (state->totBytes == state->numBytes) {
169 if (state->completionEvent) {
170 if (state->delay)
171 device->schedule(state->completionEvent,
172 curTick() + state->delay);
173 else
174 state->completionEvent->process();
175 }
176 delete state;
177 }
178 delete pkt->req;
179 delete pkt;
180
181 if (pendingCount == 0 && drainEvent) {
182 drainEvent->process();
183 drainEvent = NULL;
184 }
185 } else {
186 panic("Got packet without sender state... huh?\n");
187 }
188
189 return true;
190}
191
192DmaDevice::DmaDevice(const Params *p)
193 : PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay,
194 params()->max_backoff_delay)
195{ }
196
197void
198DmaDevice::init()
199{
200 if (!dmaPort.isConnected())
201 panic("DMA port of %s not connected to anything!", name());
202 PioDevice::init();
203}
204
205unsigned int
206DmaDevice::drain(Event *de)
207{
208 unsigned int count;
209 count = pioPort.drain(de) + dmaPort.drain(de);
210 if (count)
211 changeState(Draining);
212 else
213 changeState(Drained);
214 return count;
215}
216
217unsigned int
218DmaPort::drain(Event *de)
219{
220 if (pendingCount == 0)
221 return 0;
222 drainEvent = de;
223 return 1;
224}
225
226
227void
228DmaPort::recvRetry()
229{
230 assert(transmitList.size());
231 bool result = true;
232 do {
233 PacketPtr pkt = transmitList.front();
234 DPRINTF(DMA, "Retry on %s addr %#x\n",
235 pkt->cmdString(), pkt->getAddr());
237 result = sendTiming(pkt);
236 result = sendTimingReq(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);
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 {
237 if (result) {
238 DPRINTF(DMA, "-- Done\n");
239 transmitList.pop_front();
240 inRetry = false;
241 } else {
242 inRetry = true;
243 DPRINTF(DMA, "-- Failed, queued\n");
244 }
245 } while (!backoffTime && result && transmitList.size());
246
247 if (transmitList.size() && backoffTime && !inRetry) {
248 DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime);
249 if (!backoffEvent.scheduled())
250 device->schedule(backoffEvent, backoffTime + curTick());
251 }
252 DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
253 transmitList.size(), backoffTime, inRetry,
254 backoffEvent.scheduled());
255}
256
257
258void
259DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
260 uint8_t *data, Tick delay, Request::Flags flag)
261{
262 assert(device->getState() == SimObject::Running);
263
264 DmaReqState *reqState = new DmaReqState(event, this, size, delay);
265
266
267 DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
268 event ? event->scheduled() : -1 );
269 for (ChunkGenerator gen(addr, size, peerBlockSize());
270 !gen.done(); gen.next()) {
271 Request *req = new Request(gen.addr(), gen.size(), flag, masterId);
272 PacketPtr pkt = new Packet(req, cmd);
273
274 // Increment the data pointer on a write
275 if (data)
276 pkt->dataStatic(data + gen.complete());
277
278 pkt->senderState = reqState;
279
280 assert(pendingCount >= 0);
281 pendingCount++;
282 DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
283 gen.size());
284 queueDma(pkt);
285 }
286
287}
288
289void
290DmaPort::queueDma(PacketPtr pkt, bool front)
291{
292
293 if (front)
294 transmitList.push_front(pkt);
295 else
296 transmitList.push_back(pkt);
297 sendDma();
298}
299
300
301void
302DmaPort::sendDma()
303{
304 // some kind of selction between access methods
305 // more work is going to have to be done to make
306 // switching actually work
307 assert(transmitList.size());
308 PacketPtr pkt = transmitList.front();
309
310 Enums::MemoryMode state = sys->getMemoryMode();
311 if (state == Enums::timing) {
312 if (backoffEvent.scheduled() || inRetry) {
313 DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
314 return;
315 }
316
317 DPRINTF(DMA, "Attempting to send %s addr %#x\n",
318 pkt->cmdString(), pkt->getAddr());
319
320 bool result;
321 do {
323 result = sendTiming(pkt);
322 result = sendTimingReq(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
323 if (result) {
324 transmitList.pop_front();
325 DPRINTF(DMA, "-- Done\n");
326 } else {
327 inRetry = true;
328 DPRINTF(DMA, "-- Failed: queued\n");
329 }
330 } while (result && !backoffTime && transmitList.size());
331
332 if (transmitList.size() && backoffTime && !inRetry &&
333 !backoffEvent.scheduled()) {
334 DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
335 backoffTime+curTick());
336 device->schedule(backoffEvent, backoffTime + curTick());
337 }
338 } else if (state == Enums::atomic) {
339 transmitList.pop_front();
340
341 Tick lat;
342 DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
343 pkt->req->getPaddr(), pkt->req->getSize());
344 lat = sendAtomic(pkt);
345 assert(pkt->senderState);
346 DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
347 assert(state);
348 state->numBytes += pkt->req->getSize();
349
350 DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
351 pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
352 state->totBytes,
353 state->completionEvent ? state->completionEvent->scheduled() : 0 );
354
355 if (state->totBytes == state->numBytes) {
356 if (state->completionEvent) {
357 assert(!state->completionEvent->scheduled());
358 device->schedule(state->completionEvent,
359 curTick() + lat + state->delay);
360 }
361 delete state;
362 delete pkt->req;
363 }
364 pendingCount--;
365 assert(pendingCount >= 0);
366 delete pkt;
367
368 if (pendingCount == 0 && drainEvent) {
369 drainEvent->process();
370 drainEvent = NULL;
371 }
372
373 } else
374 panic("Unknown memory command state.");
375}
376
377DmaDevice::~DmaDevice()
378{
379}
380
381
382MasterPort &
383DmaDevice::getMasterPort(const std::string &if_name, int idx)
384{
385 if (if_name == "dma") {
386 return dmaPort;
387 }
388 return PioDevice::getMasterPort(if_name, idx);
389}
390