#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 void s1394_CSR_state_clear(cmd1394_cmd_t *req);
static void s1394_CSR_state_set(cmd1394_cmd_t *req);
static void s1394_CSR_node_ids(cmd1394_cmd_t *req);
static void s1394_CSR_reset_start(cmd1394_cmd_t *req);
static void s1394_CSR_split_timeout(cmd1394_cmd_t *req);
static void s1394_CSR_argument_regs(cmd1394_cmd_t *req);
static void s1394_CSR_test_regs(cmd1394_cmd_t *req);
static void s1394_CSR_interrupt_regs(cmd1394_cmd_t *req);
static void s1394_CSR_clock_regs(cmd1394_cmd_t *req);
static void s1394_CSR_message_regs(cmd1394_cmd_t *req);
static void s1394_CSR_cycle_time(cmd1394_cmd_t *req);
static void s1394_CSR_bus_time(cmd1394_cmd_t *req);
static void s1394_CSR_busy_timeout(cmd1394_cmd_t *req);
static void s1394_CSR_IRM_regs(cmd1394_cmd_t *req);
static void s1394_CSR_topology_map(cmd1394_cmd_t *req);
static void s1394_common_CSR_routine(s1394_hal_t *hal, cmd1394_cmd_t *req);
static int s1394_init_config_rom_structures(s1394_hal_t *hal);
static int s1394_destroy_config_rom_structures(s1394_hal_t *hal);
int
s1394_setup_CSR_space(s1394_hal_t *hal)
{
s1394_addr_space_blk_t *curr_blk;
t1394_alloc_addr_t addr;
t1394_addr_enable_t rw_flags;
int result;
rw_flags = T1394_ADDR_RDENBL | T1394_ADDR_WRENBL;
addr.aa_address = IEEE1394_CSR_STATE_CLEAR;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_state_clear;
addr.aa_evts.recv_write_request = s1394_CSR_state_clear;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_STATE_SET;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = T1394_ADDR_WRENBL;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = NULL;
addr.aa_evts.recv_write_request = s1394_CSR_state_set;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_NODE_IDS;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_node_ids;
addr.aa_evts.recv_write_request = s1394_CSR_node_ids;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_RESET_START;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = T1394_ADDR_WRENBL;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = NULL;
addr.aa_evts.recv_write_request = s1394_CSR_reset_start;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_SPLIT_TIMEOUT_HI;
addr.aa_length = IEEE1394_OCTLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_split_timeout;
addr.aa_evts.recv_write_request = s1394_CSR_split_timeout;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_ARG_HI;
addr.aa_length = 2 * (IEEE1394_QUADLET);
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_argument_regs;
addr.aa_evts.recv_write_request = s1394_CSR_argument_regs;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_TEST_START;
addr.aa_length = 2 * (IEEE1394_QUADLET);
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_test_regs;
addr.aa_evts.recv_write_request = s1394_CSR_test_regs;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_INTERRUPT_TARGET;
addr.aa_length = 2 * (IEEE1394_QUADLET);
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_interrupt_regs;
addr.aa_evts.recv_write_request = s1394_CSR_interrupt_regs;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_CLOCK_VALUE;
addr.aa_length = IEEE1394_CSR_CLOCK_VALUE_SZ;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_clock_regs;
addr.aa_evts.recv_write_request = s1394_CSR_clock_regs;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CSR_MESSAGE_REQUEST;
addr.aa_length = IEEE1394_CSR_MESSAGE_REQUEST_SZ;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_message_regs;
addr.aa_evts.recv_write_request = s1394_CSR_message_regs;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_SCSR_CYCLE_TIME;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_cycle_time;
addr.aa_evts.recv_write_request = s1394_CSR_cycle_time;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_SCSR_BUS_TIME;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_bus_time;
addr.aa_evts.recv_write_request = s1394_CSR_bus_time;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_SCSR_BUSY_TIMEOUT;
addr.aa_length = IEEE1394_QUADLET;
addr.aa_enable = rw_flags;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_busy_timeout;
addr.aa_evts.recv_write_request = s1394_CSR_busy_timeout;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_SCSR_BUSMGR_ID;
addr.aa_length = 3 * (IEEE1394_QUADLET);
addr.aa_enable = T1394_ADDR_RDENBL | T1394_ADDR_LKENBL;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_IRM_regs;
addr.aa_evts.recv_write_request = NULL;
addr.aa_evts.recv_lock_request = s1394_CSR_IRM_regs;
addr.aa_kmem_bufp = NULL;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_CONFIG_ROM_ADDR;
addr.aa_length = IEEE1394_CONFIG_ROM_SZ;
result = s1394_reserve_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
hal->CSR_topology_map = kmem_zalloc(IEEE1394_UCSR_TOPOLOGY_MAP_SZ,
KM_SLEEP);
addr.aa_address = IEEE1394_UCSR_TOPOLOGY_MAP;
addr.aa_length = IEEE1394_UCSR_TOPOLOGY_MAP_SZ;
addr.aa_enable = T1394_ADDR_RDENBL;
addr.aa_type = T1394_ADDR_FIXED;
addr.aa_evts.recv_read_request = s1394_CSR_topology_map;
addr.aa_evts.recv_write_request = NULL;
addr.aa_evts.recv_lock_request = NULL;
addr.aa_kmem_bufp = (caddr_t)hal->CSR_topology_map;
addr.aa_arg = hal;
result = s1394_claim_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
kmem_free((void *)hal->CSR_topology_map,
IEEE1394_UCSR_TOPOLOGY_MAP_SZ);
return (DDI_FAILURE);
}
curr_blk = (s1394_addr_space_blk_t *)(addr.aa_hdl);
curr_blk->free_kmem_bufp = B_TRUE;
addr.aa_address = IEEE1394_UCSR_SPEED_MAP;
addr.aa_length = IEEE1394_UCSR_SPEED_MAP_SZ;
result = s1394_reserve_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr.aa_address = IEEE1394_UCSR_RESERVED_BOUNDARY;
addr.aa_length = IEEE1394_QUADLET;
result = s1394_reserve_addr_blk(hal, &addr);
if (result != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
s1394_CSR_state_clear(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t data;
uint_t offset;
uint_t is_from;
uint_t should_be_from;
int result;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
mutex_enter(&hal->topology_tree_mutex);
is_from = IEEE1394_NODE_NUM(req->nodeID);
if (hal->bus_mgr_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
else if (hal->IRM_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
else
should_be_from = S1394_INVALID_NODE_NUM;
mutex_exit(&hal->topology_tree_mutex);
switch (req->cmd_type) {
case CMD1394_ASYNCH_RD_QUAD:
result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
offset, &data);
if (result == DDI_SUCCESS) {
req->cmd_u.q.quadlet_data = data;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
case CMD1394_ASYNCH_WR_QUAD:
data = req->cmd_u.q.quadlet_data;
if (is_from != should_be_from) {
data = data & ~IEEE1394_CSR_STATE_CMSTR;
}
mutex_enter(&hal->topology_tree_mutex);
if (data & IEEE1394_CSR_STATE_DREQ) {
hal->disable_requests_bit = 0;
if (hal->hal_state == S1394_HAL_DREQ)
hal->hal_state = S1394_HAL_NORMAL;
}
if (data & IEEE1394_CSR_STATE_ABDICATE) {
hal->abdicate_bus_mgr_bit = 0;
}
mutex_exit(&hal->topology_tree_mutex);
result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
if (result == DDI_SUCCESS) {
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_state_set(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t data;
uint_t offset;
uint_t is_from;
uint_t should_be_from;
uint_t hal_node_num;
uint_t hal_number_of_nodes;
int result;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
mutex_enter(&hal->topology_tree_mutex);
is_from = IEEE1394_NODE_NUM(req->nodeID);
if (hal->bus_mgr_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
else if (hal->IRM_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
else
should_be_from = S1394_INVALID_NODE_NUM;
hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
hal_number_of_nodes = hal->number_of_nodes;
mutex_exit(&hal->topology_tree_mutex);
switch (req->cmd_type) {
case CMD1394_ASYNCH_WR_QUAD:
data = req->cmd_u.q.quadlet_data;
if ((is_from != should_be_from) ||
(hal_node_num != (hal_number_of_nodes - 1))) {
data = data & ~IEEE1394_CSR_STATE_CMSTR;
}
mutex_enter(&hal->topology_tree_mutex);
if (is_from != should_be_from) {
data = data & ~IEEE1394_CSR_STATE_DREQ;
} else if (data & IEEE1394_CSR_STATE_DREQ) {
hal->disable_requests_bit = 1;
if (hal->hal_state == S1394_HAL_NORMAL)
hal->hal_state = S1394_HAL_DREQ;
}
if (data & IEEE1394_CSR_STATE_ABDICATE) {
hal->abdicate_bus_mgr_bit = 1;
}
mutex_exit(&hal->topology_tree_mutex);
result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
if (result == DDI_SUCCESS) {
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_node_ids(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_reset_start(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t data;
uint_t offset;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
switch (req->cmd_type) {
case CMD1394_ASYNCH_WR_QUAD:
data = req->cmd_u.q.quadlet_data;
(void) HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
req->cmd_result = IEEE1394_RESP_COMPLETE;
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_split_timeout(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_argument_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_test_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint_t offset;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset == (IEEE1394_CSR_TEST_STATUS & IEEE1394_CSR_OFFSET_MASK)) &&
(req->cmd_type == CMD1394_ASYNCH_WR_QUAD)) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
} else {
s1394_common_CSR_routine(hal, req);
}
}
static void
s1394_CSR_interrupt_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_clock_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_message_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_cycle_time(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t data;
uint_t offset;
int result;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
switch (req->cmd_type) {
case CMD1394_ASYNCH_RD_QUAD:
result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
offset, &data);
if (result == DDI_SUCCESS) {
req->cmd_u.q.quadlet_data = data;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
case CMD1394_ASYNCH_WR_QUAD:
data = req->cmd_u.q.quadlet_data;
result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
if (result == DDI_SUCCESS) {
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_bus_time(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t data;
uint_t offset;
uint_t is_from;
uint_t should_be_from;
int result;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
switch (req->cmd_type) {
case CMD1394_ASYNCH_RD_QUAD:
result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
offset, &data);
if (result == DDI_SUCCESS) {
req->cmd_u.q.quadlet_data = data;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
case CMD1394_ASYNCH_WR_QUAD:
mutex_enter(&hal->topology_tree_mutex);
is_from = IEEE1394_NODE_NUM(req->nodeID);
if (hal->bus_mgr_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
else if (hal->IRM_node != -1)
should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
else
should_be_from = S1394_INVALID_NODE_NUM;
mutex_exit(&hal->topology_tree_mutex);
if ((req->broadcast != 1) || (is_from != should_be_from)) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
break;
}
data = req->cmd_u.q.quadlet_data;
result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
if (result == DDI_SUCCESS) {
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_busy_timeout(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
s1394_common_CSR_routine(hal, req);
}
static void
s1394_CSR_IRM_regs(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
uint32_t generation;
uint32_t data;
uint32_t compare;
uint32_t swap;
uint32_t old;
uint_t offset;
int result;
hal = (s1394_hal_t *)req->cmd_callback_arg;
offset = (req->cmd_addr & IEEE1394_CSR_OFFSET_MASK);
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
return;
}
switch (req->cmd_type) {
case CMD1394_ASYNCH_RD_QUAD:
result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
offset, &data);
if (result == DDI_SUCCESS) {
req->cmd_u.q.quadlet_data = data;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
case CMD1394_ASYNCH_LOCK_32:
mutex_enter(&hal->topology_tree_mutex);
generation = hal->generation_count;
mutex_exit(&hal->topology_tree_mutex);
if (req->cmd_u.l32.lock_type == CMD1394_LOCK_COMPARE_SWAP) {
compare = req->cmd_u.l32.arg_value;
swap = req->cmd_u.l32.data_value;
result = HAL_CALL(hal).csr_cswap32(
hal->halinfo.hal_private, generation,
offset, compare, swap, &old);
if (result == DDI_SUCCESS) {
req->cmd_u.l32.old_value = old;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
} else {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
static void
s1394_CSR_topology_map(cmd1394_cmd_t *req)
{
s1394_hal_t *hal;
hal = (s1394_hal_t *)req->cmd_callback_arg;
if (req->cmd_type == CMD1394_ASYNCH_RD_QUAD)
req->cmd_result = IEEE1394_RESP_COMPLETE;
else
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
}
void
s1394_CSR_topology_map_update(s1394_hal_t *hal)
{
s1394_selfid_pkt_t *selfid_packet;
uint32_t *tm_ptr;
uint32_t *data_ptr;
uint32_t node_count;
uint32_t self_id_count;
uint_t CRC;
uint32_t length;
int i, j, c;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
tm_ptr = (uint32_t *)hal->CSR_topology_map;
data_ptr = (uint32_t *)&(tm_ptr[3]);
c = 0;
for (i = 0; i < hal->number_of_nodes; i++) {
j = -1;
selfid_packet = hal->selfid_ptrs[i];
do {
j++;
data_ptr[c++] = selfid_packet[j].spkt_data;
}
while (IEEE1394_SELFID_ISMORE(&selfid_packet[j]));
}
tm_ptr[1] = tm_ptr[1] + 1;
node_count = (i & IEEE1394_TOP_MAP_LEN_MASK);
self_id_count = (c & IEEE1394_TOP_MAP_LEN_MASK);
tm_ptr[2] = (node_count << IEEE1394_TOP_MAP_LEN_SHIFT) |
(self_id_count);
length = self_id_count + 2;
CRC = s1394_CRC16(&(tm_ptr[1]), length);
tm_ptr[0] = (length << IEEE1394_TOP_MAP_LEN_SHIFT) | CRC;
}
void
s1394_CSR_topology_map_disable(s1394_hal_t *hal)
{
uint32_t *tm_ptr;
ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
tm_ptr = (uint32_t *)hal->CSR_topology_map;
tm_ptr[0] = tm_ptr[0] & IEEE1394_TOP_MAP_LEN_MASK;
}
static void
s1394_common_CSR_routine(s1394_hal_t *hal, cmd1394_cmd_t *req)
{
uint32_t data;
uint_t offset;
int result;
offset = (req->cmd_addr & IEEE1394_CSR_OFFSET_MASK);
if ((offset & 0x3) != 0) {
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
(void) s1394_send_response(hal, req);
}
switch (req->cmd_type) {
case CMD1394_ASYNCH_RD_QUAD:
result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
offset, &data);
if (result == DDI_SUCCESS) {
req->cmd_u.q.quadlet_data = data;
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
case CMD1394_ASYNCH_WR_QUAD:
data = req->cmd_u.q.quadlet_data;
result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
offset, data);
if (result == DDI_SUCCESS) {
req->cmd_result = IEEE1394_RESP_COMPLETE;
} else {
req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
}
break;
default:
req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
}
(void) s1394_send_response(hal, req);
}
int
s1394_init_local_config_rom(s1394_hal_t *hal)
{
uint32_t *config_rom;
uint32_t *node_unique_id_leaf;
uint32_t *unit_dir;
uint32_t *text_leaf;
void *n_handle;
uint64_t guid;
uint32_t guid_hi, guid_lo;
uint32_t bus_capabilities;
uint32_t irmc, g;
uint32_t module_vendor_id;
uint32_t node_capabilities;
uint32_t root_dir_len;
uint32_t CRC;
int status, i, ret;
mutex_init(&hal->local_config_rom_mutex,
NULL, MUTEX_DRIVER, hal->halinfo.hw_interrupt);
hal->local_config_rom = (uint32_t *)kmem_zalloc(IEEE1394_CONFIG_ROM_SZ,
KM_SLEEP);
hal->temp_config_rom_buf = (uint32_t *)kmem_zalloc(
IEEE1394_CONFIG_ROM_SZ, KM_SLEEP);
config_rom = hal->local_config_rom;
mutex_enter(&hal->local_config_rom_mutex);
ret = s1394_init_config_rom_structures(hal);
if (ret != DDI_SUCCESS) {
mutex_exit(&hal->local_config_rom_mutex);
kmem_free((void *)hal->temp_config_rom_buf,
IEEE1394_CONFIG_ROM_SZ);
kmem_free((void *)hal->local_config_rom,
IEEE1394_CONFIG_ROM_SZ);
mutex_destroy(&hal->local_config_rom_mutex);
return (DDI_FAILURE);
}
bus_capabilities = hal->halinfo.bus_capabilities;
irmc = (bus_capabilities & IEEE1394_BIB_IRMC_MASK) >>
IEEE1394_BIB_IRMC_SHIFT;
if (irmc)
bus_capabilities = bus_capabilities | IEEE1394_BIB_BMC_MASK;
g = 2 << IEEE1394_BIB_GEN_SHIFT;
bus_capabilities = bus_capabilities | g;
guid = hal->halinfo.guid;
guid_hi = (uint32_t)(guid >> 32);
guid_lo = (uint32_t)(guid & 0x00000000FFFFFFFF);
config_rom[1] = 0x31333934;
config_rom[2] = bus_capabilities;
config_rom[3] = guid_hi;
config_rom[4] = guid_lo;
CRC = s1394_CRC16(&config_rom[1], 4);
config_rom[0] = (0x04040000) | CRC;
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
config_rom[i] = T1394_DATA32(config_rom[i]);
module_vendor_id = S1394_SUNW_OUI;
node_capabilities = hal->halinfo.node_capabilities &
IEEE1212_NODE_CAPABILITIES_MASK;
root_dir_len = 2;
config_rom[6] = (IEEE1212_MODULE_VENDOR_ID <<
IEEE1212_KEY_VALUE_SHIFT) | module_vendor_id;
config_rom[7] = (IEEE1212_NODE_CAPABILITIES <<
IEEE1212_KEY_VALUE_SHIFT) | node_capabilities;
CRC = s1394_CRC16(&config_rom[6], root_dir_len);
config_rom[IEEE1394_BIB_QUAD_SZ] =
(root_dir_len << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
for (i = IEEE1394_BIB_QUAD_SZ; i < 8; i++)
config_rom[i] = T1394_DATA32(config_rom[i]);
text_leaf = (uint32_t *)kmem_zalloc(S1394_ROOT_TEXT_LEAF_SZ, KM_SLEEP);
text_leaf[1] = 0x00000000;
text_leaf[2] = 0x00000000;
text_leaf[3] = 0x53756e20;
text_leaf[4] = 0x4d696372;
text_leaf[5] = 0x6f737973;
text_leaf[6] = 0x74656d73;
text_leaf[7] = 0x2c20496e;
text_leaf[8] = 0x632e0000;
CRC = s1394_CRC16(&text_leaf[1], S1394_ROOT_TEXT_LEAF_QUAD_SZ - 1);
text_leaf[0] = (0x00080000) | CRC;
for (i = 0; i < 9; i++)
text_leaf[i] = T1394_DATA32(text_leaf[i]);
ret = s1394_add_config_rom_entry(hal, S1394_ROOT_TEXT_KEY, text_leaf,
S1394_ROOT_TEXT_LEAF_QUAD_SZ, &n_handle, &status);
if (ret != DDI_SUCCESS) {
kmem_free((void *)text_leaf, S1394_ROOT_TEXT_LEAF_SZ);
(void) s1394_destroy_config_rom_structures(hal);
mutex_exit(&hal->local_config_rom_mutex);
kmem_free((void *)hal->temp_config_rom_buf,
IEEE1394_CONFIG_ROM_SZ);
kmem_free((void *)hal->local_config_rom,
IEEE1394_CONFIG_ROM_SZ);
mutex_destroy(&hal->local_config_rom_mutex);
return (DDI_FAILURE);
}
kmem_free((void *)text_leaf, S1394_ROOT_TEXT_LEAF_SZ);
node_unique_id_leaf = (uint32_t *)kmem_zalloc(S1394_NODE_UNIQUE_ID_SZ,
KM_SLEEP);
node_unique_id_leaf[1] = guid_hi;
node_unique_id_leaf[2] = guid_lo;
CRC = s1394_CRC16(&node_unique_id_leaf[1],
S1394_NODE_UNIQUE_ID_QUAD_SZ - 1);
node_unique_id_leaf[0] = (0x00020000) | CRC;
for (i = 0; i < S1394_NODE_UNIQUE_ID_QUAD_SZ; i++)
node_unique_id_leaf[i] = T1394_DATA32(node_unique_id_leaf[i]);
ret = s1394_add_config_rom_entry(hal, S1394_NODE_UNIQUE_ID_KEY,
node_unique_id_leaf, S1394_NODE_UNIQUE_ID_QUAD_SZ, &n_handle,
&status);
if (ret != DDI_SUCCESS) {
kmem_free((void *)node_unique_id_leaf,
S1394_NODE_UNIQUE_ID_SZ);
(void) s1394_destroy_config_rom_structures(hal);
mutex_exit(&hal->local_config_rom_mutex);
kmem_free((void *)hal->temp_config_rom_buf,
IEEE1394_CONFIG_ROM_SZ);
kmem_free((void *)hal->local_config_rom,
IEEE1394_CONFIG_ROM_SZ);
mutex_destroy(&hal->local_config_rom_mutex);
return (DDI_FAILURE);
}
kmem_free((void *)node_unique_id_leaf, S1394_NODE_UNIQUE_ID_SZ);
unit_dir = (uint32_t *)kmem_zalloc(S1394_UNIT_DIR_SZ, KM_SLEEP);
unit_dir[1] = 0x12080020;
unit_dir[2] = 0x13000001;
unit_dir[3] = 0x81000001;
CRC = s1394_CRC16(&unit_dir[1], 3);
unit_dir[0] = (0x00030000) | CRC;
for (i = 0; i < 4; i++)
unit_dir[i] = T1394_DATA32(unit_dir[i]);
unit_dir[5] = 0x00000000;
unit_dir[6] = 0x00000000;
unit_dir[7] = 0x536f6c61;
unit_dir[8] = 0x72697320;
unit_dir[9] = 0x31333934;
unit_dir[10] = 0x20535720;
unit_dir[11] = 0x4672616d;
unit_dir[12] = 0x65576f72;
unit_dir[13] = 0x6b000000;
CRC = s1394_CRC16(&unit_dir[5], 9);
unit_dir[4] = (0x00090000) | CRC;
for (i = 4; i < S1394_UNIT_DIR_QUAD_SZ; i++)
unit_dir[i] = T1394_DATA32(unit_dir[i]);
ret = s1394_add_config_rom_entry(hal, S1394_UNIT_DIR_KEY, unit_dir,
S1394_UNIT_DIR_QUAD_SZ, &n_handle, &status);
if (ret != DDI_SUCCESS) {
kmem_free((void *)unit_dir, S1394_UNIT_DIR_SZ);
(void) s1394_destroy_config_rom_structures(hal);
mutex_exit(&hal->local_config_rom_mutex);
kmem_free((void *)hal->temp_config_rom_buf,
IEEE1394_CONFIG_ROM_SZ);
kmem_free((void *)hal->local_config_rom,
IEEE1394_CONFIG_ROM_SZ);
mutex_destroy(&hal->local_config_rom_mutex);
return (DDI_FAILURE);
}
kmem_free((void *)unit_dir, S1394_UNIT_DIR_SZ);
hal->config_rom_update_amount = (IEEE1394_CONFIG_ROM_QUAD_SZ -
hal->free_space);
mutex_exit(&hal->local_config_rom_mutex);
(void) HAL_CALL(hal).update_config_rom(hal->halinfo.hal_private,
config_rom, IEEE1394_CONFIG_ROM_QUAD_SZ);
return (DDI_SUCCESS);
}
void
s1394_destroy_local_config_rom(s1394_hal_t *hal)
{
mutex_enter(&hal->local_config_rom_mutex);
(void) s1394_destroy_config_rom_structures(hal);
mutex_exit(&hal->local_config_rom_mutex);
kmem_free((void *)hal->temp_config_rom_buf, IEEE1394_CONFIG_ROM_SZ);
kmem_free((void *)hal->local_config_rom, IEEE1394_CONFIG_ROM_SZ);
mutex_destroy(&hal->local_config_rom_mutex);
}
static int
s1394_init_config_rom_structures(s1394_hal_t *hal)
{
s1394_config_rom_t *root_directory;
s1394_config_rom_t *rest_of_config_rom;
ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
root_directory = (s1394_config_rom_t *)kmem_zalloc(
sizeof (s1394_config_rom_t), KM_SLEEP);
root_directory->cfgrom_used = B_TRUE;
root_directory->cfgrom_addr_lo = IEEE1394_BIB_QUAD_SZ;
root_directory->cfgrom_addr_hi = IEEE1394_BIB_QUAD_SZ + 2;
rest_of_config_rom = (s1394_config_rom_t *)kmem_zalloc(
sizeof (s1394_config_rom_t), KM_SLEEP);
rest_of_config_rom->cfgrom_used = B_FALSE;
rest_of_config_rom->cfgrom_addr_lo = root_directory->cfgrom_addr_hi + 1;
rest_of_config_rom->cfgrom_addr_hi = IEEE1394_CONFIG_ROM_QUAD_SZ - 1;
root_directory->cfgrom_next = rest_of_config_rom;
root_directory->cfgrom_prev = NULL;
rest_of_config_rom->cfgrom_next = NULL;
rest_of_config_rom->cfgrom_prev = root_directory;
hal->root_directory = root_directory;
hal->free_space = IEEE1394_CONFIG_ROM_QUAD_SZ -
(rest_of_config_rom->cfgrom_addr_lo);
return (DDI_SUCCESS);
}
static int
s1394_destroy_config_rom_structures(s1394_hal_t *hal)
{
s1394_config_rom_t *curr_blk;
s1394_config_rom_t *next_blk;
ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
curr_blk = hal->root_directory;
while (curr_blk != NULL) {
next_blk = curr_blk->cfgrom_next;
kmem_free(curr_blk, sizeof (s1394_config_rom_t));
curr_blk = next_blk;
}
return (DDI_SUCCESS);
}
int
s1394_add_config_rom_entry(s1394_hal_t *hal, uint8_t key, uint32_t *buffer,
uint_t size, void **handle, int *status)
{
s1394_config_rom_t *curr_blk;
s1394_config_rom_t *new_blk;
uint32_t *config_rom;
uint32_t *temp_buf;
uint32_t CRC;
uint_t tmp_offset;
uint_t tmp_size, temp;
uint_t last_entry_offset;
int i;
ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
if (size > hal->free_space) {
*status = CMD1394_ERSRC_CONFLICT;
return (DDI_FAILURE);
}
config_rom = hal->local_config_rom;
temp_buf = hal->temp_config_rom_buf;
bcopy(&config_rom[0], &temp_buf[0], IEEE1394_BIB_SZ);
tmp_offset = hal->root_directory->cfgrom_addr_lo;
tmp_size = (hal->root_directory->cfgrom_addr_hi - tmp_offset) + 1;
tmp_size = tmp_size + 1;
bcopy(&config_rom[tmp_offset], &temp_buf[tmp_offset], tmp_size << 2);
last_entry_offset = hal->root_directory->cfgrom_addr_hi + 1;
curr_blk = hal->root_directory;
curr_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi + 1;
while (curr_blk->cfgrom_next != NULL) {
if (curr_blk->cfgrom_next->cfgrom_used == B_TRUE) {
tmp_offset = curr_blk->cfgrom_next->cfgrom_addr_lo;
tmp_size = (curr_blk->cfgrom_next->cfgrom_addr_hi -
tmp_offset) + 1;
bcopy(&config_rom[tmp_offset],
&temp_buf[tmp_offset + 1], tmp_size << 2);
curr_blk->cfgrom_next->cfgrom_addr_lo++;
curr_blk->cfgrom_next->cfgrom_addr_hi++;
last_entry_offset =
curr_blk->cfgrom_next->cfgrom_addr_hi;
tmp_offset = curr_blk->cfgrom_next->root_dir_offset;
temp = T1394_DATA32(temp_buf[tmp_offset]);
temp++;
temp_buf[tmp_offset] = T1394_DATA32(temp);
} else {
curr_blk->cfgrom_next->cfgrom_addr_lo++;
hal->free_space--;
break;
}
curr_blk = curr_blk->cfgrom_next;
}
curr_blk = curr_blk->cfgrom_next;
if (hal->free_space == size) {
curr_blk->cfgrom_used = B_TRUE;
} else {
new_blk = (s1394_config_rom_t *)kmem_zalloc(
sizeof (s1394_config_rom_t), KM_SLEEP);
if (new_blk == NULL) {
return (DDI_FAILURE);
}
new_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi;
new_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo + size;
curr_blk->cfgrom_addr_hi = new_blk->cfgrom_addr_lo - 1;
new_blk->cfgrom_next = curr_blk->cfgrom_next;
curr_blk->cfgrom_next = new_blk;
new_blk->cfgrom_prev = curr_blk;
curr_blk->cfgrom_used = B_TRUE;
last_entry_offset = curr_blk->cfgrom_addr_hi;
}
hal->free_space = hal->free_space - size;
tmp_offset = curr_blk->cfgrom_addr_lo;
bcopy(buffer, &temp_buf[tmp_offset], size << 2);
tmp_offset = hal->root_directory->cfgrom_addr_hi;
tmp_size = tmp_offset - hal->root_directory->cfgrom_addr_lo;
curr_blk->root_dir_offset = tmp_offset;
tmp_offset = curr_blk->cfgrom_addr_lo - tmp_offset;
temp_buf[hal->root_directory->cfgrom_addr_hi] =
T1394_DATA32((((uint32_t)key) << IEEE1212_KEY_VALUE_SHIFT) |
tmp_offset);
tmp_offset = hal->root_directory->cfgrom_addr_lo;
for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
i++)
temp_buf[i] = T1394_DATA32(temp_buf[i]);
CRC = s1394_CRC16(&temp_buf[tmp_offset + 1], tmp_size);
temp_buf[tmp_offset] = (tmp_size << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
for (i = tmp_offset; i <= hal->root_directory->cfgrom_addr_hi; i++)
temp_buf[i] = T1394_DATA32(temp_buf[i]);
last_entry_offset++;
bcopy(&temp_buf[0], &config_rom[0], last_entry_offset << 2);
*handle = curr_blk;
*status = T1394_NOERROR;
return (DDI_SUCCESS);
}
int
s1394_remove_config_rom_entry(s1394_hal_t *hal, void **handle, int *status)
{
s1394_config_rom_t *del_blk;
s1394_config_rom_t *curr_blk;
s1394_config_rom_t *last_blk;
s1394_config_rom_t *free_blk;
uint32_t *config_rom;
uint32_t *temp_buf;
uint32_t entry;
uint_t CRC;
uint_t root_offset;
uint_t del_offset;
uint_t tmp_offset;
uint_t tmp_size;
int i;
ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
del_blk = (s1394_config_rom_t *)(*handle);
config_rom = hal->local_config_rom;
temp_buf = hal->temp_config_rom_buf;
bcopy(&config_rom[0], &temp_buf[0], IEEE1394_BIB_SZ);
root_offset = hal->root_directory->cfgrom_addr_lo;
del_offset = del_blk->root_dir_offset;
for (i = root_offset; i < del_offset; i++) {
entry = T1394_DATA32(config_rom[i]);
if (entry & 0x80000000)
temp_buf[i] = T1394_DATA32(entry - 1);
else
temp_buf[i] = T1394_DATA32(entry);
}
curr_blk = hal->root_directory->cfgrom_next;
while (curr_blk != del_blk) {
tmp_offset = curr_blk->cfgrom_addr_lo;
tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
bcopy(&config_rom[tmp_offset], &temp_buf[tmp_offset - 1],
tmp_size << 2);
curr_blk->cfgrom_addr_lo--;
curr_blk->cfgrom_addr_hi--;
curr_blk = curr_blk->cfgrom_next;
}
curr_blk = del_blk->cfgrom_next;
last_blk = del_blk->cfgrom_prev;
del_offset = (del_blk->cfgrom_addr_hi - del_blk->cfgrom_addr_lo) + 1;
while ((curr_blk != NULL) && (curr_blk->cfgrom_used == B_TRUE)) {
tmp_offset = curr_blk->cfgrom_addr_lo;
tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
bcopy(&config_rom[tmp_offset],
&temp_buf[tmp_offset - (del_offset + 1)], tmp_size << 2);
root_offset = curr_blk->root_dir_offset;
temp_buf[root_offset - 1] =
config_rom[root_offset] - del_offset;
curr_blk->root_dir_offset--;
curr_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo -
(del_offset + 1);
curr_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi -
(del_offset + 1);
last_blk = curr_blk;
curr_blk = curr_blk->cfgrom_next;
}
if (del_blk->cfgrom_prev != NULL)
del_blk->cfgrom_prev->cfgrom_next = del_blk->cfgrom_next;
if (del_blk->cfgrom_next != NULL)
del_blk->cfgrom_next->cfgrom_prev = del_blk->cfgrom_prev;
del_blk->cfgrom_prev = NULL;
del_blk->cfgrom_next = NULL;
kmem_free((void *)del_blk, sizeof (s1394_config_rom_t));
if (curr_blk != NULL) {
curr_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo -
(del_offset + 1);
} else {
free_blk = (s1394_config_rom_t *)kmem_zalloc(
sizeof (s1394_config_rom_t), KM_SLEEP);
if (free_blk == NULL) {
return (DDI_FAILURE);
}
free_blk->cfgrom_used = B_FALSE;
free_blk->cfgrom_addr_lo = (IEEE1394_CONFIG_ROM_QUAD_SZ - 1) -
(del_offset + 1);
free_blk->cfgrom_addr_hi = (IEEE1394_CONFIG_ROM_QUAD_SZ - 1);
free_blk->cfgrom_prev = last_blk;
free_blk->cfgrom_next = NULL;
curr_blk = free_blk;
}
hal->free_space = hal->free_space + (del_offset + 1);
tmp_offset = curr_blk->cfgrom_addr_lo;
tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
bzero(&temp_buf[tmp_offset], tmp_size << 2);
hal->root_directory->cfgrom_addr_hi--;
tmp_offset = hal->root_directory->cfgrom_addr_lo;
tmp_size = hal->root_directory->cfgrom_addr_hi - tmp_offset;
for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
i++)
temp_buf[i] = T1394_DATA32(temp_buf[i]);
CRC = s1394_CRC16(&temp_buf[tmp_offset + 1], tmp_size);
temp_buf[tmp_offset] = (tmp_size << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
i++)
temp_buf[i] = T1394_DATA32(temp_buf[i]);
tmp_size = IEEE1394_CONFIG_ROM_SZ - (hal->free_space << 2);
bcopy(&temp_buf[0], &config_rom[0], tmp_size);
*handle = NULL;
*status = T1394_NOERROR;
return (DDI_SUCCESS);
}
void
s1394_update_config_rom_callback(void *arg)
{
s1394_hal_t *hal;
uint32_t *config_rom;
uint32_t bus_capabilities;
uint32_t g;
uint_t CRC;
uint_t last_entry_offset;
int i;
hal = (s1394_hal_t *)arg;
mutex_enter(&hal->local_config_rom_mutex);
config_rom = hal->local_config_rom;
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
config_rom[i] = T1394_DATA32(config_rom[i]);
bus_capabilities = config_rom[IEEE1212_NODE_CAP_QUAD];
g = ((bus_capabilities & IEEE1394_BIB_GEN_MASK) >>
IEEE1394_BIB_GEN_SHIFT) + 1;
if (g > 15)
g = 2;
g = g << IEEE1394_BIB_GEN_SHIFT;
bus_capabilities = (bus_capabilities & (~IEEE1394_BIB_GEN_MASK)) | g;
config_rom[IEEE1212_NODE_CAP_QUAD] = bus_capabilities;
CRC = s1394_CRC16(&config_rom[1], IEEE1394_BIB_QUAD_SZ - 1);
config_rom[0] = (0x04040000) | CRC;
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
config_rom[i] = T1394_DATA32(config_rom[i]);
last_entry_offset = (IEEE1394_CONFIG_ROM_QUAD_SZ - hal->free_space);
if (last_entry_offset < hal->config_rom_update_amount)
last_entry_offset = hal->config_rom_update_amount;
hal->config_rom_update_amount = (IEEE1394_CONFIG_ROM_QUAD_SZ -
hal->free_space);
hal->config_rom_timer_set = B_FALSE;
mutex_exit(&hal->local_config_rom_mutex);
(void) HAL_CALL(hal).update_config_rom(hal->halinfo.hal_private,\
config_rom, last_entry_offset);
(void) HAL_CALL(hal).bus_reset(hal->halinfo.hal_private);
}