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 &section)
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