*copy osd$default_pragmats
?? NEWTITLE := 'NOS/VE Device Management' ??
MODULE dmm$transfer_unit_completed;
?? RIGHT := 110 ??

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$mainframe_wired_literal
*copyc amt$file_byte_address
*copyc dmt$active_volume_table_index
*copyc dmt$assigned_ms_vol_attributes
*copyc dmt$device_allocation_unit
*copyc dmt$error_condition_codes
*copyc dmt$file_allocation_descriptor
*copyc dmt$file_attributes
*copyc dmt$file_medium_descriptor
*copyc dmt$file_table_lock
*copyc dmt$log_flaw_init_data
*copyc dmt$minimum_allocation_unit
*copyc dmt$ms_logical_device_address
*copyc dst$system_message_types
*copyc gft$locked_file_desc_entry_p
*copyc gft$system_file_identifier
*copyc iot$cylinder
*copyc iot$io_function
*copyc jmt$ajl_ordinal
*copyc jmt$ijl_ordinal
*copyc syt$monitor_request_code
?? POP ??
*copyc dpp$convert_int_to_str_hex
*copyc dmp$get_disk_file_descriptor_p
*copyc dmp$get_fau_entry
*copyc dmp$get_fmd_by_index
*copyc dmp$mtr_log
*copyc dpp$display_error
*copyc dsp$report_system_message
*copyc gfp$mtr_get_locked_fde_p
*copyc jmf$ijle_p
*copyc jmp$lock_ajl
*copyc jmp$unlock_ajl
*copyc mtp$error_stop
*copyc tmp$clear_lock
*copyc tmp$get_xcb_access_status
*copyc tmp$set_lock
*copyc dmv$active_volume_table
*copyc dmv$allocation_log
*copyc dmv$null_vsn
*copyc gfv$null_sfid
*copyc jmv$ijl_p
*copyc tmv$ptl_lock
*copyc cml$ms_media_flaw_change
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] dmp$transfer_unit_complete', EJECT ??
*copy dmh$transfer_unit_completed

  PROCEDURE [XDCL] dmp$transfer_unit_completed
    (    job_id: jmt$ijl_ordinal;
         system_file_id: gft$system_file_identifier;
         byte_address: amt$file_byte_address;
         write_tu_status: dmt$write_tu_status;
         au_was_previously_written: boolean;
         media_error: boolean;
         cylinder: iot$cylinder;
         mau_offset_in_cylinder: dmt$maus_per_position;
         io_function: iot$io_function;
     VAR status: syt$monitor_status);

    VAR
      able_to_log: boolean,
      ajlo: jmt$ajl_ordinal,
      al_entry: dmt$al_entry,
      avt_index: dmt$active_volume_table_index,
      dau: dmt$dau_address,
      entry_p: ^dmt$ms_active_vol_table_entry,
      p_dfd: ^dmt$disk_file_descriptor,
      fau_state: dmt$fau_states,
      p_fde: gft$locked_file_desc_entry_p,
      flaw_logging_data: dmt$monitor_flaw_init_data,
      p_fmd: ^dmt$file_medium_descriptor,
      ijle_p: ^jmt$initiated_job_list_entry,
      inhibit_access: boolean,
      logging_active_for_volume: boolean,
      logging_required_for_file: boolean,
      message_recorded: boolean,
      p_fau: ^dmt$file_allocation_unit,
      p_flaw_logging_data: ^SEQ ( * );

?? NEWTITLE := 'p$display_error', EJECT ??

    PROCEDURE p$display_error;

      VAR
        str: string (80);

      str := ' Invalid DAU flaw address. Unit= xxxxxx, DAU=';
      str (34, 6) := entry_p^.recorded_vsn;
      dpp$convert_int_to_str_hex (8, dau, str (46, 8));

      dpp$display_error (str (1, 54));

    PROCEND p$display_error;
