iob.cc revision 7723
15449Sgblack@eecs.umich.edu/* 28610Snilay@cs.wisc.edu * Copyright (c) 2006 The Regents of The University of Michigan 34519Sgblack@eecs.umich.edu * All rights reserved. 44519Sgblack@eecs.umich.edu * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 134519Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 157087Snate@binkert.org * 167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224519Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244519Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254519Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264519Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274519Sgblack@eecs.umich.edu * 284519Sgblack@eecs.umich.edu * Authors: Ali Saidi 294519Sgblack@eecs.umich.edu */ 304519Sgblack@eecs.umich.edu 314519Sgblack@eecs.umich.edu/** @file 324519Sgblack@eecs.umich.edu * This device implemetns the niagara I/O bridge chip. It manages incomming 334519Sgblack@eecs.umich.edu * interrupts and posts them to the CPU when needed. It holds mask registers and 344519Sgblack@eecs.umich.edu * various status registers for CPUs to check what interrupts are pending as 354519Sgblack@eecs.umich.edu * well as facilities to send IPIs to other cpus. 364519Sgblack@eecs.umich.edu */ 374519Sgblack@eecs.umich.edu 384519Sgblack@eecs.umich.edu#include <cstring> 394519Sgblack@eecs.umich.edu 404519Sgblack@eecs.umich.edu#include "arch/sparc/isa_traits.hh" 414519Sgblack@eecs.umich.edu#include "arch/sparc/faults.hh" 424519Sgblack@eecs.umich.edu#include "base/bitfield.hh" 434519Sgblack@eecs.umich.edu#include "base/trace.hh" 444519Sgblack@eecs.umich.edu#include "cpu/intr_control.hh" 454590Sgblack@eecs.umich.edu#include "dev/sparc/iob.hh" 465163Sgblack@eecs.umich.edu#include "dev/platform.hh" 474590Sgblack@eecs.umich.edu#include "mem/port.hh" 484590Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 494590Sgblack@eecs.umich.edu#include "sim/faults.hh" 505163Sgblack@eecs.umich.edu#include "sim/system.hh" 514590Sgblack@eecs.umich.edu 524590Sgblack@eecs.umich.eduIob::Iob(const Params *p) 535163Sgblack@eecs.umich.edu : PioDevice(p), ic(p->platform->intrctrl) 547620Sgblack@eecs.umich.edu{ 554590Sgblack@eecs.umich.edu iobManAddr = ULL(0x9800000000); 564696Sgblack@eecs.umich.edu iobManSize = ULL(0x0100000000); 574696Sgblack@eecs.umich.edu iobJBusAddr = ULL(0x9F00000000); 584590Sgblack@eecs.umich.edu iobJBusSize = ULL(0x0100000000); 595172Sgblack@eecs.umich.edu assert (params()->system->threadContexts.size() <= MaxNiagaraProcs); 605172Sgblack@eecs.umich.edu 615172Sgblack@eecs.umich.edu pioDelay = p->pio_latency; 625172Sgblack@eecs.umich.edu 635172Sgblack@eecs.umich.edu // Get the interrupt controller from the platform 647620Sgblack@eecs.umich.edu ic = platform->intrctrl; 657682Sgblack@eecs.umich.edu 6610341Smitch.hayenga@arm.com for (int x = 0; x < NumDeviceIds; ++x) { 6710341Smitch.hayenga@arm.com intMan[x].cpu = 0; 687682Sgblack@eecs.umich.edu intMan[x].vector = 0; 695172Sgblack@eecs.umich.edu intCtl[x].mask = true; 705172Sgblack@eecs.umich.edu intCtl[x].pend = false; 715172Sgblack@eecs.umich.edu } 7212236Sgabeblack@google.com 735449Sgblack@eecs.umich.edu} 745449Sgblack@eecs.umich.edu 755449Sgblack@eecs.umich.eduTick 765172Sgblack@eecs.umich.eduIob::read(PacketPtr pkt) 774590Sgblack@eecs.umich.edu{ 784590Sgblack@eecs.umich.edu 795163Sgblack@eecs.umich.edu if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) 805163Sgblack@eecs.umich.edu readIob(pkt); 815163Sgblack@eecs.umich.edu else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) 825163Sgblack@eecs.umich.edu readJBus(pkt); 835163Sgblack@eecs.umich.edu else 847620Sgblack@eecs.umich.edu panic("Invalid address reached Iob\n"); 855163Sgblack@eecs.umich.edu 8612236Sgabeblack@google.com pkt->makeAtomicResponse(); 875163Sgblack@eecs.umich.edu return pioDelay; 885163Sgblack@eecs.umich.edu} 895163Sgblack@eecs.umich.edu 905163Sgblack@eecs.umich.eduvoid 9112234Sgabeblack@google.comIob::readIob(PacketPtr pkt) 924519Sgblack@eecs.umich.edu{ 934519Sgblack@eecs.umich.edu Addr accessAddr = pkt->getAddr() - iobManAddr; 945163Sgblack@eecs.umich.edu 955163Sgblack@eecs.umich.edu if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { 965163Sgblack@eecs.umich.edu int index = (accessAddr - IntManAddr) >> 3; 975163Sgblack@eecs.umich.edu uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0; 985163Sgblack@eecs.umich.edu pkt->set(data); 995163Sgblack@eecs.umich.edu return; 1005163Sgblack@eecs.umich.edu } 1015163Sgblack@eecs.umich.edu 1024519Sgblack@eecs.umich.edu if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { 1034519Sgblack@eecs.umich.edu int index = (accessAddr - IntCtlAddr) >> 3; 1044519Sgblack@eecs.umich.edu uint64_t data = intCtl[index].mask ? 1 << 2 : 0 | 1055172Sgblack@eecs.umich.edu intCtl[index].pend ? 1 << 0 : 0; 1065172Sgblack@eecs.umich.edu pkt->set(data); 10712234Sgabeblack@google.com return; 1085172Sgblack@eecs.umich.edu } 1095173Sgblack@eecs.umich.edu 1105172Sgblack@eecs.umich.edu if (accessAddr == JIntVecAddr) { 1115172Sgblack@eecs.umich.edu pkt->set(jIntVec); 1125172Sgblack@eecs.umich.edu return; 1135172Sgblack@eecs.umich.edu } 1144590Sgblack@eecs.umich.edu 11510184SCurtis.Dunham@arm.com panic("Read to unknown IOB offset 0x%x\n", accessAddr); 1165163Sgblack@eecs.umich.edu} 1177620Sgblack@eecs.umich.edu 1187620Sgblack@eecs.umich.eduvoid 1195163Sgblack@eecs.umich.eduIob::readJBus(PacketPtr pkt) 1204519Sgblack@eecs.umich.edu{ 1214519Sgblack@eecs.umich.edu Addr accessAddr = pkt->getAddr() - iobJBusAddr; 1224519Sgblack@eecs.umich.edu int cpuid = pkt->req->contextId(); 1234519Sgblack@eecs.umich.edu int index; 1245163Sgblack@eecs.umich.edu uint64_t data; 12510184SCurtis.Dunham@arm.com 1267620Sgblack@eecs.umich.edu 1275163Sgblack@eecs.umich.edu 1287620Sgblack@eecs.umich.edu 1295163Sgblack@eecs.umich.edu if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) { 1307626Sgblack@eecs.umich.edu index = (accessAddr - JIntData0Addr) >> 3; 1315163Sgblack@eecs.umich.edu pkt->set(jBusData0[index]); 1325163Sgblack@eecs.umich.edu return; 1335163Sgblack@eecs.umich.edu } 1344696Sgblack@eecs.umich.edu 1355163Sgblack@eecs.umich.edu if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) { 1364696Sgblack@eecs.umich.edu index = (accessAddr - JIntData1Addr) >> 3; 1374696Sgblack@eecs.umich.edu pkt->set(jBusData1[index]); 1384696Sgblack@eecs.umich.edu return; 1394696Sgblack@eecs.umich.edu } 1404696Sgblack@eecs.umich.edu 1414696Sgblack@eecs.umich.edu if (accessAddr == JIntDataA0Addr) { 1424696Sgblack@eecs.umich.edu pkt->set(jBusData0[cpuid]); 1434696Sgblack@eecs.umich.edu return; 1444696Sgblack@eecs.umich.edu } 1454696Sgblack@eecs.umich.edu 1464696Sgblack@eecs.umich.edu if (accessAddr == JIntDataA1Addr) { 1474696Sgblack@eecs.umich.edu pkt->set(jBusData1[cpuid]); 1485449Sgblack@eecs.umich.edu return; 1495449Sgblack@eecs.umich.edu } 1505449Sgblack@eecs.umich.edu 1515449Sgblack@eecs.umich.edu if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { 1525449Sgblack@eecs.umich.edu index = (accessAddr - JIntBusyAddr) >> 3; 1535449Sgblack@eecs.umich.edu data = jIntBusy[index].busy ? 1 << 5 : 0 | 1545449Sgblack@eecs.umich.edu jIntBusy[index].source; 1555449Sgblack@eecs.umich.edu pkt->set(data); 1565449Sgblack@eecs.umich.edu return; 1575449Sgblack@eecs.umich.edu } 1584696Sgblack@eecs.umich.edu if (accessAddr == JIntABusyAddr) { 1594696Sgblack@eecs.umich.edu data = jIntBusy[cpuid].busy ? 1 << 5 : 0 | 1604519Sgblack@eecs.umich.edu jIntBusy[cpuid].source; 1614590Sgblack@eecs.umich.edu pkt->set(data); 1625163Sgblack@eecs.umich.edu return; 1635163Sgblack@eecs.umich.edu }; 1644590Sgblack@eecs.umich.edu 1655163Sgblack@eecs.umich.edu panic("Read to unknown JBus offset 0x%x\n", accessAddr); 1665163Sgblack@eecs.umich.edu} 1675163Sgblack@eecs.umich.edu 1685163Sgblack@eecs.umich.eduTick 1695163Sgblack@eecs.umich.eduIob::write(PacketPtr pkt) 1705163Sgblack@eecs.umich.edu{ 1715163Sgblack@eecs.umich.edu if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) 1724590Sgblack@eecs.umich.edu writeIob(pkt); 1737620Sgblack@eecs.umich.edu else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) 1747620Sgblack@eecs.umich.edu writeJBus(pkt); 1755163Sgblack@eecs.umich.edu else 1765163Sgblack@eecs.umich.edu panic("Invalid address reached Iob\n"); 1774590Sgblack@eecs.umich.edu 1785163Sgblack@eecs.umich.edu 1795163Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1804590Sgblack@eecs.umich.edu return pioDelay; 1815163Sgblack@eecs.umich.edu} 1825293Sgblack@eecs.umich.edu 1835163Sgblack@eecs.umich.eduvoid 1849211Snilay@cs.wisc.eduIob::writeIob(PacketPtr pkt) 1859010Snilay@cs.wisc.edu{ 1865163Sgblack@eecs.umich.edu Addr accessAddr = pkt->getAddr() - iobManAddr; 1875163Sgblack@eecs.umich.edu int index; 1885163Sgblack@eecs.umich.edu uint64_t data; 1895293Sgblack@eecs.umich.edu 1905163Sgblack@eecs.umich.edu if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { 1915163Sgblack@eecs.umich.edu index = (accessAddr - IntManAddr) >> 3; 1925163Sgblack@eecs.umich.edu data = pkt->get<uint64_t>(); 1935163Sgblack@eecs.umich.edu intMan[index].cpu = bits(data,12,8); 1945163Sgblack@eecs.umich.edu intMan[index].vector = bits(data,5,0); 1954590Sgblack@eecs.umich.edu DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index, 1965172Sgblack@eecs.umich.edu intMan[index].cpu, intMan[index].vector); 1975172Sgblack@eecs.umich.edu return; 1986047Sgblack@eecs.umich.edu } 1995172Sgblack@eecs.umich.edu 2005172Sgblack@eecs.umich.edu if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { 2015172Sgblack@eecs.umich.edu index = (accessAddr - IntCtlAddr) >> 3; 2027620Sgblack@eecs.umich.edu data = pkt->get<uint64_t>(); 2037620Sgblack@eecs.umich.edu intCtl[index].mask = bits(data,2,2); 2045172Sgblack@eecs.umich.edu if (bits(data,1,1)) 2055172Sgblack@eecs.umich.edu intCtl[index].pend = false; 2065172Sgblack@eecs.umich.edu DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index, 2074519Sgblack@eecs.umich.edu intCtl[index].pend, bits(data,2,2)); 2088610Snilay@cs.wisc.edu return; 2098610Snilay@cs.wisc.edu } 2108610Snilay@cs.wisc.edu 2118610Snilay@cs.wisc.edu if (accessAddr == JIntVecAddr) { 2128610Snilay@cs.wisc.edu jIntVec = bits(pkt->get<uint64_t>(), 5,0); 2138610Snilay@cs.wisc.edu DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec); 2148610Snilay@cs.wisc.edu return; 2158610Snilay@cs.wisc.edu } 2168610Snilay@cs.wisc.edu 21712236Sgabeblack@google.com if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) { 2188610Snilay@cs.wisc.edu Type type; 2198610Snilay@cs.wisc.edu int cpu_id; 2208610Snilay@cs.wisc.edu int vector; 2218610Snilay@cs.wisc.edu index = (accessAddr - IntManAddr) >> 3; 22210184SCurtis.Dunham@arm.com data = pkt->get<uint64_t>(); 2238610Snilay@cs.wisc.edu type = (Type)bits(data,17,16); 2248610Snilay@cs.wisc.edu cpu_id = bits(data, 12,8); 2258610Snilay@cs.wisc.edu vector = bits(data,5,0); 2268610Snilay@cs.wisc.edu generateIpi(type,cpu_id, vector); 2278610Snilay@cs.wisc.edu return; 2288610Snilay@cs.wisc.edu } 2298610Snilay@cs.wisc.edu 2308610Snilay@cs.wisc.edu panic("Write to unknown IOB offset 0x%x\n", accessAddr); 2318610Snilay@cs.wisc.edu} 2328610Snilay@cs.wisc.edu 2338610Snilay@cs.wisc.eduvoid 2348610Snilay@cs.wisc.eduIob::writeJBus(PacketPtr pkt) 2358610Snilay@cs.wisc.edu{ 2368610Snilay@cs.wisc.edu Addr accessAddr = pkt->getAddr() - iobJBusAddr; 2378610Snilay@cs.wisc.edu int cpuid = pkt->req->contextId(); 2388610Snilay@cs.wisc.edu int index; 2398610Snilay@cs.wisc.edu uint64_t data; 2408610Snilay@cs.wisc.edu 2418610Snilay@cs.wisc.edu if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { 2428610Snilay@cs.wisc.edu index = (accessAddr - JIntBusyAddr) >> 3; 2438610Snilay@cs.wisc.edu data = pkt->get<uint64_t>(); 2448610Snilay@cs.wisc.edu jIntBusy[index].busy = bits(data,5,5); 2458610Snilay@cs.wisc.edu DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index, 2468610Snilay@cs.wisc.edu jIntBusy[index].busy); 2478610Snilay@cs.wisc.edu return; 2488610Snilay@cs.wisc.edu } 2498610Snilay@cs.wisc.edu if (accessAddr == JIntABusyAddr) { 2508610Snilay@cs.wisc.edu data = pkt->get<uint64_t>(); 2518610Snilay@cs.wisc.edu jIntBusy[cpuid].busy = bits(data,5,5); 2528610Snilay@cs.wisc.edu DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid, 2538610Snilay@cs.wisc.edu jIntBusy[cpuid].busy); 2548610Snilay@cs.wisc.edu return; 2558610Snilay@cs.wisc.edu }; 2568610Snilay@cs.wisc.edu 2578610Snilay@cs.wisc.edu panic("Write to unknown JBus offset 0x%x\n", accessAddr); 2588610Snilay@cs.wisc.edu} 2598610Snilay@cs.wisc.edu 260void 261Iob::receiveDeviceInterrupt(DeviceId devid) 262{ 263 assert(devid < NumDeviceIds); 264 if (intCtl[devid].mask) 265 return; 266 intCtl[devid].mask = true; 267 intCtl[devid].pend = true; 268 DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n", 269 devid, intMan[devid].cpu, intMan[devid].vector); 270 ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector); 271} 272 273 274void 275Iob::generateIpi(Type type, int cpu_id, int vector) 276{ 277 SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset(); 278 if (cpu_id >= sys->numContexts()) 279 return; 280 281 switch (type) { 282 case 0: // interrupt 283 DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n", 284 cpu_id, vector); 285 ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); 286 break; 287 case 1: // reset 288 warn("Sending reset to CPU: %d\n", cpu_id); 289 if (vector != por->trapType()) 290 panic("Don't know how to set non-POR reset to cpu\n"); 291 por->invoke(sys->threadContexts[cpu_id]); 292 sys->threadContexts[cpu_id]->activate(); 293 break; 294 case 2: // idle -- this means stop executing and don't wake on interrupts 295 DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id); 296 sys->threadContexts[cpu_id]->halt(); 297 break; 298 case 3: // resume 299 DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id); 300 sys->threadContexts[cpu_id]->activate(); 301 break; 302 default: 303 panic("Invalid type to generate ipi\n"); 304 } 305} 306 307bool 308Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1) 309{ 310 // If we are already dealing with an interrupt for that cpu we can't deal 311 // with another one right now... come back later 312 if (jIntBusy[cpu_id].busy) 313 return false; 314 315 DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n", 316 source, cpu_id, jIntVec); 317 318 jIntBusy[cpu_id].busy = true; 319 jIntBusy[cpu_id].source = source; 320 jBusData0[cpu_id] = d0; 321 jBusData1[cpu_id] = d1; 322 323 ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec); 324 return true; 325} 326 327void 328Iob::addressRanges(AddrRangeList &range_list) 329{ 330 range_list.clear(); 331 range_list.push_back(RangeSize(iobManAddr, iobManSize)); 332 range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize)); 333} 334 335 336void 337Iob::serialize(std::ostream &os) 338{ 339 340 SERIALIZE_SCALAR(jIntVec); 341 SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); 342 SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); 343 for (int x = 0; x < NumDeviceIds; x++) { 344 nameOut(os, csprintf("%s.Int%d", name(), x)); 345 paramOut(os, "cpu", intMan[x].cpu); 346 paramOut(os, "vector", intMan[x].vector); 347 paramOut(os, "mask", intCtl[x].mask); 348 paramOut(os, "pend", intCtl[x].pend); 349 }; 350 for (int x = 0; x < MaxNiagaraProcs; x++) { 351 nameOut(os, csprintf("%s.jIntBusy%d", name(), x)); 352 paramOut(os, "busy", jIntBusy[x].busy); 353 paramOut(os, "source", jIntBusy[x].source); 354 }; 355} 356 357void 358Iob::unserialize(Checkpoint *cp, const std::string §ion) 359{ 360 UNSERIALIZE_SCALAR(jIntVec); 361 UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); 362 UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); 363 for (int x = 0; x < NumDeviceIds; x++) { 364 paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu); 365 paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector); 366 paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask); 367 paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend); 368 }; 369 for (int x = 0; x < MaxNiagaraProcs; x++) { 370 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy); 371 paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source); 372 }; 373} 374 375Iob * 376IobParams::create() 377{ 378 return new Iob(this); 379} 380