/* hp2100_mc.c: HP 12566B Microcircuit Interface simulator

   Copyright (c) 2018, J. David Bryan

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

   Except as contained in this notice, the name of the author shall not be
   used in advertising or otherwise to promote the sale, use or other dealings
   in this Software without prior written authorization from the author.

   MC           12566B Microcircuit Interface

   09-Jul-18    JDB     Created

   References:
     - 12566B[-001/2/3] Microcircuit Interface Kits Operating and Service Manual
         (12566-90015,  April 1976)


   The 12566B Microcircuit Interface provides a general-purpose 16-bit
   bidirectional data path between the CPU and an I/O device that supports both
   programmed I/O and DMA transfers.  A simple, two-wire handshake provides the
   control signals to coordinate data transfers.  All device signals are
   TTL-compatible, and transfer rates up to one-half of the DMA bandwidth are
   possible.

   The 12566B supplies 16 data bits and asserts a Device Command signal to the
   device to indicate the start of a transfer.  The device returns 16 data bits
   and asserts a Device Flag signal to indicate completion of the transfer.
   Assertion of Device Flag causes the interface to set its Flag flip-flop and
   assert an interupt request to the CPU and a service request to the DMA
   controller.

   This simulation primarily provides a target interface for several diagnostic
   programs.  In the DIAGNOSTIC mode, a loopback connector is installed in place
   of the usual device cable, and the interface provides a general data source
   and sink, as well as a source of interrupts and a break in the I/O priority
   chain.  In the DEVICE mode, the simulation provides a model to illustrate the
   required interface to the CPU's I/O backplane, as no peripheral device is
   simulated.

   Befitting its general purpose, the hardware interface has nine jumpers,
   labelled W1-W9, that may be positioned to configure the electrical polarity
   and behavior of the Device Command and Device Flag signals.  The lettered
   jumper positions and their effects are:

     Jumper  Pos  Action
     ------  ---  ------------------------------------------------------------
       W1     A   Device Command signal is ground true asserted with STC
              B   Device Command signal is positive true asserted with STC
              C   Device Command signal is ground true asserted for T6 and T2

       W2     A   Device Command flip-flop clears on positive edge of Device Flag
              B   Device Command flip-flop clears on negative edge of Device Flag
              C   Device Command flip-flop clears on ENF (T2)

       W3     A   Device Flag signal sets Flag Buffer and strobes data on positive edge
              B   Device Flag signal sets Flag Buffer and strobes data on negative edge

       W4     A   Output Data Register is gated by the data flip-flop
              B   Output Data Register is continuously available

       W5    IN   Input Data Register bits 0-3 are latched by Device Flag
             OUT  Input Data Register bits 0-3 are transparent

       W6    IN   Input Data Register bits 4-7 are latched by Device Flag
             OUT  Input Data Register bits 4-7 are transparent

       W7    IN   Input Data Register bits 8-11 are latched by Device Flag
             OUT  Input Data Register bits 8-11 are transparent

       W8    IN   Input Data Register bits 12-15 are latched by Device Flag
             OUT  Input Data Register bits 12-15 are transparent

       W9     A   Device Command flip-flop cleared by CLC, CRS, and Device Flag
              B   Device Command flip-flop cleared by CRS and Device Flag

   The electrical characteristics of the device being interfaced dictates the
   jumper settings used.  The jumper settings required for the standard HP
   peripherals that use the microcircuit card are:

     W1  W2  W3  W4  W5  W6  W7  W8  W9  Device
     --- --- --- --- --- --- --- --- --- ----------------------------------------
      A   B   A   B  OUT IN  IN  IN   A  12566B-004 Line Printer Interface (9866)

      B   A   B   B  OUT IN  IN  OUT  A  12653A Line Printer Interface (2767)

      A   B   B   B  IN  IN  IN  OUT  B  12732A Flexible Disc Subsystem (Control)
      A   A   B   B  IN  IN  IN  IN   B  12732A Flexible Disc Subsystem (Data)

      A   B   B   B  IN  IN  IN  IN   A  12875A Processor Interconnect Kit

   For diagnostic use, the required jumper settings are:

     W1  W2  W3  W4  W5  W6  W7  W8  W9   DSN    Diagnostic
     --- --- --- --- --- --- --- --- --- ------  ---------------------------------
      C   B   B   B  IN  IN  IN  IN   A  143300  General Purpose Register

      C   B   B   B  IN  IN  IN  IN   A  141203  I/O Instruction Group

      C   B   B   B  IN  IN  IN  IN   A  102103  Memory Expansion Unit

      C   B   B   B  IN  IN  IN  IN   A  101220  DMA/DCPC for 2100/1000

      B   A   A   B  IN  IN  IN  IN   A    --    DMA for 2100 (HP 24195)

      B   A   A   B  IN  IN  IN  IN   A  101105  DMA for 2114/2115/2116 (HP 24322)
      B   C   A  A/B IN  IN  IN  IN   A  101105  DMA for 2114/2115/2116 (HP 24322)

      B   C   B   B  IN  IN  IN  IN   A    --    DMA for 2115/2116 (HP 24185)

      (not relevant; interrupt only)     101112  Extended Instruction Group

      (not relevant; interrupt only)     101213  M/E-Series Fast FORTRAN Package 1

      (not relevant; interrupt only)     101115  M/E-Series Fast FORTRAN Package 2

      (not relevant; interrupt only)     101121  F-Series FPP-SIS-FFP

      (not relevant; interrupt only)     102305  Memory Protect/Parity Error

   The diagnostics that specify jumper settings above test data writing and
   reading and so require the installation of the HP 1251-0332 diagnostic test
   (loopback) connector in place of the normal device cable connector.  This
   test connector connects each data output bit with its corresponding data
   input bit and connects the Device Command output signal to the Device Flag
   input signal.

   The diagnostics that test the HP 12607B DMA card for the 2115 and 2116 CPUs
   require an unusual jumper configuration.  The card provides hardware byte
   packing and unpacking during DMA transfers.  The diagnostics test this
   hardware by strapping the microcircuit interface so that the Device Flag
   signal sets the Flag flip-flop for a CPU cycle but not for a DMA cycle.  This
   allows the diagnostic to advance the DMA byte transfer hardware sequence
   cycle-by-cycle under program control.

   In hardware, this works only because the 2115/2116 DMA cycle asserts the STC
   and CLF signals for two staggered T-periods, with CLF remaining asserted for
   one T-period after STC denies.  The 2115/2116 CPU cycle, as well as the CPU
   and DMA cycles of all other 21xx/1000 machines, assert STC and CLF
   coincidently for one T-period.

   Under simulation, this action cannot be derived by simulating the jumper
   behaviors directly, because the I/O backplane signal timing relationships are
   not simulated.  Instead, Device Flag assertion is omitted for 2115/2116 DMA
   cycles when DIAGNOSTIC mode is selected.

   This module does not simulate the individual jumper settings, for two
   reasons.  First, with no peripheral device connected to the interface, the
   jumper settings are irrelevant.  Should this module be used as the basis for
   a specific device interface, that device would dictate the jumper settings
   required.  As the settings would be fixed, having a user-configurable set of
   jumpers would serve no purpose.  Second, while user-configurable jumpers
   would be useful to configure the card for diagnostics, the fact that the I/O
   backplane signal timing is not simulated means that the interface behavior
   cannot be derived from the jumper settings alone.  Therefore, entering the
   DIAGNOSTIC mode simulates the proper jumper settings for the various
   diagnostics listed above.


   Implementation notes:

     1. Two identical interfaces are provided: MC1 and MC2.  Both interfaces are
        used by the 12936A Privileged Interrupt Fence diagnostic.  They also
        serve as an illustration of how to model multiple interfaces in the HP
        2100 simulator.

     2. The microcircuit interfaces are disabled by default, as they are only
        used during diagnostic execution.
*/



