io_device.cc revision 2659
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 "base/trace.hh" 30#include "dev/io_device.hh" 31#include "sim/builder.hh" 32 33 34PioPort::PioPort(PioDevice *dev, Platform *p) 35 : Port(dev->name() + "-pioport"), device(dev), platform(p) 36{ } 37 38 39Tick 40PioPort::recvAtomic(Packet *pkt) 41{ 42 return device->recvAtomic(pkt); 43} 44 45void 46PioPort::recvFunctional(Packet *pkt) 47{ 48 device->recvAtomic(pkt); 49} 50 51void 52PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 53{ 54 snoop.clear(); 55 device->addressRanges(resp); 56} 57 58 59void 60PioPort::recvRetry() 61{ 62 Packet* pkt = transmitList.front(); 63 if (Port::sendTiming(pkt)) { 64 transmitList.pop_front(); 65 } 66} 67 68 69void 70PioPort::SendEvent::process() 71{ 72 if (port->Port::sendTiming(packet)) 73 return; 74 75 port->transmitList.push_back(packet); 76} 77 78 79 80bool 81PioPort::recvTiming(Packet *pkt) 82{ 83 device->recvAtomic(pkt); 84 // turn packet around to go back to requester 85 pkt->makeTimingResponse(); 86 sendTiming(pkt, pkt->time - pkt->req->getTime()); 87 return true; 88} 89 90PioDevice::~PioDevice() 91{ 92 if (pioPort) 93 delete pioPort; 94} 95 96void 97PioDevice::init() 98{ 99 if (!pioPort) 100 panic("Pio port not connected to anything!"); 101 pioPort->sendStatusChange(Port::RangeChange); 102} 103 104void 105BasicPioDevice::addressRanges(AddrRangeList &range_list) 106{ 107 assert(pioSize != 0); 108 range_list.clear(); 109 range_list.push_back(RangeSize(pioAddr, pioSize)); 110} 111 112 113DmaPort::DmaPort(DmaDevice *dev, Platform *p) 114 : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) 115{ } 116 117bool 118DmaPort::recvTiming(Packet *pkt) 119{ 120 if (pkt->senderState) { 121 DmaReqState *state; 122 DPRINTF(DMA, "Received response Packet %#x with senderState: %#x\n", 123 pkt, pkt->senderState); 124 state = dynamic_cast<DmaReqState*>(pkt->senderState); 125 assert(state); 126 state->completionEvent->process(); 127 delete pkt->req; 128 delete pkt; 129 } else { 130 DPRINTF(DMA, "Received response Packet %#x with no senderState\n", pkt); 131 delete pkt->req; 132 delete pkt; 133 } 134 135 return true; 136} 137 138DmaDevice::DmaDevice(Params *p) 139 : PioDevice(p), dmaPort(NULL) 140{ } 141 142void 143DmaPort::recvRetry() 144{ 145 Packet* pkt = transmitList.front(); 146 bool result = true; 147 while (result && transmitList.size()) { 148 DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n", 149 pkt, pkt->senderState); 150 result = sendTiming(pkt); 151 if (result) { 152 DPRINTF(DMA, "-- Done\n"); 153 transmitList.pop_front(); 154 pendingCount--; 155 assert(pendingCount >= 0); 156 } else { 157 DPRINTF(DMA, "-- Failed, queued\n"); 158 } 159 } 160} 161 162 163void 164DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 165 uint8_t *data) 166{ 167 assert(event); 168 169 int prevSize = 0; 170 171 for (ChunkGenerator gen(addr, size, peerBlockSize()); 172 !gen.done(); gen.next()) { 173 Request *req = new Request(false); 174 req->setPaddr(gen.addr()); 175 req->setSize(gen.size()); 176 req->setTime(curTick); 177 Packet *pkt = new Packet(req, cmd, Packet::Broadcast); 178 179 // Increment the data pointer on a write 180 if (data) 181 pkt->dataStatic(data + prevSize) ; 182 183 prevSize += gen.size(); 184 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 pkt->senderState = new DmaReqState(event, true); 189 } 190 assert(pendingCount >= 0); 191 pendingCount++; 192 sendDma(pkt); 193 } 194} 195 196 197void 198DmaPort::sendDma(Packet *pkt) 199{ 200 // some kind of selction between access methods 201 // more work is going to have to be done to make 202 // switching actually work 203 /* MemState state = device->platform->system->memState; 204 205 if (state == Timing) { */ 206 DPRINTF(DMA, "Attempting to send Packet %#x with senderState: %#x\n", 207 pkt, pkt->senderState); 208 if (transmitList.size() || !sendTiming(pkt)) { 209 transmitList.push_back(pkt); 210 DPRINTF(DMA, "-- Failed: queued\n"); 211 } else { 212 DPRINTF(DMA, "-- Done\n"); 213 pendingCount--; 214 assert(pendingCount >= 0); 215 } 216 /* } else if (state == Atomic) { 217 sendAtomic(pkt); 218 if (pkt->senderState) { 219 DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); 220 assert(state); 221 state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1); 222 } 223 pendingCount--; 224 assert(pendingCount >= 0); 225 delete pkt->req; 226 delete pkt; 227 228 } else if (state == Functional) { 229 sendFunctional(pkt); 230 // Is this correct??? 231 completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime); 232 completionEvent == NULL; 233 } else 234 panic("Unknown memory command state."); 235 */ 236} 237 238DmaDevice::~DmaDevice() 239{ 240 if (dmaPort) 241 delete dmaPort; 242} 243 244 245