?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Dump Analyzer : Display CIO Registers Command' ??
MODULE dum$display_cio_regs_command;

{ PURPOSE:
{   This module contains the command which displays the CIO register information that
{   is contained in the CCR and CC1 dump records.
{        CCR - channel registers of the primary IOU element.
{        CC1 - channel registers of the secondary IOU element.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc due$exception_condition_codes
?? POP ??
*copyc clp$close_display
*copyc clp$convert_integer_to_rjstring
*copyc clp$evaluate_parameters
*copyc clp$open_display_reference
*copyc clp$put_display
*copyc dup$find_record_list_entry
*copyc dup$new_page_procedure
*copyc dup$retrieve_register
*copyc osp$append_status_integer
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$set_status_abnormal
?? EJECT ??
*copyc duv$dump_environment_p
*copyc duv$execution_environment
*copyc duv$title_data
?? OLDTITLE ??
?? NEWTITLE := 'convert_display_to_ascii', EJECT ??

{ PURPOSE:
{   This function converts a display character to an ascii character.

  FUNCTION convert_display_to_ascii (display_character: 0 .. 3f(16)): char;

    CONST
      c$a_display_code = 1,
      c$zero_display_code = 27,
      c$nine_display_code = 36,
      c$numeric_bias = 48,
      c$alphabetic_bias = 65;

    IF (display_character >= c$zero_display_code) AND (display_character <= c$nine_display_code) THEN
      convert_display_to_ascii := $CHAR (c$numeric_bias + (display_character - c$zero_display_code));
    ELSE
      convert_display_to_ascii := $CHAR (c$alphabetic_bias + (display_character - c$a_display_code));
    IFEND;

  FUNCEND convert_display_to_ascii;
?? OLDTITLE ??
?? NEWTITLE := 'dup$display_cio_regs_command', EJECT ??

{ PURPOSE:
{   This procedure displays the cio registers.

  PROCEDURE [XDCL] dup$display_cio_regs_command
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE display_cio_registers, discr (
{   output, o: file = $optional
{   title, t: string 1..31 = 'display_cio_registers'
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??
  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 5] of clt$pdt_parameter_name,
      parameters: array [1 .. 3] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$string_type_qualifier,
        default_value: string (23),
      recend,
      type3: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [90, 4, 18, 8, 54, 14, 616],
    clc$command, 5, 3, 0, 0, 0, 0, 3, ''], [
    ['O                              ',clc$abbreviation_entry, 1],
    ['OUTPUT                         ',clc$nominal_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 3],
    ['T                              ',clc$abbreviation_entry, 2],
    ['TITLE                          ',clc$nominal_entry, 2]],
    [
{ PARAMETER 1
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3, clc$optional_parameter, 0
  , 0],
{ PARAMETER 2
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 8,
  clc$optional_default_parameter, 0, 23],
{ PARAMETER 3
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$file_type]],
{ PARAMETER 2
    [[1, 0, clc$string_type], [1, 31, FALSE],
    '''display_cio_registers'''],
{ PARAMETER 3
    [[1, 0, clc$status_type]]];
?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$output = 1,
      p$title = 2,
      p$status = 3;

    VAR
      pvt: array [1 .. 3] of clt$parameter_value;

    TYPE
      t$ascii_char_data = RECORD
        CASE boolean OF
        = TRUE =
          data: string (2),
        = FALSE =
          char_1: char,
          char_2: char,
        CASEND,
      RECEND,

      t$channel_data = PACKED RECORD
        unused: 0 .. 0ff(16),
        data: 0 .. 0ff(16),
      RECEND,

      t$data_line = RECORD
        CASE boolean OF
        = TRUE =
          line: string (79),
        = FALSE =
          unused_1: string (1),
          iou_name: string (3),
          iou_number: string (2),
          unused_2: string (1),
          cio_name: string (3),
          channel_number: string (2),
          colon: string (1),
          unused_3: string (1),
          channel_type: string (16),
          unused_4: string (2),
          status_register: ARRAY [1 .. 4] OF t$register_string,
          unused_5: string (1),
          t_register: ARRAY [1 .. 3] OF t$register_string,
          unused_6: string (1),
          flag_mask: string (4),
          unused_7: string (3),
          test_mode_operand: string (2),
        CASEND,
      RECEND,

      t$display_code_data = PACKED RECORD
        unused: 0 .. 0f(16),
        char_1: 0 .. 77(8),
        char_2: 0 .. 77(8),
      RECEND,

      t$flag_mask = RECORD
        CASE boolean OF
        = TRUE =
          data: 0 .. 0ffff(16),
        = FALSE =
          list: ARRAY [1 .. 2] OF 0 .. 0ff(16),
        CASEND,
      RECEND,

      t$register_entry = PACKED RECORD
        channel_number: t$display_code_data,
        channel_type: t$display_code_data,
        t_register: PACKED ARRAY [0 .. 5] OF t$channel_data,
        flag_mask: PACKED ARRAY [1 .. 2] OF t$channel_data,
        test_mode_operand: t$channel_data,
      RECEND,

      t$register_list_entry = RECORD
        available: boolean,
        iou_number: 0 .. 1,
        channel_number: t$ascii_char_data,
        channel_type: t$ascii_char_data,
        status_register: t$status_register,
        t_register: t$t_register,
        flag_mask: t$flag_mask,
        test_mode_operand: 0 .. 0ff(16),
      RECEND,

      t$register_string = RECORD
        data: string (4),
        unused: string (1),
      RECEND,

      t$status_register = RECORD
        CASE boolean OF
        = TRUE =
          data: ARRAY [1 .. 4] OF 0 .. 0ffff(16),
        = FALSE =
          value: ARRAY [1 .. duc$de_max_register_length] OF 0 .. 0ff(16),
        CASEND,
      RECEND,

      t$t_register = RECORD
        CASE boolean OF
        = TRUE =
          data: ARRAY [1 .. 3] OF 0 .. 0ffff(16),
        = FALSE =
          list: ARRAY [0 .. 5] OF 0 .. 0ff(16),
        CASEND,
      RECEND,

      t$title_line = RECORD
        CASE boolean OF
        = TRUE =
          line: string (79),
        = FALSE =
          unused_1: string (34),
          status_register: string (15),
          unused_2: string (6),
          t_register: string (10),
          unused_3: string (4),
          flag_mask: string (4),
          unused_4: string (2),
          test_mode_operand: string (4),
        CASEND,
      RECEND;

    VAR
      cc1_entry_p: ^dut$de_other_record_entry,
      cell_p: ^cell,
      channels_still_exist: boolean,
      checked_cc1: boolean,
      data_line: t$data_line,
      data_size: integer,
      data_value: clt$data_value,
      display_control: clt$display_control,
      entry_p: ^dut$de_other_record_entry,
      ignore_status: ost$status,
      index: 1 .. duc$de_maximum_channels,
      index_2: 0 .. 5,
      iou_number: 0 .. duc$de_maximum_ious,
      output_display_opened: boolean,
      register: dut$de_maintenance_register,
      register_entry_p: ^t$register_entry,
      register_list: ARRAY [1 .. duc$de_maximum_channels] OF t$register_list_entry,
      register_number: 0 .. duc$de_max_register_number,
      restart_file_seq_p: ^SEQ ( * ),
      ring_attributes: amt$ring_attributes,
      title_line: t$title_line;

*copy dup$abort_handler
?? NEWTITLE := 'clean_up', EJECT ??

{ PURPOSE:
{   This procedure is called from the abort handler to close the file.

    PROCEDURE [INLINE] clean_up;

      VAR
        ignore_status: ost$status;

      IF output_display_opened THEN
        clp$close_display (display_control, ignore_status);
      IFEND;

    PROCEND clean_up;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;  {---->
    IFEND;

    IF duv$dump_environment_p = NIL THEN
      osp$set_status_abnormal (duc$dump_analyzer_id, due$no_restart_file, '', status);
      RETURN;  {---->
    IFEND;

    output_display_opened := FALSE;
    osp$establish_block_exit_hndlr (^abort_handler);

   /display_opened/
    BEGIN

    { Prepare the output display file.

      IF pvt [p$output].specified THEN
        ring_attributes.r1 := #RING (^ring_attributes);
        ring_attributes.r2 := #RING (^ring_attributes);
        ring_attributes.r3 := #RING (^ring_attributes);
        clp$open_display_reference (pvt [p$output].value^.file_value^, ^dup$new_page_procedure, fsc$list,
              ring_attributes, display_control, status);
        IF NOT status.normal THEN
          EXIT /display_opened/;  {---->
        IFEND;
        output_display_opened := TRUE;
      ELSE
        display_control := duv$execution_environment.output_file.display_control;
        display_control.line_number := display_control.page_length + 1;
      IFEND;

      duv$title_data.build_title := TRUE;
      duv$title_data.command_name := pvt [p$title].value^.string_value^;

      data_value.kind := clc$name;
      data_value.name_value := 'CCR';
      dup$find_record_list_entry (data_value, entry_p);
      IF entry_p = NIL THEN
        osp$set_status_abnormal (duc$dump_analyzer_id, due$data_not_on_dump, 'The specified record is',
              status);
        EXIT /display_opened/;  {---->
      IFEND;

      FOR index := 1 TO duc$de_maximum_channels DO
        register_list [index].available := FALSE;
      FOREND;

      restart_file_seq_p := duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer;
      cell_p := #ADDRESS (#RING (restart_file_seq_p), #SEGMENT (restart_file_seq_p), entry_p^.first_byte);
      RESET restart_file_seq_p TO cell_p;
      data_size := entry_p^.size;
      channels_still_exist := (data_size >= #SIZE (t$register_entry));
      checked_cc1 := FALSE;
      iou_number := 0;
      index := 1;

      WHILE channels_still_exist DO
        NEXT register_entry_p IN restart_file_seq_p;
        IF register_entry_p = NIL THEN
          osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);
          EXIT /display_opened/;  {---->
        IFEND;
        data_size := data_size - #SIZE (t$register_entry);
        register_list [index].available := TRUE;
        register_list [index].iou_number := iou_number;
        register_list [index].channel_number.char_1 :=
              convert_display_to_ascii (register_entry_p^.channel_number.char_1);
        register_list [index].channel_number.char_2 :=
              convert_display_to_ascii (register_entry_p^.channel_number.char_2);
        register_list [index].channel_type.char_1 :=
              convert_display_to_ascii (register_entry_p^.channel_type.char_1);
        register_list [index].channel_type.char_2 :=
              convert_display_to_ascii (register_entry_p^.channel_type.char_2);
        FOR index_2 := 0 TO 5 DO
          register_list [index].t_register.list [index_2] := register_entry_p^.t_register [index_2].data;
        FOREND;
        FOR index_2 := 1 TO 2 DO
          register_list [index].flag_mask.list [index_2] := register_entry_p^.flag_mask [index_2].data;
        FOREND;
        register_list [index].test_mode_operand := register_entry_p^.test_mode_operand.data;
        index := index + 1;
        IF data_size < #SIZE (t$register_entry) THEN
          IF checked_cc1 THEN
            channels_still_exist := FALSE;
          ELSE
            checked_cc1 := TRUE;
            data_value.kind := clc$name;
            data_value.name_value := 'CC1';
            dup$find_record_list_entry (data_value, cc1_entry_p);
            IF cc1_entry_p = NIL THEN
              channels_still_exist := FALSE;
            ELSE
              restart_file_seq_p := duv$execution_environment.data_file_p^.segment_pointer.sequence_pointer;
              cell_p := #ADDRESS (#RING (restart_file_seq_p), #SEGMENT (restart_file_seq_p),
                    cc1_entry_p^.first_byte);
              RESET restart_file_seq_p TO cell_p;
              data_size := cc1_entry_p^.size;
              channels_still_exist := (data_size >= #SIZE (t$register_entry));
              iou_number := 1;
            IFEND;
          IFEND;
        IFEND;
      WHILEND;

     /register_loop/
      FOR index := 1 TO duc$de_maximum_channels DO
        IF NOT register_list [index].available THEN
          EXIT /register_loop/;  {---->
        IFEND;
        register_number := ((($INTEGER (register_list [index].channel_number.char_1) - 30(16)) * 10(8)) +
              ($INTEGER (register_list [index].channel_number.char_2) - 30(16))) + 0b0(16);
        iou_number := register_list [index].iou_number;

        dup$retrieve_register (duc$de_iou, iou_number, register_number, register);
        register_list [index].status_register.value := register.value;
      FOREND /register_loop/;

      clp$put_display (display_control, 'CIO Channel Registers', clc$trim, ignore_status);
      clp$put_display (display_control, ' ', clc$trim, ignore_status);

      title_line.line := ' ';
      title_line.flag_mask := 'FLAG';
      title_line.test_mode_operand := 'TEST';
      clp$put_display (display_control, title_line.line, clc$trim, ignore_status);

      title_line.line := ' ';
      title_line.status_register := 'STATUS REGISTER';
      title_line.t_register := 'T REGISTER';
      title_line.flag_mask := 'MASK';
      title_line.test_mode_operand := 'MODE';
      clp$put_display (display_control, title_line.line, clc$trim, ignore_status);

      title_line.line := ' ';
      title_line.status_register := '---------------';
      title_line.t_register := '----------';
      title_line.flag_mask := '----';
      title_line.test_mode_operand := '----';
      clp$put_display (display_control, title_line.line, clc$trim, ignore_status);

      FOR index := 1 TO duc$de_maximum_channels DO
        IF NOT register_list [index].available THEN
          EXIT /display_opened/;  {---->
        IFEND;

        data_line.line := ' ';
        data_line.iou_name := 'IOU';
        clp$convert_integer_to_rjstring (register_list [index].iou_number, 8, FALSE, '0',
              data_line.iou_number, ignore_status);
        data_line.cio_name := 'CCH';
        data_line.channel_number := register_list [index].channel_number.data;
        data_line.colon := ':';

        IF register_list [index].channel_type.data = '01' THEN
          data_line.channel_type := '170 Channel';
        ELSEIF register_list [index].channel_type.data = '02' THEN
          data_line.channel_type := 'ISI Channel';
        ELSEIF register_list [index].channel_type.data = '03' THEN
          data_line.channel_type := 'ISI DMA Channel';
        ELSEIF register_list [index].channel_type.data = '04' THEN
          data_line.channel_type := 'Internal Channel';
        ELSEIF register_list [index].channel_type.data = '05' THEN
          data_line.channel_type := '170 DMA ESM';
        ELSEIF register_list [index].channel_type.data = '06' THEN
          data_line.channel_type := '25MB IPI DMA';
        ELSEIF register_list [index].channel_type.data = '07' THEN
          data_line.channel_type := 'IPI DMA Channel';
        ELSEIF register_list [index].channel_type.data = '10' THEN
          data_line.channel_type := 'PP Comm Channel';
        ELSEIF register_list [index].channel_type.data = '11' THEN
          data_line.channel_type := 'SCSI Interface';
        ELSEIF register_list [index].channel_type.data = '17' THEN
          data_line.channel_type := 'Not Installed';
        ELSE
          data_line.channel_type := 'Unknown';
        IFEND;

        FOR index_2 := 1 TO 4 DO
          clp$convert_integer_to_rjstring (register_list [index].status_register.data [index_2], 16, FALSE,
                '0', data_line.status_register [index_2].data, ignore_status);
        FOREND;

        FOR index_2 := 1 TO 3 DO
          clp$convert_integer_to_rjstring (register_list [index].t_register.data [index_2], 16, FALSE,
                '0', data_line.t_register [index_2].data, ignore_status);
        FOREND;

        clp$convert_integer_to_rjstring (register_list [index].flag_mask.data, 16, FALSE,
              '0', data_line.flag_mask, ignore_status);

        clp$convert_integer_to_rjstring (register_list [index].test_mode_operand, 16, FALSE,
              '0', data_line.test_mode_operand, ignore_status);

        clp$put_display (display_control, data_line.line, clc$trim, ignore_status);
      FOREND;

    END /display_opened/;

    IF output_display_opened THEN
      clp$close_display (display_control, ignore_status);
    IFEND;
    osp$disestablish_cond_handler;

  PROCEND dup$display_cio_regs_command;
MODEND dum$display_cio_regs_command;