#include "hp2100_defs.h"
#include "hp2100_io.h"



/* Program limits */

#define CARD_COUNT          2                   /* count of cards supported */


/* Device property constant declarations */

#define LOOPBACK_DELAY      (int32) uS (1)      /* diagnostic loopback flag assertion delay */


/* Unit flags */

#define UNIT_V_DIAG         (UNIT_V_UF + 0)     /* diagnostic mode is selected */

#define UNIT_DIAG           (1 << UNIT_V_DIAG)


/* Unit references */

typedef enum {
    mc1,                                        /* first microcircuit card index */
    mc2                                         /* second microcircuit card index */
    } CARD_INDEX;


/* Interface state */

typedef struct {
    HP_WORD      output_data;                   /* output data register */
    HP_WORD      input_data;                    /* input data register */
    FLIP_FLOP    command;                       /* command flip-flop */
    FLIP_FLOP    control;                       /* control flip-flop */
    FLIP_FLOP    flag;                          /* flag flip-flop */
    FLIP_FLOP    flag_buffer;                   /* flag buffer flip-flop */
    } CARD_STATE;

static CARD_STATE mc [CARD_COUNT];              /* per-card state */


/* Interface local SCP support routines */

static INTERFACE mc_interface;


/* Interface local SCP support routines */

