?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Network Access : Network Initialization' ??
?? NEWTITLE := 'Global Declarations Referenced by This Module' ??
MODULE nam$initialize_networks_r1;

{
{     PURPOSE:
{       The purpose of this module is to declare and initialize network PPU interface variables
{       in the mainframe wired segment.  This includes buffers for incoming data.
{       Procedures to return structures to a null state accompany the initialization procedures.
{
{       The module also contains procedures to record task identifies of NAM/VE well known tasks
{       in mainframe wired.
{
{     DESIGN:
{       This module must reside in the OSF$SYSTEM_CORE_113 library.  The procedure, nap$initialize_r1,
{       must only execute in the network initialize task.  The procedure nap$initialize_r1 is to be
{       called only during network initialization.  The task identifier recording procedures are
{       called each time a NAM/VE task begins execution.
{
{       NOTE: Smaller PP buffer pools are created when NOS/VE memory is below a defined threshold
{             (currently 16MB).
{
?? PUSH (LISTEXT := ON) ??
*copyc nat$network_address
*copyc nlc$bm_small_buffer_size
*copyc nlt$pp_buffer
*copyc nlt$pp_send_queue_tails
*copyc nlc$small_machine_threshold
*copyc ost$signature_lock
?? POP ??
*copyc i#real_memory_address
*copyc pmp$get_executing_task_gtid
*copyc pmp$zero_out_table

*copyc nav$network_wired_heap
*copyc nav$si_received_message_list
*copyc nav$completed_output_requests
*copyc nav$connection_establish_taskid
*copyc nav$completed_output_taskid
*copyc nav$directory_me_taskid
*copyc nav$system_input_taskid
*copyc nav$system_id
*copyc nlv$bm_large_buffer_size
*copyc nlv$configured_network_devices
*copyc osv$180_memory_limits
*copyc osv$mainframe_wired_cb_heap

  TYPE

{ Align the buffer pools pp_max_small_buffers * #SIZE(nlt$pp_buffer_pool_entry).
{ The alignment prevents the pool from crossing a page boundry.

    aligned_small_pp_pool_type = record
      pool: ALIGNED [0 MOD 1024] nlt$pp_buffer_pool,
    recend,

{ Align the buffer pools pp_max_large_buffers * #SIZE(nlt$pp_buffer_pool_entry).
{ The alignment prevents the pool from crossing a page boundry.

    aligned_large_pp_pool_type = record
      pool: ALIGNED [0 MOD 1024] nlt$pp_buffer_pool,
    recend;

  VAR
    aligned_small_pp_pool: [STATIC] ^aligned_small_pp_pool_type := NIL,
    aligned_large_pp_pool: [STATIC] ^aligned_large_pp_pool_type := NIL,

    nlv$pp_buffer: [XDCL, #GATE] ^nlt$pp_buffer := NIL,
    nlv$pp_send_queue_tails: [XDCL, #GATE] ^nlt$pp_send_queue_tails := NIL;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] nap$free_pp_send_queue_tails', EJECT ??
*copy nah$free_pp_send_queue_tails
  PROCEDURE [XDCL, #GATE] nap$free_pp_send_queue_tails;

    FREE nlv$pp_send_queue_tails IN osv$mainframe_wired_cb_heap^;

  PROCEND nap$free_pp_send_queue_tails;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] nap$init_pp_send_queue_tails', EJECT ??
*copy nah$init_pp_send_queue_tails
  PROCEDURE [XDCL, #GATE] nap$init_pp_send_queue_tails;

    VAR
      i: integer,
      network_device_count: nlt$device_count,
      queue: nlt$cc_connection_class;

    network_device_count := nlv$configured_network_devices.network_device_count;
    ALLOCATE nlv$pp_send_queue_tails: [1 .. network_device_count] IN osv$mainframe_wired_cb_heap^;

    FOR i := 1 TO network_device_count DO
      FOR queue := nlc$cc_normal_class TO nlc$cc_priority_class DO
        nlv$pp_send_queue_tails^ [i] [queue].send_queue_tail := NIL;
      FOREND;
    FOREND;

  PROCEND nap$init_pp_send_queue_tails;

?? TITLE := '  [XDCL, #GATE] nap$initialize_pp_buffer_descr', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$initialize_pp_buffer_descr;
*copy nah$initialize_pp_buffer_descr

  VAR
    pp_max_small_buffers: 0 .. 511,
    pp_small_buffer_threshold: 0 .. 511,
    pp_max_large_buffers: 0 .. 511,
    pp_large_buffer_threshold: 0 .. 511,
    rma: integer;

    ALLOCATE nlv$pp_buffer IN osv$mainframe_wired_cb_heap^;
    pmp$zero_out_table (#LOC (nlv$pp_buffer^), #SIZE (nlv$pp_buffer^));

    IF (osv$180_memory_limits.upper - osv$180_memory_limits.lower) < nlc$small_machine_threshold THEN
      pp_max_small_buffers := 50;
      pp_small_buffer_threshold := 25;
      pp_max_large_buffers := 30;
      pp_large_buffer_threshold := 20;
    ELSE
      pp_max_small_buffers := 256;
      pp_small_buffer_threshold := 120;
      pp_max_large_buffers := 200;
      pp_large_buffer_threshold := 120;
    IFEND;

    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].buffer_length := nlc$bm_small_buffer_size;
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].inn := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].cpu_out := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].pp_out := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].threshold := pp_small_buffer_threshold;
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].limit :=
          ((pp_max_small_buffers + 1) * #SIZE (nlt$pp_buffer_pool_entry));

    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].buffer_length := nlv$bm_large_buffer_size;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].inn := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].cpu_out := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].pp_out := 0;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].threshold := pp_large_buffer_threshold;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].limit :=
          ((pp_max_large_buffers + 1) * #SIZE (nlt$pp_buffer_pool_entry));

    ALLOCATE aligned_small_pp_pool: [0 .. pp_max_small_buffers] IN osv$mainframe_wired_cb_heap^;
    nlv$pp_buffer^.pool [nlc$bm_small_buffer_index] := ^aligned_small_pp_pool^.pool;
    pmp$zero_out_table (#LOC (nlv$pp_buffer^.pool [nlc$bm_small_buffer_index]^),
          ((pp_max_small_buffers + 1) * #SIZE (nlt$pp_buffer_pool_entry)));
    i#real_memory_address (nlv$pp_buffer^.pool [nlc$bm_small_buffer_index], rma);
    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].pp_buffer_pool := rma;

    ALLOCATE aligned_large_pp_pool: [0 .. pp_max_large_buffers] IN osv$mainframe_wired_cb_heap^;
    nlv$pp_buffer^.pool [nlc$bm_large_buffer_index] := ^aligned_large_pp_pool^.pool;
    pmp$zero_out_table (#LOC (nlv$pp_buffer^.pool [nlc$bm_large_buffer_index]^),
          ((pp_max_large_buffers + 1) * #SIZE (nlt$pp_buffer_pool_entry)));
    i#real_memory_address (nlv$pp_buffer^.pool[nlc$bm_large_buffer_index], rma);
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].pp_buffer_pool := rma;

  PROCEND nap$initialize_pp_buffer_descr;
?? TITLE := '[XDCL, #GATE] nap$free_pp_buffer_descriptor', EJECT ??
  PROCEDURE [XDCL, #GATE] nap$free_pp_buffer_descriptor;
*copy nah$free_pp_buffer_descriptor

    FREE nlv$pp_buffer^.pool [nlc$bm_small_buffer_index] IN osv$mainframe_wired_cb_heap^;
    FREE nlv$pp_buffer^.pool [nlc$bm_large_buffer_index] IN osv$mainframe_wired_cb_heap^;
    FREE nlv$pp_buffer IN osv$mainframe_wired_cb_heap^;

  PROCEND nap$free_pp_buffer_descriptor;

?? TITLE := '  [XDCL, #GATE] nap$free_pp_buffer_pools', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$free_pp_buffer_pools;
*copy nah$free_pp_buffer_pools

    {
    { NOTE: message buffers in the the PP buffer pools are not actually freed, but the pools are rendered
    {       empty by this procedure.  The process relies on resetting the network wired heap to free
    {       any containers which may exist in the pools.
    {

    nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].inn :=
          nlv$pp_buffer^.pool_header [nlc$bm_small_buffer_index].cpu_out;
    nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].inn :=
          nlv$pp_buffer^.pool_header [nlc$bm_large_buffer_index].cpu_out;
  PROCEND nap$free_pp_buffer_pools;
?? TITLE := '  [XDCL, #GATE] nap$reset_network_responses', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$reset_network_responses;
*copy nah$reset_network_responses

    nav$si_received_message_list.next_received_message := NIL;
    nav$si_received_message_list.fill := 0;
    nav$completed_output_requests.request_block_link := NIL;
    nav$completed_output_requests.requests_queued := 0;
  PROCEND nap$reset_network_responses;
?? NEWTITLE := '  [XDCL, #GATE] nap$record_connection_establish' ??
?? NEWTITLE := '  [XDCL, #GATE] nap$record_directory_me' ??
?? NEWTITLE := '  [XDCL, #GATE] nap$record_completed_output' ??
?? NEWTITLE := '  [XDCL, #GATE] nap$record_system_id' ??
?? NEWTITLE := '  [XDCL, #GATE] nap$record_system_input', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$record_connection_establish;

    pmp$get_executing_task_gtid (nav$connection_establish_taskid);
  PROCEND nap$record_connection_establish;

  PROCEDURE [XDCL, #GATE] nap$record_completed_output;

    pmp$get_executing_task_gtid (nav$completed_output_taskid);

  PROCEND nap$record_completed_output;

  PROCEDURE [XDCL, #GATE] nap$record_directory_me;

    pmp$get_executing_task_gtid (nav$directory_me_taskid);
  PROCEND nap$record_directory_me;

  PROCEDURE [XDCL, #GATE] nap$record_system_id (system_id: nat$system_identifier);

    nav$system_id := system_id;
  PROCEND nap$record_system_id;

  PROCEDURE [XDCL, #GATE] nap$record_system_input;

    pmp$get_executing_task_gtid (nav$system_input_taskid);
  PROCEND nap$record_system_input;
?? OLDTITLE, OLDTITLE, OLDTITLE, OLDTITLE, OLDTITLE ??
MODEND nam$initialize_networks_r1;
