root/src/dps8/dps8_urp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. urpShowUnits
  2. urpSetUnits
  3. urpShowDeviceName
  4. urpSetDeviceName
  5. urpReset
  6. urp_init
  7. urpCmd
  8. urp_iom_cmd

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 0aeda9d7-f62f-11ec-a611-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2016 Charles Anthony
  11  * Copyright (c) 2021-2024 The DPS8M Development Team
  12  *
  13  * This software is made available under the terms of the ICU License.
  14  * See the LICENSE.md file at the top-level directory of this distribution.
  15  *
  16  * ---------------------------------------------------------------------------
  17  */
  18 
  19 #include <stdio.h>
  20 #include <ctype.h>
  21 #include <unistd.h>
  22 
  23 #include "dps8.h"
  24 #include "dps8_iom.h"
  25 #include "dps8_urp.h"
  26 #include "dps8_sys.h"
  27 #include "dps8_cable.h"
  28 #include "dps8_cpu.h"
  29 #include "dps8_faults.h"
  30 #include "dps8_scu.h"
  31 #include "dps8_utils.h"
  32 
  33 #define DBG_CTR 1
  34 
  35 //-- // XXX We use this where we assume there is only one unit
  36 //-- #define ASSUME0 0
  37 //--
  38 
  39 #define N_PRU_UNITS 1 // default
  40 
  41 static struct urpState
  42   {
  43     enum urpMode
  44       {
  45         urpNoMode, urpSetDiag, urpInitRdData
  46       } ioMode;
  47     char deviceName [MAX_DEV_NAME_LEN];
  48   } urpState [N_URP_UNITS_MAX];
  49 
  50 #define UNIT_FLAGS ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | \
  51                      UNIT_IDLE )
  52 UNIT urp_unit [N_URP_UNITS_MAX] = {
  53 #if defined(NO_C_ELLIPSIS)
  54   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  55   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  56   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  57   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  58   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  59   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  60   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  61   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  62   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  63   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  64   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  65   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  66   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  67   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  68   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
  69   { UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
  70 #else
  71   [0 ... N_URP_UNITS_MAX-1] = {
  72     UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
  73   }
  74 #endif /* if defined(NO_C_ELLIPSIS) */
  75 };
  76 
  77 #define URPUNIT_NUM(uptr) ((uptr) - urp_unit)
  78 
  79 static DEBTAB urp_dt [] =
  80   {
  81     { "NOTIFY", DBG_NOTIFY, NULL },
  82     {   "INFO",   DBG_INFO, NULL },
  83     {    "ERR",    DBG_ERR, NULL },
  84     {   "WARN",   DBG_WARN, NULL },
  85     {  "DEBUG",  DBG_DEBUG, NULL },
  86     {  "TRACE",  DBG_TRACE, NULL },
  87     {    "ALL",    DBG_ALL, NULL }, // Don't move as it messes up DBG message
  88     {     NULL,          0, NULL }
  89   };
  90 
  91 static t_stat urpShowUnits (UNUSED FILE * st, UNUSED UNIT * uptr, UNUSED int val, UNUSED const void * desc)
     /* [previous][next][first][last][top][bottom][index][help] */
  92   {
  93     sim_printf("Number of URP units in system is %d\n", urp_dev.numunits);
  94     return SCPE_OK;
  95   }
  96 
  97 static t_stat urpSetUnits (UNUSED UNIT * uptr, UNUSED int32 value, const char * cptr, UNUSED void * desc)
     /* [previous][next][first][last][top][bottom][index][help] */
  98   {
  99     if (! cptr)
 100       return SCPE_ARG;
 101     int n = atoi (cptr);
 102     if (n < 1 || n > N_URP_UNITS_MAX)
 103       return SCPE_ARG;
 104     urp_dev.numunits = (uint32) n;
 105     return SCPE_OK;
 106   }
 107 
 108 static t_stat urpShowDeviceName (UNUSED FILE * st, UNIT * uptr, UNUSED int val, UNUSED const void * desc)
     /* [previous][next][first][last][top][bottom][index][help] */
 109   {
 110     int n = (int) URPUNIT_NUM (uptr);
 111     if (n < 0 || n >= N_URP_UNITS_MAX)
 112       return SCPE_ARG;
 113     sim_printf ("name     : %s", urpState[n].deviceName);
 114     return SCPE_OK;
 115   }
 116 
 117 static t_stat urpSetDeviceName (UNUSED UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr, UNUSED void * desc)
     /* [previous][next][first][last][top][bottom][index][help] */
 118   {
 119     int n = (int) URPUNIT_NUM (uptr);
 120     if (n < 0 || n >= N_URP_UNITS_MAX)
 121       return SCPE_ARG;
 122     if (cptr)
 123       {
 124         strncpy (urpState[n].deviceName, cptr, MAX_DEV_NAME_LEN - 1);
 125         urpState[n].deviceName[MAX_DEV_NAME_LEN - 1] = 0;
 126       }
 127     else
 128       urpState[n].deviceName [0] = 0;
 129     return SCPE_OK;
 130   }
 131 
 132 #define UNIT_WATCH UNIT_V_UF
 133 
 134 static MTAB urp_mod [] =
 135   {
 136 #if !defined(SPEED)
 137     { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
 138     { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
 139 #endif /* if !defined(SPEED) */
 140     {
 141       MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR, /* Mask               */
 142       0,                                          /* Match              */
 143       "NUNITS",                                   /* Print string       */
 144       "NUNITS",                                   /* Match string       */
 145       urpSetUnits,                                /* Validation routine */
 146       urpShowUnits,                               /* Display routine    */
 147       "Number of URP units in the system",        /* Value descriptor   */
 148       NULL                                        /* Help               */
 149     },
 150     {
 151       MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,  /* Mask               */
 152       0,                                          /* Match              */
 153       "NAME",                                     /* Print string       */
 154       "NAME",                                     /* Match string       */
 155       urpSetDeviceName,                           /* Validation routine */
 156       urpShowDeviceName,                          /* Display routine    */
 157       "Set the device name",                      /* Value descriptor   */
 158       NULL                                        /* Help               */
 159     },
 160 
 161     { 0, 0, NULL, NULL, 0, 0, NULL, NULL }
 162   };
 163 
 164 static t_stat urpReset (UNUSED DEVICE * dptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 165   {
 166     return SCPE_OK;
 167   }
 168 
 169 DEVICE urp_dev = {
 170     "URP",        /* Name                */
 171     urp_unit,     /* Unit                */
 172     NULL,         /* Registers           */
 173     urp_mod,      /* Modifiers           */
 174     N_PRU_UNITS,  /* Number of units     */
 175     10,           /* Address radix       */
 176     24,           /* Address width       */
 177     1,            /* Address increment   */
 178     8,            /* Data radix          */
 179     36,           /* Data width          */
 180     NULL,         /* Examine             */
 181     NULL,         /* Deposit             */
 182     urpReset,     /* Reset               */
 183     NULL,         /* Boot                */
 184     NULL,         /* Attach              */
 185     NULL,         /* Detach              */
 186     NULL,         /* Context             */
 187     DEV_DEBUG,    /* Flags               */
 188     0,            /* Debug control flags */
 189     urp_dt,       /* Debug flag names    */
 190     NULL,         /* Memory size change  */
 191     NULL,         /* Logical name        */
 192     NULL,         /* Help                */
 193     NULL,         /* Attach help         */
 194     NULL,         /* Attach context      */
 195     NULL,         /* Description         */
 196     NULL          /* End                 */
 197 };
 198 
 199 /*
 200  * urp_init()
 201  */
 202 
 203 // Once-only initialization
 204 
 205 void urp_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 206   {
 207     (void)memset (urpState, 0, sizeof (urpState));
 208   }
 209 
 210 static iom_cmd_rc_t urpCmd (uint iomUnitIdx, uint chan) {
     /* [previous][next][first][last][top][bottom][index][help] */
 211   iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
 212 #if defined(TESTING)
 213   cpu_state_t * cpup = _cpup;
 214   if_sim_debug (DBG_TRACE, & urp_dev) dumpDCW (p->DCW, 0);
 215 #endif /* if defined(TESTING) */
 216  uint ctlrUnitIdx = get_ctlr_idx (iomUnitIdx, chan);
 217  uint devUnitIdx  = cables->urp_to_urd[ctlrUnitIdx][p->IDCW_DEV_CODE].unit_idx;
 218  //UNIT * unitp = & urp_unit [devUnitIdx];
 219  //int urp_unit_num = (int) URPUNIT_NUM (unitp);
 220  struct urpState * statep = & urpState[devUnitIdx];
 221 
 222  // IDCW?
 223  if (IS_IDCW (p)) {
 224     // IDCW
 225     statep->ioMode = urpNoMode;
 226 
 227     switch (p->IDCW_DEV_CMD) {
 228       case 000: // CMD 00 Request status
 229         if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP Request Status\r\n"); }
 230         sim_debug (DBG_DEBUG, & urp_dev, "%s: Request Status\n", __func__);
 231         p->stati = 04000;
 232         break;
 233 
 234       case 006: // CMD 005 Initiate read data xfer (load_mpc.pl1)
 235         if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP Initiate Read Data Xfer\r\n"); }
 236         sim_debug (DBG_DEBUG, & urp_dev, "%s: Initiate Read Data Xfer\n", __func__);
 237         statep->ioMode = urpInitRdData;
 238         p->stati = 04000;
 239         break;
 240 
 241 // 011 punch binary
 242 // 031 set diagnostic mode
 243 
 244       case 031: // CMD 031 Set Diagnostic Mode (load_mpc.pl1)
 245         if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP Set Diagnostic Mode\r\n"); }
 246         sim_debug (DBG_DEBUG, & urp_dev, "%s: Set Diagnostic Mode\n", __func__);
 247         statep->ioMode = urpSetDiag;
 248         p->stati = 04000;
 249         break;
 250 
 251       case 040: // CMD 40 Reset status
 252         if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP Reset Status\r\n"); }
 253         sim_debug (DBG_DEBUG, & urp_dev, "%s: Reset Status\n", __func__);
 254         p->stati = 04000;
 255         p->isRead = false;
 256         break;
 257 
 258       default:
 259         if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP unknown command %o\r\n", p->IDCW_DEV_CMD); }
 260         p->stati = 04501; // cmd reject, invalid opcode
 261         p->chanStatus = chanStatIncorrectDCW;
 262         if (p->IDCW_DEV_CMD != 051) // ignore bootload console probe
 263           sim_warn ("%s: URP unrecognized device command  %02o\n", __func__, p->IDCW_DEV_CMD);
 264         return IOM_CMD_ERROR;
 265     } // switch IDCW_DEV_CMD
 266 
 267     sim_debug (DBG_DEBUG, & urp_dev, "%s: stati %04o\n", __func__, p->stati);
 268     return IOM_CMD_PROCEED;
 269   } // if IDCW
 270 
 271   // Not IDCW; TDCW are captured in IOM, so must be IOTD, IOTP or IOTNP
 272   switch (statep->ioMode) {
 273     case urpNoMode:
 274       if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP IOT no mode\r\n"); }
 275       //sim_printf ("%s: Unexpected IOTx\n", __func__);
 276       //sim_warn ("%s: Unexpected IOTx\n", __func__);
 277       //return IOM_CMD_ERROR;
 278       break;
 279 
 280     case urpSetDiag:
 281       if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP IOT Set Diag\r\n"); }
 282       // We don't use the DDCW, so just pretend we do. BUG
 283       p->stati = 04000;
 284       break;
 285 
 286     case urpInitRdData:
 287       if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP IOT Init Rd Data\r\n"); }
 288       // We don't use the DDCW, so just pretend we do. BUG
 289       p->stati = 04000;
 290       break;
 291 
 292      default:
 293       if_sim_debug (DBG_TRACE, & urp_dev) { sim_printf ("// URP IOT unknown %d\r\n", statep->ioMode); }
 294       sim_warn ("%s: Unrecognized ioMode %d\n", __func__, statep->ioMode);
 295       return IOM_CMD_ERROR;
 296   }
 297   return IOM_CMD_PROCEED;
 298 }
 299 
 300 iom_cmd_rc_t urp_iom_cmd (uint iomUnitIdx, uint chan) {
     /* [previous][next][first][last][top][bottom][index][help] */
 301   iom_chan_data_t * p = & iom_chan_data [iomUnitIdx] [chan];
 302   uint devCode = p->IDCW_DEV_CODE;
 303   if (devCode == 0)
 304     return urpCmd (iomUnitIdx, chan);
 305   uint urpUnitIdx = cables->iom_to_ctlr[iomUnitIdx][chan].ctlr_unit_idx;
 306   iom_cmd_t * cmd = cables->urp_to_urd[urpUnitIdx][devCode].iom_cmd;
 307   if (! cmd) {
 308     //sim_warn ("URP can't find device handler\n");
 309     //return IOM_CMD_ERROR;
 310     p->stati = 04502; //-V536  // invalid device code
 311     return IOM_CMD_DISCONNECT;
 312   }
 313   return cmd (iomUnitIdx, chan);
 314 }

/* [previous][next][first][last][top][bottom][index][help] */