static t_stat mc_service (UNIT *uptr);
static t_stat mc_reset   (DEVICE *dptr);


/* Interface SCP data structures */


/* Device information block */

static DIB mc_dib [CARD_COUNT] = {
    { &mc_interface,                            /* the device's I/O interface function pointer */
      MC1,                                      /* the device's select code (02-77) */
      0,                                        /* the card index */
      "12566B Microcircuit Interface",          /* the card description */
      NULL },                                   /* the ROM description */

    { &mc_interface,                            /* the device's I/O interface function pointer */
      MC2,                                      /* the device's select code (02-77) */
      1,                                        /* the card index */
      "12566B Microcircuit Interface",          /* the card description */
      NULL }                                    /* the ROM description */
    };


/* Unit list */

#define UNIT_FLAGS          (0)

static UNIT mc_unit [CARD_COUNT] = {
/*           Event Routine  Unit Flags  Capacity  Delay */
/*           -------------  ----------  --------  ----- */
    { UDATA (&mc_service,   UNIT_FLAGS,    0),      0   },
    { UDATA (&mc_service,   UNIT_FLAGS,    0),      0   }
    };


/* Register lists.


   Implementation notes:

    1. The two REG arrays would be more conveniently declared as:

         static REG mc_reg [CARD_COUNT] [] = { { ... }, { ... } };

       Unfortunately, this is illegal in C ("a multidimensional array must have
       bounds for all dimensions except the first").
*/

static REG mc1_reg [] = {
/*    Macro   Name    Location                    Width     Offset        Flags       */
/*    ------  ------  ------------------------  ----------  ------  ----------------- */
    { ORDATA (IN,     mc [mc1].input_data,         16)                                },
    { ORDATA (OUT,    mc [mc1].output_data,        16)                                },
    { FLDATA (CTL,    mc [mc1].control,                       0)                      },
    { FLDATA (FLG,    mc [mc1].flag,                          0)                      },
    { FLDATA (FBF,    mc [mc1].flag_buffer,                   0)                      },
    { FLDATA (CMD,    mc [mc1].command,                       0)                      },

      DIB_REGS (mc_dib [mc1]),

    { NULL }
    };

static REG mc2_reg [] = {
/*    Macro   Name    Location                    Width     Offset        Flags       */
/*    ------  ------  ------------------------  ----------  ------  ----------------- */
    { ORDATA (IN,     mc [mc2].input_data,         16)                                },
    { ORDATA (OUT,    mc [mc2].output_data,        16)                                },
    { FLDATA (CTL,    mc [mc2].control,                       0)                      },
    { FLDATA (FLG,    mc [mc2].flag,                          0)                      },
    { FLDATA (FBF,    mc [mc2].flag_buffer,                   0)                      },
    { FLDATA (CMD,    mc [mc2].command,                       0)                      },

      DIB_REGS (mc_dib [mc2]),

    { NULL }
    };


/* Modifier lists */

