copy_engine.cc revision 5954
12SN/A/* 211856Sbrandon.potter@amd.com * Copyright (c) 2008 The Regents of The University of Michigan 38852Sandreas.hansson@arm.com * All rights reserved. 48852Sandreas.hansson@arm.com * 58852Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68852Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78852Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88852Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98852Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108852Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118852Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128852Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138852Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 148852Sandreas.hansson@arm.com * this software without specific prior written permission. 151762SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Ali Saidi 292SN/A */ 302SN/A 312SN/A/* @file 322SN/A * Device model for Intel's I/O AT DMA copy engine. 332SN/A */ 342SN/A 352SN/A#include <algorithm> 362SN/A 372SN/A#include "base/cp_annotate.hh" 382SN/A#include "base/trace.hh" 392SN/A#include "dev/copy_engine.hh" 402665Ssaidi@eecs.umich.edu#include "mem/packet.hh" 412665Ssaidi@eecs.umich.edu#include "mem/packet_access.hh" 422665Ssaidi@eecs.umich.edu#include "params/CopyEngine.hh" 432665Ssaidi@eecs.umich.edu#include "sim/stats.hh" 4411856Sbrandon.potter@amd.com#include "sim/system.hh" 452SN/A 462SN/Ausing namespace CopyEngineReg; 4711793Sbrandon.potter@amd.comusing namespace std; 4811793Sbrandon.potter@amd.com 498229Snate@binkert.orgCopyEngine::CopyEngine(const Params *p) 502SN/A : PciDev(p) 516712Snate@binkert.org{ 5211800Sbrandon.potter@amd.com // All Reg regs are initialized to 0 by default 5311911SBrandon.Potter@amd.com regs.chanCount = p->ChanCnt; 5410930Sbrandon.potter@amd.com regs.xferCap = findMsbSet(p->XferCap); 552SN/A regs.attnStatus = 0; 5611800Sbrandon.potter@amd.com 572SN/A if (regs.chanCount > 64) 5811793Sbrandon.potter@amd.com fatal("CopyEngine interface doesn't support more than 64 DMA engines\n"); 5956SN/A 601158SN/A for (int x = 0; x < regs.chanCount; x++) { 61146SN/A CopyEngineChannel *ch = new CopyEngineChannel(this, x); 626658Snate@binkert.org chan.push_back(ch); 632680Sktlim@umich.edu } 642378SN/A} 658706Sandreas.hansson@arm.com 665154Sgblack@eecs.umich.edu 6711800Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::CopyEngineChannel(CopyEngine *_ce, int cid) 6811856Sbrandon.potter@amd.com : ce(_ce), channelId(cid), busy(false), underReset(false), 6911856Sbrandon.potter@amd.com refreshNext(false), latBeforeBegin(ce->params()->latBeforeBegin), 7011794Sbrandon.potter@amd.com latAfterCompletion(ce->params()->latAfterCompletion), 712378SN/A completionDataReg(0), nextState(Idle), drainEvent(NULL), 722SN/A fetchCompleteEvent(this), addrCompleteEvent(this), 732715Sstever@eecs.umich.edu readCompleteEvent(this), writeCompleteEvent(this), 742715Sstever@eecs.umich.edu statusCompleteEvent(this) 7511911SBrandon.Potter@amd.com 762715Sstever@eecs.umich.edu{ 772715Sstever@eecs.umich.edu cr.status.dma_transfer_status(3); 782715Sstever@eecs.umich.edu cr.descChainAddr = 0; 7911911SBrandon.Potter@amd.com cr.completionAddr = 0; 802715Sstever@eecs.umich.edu 812715Sstever@eecs.umich.edu curDmaDesc = new DmaDesc; 8211911SBrandon.Potter@amd.com memset(curDmaDesc, 0, sizeof(DmaDesc)); 835335Shines@cs.fsu.edu copyBuffer = new uint8_t[ce->params()->XferCap]; 8411911SBrandon.Potter@amd.com} 855335Shines@cs.fsu.edu 8611911SBrandon.Potter@amd.comCopyEngine::~CopyEngine() 874157Sgblack@eecs.umich.edu{ 884166Sgblack@eecs.umich.edu for (int x = 0; x < chan.size(); x++) { 8911911SBrandon.Potter@amd.com delete chan[x]; 906691Stjones1@inf.ed.ac.uk } 916691Stjones1@inf.ed.ac.uk} 9211911SBrandon.Potter@amd.com 9311723Sar4jc@virginia.eduCopyEngine::CopyEngineChannel::~CopyEngineChannel() 9411723Sar4jc@virginia.edu{ 9511911SBrandon.Potter@amd.com delete curDmaDesc; 962715Sstever@eecs.umich.edu delete [] copyBuffer; 972715Sstever@eecs.umich.edu delete cePort; 982715Sstever@eecs.umich.edu} 992715Sstever@eecs.umich.edu 1002715Sstever@eecs.umich.eduvoid 1012SN/ACopyEngine::init() 1022107SN/A{ 1032SN/A PciDev::init(); 10412431Sgabeblack@google.com for (int x = 0; x < chan.size(); x++) 10512431Sgabeblack@google.com chan[x]->init(); 1067532Ssteve.reinhardt@amd.com} 10710299Salexandru.dutu@amd.com 10810554Salexandru.dutu@amd.comvoid 10912431Sgabeblack@google.comCopyEngine::CopyEngineChannel::init() 1108852Sandreas.hansson@arm.com{ 11110929Sbrandon.potter@amd.com Port *peer; 11211851Sbrandon.potter@amd.com 11311851Sbrandon.potter@amd.com cePort = new DmaPort(ce, ce->sys); 11411851Sbrandon.potter@amd.com peer = ce->dmaPort->getPeer()->getOwner()->getPort(""); 11511801Sbrandon.potter@amd.com peer->setPeer(cePort); 11611801Sbrandon.potter@amd.com cePort->setPeer(peer); 11711851Sbrandon.potter@amd.com} 11811885Sbrandon.potter@amd.com 11911886Sbrandon.potter@amd.comvoid 12011886Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::recvCommand() 1212SN/A{ 12211885Sbrandon.potter@amd.com if (cr.command.start_dma()) { 12311885Sbrandon.potter@amd.com assert(!busy); 12411885Sbrandon.potter@amd.com cr.status.dma_transfer_status(0); 12511885Sbrandon.potter@amd.com nextState = DescriptorFetch; 12611885Sbrandon.potter@amd.com fetchAddress = cr.descChainAddr; 12711885Sbrandon.potter@amd.com if (ce->getState() == SimObject::Running) 12811885Sbrandon.potter@amd.com fetchDescriptor(cr.descChainAddr); 12911886Sbrandon.potter@amd.com } else if (cr.command.append_dma()) { 13011886Sbrandon.potter@amd.com if (!busy) { 13111886Sbrandon.potter@amd.com nextState = AddressFetch; 13211886Sbrandon.potter@amd.com if (ce->getState() == SimObject::Running) 13311886Sbrandon.potter@amd.com fetchNextAddr(lastDescriptorAddr); 13411886Sbrandon.potter@amd.com } else 13511886Sbrandon.potter@amd.com refreshNext = true; 13611886Sbrandon.potter@amd.com } else if (cr.command.reset_dma()) { 13711886Sbrandon.potter@amd.com if (busy) 13811886Sbrandon.potter@amd.com underReset = true; 13911886Sbrandon.potter@amd.com else { 14011886Sbrandon.potter@amd.com cr.status.dma_transfer_status(3); 14111886Sbrandon.potter@amd.com nextState = Idle; 14211886Sbrandon.potter@amd.com } 14311886Sbrandon.potter@amd.com } else if (cr.command.resume_dma() || cr.command.abort_dma() || 14411886Sbrandon.potter@amd.com cr.command.suspend_dma()) 14511886Sbrandon.potter@amd.com panic("Resume, Abort, and Suspend are not supported\n"); 14611851Sbrandon.potter@amd.com cr.command(0); 14711851Sbrandon.potter@amd.com} 14811851Sbrandon.potter@amd.com 14911851Sbrandon.potter@amd.comTick 15011851Sbrandon.potter@amd.comCopyEngine::read(PacketPtr pkt) 15111851Sbrandon.potter@amd.com{ 15211919SBrandon.Potter@amd.com int bar; 15311851Sbrandon.potter@amd.com Addr daddr; 15411851Sbrandon.potter@amd.com 1552SN/A if (!getBAR(pkt->getAddr(), bar, daddr)) 1562SN/A panic("Invalid PCI memory access to unmapped memory.\n"); 1572SN/A 15811886Sbrandon.potter@amd.com // Only Memory register BAR is allowed 15911886Sbrandon.potter@amd.com assert(bar == 0); 16011886Sbrandon.potter@amd.com 16111920SBrandon.Potter@amd.com int size = pkt->getSize(); 16211920SBrandon.Potter@amd.com if (size != sizeof(uint64_t) && size != sizeof(uint32_t) && 16311920SBrandon.Potter@amd.com size != sizeof(uint16_t) && size != sizeof(uint8_t)) { 16411920SBrandon.Potter@amd.com panic("Unknown size for MMIO access: %d\n", pkt->getSize()); 16511920SBrandon.Potter@amd.com } 16611920SBrandon.Potter@amd.com 16711920SBrandon.Potter@amd.com DPRINTF(DMACopyEngine, "Read device register %#X size: %d\n", daddr, size); 16811920SBrandon.Potter@amd.com 16911920SBrandon.Potter@amd.com pkt->allocate(); 17011886Sbrandon.potter@amd.com 17111886Sbrandon.potter@amd.com /// 17211886Sbrandon.potter@amd.com /// Handle read of register here 17311886Sbrandon.potter@amd.com /// 17411886Sbrandon.potter@amd.com 17511886Sbrandon.potter@amd.com if (daddr < 0x80) { 17611886Sbrandon.potter@amd.com switch (daddr) { 17711886Sbrandon.potter@amd.com case GEN_CHANCOUNT: 17811886Sbrandon.potter@amd.com assert(size == sizeof(regs.chanCount)); 17911886Sbrandon.potter@amd.com pkt->set<uint8_t>(regs.chanCount); 18011886Sbrandon.potter@amd.com break; 18111886Sbrandon.potter@amd.com case GEN_XFERCAP: 18211886Sbrandon.potter@amd.com assert(size == sizeof(regs.xferCap)); 18311886Sbrandon.potter@amd.com pkt->set<uint8_t>(regs.xferCap); 18411886Sbrandon.potter@amd.com break; 18511886Sbrandon.potter@amd.com case GEN_INTRCTRL: 18611886Sbrandon.potter@amd.com assert(size == sizeof(uint8_t)); 18711886Sbrandon.potter@amd.com pkt->set<uint8_t>(regs.intrctrl()); 18811886Sbrandon.potter@amd.com regs.intrctrl.master_int_enable(0); 18911886Sbrandon.potter@amd.com break; 19011886Sbrandon.potter@amd.com case GEN_ATTNSTATUS: 19111886Sbrandon.potter@amd.com assert(size == sizeof(regs.attnStatus)); 19211886Sbrandon.potter@amd.com pkt->set<uint32_t>(regs.attnStatus); 19311886Sbrandon.potter@amd.com regs.attnStatus = 0; 19411886Sbrandon.potter@amd.com break; 19511886Sbrandon.potter@amd.com default: 19611886Sbrandon.potter@amd.com panic("Read request to unknown register number: %#x\n", daddr); 19711886Sbrandon.potter@amd.com } 19811886Sbrandon.potter@amd.com pkt->makeAtomicResponse(); 19911886Sbrandon.potter@amd.com return pioDelay; 20011886Sbrandon.potter@amd.com } 20111886Sbrandon.potter@amd.com 20211886Sbrandon.potter@amd.com 20311886Sbrandon.potter@amd.com // Find which channel we're accessing 20411886Sbrandon.potter@amd.com int chanid = 0; 20511886Sbrandon.potter@amd.com daddr -= 0x80; 20611886Sbrandon.potter@amd.com while (daddr >= 0x80) { 20711886Sbrandon.potter@amd.com chanid++; 20811886Sbrandon.potter@amd.com daddr -= 0x80; 20911886Sbrandon.potter@amd.com } 21011886Sbrandon.potter@amd.com 21111886Sbrandon.potter@amd.com if (chanid >= regs.chanCount) 21211886Sbrandon.potter@amd.com panic("Access to channel %d (device only configured for %d channels)", 21311886Sbrandon.potter@amd.com chanid, regs.chanCount); 21411886Sbrandon.potter@amd.com 21511886Sbrandon.potter@amd.com /// 21611886Sbrandon.potter@amd.com /// Channel registers are handled here 21711886Sbrandon.potter@amd.com /// 21811886Sbrandon.potter@amd.com chan[chanid]->channelRead(pkt, daddr, size); 21911886Sbrandon.potter@amd.com 22011886Sbrandon.potter@amd.com pkt->makeAtomicResponse(); 22111886Sbrandon.potter@amd.com return pioDelay; 22211886Sbrandon.potter@amd.com} 22311886Sbrandon.potter@amd.com 22411886Sbrandon.potter@amd.comvoid 22511886Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::channelRead(Packet *pkt, Addr daddr, int size) 22611886Sbrandon.potter@amd.com{ 22711886Sbrandon.potter@amd.com switch (daddr) { 22811886Sbrandon.potter@amd.com case CHAN_CONTROL: 22911886Sbrandon.potter@amd.com assert(size == sizeof(uint16_t)); 23011886Sbrandon.potter@amd.com pkt->set<uint16_t>(cr.ctrl()); 23111886Sbrandon.potter@amd.com cr.ctrl.in_use(1); 23211886Sbrandon.potter@amd.com break; 23311886Sbrandon.potter@amd.com case CHAN_STATUS: 23411886Sbrandon.potter@amd.com assert(size == sizeof(uint64_t)); 23511886Sbrandon.potter@amd.com pkt->set<uint64_t>(cr.status() | ~busy); 23611886Sbrandon.potter@amd.com break; 23711886Sbrandon.potter@amd.com case CHAN_CHAINADDR: 23811886Sbrandon.potter@amd.com assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); 23911886Sbrandon.potter@amd.com if (size == sizeof(uint64_t)) 24011886Sbrandon.potter@amd.com pkt->set<uint64_t>(cr.descChainAddr); 24111886Sbrandon.potter@amd.com else 24211886Sbrandon.potter@amd.com pkt->set<uint32_t>(bits(cr.descChainAddr,0,31)); 24311886Sbrandon.potter@amd.com break; 24411886Sbrandon.potter@amd.com case CHAN_CHAINADDR_HIGH: 24511886Sbrandon.potter@amd.com assert(size == sizeof(uint32_t)); 24611886Sbrandon.potter@amd.com pkt->set<uint32_t>(bits(cr.descChainAddr,32,63)); 24711886Sbrandon.potter@amd.com break; 24811886Sbrandon.potter@amd.com case CHAN_COMMAND: 24911886Sbrandon.potter@amd.com assert(size == sizeof(uint8_t)); 2502SN/A pkt->set<uint32_t>(cr.command()); 2512SN/A break; 25211522Sstephan.diestelhorst@arm.com case CHAN_CMPLNADDR: 25311522Sstephan.diestelhorst@arm.com assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); 254729SN/A if (size == sizeof(uint64_t)) 2552SN/A pkt->set<uint64_t>(cr.completionAddr); 25611886Sbrandon.potter@amd.com else 25711886Sbrandon.potter@amd.com pkt->set<uint32_t>(bits(cr.completionAddr,0,31)); 2582SN/A break; 2592SN/A case CHAN_CMPLNADDR_HIGH: 2602SN/A assert(size == sizeof(uint32_t)); 2612SN/A pkt->set<uint32_t>(bits(cr.completionAddr,32,63)); 2625713Shsul@eecs.umich.edu break; 2635713Shsul@eecs.umich.edu case CHAN_ERROR: 2642SN/A assert(size == sizeof(uint32_t)); 26511886Sbrandon.potter@amd.com pkt->set<uint32_t>(cr.error()); 26611886Sbrandon.potter@amd.com break; 26711886Sbrandon.potter@amd.com default: 2685512SMichael.Adler@intel.com panic("Read request to unknown channel register number: (%d)%#x\n", 26911919SBrandon.Potter@amd.com channelId, daddr); 2702SN/A } 2712SN/A} 2721395SN/A 27311886Sbrandon.potter@amd.com 27411886Sbrandon.potter@amd.comTick 27511886Sbrandon.potter@amd.comCopyEngine::write(PacketPtr pkt) 27611886Sbrandon.potter@amd.com{ 27711886Sbrandon.potter@amd.com int bar; 27811886Sbrandon.potter@amd.com Addr daddr; 27911886Sbrandon.potter@amd.com 28011886Sbrandon.potter@amd.com 28111886Sbrandon.potter@amd.com if (!getBAR(pkt->getAddr(), bar, daddr)) 28211886Sbrandon.potter@amd.com panic("Invalid PCI memory access to unmapped memory.\n"); 28311886Sbrandon.potter@amd.com 28411886Sbrandon.potter@amd.com // Only Memory register BAR is allowed 28511886Sbrandon.potter@amd.com assert(bar == 0); 2867532Ssteve.reinhardt@amd.com 2871395SN/A int size = pkt->getSize(); 2885713Shsul@eecs.umich.edu 2895713Shsul@eecs.umich.edu /// 2902378SN/A /// Handle write of register here 2912680Sktlim@umich.edu /// 2925713Shsul@eecs.umich.edu 2931395SN/A if (size == sizeof(uint64_t)) { 2941634SN/A uint64_t val M5_VAR_USED = pkt->get<uint64_t>(); 29510407Smitch.hayenga@arm.com DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); 29610298Salexandru.dutu@amd.com } else if (size == sizeof(uint32_t)) { 29710298Salexandru.dutu@amd.com uint32_t val M5_VAR_USED = pkt->get<uint32_t>(); 2981395SN/A DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); 2992SN/A } else if (size == sizeof(uint16_t)) { 30010913Sandreas.sandberg@arm.com uint16_t val M5_VAR_USED = pkt->get<uint16_t>(); 30110913Sandreas.sandberg@arm.com DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); 30210905Sandreas.sandberg@arm.com } else if (size == sizeof(uint8_t)) { 30311856Sbrandon.potter@amd.com uint8_t val M5_VAR_USED = pkt->get<uint8_t>(); 30410913Sandreas.sandberg@arm.com DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); 30510905Sandreas.sandberg@arm.com } else { 30610905Sandreas.sandberg@arm.com panic("Unknown size for MMIO access: %d\n", size); 3078601Ssteve.reinhardt@amd.com } 3088601Ssteve.reinhardt@amd.com 3098601Ssteve.reinhardt@amd.com if (daddr < 0x80) { 31010318Sandreas.hansson@arm.com switch (daddr) { 3118601Ssteve.reinhardt@amd.com case GEN_CHANCOUNT: 31211294Sandreas.hansson@arm.com case GEN_XFERCAP: 31311294Sandreas.hansson@arm.com case GEN_ATTNSTATUS: 3148601Ssteve.reinhardt@amd.com DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n", 3158601Ssteve.reinhardt@amd.com daddr); 31611886Sbrandon.potter@amd.com break; 31711886Sbrandon.potter@amd.com case GEN_INTRCTRL: 31811886Sbrandon.potter@amd.com regs.intrctrl.master_int_enable(bits(pkt->get<uint8_t>(),0,1)); 31911886Sbrandon.potter@amd.com break; 32011886Sbrandon.potter@amd.com default: 32111886Sbrandon.potter@amd.com panic("Read request to unknown register number: %#x\n", daddr); 32211886Sbrandon.potter@amd.com } 32311886Sbrandon.potter@amd.com pkt->makeAtomicResponse(); 32411886Sbrandon.potter@amd.com return pioDelay; 32511886Sbrandon.potter@amd.com } 32611886Sbrandon.potter@amd.com 32711886Sbrandon.potter@amd.com // Find which channel we're accessing 32811886Sbrandon.potter@amd.com int chanid = 0; 32911886Sbrandon.potter@amd.com daddr -= 0x80; 33011886Sbrandon.potter@amd.com while (daddr >= 0x80) { 33111886Sbrandon.potter@amd.com chanid++; 33211886Sbrandon.potter@amd.com daddr -= 0x80; 33311886Sbrandon.potter@amd.com } 33411886Sbrandon.potter@amd.com 3354434Ssaidi@eecs.umich.edu if (chanid >= regs.chanCount) 3368539Sgblack@eecs.umich.edu panic("Access to channel %d (device only configured for %d channels)", 3374434Ssaidi@eecs.umich.edu chanid, regs.chanCount); 33811905SBrandon.Potter@amd.com 33911905SBrandon.Potter@amd.com /// 34011905SBrandon.Potter@amd.com /// Channel registers are handled here 34111905SBrandon.Potter@amd.com /// 3428539Sgblack@eecs.umich.edu chan[chanid]->channelWrite(pkt, daddr, size); 3438539Sgblack@eecs.umich.edu 34411905SBrandon.Potter@amd.com pkt->makeAtomicResponse(); 34510318Sandreas.hansson@arm.com return pioDelay; 3464434Ssaidi@eecs.umich.edu} 3474434Ssaidi@eecs.umich.edu 3484434Ssaidi@eecs.umich.eduvoid 3498539Sgblack@eecs.umich.eduCopyEngine::CopyEngineChannel::channelWrite(Packet *pkt, Addr daddr, int size) 3508539Sgblack@eecs.umich.edu{ 35111905SBrandon.Potter@amd.com switch (daddr) { 35211905SBrandon.Potter@amd.com case CHAN_CONTROL: 35311905SBrandon.Potter@amd.com assert(size == sizeof(uint16_t)); 35411905SBrandon.Potter@amd.com int old_int_disable; 3555154Sgblack@eecs.umich.edu old_int_disable = cr.ctrl.interrupt_disable(); 35611905SBrandon.Potter@amd.com cr.ctrl(pkt->get<uint16_t>()); 3575823Ssaidi@eecs.umich.edu if (cr.ctrl.interrupt_disable()) 35811906SBrandon.Potter@amd.com cr.ctrl.interrupt_disable(0); 35911905SBrandon.Potter@amd.com else 3604434Ssaidi@eecs.umich.edu cr.ctrl.interrupt_disable(old_int_disable); 3614434Ssaidi@eecs.umich.edu break; 3624434Ssaidi@eecs.umich.edu case CHAN_STATUS: 3634434Ssaidi@eecs.umich.edu assert(size == sizeof(uint64_t)); 3644434Ssaidi@eecs.umich.edu DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n", 3655282Srstrong@cs.ucsd.edu daddr); 36610905Sandreas.sandberg@arm.com break; 3673311Ssaidi@eecs.umich.edu case CHAN_CHAINADDR: 36812283Saustinharris@utexas.edu assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); 36910905Sandreas.sandberg@arm.com if (size == sizeof(uint64_t)) 37011856Sbrandon.potter@amd.com cr.descChainAddr = pkt->get<uint64_t>(); 37111856Sbrandon.potter@amd.com else 37211856Sbrandon.potter@amd.com cr.descChainAddr = (uint64_t)pkt->get<uint32_t>() | 37311856Sbrandon.potter@amd.com (cr.descChainAddr & ~mask(32)); 37411856Sbrandon.potter@amd.com DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr); 37511856Sbrandon.potter@amd.com break; 37611856Sbrandon.potter@amd.com case CHAN_CHAINADDR_HIGH: 37711856Sbrandon.potter@amd.com assert(size == sizeof(uint32_t)); 37811856Sbrandon.potter@amd.com cr.descChainAddr = ((uint64_t)pkt->get<uint32_t>() <<32) | 37911856Sbrandon.potter@amd.com (cr.descChainAddr & mask(32)); 3803311Ssaidi@eecs.umich.edu DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr); 3813311Ssaidi@eecs.umich.edu break; 3823311Ssaidi@eecs.umich.edu case CHAN_COMMAND: 3833311Ssaidi@eecs.umich.edu assert(size == sizeof(uint8_t)); 38410905Sandreas.sandberg@arm.com cr.command(pkt->get<uint8_t>()); 3853311Ssaidi@eecs.umich.edu recvCommand(); 38612283Saustinharris@utexas.edu break; 38710905Sandreas.sandberg@arm.com case CHAN_CMPLNADDR: 38811856Sbrandon.potter@amd.com assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); 38911856Sbrandon.potter@amd.com if (size == sizeof(uint64_t)) 39011856Sbrandon.potter@amd.com cr.completionAddr = pkt->get<uint64_t>(); 39111856Sbrandon.potter@amd.com else 39211856Sbrandon.potter@amd.com cr.completionAddr = pkt->get<uint32_t>() | 39311856Sbrandon.potter@amd.com (cr.completionAddr & ~mask(32)); 39411856Sbrandon.potter@amd.com break; 39511856Sbrandon.potter@amd.com case CHAN_CMPLNADDR_HIGH: 39611856Sbrandon.potter@amd.com assert(size == sizeof(uint32_t)); 39711856Sbrandon.potter@amd.com cr.completionAddr = ((uint64_t)pkt->get<uint32_t>() <<32) | 3986820SLisa.Hsu@amd.com (cr.completionAddr & mask(32)); 3996820SLisa.Hsu@amd.com break; 40010930Sbrandon.potter@amd.com case CHAN_ERROR: 40110929Sbrandon.potter@amd.com assert(size == sizeof(uint32_t)); 4023311Ssaidi@eecs.umich.edu cr.error(~pkt->get<uint32_t>() & cr.error()); 4032SN/A break; 4049110Ssteve.reinhardt@amd.com default: 40510558Salexandru.dutu@amd.com panic("Read request to unknown channel register number: (%d)%#x\n", 4069110Ssteve.reinhardt@amd.com channelId, daddr); 40710558Salexandru.dutu@amd.com } 40811294Sandreas.hansson@arm.com} 4099110Ssteve.reinhardt@amd.com 4109110Ssteve.reinhardt@amd.comvoid 4119110Ssteve.reinhardt@amd.comCopyEngine::regStats() 4122378SN/A{ 41311877Sbrandon.potter@amd.com using namespace Stats; 4142093SN/A bytesCopied 41511886Sbrandon.potter@amd.com .init(regs.chanCount) 4162093SN/A .name(name() + ".bytes_copied") 4172093SN/A .desc("Number of bytes copied by each engine") 41811919SBrandon.Potter@amd.com .flags(total) 4192093SN/A ; 4202093SN/A copiesProcessed 42111877Sbrandon.potter@amd.com .init(regs.chanCount) 4222093SN/A .name(name() + ".copies_processed") 4232SN/A .desc("Number of copies processed by each engine") 4246701Sgblack@eecs.umich.edu .flags(total) 42511851Sbrandon.potter@amd.com ; 4266701Sgblack@eecs.umich.edu} 4276701Sgblack@eecs.umich.edu 4286701Sgblack@eecs.umich.eduvoid 4296701Sgblack@eecs.umich.eduCopyEngine::CopyEngineChannel::fetchDescriptor(Addr address) 43010496Ssteve.reinhardt@amd.com{ 43111851Sbrandon.potter@amd.com anDq(); 43210496Ssteve.reinhardt@amd.com anBegin("FetchDescriptor"); 43310496Ssteve.reinhardt@amd.com DPRINTF(DMACopyEngine, "Reading descriptor from at memory location %#x(%#x)\n", 43410496Ssteve.reinhardt@amd.com address, ce->platform->pciToDma(address)); 43510496Ssteve.reinhardt@amd.com assert(address); 43610496Ssteve.reinhardt@amd.com busy = true; 43710496Ssteve.reinhardt@amd.com 43811919SBrandon.Potter@amd.com DPRINTF(DMACopyEngine, "dmaAction: %#x, %d bytes, to addr %#x\n", 43910496Ssteve.reinhardt@amd.com ce->platform->pciToDma(address), sizeof(DmaDesc), curDmaDesc); 44010496Ssteve.reinhardt@amd.com 44111389Sbrandon.potter@amd.com cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address), 44211851Sbrandon.potter@amd.com sizeof(DmaDesc), &fetchCompleteEvent, (uint8_t*)curDmaDesc, 44311389Sbrandon.potter@amd.com latBeforeBegin); 44411389Sbrandon.potter@amd.com lastDescriptorAddr = address; 44511389Sbrandon.potter@amd.com} 44611389Sbrandon.potter@amd.com 44711389Sbrandon.potter@amd.comvoid 44811389Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::fetchDescComplete() 44911389Sbrandon.potter@amd.com{ 45011389Sbrandon.potter@amd.com DPRINTF(DMACopyEngine, "Read of descriptor complete\n"); 45111389Sbrandon.potter@amd.com 45211389Sbrandon.potter@amd.com if ((curDmaDesc->command & DESC_CTRL_NULL)) { 45311389Sbrandon.potter@amd.com DPRINTF(DMACopyEngine, "Got NULL descriptor, skipping\n"); 45411389Sbrandon.potter@amd.com assert(!(curDmaDesc->command & DESC_CTRL_CP_STS)); 45511905SBrandon.Potter@amd.com if (curDmaDesc->command & DESC_CTRL_CP_STS) { 45611905SBrandon.Potter@amd.com panic("Shouldn't be able to get here\n"); 45711389Sbrandon.potter@amd.com nextState = CompletionWrite; 45811389Sbrandon.potter@amd.com if (inDrain()) return; 45911389Sbrandon.potter@amd.com writeCompletionStatus(); 46011389Sbrandon.potter@amd.com } else { 46111905SBrandon.Potter@amd.com anBegin("Idle"); 46211905SBrandon.Potter@amd.com anWait(); 46311389Sbrandon.potter@amd.com busy = false; 46411389Sbrandon.potter@amd.com nextState = Idle; 46511389Sbrandon.potter@amd.com inDrain(); 46611389Sbrandon.potter@amd.com } 46711392Sbrandon.potter@amd.com return; 46811851Sbrandon.potter@amd.com } 46911392Sbrandon.potter@amd.com 47011392Sbrandon.potter@amd.com if (curDmaDesc->command & ~DESC_CTRL_CP_STS) 47111392Sbrandon.potter@amd.com panic("Descriptor has flag other that completion status set\n"); 47211392Sbrandon.potter@amd.com 47311389Sbrandon.potter@amd.com nextState = DMARead; 47411851Sbrandon.potter@amd.com if (inDrain()) return; 47511389Sbrandon.potter@amd.com readCopyBytes(); 47611392Sbrandon.potter@amd.com} 47711389Sbrandon.potter@amd.com 47811389Sbrandon.potter@amd.comvoid 47911389Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::readCopyBytes() 48011389Sbrandon.potter@amd.com{ 48111389Sbrandon.potter@amd.com anBegin("ReadCopyBytes"); 48211851Sbrandon.potter@amd.com DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n", 48311389Sbrandon.potter@amd.com curDmaDesc->len, curDmaDesc->dest, 48411392Sbrandon.potter@amd.com ce->platform->pciToDma(curDmaDesc->src)); 48511389Sbrandon.potter@amd.com cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src), 48611389Sbrandon.potter@amd.com curDmaDesc->len, &readCompleteEvent, copyBuffer, 0); 48711389Sbrandon.potter@amd.com} 48811389Sbrandon.potter@amd.com 48911851Sbrandon.potter@amd.comvoid 49011851Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::readCopyBytesComplete() 4912715Sstever@eecs.umich.edu{ 49211919SBrandon.Potter@amd.com DPRINTF(DMACopyEngine, "Read of bytes to copy complete\n"); 4932715Sstever@eecs.umich.edu 49411140Sjthestness@gmail.com nextState = DMAWrite; 49511140Sjthestness@gmail.com if (inDrain()) return; 49611851Sbrandon.potter@amd.com writeCopyBytes(); 49711851Sbrandon.potter@amd.com} 49811140Sjthestness@gmail.com 49911140Sjthestness@gmail.comvoid 50011851Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::writeCopyBytes() 50111919SBrandon.Potter@amd.com{ 50211851Sbrandon.potter@amd.com anBegin("WriteCopyBytes"); 5032715Sstever@eecs.umich.edu DPRINTF(DMACopyEngine, "Writing %d bytes from buffer to memory location %#x(%#x)\n", 5042715Sstever@eecs.umich.edu curDmaDesc->len, curDmaDesc->dest, 5055089Sgblack@eecs.umich.edu ce->platform->pciToDma(curDmaDesc->dest)); 50611851Sbrandon.potter@amd.com 5075753Ssteve.reinhardt@amd.com cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest), 5085753Ssteve.reinhardt@amd.com curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0); 50911851Sbrandon.potter@amd.com 5105753Ssteve.reinhardt@amd.com ce->bytesCopied[channelId] += curDmaDesc->len; 5115753Ssteve.reinhardt@amd.com ce->copiesProcessed[channelId]++; 5125753Ssteve.reinhardt@amd.com} 5132715Sstever@eecs.umich.edu 51411851Sbrandon.potter@amd.comvoid 5152715Sstever@eecs.umich.eduCopyEngine::CopyEngineChannel::writeCopyBytesComplete() 5162715Sstever@eecs.umich.edu{ 5172715Sstever@eecs.umich.edu DPRINTF(DMACopyEngine, "Write of bytes to copy complete user1: %#x\n", 5182715Sstever@eecs.umich.edu curDmaDesc->user1); 5192715Sstever@eecs.umich.edu 5202715Sstever@eecs.umich.edu cr.status.compl_desc_addr(lastDescriptorAddr >> 6); 52111851Sbrandon.potter@amd.com completionDataReg = cr.status() | 1; 52211851Sbrandon.potter@amd.com 5232715Sstever@eecs.umich.edu anQ("DMAUsedDescQ", channelId, 1); 52411851Sbrandon.potter@amd.com anQ("AppRecvQ", curDmaDesc->user1, curDmaDesc->len); 5255753Ssteve.reinhardt@amd.com if (curDmaDesc->command & DESC_CTRL_CP_STS) { 5265753Ssteve.reinhardt@amd.com nextState = CompletionWrite; 5275753Ssteve.reinhardt@amd.com if (inDrain()) return; 5282715Sstever@eecs.umich.edu writeCompletionStatus(); 52911851Sbrandon.potter@amd.com return; 53011851Sbrandon.potter@amd.com } 5314111Sgblack@eecs.umich.edu 53211851Sbrandon.potter@amd.com continueProcessing(); 5334111Sgblack@eecs.umich.edu} 5342715Sstever@eecs.umich.edu 5352715Sstever@eecs.umich.eduvoid 5362715Sstever@eecs.umich.eduCopyEngine::CopyEngineChannel::continueProcessing() 53711851Sbrandon.potter@amd.com{ 5382715Sstever@eecs.umich.edu busy = false; 5395753Ssteve.reinhardt@amd.com 5402715Sstever@eecs.umich.edu if (underReset) { 5412715Sstever@eecs.umich.edu anBegin("Reset"); 5422715Sstever@eecs.umich.edu anWait(); 5434157Sgblack@eecs.umich.edu underReset = false; 54411851Sbrandon.potter@amd.com refreshNext = false; 54511851Sbrandon.potter@amd.com busy = false; 5464166Sgblack@eecs.umich.edu nextState = Idle; 54711851Sbrandon.potter@amd.com return; 5485753Ssteve.reinhardt@amd.com } 5495753Ssteve.reinhardt@amd.com 5505753Ssteve.reinhardt@amd.com if (curDmaDesc->next) { 5514166Sgblack@eecs.umich.edu nextState = DescriptorFetch; 55211851Sbrandon.potter@amd.com fetchAddress = curDmaDesc->next; 55311851Sbrandon.potter@amd.com if (inDrain()) return; 5545874Sgblack@eecs.umich.edu fetchDescriptor(curDmaDesc->next); 55511851Sbrandon.potter@amd.com } else if (refreshNext) { 5565874Sgblack@eecs.umich.edu nextState = AddressFetch; 5574166Sgblack@eecs.umich.edu refreshNext = false; 5585753Ssteve.reinhardt@amd.com if (inDrain()) return; 5594157Sgblack@eecs.umich.edu fetchNextAddr(lastDescriptorAddr); 5604157Sgblack@eecs.umich.edu } else { 5614157Sgblack@eecs.umich.edu inDrain(); 5622715Sstever@eecs.umich.edu nextState = Idle; 56311851Sbrandon.potter@amd.com anWait(); 5642715Sstever@eecs.umich.edu anBegin("Idle"); 56511851Sbrandon.potter@amd.com } 5665753Ssteve.reinhardt@amd.com} 5675753Ssteve.reinhardt@amd.com 5685753Ssteve.reinhardt@amd.comvoid 5692715Sstever@eecs.umich.eduCopyEngine::CopyEngineChannel::writeCompletionStatus() 57011851Sbrandon.potter@amd.com{ 5712715Sstever@eecs.umich.edu anBegin("WriteCompletionStatus"); 5722715Sstever@eecs.umich.edu DPRINTF(DMACopyEngine, "Writing completion status %#x to address %#x(%#x)\n", 5732715Sstever@eecs.umich.edu completionDataReg, cr.completionAddr, 5742715Sstever@eecs.umich.edu ce->platform->pciToDma(cr.completionAddr)); 5752715Sstever@eecs.umich.edu 5765335Shines@cs.fsu.edu cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(cr.completionAddr), 57711851Sbrandon.potter@amd.com sizeof(completionDataReg), &statusCompleteEvent, 57810037SARM gem5 Developers (uint8_t*)&completionDataReg, latAfterCompletion); 57910037SARM gem5 Developers} 5805335Shines@cs.fsu.edu 58111851Sbrandon.potter@amd.comvoid 5825753Ssteve.reinhardt@amd.comCopyEngine::CopyEngineChannel::writeStatusComplete() 5835753Ssteve.reinhardt@amd.com{ 5845753Ssteve.reinhardt@amd.com DPRINTF(DMACopyEngine, "Writing completion status complete\n"); 5855335Shines@cs.fsu.edu continueProcessing(); 58610037SARM gem5 Developers} 58711851Sbrandon.potter@amd.com 58811851Sbrandon.potter@amd.comvoid 58910037SARM gem5 DevelopersCopyEngine::CopyEngineChannel::fetchNextAddr(Addr address) 59011851Sbrandon.potter@amd.com{ 59111851Sbrandon.potter@amd.com anBegin("FetchNextAddr"); 59210037SARM gem5 Developers DPRINTF(DMACopyEngine, "Fetching next address...\n"); 5935335Shines@cs.fsu.edu busy = true; 59410810Sbr@bsdpad.com cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address + 59510810Sbr@bsdpad.com offsetof(DmaDesc, next)), sizeof(Addr), &addrCompleteEvent, 59611851Sbrandon.potter@amd.com (uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0); 59711851Sbrandon.potter@amd.com} 59810810Sbr@bsdpad.com 59911851Sbrandon.potter@amd.comvoid 60011851Sbrandon.potter@amd.comCopyEngine::CopyEngineChannel::fetchAddrComplete() 60110810Sbr@bsdpad.com{ 60210810Sbr@bsdpad.com DPRINTF(DMACopyEngine, "Fetching next address complete: %#x\n", 6036392Ssaidi@eecs.umich.edu curDmaDesc->next); 6046392Ssaidi@eecs.umich.edu if (!curDmaDesc->next) { 6056392Ssaidi@eecs.umich.edu DPRINTF(DMACopyEngine, "Got NULL descriptor, nothing more to do\n"); 6065335Shines@cs.fsu.edu busy = false; 6075335Shines@cs.fsu.edu nextState = Idle; 6085335Shines@cs.fsu.edu anWait(); 6096691Stjones1@inf.ed.ac.uk anBegin("Idle"); 61011851Sbrandon.potter@amd.com inDrain(); 6116691Stjones1@inf.ed.ac.uk return; 61211851Sbrandon.potter@amd.com } 6136691Stjones1@inf.ed.ac.uk nextState = DescriptorFetch; 6146691Stjones1@inf.ed.ac.uk fetchAddress = curDmaDesc->next; 6156691Stjones1@inf.ed.ac.uk if (inDrain()) return; 6166691Stjones1@inf.ed.ac.uk fetchDescriptor(curDmaDesc->next); 61711851Sbrandon.potter@amd.com} 6186691Stjones1@inf.ed.ac.uk 6196691Stjones1@inf.ed.ac.ukbool 6206691Stjones1@inf.ed.ac.ukCopyEngine::CopyEngineChannel::inDrain() 6216691Stjones1@inf.ed.ac.uk{ 6226691Stjones1@inf.ed.ac.uk if (ce->getState() == SimObject::Draining) { 62311723Sar4jc@virginia.edu DPRINTF(DMACopyEngine, "processing drain\n"); 62411851Sbrandon.potter@amd.com assert(drainEvent); 62511723Sar4jc@virginia.edu drainEvent->process(); 62611851Sbrandon.potter@amd.com drainEvent = NULL; 62711723Sar4jc@virginia.edu } 62811723Sar4jc@virginia.edu 62911723Sar4jc@virginia.edu return ce->getState() != SimObject::Running; 63011723Sar4jc@virginia.edu} 63111851Sbrandon.potter@amd.com 63211723Sar4jc@virginia.eduunsigned int 63311723Sar4jc@virginia.eduCopyEngine::CopyEngineChannel::drain(Event *de) 63411723Sar4jc@virginia.edu{ 63511723Sar4jc@virginia.edu if (nextState == Idle || ce->getState() != SimObject::Running) 6362715Sstever@eecs.umich.edu return 0; 6372715Sstever@eecs.umich.edu unsigned int count = 1; 6382715Sstever@eecs.umich.edu count += cePort->drain(de); 6392715Sstever@eecs.umich.edu 64011919SBrandon.Potter@amd.com DPRINTF(DMACopyEngine, "unable to drain, returning %d\n", count); 6412715Sstever@eecs.umich.edu drainEvent = de; 6422715Sstever@eecs.umich.edu return count; 6432715Sstever@eecs.umich.edu} 64411854Sbrandon.potter@amd.com 64511854Sbrandon.potter@amd.comunsigned int 64611854Sbrandon.potter@amd.comCopyEngine::drain(Event *de) 64711854Sbrandon.potter@amd.com{ 64811854Sbrandon.potter@amd.com unsigned int count; 64911854Sbrandon.potter@amd.com count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); 65011854Sbrandon.potter@amd.com for (int x = 0;x < chan.size(); x++) 65111854Sbrandon.potter@amd.com count += chan[x]->drain(de); 65211854Sbrandon.potter@amd.com 65311854Sbrandon.potter@amd.com if (count) 65411854Sbrandon.potter@amd.com changeState(Draining); 65511854Sbrandon.potter@amd.com else 65611854Sbrandon.potter@amd.com changeState(Drained); 65711854Sbrandon.potter@amd.com 658 DPRINTF(DMACopyEngine, "call to CopyEngine::drain() returning %d\n", count); 659 return count; 660} 661 662void 663CopyEngine::serialize(std::ostream &os) 664{ 665 PciDev::serialize(os); 666 regs.serialize(os); 667 for (int x =0; x < chan.size(); x++) { 668 nameOut(os, csprintf("%s.channel%d", name(), x)); 669 chan[x]->serialize(os); 670 } 671} 672 673void 674CopyEngine::unserialize(Checkpoint *cp, const std::string §ion) 675{ 676 PciDev::unserialize(cp, section); 677 regs.unserialize(cp, section); 678 for (int x = 0; x < chan.size(); x++) 679 chan[x]->unserialize(cp, csprintf("%s.channel%d", section, x)); 680} 681 682void 683CopyEngine::CopyEngineChannel::serialize(std::ostream &os) 684{ 685 SERIALIZE_SCALAR(channelId); 686 SERIALIZE_SCALAR(busy); 687 SERIALIZE_SCALAR(underReset); 688 SERIALIZE_SCALAR(refreshNext); 689 SERIALIZE_SCALAR(lastDescriptorAddr); 690 SERIALIZE_SCALAR(completionDataReg); 691 SERIALIZE_SCALAR(fetchAddress); 692 int nextState = this->nextState; 693 SERIALIZE_SCALAR(nextState); 694 arrayParamOut(os, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc)); 695 SERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap); 696 cr.serialize(os); 697 698} 699void 700CopyEngine::CopyEngineChannel::unserialize(Checkpoint *cp, const std::string §ion) 701{ 702 UNSERIALIZE_SCALAR(channelId); 703 UNSERIALIZE_SCALAR(busy); 704 UNSERIALIZE_SCALAR(underReset); 705 UNSERIALIZE_SCALAR(refreshNext); 706 UNSERIALIZE_SCALAR(lastDescriptorAddr); 707 UNSERIALIZE_SCALAR(completionDataReg); 708 UNSERIALIZE_SCALAR(fetchAddress); 709 int nextState; 710 UNSERIALIZE_SCALAR(nextState); 711 this->nextState = (ChannelState)nextState; 712 arrayParamIn(cp, section, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc)); 713 UNSERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap); 714 cr.unserialize(cp, section); 715 716} 717 718void 719CopyEngine::CopyEngineChannel::restartStateMachine() 720{ 721 switch(nextState) { 722 case AddressFetch: 723 fetchNextAddr(lastDescriptorAddr); 724 break; 725 case DescriptorFetch: 726 fetchDescriptor(fetchAddress); 727 break; 728 case DMARead: 729 readCopyBytes(); 730 break; 731 case DMAWrite: 732 writeCopyBytes(); 733 break; 734 case CompletionWrite: 735 writeCompletionStatus(); 736 break; 737 case Idle: 738 break; 739 default: 740 panic("Unknown state for CopyEngineChannel\n"); 741 } 742} 743 744void 745CopyEngine::resume() 746{ 747 SimObject::resume(); 748 for (int x = 0;x < chan.size(); x++) 749 chan[x]->resume(); 750} 751 752 753void 754CopyEngine::CopyEngineChannel::resume() 755{ 756 DPRINTF(DMACopyEngine, "Restarting state machine at state %d\n", nextState); 757 restartStateMachine(); 758} 759 760CopyEngine * 761CopyEngineParams::create() 762{ 763 return new CopyEngine(this); 764} 765