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

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