static MTAB mc1_mod [] = {
/*    Mask Value  Match Value  Print String       Match String  Validation   Display  Descriptor */
/*    ----------  -----------  -----------------  ------------  -----------  -------  ---------- */
    { UNIT_DIAG,  UNIT_DIAG,   "diagnostic mode", "DIAGNOSTIC", NULL,        NULL,    NULL       },
    { UNIT_DIAG,  0,           "device mode",     "DEVICE",     NULL,        NULL,    NULL       },

/*    Entry Flags  Value  Print String  Match String  Validation    Display        Descriptor             */
/*    -----------  -----  ------------  ------------  ------------  -------------  ---------------------- */
    { MTAB_XDV,     1u,   "SC",         "SC",         &hp_set_dib,  &hp_show_dib,  (void *) &mc_dib [mc1] },
    { 0 }
    };

static MTAB mc2_mod [] = {
/*    Mask Value  Match Value  Print String       Match String  Validation   Display  Descriptor */
/*    ----------  -----------  -----------------  ------------  -----------  -------  ---------- */
    { UNIT_DIAG,  UNIT_DIAG,   "diagnostic mode", "DIAGNOSTIC", NULL,        NULL,    NULL       },
    { UNIT_DIAG,  0,           "device mode",     "DEVICE",     NULL,        NULL,    NULL       },

/*    Entry Flags  Value  Print String  Match String  Validation    Display        Descriptor             */
/*    -----------  -----  ------------  ------------  ------------  -------------  ---------------------- */
    { MTAB_XDV,     1u,   "SC",         "SC",         &hp_set_dib,  &hp_show_dib,  (void *) &mc_dib [mc2] },
    { 0 }
    };


/* Debugging trace list */

static DEBTAB mc_deb [] = {
    { "XFER",  TRACE_XFER  },                   /* trace data transmissions and receptions */
    { "IOBUS", TRACE_IOBUS },                   /* trace I/O bus signals and data words received and returned */
    { NULL,    0           }
    };


/* Device descriptors */

DEVICE mc1_dev = {
    "MC1",                                      /* device name */
    &mc_unit [mc1],                             /* unit array */
    mc1_reg,                                    /* register array */
    mc1_mod,                                    /* modifier array */
    1,                                          /* number of units */
    10,                                         /* address radix */
    31,                                         /* address width */
    1,                                          /* address increment */
    8,                                          /* data radix */
    16,                                         /* data width */
    NULL,                                       /* examine routine */
    NULL,                                       /* deposit routine */
    &mc_reset,                                  /* reset routine */
    NULL,                                       /* boot routine */
    NULL,                                       /* attach routine */
    NULL,                                       /* detach routine */
    &mc_dib [mc1],                              /* device information block pointer */
    DEV_DISABLE | DEV_DIS | DEV_DEBUG,          /* device flags */
    0,                                          /* debug control flags */
    mc_deb,                                     /* debug flag name array */
    NULL,                                       /* memory size change routine */
    NULL                                        /* logical device name */
    };

DEVICE mc2_dev = {
    "MC2",                                      /* device name */
    &mc_unit [mc2],                             /* unit array */
    mc2_reg,                                    /* register array */
    mc2_mod,                                    /* modifier array */
    1,                                          /* number of units */
    10,                                         /* address radix */
    31,                                         /* address width */
    1,                                          /* address increment */
    8,                                          /* data radix */
    16,                                         /* data width */
    NULL,                                       /* examine routine */
    NULL,                                       /* deposit routine */
    &mc_reset,                                  /* reset routine */
    NULL,                                       /* boot routine */
    NULL,                                       /* attach routine */
    NULL,                                       /* detach routine */
    &mc_dib [mc2],                              /* device information block pointer */
    DEV_DISABLE | DEV_DIS | DEV_DEBUG,          /* device flags */
    0,                                          /* debug control flags */
    mc_deb,                                     /* debug flag name array */
    NULL,                                       /* memory size change routine */
    NULL                                        /* logical device name */
    };

static DEVICE *dptrs [CARD_COUNT] = {           /* device pointer array, indexed by CARD_INDEX */
    &mc1_dev,
    &mc2_dev
    };



