io_device.cc revision 2639:78773954274f
16184SN/A/* 26184SN/A * Copyright (c) 2006 The Regents of The University of Michigan 36184SN/A * All rights reserved. 46184SN/A * 56184SN/A * Redistribution and use in source and binary forms, with or without 66184SN/A * modification, are permitted provided that the following conditions are 76184SN/A * met: redistributions of source code must retain the above copyright 86184SN/A * notice, this list of conditions and the following disclaimer; 96184SN/A * redistributions in binary form must reproduce the above copyright 106184SN/A * notice, this list of conditions and the following disclaimer in the 116184SN/A * documentation and/or other materials provided with the distribution; 126184SN/A * neither the name of the copyright holders nor the names of its 136184SN/A * contributors may be used to endorse or promote products derived from 146184SN/A * this software without specific prior written permission. 156184SN/A * 166184SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176184SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186184SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196184SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206184SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216184SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226184SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236184SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246184SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256184SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266184SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276184SN/A */ 286184SN/A 296184SN/A#include "dev/io_device.hh" 306184SN/A#include "sim/builder.hh" 316184SN/A 326184SN/A 336184SN/APioPort::PioPort(PioDevice *dev, Platform *p) 346226Snate@binkert.org : device(dev), platform(p) 358232Snate@binkert.org{ } 366184SN/A 379480Snilay@cs.wisc.edu 389480Snilay@cs.wisc.eduTick 399480Snilay@cs.wisc.eduPioPort::recvAtomic(Packet *pkt) 409480Snilay@cs.wisc.edu{ 419480Snilay@cs.wisc.edu return device->recvAtomic(pkt); 426184SN/A} 436184SN/A 446184SN/Avoid 456184SN/APioPort::recvFunctional(Packet *pkt) 466184SN/A{ 476184SN/A device->recvAtomic(pkt); 486184SN/A} 496184SN/A 506184SN/Avoid 516184SN/APioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 526184SN/A{ 536184SN/A snoop.clear(); 546184SN/A device->addressRanges(resp); 556184SN/A} 569480Snilay@cs.wisc.edu 576184SN/A 586184SN/APacket * 596184SN/APioPort::recvRetry() 606184SN/A{ 616227Snate@binkert.org Packet* pkt = transmitList.front(); 629480Snilay@cs.wisc.edu transmitList.pop_front(); 636184SN/A return pkt; 649480Snilay@cs.wisc.edu} 656184SN/A 666184SN/A 679480Snilay@cs.wisc.eduvoid 686184SN/APioPort::SendEvent::process() 699480Snilay@cs.wisc.edu{ 706184SN/A if (port->Port::sendTiming(packet) == Success) 716184SN/A return; 726184SN/A 736184SN/A port->transmitList.push_back(packet); 746184SN/A} 756184SN/A 766227Snate@binkert.org 776184SN/Abool 786184SN/APioPort::recvTiming(Packet *pkt) 796184SN/A{ 806184SN/A device->recvAtomic(pkt); 818842Smrinmoy.ghosh@arm.com // turn packet around to go back to requester 829480Snilay@cs.wisc.edu pkt->dest = pkt->src; 838842Smrinmoy.ghosh@arm.com sendTiming(pkt, pkt->time - pkt->req->getTime()); 848842Smrinmoy.ghosh@arm.com return Success; 858842Smrinmoy.ghosh@arm.com} 868842Smrinmoy.ghosh@arm.com 878842Smrinmoy.ghosh@arm.comPioDevice::~PioDevice() 888842Smrinmoy.ghosh@arm.com{ 896184SN/A if (pioPort) 909480Snilay@cs.wisc.edu delete pioPort; 916184SN/A} 926184SN/A 936184SN/Avoid 946184SN/APioDevice::init() 956184SN/A{ 969480Snilay@cs.wisc.edu if (!pioPort) 976184SN/A panic("Pio port not connected to anything!"); 986184SN/A pioPort->sendStatusChange(Port::RangeChange); 996184SN/A} 1006184SN/A 1019480Snilay@cs.wisc.eduvoid 1026184SN/ABasicPioDevice::addressRanges(AddrRangeList &range_list) 1036184SN/A{ 1046184SN/A assert(pioSize != 0); 1056184SN/A range_list.clear(); 1066184SN/A range_list.push_back(RangeSize(pioAddr, pioSize)); 1076184SN/A} 1086184SN/A 1099480Snilay@cs.wisc.edu 1106184SN/ADmaPort::DmaPort(DmaDevice *dev, Platform *p) 1116184SN/A : device(dev), platform(p), pendingCount(0) 1129480Snilay@cs.wisc.edu{ } 1136184SN/A 1146184SN/Abool 1156184SN/ADmaPort::recvTiming(Packet *pkt) 1166184SN/A{ 1176184SN/A if (pkt->senderState) { 1186184SN/A DmaReqState *state; 1196184SN/A state = (DmaReqState*)pkt->senderState; 1206184SN/A state->completionEvent->schedule(pkt->time - pkt->req->getTime()); 1219480Snilay@cs.wisc.edu delete pkt->req; 1226184SN/A delete pkt; 1236184SN/A } else { 1246184SN/A delete pkt->req; 1256184SN/A delete pkt; 1266184SN/A } 1276184SN/A 1286184SN/A return Success; 1299480Snilay@cs.wisc.edu} 1306184SN/A 1316184SN/ADmaDevice::DmaDevice(Params *p) 1329480Snilay@cs.wisc.edu : PioDevice(p), dmaPort(NULL) 1336184SN/A{ } 1346184SN/A 1359480Snilay@cs.wisc.eduvoid 1366184SN/ADmaPort::SendEvent::process() 1376184SN/A{ 1386184SN/A if (port->Port::sendTiming(packet) == Success) 1396184SN/A return; 1406184SN/A 1416184SN/A port->transmitList.push_back(packet); 1426184SN/A} 1436184SN/A 1446184SN/APacket * 1456184SN/ADmaPort::recvRetry() 1466184SN/A{ 1476184SN/A Packet* pkt = transmitList.front(); 1486184SN/A transmitList.pop_front(); 1496184SN/A return pkt; 1506184SN/A} 1516184SN/Avoid 1526184SN/ADmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event, 1536184SN/A uint8_t *data) 1549480Snilay@cs.wisc.edu{ 1559480Snilay@cs.wisc.edu 1569480Snilay@cs.wisc.edu assert(event); 1579480Snilay@cs.wisc.edu 1589480Snilay@cs.wisc.edu int prevSize = 0; 159 Packet basePkt; 160 Request baseReq(false); 161 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 172 for (ChunkGenerator gen(addr, size, peerBlockSize()); 173 !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); 181 // Increment the data pointer on a write 182 if (data) 183 pkt->dataStatic(data + prevSize) ; 184 prevSize += pkt->size; 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 DmaReqState *state = new DmaReqState(event, true); 189 190 pkt->senderState = (void*)state; 191 } 192 assert(pendingCount >= 0); 193 pendingCount++; 194 sendDma(pkt); 195 } 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); 199} 200 201 202void 203DmaPort::sendDma(Packet *pkt) 204{ 205 // some kind of selction between access methods 206 // more work is going to have to be done to make 207 // switching actually work 208 /* MemState state = device->platform->system->memState; 209 210 if (state == Timing) { 211 if (sendTiming(pkt) == Failure) 212 transmitList.push_back(&packet); 213 } else if (state == Atomic) {*/ 214 sendAtomic(pkt); 215 if (pkt->senderState) { 216 DmaReqState *state = (DmaReqState*)pkt->senderState; 217 state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1); 218 } 219 pendingCount--; 220 assert(pendingCount >= 0); 221 delete pkt->req; 222 delete pkt; 223 224/* } else if (state == Functional) { 225 sendFunctional(pkt); 226 // Is this correct??? 227 completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime); 228 completionEvent == NULL; 229 } else 230 panic("Unknown memory command state."); 231 */ 232} 233 234DmaDevice::~DmaDevice() 235{ 236 if (dmaPort) 237 delete dmaPort; 238} 239 240 241