?? RIGHT := 110 ??
MODULE sym$mtr_inject_hardware_fault;

{ PURPOSE:
{   This module contains the procedures to inject various hardware faults on the 960.
{
{ DESIGN:
{   Special microcode is required to run with this utility that actually causes the
{   desired hardware fault.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ost$cpu_state_table
*copyc syt$rb_inject_hardware_fault
*copyc sye$system_conditions
?? POP ??
*copyc i#mtr_disable_traps
*copyc i#mtr_restore_traps
*copyc mtp$set_status_abnormal
*copyc syp$cause_hardware_faults
*copyc syv$enable_fault_injection
?? TITLE := 'syp$mtrj_inject_hardware_fault', EJECT ??

{ PURPOSE:
{   This procedure processes the monitor request to inject hardware faults in monitor mode.

  PROCEDURE [XDCL] syp$mtr_inject_hardware_fault
    (VAR request_block: syt$rb_inject_hardware_fault;
         cst_p: ^ost$cpu_state_table);

    VAR
      old_te: 0 .. 3;

    request_block.status.normal := TRUE;
    IF (cst_p^.ajlo <> 0) OR NOT syv$enable_fault_injection THEN
      mtp$set_status_abnormal ('SY', sye$unimplemented_request, request_block.status);
      RETURN;
    IFEND;

    IF NOT request_block.traps_enabled THEN
      i#mtr_disable_traps (old_te);
    IFEND;

    IF request_block.hardware_fault_request < syc$hfk_uf_null_function THEN
      syp$cause_hardware_faults (request_block.hardware_fault_request, request_block.rma,
            request_block.status.normal);
    ELSE

      {  Process utility functions.

      CASE request_block.hardware_fault_request OF
      = syc$hfk_uf_clear_sync_in_mm =

        {  Clear the synchronous bits in monitor mask of the exchange package of task making the request
        {  except for page fault.  Want to allow the task to page fault but processor will halt for
        {  other errors.

        cst_p^.xcb_p^.xp.monitor_mask := cst_p^.xcb_p^.xp.monitor_mask -
              $ost$monitor_conditions [osc$detected_uncorrected_err, osc$not_assigned, osc$instruction_spec,
              osc$address_specification, osc$access_violation, osc$environment_spec,
              osc$invalid_segment_ring_0, osc$out_call_in_return];
      ELSE
        mtp$set_status_abnormal ('SY', sye$unimplemented_request, request_block.status);
      CASEND;
    IFEND;

    IF NOT request_block.traps_enabled THEN
      i#mtr_restore_traps (old_te);
    IFEND;

  PROCEND syp$mtr_inject_hardware_fault;
MODEND sym$mtr_inject_hardware_fault;