/* Microcircuit interface.

   The microcircuit interface is installed on the I/O bus and receives I/O
   commands from the CPU and DMA/DCPC channels.  In simulation, the asserted
   signals on the bus are represented as bits in the inbound_signals set.  Each
   signal is processed sequentially in ascending numerical order.  The outbound
   signals and optional data value are returned after inbound signal processing
   is complete.

   In DIAGNOSTIC mode, the interface behaves as though a loopback connector
   is installed.  In addition, for all accesses other than DMA cycles for a 2115 or
   2116 CPU, it behaves as though jumpers W1-W3 are installed in locations
   C-B-B, respectively.  In this case, the Flag flip-flop sets one I/O cycle
   after STC signal assertion.  For 2115/2116 DMA cycles, it behaves as though
   the jumpers are installed in locations B-C-A, which suppresses setting the
   Flag flip-flop.

   Because there is no attached peripheral, the Flag flip-flop never sets in
   DEVICE mode in response to a programmed STC instruction.


   Implementation notes:

    1. The B-C-B jumper setting used by the HP 24185 DMA diagnostic causes the
       Flag flip-flop to set two I/O cycles after STC assertion.  However, the
       diagnostic executes an STC,C instruction at that point that clears the
       Flag flip-flop explictly.  This has the same effect as if the Flag had
       never set and so is functionally identical to the B-C-A jumper setting.

    2. The 12195 DMA diagnostic depends on the input data register being clocked
       by an STC instruction.  W1 = B and W3 = A asserts Device Command positive
       true and strobes the input register on the positive edge of Device Flag.
       This is simulated by copying the output data register to the input data
       register in the STC handler if DIAGNOSTIC mode is enabled.
*/

