1 /****^  ***********************************************************
   2         *                                                         *
   3         * Copyright, (C) BULL HN Information Systems Inc., 1989   *
   4         *                                                         *
   5         * Copyright, (C) Honeywell Bull Inc., 1987                *
   6         *                                                         *
   7         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
   8         *                                                         *
   9         *********************************************************** */
  10 
  11 
  12 /****^  HISTORY COMMENTS:
  13   1) change(1985-09-30,Farley), approve(1985-11-14,MCR6979),
  14      audit(1985-11-14,Fawcett), install(1986-03-21,MR12.0-1033):
  15      To support IMU.
  16   2) change(1985-12-03,Farley), approve(1985-12-03,MCR7306),
  17      audit(1986-03-03,Fawcett), install(1986-03-21,MR12.0-1033):
  18      Fix bugs found while doing Dipper changes.
  19   3) change(1985-12-03,Farley), approve(1985-12-03,MCR7312),
  20      audit(1986-03-03,Fawcett), install(1986-03-21,MR12.0-1033):
  21      Add BCE MCA lock and unlock.
  22   4) change(1986-03-12,Fawcett), approve(1986-03-12,MCR7359),
  23      audit(1986-09-05,Lippard), install(1986-09-16,MR12.0-1159):
  24      Enable the locking and unlocking of MCA after system is booted. If system
  25      is not at BCE then enter audit trail.
  26   5) change(1986-05-13,GJohnson), approve(1986-05-13,MCR7387),
  27      audit(1986-05-13,Martinson), install(1986-05-14,MR12.0-1056):
  28      Correct error message documentation.
  29   6) change(1986-07-01,Farley), approve(1986-09-02,MCR7523),
  30      audit(1986-10-03,Fawcett), install(1986-10-09,MR12.0-1181):
  31      Add the BAIL_OUT label, as a place for process_io to goto when it finds
  32      that there is no functional console. Also some other fixes suggested by
  33      John Ata in TR phx19534.
  34   7) change(1986-08-07,Farley), approve(1986-09-02,MCR7523),
  35      audit(1986-10-03,Fawcett), install(1986-10-09,MR12.0-1181):
  36      Increased all timeouts for IMU consoles to 2 min 30 sec. This is needed
  37      because the console adapter firmware waits 2 min before returning "Device
  38      Busy" (01/00) when someone is inputing something on the multi-drop.
  39      Also removed the timeout_factor code, as it is nolonger needed.
  40   8) change(1986-12-18,Farley), approve(1987-01-05,MECR0007),
  41      audit(1986-12-18,Fawcett), install(1987-01-05,MR12.0-1253):
  42      Reset oc_data.write_q_full after get_mc_output entry picks up a message
  43      and after freeing all the write queues in the esd_reset entry and
  44      reset_console/retry_io procedures.
  45 
  46      Changed to call process_io as part of the duties of the poll_for_timeout
  47      entry.  This will allow queued IO to be started.
  48   9) change(1987-01-14,Farley), approve(1987-01-14,MCR7603),
  49      audit(1987-01-14,Fawcett), install(1987-01-14,MR12.0-1279):
  50      Offical installation of above corrections (closes MECR0007).
  51  10) change(1987-07-15,Farley), approve(1987-07-17,MCR7735),
  52      audit(1987-07-20,Fawcett), install(1987-07-22,MR12.1-1044):
  53      Changed queue_io entry to set oc_entry_ptr before checking if MC I/O
  54      is enabled, as this code will eventually want to use it..
  55 
  56      Changed queue_console_io to check for a write_queue_full condition
  57      after adding an entry.  This corrects the age old problem of
  58      out-of-sequence I/O..
  59 
  60      Added a wire_and_mask flag and moved the wiring/masking and
  61      unwiring/unmasking to internal procs to allow it to only occur when
  62      required.
  63 
  64      Changed several sections of the code to check for a null oc_entry_ptr
  65      before attempting to reference data in the oc_entry structure.  Also
  66      turn off the in_service flag in most cases.
  67 
  68      Removed extra new_line (NL) from error_msg.
  69 
  70      Changed all CRASH severities to PANIC, so that report_error will
  71      properly crash the system.
  72 
  73      Changed init_all_consoles to first find all available consoles then
  74      try to assign the bootload.  If attempt fails then it will now
  75      attempt error recovery.
  76 
  77      Changed reconfigure (MAKE_BOOTLOAD_CONSOLE) to reassign previous
  78      (old) console if new console assignment fails.
  79  11) change(1989-08-28,Farley), approve(1989-09-18,MCR8132),
  80      audit(1989-10-10,WAAnderson), install(1989-10-11,MR12.3-1091):
  81      Added checks in the reconfigure MAKE_IO_DEVICE and MAKE_INOP_DEVICE code
  82      after unassigning the bootload console for a NULL oc_entry_ptr.  If it is
  83      null then attempt to find the console again and if unsuccessful return an
  84      error code to the caller.
  85 
  86      Changed console_recovery to call change_console_state to insure that the
  87      config_deck gets properly modified.
  88 
  89      Changed fill_oc_entry to insure that only ONE console has a state of "ON",
  90      changing all others to "ALT".
  91 
  92      Increased the size of the error_msg and error_buffer to be consistent with
  93      oc_trans_output_.
  94 
  95      Added a temporary holding area for oc_entry.line_leng in report_error.
  96      This is required when reporting a multi-line error message and the console
  97      goes inoperative prior to completing the sequence.
  98 
  99      Changed "I/O error" log message to optionally include a timeout indication
 100      ("I/O timeout error") and also include the OPC name in the ascii text.
 101  12) change(2021-10-27,Swenson), approve(2021-10-27,MCR10095),
 102      audit(2021-10-29,GDixon), install(2021-10-29,MR12.8-1004):
 103      Fix occasional console hang due to lost terminate interrupt.
 104                                                    END HISTORY COMMENTS */
 105 /* format: off */
 106 ^L
 107 ocdcm_:
 108      proc ();
 109 
 110           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 111           /*                                                                                                  */
 112           /* Purpose:                                                                                         */
 113           /*                                                                                                  */
 114           /*        This is the operator console DIM. It has the following responsibilities:                  */
 115           /*                                                                                                  */
 116           /*                  1.) Initialize and maintain the ring 0 oc_data database.                        */
 117           /*                                                                                                  */
 118           /*                  2.) Establish and maintain communications with the bootload console.            */
 119           /*                                                                                                  */
 120           /*                  3.) Detect console faults and handle these faults through one of the following  */
 121           /*                  recovery strategies:                                                            */
 122           /*                                                                                                  */
 123           /*                            a.) Utilize an alternate console as the bootload console device.      */
 124           /*                            b.) Forward all console traffic to the message coordinator.           */
 125           /*                                                                                                  */
 126           /*                  4.) Provide an orderly means explicitly reconfiguring all configured console    */
 127           /*                      devices.                                                                    */
 128           /*                                                                                                  */
 129           /* Note:  This code was redesigned and rewritten from the original ocdcm_ to add support of         */
 130           /*        multiple consoles and to provide a better automated recovery strategy.                    */
 131           /*                                                                                                  */
 132           /*                                                                                                  */
 133           /* Written:                   07/20/73                                                              */
 134           /*                                                                                                  */
 135           /* Author:                    Bill Silver         (Silver.Multics)                                  */
 136           /*                                                                                                  */
 137           /* Rewritten:                 05/01/83                                                              */
 138           /*                                                                                                  */
 139           /* Author:                    E. A. Ranzenbach    (Ranzenbach.Multics@M)                            */
 140           /* Location:                  System-M.                                                             */
 141           /* Release:                   MR10.2                                                                */
 142           /*                                                                                                  */
 143           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 144           /*                                                                                                  */
 145           /* Modifications:                                                                                   */
 146           /*                                                                                                  */
 147           /*  Date    Author                      Reason                                                      */
 148           /*                                                                                                  */
 149           /*  831207  Edward A. Ranzenbach        Set the wired_hardcore_data$abort_request bit for bce.      */
 150           /*                                      Also, list consoles only at appropriate times.              */
 151           /*                                                                                                  */
 152           /*  840320  Edward A. Ranzenbach        Critical Fix for MR10.2. Corrected reconfiguration crashes  */
 153           /*                                      caused by inadvertantly leaving oc_data locked.             */
 154           /*                                                                                                  */
 155           /*  840410  Edward A. Ranzenbach        Fixed yet another reconfiguration problem which produces    */
 156           /*                                      a "Lock not Mine" condition. Added set_prompt entrypoint    */
 157           /*                                      for B2. Cut size of I/Os to 132 bytes. Changed bootload     */
 158           /*                                      consoles reconfigured implicitly by a new bootload console  */
 159           /*                                      to have a state of ALT, thus making them immediately        */
 160           /*                                      available to console recovery. Changed console recovery     */
 161           /*                                      strategy during crash to search for a good console until it */
 162           /*                                      can find one.                                               */
 163           /*                                                                                                  */
 164           /*  840417  E. A. Ranzenbach            Better error reporting stragegy which prevents syserr race  */
 165           /*                                      conditions.                                                 */
 166           /*  840502  E. A. Ranzenbach            Changed certain reconfiguration options to not wire and     */
 167           /*                                      mask.                                                       */
 168           /*                                                                                                  */
 169           /*  840517  E. A. Ranzenbach            Update the wired config deck dynamically.                   */
 170           /*                                                                                                  */
 171           /*  840605  E. A. Ranzenbach            Fix garbled I/O problems and attempts to unlock oc_data     */
 172           /*                                      multiple times.                                             */
 173           /*  840712  E. A. Ranzenbach            Fixed problem that stored uninitialized pointer in the      */
 174           /*                                      event queue.                                                */
 175           /*                                                                                                  */
 176           /*  840724  E. A. Ranzenbach            To change timeouts to look for good status before retrying  */
 177           /*                                      the I/O. Necessary for bce breakpoints.                     */
 178           /*                                                                                                  */
 179           /*  841105  E. A. Ranzenbach            Implemented printer_(on off) control order and fixed one    */
 180           /*                                      more reconfiguration locking strategy problem.              */
 181           /*                                                                                                  */
 182           /*  841115  E. A. Ranzenbach            Change for Olin to send wakeup when taking back             */
 183           /*                                      responsibility for I/O from theMC.                          */
 184           /*                                                                                                  */
 185           /*  841115  E. A. Ranzenbach            Simulate a pending READ during initialization.              */
 186           /*                                                                                                  */
 187           /*  850111  E. A. Ranzenbach            Added lost special interrupt protection so that EMC's       */
 188           /*                                      won't lose during heavey traffic.                           */
 189           /*  850329  E. A. Ranzenbach            Cut the size of I/O's to 132 chars, improved error          */
 190           /*                                      reporting. TR19223.                                         */
 191           /*  850405  E. A. Ranzenbach            Fixed console_io.io_in_progress not being reset during      */
 192           /*                                      console recovery. TR19225.                                  */
 193           /*                                                                                                  */
 194           /*  850620  Paul K  Farley              To wait five milliseconds after status arrives, if doing    */
 195           /*                                      priority_io. This will allow the IMU console time to send   */
 196           /*                                      the interrupt and get ready for the next IO.                */
 197           /*                                                                                                  */
 198           /*                                      Add code to check if PCW gets executed by console. Only     */
 199           /*                                      IOM consoles use it, and if on an IMU we need to know.      */
 200           /*                                                                                                  */
 201           /*                                      Add a flag to know that the program was called at           */
 202           /*                                      $interrupt_handler.  Change the status pause check to       */
 203           /*                                      check this flag, instead of checking for priority io in     */
 204           /*                                      progress.  This is because there could be an IO             */
 205           /*                                      outstanding that will not terminate properly if not given   */
 206           /*                                      the extra time.                                             */
 207           /*                                                                                                  */
 208           /*                                      Added code to LOCK(disable) or UNLOCK(enable) the console   */
 209           /*                                      input to the MCA (in the IMU).                              */
 210           /*                                                                                                  */
 211           /*  850827  Paul K  Farley              To change report_error to locate the bootload console       */
 212           /*                                      before outputting error message. Also added more info       */
 213           /*                                      to the oc_data event trace.                                 */
 214           /*                                                                                                  */
 215           /*  850911  Paul K  Farley              To reset alerted switch in priority_io entry.               */
 216           /*                                                                                                  */
 217           /*  850913  Paul K  Farley              To add a timeout_factor to oc_entry for increasing the      */
 218           /*                                      IO timeout under special conditions.                        */
 219           /*                                                                                                  */
 220           /*  850925  Paul K  Farley              To allow for times when NO cpu cards are present and        */
 221           /*                                      to properly find the entrypoint_name in report_error.       */
 222           /*                                                                                                  */
 223           /*  850930  Paul K  Farley              To add the process_group_id to the new MCA messages.        */
 224           /*                                                                                                  */
 225           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 226 ^L
 227 console_free:
 228      entry (console_to_check_parm, console_is_free_parm);
 229 
 230           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 231           /*                                                                                                  */
 232           /* Entry to check if the specified console is available to RCP. If the console is not assigned as   */
 233           /* a bootload or alternate then console_is_free is returned true. If no such console is configured  */
 234           /* or the console is assigned as a bootload or alternate console then console_is_free is returned   */
 235           /* false.                                                                                           */
 236           /*                                                                                                  */
 237           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 238 
 239 /* parameters... (I) = Input, (O) = Output */
 240 
 241      dcl  console_to_check_parm         char      (4)       parameter;          /* name of the console to check...  (I) */
 242      dcl  console_is_free_parm          bit       (1)       parameter;          /* ON => console is free...         (O) */
 243 
 244 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 245 
 246 
 247      console_to_check = console_to_check_parm;                                  /* copy args before we wire and mask... */
 248 
 249      call lock_oc_data ();                                                      /* get the lock, wire and mask...       */
 250 
 251      oc_entry_ptr = find_oc_entry (console_to_check);                           /* locate the console...                */
 252      if oc_entry_ptr = null then do;                                            /* no such animal...                    */
 253           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
 254           console_is_free_parm = false;                                         /* set parameter value...               */
 255           return;
 256      end;
 257 
 258      console_is_free = (^oc_entry.bootload_console & ^oc_entry.alternate);      /* setup internal parm value...         */
 259 
 260      call unlock_oc_data ();                                                    /* release lock, unwire, unmask...      */
 261 
 262      console_is_free_parm = console_is_free;                                    /* copy to caller's stack...            */
 263 
 264      return;                                                                    /* done...                              */
 265 ^L
 266 console_info:
 267      entry (oc_name, oc_flags, oc_channel, oc_device_idx, oc_line_leng, code);
 268 
 269           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 270           /*                                                                                                  */
 271           /* Entry to return information about the requested console. If oc_name  = "" then information about */
 272           /* the bootload console is returned.                                                                */
 273           /*                                                                                                  */
 274           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 275 
 276 /* parameters... (I) = Input, (O) = Output */
 277 
 278      dcl  oc_name                       char      (4)       aligned             /* console info is requested for..(I/O) */
 279                                                             parameter;
 280      dcl  oc_flags                      bit       (36)      parameter;          /* oc_entry.flags...                (O) */
 281      dcl  oc_channel                    char      (8)       parameter;          /* console's IOM channel...         (O) */
 282      dcl  oc_device_idx                 fixed bin (17)      parameter;          /* console's assigned device index..(O) */
 283      dcl  oc_line_leng                  fixed bin (17)      parameter;          /* console's line length...         (O) */
 284 /*   dcl  code                          fixed bin (35)      parameter;             standard Multics error code...   (O) */
 285 
 286 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 287 
 288      oc_entry_ptr = find_oc_entry (oc_name);                                    /* locate the requested console...      */
 289 
 290      if oc_entry_ptr = null then do;                                            /* no such console...                   */
 291           code = error_table_$device_not_active;
 292           return;
 293      end;
 294 
 295      oc_flags = unspec (oc_entry.flags);                                        /* copy the info...                     */
 296      oc_channel = oc_entry.channel;
 297      oc_device_idx = oc_entry.device_idx;
 298      oc_line_leng = oc_entry.line_leng;
 299 
 300      code = 0;                                                                  /* indicate successful completion...    */
 301 
 302      return;
 303 ^L
 304 drain_io:
 305      entry ();
 306 
 307           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 308           /*                                                                                                  */
 309           /* Entry to quies the console. This is done by locking oc_data, thus preventing I/O queueing, then  */
 310           /* completing any I/O in progress and then attempting to complete any I/O in the queue.             */
 311           /*                                                                                                  */
 312           /* Note: This entry leaves oc_entry.io_in_progress set to prevent further attempts at I/O...        */
 313           /*                                                                                                  */
 314           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 315 
 316      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 317 
 318      if ^oc_data.in_service | oc_data.mc_io_enabled then return;                /* console is not configured...         */
 319 
 320      oc_entry_ptr = find_oc_entry ("");                                         /* find the bootload console...         */
 321      if oc_entry_ptr = null then return;                                        /* no console, no need to drain...      */
 322 
 323      do while (^done);                                                          /* quies the console...                 */
 324           call lock_oc_data ();                                                 /* get the lock, wire and mask...       */
 325           do while (oc_entry.io_in_progress);                                   /* finish I/O that is in progress...    */
 326                call process_io_status ();                                       /* process received statuses...         */
 327           end;
 328           if next_console_io () = null then done = true;
 329           else call process_io ();                                              /* and outstanding I/O...               */
 330           call unlock_oc_data ();                                               /* release lock, unwire and unmask...   */
 331      end;
 332 
 333      oc_entry.io_in_progress = true;                                            /* only my hairdresser knows for sure...*/
 334 
 335      return;                                                                    /* pending I/O completed...             */
 336 ^L
 337 err_event_chan:
 338      entry (event_chan);
 339 
 340           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 341           /*                                                                                                  */
 342           /* Entry which when called will install the event channel specified by the caller into              */
 343           /* oc_data.err_event_cid. This event channel will be utilizied to wakeup the caller any time a      */
 344           /* condition exists where I/O cannot be handled by any of the configured consoles.                  */
 345           /*                                                                                                  */
 346           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 347 
 348 /* parameters... (I) = Input, (O) = Output */
 349 
 350      dcl  event_chan                    fixed bin (71)      parameter;          /* event channel to send wakeup on..(I) */
 351 
 352 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 353 
 354      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 355 
 356      oc_data.err_event_cid = event_chan;                                        /* install the channel...               */
 357      oc_data.err_event_pid = pds$process_id;                                    /* and the process ID of the caller...  */
 358 
 359      return;                                                                    /* done...                              */
 360 ^L
 361 esd_reset:
 362      entry ();
 363 
 364           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 365           /*                                                                                                  */
 366           /* Entry called by ESD to ensure that it has a usable console.                                      */
 367           /*                                                                                                  */
 368           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 369 
 370      entrypoint = "esd_reset";                                                  /* set entrypoint name...               */
 371 
 372      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 373      oc_data.lock = ""b;                                                        /* reset lock...                        */
 374 
 375      if ^oc_data.in_service then do;                                            /* no good consoles to run on...        */
 376           return;                                                               /* all that is necessary...             */
 377      end;
 378 
 379      oc_data.mc_io_enabled = false;                                             /* MC will not be operative...          */
 380 
 381      oc_data.crash_on_crf = false;                                              /* give ESD a fair shake at recovery... */
 382 
 383      unspec (oc_data.priority_io) = ""b;                                        /* erase any residue...                 */
 384      oc_data.priority_io.completed = true;                                      /* mark the slot free...                */
 385 
 386      do idx = 1 to WRITE_QUEUE_SIZE;                                            /* free all WRITES...                   */
 387           unspec (oc_data.write_queue (idx)) = ""b;                             /* erase any residue...                 */
 388           oc_data.write_queue (idx).completed = true;                           /* mark the slot free...                */
 389      end;
 390      oc_data.write_q_full  = false;                                             /* reset the full flag...               */
 391 
 392      oc_data.stacked_read_cnt = 1;                                              /* free all READs, leave one pending... */
 393      unspec (oc_data.read_io) = ""b;                                            /* erase any residue...                 */
 394      oc_data.read_io.completed = true;                                          /* mark the slot free...                */
 395 
 396      call unassign_bootload_console ();                                         /* unassign the bootload console...     */
 397 
 398      if oc_entry_ptr = null then do;                                            /* no bootload console found...         */
 399           oc_data.in_service = false;                                           /* best we can do...                    */
 400           return;
 401      end;
 402 
 403      oc_entry.io_in_progress = false;                                           /* reset certain flags...               */
 404      oc_entry.discard = false;
 405      oc_entry.discarded = false;
 406      oc_entry.got_special_int = false;
 407      oc_entry.oper_request = false;
 408      oc_entry.retry_cnt = 0;
 409      oc_entry.io_time = 0;
 410 
 411      call assign_bootload_console (oc_entry.name, err_code);                    /* and now re-assign it...              */
 412 
 413      call reset_channel ();                                                     /* reset the console channel...         */
 414 
 415      return;
 416 ^L
 417 get_input:
 418      entry (input_text, input_length, code);
 419 
 420           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 421           /*                                                                                                  */
 422           /* Entry to pickup operator input. Although there is only one physical READ I/O additional READs    */
 423           /* may be queued before this one completes. This is accomplished by stacking the READ requests. As  */
 424           /* a READ is picked up a check is made and the READ is reset if any READs have been stacked.        */
 425           /*                                                                                                  */
 426           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 427 
 428 /* parameters... (I) = Input, (O) = Output */
 429 
 430      dcl  input_text                    char      (256)     parameter;          /* text of the input line...        (O) */
 431      dcl  input_length                  fixed bin (17)      parameter;          /* length of the input line...      (O) */
 432 /*   dcl  code                          fixed bin (35)      parameter;             standard Multics error code...   (O) */
 433 
 434 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 435 
 436      input_text = "";                                                           /* initialize...                        */
 437      input_length = 0;
 438      code = 0;
 439 
 440      oc_entry_ptr = find_oc_entry ("");                                         /* find the bootload console...         */
 441      if oc_entry_ptr = null then return;                                        /* no console, no data...               */
 442 
 443      call lock_oc_data ();                                                      /* get the lock, wire and mask...       */
 444 
 445      local_io = oc_data.read_io;                                                /* copy to local storage...             */
 446      call reset_read ();                                                        /* reset the READ I/O...                */
 447      oc_data.stacked_read_cnt = oc_data.stacked_read_cnt - 1;                   /* decrement the read stack...          */
 448      if oc_data.stacked_read_cnt > 0 then do;                                   /* if we have stacked reads...          */
 449           call log_console_event (POPPED_READ, addr (oc_data.read_io));         /* log the POP...                       */
 450      end;
 451      call unlock_oc_data ();                                                    /* release lock, unwire and unmask...   */
 452      input_text = local_io.text;                                                /* copy the input text...               */
 453      input_length = local_io.leng;                                              /* and the input text length...         */
 454      call log_console_event (READ_PICKUP, addr (oc_data.read_io));              /* log the event...                     */
 455 
 456      return;
 457 ^L
 458 get_mc_output:
 459      entry (mc_io_uid , output_length, output_text);
 460 
 461 
 462           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 463           /*                                                                                                  */
 464           /* Entry called be the Message Coordinator to pickup the text of a non-syserr message. The          */
 465           /* mc_io_uid contains the negated time that the message was queued. This was passed to the Message  */
 466           /* Coordinator when we told it there was someting to do. This message UID is used to search the     */
 467           /* message queue and retrieve the right message.                                                    */
 468           /*                                                                                                  */
 469           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 470 
 471 /* parameters... (I) = Input, (O) = Output */
 472 
 473      dcl  mc_io_uid                     fixed bin (71)      parameter;          /* negated time queued of output... (I) */
 474      dcl  output_length                 fixed bin (17)      parameter;          /*                                  (O) */
 475      dcl  output_text                   char      (256)     parameter;          /*                                  (O) */
 476 
 477 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 478 
 479      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 480      oc_entry_ptr = null;
 481 
 482      do idx = 1 to WRITE_QUEUE_SIZE;                                            /* search the WRITE queue...            */
 483           if -oc_data.write_queue (idx).time_queued = mc_io_uid then do;        /* found it...                          */
 484                console_io_ptr = addr (oc_data.write_queue (idx));               /* overlay the WRITE...                 */
 485                output_length = multiply (console_io.leng, 4, 17);               /* setup return parameters...           */
 486                output_text = console_io.text;
 487                console_io.completed = true;                                     /* free the I/O slot...                 */
 488                oc_data.write_q_full  = false;                                   /* reset the full flag...               */
 489                call log_console_event (MC_IO_PICKUP, console_io_ptr);
 490                return;
 491           end;
 492      end;
 493 
 494      output_length = 0;                                                         /* requested output not found...        */
 495      output_text = "";
 496 
 497      call log_console_event (MC_IO_FAILURE, null);
 498 
 499      return;                                                                    /* done...                              */
 500 ^L
 501 init_all_consoles:
 502      entry ();
 503 
 504           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 505           /*                                                                                                  */
 506           /* This entry is called by real_initializer during initialization to configure all consoles         */
 507           /* described in the config file.                                                                    */
 508           /*                                                                                                  */
 509           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 510 
 511      entrypoint = "init_all_consoles";                                          /* set entrypoint name...               */
 512 
 513      oc_data_ptr = addr (oc_data$);                                             /* find oc_data...                      */
 514      oc_entry_ptr = null;
 515 
 516      unspec (oc_data) = ""b;                                                    /* zero the database...                 */
 517 
 518      sd_ptr = addr (syserr_data$syserr_area);                                   /* find syserr data...                  */
 519      sd.char_type_flag = true;                                                  /* ASCII console...                     */
 520      sd.ocdcm_init_flag = false;                                                /* specify no active console yet...     */
 521 
 522      oc_data.version = oc_data_version;                                         /* set the version...                   */
 523      oc_data.flags.printer_on = true;                                           /* start with echoing input...          */
 524 
 525      oc_data.last_read_queued = -1;                                             /* initialize some times...             */
 526      oc_data.last_write_queued = -1;
 527      oc_data.last_poll_time = -1;
 528      oc_data.max_computed_io_time = MAX_MAX_IO_TIME * 1e06;                     /* for now...                           */
 529 
 530      oc_data.next_free_write = 1;                                               /* initialize indices...                */
 531      oc_data.next_event = 1;
 532 
 533      oc_data.read_io.completed = true;                                          /* free the read slot...                */
 534      oc_data.priority_io.completed = true;                                      /* and mark priority as empty...        */
 535 
 536      do idx = 1 to WRITE_QUEUE_SIZE;                                            /* mark all WRITE slots as free...      */
 537           oc_data.write_queue (idx).completed = true;
 538      end;
 539 
 540      oc_data.abs_addr = absadr (oc_data_ptr, err_code);                         /* find absolute address of oc_data...  */
 541      if err_code ^= 0 then call report_error (PANIC, entrypoint,
 542           "Unable to determine absolute memory address of oc_data.");
 543 
 544      oc_data.prompt = "M-> " || copy (byte (binary ("177"b3)), 4);              /* setup prompt string & pad...         */
 545      oc_data.write_return = "177177012015"b3;                                   /* string to write = PAD PAD CR LF...   */
 546      oc_data.discard_notice = byte (10) || byte (13) || "(output discarded)" || /* initialize the discard notice...     */
 547           byte (10) || byte (13) || copy (byte (binary ("177"b3)), 2);
 548 
 549      prph_opc_cardp = null;                                                     /* initialize for card search...        */
 550 
 551      call config_$find_parm ("ccrf", parm_ptr);                                 /* find the CCRF parm...                */
 552      if parm_ptr ^= null then oc_data.crash_on_crf = true;                      /* found it...                          */
 553 
 554      call config_$find_parm ("clst", parm_ptr);                                 /* find the CLST parm...                */
 555      if parm_ptr ^= null then oc_data.list_consoles = true;                     /* found it...                          */
 556 
 557      do while (^done);                                                          /* process all "opc" "prph" cards...    */
 558           call config_$find ("prph", prph_opc_cardp);                           /* find a "prph" card...                */
 559           if prph_opc_cardp = null then done = true;                            /* no more prph cards...                */
 560           else do;
 561                if substr (prph_opc_card.name, 1, 3) = "opc" then do;            /* found an "opc" card...               */
 562                     if oc_data.console_cnt = MAX_OPC_CNT then do;               /* don't reference beyond oc_data...    */
 563                          done = true;                                           /* signal end of initialization loop... */
 564                          call report_error (BEEP, entrypoint, "Maximum console count exceeded.");
 565                          call report_error (ANNOUNCE, entrypoint, "Additional consoles will not be configured.");
 566                     end;
 567                     else do;
 568                          call fill_oc_entry (oc_data_ptr,                       /* build DCW list, etc...               */
 569                               oc_data.console_cnt + 1, prph_opc_cardp, oc_entry_ptr);
 570                          if oc_entry.active then                                /* if we succeeded...                   */
 571                               oc_data.console_cnt = oc_data.console_cnt + 1;
 572                     end;
 573                end;
 574           end;
 575      end;
 576 
 577      if oc_data.console_cnt < 1 then do;                                        /* must be at least one opc card...     */
 578           call report_error (PANIC, entrypoint, "Missing prph opc card.");
 579      end;
 580 
 581      do idx = 1 to oc_data.console_cnt;                                         /* locate the console...                */
 582           oc_entry_ptr = addr (oc_data.opc (idx));
 583           if oc_entry.bootload_console then do;                                 /* found bootload console, turn it on...*/
 584                call assign_bootload_console (oc_entry.name, err_code);
 585                if err_code ^= 0 then call console_recovery ();
 586                if oc_data.bootload_console_idx < 1 then
 587                     call report_error (PANIC, entrypoint, "Console channel assignment failed.");
 588                sd.ocdcm_init_flag = true;                                       /* enable syserr traffic...             */
 589           end;
 590      end;
 591 
 592      if oc_data.bootload_console_idx < 1 then do;                               /* must have an active console...       */
 593           call console_recovery ();
 594           if oc_data.bootload_console_idx < 1 then
 595                call report_error (PANIC, entrypoint, "No active console configured.");
 596      end;
 597 
 598      prph_opc_cardp = null;                                                     /* might as well use this ptr...        */
 599      cpu_cnt = 0;                                                               /* initialize the counter...            */
 600      done = false;                                                              /* initialize loop terminator...        */
 601 
 602      do while (^done);                                                          /* count the number of CPUs...          */
 603           call config_$find ("cpu", prph_opc_cardp);
 604           if prph_opc_cardp ^= null then cpu_cnt = cpu_cnt + 1;
 605           else done = true;
 606      end;
 607                                                                                 /* maximum time we will wait for lock...*/
 608      oc_data.max_computed_io_time = oc_data.max_computed_io_time * max (1, cpu_cnt);
 609 
 610      if oc_data.list_consoles &
 611           (sys_info$collection_1_phase = BOOT_INITIALIZATION
 612           | sys_info$collection_1_phase = SERVICE_INITIALIZATION) then
 613           do idx = 1 to oc_data.console_cnt;                                    /* list the assignments...              */
 614                oc_entry_ptr = addr (oc_data.opc (idx));
 615                device_type = "uninitialized";
 616                if oc_entry.bootload_console then device_type = "bootload";
 617                else if oc_entry.alternate then device_type = "alternate";
 618                else if oc_entry.io_device then device_type = "I/O";
 619                else if oc_entry.inop_device then device_type = "inoperative";
 620                else if oc_entry.no_device then device_type = "off";
 621                call report_error (ANNOUNCE, entrypoint, "Assigned console ^a as ^a device.",
 622                     oc_entry.name, device_type);
 623      end;
 624 
 625      if sys_info$collection_1_phase < SERVICE_INITIALIZATION then do;           /* simulate a waiting READ...           */
 626           oc_data.opc (oc_data.bootload_console_idx).oper_request = true;       /* prime the RE(TURN QUEST) key...      */
 627      end;
 628 
 629      call log_console_event (INIT_OC_DATA, oc_data.io_ptr);
 630 
 631      return;                                                                    /* done...                              */
 632 ^L
 633 interrupt_handler:
 634      entry (assigned_idx, interrupt_level, fault_status);
 635 
 636           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 637           /*                                                                                                  */
 638           /* Entry called to field an interrupt for the console channel. It should be noted that any Multics  */
 639           /* process on the CPU when the interrupt arrives will execute this code. If we are unable to get    */
 640           /* the lock and we have a special interrupt (level 7) then we will post it in a special area of     */
 641           /* oc_data that can be modified without protection of the lock. It is the responsibility of anyone  */
 642           /* unlocking oc_data to process any pending specials.                                               */
 643           /*                                                                                                  */
 644           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 645 
 646 /* parameters... (I) = Input, (O) = Output */
 647 
 648      dcl  assigned_idx                  fixed bin (35)      parameter;          /* index of console causing interrupt. (I) */
 649      dcl  interrupt_level               fixed bin (3)       parameter;          /* should be 1, 3, or 7...          (I) */
 650      dcl  fault_status                  bit       (36)      parameter;          /* system fault status, IGNORED...  (I) */
 651 
 652 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 653 
 654      entrypoint = "interrupt_handler";                                          /* set entrypoint name...               */
 655 
 656 
 657      entered_via_interrupt = true;                                              /* show which way we came in..          */
 658 
 659      if interrupt_level = 1 then do;                                            /* IOM overhead fault...                */
 660           call report_error (JUST_LOG, entrypoint, "System Fault.");            /* log it...                            */
 661           return;                                                               /* and ignore it...                     */
 662      end;
 663 
 664      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 665 
 666      oc_entry_ptr = find_oc_entry ("");                                         /* locate the bootload console...       */
 667      if oc_entry_ptr = null then return;                                        /* no bootload console... */
 668      if assigned_idx > 0 & assigned_idx ^= oc_entry.device_idx then do;         /* interrupt not from bootload console. */
 669           if interrupt_level = 7 then return;                                   /* no specials, please...               */
 670           do idx = 1 to oc_data.console_cnt;                                    /* locate the console...                */
 671                if oc_data.opc (idx).device_idx = assigned_idx then              /* found it...                          */
 672                     oc_entry_ptr = (addr (oc_data.opc (idx)));
 673           end;
 674           if assigned_idx ^= oc_entry.device_idx then return;                   /* could not locate console...          */
 675           if ^oc_entry.assigned then return;                                    /* console no longer assigned...        */
 676      end;
 677 
 678      if stac (addr (oc_data.lock), pds$process_id) then do;                     /* only field terminates if we get lock.*/
 679           call wire_and_mask;                                                   /* so unlock can unwire...              */
 680           if interrupt_level = 7 then oc_entry.got_special_int = true;          /* operator pushed RE(TURN QUEST) ...   */
 681 
 682           call process_io_status ();                                            /* process any associated I/O status... */
 683 
 684           call process_io ();                                                   /* process any waiting output...        */
 685 
 686           call unlock_oc_data ();                                               /* release lock, unwire and unmask...   */
 687      end;
 688      else if interrupt_level = 7 then do;
 689           oc_data.no_lock_flags.got_special_int = true;
 690           oc_data.meters.queued_special_int_count = oc_data.meters.queued_special_int_count +1;
 691      end;
 692      else if interrupt_level = 3 then do;
 693           oc_data.no_lock_flags.got_terminate_int = true;
 694      end;
 695 
 696      return;
 697 ^L
 698 poll_for_timeout:
 699      entry ();
 700 
 701           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 702           /*                                                                                                  */
 703           /* Entry called by traffic control to check for I/O timeouts on the console.                        */
 704           /*                                                                                                  */
 705           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 706 
 707      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 708 
 709      if ^oc_data.in_service | oc_data.mc_io_enabled then return;                /* no console service, no timeouts...   */
 710 
 711      if oc_data.lock = pds$process_id then do;                                  /* MYLOCK error...                      */
 712           call report_error (PANIC, "lock_oc_data", "Mylock error.");           /* crash system, store flagbox message..*/
 713      end;
 714 
 715      if ^stac (addr (oc_data.lock), pds$process_id) then return;                /* if I can't get the lock return...    */
 716 
 717      oc_data.last_poll_time = clock ();                                         /* note last time polling occured...    */
 718 
 719      oc_entry_ptr = find_oc_entry ("");                                         /* find the bootload console entry...   */
 720 
 721      if oc_entry_ptr ^= null then do;                                           /* only do if console available...      */
 722           call process_io_status ();                                            /* timeout check done there..           */
 723 
 724           call process_io ();                                                   /* process any waiting output...        */
 725      end;
 726      else if ^oc_data.mc_io_enabled then
 727           oc_data.in_service = false;
 728 
 729      if ^stacq (oc_data.lock, ""b, pds$process_id) then do;                     /* clear lock...                        */
 730           if oc_data.lock ^= ""b then                                           /* if not free crash...                 */
 731                call report_error (PANIC, "unlock_oc_data", "Lock not mine.");
 732      end;
 733 
 734      return;                                                                    /* done...                              */
 735 ^L
 736 printer_off:
 737      entry ();
 738 
 739           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 740           /*                                                                                                  */
 741           /* Entry which implements "printer_off" control order. Once this entry has been called all input    */
 742           /* from the console will be in the blind until the "printer_on" entry is called.                    */
 743           /*                                                                                                  */
 744           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 745 
 746      oc_data_ptr = addr (oc_data$);                                             /* no need to lock and wire for this... */
 747      oc_data.flags.printer_on = false;                                          /* turn off read echoing...             */
 748      return;                                                                    /* all there is to it...                */
 749 
 750 printer_on:
 751      entry ();
 752 
 753           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 754           /*                                                                                                  */
 755           /* Re-enables echoing of input from the console...                                                  */
 756           /*                                                                                                  */
 757           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 758 
 759      oc_data_ptr = addr (oc_data$);                                             /* no need to lock and wire for this... */
 760      oc_data.flags.printer_on = true;                                           /* turn it back on...                   */
 761      return;                                                                    /* all there is to it...                */
 762 ^L
 763 priority_io:
 764      entry (priority_io_ptr);
 765 
 766           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 767           /*                                                                                                  */
 768           /* This entry provides a means of performing priority I/O to the operator's console. The I/O is     */
 769           /* placed into a special buffer in oc_data. The caller then calls the appropriate internal          */
 770           /* procedures to cause the I/O to be immediately executed.                                          */
 771           /*                                                                                                  */
 772           /*                                 * * *  W A R N I N G * * *                                       */
 773           /*                                                                                                  */
 774           /* The use of this entrypoint causes the caller to loop in ocdcm_ awaiting the successful           */
 775           /* completion of the I/O. This looping is done on a wired stack in a masked interrupt environment   */
 776           /* and can cause the processor of execution to loop for as long as it takes to complete the I/O.    */
 777           /* For READs this can take longer than thirty (30) seconds.                                         */
 778           /*                                                                                                  */
 779           /* Noting the effects that this can have on performance it is imperative that this entrypoint be    */
 780           /* utilized judiciously.                                                                            */
 781           /*                                                                                                  */
 782           /* Note:  An additional side effect of this entrypoint is that I/O performed by it will not be in   */
 783           /* chronological order with I/O performed through the queue_io entrypoint.                          */
 784           /*                                                                                                  */
 785           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 786 
 787 /* parameters... (I) = Input, (O) = Output */
 788 
 789      dcl  priority_io_ptr               ptr                 parameter;          /* -> console_io structure...       (I) */
 790 
 791 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 792 
 793      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
 794 
 795      if ^oc_data.in_service then return;                                        /* no tickee, no washee...              */
 796 
 797      local_io = priority_io_ptr -> console_io;                                  /* copy the I/O to our stack...         */
 798 
 799      call lock_oc_data ();                                                      /* get the lock, wire and mask...       */
 800 
 801      oc_data.priority_io = local_io;                                            /* copy the priority I/O...             */
 802 
 803      oc_data.priority_io.time_queued = clock ();                                /* next_console_io needs this...        */
 804      oc_data.priority_io.process_id = pds$process_id;                           /* store our process_id...              */
 805      oc_data.priority_io.event_chan = 0;                                        /* caller will loop on completion...    */
 806      oc_data.priority_io.completed = false;                                     /* start off on the right foot..        */
 807      oc_data.priority_io.in_progress = false;
 808      oc_data.priority_io.alerted = false;
 809 
 810      if oc_data.priority_io.read then do;                                       /* reset READ stuff...                  */
 811           oc_data.priority_io.sequence_no = 0;                                  /* READs don't have syserr numbers...   */
 812           oc_data.priority_io.prompted = false;
 813           oc_data.priority_io.leng = 0;
 814           oc_data.priority_io.text = "";
 815      end;
 816 
 817      oc_entry_ptr = find_oc_entry ("");                                         /* locate the bootload console...       */
 818 
 819      if oc_entry_ptr ^= null then
 820           do while (oc_entry.io_in_progress);                                   /* quies the console...                 */
 821           call process_io_status ();
 822      end;
 823 
 824      if oc_data.mc_io_enabled then do;                                          /* Message Coordinator is handling I/O..*/
 825           if ^oc_data.priority_io.read then do;                                 /* only pass on WRITEs...               */
 826                call bump_io_to_mc ((oc_data.priority_io.sequence_no));
 827                oc_data.priority_io.completed = true;                            /* free the space...                    */
 828           end;
 829           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
 830           return;                                                               /* all we can do...                     */
 831      end;
 832 
 833 
 834      do while (^oc_data.priority_io.completed);                                 /* LOOP IN RING ZERO TILL I/O COMPLETE..*/
 835           call process_io ();                                                   /* process the I/O...                   */
 836           if oc_data.priority_io.read & ^oc_data.priority_io.in_progress then do;
 837                call unlock_oc_data ();                                          /* let Special interrupts through...    */
 838                call lock_oc_data ();                                            /* and wire and mask again...           */
 839           end;
 840           call process_io_status ();                                            /* process the status...                */
 841      end;
 842 
 843      local_io = oc_data.priority_io;                                            /* copy results to local storage...     */
 844      oc_data.priority_io.read = false;                                          /* prevent priority READ resets...      */
 845 
 846      call unlock_oc_data ();                                                    /* release lock, unwire and unmask...   */
 847 
 848      if local_io.read then do;                                                  /* copy results for the caller...       */
 849           priority_io_ptr -> console_io = local_io;
 850      end;
 851 
 852      return;                                                                    /* I/O complete...                      */
 853 ^L
 854 queue_io:
 855      entry (user_io_ptr, io_queue_time);
 856 
 857           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 858           /*                                                                                                  */
 859           /* Entry to queue an I/O. This entry first copies the I/O onto our stack before we wire it with a   */
 860           /* call to lock_oc_data. This is necessary because we would are not allowed to page fault on the    */
 861           /* callers data after we wire ourselves. The entry the makes some preliminary decisions about the   */
 862           /* I/O and the console state and calls the queue_console_io routine to do the actual queueing. For  */
 863           /* WRITEs the caller is returned the time that the I/O is queued. If that time is 0 then the queue  */
 864           /* is full and the caller will have to try again later. A time of 0 is always returned for          */
 865           /* READs since the caller always goes blocked awaiting READ completion.                             */
 866           /*                                                                                                  */
 867           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 868 
 869 /* parameters... (I) = Input, (O) = Output */
 870 
 871      dcl  user_io_ptr                   ptr                 parameter;          /* -> console_io structure...       (I) */
 872      dcl  io_queue_time                 fixed bin (71)      parameter;          /* UID of this I/O request...       (O) */
 873 
 874 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 875 
 876      oc_data_ptr = addr (oc_data$);                                             /* find oc_data...                      */
 877 
 878      if ^oc_data.in_service then do;                                            /* pass it to the log...                */
 879           call syserr (JUST_LOG, substr (user_io_ptr -> console_io.text, 1,
 880                multiply (user_io_ptr -> console_io.leng, 4, 17)));
 881           io_queue_time = clock ();                                             /* make it look as if successful...     */
 882           return;
 883      end;
 884 
 885      local_io = user_io_ptr -> console_io;                                      /* copy the I/O to our stack...         */
 886 
 887      if oc_data.write_q_full & ^local_io.read then do;                          /* no room at the Inn...                */
 888           oc_data.meters.write_q_full_cnt = oc_data.meters.write_q_full_cnt + 1;
 889           io_queue_time = 0;                                                    /* make them try again...               */
 890           return;
 891      end;
 892 
 893      call lock_oc_data ();                                                      /* get the lock, wire and mask...       */
 894 
 895      oc_entry_ptr = find_oc_entry ("");                                         /* locate the bootload console...       */
 896 
 897      if oc_data.mc_io_enabled then do;                                          /* Message Coordinator is handling I/O..*/
 898           local_time = 0;
 899           if ^local_io.read then do;                                            /* only pass on WRITEs...               */
 900                local_time = queue_console_io ();                                /* attempt to queue the I/O...          */
 901                if local_time ^= 0 then do;                                      /* if we were successful then do...     */
 902                     call bump_io_to_mc ((-local_time));                         /* send I/O to the MC...                */
 903                end;
 904           end;
 905           else local_time = clock ();                                           /* simulate successful queuing of READ..*/
 906           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
 907           io_queue_time = local_time;                                           /* copy argument...                     */
 908           return;                                                               /* all we can do...                     */
 909      end;
 910 
 911      if oc_entry_ptr = null then do;                                            /* no bootload console...               */
 912           call syserr (JUST_LOG, substr (user_io_ptr -> console_io.text, 1,
 913                multiply (user_io_ptr -> console_io.leng, 4, 17)));
 914           io_queue_time = clock ();                                             /* make it look as if successful...     */
 915           oc_data.in_service = false;
 916           return;
 917      end;
 918 
 919      if oc_entry.discard & ^local_io.read then do;                              /* if DISCARD condition and not a READ..*/
 920           if ^oc_entry.discarded then do;                                       /* haven't informed them yet...         */
 921                oc_entry.discarded = true;                                       /* note that we're informing them...    */
 922                call log_console_event (DISCARDED_OUTPUT, oc_data.io_ptr);       /* log it...                            */
 923           end;
 924           call unlock_oc_data ();                                               /* release lock, unwire and unmask...   */
 925           io_queue_time = -1;                                                   /* let caller know...                   */
 926           return;                                                               /* flush the output...                  */
 927      end;
 928 
 929      call process_io_status ();                                                 /* process any pending I/O status...    */
 930      call process_io ();                                                        /* process any pending I/O...           */
 931      local_time = queue_console_io ();                                          /* attempt to queue the I/O...          */
 932 
 933      call process_io ();                                                        /* attempt to start the I/O...          */
 934 
 935      call unlock_oc_data ();                                                    /* release lock, unwire and unmask...   */
 936 
 937      io_queue_time = local_time;                                                /* copy argument...                     */
 938 
 939      return;
 940 ^L
 941 reconfigure:
 942      entry (console_name_parm, reconfig_option_parm, code);
 943 
 944           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 945           /*                                                                                                  */
 946           /* This entry is called to explicitly reconfigure any configured console. The respective actions    */
 947           /* taken are controlled via the reconfig_option parameter and are described in                      */
 948           /* opc_reconfig_options.incl.pl1                                                                    */
 949           /*                                                                                                  */
 950           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
 951 
 952 /* parameters... (I) = Input, (O) = Output */
 953 
 954      dcl  console_name_parm             char      (4)       parameter;          /* console being reconfigured or MCA    */
 955                                                                                 /* number to unlock "M_xx"...       (I) */
 956      dcl  reconfig_option_parm          fixed bin (17)      parameter;          /* see opc_reconfig_options...      (I) */
 957 /*   dcl  code                          fixed bin (35)      parameter;             standard Multics error code...   (O) */
 958 
 959 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 960 
 961      entrypoint = "reconfigure";                                                /* set entrypoint name...               */
 962      audit_flag = "0"b;
 963      code = 0;                                                                  /* initialize it...                     */
 964      console_name = console_name_parm;                                          /* copy arguments into our stack...     */
 965      reconfig_option = reconfig_option_parm;
 966 
 967      oc_data_ptr = addr (oc_data$);                                             /* for unwired operations...            */
 968 
 969      if reconfig_option = NOP then do;                                          /* just return an error code...         */
 970           code = error_table_$no_operation;
 971      end;
 972 
 973      if reconfig_option = SUSPEND_CONSOLE_SERVICE then do;                      /* indicate no console service...       */
 974           oc_data.in_service = false;                                           /* and normal I/O...                    */
 975           return;
 976      end;
 977 
 978      if reconfig_option = ENABLE_CONSOLE_SERVICE then do;                       /* indicate no console service...       */
 979           oc_data.in_service = true;                                            /* and normal I/O...                    */
 980           return;
 981      end;
 982 
 983      if reconfig_option = SEND_MC_IO then do;                                   /* send I/O to MC...                    */
 984           oc_data.mc_io_enabled = true;
 985           return;
 986      end;
 987 
 988      if reconfig_option = CRASH_ON_CRF then do;                                 /* set the right flags...               */
 989           oc_data.crash_on_crf = true;
 990           return;
 991      end;
 992 
 993      if reconfig_option = RUN_ON_CRF then do;                                   /* set the right flags...               */
 994           oc_data.crash_on_crf = false;
 995           return;
 996      end;
 997 
 998      if reconfig_option = UNLOCK_MCA_INPUT then do;                             /* save mca# & reset console_name...    */
 999           mca_to_unlock = cv_dec_check_ (substr (console_name, 3, 2), err_code);
