#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/1394/t1394.h>
#include <sys/1394/s1394.h>
#include <sys/1394/h1394.h>
#include <sys/1394/ieee1394.h>
#include <sys/1394/ieee1212.h>
static uint8_t selfid_speed(s1394_selfid_pkt_t *s);
static int selfid_num_ports(s1394_selfid_pkt_t *s);
static int selfid_port_type(s1394_selfid_pkt_t *s, int port);
static void s1394_hal_stack_push(s1394_hal_t *hal, void *o);
static void *s1394_hal_stack_pop(s1394_hal_t *hal);
static void s1394_hal_queue_insert(s1394_hal_t *hal, void *o);
static void *s1394_hal_queue_remove(s1394_hal_t *hal);
static void s1394_node_number_list_add(s1394_hal_t *hal, int node_num);
static void s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd);
static void s1394_speed_map_initialize(s1394_hal_t *hal);
int s1394_ignore_invalid_gap_cnt = 0;
static int gap_count[MAX_HOPS + 1] = {
0, 5, 7, 8, 10, 13, 16, 18, 21,
24, 26, 29, 32, 35, 37, 40, 43,
46, 48, 51, 54, 57, 59, 62
};
int
s1394_parse_selfid_buffer(s1394_hal_t *hal, void *selfid_buf_addr,
uint32_t selfid_size)
{
s1394_selfid_pkt_t *s;
uint32_t *data;
uint_t i = 0;
uint_t j = 0;
boolean_t error = B_FALSE;
int valid_pkt_id;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
data = (uint32_t *)selfid_buf_addr;
if (selfid_size == 0) {
s1394_initiate_hal_reset(hal, CRITICAL);
error = B_TRUE;
goto parse_buffer_done;
}
selfid_size = selfid_size >> 2;
while (j < selfid_size) {
valid_pkt_id = ((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
IEEE1394_SELFID_PCKT_ID_SHIFT);
s = (s1394_selfid_pkt_t *)(&data[j]);
if (IEEE1394_SELFID_ISVALID(s) &&
(valid_pkt_id == IEEE1394_SELFID_PCKT_ID_VALID)) {
hal->selfid_ptrs[i] = s;
j += 2;
while (IEEE1394_SELFID_ISMORE(s)) {
valid_pkt_id =
((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
IEEE1394_SELFID_PCKT_ID_SHIFT);
s = (s1394_selfid_pkt_t *)(&data[j]);
if (IEEE1394_SELFID_ISVALID(s) &&
(valid_pkt_id ==
IEEE1394_SELFID_PCKT_ID_VALID)) {
j += 2;
} else {
s1394_initiate_hal_reset(hal, CRITICAL);
error = B_TRUE;
goto parse_buffer_done;
}
}
i++;
} else {
s1394_initiate_hal_reset(hal, CRITICAL);
error = B_TRUE;
goto parse_buffer_done;
}
}
hal->number_of_nodes = i;
parse_buffer_done:
if (error == B_TRUE)
return (DDI_FAILURE);
else
return (DDI_SUCCESS);
}
void
s1394_sort_selfids(s1394_hal_t *hal)
{
s1394_selfid_pkt_t *current;
uint_t number_of_nodes;
int i;
int j;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
for (i = 1; i < number_of_nodes; i++) {
current = hal->selfid_ptrs[i];
j = i;
while ((j > 0) && (IEEE1394_SELFID_PHYID(current) >
IEEE1394_SELFID_PHYID(hal->selfid_ptrs[j / 2]))) {
hal->selfid_ptrs[j] = hal->selfid_ptrs[j / 2];
hal->selfid_ptrs[j / 2] = current;
j = j / 2;
}
}
for (i = number_of_nodes - 1; i > 0; i--) {
current = hal->selfid_ptrs[i];
hal->selfid_ptrs[i] = hal->selfid_ptrs[0];
hal->selfid_ptrs[0] = current;
j = 0;
while (2 * j + 1 < i) {
if (2 * j + 2 >= i) {
if (IEEE1394_SELFID_PHYID(current) <
IEEE1394_SELFID_PHYID(
hal->selfid_ptrs[2 * j + 1])) {
hal->selfid_ptrs[j] =
hal->selfid_ptrs[2 * j + 1];
hal->selfid_ptrs[2 * j + 1] = current;
j = 2 * j + 1;
}
break;
}
if (IEEE1394_SELFID_PHYID(hal->selfid_ptrs[2 * j + 1]) >
IEEE1394_SELFID_PHYID(
hal->selfid_ptrs[2 * j + 2])) {
if (IEEE1394_SELFID_PHYID(current) <
IEEE1394_SELFID_PHYID(
hal->selfid_ptrs[2 * j + 1])) {
hal->selfid_ptrs[j] =
hal->selfid_ptrs[2 * j + 1];
hal->selfid_ptrs[2 * j + 1] = current;
j = 2 * j + 1;
} else {
break;
}
} else {
if (IEEE1394_SELFID_PHYID(current) <
IEEE1394_SELFID_PHYID(
hal->selfid_ptrs[2 * j + 2])) {
hal->selfid_ptrs[j] =
hal->selfid_ptrs[2 * j + 2];
hal->selfid_ptrs[2 * j + 2] = current;
j = 2 * j + 2;
} else {
break;
}
}
}
}
}
static uint8_t
selfid_speed(s1394_selfid_pkt_t *s)
{
uint32_t sp;
sp = ((s->spkt_data & IEEE1394_SELFID_SP_MASK) >>
IEEE1394_SELFID_SP_SHIFT);
switch (sp) {
case IEEE1394_S100:
case IEEE1394_S200:
case IEEE1394_S400:
return (sp);
default:
return (IEEE1394_S400);
}
}
static int
selfid_num_ports(s1394_selfid_pkt_t *s)
{
int p = 3;
while (IEEE1394_SELFID_ISMORE(s)) {
p += 8;
s++;
}
if (p > IEEE1394_MAX_NUM_PORTS)
p = IEEE1394_MAX_NUM_PORTS;
return (p);
}
static int
selfid_port_type(s1394_selfid_pkt_t *s, int port)
{
int block;
int offset = IEEE1394_SELFID_PORT_OFFSET_FIRST;
if (port > 2) {
port -= 3;
block = (port >> 3) + 1;
port = port % 8;
s += block;
offset = IEEE1394_SELFID_PORT_OFFSET_OTHERS;
}
return ((s->spkt_data >> (offset - 2 * port)) & 0x00000003);
}
void
s1394_init_topology_tree(s1394_hal_t *hal, boolean_t copied,
ushort_t number_of_nodes)
{
s1394_node_t *node;
uint32_t *config_rom;
uint_t tree_size;
int i;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
if (copied == B_FALSE) {
for (i = 0; i < number_of_nodes; i++) {
node = &hal->topology_tree[i];
config_rom = node->cfgrom;
if (config_rom != NULL) {
if (CFGROM_NEW_ALLOC(node) == B_TRUE) {
kmem_free((void *)config_rom,
IEEE1394_CONFIG_ROM_SZ);
}
}
}
}
tree_size = hal->number_of_nodes * sizeof (s1394_node_t);
bzero((void *)hal->topology_tree, tree_size);
}
int
s1394_topology_tree_build(s1394_hal_t *hal)
{
s1394_node_t *tmp;
uint32_t number_of_nodes;
boolean_t push_to_orphan_stack = B_FALSE;
boolean_t found_parent = B_FALSE;
boolean_t found_connection = B_FALSE;
int i;
int j;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
hal->hal_stack_depth = -1;
for (i = 0; i < number_of_nodes; i++) {
if (i != IEEE1394_SELFID_PHYID(hal->selfid_ptrs[i])) {
s1394_initiate_hal_reset(hal, CRITICAL);
return (DDI_FAILURE);
}
hal->topology_tree[i].selfid_packet = hal->selfid_ptrs[i];
hal->topology_tree[i].parent_port = (char)NO_PARENT;
hal->topology_tree[i].is_a_leaf = 1;
hal->topology_tree[i].node_num = (uchar_t)i;
}
for (i = 0; i < number_of_nodes; i++) {
found_parent = B_FALSE;
found_connection = B_FALSE;
for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++)
hal->topology_tree[i].phy_port[j] = NULL;
for (j = selfid_num_ports(hal->selfid_ptrs[i]) - 1;
j >= 0; j--) {
if (selfid_port_type(hal->selfid_ptrs[i], j) ==
IEEE1394_SELFID_PORT_TO_PARENT) {
found_connection = B_TRUE;
if (found_parent == B_FALSE) {
push_to_orphan_stack = B_TRUE;
hal->topology_tree[i].parent_port =
(char)j;
found_parent = B_TRUE;
} else {
s1394_initiate_hal_reset(hal, CRITICAL);
return (DDI_FAILURE);
}
} else if (selfid_port_type(hal->selfid_ptrs[i], j) ==
IEEE1394_SELFID_PORT_TO_CHILD) {
found_connection = B_TRUE;
tmp = (s1394_node_t *)s1394_hal_stack_pop(hal);
if (tmp == NULL) {
s1394_initiate_hal_reset(hal, CRITICAL);
return (DDI_FAILURE);
}
hal->topology_tree[i].phy_port[j] = tmp;
hal->topology_tree[i].is_a_leaf = 0;
tmp->phy_port[tmp->parent_port] =
&hal->topology_tree[i];
}
}
if ((found_connection == B_FALSE) && (number_of_nodes > 1)) {
s1394_initiate_hal_reset(hal, CRITICAL);
return (DDI_FAILURE);
}
if (push_to_orphan_stack == B_TRUE) {
push_to_orphan_stack = B_FALSE;
s1394_hal_stack_push(hal, &hal->topology_tree[i]);
}
}
if (hal->hal_stack_depth != -1) {
s1394_initiate_hal_reset(hal, CRITICAL);
return (DDI_FAILURE);
}
hal->topology_tree_valid = B_TRUE;
return (DDI_SUCCESS);
}
static void
s1394_hal_stack_push(s1394_hal_t *hal, void *obj)
{
if (hal->hal_stack_depth < IEEE1394_MAX_NODES - 1) {
hal->hal_stack_depth++;
hal->hal_stack[hal->hal_stack_depth] = obj;
}
}
static void *
s1394_hal_stack_pop(s1394_hal_t *hal)
{
if (hal->hal_stack_depth > -1) {
hal->hal_stack_depth--;
return (hal->hal_stack[hal->hal_stack_depth + 1]);
} else {
return (NULL);
}
}
static void
s1394_hal_queue_insert(s1394_hal_t *hal, void *obj)
{
if (((hal->hal_queue_front + 1) % IEEE1394_MAX_NODES) ==
hal->hal_queue_back) {
return;
} else {
hal->hal_queue[hal->hal_queue_front] = obj;
hal->hal_queue_front = (hal->hal_queue_front + 1) %
IEEE1394_MAX_NODES;
}
}
static void *
s1394_hal_queue_remove(s1394_hal_t *hal)
{
void *tmp;
if (hal->hal_queue_back == hal->hal_queue_front) {
return (NULL);
} else {
tmp = hal->hal_queue[hal->hal_queue_back];
hal->hal_queue_back = (hal->hal_queue_back + 1) %
IEEE1394_MAX_NODES;
return (tmp);
}
}
static void
s1394_node_number_list_add(s1394_hal_t *hal, int node_num)
{
if (hal->hal_node_number_list_size >= IEEE1394_MAX_NODES - 1) {
return;
}
hal->hal_node_number_list[hal->hal_node_number_list_size] = node_num;
hal->hal_node_number_list_size++;
}
void
s1394_topology_tree_mark_all_unvisited(s1394_hal_t *hal)
{
uint_t number_of_nodes;
int i;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
for (i = 0; i < number_of_nodes; i++)
CLEAR_NODE_VISITED(&hal->topology_tree[i]);
}
void
s1394_old_tree_mark_all_unvisited(s1394_hal_t *hal)
{
uint_t number_of_nodes;
int i;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->old_number_of_nodes;
for (i = 0; i < number_of_nodes; i++)
CLEAR_NODE_VISITED(&hal->old_tree[i]);
}
void
s1394_old_tree_mark_all_unmatched(s1394_hal_t *hal)
{
uint_t number_of_nodes;
int i;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->old_number_of_nodes;
for (i = 0; i < number_of_nodes; i++)
CLEAR_NODE_MATCHED(&hal->old_tree[i]);
}
void
s1394_copy_old_tree(s1394_hal_t *hal)
{
s1394_node_t *temp;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
temp = hal->old_tree;
hal->old_tree = hal->topology_tree;
hal->topology_tree = temp;
hal->old_number_of_nodes = hal->number_of_nodes;
hal->old_node_id = hal->node_id;
hal->old_generation_count = hal->generation_count;
hal->old_tree_valid = B_TRUE;
}
void
s1394_match_tree_nodes(s1394_hal_t *hal)
{
s1394_node_t *tmp;
uint_t hal_node_num;
uint_t hal_node_num_old;
int i;
int port_type;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
hal->hal_queue_front = hal->hal_queue_back = 0;
hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
hal_node_num_old = IEEE1394_NODE_NUM(hal->old_node_id);
hal->topology_tree[hal_node_num].old_node =
&hal->old_tree[hal_node_num_old];
hal->old_tree[hal_node_num_old].cur_node =
&hal->topology_tree[hal_node_num];
s1394_hal_queue_insert(hal, &hal->topology_tree[hal_node_num]);
while (hal->hal_queue_front != hal->hal_queue_back) {
tmp = (s1394_node_t *)s1394_hal_queue_remove(hal);
SET_NODE_VISITED(tmp);
SET_NODE_VISITED(tmp->old_node);
tmp->old_node->cur_node = tmp;
SET_NODE_MATCHED(tmp);
SET_NODE_MATCHED(tmp->old_node);
s1394_copy_cfgrom(tmp, tmp->old_node);
if ((tmp->cfgrom != NULL && CONFIG_ROM_GEN(tmp->cfgrom) <= 1) ||
NODE_MATCHED(tmp) == B_TRUE) {
s1394_target_t *t;
rw_enter(&hal->target_list_rwlock, RW_WRITER);
t = tmp->target_list = tmp->old_node->target_list;
while (t != NULL) {
t->on_node = tmp;
t = t->target_sibling;
}
rw_exit(&hal->target_list_rwlock);
}
for (i = 0; i < selfid_num_ports(tmp->selfid_packet); i++) {
port_type = selfid_port_type(tmp->selfid_packet, i);
if ((port_type == IEEE1394_SELFID_PORT_TO_CHILD) ||
(port_type == IEEE1394_SELFID_PORT_TO_PARENT)) {
port_type = selfid_port_type(
tmp->old_node->selfid_packet, i);
if ((port_type ==
IEEE1394_SELFID_PORT_TO_CHILD) ||
(port_type ==
IEEE1394_SELFID_PORT_TO_PARENT)) {
if (!NODE_VISITED(tmp->phy_port[i])) {
tmp->phy_port[i]->old_node =
tmp->old_node->phy_port[i];
s1394_hal_queue_insert(hal,
tmp->phy_port[i]);
}
}
}
}
}
}
int
s1394_topology_tree_calculate_diameter(s1394_hal_t *hal)
{
s1394_node_t *current;
uint_t number_of_nodes;
int i;
int start;
int end;
boolean_t done;
boolean_t found_a_child;
int distance = 0;
int diameter = 0;
int local_diameter = 0;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
for (i = 0; i < number_of_nodes; i++) {
hal->topology_tree[i].max_1st = 0;
hal->topology_tree[i].max_2nd = 0;
hal->topology_tree[i].last_port_checked = 0;
}
current = s1394_topology_tree_get_root_node(hal);
hal->hal_stack_depth = -1;
do {
done = B_FALSE;
found_a_child = B_FALSE;
start = current->last_port_checked;
end = selfid_num_ports(current->selfid_packet);
for (i = start; i < end; i++) {
current->last_port_checked++;
if (selfid_port_type(current->selfid_packet, i) ==
IEEE1394_SELFID_PORT_TO_CHILD) {
found_a_child = B_TRUE;
s1394_hal_stack_push(hal, current);
current = current->phy_port[i];
break;
}
}
if (hal->hal_stack_depth == -1) {
done = B_TRUE;
continue;
}
if (found_a_child == B_FALSE) {
distance = current->max_1st + 1;
current = s1394_hal_stack_pop(hal);
if (distance > current->max_1st) {
current->max_2nd = current->max_1st;
current->max_1st = (uchar_t)distance;
} else if (distance > current->max_2nd) {
current->max_2nd = (uchar_t)distance;
}
local_diameter = current->max_1st + current->max_2nd;
if (local_diameter > diameter)
diameter = local_diameter;
}
} while (done == B_FALSE);
return (diameter);
}
int
s1394_gap_count_optimize(int diameter)
{
if ((diameter >= 0) && (diameter <= MAX_HOPS)) {
return (gap_count[diameter]);
} else {
cmn_err(CE_NOTE, "Too may point-to-point links on the 1394"
" bus - If new devices have recently been added, remove"
" them.");
return (gap_count[MAX_HOPS]);
}
}
int
s1394_get_current_gap_count(s1394_hal_t *hal)
{
int i;
int gap_count = -1;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
gap_count = IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[0]);
for (i = 1; i < hal->number_of_nodes; i++) {
if (gap_count !=
IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[i])) {
if (s1394_ignore_invalid_gap_cnt == 0) {
s1394_initiate_hal_reset(hal, CRITICAL);
}
return (-1);
}
}
return (gap_count);
}
void
s1394_speed_map_fill(s1394_hal_t *hal)
{
uint_t number_of_nodes;
int i;
int j;
int node_num;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
s1394_speed_map_initialize(hal);
for (i = 0; i < number_of_nodes; i++) {
if (selfid_speed(hal->topology_tree[i].selfid_packet) ==
IEEE1394_S100) {
hal->slowest_node_speed = IEEE1394_S100;
node_num = IEEE1394_SELFID_PHYID(
hal->topology_tree[i].selfid_packet);
for (j = 0; j < number_of_nodes; j++) {
if (j != node_num) {
hal->speed_map[node_num][j] =
IEEE1394_S100;
hal->speed_map[j][node_num] =
IEEE1394_S100;
}
}
}
}
s1394_speed_map_fill_speed_N(hal, IEEE1394_S200);
s1394_speed_map_fill_speed_N(hal, IEEE1394_S400);
for (i = 0; i < number_of_nodes; i++) {
hal->speed_map[i][i] =
selfid_speed(hal->topology_tree[i].selfid_packet);
}
}
static void
s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd)
{
s1394_node_t *tmp;
uint_t number_of_nodes;
int i;
int j;
int k;
int size;
int ix_a, ix_b;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
s1394_topology_tree_mark_all_unvisited(hal);
hal->hal_queue_front = hal->hal_queue_back = 0;
for (i = 0; i < number_of_nodes; i++) {
if (!NODE_VISITED(&hal->topology_tree[i]) &&
(selfid_speed(hal->topology_tree[i].selfid_packet) ==
min_spd)) {
if (min_spd < hal->slowest_node_speed)
hal->slowest_node_speed = (uint8_t)min_spd;
SET_NODE_VISITED(&hal->topology_tree[i]);
s1394_hal_queue_insert(hal, &hal->topology_tree[i]);
while (hal->hal_queue_front != hal->hal_queue_back) {
tmp = (s1394_node_t *)s1394_hal_queue_remove(
hal);
s1394_node_number_list_add(hal,
IEEE1394_SELFID_PHYID(tmp->selfid_packet));
for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++) {
if ((tmp->phy_port[j] != NULL) &&
(!NODE_VISITED(tmp->phy_port[j]))) {
if (selfid_speed(
tmp->phy_port[j]->
selfid_packet) >= min_spd) {
SET_NODE_VISITED(
tmp->phy_port[j]);
s1394_hal_queue_insert(
hal,
tmp->phy_port[j]);
}
}
}
}
size = hal->hal_node_number_list_size;
for (j = 0; j < size; j++) {
for (k = 0; k < size; k++) {
if (j != k) {
ix_a = hal->
hal_node_number_list[j];
ix_b = hal->
hal_node_number_list[k];
hal->speed_map[ix_a][ix_b] =
(uint8_t)min_spd;
}
}
}
hal->hal_node_number_list_size = 0;
}
}
}
static void
s1394_speed_map_initialize(s1394_hal_t *hal)
{
uint_t number_of_nodes;
int i, j;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
for (i = 0; i < number_of_nodes; i++) {
for (j = 0; j < number_of_nodes; j++) {
if (i != j)
hal->speed_map[i][j] = IEEE1394_S100;
else
hal->speed_map[i][j] = SPEED_MAP_INVALID;
}
}
}
uint8_t
s1394_speed_map_get(s1394_hal_t *hal, uint_t from_node, uint_t to_node)
{
if (to_node >= hal->number_of_nodes) {
return (hal->slowest_node_speed);
}
return (hal->speed_map[from_node][to_node]);
}
void
s1394_update_speed_map_link_speeds(s1394_hal_t *hal)
{
uint32_t bus_capabilities;
uint8_t link_speed;
uint_t number_of_nodes;
int i, j;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
number_of_nodes = hal->number_of_nodes;
for (i = 0; i < number_of_nodes; i++) {
if (CFGROM_VALID(&hal->topology_tree[i])) {
ASSERT(hal->topology_tree[i].cfgrom);
bus_capabilities = hal->topology_tree[i].
cfgrom[IEEE1212_NODE_CAP_QUAD];
if ((bus_capabilities & IEEE1394_BIB_GEN_MASK) != 0) {
link_speed = (bus_capabilities &
IEEE1394_BIB_LNK_SPD_MASK);
for (j = 0; j < number_of_nodes; j++) {
if (hal->speed_map[i][j] > link_speed) {
hal->speed_map[i][j] =
link_speed;
hal->speed_map[j][i] =
link_speed;
}
if (link_speed <
hal->slowest_node_speed)
hal->slowest_node_speed =
link_speed;
}
}
}
}
}
int
s1394_get_isoch_rsrc_mgr(s1394_hal_t *hal)
{
int i;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
for (i = hal->number_of_nodes - 1; i >= 0; i--) {
if ((IEEE1394_SELFID_ISLINKON(hal->selfid_ptrs[i])) &&
(IEEE1394_SELFID_ISCONTENDER(hal->selfid_ptrs[i]))) {
return (i);
}
}
return (-1);
}
void
s1394_physical_arreq_setup_all(s1394_hal_t *hal)
{
s1394_target_t *curr_target;
uint64_t mask = 0;
uint32_t node_num;
uint_t generation;
ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
mutex_enter(&hal->topology_tree_mutex);
generation = hal->generation_count;
rw_enter(&hal->target_list_rwlock, RW_READER);
curr_target = hal->target_head;
while (curr_target != NULL) {
if ((curr_target->on_node != NULL) &&
(curr_target->physical_arreq_enabled != 0)) {
node_num = curr_target->on_node->node_num;
mask = mask | (1 << node_num);
}
curr_target = curr_target->target_next;
}
rw_exit(&hal->target_list_rwlock);
mutex_exit(&hal->topology_tree_mutex);
(void) HAL_CALL(hal).physical_arreq_enable_set(
hal->halinfo.hal_private, mask, generation);
}
void
s1394_physical_arreq_set_one(s1394_target_t *target)
{
s1394_hal_t *hal;
uint64_t mask = 0;
uint32_t node_num;
uint_t generation;
hal = target->on_hal;
ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
mutex_enter(&hal->topology_tree_mutex);
rw_enter(&hal->target_list_rwlock, RW_READER);
if ((target->on_node != NULL) &&
(target->physical_arreq_enabled != 0)) {
node_num = target->on_node->node_num;
mask = mask | (1 << node_num);
generation = hal->generation_count;
rw_exit(&hal->target_list_rwlock);
mutex_exit(&hal->topology_tree_mutex);
(void) HAL_CALL(hal).physical_arreq_enable_set(
hal->halinfo.hal_private, mask, generation);
} else {
rw_exit(&hal->target_list_rwlock);
mutex_exit(&hal->topology_tree_mutex);
}
}
void
s1394_physical_arreq_clear_one(s1394_target_t *target)
{
s1394_hal_t *hal;
uint64_t mask = 0;
uint32_t node_num;
uint_t generation;
hal = target->on_hal;
ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
mutex_enter(&hal->topology_tree_mutex);
rw_enter(&hal->target_list_rwlock, RW_READER);
if ((target->on_node != NULL) &&
(target->physical_arreq_enabled == 0)) {
node_num = target->on_node->node_num;
mask = mask | (1 << node_num);
generation = hal->generation_count;
rw_exit(&hal->target_list_rwlock);
mutex_exit(&hal->topology_tree_mutex);
(void) HAL_CALL(hal).physical_arreq_enable_clr(
hal->halinfo.hal_private, mask, generation);
} else {
rw_exit(&hal->target_list_rwlock);
mutex_exit(&hal->topology_tree_mutex);
}
}
s1394_node_t *
s1394_topology_tree_get_root_node(s1394_hal_t *hal)
{
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
return (&hal->topology_tree[hal->number_of_nodes - 1]);
}