// treeid.c

#include "1394.h"
#include "data_structures.h"
#include "phy_services.h"
#include "arb.h"
#include "shared.h"

void tree_ID_start_actions() {
  int i;

  do {
    children = 0;                       // Count the kids afresh on each loop
    for (i = 0; i < NPORT; i++)
      if (!active[i] || portRarb[i] == PARENT_NOTIFY) {
        child[i] = TRUE;                // Child if disabled, disconnected or suspended
        children++;                     // or if other PHY asks us to be the parent
      }
    if (children == NPORT - 1 && (!force_root || arb_timer >= FORCE_ROOT_TIMEOUT))
      return;                         // Only one port left as the parent
    else if (children == NPORT)
      return;                         // node is the root
  } while (!(reset_detected() || ibr || isbr|| (!T0_timeout && (arb_timer == CONFIG_TIMEOUT))));
}

void child_handshake_actions() {
  int i;
  senior_port = parent_port = NPORT+1;  // No parent port (in case node becomes root)
  proxy_root = root = TRUE;             // Remains TRUE if all the ports are child ports
  for (i = 0; i < NPORT; i++)
    if (active[i])                      // Only the connected, active ports participate
      if (child[i])
        portTarb(i, CHILD_NOTIFY);      // Tell peer PHY, "You are my child"
      else {
        portTarb(i, PARENT_NOTIFY);     // Ask peer PHY, "Please be my parent"
        senior_port = parent_port = i;  // Only one parent port possible
        proxy_root = root = FALSE;      // Tentative---see root contention
      }
}

boolean child_handshake_complete() {    // TRUE once all active children are in S0: Self ID Start
  int i;
  for (i = 0; i < NPORT; i++)
    if (active[i] && child[i] && !((portRarb[i] == CHILD_HANDSHAKE) ||  // DS ports
            (portRarb[i] == IDLE)))     // Beta ports 
      return(FALSE);                    // One as yet uncompleted handshake...
  return(TRUE);                         // All child ports have finished their handshakes
}

void root_contend_actions() {
  int i;
  contend_time = (random_bool() ? ROOT_CONTEND_SLOW : ROOT_CONTEND_FAST);
  for (i = 0; i < NPORT; i++)
    if (child[i])                       // Only the connected, active ports matter
      portTarb(i, CHILD_NOTIFY);        // Continue to tell peer PHY, "You are my child"   
    else
      portTarb(i, IDLE);                // Withdraw "Please be my parent" request
  arb_timer = 0;                        // Restart arbitration timer
}