1000           if substr (console_name, 1, 2) ^= "M_" | err_code ^= 0 | mca_to_unlock < MIN_MCA | mca_to_unlock > MAX_MCA then do;
1001                code = error_table_$bad_arg;
1002                return;
1003           end;
1004           console_name = "";
1005      end;
1006 
1007      call lock_oc_data ();                                                      /* get lock, wire and mask...           */
1008 
1009      oc_entry_ptr = find_oc_entry (console_name);
1010      if oc_entry_ptr = null then do;                                            /* it is not...                         */
1011 null_ocep:
1012           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
1013           code = error_table_$dev_nt_assnd;
1014           return;
1015      end;
1016 
1017      if reconfig_option = RESET_CONSOLE then do;
1018           call reset_console ();                                                /* simple enough...                     */
1019           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
1020           return;
1021      end;
1022 
1023      if reconfig_option = MAKE_BOOTLOAD_CONSOLE then do;                        /* make specified console the bootload..*/
1024           call unassign_bootload_console ();                                    /* unassign the current bootload console*/
1025           if oc_entry_ptr ^= null then do;
1026                oc_entry.alternate = true;                                       /* make available to console recovery...*/
1027                oc_entry.io_device = false;
1028                call change_console_state ();
1029           end;
1030           call assign_bootload_console (console_name, err_code);                /* attach the console...                */
1031           if err_code ^= 0 then do;
1032                if old_console_name ^= "" then
1033                     call assign_bootload_console (old_console_name, (0));       /* reattach the old console...          */
1034                call unlock_oc_data ();                                          /* release lock, unwire, unmask...      */
1035                code = err_code;                                                 /* OK for page / seg faults...          */
1036                return;                                                          /* all we can do...                     */
1037           end;
1038           call report_error (BEEP, entrypoint, "Assigned ^a as the bootload console for ^a.", oc_entry.name, pds$process_group_id);
1039           call unlock_oc_data ();
1040           return;
1041      end;
1042 
1043      if reconfig_option = MAKE_ALTERNATE_CONSOLE then do;                       /* make specified console an alternate..*/
1044           if oc_entry.bootload_console then do;                                 /* not a good move...                   */
1045                call unlock_oc_data ();                                          /* release lock, unwire, unmask...      */
1046                code = error_table_$device_busy;                                 /* device is not available...           */
1047                return;
1048           end;
1049           oc_entry.alternate = true;                                            /* set the proper flags...              */
1050           oc_entry.io_device = false;
1051           oc_entry.inop_device = false;
1052           oc_entry.no_device = false;
1053           oc_entry.config_change = true;                                        /* note config change has occurred...   */
1054           call change_console_state ();
1055           call report_error (BEEP, entrypoint, "Assigned ^a as an alternate console for ^a.",
1056                oc_entry.name, pds$process_group_id);
1057           call unlock_oc_data ();
1058           return;
1059      end;
1060 
1061      if reconfig_option = MAKE_IO_DEVICE then do;                               /* make specified console an I/O device.*/
1062           if oc_entry.bootload_console then do;                                 /* not a good move...                   */
1063                if oc_data.err_event_cid ^= 0 then oc_data.mc_io_enabled = true; /* use Message Coordinator if we can... */
1064                else do;
1065                     if oc_data.crash_on_crf then call report_error (PANIC,      /* that was a dumb move...              */
1066                          entrypoint, "Bootload console deconfigured with CCRF set.");
1067                     else oc_data.in_service = false;                            /* just send it to the log...           */
1068                end;
1069                call unassign_bootload_console ();
1070                if oc_entry_ptr = null then do;                                  /* lost console, try to relocate...     */
1071                     oc_entry_ptr = find_oc_entry (console_name);
1072                     if oc_entry_ptr = null then goto null_ocep;                  /* can't locate.  Report error to caller */
1073                end;
1074           end;
1075           oc_entry.io_device = true;                                            /* set the proper flags...              */
1076           oc_entry.alternate = false;
1077           oc_entry.inop_device = false;
1078           oc_entry.no_device = false;
1079           oc_entry.config_change = true;                                        /* note config change has occurred...   */
1080           call change_console_state ();
1081           call report_error (BEEP, entrypoint, "Consigned ^a as an I/O device for ^a.",
1082                oc_entry.name, pds$process_group_id);
1083           call unlock_oc_data ();
1084           return;
1085      end;
1086 
1087      if reconfig_option = MAKE_INOP_DEVICE then do;                             /* make specified console an I/O device.*/
1088           if oc_entry.bootload_console then do;                                 /* not a good move...                   */
1089                if oc_data.err_event_cid ^= 0 then oc_data.mc_io_enabled = true; /* use Message Coordinator if we can... */
1090                else do;
1091                     if oc_data.crash_on_crf then call report_error (PANIC,      /* that was a dumb move...              */
1092                          entrypoint, "Bootload console deconfigured with CCRF set.");
1093                     else oc_data.in_service = false;                            /* just send it to the log...           */
1094                end;
1095                call unassign_bootload_console ();
1096                if oc_entry_ptr = null then do;                                  /* lost console, try to relocate...     */
1097                     oc_entry_ptr = find_oc_entry (console_name);
1098                     if oc_entry_ptr = null then goto null_ocep;                  /* can't locate.  Report error to caller */
1099                end;
1100           end;
1101           oc_entry.inop_device = true;                                          /* set the proper flags...              */
1102           oc_entry.io_device = false;
1103           oc_entry.alternate = false;
1104           oc_entry.no_device = false;
1105           oc_entry.config_change = true;                                        /* note config change has occurred...   */
1106           call change_console_state ();
1107           call report_error (BEEP, entrypoint, "Marked ^a as an inoperative device for ^a.",
1108                oc_entry.name, pds$process_group_id);
1109           call unlock_oc_data ();
1110           return;
1111      end;
1112 
1113      if reconfig_option = MAKE_UNAVAILABLE then do;                             /* delete console from configuration... */
1114           if oc_entry.bootload_console then do;                                 /* can't go directly from "on" to "off".*/
1115                call unlock_oc_data ();                                          /* relinquish lock, unwire, unmask...   */
1116                code = error_table_$resource_not_free;
1117                return;
1118           end;
1119           else do;
1120                oc_entry.inop_device = false;                                    /* set the proper flags...              */
1121                oc_entry.io_device = false;
1122                oc_entry.alternate = false;
1123                oc_entry.no_device = true;
1124                oc_entry.config_change = true;                                   /* note config change has occurred...   */
1125                call change_console_state ();
1126                call unlock_oc_data ();
1127                return;
1128           end;
1129      end;
1130 
1131      if reconfig_option = LOCK_MCA_INPUT |
1132           reconfig_option = UNLOCK_MCA_INPUT then do;
1133           audit_flag = (sys_info$collection_1_phase = SERVICE_INITIALIZATION);
1134           call lock_unlock_mca ();                                              /* do the lock or unlock...             */
1135           if ^mca_lock_unlock_success then code = error_table_$action_not_performed;
1136           call unlock_oc_data ();                                               /* release lock, unwire, unmask...      */
1137           return;
1138      end;
1139 
1140      call unlock_oc_data ();                                                    /* should never really get here...      */
1141 
1142      return;
1143 
1144 ^L
1145 set_prompt:
1146      entry (new_prompt_parm);
1147 
1148           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1149           /*                                                                                                  */
1150           /* Entry to set the prompt. The prompt can be set to any 6 character string. If the prompt          */
1151           /* specified is "" then the default of "M->" will be set.                                           */
1152           /*                                                                                                  */
1153           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1154 
1155 /* parameters... (all input) */
1156 
1157      dcl  new_prompt_parm               char      (8)       parameter;          /* new prompt string...             (I) */
1158 
1159 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1160 
1161      new_prompt = new_prompt_parm;                                              /* copy arguments...                    */
1162 
1163      call lock_oc_data ();                                                      /* get lock, wire and mask...           */
1164 
1165      if rtrim (new_prompt) = "" then new_prompt = "M->";                        /* default case...                      */
1166      else new_prompt = rtrim (substr (new_prompt, 1, 6)) || "->";               /* format the prompt...                 */
1167 
1168      oc_data.prompt = new_prompt;                                               /* install it...                        */
1169 
1170      call unlock_oc_data ();                                                    /* relinquish lock, unwire, unmask...   */
1171 
1172      return;
1173 ^L
1174 BAIL_OUT:
1175           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1176           /*                                                                                                  */
1177           /*  BAIL_OUT is used as a non-local goto from process_io when it is found that there is             */
1178           /* no current console.                                                                              */
1179           /*                                                                                                  */
1180           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1181 
1182      if ^stacq (oc_data.lock, ""b, pds$process_id) then do;                     /* clear lock if it is ours...          */
1183           if oc_data.lock ^= ""b then                                           /* not ours, if not free crash...       */
1184                call report_error (PANIC, "unlock_oc_data", "Lock not mine.");
1185      end;
1186 
1187      call unwire_and_unmask;                                                    /* unwire stack, accept interrupts...   */
1188 
1189      return;
1190 ^L
1191 
1192 assign_bootload_console:
1193      proc (name, error_code);
1194 
1195 
1196           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1197           /*                                                                                                  */
1198           /* Internal procedure to assign the specified console as the bootload console. When this procedure  */
1199           /* returns all oc_entry flags for the assigned console are correctly set, the bootload console      */
1200           /* entry index oc_data.bootload_console_idx is correctly set and the oc_data.in_service flag is     */
1201           /* set.                                                                                             */
1202           /*                                                                                                  */
1203           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1204 
1205 
1206 /* parameters... (I) = Input, (O) = Output */
1207 
1208      dcl  name                          char      (4)       aligned             /* of the console to activate...    (I) */
1209                                                             parameter;
1210      dcl  error_code                    fixed bin (35)      parameter;          /* standard Multics error code...   (O) */
1211 
1212 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1213 
1214      oc_entry_ptr = find_oc_entry (name);                                       /* check to see if console active...    */
1215      if oc_entry_ptr = null then do;                                            /* specified console not active...      */
1216           error_code = error_table_$device_not_active;
1217           return;
1218      end;
1219 
1220      call io_manager$assign (oc_entry.device_idx, oc_entry.channel,             /* attach this console...               */
1221           ocdcm_$interrupt_handler, (0), oc_data.status_ptr, error_code);
1222      if error_code ^= 0 then return;
1223 
1224      oc_entry.assigned = true;
1225      oc_data.bootload_console_idx = oc_entry.opc_idx;                           /* note this is the bootload console... */
1226      oc_entry.bootload_console = true;                                          /* and flag it...                       */
1227      oc_entry.alternate = false;                                                /* make sure things are consistent...   */
1228      oc_entry.io_device = false;
1229      oc_entry.inop_device = false;
1230      oc_entry.no_device = false;
1231      oc_entry.retry_cnt = 0;                                                    /* reset the I/O retry count...         */
1232      oc_entry.config_change = true;                                             /* note config change has occurred...   */
1233      call change_console_state ();
1234 
1235      oc_data.in_service = true;                                                 /* we can start processing I/O...       */
1236      if oc_data.mc_io_enabled then do;                                          /* tell MC that we are taking over...   */
1237           call pxss$ring_0_wakeup (oc_data.err_event_pid, oc_data.err_event_cid, 0, (0));
1238           oc_data.mc_io_enabled = false;                                        /* suspend MC I/O...                    */
1239      end;
1240 
1241      return;
1242 
1243 end assign_bootload_console;
1244 ^L
1245 bump_io_to_mc:
1246      proc (io_uid);
1247 
1248 
1249           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1250           /*                                                                                                  */
1251           /* Internal procedure to inform the Message Coordinator that there is a message that it should      */
1252           /* handle. The Message Coordinator will be sent a message containing the UID of the message to be   */
1253           /* processed by it. This io_uid is a syserr sequence number for syserr messages or the negated      */
1254           /* time that the I/O was queued for non-syserr traffic.                                             */
1255           /*                                                                                                  */
1256           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1257 
1258 /* parameters... (I) = Input, (O) = Output */
1259 
1260      dcl  io_uid                        fixed bin (71)      parameter;          /* used by the MC to get this I/O...(I) */
1261 
1262 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1263 
1264      if oc_data.err_event_cid ^= 0 then do;                                     /* if MC has placed process ID here...  */
1265           call pxss$ring_0_wakeup (oc_data.err_event_pid, oc_data.err_event_cid,/* tell MC about the I/O...             */
1266                io_uid, (0));
1267           if io_uid > 0 then call log_console_event (SENT_MC_PRIORITY_IO, addr (oc_data.priority_io));
1268           else call log_console_event (SENT_MC_IO, console_io_ptr);
1269           return;
1270      end;
1271      else do;                                                                   /* Message Coordinator disappeared...   */
1272           if oc_data.crash_on_crf | sys_info$collection_1_phase < SERVICE_INITIALIZATION then
1273                                                                                 /* sorry, MUST crash...                 */
1274                call unlock_oc_data ();                                          /* relinquish lock, unwire, unmask...   */
1275                call syserr_real$panic ("ocdcm_ (bump_io_to_mc): Console recovery failure.");
1276           oc_data.mc_io_enabled = false;
1277           oc_data.in_service = false;
1278           call report_error (JUST_LOG, "bump_io_to_mc", "Message Coordinator failure.");
1279           return;
1280      end;
1281 
1282 end bump_io_to_mc;
1283 ^L
1284 change_console_state:
1285      proc ();
1286 
1287           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1288           /*                                                                                                  */
1289           /* Internal entry to change the state of a console as listed in the config file.  The config file   */
1290           /* is wired so but the conf partition must be paged. In order to write the partition we will have   */
1291           /* to call config_$update when were unwired and unmasked. This is not yet implemented.              */
1292           /*                                                                                                  */
1293           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1294 
1295      do idx = 1 to MAX_OPC_CNT;                                                 /* check all consoles for changes...    */
1296           if oc_data.opc (idx).active then do;                                  /* only check active entries...         */
1297                if oc_data.opc (idx).config_change then do;                      /* found a config change...             */
1298                     oc_data.opc (idx).config_change = false;                    /* reset change indicator...            */
1299                     if oc_data.opc (idx).bootload_console then new_state = "on";
1300                     else if oc_data.opc (idx).alternate then new_state = "alt";
1301                     else if oc_data.opc (idx).io_device then new_state = "io";
1302                     else if oc_data.opc (idx).inop_device then new_state = "inop";
1303                     else if oc_data.opc (idx).no_device then new_state = "off";
1304                     prph_opc_cardp = null;                                      /* start ath the beginning of the file..*/
1305                     console_found = false;                                      /* reset loop terminator...             */
1306                     do while (^console_found);                                  /* process all "opc" "prph" cards...    */
1307                          call config_$find ("prph", prph_opc_cardp);            /* find a "prph" card...                */
1308                          if prph_opc_cardp = null then console_found = true;    /* no more prph cards...                */
1309                          else do;
1310                               if prph_opc_card.name = oc_data (idx).name then do;    /* found it...                     */
1311                                    prph_opc_card.state = new_state;             /* update the new state...              */
1312                                    console_found = true;                        /* signal end of loop...                */
1313                               end;
1314                          end;
1315                     end;
1316                end;
1317           end;
1318      end;
1319 
1320      return;                                                                    /* done...                              */
1321 
1322 end change_console_state;
1323 ^L
1324 console_recovery:
1325      proc ();
1326 
1327           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1328           /*                                                                                                  */
1329           /* Internal procedure to attempt console failure recovery. This procedure takes the following       */
1330           /* actions:                                                                                         */
1331           /*                                                                                                  */
1332           /*        1.) Attempt to find an alternate console making it the bootload if one is found.          */
1333           /*                                                                                                  */
1334           /*        2.) If no alternates exist attempt to set up switches so that all I/O is bumped to the    */
1335           /*        Message Coordinator if one exists.                                                        */
1336           /*                                                                                                  */
1337           /*        3.) If no Message Coordinator exists then take the following actions with regards to the  */
1338           /*        CCRF parm specified in the config file:                                                   */
1339           /*                                                                                                  */
1340           /*                  a.) If CCRF was specified then crash.                                           */
1341           /*                  b.) If CCRF was not specified setup switches so that all I/O is bumped to the   */
1342           /*                  syserr_log.                                                                     */
1343           /*                                                                                                  */
1344           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1345 
1346      entrypoint = "console_recovery";                                           /* set entrypoint name...               */
1347 
1348      if oc_data.must_have_console then do;                                      /* ensure we have a real console...     */
1349           call poll_for_console ();                                             /* it will find one...                  */
1350           oc_data.must_have_console = false;                                    /* reset flag...                        */
1351           return;                                                               /* done all that was required...        */
1352      end;
1353 
1354      error_msg = "";                                                            /* clear error message...               */
1355 
1356      call unassign_bootload_console ();                                         /* unassign the bootload console...     */
1357 
1358      if oc_entry_ptr ^= null then do;                                           /* if unassign_bootload_console found it*/
1359           oc_entry.io_device = false;                                           /* this was set by unassign_bootload... */
1360           oc_entry.inop_device = true;                                          /* mark it inoperative...               */
1361           oc_entry.config_change = true;                                        /* note config change occurred...       */
1362      end;
1363 
1364      found = false;                                                             /* initialize loop terminator...        */
1365 
1366      do idx = 1 to oc_data.console_cnt while (^found);                          /* locate an alternate console...       */
1367           oc_entry_ptr = addr (oc_data.opc (idx));                              /* find the console entry...            */
1368           if oc_entry.alternate then do;                                        /* found one...                         */
1369                found = true;                                                    /* signal loop termination...           */
1370                call assign_bootload_console (oc_entry.name, err_code);          /* assign it...                         */
1371                if err_code = 0 then do;                                         /* assignment successful...             */
1372                     call ioa_$rsnnl ("Console inoperative, alternate ^a assigned.",
1373                          error_msg, 0, oc_entry.name);
1374                end;
1375                else do;                                                         /* assignment failed...                 */
1376                     call ioa_$rsnnl ("Console failed, assignment of alternate ^a failed.",
1377                          error_msg, 0, oc_entry.name);
1378                     oc_entry.inop_device = true;                                /* change its state...                  */
1379                     oc_entry.alternate = false;
1380                     oc_entry.config_change = true;                              /* note config change occurred...       */
1381                     found = false;                                              /* continue search...                   */
1382                end;
1383           end;
1384      end;
1385 
1386      if ^found then do;                                                         /* no alternates, MC or CRASH?...       */
1387           if oc_data.err_event_cid = 0 then do;                                 /* no Message Coordinator...            */
1388                if oc_data.crash_on_crf | sys_info$collection_1_phase < SERVICE_INITIALIZATION then do;
1389                                                                                 /* no choice but to crash...            */
1390                     call report_error (PANIC, entrypoint, "Console recovery failure.");
1391                end;
1392                oc_data.in_service = false;                                      /* next time we'll know...              */
1393                oc_data.mc_io_enabled = false;                                   /* ditto...                             */
1394           end;
1395           else oc_data.mc_io_enabled = true;                                    /* flag MC is in control...             */
1396 
1397           if oc_data.mc_io_enabled then do;
1398                error_msg = "Console inoperative, no alternates available.";     /* let 'em know...                      */
1399           end;
1400           else do;
1401                error_msg = "Console inoperative, no alternates, no MC.";
1402                console_io_ptr = oc_data.io_ptr;
1403                console_io.in_progress = false;                                  /* reset failed I/O to prevent MYLOCK...*/
1404                oc_data.priority_io.completed = true;                            /* mark this so priority_io will not loop on it forever. */
1405           end;
1406      end;
1407 
1408      call change_console_state ();                                              /* show any changes that may have occured */
1409 
1410      if error_msg ^= "" then call report_error (JUST_LOG, entrypoint, error_msg);
1411 
1412      return;                                                                    /* done...                              */
1413 
1414 end console_recovery;
1415 ^L
1416 console_responds_to_bell:
1417      proc (console_idx) returns (bit (1));
1418 
1419           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1420           /*                                                                                                  */
1421           /* Internal procedure that sends a bell to the the specified console and returns true if the I/O    */
1422           /* succeeds.                                                                                        */
1423           /*                                                                                                  */
1424           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1425 
1426 /* parameters... (all input) */
1427 
1428      dcl console_idx                    fixed bin (17)      parameter;          /* index of the console to test...      */
1429 
1430 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1431 
1432 
1433      oc_entry_ptr = addr (oc_data.opc (console_idx));                           /* overlay it...                        */
1434      oc_entry.dcw_list_idx = ALERT_DCW;                                         /* we'll test by sending a bell...      */
1435      call initiate_io ();                                                       /* send it...                           */
1436      do while (^io_status.t);                                                   /* wait for termination...              */
1437      end;
1438 
1439      if io_status_overlay.major = "00"b3 then return (true);
1440      else return (false);
1441 
1442 end console_responds_to_bell;
1443 ^L
1444 console_in_imu:
1445      proc () returns (bit (1));
1446 
1447 
1448           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1449           /*                                                                                                  */
1450           /* Internal function that returns true if the specified console is located in an IMU style IOM.     */
1451           /*                                                                                                  */
1452           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1453 
1454      iom_cardp = null;
1455      call config_$find ("iom", iom_cardp);
1456      do while (iom_cardp ^= null);
1457           if iom_card.model = "imu" | iom_card.model = "iioc" then do;          /* found an IMU...            */
1458                if iom_card.tag = prph_opc_card.iom then return (true);          /* console in this IMU...     */
1459           end;
1460           call config_$find ("iom", iom_cardp);                                 /* find next iom card...      */
1461      end;
1462      return (false);                                                            /* console not in an IMU...   */
1463 end console_in_imu;
1464 ^L
1465 fill_oc_entry:
1466      proc (oc_data_struct_ptr, console_entry_idx, opc_card_ptr, oc_entry_ptr_arg);
1467 
1468 
1469           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1470           /*                                                                                                  */
1471           /* Internal procedure that fills in an opc entry describing a configured operator's console. This   */
1472           /* procedure builds the DCW list for the device. This list is composed IDCWs describing a device    */
1473           /* instruction and optionally a DCW describing a data transfer.                                     */
1474           /*                                                                                                  */
1475           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1476 
1477 /* parameters... (I) = Input, (O) = Output */
1478 
1479      dcl  oc_data_struct_ptr            ptr                 parameter;          /* -> oc_data...                    (I) */
1480      dcl  console_entry_idx             fixed bin (17)      unaligned
1481                                                             parameter,          /* index into the opc console array.(I) */
1482           opc_card_ptr                  ptr                 parameter,          /* -> "opcx" "prph" card...         (I) */
1483           oc_entry_ptr_arg              ptr                 parameter;          /* -> oc_entry...                   (O) */
1484 
1485 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1486 
1487      oc_data_ptr = oc_data_struct_ptr;                                          /* copy arguments...                    */
1488      prph_opc_cardp = opc_card_ptr;
1489 
1490      oc_entry_ptr = addr (oc_data.opc (console_entry_idx));                     /* entry to fill...                     */
1491      oc_entry_ptr_arg = oc_entry_ptr;                                           /* returned to caller...                */
1492 
1493      unspec (oc_entry) = ""b;                                                   /* just to be safe...                   */
1494 
1495      if prph_opc_card.name < "opca" | prph_opc_card.name > "opcz" then do;
1496           call report_error (BEEP, "Illegal console name (^a) specified. It will be ignored.", prph_opc_card.name);
1497           return;
1498      end;
1499 
1500      oc_entry.active = true;                                                    /* mark the console as active...        */
1501 
1502      if substr (prph_opc_card.mask, 1, 4) = "mask" then oc_entry.flags.read_unechoed_option = false;
1503      else oc_entry.flags.read_unechoed_option = true;
1504 
1505      oc_entry.name = prph_opc_card.name;                                        /* so we can find it later...           */
1506      oc_entry.opc_idx = console_entry_idx;                                      /* note our opc array index...          */
1507      oc_entry.imu = console_in_imu ();                                          /* is console located in an IMU??       */
1508 
1509      if substr (prph_opc_card.state, 1, 2) = "on" then do;
1510           do idx = 1 to oc_data.console_cnt while (oc_data.opc (idx).bootload_console = false);
1511           end;
1512           if idx > oc_data.console_cnt then do;                                 /* if no previous bootload console...   */
1513                oc_entry.bootload_console = true;                                /* mark console as bootload...          */
1514           end;
1515           else do;                                                              /* no multiple bootload consoles...     */
1516                call report_error (BEEP, entrypoint, "Changing state of ^a to alt.", oc_entry.name);
1517                prph_opc_card.state = "alt";                                     /* change the consoles status...        */
1518                oc_entry.alternate = true;
1519           end;
1520      end;
1521 
1522      else if substr (prph_opc_card.state, 1, 3) = "alt" then do;                /* flag this as an alternate console... */
1523           oc_entry.alternate = true;
1524      end;
1525 
1526      else if prph_opc_card.state = "inop" then do;                              /* this console is inoperative...       */
1527           oc_entry.inop_device = true;
1528      end;
1529 
1530      else if substr (prph_opc_card.state, 1, 2) = "io" then do;                 /* this console is not to be used...    */
1531           oc_entry.io_device = true;
1532      end;
1533 
1534      else if substr (prph_opc_card.state, 1, 3) = "off" then do;                /* this console deconfigured...         */
1535           oc_entry.no_device = true;
1536      end;
1537 
1538      else do;                                                                   /* unknown state...                     */
1539           call report_error (BEEP, entrypoint, "Invalid state of ^a for console ^a.",
1540                prph_opc_card.state, prph_opc_card.name);
1541           call report_error (ANNOUNCE, entrypoint, "This console will not be configured.");
1542           unspec (oc_entry) = ""b;                                              /* undo what we have done...            */
1543           return;
1544      end;
1545 
1546      oc_entry.line_leng = prph_opc_card.line_leng;                              /* set console line length...           */
1547 
1548      console_data_ptr = addr (config_data_$console_model_names);                /* get console data for verification... */
1549 
1550      found = false;                                                             /* initialize it...                     */
1551 
1552      do idx = 1 to console_data.count while (^found);                           /* find our console...                  */
1553           if console_data.model (idx) = prph_opc_card.model then do;
1554                found = true;
1555                oc_entry.model = prph_opc_card.model;
1556                if substr (console_data.io_type (idx), 1, 3) = "pcw" then do;
1557                     oc_entry.pcw_io = true;
1558                     oc_entry.flags.read_unechoed_option = false;                /* CSU6001 does not have this option... */
1559                end;
1560           end;
1561      end;
1562 
1563      if ^found then do;
1564           call report_error (BEEP, entrypoint, "Unknown model, ^i, specified for ^a. It will not be configured.",
1565                prph_opc_card.model, oc_entry.name);
1566           unspec (oc_entry) = ""b;                                              /* undo what we've done...              */
1567           return;                                                               /* best we can do...                    */
1568      end;
1569 
1570      call io_chnl_util$iom_to_name ((prph_opc_card.iom), (prph_opc_card.chan),  /* get this console's channel ID...     */
1571           oc_entry.channel, err_code);
1572 
1573      if err_code ^= 0 then do;
1574           call report_error (PANIC, entrypoint, "Invalid channel specified for ^a.", oc_entry.name);
1575      end;
1576      idcwp = addr (oc_entry.dcw_list (WRITE_DCW));                              /* WRITE IDCW...                        */
1577      idcw.command = "33"b3;                                                     /* write ASCII command...               */
1578      idcw.code = "111"b;                                                        /* indicates a PCW...                   */
1579 
1580      idcwp = addr (oc_entry.dcw_list (READ_DCW));                               /* READ IDCW...                         */
1581      idcw.command = "23"b3;                                                     /* read ASCII command...                */
1582      idcw.code = "111"b;                                                        /* indicates a PCW...                   */
1583      dcwp = addr (oc_entry.dcw_list (READ_DCW + 1));                            /* get data word...                     */
1584      dcw.tally = bit (binary (divide (MAX_IO_LENGTH, 4, 17), 12));              /* maximum for READ ops...              */
1585 
1586      idcwp = addr (oc_entry.dcw_list (READ_UNECHOED_DCW));                      /* READ_UNECHOED IDCW...                */
1587      idcw.command = "43"b3;                                                     /* read unechoed ASCII command...       */
1588      idcw.code = "111"b;                                                        /* indicates a PCW...                   */
1589      dcwp = addr (oc_entry.dcw_list (READ_UNECHOED_DCW + 1));                   /* get data word...                     */
1590      dcw.tally = bit (binary (divide (MAX_IO_LENGTH, 4, 17), 12));              /* maximum for READ ops...              */
1591 
1592      idcwp = addr (oc_entry.dcw_list (RESET_DCW));                              /* READ_ID IDCW...                      */
1593      idcw.command = "57"b3;                                                     /* so I lied...                         */
1594      idcw.code = "111"b;                                                        /* indicates PCW...                     */
1595      idcw.chan_cmd = "02"b3;                                                    /* indicate "non-data" type transfer... */
1596      idcw.count = "01"b3;                                                       /* issue only once...                   */
1597 
1598      idcwp = addr (oc_entry.dcw_list (ALERT_DCW));                              /* WRITE_ALERT IDCW...                  */
1599      idcw.command = "51"b3;                                                     /* write_alert command...               */
1600      idcw.code = "111"b;                                                        /* indicates PCW...                     */
1601      idcw.chan_cmd = "02"b3;                                                    /* indicate "non-data" type transfer... */
1602      idcw.count = "01"b3;                                                       /* issue only once...                   */
1603 
1604      oc_entry.dcw_list (NEWLINE_DCW) = oc_entry.dcw_list (WRITE_DCW);           /* put IOM in WRITE mode...             */
1605      dcwp = addr (oc_entry.dcw_list (NEWLINE_DCW + 1));                         /* next in list describes what to write.*/
1606      dcw.address = bit (binary (wordno (addr (oc_data.write_return))            /* -> string to write...                */
1607           + oc_data.abs_addr, 18));
1608      dcw.tally = "0001"b3;                                                      /* tally = number of words to transfer..*/
1609 
1610      oc_entry.dcw_list (PROMPT_DCW) = oc_entry.dcw_list (WRITE_DCW);            /* put IOM in write mode...             */
1611      dcwp = addr (oc_entry.dcw_list (PROMPT_DCW + 1));                          /* next in list describes what to write.*/
1612      dcw.address = bit (binary (wordno (addr (oc_data.prompt))                  /* -> string to write...                */
1613           + oc_data.abs_addr, 18));
1614      dcw.tally = "0002"b3;                                                      /* tally = number of words to transfer..*/
1615 
1616      oc_entry.dcw_list (DISCARD_DCW) = oc_entry.dcw_list (WRITE_DCW);           /* put IOM in WRITE mode...             */
1617      dcwp = addr (oc_entry.dcw_list (DISCARD_DCW + 1));                         /* next in list describes what to write.*/
1618      dcw.address = bit (binary (wordno (addr (oc_data.discard_notice))          /* -> string to write...                */
1619           + oc_data.abs_addr, 18));
1620      dcw.tally = "0006"b3;                                                      /* tally = number of words to transfer..*/
1621 
1622      idcwp = addr (oc_entry.dcw_list (LOCK_MCA_DCW));                           /* LOCK MCA IDCW...                     */
1623      idcw.command = "60"b3;                                                     /* lock command...                      */
1624      idcw.code = "111"b;                                                        /* indicates IDCW...                    */
1625      idcw.chan_cmd = "02"b3;                                                    /* indicate "non-data" type transfer... */
1626      idcw.count = "00"b3;                                                       /* Not examined by console...           */
1627 
1628      idcwp = addr (oc_entry.dcw_list (UNLOCK_MCA_DCW));                         /* UNLOCK MCA IDCW...                   */
1629      idcw.command = "63"b3;                                                     /* unlock command...                    */
1630      idcw.code = "111"b;                                                        /* indicates IDCW...                    */
1631      idcw.chan_cmd = "02"b3;                                                    /* indicate "non-data" type transfer... */
1632      idcw.count = "00"b3;                                                       /* Set MCA# to 00...                    */
1633 
1634      oc_entry.prompt = true;                                                    /* turn on prompting for all consoles...*/
1635 
1636      return;                                                                    /* all done...                          */
1637 
1638 end fill_oc_entry;
1639 ^L
1640 find_oc_entry:
1641      proc (opc_name) returns (ptr);
1642 
1643 
1644           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1645           /*                                                                                                  */
1646           /* Internal function that returns a pointer to the specified console. If the opc_name is "" then a  */
1647           /* pointer to the bootload console is returned. If the specified console is not configured a null   */
1648           /* pointer is returned.                                                                             */
1649           /*                                                                                                  */
1650           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1651 
1652 /* parameters... (I) = Input, (O) = Output */
1653 
1654      dcl  opc_name                      char      (4)       aligned             /* name of the console...           (I) */
1655                                                             parameter;
1656 
1657 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1658 
1659      oc_data_ptr = addr (oc_data$);                                             /* just in case we don't know...        */
1660 
1661      if opc_name = "" then do;                                                  /* find the bootload console...         */
1662           if oc_data.bootload_console_idx = 0 then return (null);               /* no bootload console assigned...      */
1663           return (addr (oc_data.opc (oc_data.bootload_console_idx)));           /* return the requested pointer...      */
1664      end;
1665 
1666      do idx = 1 to oc_data.console_cnt;                                         /* locate the console...                */
1667           if oc_data.opc (idx).name = opc_name then do;                         /* found it...                          */
1668                return (addr (oc_data.opc (idx)));
1669           end;
1670      end;
1671 
1672      return (null);                                                             /* console not configured...            */
1673 
1674 end find_oc_entry;
1675 ^L
1676 initiate_io:
1677      proc ();
1678 
1679           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1680           /*                                                                                                  */
1681           /* Internal procedure to initiate the I/O indicated by the DCW list index in the oc_entry.          */
1682           /*                                                                                                  */
1683           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1684 
1685      oc_entry.io_time = clock ();                                               /* save the time we started the I/O...  */
1686      oc_entry.io_in_progress = true;                                            /* indicate console is busy...          */
1687 
1688      if oc_entry.dcw_list_idx = READ_DCW |                                      /* if we're doing a READ or...          */
1689           oc_entry.dcw_list_idx = READ_UNECHOED_DCW |                           /* or a READ_UNECHOED...                */
1690           oc_entry.dcw_list_idx = WRITE_DCW |                                   /* a WRITE                              */
1691           oc_entry.dcw_list_idx = PROMPT_DCW |                                  /* or a PROMPT                          */
1692           oc_entry.dcw_list_idx = ALERT_DCW then do;                            /* or an ALERT then do...               */
1693           oc_data.io_ptr = console_io_ptr;                                      /* save a pointer to the I/O...         */
1694           console_io.console = oc_data.opc (oc_data.bootload_console_idx).name; /* note what console the I/O went to... */
1695      end;
1696 
1697      iom_args.chx = oc_entry.device_idx;                                        /* setup I/O manager args...            */
1698 
1699      if oc_entry.pcw_io then do;                                                /* for EMC style consoles...            */
1700           iom_args.pcw = oc_entry.dcw_list (oc_entry.dcw_list_idx);
1701           iom_args.listp = addr (oc_entry.dcw_list (oc_entry.dcw_list_idx + 1));
1702      end;
1703 
1704      else do;                                                                   /* for new style consoles...            */
1705           iom_args.pcw = false;
1706           iom_args.listp = addr (oc_entry.dcw_list (oc_entry.dcw_list_idx));
1707      end;
1708 
1709      iom_args.ptp = null;                                                       /* unused...                            */
1710 
1711      call io_manager$connect_abs (iom_args);                                    /* initiate the I/O...                  */
1712 
1713      return;
1714 
1715 end initiate_io;
1716 ^L
1717 lock_oc_data:
1718      proc ();
1719 
1720           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1721           /*                                                                                                  */
1722           /* Internal procedure to wire our stack, mask interrupts and then lock oc_data. There are two       */
1723           /* possible errors during this process. The first is that the value of the lock is already set to   */
1724           /* our process_id. This is the MYLOCK error and will result in a system crash. The second possible  */
1725           /* error is that the lock cannot be had within a reasonable amount of time. In this case we will    */
1726           /* also crash the system.                                                                           */
1727           /*                                                                                                  */
1728           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1729 
1730      oc_data_ptr = addr (oc_data$);                                             /* locate oc_data...                    */
1731 
1732      if oc_data.lock = pds$process_id then do;                                  /* MYLOCK error...                      */
1733           call report_error (PANIC, "lock_oc_data", "Mylock error.");           /* crash system, store flagbox message..*/
1734      end;
1735 
1736      call wire_and_mask;                                                        /* wire our stack and mask interrupts...*/
1737 
1738      time_lock_expires = clock () + oc_data.max_computed_io_time;               /* setup spin lock timeout...           */
1739 
1740      do while (clock () < time_lock_expires);                                   /* loop on the lock...                  */
1741           if stac (addr (oc_data.lock), pds$process_id) then return;            /* if got lock then return...           */
1742      end;
1743 
1744      call report_error (PANIC, "lock_oc_data", "Lock wait timer expired.");     /* timer expired, crash the system...   */
1745 
1746 end lock_oc_data;
1747 ^L
1748 lock_unlock_mca:
1749      proc ();
1750 
1751           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1752           /*                                                                                                  */
1753           /* Internal procedure to either lock (disable) or unlock (enable) communication through the console */
1754           /* to the MCA (Maintenace Channel Adapter), located in an IMU.  In order to lock or unlock the      */
1755           /* input an I/O must be sent to the "Master" MCA console, but since we have no sure way of knowing  */
1756           /* which console in the "Master" we issue an I/O to every configured console. This way we make sure */
1757           /* that the interface to the MCA will be locked or unlocked. However if a site does not configure   */
1758           /* the console that is running as the master, then there is nothing we can do.                      */
1759           /*                                                                                                  */
1760           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1761 
1762      bootload_console_name = oc_entry.name;                                     /* need for setting later...            */
1763      save_status_ptr = oc_data.status_ptr;                                      /* ditto...                             */
1764      ad_code = 0;
1765      mca_lock_unlock_success = false;
1766 
1767      do while (oc_entry.io_in_progress);                                        /* quies the console...                 */
1768           call process_io_status ();
1769      end;
1770 
1771      do idx = 1 to oc_data.console_cnt;                                         /* scan through all consoles...         */
1772           if oc_data.opc (idx).imu &                                            /* is console on an IMU                 */
1773                ^oc_data.opc (idx).inop_device &                                 /* and not broken                       */
1774                ^oc_data.opc (idx).no_device &                                   /* and not off                          */
1775                ^oc_data.opc (idx).io_device then do;                            /* and not being used as an IO device.  */
1776                oc_entry_ptr = addr (oc_data.opc (idx));
1777                must_unassign = false;
1778                if ^oc_entry.assigned then do;                                   /* non-bootload console                 */
1779                     call io_manager$assign (oc_entry.device_idx, oc_entry.channel,
1780                          ocdcm_$interrupt_handler, (0), oc_data.status_ptr, err_code);
1781                     if err_code ^= 0 then do;
1782                          ad_code, code = err_code;
1783                          goto locate_bootload;
1784                     end;
1785                     oc_entry.assigned = true;
1786                     oc_entry.io_in_progress = false;
1787                     must_unassign = true;
1788                end;
1789                else oc_data.status_ptr = save_status_ptr;                       /* bootload console needs its ptr...    */
1790 
1791                if reconfig_option = LOCK_MCA_INPUT then do;
1792                     oc_entry.dcw_list_idx = LOCK_MCA_DCW;
1793                     call log_console_event (LOCK_MCA_IO, null);
1794                end;
1795                else do;
1796                     idcwp = addr (oc_entry.dcw_list (UNLOCK_MCA_DCW));
1797                     idcw.count =  bit (binary (mca_to_unlock, 6));
1798                     oc_entry.dcw_list_idx = UNLOCK_MCA_DCW;
1799                     call log_console_event (UNLOCK_MCA_IO, null);
1800                end;
1801                call initiate_io ();
1802 
1803                do while (oc_entry.io_in_progress);                              /* wait for I/O to finish...            */
1804                     call process_io_status ();
1805                     if console_io_timeout then do;
1806                          ad_code = error_table_$timeout;
1807                          call report_error (JUST_LOG, entrypoint, "Timeout executing MCA^[(^2.3b)^;^s^] ^[LOCK^;UNLOCK^] on ^a for ^a.",
1808                               (reconfig_option = UNLOCK_MCA_INPUT), bit (binary (mca_to_unlock, 6)),
1809                               (reconfig_option = LOCK_MCA_INPUT), oc_entry.name, pds$process_group_id);
1810                     end;
1811                     oc_entry_ptr = addr (oc_data.opc (idx));                    /* make sure we stay with right one...  */
1812                end;
1813 
1814                if oc_entry.status_word = "400002000000"b3 then do;
1815                     call report_error (JUST_LOG, entrypoint, "MCA^[(^2.3b)^;^s^] input through ^a, ^[dis^;en^]abled by ^a.",
1816                          (reconfig_option = UNLOCK_MCA_INPUT), bit (binary (mca_to_unlock, 6)),
1817                          oc_entry.name, (reconfig_option = LOCK_MCA_INPUT), pds$process_group_id);
1818                     oc_entry_ptr = addr (oc_data.opc (idx));                    /* switch back to proper console...     */
1819                     mca_lock_unlock_success = true;
1820                end;
1821 
1822                if must_unassign then do;
1823                     call io_manager$unassign (oc_entry.device_idx, (0));
1824                     oc_entry.assigned = false;
1825                     oc_entry.io_in_progress = false;
1826                     oc_entry_ptr = null;
1827                end;
1828           end;
1829      end;
1830 
1831 locate_bootload:
1832      if audit_flag then do;                                                     /* Not at BCE so audit event */
1833           if mca_lock_unlock_success then ad_code = 0;
1834           audit_eventflags = "0"b;
1835           addr (audit_eventflags) -> audit_event_flags.priv_op = "1"b;
1836           addr (audit_eventflags) -> audit_event_flags.grant = "1"b;
1837           if reconfig_option = LOCK_MCA_INPUT then
1838                call access_audit_$log_general ("ocdcm_$reconfigure", level$get (), audit_eventflags,
1839                access_operations_$lock_mca, "", ad_code, null (), 0, "");
1840           else call access_audit_$log_general ("ocdcm_$reconfigure", level$get (), audit_eventflags,
1841                access_operations_$unlock_mca, "", ad_code, null (), 0, "MCA ^d", mca_to_unlock);
1842      end;
1843      oc_entry_ptr = find_oc_entry (bootload_console_name);                      /* locate the bootload console...       */
1844      oc_data.status_ptr = save_status_ptr;                                      /* reset the status pointer back...     */
1845      return;
1846 end lock_unlock_mca;
1847 ^L
1848 log_console_error:
1849      proc ();
1850 
1851 
1852           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1853           /*                                                                                                  */
1854           /* Internal procedure to enter a note that a console error has occurred into the system log.        */
1855           /*                                                                                                  */
1856           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1857 
1858      call io_manager$get_status (oc_entry.device_idx, addr (oc_status));        /* get IOM status...                    */
1859 
1860      unspec (log_message) = ""b;                                                /* clear any previous message residue.. */
1861 
1862      log_message.level = "3"b3;                                                 /* terminate...                         */
1863      log_message.channel = oc_entry.channel;
1864      log_message.device = "00"b;
1865      log_message.time_out = console_io_timeout;                                 /* if that is why were here...          */
1866      log_message.type = oc_status.action_code;
1867      log_message.command = addr (oc_entry.dcw_list (oc_entry.dcw_list_idx)) -> idcw.command;
1868      log_message.status = oc_entry.status_word;
1869      log_message.devname = oc_entry.name;
1870 
1871      call ioa_$rsnnl ("^[in_service^1x^]^[crash_on_crf^1x^]^[mc_io_enabled^1x^]^[list_consoles^1x^]^[printer_on^1x^]^[write_q_full^]",
1872           oc_data_flags, 0,
1873           oc_data.in_service, oc_data.crash_on_crf, oc_data.mc_io_enabled,
1874           oc_data.list_consoles, oc_data.printer_on, oc_data.write_q_full);
1875 
1876      call ioa_$rsnnl ("^[io_in_progress^1x^]^[prompt^1x^]^[got_special_int^1x^]^[oper_request^1x^]^[discard^1x^]^[discarded^]",
1877           oc_entry_flags, 0,
1878           oc_entry.io_in_progress, oc_entry.prompt, oc_entry.got_special_int,
1879           oc_entry.oper_request, oc_entry.discard, oc_entry.discarded);
1880 
1881      call ioa_$rsnnl ("^[alert^1x^]^[alerted^1x^]^[read^1x^]^[prompted^1x^]^[in_progress^1x^]^[completed^1x^]^[retry_reset^1x^]",
1882           console_io_flags, 0,
1883           console_io.alert, console_io.alerted, console_io.read,
1884           console_io.prompted, console_io.in_progress,
1885           console_io.completed, console_io.retry_reset);
1886 
1887      call syserr$binary (JUST_LOG, addr (log_message), SB_ocdcm_err, SBL_ocdcm_err,
1888           "ocdcm_ (log_console_error): I/O ^[timeout ^]error on ^a; status = ^.3b^/oc_data flags: ^a^/oc_entry flags: ^a^/console_io flags: ^a",
1889           console_io_timeout, oc_entry.name,
1890           substr (string (log_message.status), 1, 36), oc_data_flags,
1891           oc_entry_flags, console_io_flags);
1892 
1893      call log_console_event (LOGGED_ERROR, oc_data.io_ptr);
1894 
1895      return;
1896 
1897 end log_console_error;
1898 ^L
1899 log_console_event:
1900      proc (event_no, event_io_ptr_parm);
1901 
1902           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1903           /*                                                                                                  */
1904           /* Internal procedure to log console events...                                                      */
1905           /*                                                                                                  */
1906           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1907 
1908 /* parameters... (I) = Input, (O) = Output */
1909 
1910      dcl  event_no                      fixed bin (35)      parameter;          /* event to log...                  (I) */
1911      dcl  event_io_ptr_parm             ptr                 parameter;          /* -> I/O being affected by the event...*/
1912 
1913 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
1914 
1915 
1916      oc_data.event (oc_data.next_event).time = clock ();                        /* note the time...                     */
1917      oc_data.event (oc_data.next_event).process_id = pds$process_id;            /* and logger's process ID...           */
1918      oc_data.event (oc_data.next_event).event_number = event_no;                /* log the event...                     */
1919      oc_data.event (oc_data.next_event).event_io_ptr = event_io_ptr_parm;       /* note current I/O...                  */
1920      if oc_entry_ptr ^= null then do;
1921           oc_data.event (oc_data.next_event).opc_name = oc_entry.name;          /* note console name...                 */
1922           oc_data.event (oc_data.next_event).opc_flags = oc_entry.flags;        /* and console flags...                 */
1923      end;
1924      else do;                                                                   /* currently no bootload console...     */
1925           oc_data.event (oc_data.next_event).opc_name = "";
1926           oc_data.event (oc_data.next_event).opc_flags = ""b;
1927      end;
1928 
1929      oc_data.next_event = oc_data.next_event + 1;                               /* bump the index...                    */
1930      if oc_data.next_event > EVENT_QUEUE_SIZE then oc_data.next_event = 1;      /* and ensure it stays in bounds...     */
1931 
1932      return;                                                                    /* done...                              */
1933 
1934 end log_console_event;
1935 ^L
1936 next_console_io:
1937      proc () returns (ptr);
1938 
1939           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1940           /*                                                                                                  */
1941           /* Internal procedure to return a pointer to the next console I/O to be performed. If there are no  */
1942           /* outstanding I/Os then a null pointer is returned.                                                */
1943           /*                                                                                                  */
1944           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1945 
1946 
1947      if oc_data.read_io.in_progress then return (addr (oc_data.read_io));       /* complete READs without interruption..*/
1948 
1949      if ^oc_data.priority_io.completed then do;                                 /* found a priority I/O...              */
1950           if oc_data.priority_io.read then do;                                  /* is it a READ?...                     */
1951                if ^oc_entry.oper_request then return (null);                    /* yes, but no RE(QUEST TURN) key...    */
1952           end;
1953           return (addr (oc_data.priority_io));
1954      end;
1955 
1956      if oc_data.write_q_full then do;                                           /* if the write queue is full...        */
1957           return (addr (oc_data.write_queue (oc_data.next_free_write)));        /* next free write is the oldest I/O... */
1958      end;
1959 
1960      first_search_pass = true;
1961      first_io_slot = oc_data.next_free_write + 1;                               /* else next free + 1 is the oldest...  */
1962      if first_io_slot > WRITE_QUEUE_SIZE then first_io_slot = 1;
1963      last_io_slot = WRITE_QUEUE_SIZE;                                           /* search to end of queue...            */
1964 
1965 SEARCH_WRITE_QUEUE:
1966 
1967      do idx = first_io_slot to last_io_slot;                                    /* search for the next pending write... */
1968           console_io_ptr = addr (oc_data.write_queue (idx));                    /* overlay the write...                 */
1969           if ^console_io.completed then return (console_io_ptr);                /* return pending WRITE to caller...    */
1970      end;
1971      if first_search_pass then do;                                              /* first try failed...                  */
1972           first_search_pass = false;
1973           first_io_slot = 1;                                                    /* start at top of the queue...         */
1974           last_io_slot = oc_data.next_free_write;
1975           go to SEARCH_WRITE_QUEUE;                                             /* and start again...                   */
1976      end;
1977 
1978      if oc_entry.discarded then do;                                             /* discarded output but noone knows...  */
1979           oc_entry.dcw_list_idx = DISCARD_DCW;                                  /* get the DISCARD DCW list...          */
1980           call initiate_io ();                                                  /* and let them know...                 */
1981           return (null);                                                        /* fake it this time around...          */
1982      end;
1983 
1984      if oc_entry.oper_request then do;                                          /* only done if RE(TURN QUEST) pushed...*/
1985           if oc_data.stacked_read_cnt > 0 then do;                              /* if any READs are queued then do...   */
1986                if ^oc_data.read_io.in_progress & oc_data.read_io.completed      /* if not in progress & last completed..*/
1987                     then return (addr (oc_data.read_io));                       /* return pending READ to caller...     */
1988           end;
1989      end;
1990 
1991      return (null);                                                             /* nothing to do...                     */
1992 
1993 end next_console_io;
1994 ^L
1995 poll_for_console:
1996      proc ();
1997 
1998           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
1999           /*                                                                                                  */
2000           /* Internal procedure that will poll for a working console and will not return until one is found.  */
2001           /*                                                                                                  */
2002           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2003 
2004      if oc_data.bootload_console_idx ^= 0 then do;                              /* appears to be a working console...   */
2005           if console_responds_to_bell ((oc_data.bootload_console_idx)) then return;
2006      end;
2007 
2008      call unassign_bootload_console ();                                         /* quash pretender to the throne...     */
2009 
2010      do while (true);
2011           poll_idx = poll_idx + 1;                                              /* get next console...                  */
2012           if poll_idx > oc_data.console_cnt then poll_idx = 1;                  /* make sure we stay in bounds...       */
2013           if ^oc_data.opc (poll_idx).no_device then do;                         /* don't poll deconfigured consoles...  */
2014                if console_responds_to_bell (poll_idx) then do;                  /* found one that works...              */
2015                     call assign_bootload_console (oc_data.opc (poll_idx).name, code);
2016                     if code = 0 then return;
2017                end;
2018           end;
2019      end;
2020 
2021 end poll_for_console;
2022 ^L
2023 process_io:
2024      proc ();
2025 
2026 
2027           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2028           /*                                                                                                  */
2029           /* Internal procedure to perform a pending I/O. If there is no I/O pending the return argument      */
2030           /* will be set to true.                                                                             */
2031           /*                                                                                                  */
2032           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2033 
2034      if oc_entry_ptr = null () then goto BAIL_OUT;                              /* Console went inoperable! Bail out... */
2035 
2036      if oc_entry.io_in_progress then return;                                    /* console is already in use...         */
2037 
2038      console_io_ptr = next_console_io ();                                       /* find I/O to process...               */
2039      if console_io_ptr = null then return;                                      /* nothing to do...                     */
2040 
2041      if console_io.read then do;                                                /* process pending read...              */
2042           oc_entry.discard = false;                                             /* end any DISCARD condition...         */
2043           wired_hardcore_data$abort_request = false;                            /* and any abort condition...           */
2044           console_io.in_progress = true;                                        /* indicate that the I/O is in progress.*/
2045           console_io.completed = false;                                         /* and has not yet completed...         */
2046           if oc_entry.prompt & ^console_io.prompted then do;                    /* prompt first...                      */
2047                oc_entry.dcw_list_idx = PROMPT_DCW;                              /* setup the prompt DCW list...         */
2048                console_io.prompted = true;
2049                call log_console_event (SENT_PROMPT, console_io_ptr);
2050           end;
2051           else do;                                                              /* perform the read...                  */
2052                if oc_data.flags.printer_on | ^oc_entry.read_unechoed_option then do;
2053                     oc_entry.dcw_list_idx = READ_DCW;                           /* perform the read...                  */
2054                     dcwp = addr (oc_entry.dcw_list (READ_DCW + 1));             /* READ DCW...                          */
2055                     call log_console_event (STARTED_READ, console_io_ptr);
2056                end;
2057                else do;                                                         /* attempt unechoed READ...             */
2058                     oc_entry.dcw_list_idx = READ_UNECHOED_DCW;                  /* perform the read...                  */
2059                     dcwp = addr (oc_entry.dcw_list (READ_UNECHOED_DCW + 1));    /* READ_UNECHOED DCW...                 */
2060                     call log_console_event (STARTED_UNECHOED_READ, console_io_ptr);
2061                end;
2062                dcw.address = bit (binary (oc_data.abs_addr +                    /* get absolute address of read buffer..*/
2063                     wordno (addr (console_io.text)), 18));
2064           end;
2065           call initiate_io ();                                                  /* start the I/O...                     */
2066           return;
2067      end;
2068 
2069      else do;                                                                   /* if not a READ then it is a WRITE..   */
2070           if console_io.alert & ^console_io.alerted then do;                    /* send WRITE_ALERT if wanted...        */
2071                oc_entry.dcw_list_idx = ALERT_DCW;                               /* get WRITE_ALERT DCW...               */
2072                console_io.alerted = true;
2073                call log_console_event (SENT_ALERT, console_io_ptr);
2074           end;
2075           else do;                                                              /* send the message...                  */
2076                console_io.in_progress = true;                                   /* indicate that the I/O is in progress.*/
2077                dcwp = addr (oc_entry.dcw_list (WRITE_DCW + 1));                 /* setup DCW list...                    */
2078                dcw.tally = bit (binary (console_io.leng, 12), 12);              /* tally = length of message in words...*/
2079                dcw.address = bit (binary (oc_data.abs_addr +                    /* get absolute address of write buffer.*/
2080                     wordno (addr (console_io.text)), 18));
2081                oc_entry.dcw_list_idx = WRITE_DCW;                               /* we will write...                     */
2082                if console_io_ptr = addr (oc_data.priority_io) then
2083                     call log_console_event (PRIORITY_OUTPUT, console_io_ptr);
2084                else call log_console_event (STARTED_WRITE, console_io_ptr);
2085           end;
2086           call initiate_io ();                                                  /* start the I/O...                     */
2087           return;
2088      end;
2089 
2090 end process_io;
2091 ^L
2092 process_io_status:
2093      proc ();
2094 
2095           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2096           /*                                                                                                  */
2097           /* Internal procedure to process statuses returned by io_manager.                                   */
2098           /*                                                                                                  */
2099           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2100 
2101     if oc_entry.got_special_int then do;                                        /* operator wants to input...           */
2102          call log_console_event (GOT_SPECIAL_INT, oc_data.io_ptr);              /* log the event...                     */
2103          oc_entry.got_special_int = false;                                      /* and reset the switch...              */
2104          if oc_entry.oper_request then do;                                      /* if already in INPUT mode...          */
2105               if ^oc_entry.discard then do;                                     /* and not in DISCARD state...          */
2106                    oc_entry.discard = true;                                     /* enter same...                        */
2107                    oc_entry.discarded = false;                                  /* have not announced it yet...         */
2108                    wired_hardcore_data$abort_request = true;                    /* he who notices shall abort...        */
2109               end;
2110               return;
2111          end;
2112          else oc_entry.oper_request = true;                                     /* else note oper hit RE(TURN QUEST) key*/
2113          return;
2114      end;
2115 
2116      if ^oc_entry.io_in_progress then return;                                   /* no outstanding I/O, no status...     */
2117 
2118      if timeout () & ^io_status.t then do;                                      /* the last I/O has exceeded its time...*/
2119           call io_manager$mask (oc_entry.device_idx);                           /* abort the I/O...                     */
2120           call retry_io ();                                                     /* retry the I/O...                     */
2121           return;                                                               /* that's all for now...                */
2122      end;
2123 
2124      if ^io_status.t then return;                                               /* no valid status to process...        */
2125 
2126      oc_entry.status_word = unspec (io_status);                                 /* save the status for debugging...     */
2127      io_status.t = false;                                                       /* indicate that we've processed it...  */
2128 
2129           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2130           /*                                                                                                  */
2131           /* If ocdcm_ was invoked anywhere other than to handle an interrupt, then we need to pause 5        */
2132           /* milliseconds after the status for the interrupt to be sent by the console.  This is due to the   */
2133           /* fact that we are not waiting for the interrupt, but only seeing if status has been stored.  The  */
2134           /* IMU console takes a long time between the status store and terminate interrupt and if time is    */
2135           /* not given then a second connect could be sent before the interrupt has been sent, causing a      */
2136           /* console fault.                                                                                   */
2137           /*                                                                                                  */
2138           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2139 
2140      if ^entered_via_interrupt then do;
2141           if io_status.initiate & ^oc_entry.pcw_io & ^oc_entry.imu then return; /* ignore initiate & no major status, if... */
2142           wait_timer = clock () + 5000;                                         /* set wait timer                       */
2143           do while (clock () < wait_timer);                                     /* loop for a while                     */
2144           end;
2145      end;
2146 
2147      if io_status.power | io_status.channel_stat | io_status.central_stat then do;
2148           call io_manager$mask (oc_entry.device_idx);                           /* abort the I/O...                     */
2149           call retry_io ();                                                     /* retry the I/O operation...           */
2150           return;                                                               /* that's all for now...                */
2151      end;
2152 
2153      if io_status_overlay.major = "00"b3 then do;
2154           if io_status.initiate & ^oc_entry.pcw_io & ^oc_entry.imu then return; /* ignore initiate & no major status, if... */
2155           call terminate_io ();                                                 /* normal termination...                */
2156           return;
2157      end;
2158 
2159      if io_status_overlay.major = "01"b3 then do;                               /* if DEVICE_BUSY..                     */
2160           call retry_io ();                                                     /* give it another try...               */
2161           return;
2162      end;
2163 
2164      if io_status_overlay.major = "02"b3 &                                      /* if DEVICE_ATTENTION..                */
2165           (oc_entry.dcw_list_idx = LOCK_MCA_DCW |
2166           oc_entry.dcw_list_idx = UNLOCK_MCA_DCW) then do;                      /* and doing MCA type I/O, then its ok...*/
2167           call terminate_io ();                                                 /* normal termination...                */
2168           return;
2169      end;
2170 
2171      if io_status_overlay.major ^= "03"b3 |                                     /* if ^DATA_ALERT...                    */
2172           (oc_entry.dcw_list_idx ^= READ_DCW &
2173           oc_entry.dcw_list_idx ^= READ_UNECHOED_DCW) then do;                  /* or not a READ I/O then retry...      */
2174           call io_manager$mask (oc_entry.device_idx);                           /* abort the I/O...                     */
2175           call retry_io ();
2176           return;
2177      end;
2178 
2179      console_io_ptr = oc_data.io_ptr;                                           /* locate I/O in progress...            */
2180 
2181      if io_status_overlay.sub = "10"b3 then do;                                 /* OPERATOR DISTRACTED...               */
2182           oc_entry.oper_request = false;                                        /* wait for oper to hit RE(TURN QUEST)..*/
2183           oc_entry.discard = false;                                             /* end the DISCARD condition...         */
2184           oc_entry.discarded = false;
2185           call reset_read ();                                                   /* reset the READ I/O...                */
2186           call send_newline ();                                                 /* start next I/O on a fresh line...    */
2187           return;
2188      end;
2189 
2190      if io_status_overlay.sub = "04"b3 |                                        /* if OPERATOR INPUT ERROR or...        */
2191           io_status_overlay.sub = "40"b3 then do;                               /* MESSAGE LENGTH ALERT...              */
2192           call reset_read ();                                                   /* reset the READ...                    */
2193           call send_newline ();                                                 /* start on a fresh line...             */
2194           return;
2195      end;
2196 
2197      call io_manager$mask (oc_entry.device_idx);                                /* abort the I/O...                     */
2198      call retry_io ();                                                          /* retry all others...                  */
2199 
2200      return;                                                                    /* done...                              */
2201 
2202 end process_io_status;
2203 ^L
2204 queue_console_io:
2205      proc () returns (fixed bin (71));
2206 
2207           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2208           /*                                                                                                  */
2209           /* Internal procedure that copies the user's I/O out of our local copy and into the appropriate     */
2210           /* I/O queue. If there is room for the I/O we return the time that the I/O is queued to our caller. */
2211           /* If we find that there is no room to queue the I/O we return a zero to our caller.                */
2212           /*                                                                                                  */
2213           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2214 
2215      local_io.in_progress = false;                                              /* reset action switches...             */
2216      local_io.completed = false;
2217      local_io.alerted = false;
2218      local_io.prompted = false;
2219      local_io.retry_reset = false;
2220      local_io.console = "";                                                     /* reset console assigned indicator...  */
2221 
2222      if local_io.read then do;
2223           if oc_data.last_read_queued = -1 then do;                             /* if this is the first ever read...    */
2224                oc_data.reader_process_id = pds$process_id;                      /* then we get the prize...             */
2225           end;
2226           oc_data.stacked_read_cnt = oc_data.stacked_read_cnt + 1;              /* push the read onto the stack...      */
2227           if oc_data.stacked_read_cnt > 1 then do;                              /* if we have more then one read...     */
2228                call log_console_event (PUSHED_READ, addr (oc_data.read_io));    /* log the PUSH...                      */
2229                oc_data.meters.pushed_read_cnt = oc_data.meters.pushed_read_cnt + 1;
2230                return (0);                                                      /* nothing else to do...                */
2231           end;
2232           local_io.completed = true;                                            /* READs always start off as completed..*/
2233           local_io.leng = 0;                                                    /* make sure read goes smoothly...      */
2234           local_io.text = "";
2235           local_io.sequence_no = 0;
2236           local_io.time_queued = clock ();
2237           local_io.process_id = pds$process_id;                                 /* for debugging purposes...            */
2238           oc_data.read_io = local_io;                                           /* copy the read...                     */
2239           oc_data.last_read_queued = local_io.time_queued;                      /* update stats...                      */
2240           call log_console_event (QUEUED_READ, addr (oc_data.read_io));         /* log the event...                     */
2241           return (local_io.time_queued);                                        /* and return the time we queued it...  */
2242      end;
2243      else do;                                                                   /* I/O is a WRITE...                    */
2244           if ^oc_data.write_queue (oc_data.next_free_write).completed then do;  /* no room to queue a write...          */
2245                oc_data.meters.write_q_full_cnt = oc_data.meters.write_q_full_cnt + 1;
2246                oc_data.write_q_full = true;                                     /* let next_console_io know...          */
2247                return (0);                                                      /* DIM will try again later...          */
2248           end;
2249           else do;                                                              /* we have room to queue the WRITE...   */
2250                local_io.time_queued = clock ();
2251                local_io.process_id = pds$process_id;                            /* get the writers process ID...        */
2252                console_io_ptr = addr (oc_data.write_queue (oc_data.next_free_write));
2253                console_io = local_io;
2254                oc_data.last_write_queued = local_io.time_queued;                /* update stats...                      */
2255                call log_console_event (QUEUED_WRITE, console_io_ptr);
2256                oc_data.next_free_write = oc_data.next_free_write + 1;           /* update the next free slot number...  */
2257                if oc_data.next_free_write > WRITE_QUEUE_SIZE then               /* if past the end of the queue then... */
2258                     oc_data.next_free_write = 1;                                /* wrap around...                       */
2259                if ^oc_data.write_queue (oc_data.next_free_write).completed then do;/* no room to queue any more writes...*/
2260                     oc_data.meters.write_q_full_cnt = oc_data.meters.write_q_full_cnt + 1;
2261                     oc_data.write_q_full = true;                                /* let next_console_io know...          */
2262                end;
2263                return (local_io.time_queued);                                   /* return the time we queued it...      */
2264           end;
2265      end;
2266 
2267 end queue_console_io;
2268 ^L
2269 report_error:
2270      proc options (variable);
2271 
2272           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2273           /*                                                                                                  */
2274           /* Internal procedure to report errors to the operator. Depending upon the severity of the error    */
2275           /* we will either return or crash.                                                                  */
2276           /*                                                                                                  */
2277           /* Calling sequence:                                                                                */
2278           /*                                                                                                  */
2279           /*        call report_error (SEVERITY, entrypoint_name, control_string, arg_1,... arg_n);           */
2280           /*                                                                                                  */
2281           /* Note:  This procedure does not validate its arguments.                                           */
2282           /*                                                                                                  */
2283           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2284 
2285      dcl  arg_list_ptr                  ptr;                                    /* -> arg_list...                       */
2286      dcl  based_epname                  char      (32)      based;              /* entrypoint name overlay...           */
2287      dcl  based_severity                fixed bin (17)      based;              /* severity overlay...                  */
2288      dcl  entrypoint_name               char      (32);                         /* name of our caller...                */
2289      dcl  error_msg                     char      (256);                        /* filled by formline_...               */
2290      dcl  error_buffer                  char      (256);                        /* filled by oc_trans_output_...        */
2291      dcl  severity                      fixed bin (17);                         /* severity of the error...             */
2292 
2293      dcl  1 saved_priority_io           aligned                                 /*  copy of a priority I/O...           */
2294                                         like      priority_io;
2295 
2296 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
2297 
2298 
2299      arg_list_ptr = arg_list_ptr_ ();                                           /* -> argument list...                  */
2300 
2301      severity = arg_list_ptr -> arg_list.arg_ptrs (1) -> based_severity;        /* first arg is the severity...         */
2302      if arg_list_ptr -> arg_list.call_type = Envptr_supplied_call_type then
2303           entrypoint_name = substr (arg_list_ptr -> arg_list_with_envptr.arg_ptrs (2) -> based_epname, 1,
2304           arg_list_ptr -> arg_list_with_envptr.desc_ptrs (2) -> arg_descriptor.size);
2305      else entrypoint_name = substr (arg_list_ptr -> arg_list.arg_ptrs (2) -> based_epname, 1, arg_list_ptr -> arg_list.desc_ptrs (2) -> arg_descriptor.size);
2306 
2307      error_msg = "";                                                            /* start with a clean slate...          */
2308 
2309      call formline_ (3, 4, addr (error_msg), length (error_msg), 1, arg_list_ptr);
2310 
2311      error_msg = "ocdcm_ (" || rtrim (entrypoint_name) || "): " || rtrim (error_msg);
2312 
2313      oc_entry_ptr = find_oc_entry ("");                                         /* locate the bootload console...       */
2314 
2315      if severity = PANIC then do;                                               /* must crash Multics...                */
2316           call unlock_oc_data ();                                               /* relinquish lock, unwire, unmask...   */
2317           call syserr_real$panic (error_msg);                                   /* the point of no return...            */
2318      end;
2319 
2320      call syserr (JUST_LOG, error_msg);                                         /* log the error...                     */
2321 
2322      if severity = JUST_LOG then return;                                        /* all that is necessary...             */
2323 
2324      if ^oc_data.in_service then do;
2325           if sys_info$collection_1_phase > SERVICE_INITIALIZATION then do;      /* if crashing then must have console...*/
2326                oc_data.must_have_console = true;                                /* set the appropriate flag...          */
2327                call console_recovery ();                                        /* console recovery knows what to do... */
2328           end;
2329           else if oc_data.crash_on_crf | sys_info$collection_1_phase < SERVICE_INITIALIZATION then do;
2330                call unlock_oc_data ();                                          /* relinquish lock, unwire, unmask...   */
2331                call syserr_real$panic (error_msg);                              /* oh well...                           */
2332           end;
2333           else return;                                                          /* can't go any further...              */
2334      end;
2335 
2336      if ^oc_data.priority_io.completed then do;                                 /* must save that message...            */
2337           i_saved_priority_io = true;
2338           if ^saved_priority_io.completed then do;                              /* LOST CONSOLE I/O...                  */
2339                call syserr (JUST_LOG, "ocdcm_ (report_error): LOST CONSOLE I/O. I/O follows...");
2340                call syserr (JUST_LOG, saved_priority_io.text);                  /* pass it to the log...                */
2341           end;
2342           saved_priority_io = oc_data.priority_io;                              /* copy it...                           */
2343      end;
2344 
2345      oc_data.priority_io.time_queued = clock ();
2346      oc_data.priority_io.process_id = pds$process_id;
2347      oc_data.priority_io.event_chan = 0;
2348      oc_data.priority_io.in_progress = false;
2349      oc_data.priority_io.alert = (severity <= BEEP);
2350 
2351      if oc_data.mc_io_enabled then do;                                          /* Message Coordinator is handling I/O..*/
2352           call bump_io_to_mc ((oc_data.priority_io.sequence_no));
2353           oc_data.priority_io.completed = true;                                 /* free the space...                    */
2354           return;                                                               /* all we can do...                     */
2355      end;
2356 
2357      if oc_entry_ptr = null then return;                                        /* no need to continue...               */
2358      to_write_ptr = addr (error_msg);
2359      to_write_length = length (rtrim (error_msg));
2360      continue_flag = false;
2361      this_part_length = 0;
2362      console_line_length = oc_entry.line_leng;                                  /* in case the console gets lost...     */
2363 
2364      do while (to_write_length > 0);
2365           oc_data.priority_io.completed = false;
2366           oc_data.priority_io.in_progress = false;
2367           error_buffer = "";
2368           call oc_trans_output_ (to_write_ptr, to_write_length, this_part_length, addr (error_buffer),
2369                word_length, console_line_length, continue_flag);
2370           oc_data.priority_io.leng = word_length;
2371           oc_data.priority_io.text = substr (error_buffer, 1, multiply (word_length, 4, 17));
2372 
2373           oc_data.priority_io.completed = false;                                /* lest it not be performed...          */
2374 
2375           do while (^oc_data.priority_io.completed & oc_data.in_service);       /* LOOP IN RING ZERO TILL I/O COMPLETE..*/
2376                call process_io ();                                              /* process the I/O...                   */
2377                call process_io_status ();                                       /* process the status...                */
2378           end;
2379           to_write_ptr = addcharno (to_write_ptr, (this_part_length));
2380           to_write_length = to_write_length - this_part_length;
2381      end;
2382 
2383      if i_saved_priority_io then priority_io = saved_priority_io;               /* restore priority I/O if necessary... */
2384      saved_priority_io.completed = true;
2385 
2386 end report_error;
2387 ^L
2388 reset_channel:
2389      proc ();
2390 
2391           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2392           /*                                                                                                  */
2393           /* Internal procedure to reset the console channel by sending a READ_ID DCW to the channel.         */
2394           /*                                                                                                  */
2395           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2396 
2397 
2398      if true then return;                                                       /* UNTIL I FIGURE OUT RESETS...         */
2399 
2400      oc_entry.dcw_list_idx = RESET_DCW;
2401 
2402      call log_console_event (RESET_CHANNEL, oc_data.io_ptr);                    /* log the event...                     */
2403 
2404      call initiate_io ();                                                       /* and do it...                         */
2405 
2406      return;                                                                    /* done...                              */
2407 
2408 end reset_channel;
2409 ^L
2410 reset_console:
2411      proc ();
2412 
2413           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2414           /*                                                                                                  */
2415           /* Internal procedure to reset the console.                                                         */
2416           /*                                                                                                  */
2417           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2418 
2419      entrypoint = "reset_console";                                              /* set entrypoint name...               */
2420 
2421      oc_data.in_service = true;                                                 /* attempt to put us back in service... */
2422      oc_data.mc_io_enabled = false;
2423 
2424      do idx = 1 to WRITE_QUEUE_SIZE;                                            /* mark all WRITE slots as free...      */
2425           oc_data.write_queue (idx).completed = true;
2426      end;
2427      oc_data.write_q_full  = false;                                             /* reset the full flag...               */
2428 
2429      oc_data.stacked_read_cnt = 1;                                              /* free all READs, leave one pending... */
2430      call reset_read ();                                                        /* and simulate one pending...          */
2431 
2432      call unassign_bootload_console ();                                         /* first unassign it...                 */
2433 
2434      if oc_entry_ptr = null then do;                                            /* no active console...                 */
2435           call console_recovery ();                                             /* try another...                       */
2436           return;                                                               /* best we can do...                    */
2437      end;
2438 
2439      oc_entry.io_in_progress = false;                                           /* reset certain flags...               */
2440      oc_entry.discard = false;
2441      oc_entry.discarded = false;
2442      oc_entry.got_special_int = false;
2443      oc_entry.oper_request = false;
2444      oc_entry.retry_cnt = 0;
2445      oc_entry.io_time = 0;
2446 
2447      call assign_bootload_console (oc_entry.name, err_code);                    /* then re-assign it...                 */
2448      if err_code ^= 0 then do;
2449           call console_recovery ();                                             /* failed, try another console...       */
2450           return;                                                               /* done...                              */
2451      end;
2452 
2453      call reset_channel ();                                                     /* reset console channel...             */
2454 
2455      call report_error (BEEP, entrypoint, "Reset bootload console for ^a.", pds$process_group_id);
2456 
2457      return;
2458 
2459 end  reset_console;
2460 ^L
2461 reset_read:
2462      proc ();
2463 
2464           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2465           /*                                                                                                  */
2466           /* Internal procedure to reset a READ so that it will be done again.                                */
2467           /*                                                                                                  */
2468           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2469 
2470      if oc_data.priority_io.read then read_io_ptr = addr (oc_data.priority_io); /* if we were doing a priority READ...  */
2471      else read_io_ptr = addr (oc_data.read_io);
2472 
2473      unspec (read_io_ptr -> console_io.flags) = ""b;                            /* reset all flags...                   */
2474      read_io_ptr -> console_io.read = true;                                     /* and not that it is a READ...         */
2475      read_io_ptr -> console_io.completed = true;                                /* so that it will be executed...       */
2476      read_io_ptr -> console_io.console = "";                                    /* reset assigned console...            */
2477      read_io_ptr -> console_io.leng = 0;                                        /* clear text length...                 */
2478      read_io_ptr -> console_io.text = "";                                       /* and text...                          */
2479 
2480      return;                                                                    /* done...                              */
2481 
2482 end reset_read;
2483 ^L
2484 retry_io:
2485      proc ();
2486 
2487           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2488           /*                                                                                                  */
2489           /* Internal procedure that will attempt to retry the last I/O operation initiated. If the console   */
2490           /* has already been flagged as inoperative then we will pass control to console_recovery who will   */
2491           /* handle the problem.                                                                              */
2492           /*                                                                                                  */
2493           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2494 
2495      console_io_ptr = oc_data.io_ptr;                                           /* find I/O we were processing...       */
2496 
2497      if oc_entry.retry_cnt = 0 then call log_console_error ();                  /* log the error on the first retry...  */
2498 
2499      call log_console_event (RETRY_IO, oc_data.io_ptr);                         /* log the retry event...               */
2500 
2501      if oc_entry.retry_cnt = MAX_RETRIES then do;                               /* sorry...                             */
2502           call console_recovery ();                                             /* get a new console...                 */
2503           if ^oc_data.in_service then do;                                       /* console recovery failed...           */
2504                console_io.completed = true;                                     /* free up the I/O...                   */
2505                return;                                                          /* I/O was at least logged...           */
2506           end;
2507           else if oc_data.mc_io_enabled then do;                                /* no real consoles left...             */
2508                local_io = console_io;                                           /* copy the I/O to local_io structure...*/
2509                if local_io.sequence_no > 0 then do;                             /* if a syserr message then...          */
2510                     call bump_io_to_mc ((local_io.sequence_no));                /* pass it to the MC...                 */
2511                     console_io.completed = true;                                /* signal priority I/O completion...    */
2512                end;
2513                else call bump_io_to_mc (-(local_io.time_queued));               /* for normal messages...               */
2514                return;                                                          /* done...                              */
2515           end;
2516      end;
2517 
2518      else do;                                                                   /* give 'em another chance...           */
2519           oc_entry.retry_cnt = oc_entry.retry_cnt + 1;                          /* bump the retry count...              */
2520           if console_io.read then do;                                           /* READs are special...                 */
2521                oc_entry.oper_request = false;                                   /* make 'em hit RE(TURN QUEST) again... */
2522                oc_entry.discard = false;                                        /* reset any DISCARD condition...       */
2523                oc_entry.discarded = false;
2524                oc_entry.io_in_progress = false;                                 /* no I/O in progress...                */
2525                call reset_read ();                                              /* reset the READ...                    */
2526                call send_newline ();                                            /* start on a fresh line...             */
2527                return;                                                          /* don't try again...                   */
2528           end;
2529           call reset_channel ();                                                /* reset the console channel...         */
2530           call initiate_io ();                                                  /* retry the I/O...                     */
2531           return;
2532      end;
2533 
2534      return;
2535 
2536 end retry_io;
2537 ^L
2538 send_newline:
2539      proc ();
2540 
2541           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2542           /*                                                                                                  */
2543           /* Internal procedure that sends a newline to the console.                                          */
2544           /*                                                                                                  */
2545           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2546 
2547      oc_entry.dcw_list_idx = NEWLINE_DCW;                                       /* get newline DCW...                   */
2548 
2549      call log_console_event (SENT_NEWLINE, oc_data.io_ptr);
2550 
2551      call initiate_io ();                                                       /* send it...                           */
2552 
2553      return;
2554 
2555 end send_newline;
2556 ^L
2557 terminate_io:
2558      proc ();
2559 
2560           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2561           /*                                                                                                  */
2562           /* Internal procedure to terminate a successful I/O operation.                                      */
2563           /*                                                                                                  */
2564           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2565 
2566      oc_entry.io_in_progress = false;                                           /* signal end of I/O operation...       */
2567      oc_entry.retry_cnt = 0;                                                    /* reset for successful termination...  */
2568 
2569      if oc_entry.dcw_list_idx = NEWLINE_DCW then do;
2570           call log_console_event (TERMINATED_NEWLINE, oc_data.io_ptr);
2571           return;                                                               /* nothing else to do...                */
2572      end;
2573 
2574      if oc_entry.dcw_list_idx = LOCK_MCA_DCW then do;
2575           call log_console_event (TERMINATED_MCA_LOCK, null);
2576           return;                                                               /* nothing else to do...                */
2577      end;
2578 
2579      if oc_entry.dcw_list_idx = UNLOCK_MCA_DCW then do;
2580           call log_console_event (TERMINATED_MCA_UNLOCK, null);
2581           return;                                                               /* nothing else to do...                */
2582      end;
2583 
2584      if oc_entry.dcw_list_idx = DISCARD_DCW then do;
2585           oc_entry.discard = false;                                             /* reset the DISCARD condition...       */
2586           oc_entry.discarded = false;
2587           return;                                                               /* nothing else to do...                */
2588      end;
2589 
2590      console_io_ptr = oc_data.io_ptr;                                           /* find the I/O to terminate...         */
2591 
2592      if oc_entry.dcw_list_idx = RESET_DCW then do;
2593           call log_console_event (TERMINATED_RESET, oc_data.io_ptr);
2594           return;                                                               /* nothing more to do...                */
2595      end;
2596 
2597      if oc_entry.dcw_list_idx = ALERT_DCW then do;
2598           call log_console_event (TERMINATED_ALERT, oc_data.io_ptr);
2599           return;                                                               /* nothing more to do...                */
2600      end;
2601 
2602      if oc_entry.dcw_list_idx = PROMPT_DCW then do;                             /* note that prompt succeeded...        */
2603           call log_console_event (TERMINATED_PROMPT, oc_data.io_ptr);
2604           return;                                                               /* nothing else to do...                */
2605      end;
2606 
2607      if oc_entry.dcw_list_idx = WRITE_DCW then do;
2608           oc_data.write_q_full  = false;                                        /* reset the full flag...               */
2609           console_io.completed = true;                                          /* free the I/O slot...                 */
2610           console_io.in_progress = false;                                       /* terminate the I/O...                 */
2611           call log_console_event (TERMINATED_WRITE, oc_data.io_ptr);
2612           return;
2613      end;
2614 
2615      if (oc_entry.dcw_list_idx = READ_DCW |                                     /* READ termination...                  */
2616           oc_entry.dcw_list_idx = READ_UNECHOED_DCW) then do;                   /* READ_UNECHOED termination...         */
2617           console_io.in_progress = false;                                       /* READ operation completed...          */
2618           call io_manager$get_status (oc_entry.device_idx, addr (oc_status));   /* get number of characters read...     */
2619           console_io.leng =
2620                multiply ((divide (MAX_IO_LENGTH, 4, 17) - oc_status.tally_residue), 4, 17); /* calculate number of characters read..*/
2621           if oc_status.character_position > 0 then
2622                console_io.leng = console_io.leng + oc_status.character_position - 4;
2623           call log_console_event (TERMINATED_READ, oc_data.io_ptr);
2624           call send_newline ();                                                 /* our way of acknowledging the I/O...  */
2625           if console_io.leng = 0 then do;
2626                oc_entry.oper_request = false;                                   /* null input line terminates INPUT mode*/
2627                call reset_read ();                                              /* reset the READ I/O...                */
2628                return;
2629           end;
2630           if console_io_ptr = addr (oc_data.priority_io) then do;               /* if the READ was a priority I/O...    */
2631                console_io.completed = true;                                     /* priority READ is finished...         */
2632                return;                                                          /* no wakeup necessary...               */
2633           end;
2634           call pxss$ring_0_wakeup (oc_data.reader_process_id,                   /* tell reader to come get his mail...  */
2635                console_io.event_chan, console_io.time_queued, (0));
2636           call log_console_event (SENT_WAKEUP, oc_data.io_ptr);                 /* log the event...                     */
2637      end;
2638 
2639      return;
2640 
2641 end terminate_io;
2642 ^L
2643 timeout:
2644      proc () returns (bit (1));
2645 
2646           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2647           /*                                                                                                  */
2648           /* Internal function that returns true if the I/O operation being performed has timed out.          */
2649           /*                                                                                                  */
2650           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2651 
2652      console_io_timeout = false;
2653      if oc_entry.imu then
2654           if (clock () > (oc_entry.io_time + 1e06 * MAX_IMU_IO_TIME)) then
2655                goto console_timed_out;
2656           else return (false);
2657      else if (clock () > (oc_entry.io_time + 1e06 * MAX_IO_TIME (oc_entry.dcw_list_idx))) then do;
2658 console_timed_out:
2659           console_io_timeout = true;
2660           call log_console_event (IO_TIMEOUT, oc_data.io_ptr);
2661           return (true);
2662      end;
2663 
2664      return (false);
2665 
2666 end timeout;
2667 ^L
2668 unassign_bootload_console:
2669      proc ();
2670 
2671           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2672           /*                                                                                                  */
2673           /* Internal procedure to unassign the bootload console. At the conclusion of this procedure         */
2674           /* oc_data.bootload_console_idx = 0.                                                                */
2675           /*                                                                                                  */
2676           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2677 
2678 
2679      oc_entry_ptr = null;                                                       /* initialize it to start...            */
2680 
2681      if oc_data.bootload_console_idx = 0 then do;                               /* can't unassign if no bootload console*/
2682           old_console_name = "";
2683           return;
2684      end;
2685 
2686      oc_entry_ptr = addr (oc_data.opc (oc_data.bootload_console_idx));          /* overlay the bootload console entry...*/
2687      old_console_name = oc_entry.name;                                          /* in case reassignment is needed...    */
2688      oc_entry.io_in_progress = false;                                           /* prevent MYLOCK race conditions...    */
2689 
2690      call io_manager$unassign (oc_entry.device_idx, (0));                       /* unassign it...                       */
2691      oc_entry.assigned = false;
2692      oc_data.bootload_console_idx = 0;                                          /* indicate no bootload console assigned*/
2693      oc_entry.bootload_console = false;                                         /* bookeeping...                        */
2694      oc_entry.io_device = true;                                                 /* let them have it...                  */
2695      oc_entry.config_change = true;                                             /* note config change occurred...       */
2696 
2697      return;
2698 
2699 end unassign_bootload_console;
2700 ^L
2701 unlock_oc_data:
2702      proc ();
2703 
2704      dcl special_interrupt_received bit (1) automatic init (false);
2705 
2706           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2707           /*                                                                                                  */
2708           /* Internal procedure to unlock the oc_data database. This procedure will also unwire our stack     */
2709           /* and unmask interrupts. The only possible error here will be that the lock does not belong to     */
2710           /* us. This situation should not happen and will result in a system  crash.                         */
2711           /*                                                                                                  */
2712           /* Before unlocking we will check to see if any specials have occurred while we were busy. If so    */
2713           /* we will process them.                                                                            */
2714           /*                                                                                                  */
2715           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2716 
2717      do while (oc_data.no_lock_flags.got_special_int | oc_data.no_lock_flags.got_terminate_int);
2718                           /* special or terminate interrupt occurred while we held lock */
2719 
2720           /* reset the appropriate flag */
2721           if oc_data.no_lock_flags.got_special_int then do;
2722                special_interrupt_received = true;
2723                oc_data.no_lock_flags.got_special_int = false;
2724           end;
2725           if oc_data.no_lock_flags.got_terminate_int then
2726                oc_data.no_lock_flags.got_terminate_int = false;
2727 
2728 
2729           oc_entry_ptr = find_oc_entry ("");                                    /* find the bootload console...         */
2730           if oc_entry_ptr ^= null then do;                                      /* only do if console available...      */
2731 
2732                if special_interrupt_received then do;
2733                     special_interrupt_received = false;
2734                     oc_entry.got_special_int = true;                            /* say it came from there...            */
2735                end;
2736 
2737                call process_io_status ();                                       /* process any pending status...        */
2738                call process_io ();                                              /* attempt to start the I/O...          */
2739           end;
2740           else if ^oc_data.mc_io_enabled then
2741                oc_data.in_service = false;
2742 
2743      end;
2744 
2745      if ^stacq (oc_data.lock, ""b, pds$process_id) then do;                     /* clear lock if it is ours...          */
2746           if oc_data.lock ^= ""b then                                           /* not ours, if not free crash...       */
2747                call report_error (PANIC, "unlock_oc_data", "Lock not mine.");
2748      end;
2749 
2750      call unwire_and_unmask;                                                    /* unwire stack, accept interrupts...   */
2751 
2752      return;
2753 
2754 end unlock_oc_data;
2755 ^L
2756 wire_and_mask:
2757      proc ();
2758 
2759      call privileged_mode_ut$wire_and_mask (wire_mask, wire_ptw_ptr);           /* wire our stack and mask interrupts...*/
2760      wired_and_masked = true;
2761      return;
2762 
2763 unwire_and_unmask:
2764      entry;
2765      if wired_and_masked then do;
2766           call privileged_mode_ut$unwire_unmask (wire_mask, wire_ptw_ptr);      /* unwire stack, accept interrupts...   */
2767           wired_and_masked = false;
2768      end;
2769      return;
2770 
2771 end wire_and_mask;
2772 ^L
2773           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2774           /*                                                                                                  */
2775           /*                                      Declarations...                                             */
2776           /* format: off                                                                                      */
2777           /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
2778 
2779 
2780 /* global parameters... (I) = Input, (O) = Output */
2781 
2782      dcl  code                          fixed bin (35)      parameter;
2783 /* standard Multics error code...  (O) */
2784 
2785 /* entries... */
2786 
2787      dcl  absadr entry (ptr, fixed bin (35)) returns (fixed bin (26));
2788      dcl  access_audit_$log_general entry options (variable);
2789      dcl  arg_list_ptr_ entry () returns (ptr);
2790      dcl  config_$find entry (char(4) aligned, ptr);
2791      dcl  config_$find_parm entry (char(4) aligned, ptr);
2792      dcl  cv_dec_check_ entry (char(*), fixed bin(35)) returns(fixed bin(35));
2793      dcl  formline_ entry options(variable);
2794      dcl  ioa_$rsnnl entry() options(variable);
2795 /*  dcl   io_chnl_util$iom_to_name;                                             declared in io_chnl_util_dcls include.. */
2796 /*   dcl  io_manager$assign;                                                    declared in io_manager_dcls include...  */
2797 /*   dcl  io_manager$connect_abs;                                               declared in io_manager_dcls include...  */
2798 /*   dcl  io_manager$get_status;                                                declared in io_manager_dcls include...  */
2799 /*   dcl  io_manager$mask;                                                      declared in io_manager_dcls include...  */
2800 /*   dcl  io_manager$unassign;                                                  declared in io_manager_dcls include...  */
2801      dcl  level$get entry () returns (fixed bin);
2802      dcl  ocdcm_$interrupt_handler entry (fixed bin (35), fixed bin (3), bit (36) aligned);
2803      dcl  oc_trans_output_ entry (ptr, fixed bin(21), fixed bin(21), ptr, fixed bin(19), fixed bin, bit(1) aligned);
2804      dcl  privileged_mode_ut$wire_and_mask entry (fixed bin (71), ptr);
2805      dcl  privileged_mode_ut$unwire_unmask entry (fixed bin (71), ptr);
2806      dcl  pxss$ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
2807      dcl  syserr entry options (variable);
2808      dcl  syserr$binary entry options (variable);
2809      dcl  syserr_real$panic entry options (variable);
2810 
2811 /* builtins... */
2812 
2813      dcl  addr                          builtin;
2814      dcl  addcharno                     builtin;
2815      dcl  binary                        builtin;
2816      dcl  bit                           builtin;
2817      dcl  byte                          builtin;
2818      dcl  clock                         builtin;
2819      dcl  copy                          builtin;
2820      dcl  divide                        builtin;
2821      dcl  length                        builtin;
2822      dcl  max                           builtin;
2823      dcl  multiply                      builtin;
2824      dcl  null                          builtin;
2825      dcl  rtrim                         builtin;
2826      dcl  stac                          builtin;
2827      dcl  stacq                         builtin;
2828      dcl  string                        builtin;
2829      dcl  substr                        builtin;
2830      dcl  unspec                        builtin;
2831      dcl  wordno                        builtin;
2832 
2833 /* pointers... */
2834 
2835      dcl  console_data_ptr              ptr;                                    /* -> console_data structure...         */
2836      dcl  read_io_ptr                   ptr;                                    /* -> the READ I/O to reset...          */
2837      dcl  to_write_ptr                  ptr;                                    /* -> string to be written...           */
2838      dcl  wire_ptw_ptr                  ptr;                                    /* gotten and returned w/o changes...   */
2839      dcl  save_status_ptr               ptr;                                    /* used to save oc_data.status_ptr...   */
2840 
2841 /* switches... */
2842 
2843      dcl  audit_flag                    bit       (1);
2844      dcl  true                          bit       (1)       init      ("1"b)
2845                                         internal static     options (constant);
2846 
2847      dcl  false                         bit       (1)       init      ("0"b)
2848                                         internal static     options (constant);
2849 
2850      dcl  console_found                 bit       (1)       init      ("0"b);   /* used for loop termination...         */
2851      dcl  console_is_free               bit       (1);                          /* ON => OK for RCP attachment...       */
2852      dcl  continue_flag                 bit       (1)       init      ("0"b)    /* line being written gets "\c" chars...*/
2853                                                             aligned;
2854      dcl  done                          bit       (1)       init      ("0"b);   /* used for loop termination...         */
2855      dcl  first_search_pass             bit       (1)       init      ("0"b);   /* ON => first pass to find an I/O...   */
2856      dcl  found                         bit       (1)       init      ("0"b);   /* used for loop termination...         */
2857      dcl  i_saved_priority_io           bit       (1)       init      ("0"b);   /* ON => I saved a priority I/O...      */
2858      dcl  entered_via_interrupt         bit       (1)       init      ("0"b)    /* used to see if need to pause during status processing...*/
2859                                                             aligned;
2860      dcl  mca_lock_unlock_success       bit       (1);                          /* used during lock/unlock mca operations...*/
2861      dcl  must_unassign                 bit       (1);                          /* used during lock/unlock mca operations...*/
2862      dcl  console_io_timeout            bit       (1);                          /* ON => Had io timeout...              */
2863      dcl  wired_and_masked              bit       (1)       init      ("0"b)    /* used to control when unwiring and unmasking is needed...*/
2864                                                             aligned;
2865      dcl  wired_hardcore_data$abort_request
2866                                         bit       (1)       aligned
2867                                         external static;
2868 
2869 /* error_table_... */
2870 
2871      dcl  error_table_$action_not_performed
2872                                         fixed bin (35)      external static;
2873      dcl  error_table_$bad_arg          fixed bin (35)      external static;
2874      dcl  error_table_$device_busy      fixed bin (35)      external static;
2875      dcl  error_table_$device_not_active
2876                                         fixed bin (35)      external static;
2877      dcl  error_table_$dev_nt_assnd     fixed bin (35)      external static;
2878      dcl  error_table_$no_operation     fixed bin (35)      external static;
2879      dcl  error_table_$resource_not_free
2880                                         fixed bin (35)      external static;
2881      dcl  error_table_$timeout          fixed bin (35)      external static;
2882 
2883 /* access ops */
2884 
2885      dcl  access_operations_$lock_mca   bit (36) aligned    external static;
2886      dcl  access_operations_$unlock_mca bit (36) aligned    external static;
2887 
2888 /* structures... */
2889 
2890      dcl  1 console_data      aligned   like      config_data_$console_model_names
2891                                         based     (console_data_ptr);
2892      dcl  1 io_status         aligned   like      io_status_word
2893                                         based     (oc_data.status_ptr);
2894      dcl  1 iom_args          aligned   like      io_manager_arg;
2895      dcl  1 local_io          aligned   like      console_io;
2896      dcl  1 log_message       aligned   like      io_msg;
2897      dcl  1 oc_status         aligned   like      io_status_entry;
2898 
2899 /* status_word overlay... */
2900 
2901      dcl  1 io_status_overlay           based (oc_data.status_ptr),             /* to pick up statuses easily...        */
2902                2 major                  bit       (6),                          /* major status...                      */
2903                2 sub                    bit       (6);                          /* sub status...                        */
2904 
2905 /* miscellaneous... */
2906 
2907      dcl  MAX_MCA                       fixed bin (17)      init      (31)
2908                                         internal static     options (constant);
2909      dcl  MIN_MCA                       fixed bin (17)      init      (0)
2910                                         internal static     options (constant);
2911      dcl  PANIC                         fixed bin (17)      init      (6)       /* call syserr_real$panic...            */
2912                                         internal static     options (constant);
2913      dcl  ad_code                       fixed bin (35);
2914      dcl  audit_eventflags              bit (36) aligned;                       /* access audit flags...                */
2915      dcl  bootload_console_name         char      (4)       aligned;
2916      dcl  console_name                  char      (4)       aligned;
2917      dcl  console_to_check              char      (4)       aligned;            /* for RCP availability...              */
2918      dcl  console_io_flags              char      (80);                         /* string representation of flags...    */
2919      dcl  console_line_length           fixed bin (17);                         /* temp holding space...                */
2920      dcl  cpu_cnt                       fixed bin (17);                         /* number of CPUs in the config file... */
2921      dcl  device_type                   char      (16);                         /* alternate, inoperative, I/O...       */
2922      dcl  entrypoint                    char      (32);                         /* name of where we are in the code...  */
2923      dcl  err_code                      fixed bin (35);                         /* internal standard error code...      */
2924      dcl  error_msg                     char      (80);                         /* error message for reporting...       */
2925      dcl  first_io_slot                 fixed bin (17);                         /* to check for pending I/O...          */
2926      dcl  idx                           fixed bin (17);                         /* miscellaneous working index...       */
2927      dcl  last_io_slot                  fixed bin (17);                         /* to check for pending I/O...          */
2928      dcl  local_time                    fixed bin (71);                         /* miscellaneous time value...          */
2929      dcl  mca_to_unlock                 fixed bin (35);                         /* MCA number to be unlocked...         */
2930      dcl  new_prompt                    char      (8);                          /* new prompt string...                 */
2931      dcl  new_state                     char      (4);                          /* changed state of a console...        */
2932      dcl  oc_data_flags                 char      (80);                         /* string representation of flags...    */
2933      dcl  oc_entry_flags                char      (80);                         /* string representation of flags...    */
2934      dcl  old_console_name              char      (4)       aligned;
2935      dcl  word_length                   fixed bin (19);                         /* length of I/O in words...            */
2936      dcl  pds$process_id                bit       (36)      external  static;
2937      dcl  pds$process_group_id          char      (32)      external  static;
2938      dcl  poll_idx                      fixed bin (17);                         /* index for polling consoles...        */
2939      dcl  reconfig_option               fixed bin (17);                         /* reconfiguration action to take...    */
2940      dcl  time_lock_expires             fixed bin (71);                         /* holder should relinquish by then...  */
2941      dcl  wait_timer                    fixed bin (71);                         /* priority IO wait timer               */
2942      dcl  this_part_length              fixed bin (21);                         /* ASCII char count of part of the write*/
2943      dcl  to_write_length               fixed bin (21);                         /* length of string to write...         */
2944      dcl  wire_mask                     fixed bin (71);                         /* gotten and returned w/o changes...   */
2945 ^L
2946 /* includes... */
2947 
2948 %include access_audit_eventflags;
2949 ^L
2950 %include arg_descriptor;
2951 ^L
2952 %include arg_list;
2953 ^L
2954 %include collection_1_phases;
2955 ^L
2956 %include config_data_dcls;
2957 ^L
2958 %include config_parm_card;
2959 ^L
2960 %include config_prph_opc_card;
2961 ^L
2962 %include config_iom_card;
2963 ^L
2964 %include io_chnl_util_dcls;
2965 ^L
2966 %include io_manager_dcls;
2967 ^L
2968 %include io_status_entry;
2969 ^L
2970 %include io_syserr_msg;
2971 ^L
2972 %include iom_dcw;
2973 ^L
2974 %include iom_pcw;
2975 ^L
2976 %include oc_data;
2977 ^L
2978 %include opc_reconfig_options;
2979 ^L
2980 %include syserr_binary_def;
2981 ^L
2982 %include syserr_constants;
2983 ^L
2984 %include syserr_data;
2985 ^L
2986 /*        BEGIN MESSAGE DOCUMENTATION
2987 
2988 
2989 Message:
2990 ocdcm_ (init_all_consoles): Assigned console OPCx as TYPE device.
2991 
2992 S:        $announce
2993 
2994 T:        $init
2995 
2996 M:        This message appears as the system configures consoles found
2997 in the config file. This message will only appear if the CLST
2998 parameter has been specified on the PARM card. Values for TYPE
2999 are "bootload", "alternate", "I/O", "inoperative" and "off".
3000 
3001 A:        $ignore
3002 
3003 Message:
3004 ocdcm_ (init_all_consoles): Changing state of OPCx to alt.
3005 
3006 S:        $beep
3007 
3008 T:        $init
3009 
3010 M:        During console initialization more than one console was found
3011 to have a state of "on". Since only one bootload console is
3012 allowed the software reconfigures additional "on" consoles as
3013 alternates.
3014 
3015 A:        $config
3016 
3017 Message:
3018 ocdcm_ (init_all_consoles): Unknown model, NNNN, specified for OPCx.
3019        It will not be configured.
3020 
3021 S:        $beep
3022 
3023 T:        $init
3024 
3025 M:        The console model number specified in the config file is not
3026 supported by this software and will not be configured.
3027 
3028 A:        $config
3029 
3030 Message:
3031 ocdcm_ (init_all_consoles): Illegal console name (NAME) specified.
3032 It will be ignored.
3033 
3034 S:        $beep
3035 
3036 T:        $init
3037 
3038 M:        An illegal console name was found. Console names must be values
3039 of "opca" through "opcz".
3040 
3041 A:        $config
3042 
3043 Message:
3044 ocdcm_ (init_all_consoles): Invalid state of STATE for console OPCx.
3045 ocdcm_ (init_all_consoles): This console will not be configured.
3046 
3047 S:        $beep
3048 
3049 T:        $init
3050 
3051 M:        An unrecognizable state was found for the specified console.
3052 That console will not be configured. Only valid states are
3053 "on", "alt", "io", "inop" and "off".
3054 
3055 A:        $config
3056 
3057 Message:
3058 ocdcm_ (init_all_consoles): Maximum console count exceeded.
3059 ocdcm_ (init_all_consoles): Additional consoles will not be configured.
3060 
3061 S:        $beep
3062 
3063 T:        $init
3064 
3065 M:        Too many consoles have been specified in the config file. Only
3066 the maximum number allowable will be configured.
3067 
3068 A:        $config
3069 
3070 Message:
3071 ocdcm_ (reconfigure): Assigned OPCx as an alternate console for PERSON.PROJ.T.
3072 
3073 S:        $beep
3074 
3075 T:        $run
3076 
3077 M:        The specified process has configured the specified console as an
3078 alternate.
3079 
3080 A:        $ignore
3081 
3082 Message:
3083 ocdcm_ (reconfigure): Assigned OPCx as the bootload console for PERSON.PROJ.T.
3084 
3085 S:        $beep
3086 
3087 T:        $run
3088 
3089 M:        The specified process has configured the specified console as
3090 the bootload console. The bootload console at the time of the
3091 reconfiguration is reconfigured as an alternate device.
3092 
3093 A:        $ignore
3094 
3095 Message:
3096 ocdcm_ (reconfigure): Consigned OPCx as an I/O device for PERSON.PROJ.T.
3097 
3098 S:        $beep
3099 
3100 T:        $run
3101 
3102 M:        The specified process has configured the specified console as an
3103 I/O device.
3104 
3105 A:        $ignore
3106 
3107 Message:
3108 ocdcm_ (reconfigure): Marked OPCx as an inoperative device for PERSON.PROJ.T.
3109 
3110 S:        $beep
3111 
3112 T:        $run
3113 
3114 M:        The specified process has configured the specified console as an
3115 inoperative device.
3116 
3117 A:        $ignore
3118 
3119 Message:
3120 ocdcm_ (reconfigure): Timeout executing MCA LOCK on OPCx for PERSON.PROJ.T.
3121 
3122 S:        $log
3123 
3124 T:        $run
3125 
3126 M:        The I/O to LOCK the MCA interface through OPCx did not complete
3127 within a given time.
3128 
3129 A:        This is most likely a hardware failure of the console channel adapter
3130 or the IMU central.
3131 
3132 Message:
3133 ocdcm_ (reconfigure): Timeout executing MCA(nn) UNLOCK on OPCx for PERSON.PROJ.T.
3134 
3135 S:        $log
3136 
3137 T:        $run
3138 
3139 M:        The I/O to UNLOCK the MCA(nn) interface through OPCx did not
3140 complete within a given time.
3141 
3142 A:        This is most likely a hardware failure of the console channel adapter
3143 or the IMU central.
3144 
3145 Message:
3146 ocdcm_ (reconfigure): MCA input through OPCx, disabled by PERSON.PROJ.T.
3147 
3148 S:        $log
3149 
3150 T:        $run
3151 
3152 M:        The input to the MCA (Maint. Channel Adapter) in the IMU
3153 (Interrupt Multiplexer Unit) from special keyboard sequences
3154 has been LOCKed (disabled). Input to the MCA can now only come
3155 from the on-line, Multics controlled, channel 03 interface.
3156 
3157 A:        $ignore
3158 
3159 Message:
3160 ocdcm_ (reconfigure): MCA(nn) input through OPCx, enabled by PERSON.PROJ.T.
3161 
3162 S:        $log
3163 
3164 T:        $run
3165 
3166 M:        The input to MCA(nn) via special console keyboard sequences
3167 has been enabled (UNLOCKed).
3168 
3169 A:        $ignore
3170 
3171 Message:
3172 ocdcm_ (reset_console): Reset bootload console for PERSON.PROJ.T.
3173 
3174 S:        $beep
3175 
3176 T:        $run
3177 
3178 M:        The bootload console has been reset by the specified process.
3179 
3180 A:        $ignore
3181 
3182 Message:
3183 ocdcm_ (init_all_consoles): Invalid channel specified for OPCx.
3184 
3185 S:        $crash
3186 
3187 T:        $init
3188 
3189 M:        The console channel as specified in the config file for the
3190 specified device is illegal.
3191 
3192 A:        $config
3193 
3194 Message:
3195 ocdcm_ (init_all_consoles): Missing prph opc card.
3196 
3197 S:        $crash
3198 
3199 T:        $init
3200 
3201 M:        At least one PRPH OPCx card must be in the config file.
3202 
3203 A:        $config
3204 
3205 Message:
3206 ocdcm_ (init_all_consoles): No active console configured.
3207 
3208 S:        $crash
3209 
3210 T:        $init
3211 
3212 M:        None of the consoles specified in the config file has a state
3213 of "on".
3214 
3215 A:        $config
3216 
3217 Message:
3218 ocdcm_ (bump_io_to_mc): Message Coordinator failure.
3219 
3220 S:        $log
3221 
3222 T:        $run
3223 
3224 M:        The Message Coordinator is no longer able to handle console
3225 traffic.
3226 
3227 A:        Attempt to get an active console online as soon as possible
3228 and reset the Message Coordinator.
3229 
3230 Message:
3231 ocdcm_ (console_recovery): Console failed, assignment of alternate OPCx failed.
3232 
3233 S:        $log
3234 
3235 T:        $run
3236 
3237 M:        The console software detected a failure of the bootload console
3238 and found an alternate to utilize. However, when it tried to
3239 attach the alternate it too was found to be inoperative. The
3240 search continues for a usable console.
3241 
3242 A:        Attempt to determine why the alternate console failed to
3243 come online. If it can be repaired configure it with the
3244 set_system_console command from a highly priviliged process.
3245 
3246 Message:
3247 ocdcm_ (console_recovery): Console inoperative, alternate OPCx assigned.
3248 
3249 S:        $log
3250 
3251 T:        $run
3252 
3253 M:        The software has detected a bootload console failure and has
3254 assigned the specifed alternate to take over. The inoperative
3255 console is flagged as such.
3256 
3257 A:        $notify
3258 
3259 Message:
3260 ocdcm_ (console_recovery): Console inoperative, no alternates available.
3261 
3262 S:        $log
3263 
3264 T:        $run
3265 
3266 M:        The software dected failure of the bootload console, but no
3267 alternates are configured. It will direct subsequent console
3268 traffic to the Message Coordinator.
3269 
3270 A:        Attempt to get a running console online via the set_system_console
3271 command as soon as possible.
3272 
3273 Message:
3274 ocdcm_ (console_recovery): Console inoperative, no alternates, no MC.
3275 
3276 S:        $log
3277 
3278 T:        $run
3279 
3280 M:        The software detected failure of the bootload console, but no
3281 alternates are configured and the Message Coordinator is not
3282 functioning. All subsequent console traffic will be sent to
3283 the syserr log.
3284 
3285 A:        Attempt to get a running console online via the set_system_console
3286 command as soon as possible.
3287 
3288 Message:
3289 ocdcm_ (esd_reset): No active consoles configured.
3290 
3291 S:        $log
3292 
3293 T:        $run
3294 
3295 M:        During ESD there were no consoles in service. ESD messages
3296 will be sent to the syserr log.
3297 
3298 A:        $notify
3299 
3300 Message:
3301 ocdcm_ (interrupt_handler): System Fault.
3302 
3303 S:        $log
3304 
3305 T:        $run
3306 
3307 M:        A system fault interrupt was received from the IOM. The fault
3308 is logged and ignored.
3309 
3310 A:        $notify
3311 
3312 Message:
3313 ocdcm_ (log_console_error): I/O [timeout] error on OPCx; status = SSSSSS
3314         oc_data flags: FLAGS
3315         oc_entry flags: FLAGS
3316         console_io flags: FLAGS
3317 
3318 S:        $log
3319 
3320 T:        $run
3321 
3322 M:        An I/O error occurred. The status is the returned IOM status
3323 for the I/O in question and the flags denote the state of the
3324 oc_data, the console and the I/O, respectively, at the time of
3325 the error. The flag values are interpreted.
3326 
3327 A:        Too many of these errors will result in the invocation of
3328 console recovery. Have the console fixed.
3329 
3330 Message:
3331 ocdcm_ (bump_io_to_mc): Console recovery failure.
3332 
3333 S:        $crash
3334 
3335 T:        $run
3336 
3337 M:        The software detected Message Coordinator failure while the
3338 Message Coordinator was being used in place of a functioning
3339 console. Since the CCRF parameter was specified the system
3340 crashed.
3341 
3342 A:        $inform
3343 $inform_sa
3344 
3345 Message:
3346 ocdcm_ (console_recovery): Console recovery failure.
3347 
3348 S:        $crash
3349 
3350 T:        $run
3351 
3352 M:        The software detected console failure and was unable to continue
3353 because the CCRF parameter was specified. The system crashed.
3354 
3355 A:        $inform
3356 $inform_sa
3357 
3358 Message:
3359 ocdcm_ (init_all_consoles): Console channel assignment failed.
3360 
3361 S:        $crash
3362 
3363 T:        $run
3364 
3365 M:        Attachment of the specified bootload console failed during
3366 initialization.
3367 
3368 A:        This is most likely a hardware failure of the console channel
3369 adapter.
3370 
3371 Message:
3372 ocdcm_ (init_all_consoles): Unable to determine absolute memory address of
3373        oc_data.
3374 
3375 S:        $crash
3376 
3377 T:        $run
3378 
3379 M:        The absloute memory address of oc_data could not be determined
3380 during console initialization.
3381 
3382 A:        This is a very serious error. Ensure that your MST is good and
3383 then consider hardware.
3384 
3385 Message:
3386 ocdcm_ (lock_oc_data): Mylock error.
3387 
3388 S:        $crash
3389 
3390 T:        $run
3391 
3392 M:        The offending process found its own process_id in the lock.
3393 
3394 A:        $inform
3395 
3396 Message:
3397 ocdcm_ (lock_oc_data): Lock wait timer expired.
3398 
3399 S:        $crash
3400 
3401 T:        $run
3402 
3403 M:        A process waiting on the lock was not able to get the lock before
3404 the wait timer expired. This timer is calculated as the maximum
3405 time that it should take a READ I/O to complete times the number of
3406 CPUs specified in the config file. Any process waiting on the lock
3407 should never have to wait more than that amount of time for the
3408 lock to become available without there being a serious problem
3409 with the hardcore process holding the lock.
3410 
3411 A:        $inform
3412 
3413 Message:
3414 ocdcm_ (reconfigure): Bootload console deconfigured with CCRF set.
3415 
3416 S:        $crash
3417 
3418 T:        During console reconfiguration.
3419 
3420 M:        The bootload console was deconfigured by use of the
3421 set_system_console command and the site had specified the CCRF
3422 parameter in the config file.
3423 
3424 A:        $recover
3425 
3426 Message:
3427 ocdcm_ (unlock_oc_data): Lock not mine.
3428 
3429 S:        $crash
3430 
3431 T:        $run
3432 
3433 M:        A process attempting to unlock oc_data found a non-zero lock
3434 that was not its own.
3435 
3436 A:        $inform
3437 
3438 END MESSAGE DOCUMENTATION */
3439 
3440 end ocdcm_;