static SIGNALS_VALUE mc_interface (const DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
{
const CARD_INDEX card = (CARD_INDEX) dibptr->card_index;    /* the card selector */
UNIT * const     uptr = &(mc_unit [card]);                  /* the associated unit pointer */
INBOUND_SIGNAL   signal;
INBOUND_SET      working_set = inbound_signals;
SIGNALS_VALUE    outbound    = { ioNONE, 0 };
t_bool           irq_enabled = FALSE;

while (working_set) {                                   /* while signals remain */
    signal = IONEXTSIG (working_set);                   /*   isolate the next signal */

    switch (signal) {                                   /* dispatch the I/O signal */

        case ioCLF:                                     /* Clear Flag flip-flop */
            mc [card].flag_buffer = CLEAR;              /* clear the flag buffer */
            mc [card].flag        = CLEAR;              /*   and flag flip-flops */
            break;


        case ioSTF:                                     /* Set Flag flip-flop */
            mc [card].flag_buffer = SET;                /* set the flag buffer flip-flop */
            break;


        case ioENF:                                     /* Enable Flag */
            if (mc [card].flag_buffer == SET)           /* if the flag buffer flip-flop is set */
                mc [card].flag = SET;                   /*   then set the flag flip-flop */
            break;


        case ioSFC:                                     /* Skip if Flag is Clear */
            if (mc [card].flag == CLEAR)                /* if the flag flip-flop is clear */
                outbound.signals |= ioSKF;              /*   then assert the Skip on Flag signal */
            break;


        case ioSFS:                                     /* Skip if Flag is Set */
            if (mc [card].flag == SET)                  /* if the flag flip-flop is set */
                outbound.signals |= ioSKF;              /*   then assert the Skip on Flag signal */
            break;


        case ioIOI:                                     /* I/O data input */
            outbound.value = mc [card].input_data;      /* set the outbound data value from the input buffer */
            break;


        case ioIOO:                                     /* I/O data output */
            mc [card].output_data = inbound_value;      /* store the inbound data value in the output buffer */
            break;


        case ioPOPIO:                                   /* Power-On Preset to I/O */
            mc [card].flag_buffer = SET;                /* set the flag buffer flip-flop */
            mc [card].output_data = 0;                  /*   and clear the output register */
            break;


        case ioCRS:                                     /* Control Reset */
            mc [card].control = CLEAR;                  /* clear the control flip-flop */
            mc [card].command = CLEAR;                  /*   and the command flip-flop */

            sim_cancel (uptr);                          /* cancel any operation in progress */
            break;


        case ioCLC:                                     /* Clear Control flip-flop */
            mc [card].control = CLEAR;                  /* clear the control flip-flop */
            mc [card].command = CLEAR;                  /*   and the command flip-flop */

            if (sim_activate_time (uptr) > LOOPBACK_DELAY)  /* if Device Flag assertion is still in the future */
                sim_cancel (uptr);                          /*   then cancel it */
            break;


        case ioSTC:                                     /* Set Control flip-flop */
            mc [card].control = SET;                    /* set the control flip-flop */
            mc [card].command = SET;                    /*   and the command flip-flop */

            if (uptr->flags & UNIT_DIAG                             /* if the card is in diagnostic mode */
              && (cpu_configuration & ~(CPU_2116 | CPU_2115)        /*   and this is not a 2116 or 2115 CPU */
              || (inbound_signals & (ioIOI | ioIOO)) == ioNONE)) {  /*     or not a DMA cycle */
                mc [card].input_data = mc [card].output_data;       /*       then loop the data back */

                tpprintf (dptrs [card], TRACE_XFER, "Output data word %06o looped back to input\n",
                          mc [card].output_data);

                sim_activate_abs (uptr, LOOPBACK_DELAY);            /* schedule Device Flag assertion */
                }
            break;


        case ioSIR:                                     /* Set Interrupt Request */
            if (mc [card].control & mc [card].flag)     /* if the control and flag flip-flops are set */
                outbound.signals |= cnVALID;            /*   then deny PRL */
            else                                        /* otherwise */
                outbound.signals |= cnPRL | cnVALID;    /*   conditionally assert PRL */

            if (mc [card].control & mc [card].flag      /* if the control and flag */
              & mc [card].flag_buffer)                  /*   and flag buffer flip-flops are set */
                outbound.signals |= cnIRQ | cnVALID;    /*     then conditionally assert IRQ */

            if (mc [card].flag == SET)                  /* if the flag flip-flop is set */
                outbound.signals |= ioSRQ;              /*   then assert SRQ */
            break;


        case ioIAK:                                     /* Interrupt Acknowledge */
            mc [card].flag_buffer = CLEAR;              /* clear the flag buffer flip-flop */
            break;


        case ioIEN:                                     /* Interrupt Enable */
            irq_enabled = TRUE;                         /* permit IRQ to be asserted */
            break;


        case ioPRH:                                         /* Priority High */
            if (irq_enabled && outbound.signals & cnIRQ)    /* if IRQ is enabled and conditionally asserted */
                outbound.signals |= ioIRQ | ioFLG;          /*   then assert IRQ and FLG */

            if (!irq_enabled || outbound.signals & cnPRL)   /* if IRQ is disabled or PRL is conditionally asserted */
                outbound.signals |= ioPRL;                  /*   then assert it unconditionally */
            break;


        case ioEDT:                                     /* not used by this interface */
        case ioPON:                                     /* not used by this interface */
            break;
        }

    IOCLEARSIG (working_set, signal);                   /* remove the current signal from the set */
    }                                                   /*   and continue until all signals are processed */

return outbound;                                        /* return the outbound signals and value */
}


/* Unit service */

static t_stat mc_service (UNIT *uptr)
{
const CARD_INDEX card = (CARD_INDEX) (uptr - mc_unit);  /* the card selector */

if (uptr->flags & UNIT_DIAG) {                          /* if the card is in diagnostic mode */
    mc [card].command     = CLEAR;                      /*   then clear the command flip-flop */
    mc [card].flag_buffer = SET;                        /*     and set the flag buffer */
    io_assert (dptrs [card], ioa_ENF);                  /*       and flag flip-flops */
    }

return SCPE_OK;
}


/* Reset routine */

static t_stat mc_reset (DEVICE *dptr)
{
UNIT * const uptr = dptr->units;                        /* a pointer to the device's unit */

if (sim_switches & SWMASK ('P')) {                      /* if this is the power-on reset */
    }                                                   /*   then perform any power-up processing */

io_assert (dptr, ioa_POPIO);                            /* PRESET the device */

sim_cancel (uptr);                                      /* cancel any I/O in progress */

return SCPE_OK;
}