?? OLDTITLE ??
?? EJECT ??
    status.normal := TRUE;

  /process_request/
    BEGIN
      ijle_p := jmf$ijle_p (job_id);

      { No processing is necessary for local file writes unless there was an
      { error and write_tu_status = dmc$tu_not_written.

{Job & Write
      IF (system_file_id.residence = gfc$tr_job) AND ((io_function = ioc$write_page) OR
            (io_function = ioc$write_locked_page)) THEN

        { Since ijle_p^.inhibit_swap_count is not updated for local file writes, the job
        { may have terminated and the IJL block released.  Or since p_fde.read_write_count
        { is not updated, the file may have been deleted.  The caller of this routine has
        { set write_tu_status to dmc$tu_written if this is the case.

        IF (write_tu_status = dmc$tu_written) THEN
          RETURN; {----->
        IFEND;

        { If the job is swapped to a point that we can no longer access the file tables,
        { we will wait until the job swaps back in to process the error.

        tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
        tmp$get_xcb_access_status (ijle_p, job_id, inhibit_access);
        tmp$clear_lock (tmv$ptl_lock);
        IF inhibit_access THEN
          RETURN; {----->
        IFEND;

{ Locate the file descriptor.
{ The ajl ordinal in the ijle is used to locate the file descriptor of a local file.
{ Tmp$get_xcb_access_status has assigned an ajl or incremented the ajl in_use count
{ if the I/O was for a local file.  The ajl must be unlocked when processing is completed.

        gfp$mtr_get_locked_fde_p (system_file_id, ijle_p, p_fde);
        dmp$get_disk_file_descriptor_p (p_fde, p_dfd);

      ELSE
        IF (system_file_id.residence = gfc$tr_job) THEN
          jmp$lock_ajl (ijle_p, job_id, ajlo);
        IFEND;

{ Locate the file descriptor.
{ The ajl ordinal in the ijle is used to locate the file descriptor of a local file.
{ Jmp$lock_ajl has assigned an ajl or incremented the ajl in_use count if the I/O was for a
{ local file.  The ajl must be unlocked when processing is completed.

        gfp$mtr_get_locked_fde_p (system_file_id, ijle_p, p_fde);
        dmp$get_disk_file_descriptor_p (p_fde, p_dfd);

        p_dfd^.read_write_count := p_dfd^.read_write_count - 1;
      IFEND;


{ Media Error or AU not initialized
      IF NOT au_was_previously_written OR media_error THEN
        dmp$get_fau_entry (p_dfd, byte_address, p_fau);
        dmp$get_fmd_by_index (p_dfd, p_fau^.fmd_index, p_fmd);

        avt_index := p_fmd^.avt_index;
        IF (avt_index <= 0) OR (avt_index > UPPERBOUND (dmv$active_volume_table.table_p^)) OR
              dmv$active_volume_table.table_p^ [avt_index].entry_available THEN
          mtp$error_stop ('unable to locate avt entry - DMP$TRANSFER_UNIT_COMPLETED');
        ELSE
          entry_p := ^dmv$active_volume_table.table_p^ [avt_index].mass_storage;
        IFEND;

        logging_active_for_volume := (entry_p^.p_device_log <> gfv$null_sfid);
        logging_required_for_file := (p_fde^.file_kind <= gfc$fk_last_permanent_file);

        IF NOT au_was_previously_written THEN
          IF write_tu_status = dmc$tu_written THEN
            fau_state := dmc$fau_initialized;
          ELSE
            fau_state := dmc$fau_invalid_data;
          IFEND;

          IF ((system_file_id.residence <> gfc$tr_job) OR ((io_function <> ioc$write_page) AND
                (io_function <> ioc$write_locked_page))) AND (p_fau^.state <> dmc$fau_initialization_in_prog)
                THEN
            mtp$error_stop ('fau already initialized - DMP$TRANSFER_UNIT_COMPLETED');
          IFEND;

          p_fau^.state := fau_state;
          IF fau_state = dmc$fau_initialized THEN
            IF logging_active_for_volume AND logging_required_for_file THEN
              al_entry.avt_index := avt_index;
              al_entry.kind := dmc$al_initialize;
              al_entry.initialize_block.global_file_name := p_fde^.global_file_name;
              al_entry.initialize_block.dfl_index := p_fmd^.dfl_index;
              al_entry.initialize_block.dau_address := p_fau^.dau_address;
              dmp$mtr_log (al_entry, able_to_log);
              IF NOT able_to_log THEN
                mtp$error_stop ('incomplete initialization - DMP$TRANSFER_UNIT_COMPLETED');
              IFEND;
            IFEND;
          IFEND;

          IF logging_required_for_file THEN
            dmv$allocation_log.committed_initialize_count := dmv$allocation_log.committed_initialize_count -
                  1;
          IFEND;
        IFEND;

        IF media_error THEN
          IF ((p_fau^.state = dmc$fau_invalid_data) OR (p_fau^.state = dmc$fau_initialized)) AND
                logging_active_for_volume THEN

            dau := (cylinder * p_fmd^.daus_per_cylinder) + (mau_offset_in_cylinder DIV p_fmd^.maus_per_dau);

            IF (dau < p_fau^.dau_address) OR (dau >= (p_fau^.dau_address + p_fmd^.daus_per_allocation_unit))
                  THEN
              p$display_error;

              mtp$error_stop ('Invalid DAU flaw address.');

              EXIT /process_request/; {----->
            IFEND;

            al_entry.avt_index := avt_index;
            al_entry.kind := dmc$al_software_flawed;
            al_entry.software_flaw_block.dau_address := dau;
            al_entry.software_flaw_block.flaw_option := dmc$add_flaw;

            dmp$mtr_log (al_entry, able_to_log);
            IF NOT able_to_log THEN
              dpp$display_error ('DM unable to log flaw - DMP$TRANSFER_UNIT_COMPLETED');
              EXIT /process_request/; {----->
            IFEND;

            flaw_logging_data.message_type := cml$ms_media_flaw_change;
            flaw_logging_data.flaw_data.recorded_vsn := entry_p^.recorded_vsn;
            flaw_logging_data.flaw_data.first_dau := dau;
            flaw_logging_data.flaw_data.last_dau := dau;
            flaw_logging_data.flaw_data.operation_code := dmc$oc_flaw_define;
            flaw_logging_data.flaw_data.initiator_code := dmc$ic_system_initiated;
            p_flaw_logging_data := #SEQ (flaw_logging_data);
            dsp$report_system_message (p_flaw_logging_data, dsc$general_system_message,
                  dsc$informative_message, message_recorded);
          IFEND;

          CASE p_fau^.state OF
          = dmc$fau_invalid_and_flawed, dmc$fau_initialized_and_flawed =
          = dmc$fau_initialized =
            p_fau^.state := dmc$fau_initialized_and_flawed;
          = dmc$fau_invalid_data =
            p_fau^.state := dmc$fau_invalid_and_flawed;
          ELSE
            dpp$display_error ('probably a transfer flaw problem - DMP$TRANSFER_UNIT_COMPLETED');
            EXIT /process_request/; {----->
          CASEND;
        IFEND;
      IFEND;
    END /process_request/;

{ Decrement the ajl in use count for local files.
    IF (system_file_id.residence = gfc$tr_job) THEN
      jmp$unlock_ajl (ijle_p);
    IFEND;

  PROCEND dmp$transfer_unit_completed;
?? OLDTITLE ??
MODEND dmm$transfer_unit_completed;
