io_device.cc revision 2665:a124942bacb8
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 * Authors: Ali Saidi 29 * Nathan Binkert 30 */ 31 32#include "base/trace.hh" 33#include "dev/io_device.hh" 34#include "sim/builder.hh" 35 36 37PioPort::PioPort(PioDevice *dev, Platform *p) 38 : Port(dev->name() + "-pioport"), device(dev), platform(p) 39{ } 40 41 42Tick 43PioPort::recvAtomic(Packet *pkt) 44{ 45 return device->recvAtomic(pkt); 46} 47 48void 49PioPort::recvFunctional(Packet *pkt) 50{ 51 device->recvAtomic(pkt); 52} 53 54void 55PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 56{ 57 snoop.clear(); 58 device->addressRanges(resp); 59} 60 61 62void 63PioPort::recvRetry() 64{ 65 Packet* pkt = transmitList.front(); 66 if (Port::sendTiming(pkt)) { 67 transmitList.pop_front(); 68 } 69} 70 71 72void 73PioPort::SendEvent::process() 74{ 75 if (port->Port::sendTiming(packet)) 76 return; 77 78 port->transmitList.push_back(packet); 79} 80 81 82 83bool 84PioPort::recvTiming(Packet *pkt) 85{ 86 Tick latency = device->recvAtomic(pkt); 87 // turn packet around to go back to requester 88 pkt->makeTimingResponse(); 89 sendTiming(pkt, latency); 90 return true; 91} 92 93PioDevice::~PioDevice() 94{ 95 if (pioPort) 96 delete pioPort; 97} 98 99void 100PioDevice::init() 101{ 102 if (!pioPort) 103 panic("Pio port not connected to anything!"); 104 pioPort->sendStatusChange(Port::RangeChange); 105} 106 107void 108BasicPioDevice::addressRanges(AddrRangeList &range_list) 109{ 110 assert(pioSize != 0); 111 range_list.clear(); 112 range_list.push_back(RangeSize(pioAddr, pioSize)); 113} 114 115 116DmaPort::DmaPort(DmaDevice *dev, Platform *p) 117 : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) 118{ } 119 120bool 121DmaPort::recvTiming(Packet *pkt) 122{ 123 if (pkt->senderState) { 124 DmaReqState *state; 125 DPRINTF(DMA, "Received response Packet %#x with senderState: %#x\n", 126 pkt, pkt->senderState); 127 state = dynamic_cast<DmaReqState*>(pkt->senderState); 128 assert(state); 129 state->completionEvent->process(); 130 delete pkt->req; 131 delete pkt; 132 } else { 133 DPRINTF(DMA, "Received response Packet %#x with no senderState\n", pkt); 134 delete pkt->req; 135 delete pkt; 136 } 137 138 return true; 139} 140 141DmaDevice::DmaDevice(Params *p) 142 : PioDevice(p), dmaPort(NULL) 143{ } 144 145void 146DmaPort::recvRetry() 147{ 148 Packet* pkt = transmitList.front(); 149 bool result = true; 150 while (result && transmitList.size()) { 151 DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n", 152 pkt, pkt->senderState); 153 result = sendTiming(pkt); 154 if (result) { 155 DPRINTF(DMA, "-- Done\n"); 156 transmitList.pop_front(); 157 pendingCount--; 158 assert(pendingCount >= 0); 159 } else { 160 DPRINTF(DMA, "-- Failed, queued\n"); 161 } 162 } 163} 164 165 166void 167DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 168 uint8_t *data) 169{ 170 assert(event); 171 172 int prevSize = 0; 173 174 for (ChunkGenerator gen(addr, size, peerBlockSize()); 175 !gen.done(); gen.next()) { 176 Request *req = new Request(gen.addr(), gen.size(), 0); 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