?? NEWTITLE := 'NOS/VE :  INPUT OUTPUT MANAGER' ??
MODULE iom$queue_image_request;
?? RIGHT := 110 ??

?? NEWTITLE := 'Global Declarations Referenced By This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc syc$monitor_request_codes
*copyc osd$default_pragmats
*copyc ioe$st_errors
*copyc amt$file_byte_address
*copyc dmt$ms_logical_device_address
*copyc gft$system_file_identifier
*copyc iot$command
*copyc iot$cylinder
*copyc iot$device_table
*copyc iot$disk_request
*copyc iot$disk_type_table
*copyc iot$image_request
*copyc iot$io_request
*copyc iot$logical_unit
*copyc iot$number_of_requests
*copyc iot$rb_translate_byte_address
*copyc iot$unit_type
*copyc jmt$ajl_ordinal
*copyc ost$hardware_subranges
*copyc ost$status

  VAR
    dmv$external_interrupt_selector: [XREF] 0 .. 0ff(16),
    osv$external_interrupt_selector: [XREF] 0 .. 0ff(16),
    iov$disk_type_table: [XREF] array [1 .. ioc$disk_type_count] of iot$disk_type_table;

?? POP ??
*copyc cmv$logical_unit_table
*copyc i#call_monitor
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] IOP$QUEUE_IMAGE_REQUEST', EJECT ??

  PROCEDURE [XDCL, #GATE] iop$queue_image_request
    (    system_file_id: gft$system_file_identifier;
         file_byte_address: amt$file_byte_address;
         length: ost$byte_count;
         image_request_area: ^SEQ ( * );
     VAR status: ost$status);

    VAR
      request_area: ^SEQ ( * ),
      image_request: iot$image_request,
      image_request_p: ^iot$image_request,
      image_disk_request: iot$image_disk_request,
      number_of_commands: iot$commands_per_request,
      command: iot$command,
      i: integer,
      command_p: ^iot$command,
      rma: integer,
      last_rma: integer,
      job_id: jmt$ajl_ordinal,
      cylinder: iot$cylinder,
      track: iot$track,
      sector: iot$sector,
      sector_offset_within_cylinder: 0 .. 1280,
      device_address: dmt$ms_logical_device_address,
      logical_unit: iot$logical_unit,
      index: 1 .. ioc$disk_type_count,
      request_block: iot$rb_translate_byte_address,
      dm_status: syt$monitor_status,
      next_io_request: ^iot$io_request,
      pva: ^cell,
      first: boolean,
      previous_io_request: ^iot$io_request,
      previous_request: ^iot$image_disk_request,
      search_test: boolean,
      p_unit_table: ^iot$unit_interface_table,
      word_boundary: integer;

    status.normal := TRUE;

  /image/
    BEGIN

      request_area := image_request_area;
      NEXT image_request_p IN request_area;

      word_boundary := image_request_p^.image_disk_request.request_length -
            (image_request_p^.image_disk_request.request_length DIV 8) * 8;
      IF word_boundary <> 0 THEN
        status.normal := FALSE;
        status.condition := ioc$invalid_image_request;
        EXIT /image/; {----->
      IFEND;

      image_request_p^.image_disk_request.recovery := ioc$attempt_recovery;
      image_request_p^.image_disk_request.interrupt.value := FALSE;
      image_request_p^.image_disk_request.interrupt.port_number := osv$external_interrupt_selector;
      image_request_p^.image_disk_request.priority := 1;
      image_request_p^.image_disk_request.alert_mask.long_input_block := FALSE;
      image_request_p^.image_disk_request.alert_mask.compare_not_satisfied := TRUE;
      image_request_p^.image_disk_request.alert_mask.physical_delimiter := FALSE;
      image_request_p^.image_disk_request.alert_mask.logical_delimiter := FALSE;
      image_request_p^.image_disk_request.alert_mask.character_fill := FALSE;
      image_request_p^.io_request.device_request_p := ^image_request_p^.image_disk_request;


      number_of_commands := (image_request_p^.image_disk_request.request_length -
            #SIZE (image_disk_request)) DIV #SIZE (command);
      FOR i := 1 TO number_of_commands DO
        NEXT command_p IN request_area;
        CASE command_p^.command_code OF
        = ioc$cc_write_bytes, ioc$cc_read_bytes =
        ELSE
          status.normal := FALSE;
          status.condition := ioc$invalid_image_request;
          EXIT /image/; {----->
        CASEND;
        word_boundary := command_p^.length - (command_p^.length DIV 8) * 8;
        IF word_boundary <> 0 THEN
          status.normal := FALSE;
          status.condition := ioc$invalid_image_request;
          EXIT /image/; {----->
        IFEND;
        word_boundary := command_p^.address - (command_p^.address DIV 8) * 8;
        IF word_boundary <> 0 THEN
          status.normal := FALSE;
          status.condition := ioc$invalid_image_request;
          EXIT /image/; {----->
        IFEND;
      FOREND;

{Check if request crosses a page boundary.
      #real_memory_address (#LOC (image_request_p^.image_disk_request), rma);
      #real_memory_address (#LOC (command_p^), last_rma);
      IF last_rma - rma - image_request_p^.image_disk_request.request_length + #SIZE (command) <> 0 THEN
        status.normal := FALSE;
        status.condition := ioc$invalid_image_request;
        EXIT /image/; {----->
      IFEND;

{Call a monitor process to issue dmp$write.}
      request_block.request_code := syc$rc_translate_byte_address;
      request_block.system_file_id := system_file_id;
      request_block.file_byte_address := file_byte_address;
      request_block.length := length;

      i#call_monitor (#LOC (request_block), #SIZE (request_block));
      IF request_block.status.normal = FALSE THEN
        status.normal := FALSE;
        status.condition := request_block.status.condition;
        EXIT /image/; {----->
      IFEND;

      device_address := request_block.device_address;


      logical_unit := image_request_p^.image_disk_request.logical_unit;
      index := cmv$logical_unit_table^ [logical_unit].unit_interface_table^.unit_type - 100(16) + 1;

      IF device_address.transfer_length * iov$disk_type_table [index].bytes_per_mau < length THEN
        status.normal := FALSE;
        status.condition := ioc$invalid_image_request;
        EXIT /image/; {----->
      IFEND;

{Calculate cylinder, track, and sector.}
      cylinder := device_address.allocation_unit_mau_address DIV (device_address.maus_per_position);
      sector_offset_within_cylinder := (device_address.allocation_unit_mau_address -
            (cylinder * device_address.maus_per_position)) * iov$disk_type_table [index].sectors_per_mau;
      sector_offset_within_cylinder := sector_offset_within_cylinder + device_address.transfer_mau_offset *
            iov$disk_type_table [index].sectors_per_mau;
      track := sector_offset_within_cylinder DIV iov$disk_type_table [index].sectors_per_track;

      sector := sector_offset_within_cylinder - (track * iov$disk_type_table [index].sectors_per_track);
      image_request_p^.image_disk_request.cylinder := cylinder;
      image_request_p^.image_disk_request.track := track;
      image_request_p^.image_disk_request.sector := sector;

{Insert request in queue.}
      p_unit_table := cmv$logical_unit_table^ [logical_unit].unit_interface_table;
      p_unit_table^.unit_status.fill4 := 1;
      next_io_request := p_unit_table^.next_request;
      #real_memory_address (#LOC (image_request_p^.image_disk_request), rma);
      image_request_p^.image_disk_request.next_pp_request := NIL;
      image_request_p^.image_disk_request.next_pp_request_rma := 0;
      search_test := TRUE;
      first := TRUE;

    /loop4/
      WHILE search_test DO
        IF next_io_request = NIL THEN
          IF first THEN
            pva := image_request_p;
            p_unit_table^.next_request := pva;
            p_unit_table^.next_request_rma := rma;
          ELSE
            pva := image_request_p;
            previous_request^.next_pp_request := pva;
            previous_request^.next_pp_request_rma := rma;
          IFEND;
          search_test := FALSE;
          EXIT /loop4/; {----->
        IFEND;

        previous_io_request := next_io_request;
        previous_request := previous_io_request^.device_request_p;
        next_io_request := previous_request^.next_pp_request;
        first := FALSE;
      WHILEND /loop4/;

{Increment queue count.}
      IF p_unit_table^.queue_count = 0ffff(16) THEN
        p_unit_table^.queue_count := 0;
      IFEND;
      p_unit_table^.queue_count := p_unit_table^.queue_count + 1;

    END /image/;

  PROCEND iop$queue_image_request;
MODEND iom$queue_image_request;
