/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_1394_S1394_H
#define	_SYS_1394_S1394_H

/*
 * s1394.h
 *    Contains all of the structures used (internally) by the 1394
 *    Software Framework
 */

#include <sys/types.h>
#include <sys/dditypes.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sunndi.h>
#include <sys/callb.h>
#include <sys/note.h>

#include <sys/1394/s1394_impl.h>
#include <sys/1394/t1394.h>
#include <sys/1394/h1394.h>
#include <sys/1394/cmd1394.h>
#include <sys/1394/ieee1212.h>
#include <sys/1394/ieee1394.h>

#ifdef	__cplusplus
extern "C" {
#endif

/* SelfID buffer size */
#define	S1394_SELFID_BUF_SIZE		8192

/* Maximum number of allocated commands per target */
#define	MAX_NUMBER_ALLOC_CMDS		256

/* Maximum number of lock retries */
#define	MAX_NUMBER_OF_LOCK_RETRIES	256

#define	S1394_INITIAL_STATES		2

/* Invalid entry in the Speed Map */
#define	SPEED_MAP_INVALID		0xFF

/* Invalid node num */
#define	S1394_INVALID_NODE_NUM		0x3F

/* Node state */
#define	S1394_NODE_OFFLINE		1
#define	S1394_NODE_ONLINE		2

/* Where are commands inserted onto the pending Q? */
#define	S1394_PENDING_Q_FRONT		1
#define	S1394_PENDING_Q_REAR		2

/* Number of self-initiated bus resets until HAL fails */
#define	NUM_BR_FAIL			5

/* Reasons for Self-Initiated Bus Reset */
#define	NON_CRITICAL			0
#define	CRITICAL			1

/* Bus Mgr (IRM) defines */
#define	ROOT_HOLDOFF			(1 << 0)
#define	GAP_COUNT			(1 << 1)

/* Root Node has no parents */
#define	NO_PARENT			-1

/* Maximum number of Hops between Nodes on the Bus */
#define	MAX_HOPS			23

/* Invalid lo and hi addresses used in s1394_init_addr_space() */
#define	ADDR_LO_INVALID			0x0000000000000001
#define	ADDR_HI_INVALID			0x0000000000000000

/* Time to delay after CYCLE_TOO_LONG before enabling cycle master */
#define	CYCLE_MASTER_TIMER		1000	/* 1 second */

/* Size of directory stack used during config rom scan */
#define	S1394_DIR_STACK_SIZE		16

/*
 * P1394a (Draft 2.x) proposes to disallow a
 * Config ROM "generation" to be repeated within
 * a 60 second window.
 * Because of that, this value should not be set
 * to any value smaller than 5 seconds without
 * another method in place to ensure that this
 * "generation" reuse can not happen.
 */

/*
 * Time delay (in ms) from Config ROM update to
 * software-initiated bus reset.
 */
#define	CONFIG_ROM_UPDATE_DELAY		5000	/* 5 seconds */

#define	S1394_ROOT_TEXT_LEAF_SZ		36
#define	S1394_ROOT_TEXT_LEAF_QUAD_SZ	9
#define	S1394_ROOT_TEXT_KEY		0x81

#define	S1394_NODE_UNIQUE_ID_SZ		12
#define	S1394_NODE_UNIQUE_ID_QUAD_SZ	3
#define	S1394_NODE_UNIQUE_ID_KEY	0x8D

#define	S1394_UNIT_DIR_SZ		56
#define	S1394_UNIT_DIR_QUAD_SZ		14
#define	S1394_UNIT_DIR_KEY		0xD1

/* The Organizationally Unique Identifier for Sun Microsystems, Inc. */
#define	S1394_SUNW_OUI			0x080020

/* Number of retries in reading the Config ROM */
#define	CFGROM_READ_RETRIES		5

/* Delay time between reads of the Config ROM */
#define	CFGROM_READ_DELAY		20000	/* 20ms */

/* Error message for serious HBA hardware shutdowns */
#define	HALT_ERROR_MESSAGE	"%s%d: Unexpected Error: Shutting down HBA -" \
	" Hardware disabled until next reboot"

/* Command Transaction Type */
#define	S1394_CMD_READ		0
#define	S1394_CMD_WRITE		1
#define	S1394_CMD_LOCK		2

/* Channel allocations */
#define	S1394_CHANNEL_ALLOC_HI	1
#define	S1394_CHANNEL_ALLOC_LO	0

/* Maximum number of bus resets allowed in isoch rsrc alloc */
#define	S1394_ISOCH_ALLOC_RETRIES	5

#define	ADDR_RESERVED		1

/* Flags used by the used tree (red-black tree) */
#define	BLACK			0
#define	RED			1
#define	LEFT			0
#define	RIGHT			1

/* Isoch Bandwidth Allocation Units conversion */
#define	ISOCH_SPEED_FACTOR_S100		16
#define	ISOCH_SPEED_FACTOR_S200		8
#define	ISOCH_SPEED_FACTOR_S400		4

/* s1394_hal_state_t */
typedef enum {
	S1394_HAL_INIT,
	S1394_HAL_RESET,
	S1394_HAL_NORMAL,
	S1394_HAL_DREQ,
	S1394_HAL_SHUTDOWN
} s1394_hal_state_t;

/* s1394_isoch_cec_type_t */
typedef enum {
	S1394_SINGLE		= 1,
	S1394_PEER_TO_PEER	= 2
} s1394_isoch_cec_type_t;

/* s1394_isoch_cec_state_t */
typedef enum {
	ISOCH_CEC_FREE		= (1 << 0),
	ISOCH_CEC_JOIN		= (1 << 1),
	ISOCH_CEC_LEAVE		= (1 << 2),
	ISOCH_CEC_SETUP		= (1 << 3),
	ISOCH_CEC_TEARDOWN	= (1 << 4),
	ISOCH_CEC_START		= (1 << 5),
	ISOCH_CEC_STOP		= (1 << 6)
} s1394_isoch_cec_state_t;

/* s1394_status_t */
typedef enum {
	S1394_NOSTATUS		= (1 << 0),
	S1394_LOCK_FAILED	= (1 << 1),
	S1394_CMD_ALLOC_FAILED	= (1 << 2),
	S1394_XFER_FAILED	= (1 << 3),
	S1394_UNKNOWN		= (1 << 4),
	S1394_CMD_INFLIGHT	= (1 << 5)
} s1394_status_t;

/* s1394_free_cfgrom_t */
typedef enum {
	S1394_FREE_CFGROM_BOTH,
	S1394_FREE_CFGROM_NEW,
	S1394_FREE_CFGROM_OLD
} s1394_free_cfgrom_t;

typedef struct s1394_node_s		s1394_node_t;
typedef struct s1394_target_s		s1394_target_t;
typedef struct s1394_hal_s		s1394_hal_t;
typedef struct s1394_addr_space_blk_s	s1394_addr_space_blk_t;
typedef struct s1394_config_rom_s	s1394_config_rom_t;
typedef struct s1394_kstat_s		s1394_kstat_t;
typedef struct s1394_isoch_cec_s	s1394_isoch_cec_t;
typedef struct s1394_isoch_cec_member_s	s1394_isoch_cec_member_t;

/* cfgrom_dir_t */
typedef struct {
	ushort_t		dir_start;
	ushort_t		dir_size;
	ushort_t		dir_next_quad;
} cfgrom_dir_t;

/* s1394_selfid_pkt_t */
typedef struct s1394_selfid_pkt_s {
	uint32_t		spkt_data;
	uint32_t		spkt_inverse;
} s1394_selfid_pkt_t;

/* s1394_node_t */
struct s1394_node_s {
	s1394_selfid_pkt_t	*selfid_packet;
	s1394_node_t		*phy_port[IEEE1394_MAX_NUM_PORTS];
	s1394_node_t		*old_node;
	s1394_node_t		*cur_node;
	s1394_target_t		*target_list;
	ushort_t		cfgrom_size;		/* in quads */
	ushort_t		cfgrom_valid_size;	/* in quads */
	uchar_t			link_active;
	uchar_t			node_num;
	uchar_t			max_1st;
	uchar_t			max_2nd;
	uchar_t			last_port_checked;
	uchar_t			parent_port;
	uchar_t			is_a_leaf;
	/* All fields above can be zero'd while initing the topology tree */
	uint32_t		*cfgrom;
#define	node_guid_hi		cfgrom[3]
#define	node_guid_lo		cfgrom[4]
#define	node_root_dir		cfgrom[5]
	uint_t			node_state;
	uint_t			cfgrom_state;
	uint_t			bus_enum_flags;
	/* fields dir_stack through expected_dir_quad constitute dir stack */
	cfgrom_dir_t		dir_stack[S1394_DIR_STACK_SIZE];
	ushort_t		cur_dir_start;
	ushort_t		cur_dir_size;
	char			dir_stack_top;
	uchar_t			expected_type;
	uchar_t			expected_dir_quad;
	ushort_t		cfgrom_quad_to_read;
	ushort_t		cfgrom_quad_read_cnt; /* if rdg blk */
	uchar_t			rescan_cnt;
	uchar_t			cfgrom_read_fails;
	uchar_t			cfgrom_read_delay;	/* in ms */
};

/* defines used during enumeration */
#define	NODE_DIR_SIZE(data)		((data) & 0xff)
#define	NODE_DIR_START(data)		(((data) >> 8) & 0xff)
#define	NODE_DIR_QUAD(data)		(((data) >> 16) & 0xff)

/* defines for link_active */
#define	SET_LINK_ACTIVE(n)	((n)->link_active = 1)
#define	CLEAR_LINK_ACTIVE(n) 	((n)->link_active = 0)
#define	LINK_ACTIVE(n)			\
		(((n)->link_active == 0) ? B_FALSE : B_TRUE)
/* defines for state */
#define	S1394_NODE_CONSUMING_PWR	0x00000001
#define	S1394_NODE_ACTIVE		0x00000010
#define	S1394_NODE_BUS_PWR_CONSUMER(n)		\
	((IEEE1394_SELFID_POWER((n)->selfid_packet) > 0x3) ? B_TRUE : B_FALSE)

/* defines for cfgrom_state */
#define	S1394_CFGROM_NEW_ALLOC		0x00000001 /* fresh alloc */
#define	S1394_CFGROM_BIB_READ		0x00000002 /* bus info blocks read */
#define	S1394_CFGROM_ALL_READ		0x00000004 /* read all of it */
#define	S1394_CFGROM_BLK_READ_OK	0x00000008 /* can be read in blocks */
#define	S1394_CFGROM_GEN_CHANGED	0x00000010 /* config rom gen changed */
#define	S1394_CFGROM_PARSED		0x00000020 /* rom enumerated */
#define	S1394_CFGROM_DIR_STACK_OFF	0x00000040 /* dir stack turned off */
#define	S1394_CFGROM_SIZE_IS_CRCSIZE	0x00000080 /* crc size == cfgrom size */

#define	S1394_CFGROM_READ_MASK	(S1394_CFGROM_BIB_READ | S1394_CFGROM_ALL_READ)

#define	S1394_VALID_MASK			\
	(S1394_CFGROM_READ_MASK | S1394_CFGROM_BLK_READ_OK | \
	S1394_CFGROM_GEN_CHANGED | S1394_CFGROM_PARSED)

#define	CLEAR_CFGROM_STATE(n)	((n)->cfgrom_state &= ~S1394_VALID_MASK)
#define	CFGROM_VALID(n)				\
	((((n)->cfgrom_state & S1394_CFGROM_READ_MASK) != 0 && (n)->cfgrom != \
	    NULL) ? B_TRUE : B_FALSE)

/* macros for cfgrom_state */
#define	SET_CFGROM_NEW_ALLOC(n)	((n)->cfgrom_state |= S1394_CFGROM_NEW_ALLOC)
#define	CLEAR_CFGROM_NEW_ALLOC(n) ((n)->cfgrom_state &= ~S1394_CFGROM_NEW_ALLOC)
#define	CFGROM_NEW_ALLOC(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_NEW_ALLOC) != 0 ? B_TRUE : B_FALSE)

#define	SET_CFGROM_BIB_READ(n)	((n)->cfgrom_state |= S1394_CFGROM_BIB_READ)
#define	CLEAR_CFGROM_BIB_READ(n) ((n)->cfgrom_state &= ~S1394_CFGROM_BIB_READ)
#define	CFGROM_BIB_READ(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_BIB_READ) != 0 ? B_TRUE : B_FALSE)

#define	SET_CFGROM_ALL_READ(n)	((n)->cfgrom_state |= S1394_CFGROM_ALL_READ)
#define	CLEAR_CFGROM_ALL_READ(n)	((n)->cfgrom_state &= \
	~S1394_CFGROM_ALL_READ)
#define	CFGROM_ALL_READ(n)				\
	(((n)->cfgrom_state & S1394_CFGROM_ALL_READ) != 0 ? B_TRUE : B_FALSE)

#define	SET_CFGROM_BLK_READ_OK(n)		\
	((n)->cfgrom_state |= S1394_CFGROM_BLK_READ_OK)
#define	CLEAR_CFGROM_BLK_READ_OK(n)		\
	((n)->cfgrom_state &= ~S1394_CFGROM_BLK_READ_OK)
#define	CFGROM_BLK_READ_OK(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_BLK_READ_OK) != 0 : B_TRUE : B_FALSE)

#define	SET_CFGROM_GEN_CHANGED(n)		\
	((n)->cfgrom_state |= S1394_CFGROM_GEN_CHANGED)
#define	CLEAR_CFGROM_GEN_CHANGED(n)		\
	((n)->cfgrom_state &= ~S1394_CFGROM_GEN_CHANGED)
#define	CFGROM_GEN_CHANGED(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_GEN_CHANGED) != 0 ? B_TRUE : B_FALSE)

#define	SET_CFGROM_PARSED(n)	((n)->cfgrom_state |= S1394_CFGROM_PARSED)
#define	CLEAR_CFGROM_PARSED(n)	((n)->cfgrom_state &= ~S1394_CFGROM_PARSED)
#define	CFGROM_PARSED(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_PARSED) != 0 ? B_TRUE : B_FALSE)

#define	SET_CFGROM_DIR_STACK_OFF(n)		\
	((n)->cfgrom_state |= S1394_CFGROM_DIR_STACK_OFF)
#define	CLEAR_CFGROM_DIR_STACK_OFF(n)		\
	((n)->cfgrom_state &= ~S1394_CFGROM_DIR_STACK_OFF)
#define	CFGROM_DIR_STACK_OFF(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_DIR_STACK_OFF) != 0 ? B_TRUE : \
	    B_FALSE)

#define	SET_CFGROM_SIZE_IS_CRCSIZE(n)		\
	((n)->cfgrom_state |= S1394_CFGROM_SIZE_IS_CRCSIZE)
#define	CLEAR_CFGROM_SIZE_IS_CRCSIZE(n)		\
	((n)->cfgrom_state &= ~S1394_CFGROM_SIZE_IS_CRCSIZE)
#define	CFGROM_SIZE_IS_CRCSIZE(n)			\
	(((n)->cfgrom_state & S1394_CFGROM_SIZE_IS_CRCSIZE) != 0 ? B_TRUE : \
	    B_FALSE)

/* defines for bus_enum_flags */
#define	S1394_NODE_VISITED		0x00000001
#define	S1394_NODE_MATCHED		0x00000010

/* macros that set/clear bus_enum_flags */
#define	SET_NODE_VISITED(n)	((n)->bus_enum_flags |= S1394_NODE_VISITED)
#define	CLEAR_NODE_VISITED(n)	((n)->bus_enum_flags &= ~S1394_NODE_VISITED)
#define	NODE_VISITED(n)				\
	(((n)->bus_enum_flags & S1394_NODE_VISITED) != 0 ? B_TRUE : B_FALSE)

#define	SET_NODE_MATCHED(n)	((n)->bus_enum_flags |= S1394_NODE_MATCHED)
#define	CLEAR_NODE_MATCHED(n)	((n)->bus_enum_flags &= ~S1394_NODE_MATCHED)
#define	NODE_MATCHED(n)				\
	(((n)->bus_enum_flags & S1394_NODE_MATCHED) != 0 ? B_TRUE : B_FALSE)

#define	SET_NODE_IDENTIFIED(n)	((n)->bus_enum_flags |= S1394_NODE_IDENTIFIED)
#define	CLEAR_NODE_IDENTIFIED(n) ((n)->bus_enum_flags &= ~S1394_NODE_IDENTIFIED)
#define	NODE_IDENTIFIED(n)			\
	(((n)->bus_enum_flags & S1394_NODE_IDENTIFIED) != 0 ? B_TRUE : B_FALSE)

/*
 * s1394_fa_type_t - FA types, used as index into target_fa and hal_fa
 */
typedef enum {
	S1394_FA_TYPE_FCP_CTL,		/* FCP controller */
	S1394_FA_TYPE_FCP_TGT,		/* FCP target */
	S1394_FA_TYPE_CMP_OMPR,		/* CMP oMPR */
	S1394_FA_TYPE_CMP_IMPR,		/* CMP iMPR */
	S1394_FA_NTYPES,		/* should remain the last field */
	S1394_FA_TYPE_CMP = S1394_FA_TYPE_CMP_OMPR	/* common CMP type */
} s1394_fa_type_t;


/*
 * s1394_fa_descr_t - FA type descriptor
 */
typedef struct s1394_fa_descr_s {
	uint64_t		fd_addr;	/* address space  */
	size_t			fd_size;	/* address space size */
	t1394_addr_enable_t	fd_enable;	/* access types */
	t1394_addr_evts_t	fd_evts;	/* event callbacks */
	uint64_t		fd_conv_base;	/* address conversion base */
} s1394_fa_descr_t;

/*
 * s1394_fcp_target_t - per-target data required for FCP support
 */
typedef struct s1394_fcp_target_s {
	t1394_fcp_evts_t	fc_evts;
} s1394_fcp_target_t;

/*
 * s1394_cmp_target_t - per-target data required for CMP support
 */
typedef struct s1394_cmp_target_s {
	t1394_cmp_evts_t	cm_evts;
} s1394_cmp_target_t;

/*
 * s1394_fa_target_t - per-target data required for fixed address support
 */
typedef struct s1394_fa_target_s {
	s1394_target_t		*fat_next;	/* next in the list */
	/* type-specific data */
	union {
		s1394_fcp_target_t	fcp;
		s1394_cmp_target_t	cmp;
	} fat_u;
} s1394_fa_target_t;

/* s1394_target_t - fields protected by the HAL's target_list_rwlock */
struct s1394_target_s {
	int			target_version;

	dev_info_t		*target_dip;

	/* Pointers to the node and HAL on which the target exists */
	s1394_node_t		*on_node;
	s1394_hal_t		*on_hal;

	s1394_target_t		*target_next;
	s1394_target_t		*target_prev;

	/* target_list is a copy of target_list pointer in the node */
	s1394_target_t		*target_list;
	s1394_target_t		*target_sibling;

	uint_t			unit_dir;

	/* The max_payload sizes - max and current conditions */
	uint_t			dev_max_payload;
	uint_t			current_max_payload;

	/* Number of asynch command target has allocated */
	uint_t			target_num_cmds;

	/*
	 * Are physical AR requests allowed from this target's node?
	 * This field keeps track of the number of allocated blocks
	 * of physical memory the target has.
	 */
	uint_t			physical_arreq_enabled;

	uint_t			target_state;

	/* FCP controller and target */
	s1394_fa_target_t	target_fa[S1394_FA_NTYPES];
};
#define	S1394_TARG_HP_NODE		0x00000001	/* on a hp node */
#define	S1394_TARG_GONE			0x00000002	/* unplugged */
#define	S1394_TARG_USING_BUS_PWR	0x00000004	/* consuming pwr now */
#define	S1394_TARG_BUS_PWR_CONSUMER	0x00000008	/* power consumer */
#define	S1394_TARG_ACTIVE		0x00000010	/* active */

/*
 * s1394_fa_hal_t - per-hal data required for fixed address support
 */
typedef struct s1394_fa_hal_s {
	/*
	 * each hal keeps a list of registered fixed address clients
	 */
	s1394_target_t		*fal_head;
	s1394_target_t		*fal_tail;
	uint_t			fal_gen;	/* list generation */

	s1394_fa_descr_t	*fal_descr;	/* type descriptor */
	s1394_addr_space_blk_t	*fal_addr_blk;	/* address space block */
} s1394_fa_hal_t;

/*
 * s1394_cmp_hal_t - per-hal data required for fixed address support
 */
typedef struct s1394_cmp_hal_s {
	/* oMPR */
	krwlock_t		cmp_ompr_rwlock;
	uint32_t		cmp_ompr_val;
	/* iMPR */
	krwlock_t		cmp_impr_rwlock;
	uint32_t		cmp_impr_val;
} s1394_cmp_hal_t;

/* s1394_hal_t */
struct s1394_hal_s {
	s1394_hal_t		*hal_next;
	s1394_hal_t		*hal_prev;

	/* Target list */
	s1394_target_t		*target_head;
	s1394_target_t		*target_tail;
	krwlock_t		target_list_rwlock;

	/* halinfo structure given at attach time */
	h1394_halinfo_t		halinfo;

	boolean_t		hal_was_suspended;

	/* Bus reset thread */
	kthread_t		*br_thread;
	kmutex_t		br_thread_mutex;
	kcondvar_t		br_thread_cv;
	uint_t			br_thread_ev_type;
	uint32_t		br_cfgrom_read_gen;
	kmutex_t		br_cmplq_mutex;
	kcondvar_t		br_cmplq_cv;
	cmd1394_cmd_t		*br_cmplq_head;
	cmd1394_cmd_t		*br_cmplq_tail;

	s1394_hal_state_t	hal_state;

	/* kstats - kernel statistics for the Services Layer */
	s1394_kstat_t		*hal_kstats;
	kstat_t			*hal_ksp;

	/* CSR STATE register bits (DREQ and ABDICATE) */
	uint_t			disable_requests_bit;
	uint_t			abdicate_bus_mgr_bit;

	boolean_t		initiated_bus_reset;
	int			initiated_br_reason;
	uint32_t		num_bus_reset_till_fail;

	/* IRM and Bus Manager */
	int			IRM_node;
	kmutex_t		bus_mgr_node_mutex;
	kcondvar_t		bus_mgr_node_cv;
	int			bus_mgr_node;
	boolean_t		incumbent_bus_mgr;
	timeout_id_t		bus_mgr_timeout_id;
	timeout_id_t		bus_mgr_query_timeout_id;

	/* 1394 Bus stats */
	int			gap_count;
	int			optimum_gap_count;
	uint8_t			slowest_node_speed;

	/* Local Config ROM */
	kmutex_t		local_config_rom_mutex;
	uint32_t		*local_config_rom;
	uint32_t		*temp_config_rom_buf;
	s1394_config_rom_t	*root_directory;
	uint_t			free_space;
	uint_t			config_rom_update_amount;
	boolean_t		config_rom_timer_set;
	timeout_id_t		config_rom_timer;

	/* Cycle Master - CYCLE_TOO_LONG timer */
	kmutex_t		cm_timer_mutex;
	boolean_t		cm_timer_set;
	timeout_id_t		cm_timer;

	/* Incoming (AR) request and 1394 address space */
	kmutex_t		addr_space_free_mutex;
	s1394_addr_space_blk_t	*addr_space_free_list;
	kmutex_t		addr_space_used_mutex;
	s1394_addr_space_blk_t	*addr_space_used_tree;
	uint64_t		physical_addr_lo;
	uint64_t		physical_addr_hi;
	uint64_t		csr_addr_lo;
	uint64_t		csr_addr_hi;
	uint64_t		normal_addr_lo;
	uint64_t		normal_addr_hi;
	uint64_t		posted_write_addr_lo;
	uint64_t		posted_write_addr_hi;

	/* Outgoing (AT) request queues */
	kmutex_t		outstanding_q_mutex;
	cmd1394_cmd_t		*outstanding_q_head;
	cmd1394_cmd_t		*outstanding_q_tail;
	kmutex_t		pending_q_mutex;
	cmd1394_cmd_t		*pending_q_head;
	cmd1394_cmd_t		*pending_q_tail;

	/* SelfID buffers */
	void			*selfid_buf0;
	void			*selfid_buf1;
	int			current_buffer;
	s1394_selfid_pkt_t	*selfid_ptrs[IEEE1394_MAX_NODES];

	/* Topology trees and local bus stats */
	kmutex_t		topology_tree_mutex;
	uint32_t		cfgroms_being_read;
	s1394_node_t		*topology_tree;
	s1394_node_t		*old_tree;
	uint32_t		generation_count;
	ushort_t		number_of_nodes;
	ushort_t		node_id;
	boolean_t		topology_tree_valid;
	boolean_t		topology_tree_processed;
	uint32_t		old_generation_count;
	ushort_t		old_number_of_nodes;
	ushort_t		old_node_id;
	s1394_node_t		current_tree[IEEE1394_MAX_NODES];
	s1394_node_t		last_valid_tree[IEEE1394_MAX_NODES];
	boolean_t		old_tree_valid;

	/* TOPOLOGY_MAP backing store buffer */
	uint32_t		*CSR_topology_map;

	/* Speed Map */
	uint8_t		speed_map[IEEE1394_MAX_NODES][IEEE1394_MAX_NODES];

	/* Stack, Queue, and Node Number list */
	void 			*hal_stack[IEEE1394_MAX_NODES];
	int			hal_stack_depth;
	void 			*hal_queue[IEEE1394_MAX_NODES];
	int   			hal_queue_front;
	int   			hal_queue_back;
	int			hal_node_number_list[IEEE1394_MAX_NODES];
	int 			hal_node_number_list_size;

	/* Isoch CEC list */
	kmutex_t		isoch_cec_list_mutex;
	s1394_isoch_cec_t	*isoch_cec_list_head;
	s1394_isoch_cec_t	*isoch_cec_list_tail;

	struct kmem_cache	*hal_kmem_cachep;

	ndi_event_hdl_t		hal_ndi_event_hdl;

	callb_cpr_t		hal_cprinfo;

	/* FCP controllers and targets */
	s1394_fa_hal_t		hal_fa[S1394_FA_NTYPES];

	/* CMP support */
	s1394_cmp_hal_t		hal_cmp;
};

_NOTE(SCHEME_PROTECTS_DATA("No lock needed to start/stop timer", \
	s1394_hal_s::cm_timer))

/* defines for br_thread_ev_type */
#define	BR_THR_CFGROM_SCAN		0x00000001	/* start reading */
#define	BR_THR_GO_AWAY			0x00000002	/* clean & exit */

/*
 * FCP command and response address space
 */
#define	IEC61883_FCP_BASE_ADDR	0xFFFFF0000B00
#define	IEC61883_FCP_CMD_ADDR	IEC61883_FCP_BASE_ADDR
#define	IEC61883_FCP_CMD_SIZE	0x200
#define	IEC61883_FCP_RESP_ADDR	(IEC61883_FCP_CMD_ADDR + IEC61883_FCP_CMD_SIZE)
#define	IEC61883_FCP_RESP_SIZE	0x200
#define	IEC61883_FCP_END_ADDR (IEC61883_FCP_RESP_ADDR + IEC61883_FCP_RESP_SIZE)

/* CMP master plugs */
#define	IEC61883_CMP_OMPR_ADDR		0xFFFFF0000900
#define	IEC61883_CMP_IMPR_ADDR		0xFFFFF0000980
#define	IEC61883_CMP_OMPR_INIT_VAL	0xBFFFFF00
#define	IEC61883_CMP_IMPR_INIT_VAL	0x80FFFF00
#define	IEC61883_CMP_OMPR_LOCK_MASK	0x3FFFFF00
#define	IEC61883_CMP_IMPR_LOCK_MASK	0x00FFFF00

/* s1394_addr_space_blk_t */
struct s1394_addr_space_blk_s {
	/* Pointers and coloring for Red-Black tree */
	s1394_addr_space_blk_t		*asb_parent;
	s1394_addr_space_blk_t		*asb_left;
	s1394_addr_space_blk_t		*asb_right;
	uint32_t			asb_color;
	boolean_t			free_kmem_bufp;

	/* Addr Blk info - callbacks, permissions, backing store, etc. */
	uint64_t			addr_lo;
	uint64_t			addr_hi;
	uint32_t			addr_reserved;
	t1394_addr_enable_t		addr_enable;
	t1394_addr_type_t		addr_type;
	t1394_addr_evts_t		addr_events;
	caddr_t				kmem_bufp;
	void				*addr_arg;
};

/* s1394_config_rom_t */
struct s1394_config_rom_s {
	boolean_t		cfgrom_used;
	uint32_t		cfgrom_addr_lo;
	uint32_t		cfgrom_addr_hi;

	uint_t			root_dir_offset;

	s1394_config_rom_t	*cfgrom_next;
	s1394_config_rom_t	*cfgrom_prev;
};

/* s1394_kstat_t */
struct s1394_kstat_s {
	/* Asynch Receive (AR) requests */
	uint_t			arreq_quad_rd;
	uint_t			arreq_blk_rd;
	uint_t			arreq_quad_wr;
	uint_t			arreq_blk_wr;
	uint_t			arreq_lock32;
	uint_t			arreq_lock64;

	uint_t			arreq_blk_rd_size;
	uint_t			arreq_blk_wr_size;

	uint_t			arreq_posted_write_error;

	/* Failure responses to AR requests (sent) */
	uint_t			arresp_quad_rd_fail;
	uint_t			arresp_blk_rd_fail;
	uint_t			arresp_quad_wr_fail;
	uint_t			arresp_blk_wr_fail;
	uint_t			arresp_lock32_fail;
	uint_t			arresp_lock64_fail;

	/* Asynch Transmit (AT) requests */
	uint_t			atreq_quad_rd;
	uint_t			atreq_blk_rd;
	uint_t			atreq_quad_wr;
	uint_t			atreq_blk_wr;
	uint_t			atreq_lock32;
	uint_t			atreq_lock64;

	uint_t			atreq_blk_rd_size;
	uint_t			atreq_blk_wr_size;

	/* Failure responses to AT requests (received) */
	uint_t			atresp_quad_rd_fail;
	uint_t			atresp_blk_rd_fail;
	uint_t			atresp_quad_wr_fail;
	uint_t			atresp_blk_wr_fail;
	uint_t			atresp_lock32_fail;
	uint_t			atresp_lock64_fail;


	/* Allocate & free requests */
	uint_t			cmd_alloc;
	uint_t			cmd_alloc_fail;
	uint_t			cmd_free;
	uint_t			addr_phys_alloc;
	uint_t			addr_posted_alloc;
	uint_t			addr_normal_alloc;
	uint_t			addr_csr_alloc;
	uint_t			addr_alloc_fail;
	uint_t			addr_space_free;

	/* Bus reset and miscellaneous */
	uint_t			bus_reset;
	uint_t			selfid_complete;
	uint_t			selfid_buffer_error;
	uint_t			pending_q_insert;
	uint64_t		guid;
};

_NOTE(SCHEME_PROTECTS_DATA("Statistics", \
	s1394_kstat_s::{arreq_blk_rd arreq_blk_wr arreq_quad_rd arreq_quad_wr \
	cmd_free selfid_buffer_error arreq_posted_write_error}))

/* s1394_isoch_cec_t */
struct s1394_isoch_cec_s {
	s1394_isoch_cec_t		*cec_next;
	s1394_isoch_cec_t		*cec_prev;

	kmutex_t			isoch_cec_mutex;

	/* Isoch CEC member list */
	s1394_isoch_cec_type_t		cec_type;
	s1394_isoch_cec_member_t	*cec_member_list_head;
	s1394_isoch_cec_member_t	*cec_member_list_tail;
	s1394_isoch_cec_member_t	*cec_member_talker;

	/* Properties given in t1394_alloc_isoch_cec() */
	t1394_isoch_cec_props_t		cec_alloc_props;

	/* Current state of Isoch CEC */
	uint_t				filter_min_speed;
	uint_t				filter_max_speed;
	uint_t				filter_current_speed;
	uint64_t			filter_channel_mask;
	uint_t				bandwidth;
	t1394_cec_options_t		cec_options;
	s1394_isoch_cec_state_t		state_transitions;
	boolean_t			in_callbacks;
	boolean_t			in_fail_callbacks;
	kcondvar_t			in_callbacks_cv;
	boolean_t			cec_want_wakeup;

	boolean_t			realloc_valid;
	boolean_t			realloc_failed;
	t1394_isoch_rsrc_error_t	realloc_fail_reason;
	uint_t				realloc_chnl_num;
	uint_t				realloc_bandwidth;
	uint_t				realloc_speed;
};
#define	CEC_IN_ANY_CALLBACKS(cec)	(((cec)->in_callbacks == B_TRUE) || \
					((cec)->in_fail_callbacks == B_TRUE))

#define	CEC_TRANSITION_LEGAL(cec, tran)	((cec)->state_transitions & (tran))
#define	CEC_SET_LEGAL(cec, tran)	((cec)->state_transitions |= (tran))
#define	CEC_SET_ILLEGAL(cec, tran)	((cec)->state_transitions &= ~(tran))


/* s1394_isoch_cec_member_t */
struct s1394_isoch_cec_member_s {
	s1394_isoch_cec_member_t	*cec_mem_next;
	s1394_isoch_cec_member_t	*cec_mem_prev;

	/* Events for Isoch CEC member - given in t1394_join_isoch_cec() */
	t1394_isoch_cec_evts_t		isoch_cec_evts;
	opaque_t			isoch_cec_evts_arg;
	uint64_t			req_channel_mask;
	uint_t				req_max_speed;
	t1394_jii_options_t		cec_mem_options;
	s1394_target_t			*cec_mem_target;
};

/* cmd1394_fa_cmd_priv_t - per-command data for fixed address support */
typedef struct s1394_fa_cmd_priv_s {
	s1394_fa_type_t		type;
	void			(*completion_callback)();
	opaque_t		callback_arg;
} s1394_fa_cmd_priv_t;

/* s1394_cmd_priv_t */
typedef struct s1394_cmd_priv_s {
	/* Services Layer private structure for asynch commands */
	cmd1394_cmd_t		*cmd_priv_next;
	cmd1394_cmd_t		*cmd_priv_prev;

	uint32_t		cmd_priv_xfer_type;
	s1394_target_t		*sent_by_target;
	s1394_hal_t		*sent_on_hal;

	int			lock_req_step;
	int			temp_num_retries;

	size_t			data_remaining;

	kmutex_t		blocking_mutex;
	kcondvar_t		blocking_cv;
	boolean_t		blocking_flag;

	boolean_t		cmd_in_use;
	boolean_t		posted_write;
	boolean_t		arreq_valid_addr;

	/*
	 * Commands can be extended to support additional functionality.
	 * The only extension at this time is FA (currently used only for FCP).
	 * The downside here is that every command should carry FA overhead
	 * even if the target doesn't use FA. However, alternative approaches
	 * would require separate allocation of FA overhead per command, which
	 * complicates the code and fragments the memory -- seems not worth it
	 * given that FA overhead is just a few bytes and there's a limit of
	 * 256 commands per target.
	 */
	int			cmd_ext_type;
	union {
		s1394_fa_cmd_priv_t	fa;
	} cmd_ext;

	h1394_cmd_priv_t	hal_cmd_private;
} s1394_cmd_priv_t;
#define	S1394_GET_CMD_PRIV(cmd)	\
	((s1394_cmd_priv_t *)((uchar_t *)(cmd) + sizeof (cmd1394_cmd_t)))

/* command extension types */
enum {
	S1394_CMD_EXT_FA	= 1
};
#define	S1394_GET_FA_CMD_PRIV(cmd)	(&(S1394_GET_CMD_PRIV(cmd)->cmd_ext.fa))

#define	S1394_IS_CMD_FCP(s_priv) \
	((s_priv->cmd_ext.fa.type == S1394_FA_TYPE_FCP_CTL) || \
	(s_priv->cmd_ext.fa.type == S1394_FA_TYPE_FCP_TGT))

_NOTE(SCHEME_PROTECTS_DATA("Unique per command", \
	s1394_cmd_priv_s::cmd_priv_xfer_type))


/* s1394_state_t */
typedef struct s1394_state_s {
	/* HAL list */
	kmutex_t	hal_list_mutex;
	s1394_hal_t	*hal_head;
	s1394_hal_t	*hal_tail;
} s1394_state_t;

/* Service Layer Global State Pointer */
extern   s1394_state_t  *s1394_statep;


/* 1394 Services Layer Internals - 1394 Address Space Routines */
int s1394_request_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp);

int s1394_claim_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp);

int s1394_free_addr_blk(s1394_hal_t *hal, s1394_addr_space_blk_t *blk);

int s1394_reserve_addr_blk(s1394_hal_t *hal, t1394_alloc_addr_t *addr_allocp);

int s1394_init_addr_space(s1394_hal_t *hal);

void s1394_destroy_addr_space(s1394_hal_t *hal);

void s1394_free_list_insert(s1394_hal_t *hal, s1394_addr_space_blk_t *new_blk);

s1394_addr_space_blk_t *s1394_used_tree_search(s1394_hal_t *hal,
    uint64_t addr);

s1394_addr_space_blk_t *s1394_used_tree_delete(s1394_hal_t *hal,
    s1394_addr_space_blk_t *z);

boolean_t s1394_is_posted_write(s1394_hal_t *hal, uint64_t addr);

boolean_t s1394_is_physical_addr(s1394_hal_t *hal, uint64_t addr);

boolean_t s1394_is_csr_addr(s1394_hal_t *hal, uint64_t addr);

boolean_t s1394_is_normal_addr(s1394_hal_t *hal, uint64_t addr);

/* 1394 Services Layer Internals - Asynchronous Communications Routines */
int s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp);

int s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp);

int s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err);

int s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target,
    cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err);

void s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd);

void s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd);

void s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req,
    int status);

void s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp,
    int status);

int s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp);

int s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target,
    cmd1394_cmd_t *cmd);

int s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target,
    cmd1394_cmd_t *cmd);

void s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags);

void s1394_resend_pending_cmds(s1394_hal_t *hal);

/* 1394 Services Layer Internals - Bus Reset Routines */
int s1394_parse_selfid_buffer(s1394_hal_t *hal, void *selfid_buf_addr,
    uint32_t selfid_size);

void s1394_sort_selfids(s1394_hal_t *hal);

void s1394_init_topology_tree(s1394_hal_t *hal, boolean_t copied,
    ushort_t number_of_nodes);

int s1394_topology_tree_build(s1394_hal_t *hal);

void s1394_topology_tree_mark_all_unvisited(s1394_hal_t *hal);

void s1394_old_tree_mark_all_unvisited(s1394_hal_t *hal);

void s1394_old_tree_mark_all_unmatched(s1394_hal_t *hal);

void s1394_copy_old_tree(s1394_hal_t *hal);

void s1394_match_tree_nodes(s1394_hal_t *hal);

int s1394_topology_tree_calculate_diameter(s1394_hal_t *hal);

int s1394_gap_count_optimize(int diameter);

int s1394_get_current_gap_count(s1394_hal_t *hal);

void s1394_speed_map_fill(s1394_hal_t *hal);

uint8_t s1394_speed_map_get(s1394_hal_t *hal, uint32_t from_node,
    uint32_t to_node);

void s1394_update_speed_map_link_speeds(s1394_hal_t *hal);

int s1394_get_isoch_rsrc_mgr(s1394_hal_t *hal);

void s1394_physical_arreq_setup_all(s1394_hal_t *hal);

void s1394_physical_arreq_set_one(s1394_target_t *target);

void s1394_physical_arreq_clear_one(s1394_target_t *target);

s1394_node_t *s1394_topology_tree_get_root_node(s1394_hal_t *hal);

/* 1394 Services Layer Internals - CSR and Config ROM Routines */
int s1394_setup_CSR_space(s1394_hal_t *hal);

void s1394_CSR_topology_map_update(s1394_hal_t *hal);

void s1394_CSR_topology_map_disable(s1394_hal_t *hal);

int s1394_init_local_config_rom(s1394_hal_t *hal);

void s1394_destroy_local_config_rom(s1394_hal_t *hal);

int s1394_add_config_rom_entry(s1394_hal_t *hal, uint8_t key,
    uint32_t *buffer, uint_t size, void **handle, int *status);

int s1394_remove_config_rom_entry(s1394_hal_t *hal, void **handle,
    int *status);

void s1394_update_config_rom_callback(void *arg);

/* In s1394_dev_disc.c */
void s1394_br_thread(s1394_hal_t *hal);

void s1394_free_cfgrom(s1394_hal_t *hal, s1394_node_t *node,
    s1394_free_cfgrom_t options);

void s1394_copy_cfgrom(s1394_node_t *to, s1394_node_t *from);

int s1394_read_rest_of_cfgrom(s1394_hal_t *hal, s1394_node_t *node,
    s1394_status_t *status);

void s1394_cfgrom_parse_unit_dir(uint32_t *unit_dir, uint32_t *addr_hi,
    uint32_t *addr_lo, uint32_t *size_hi, uint32_t *size_lo);

boolean_t s1394_valid_cfgrom(s1394_hal_t *hal, s1394_node_t *node);

boolean_t s1394_valid_dir(s1394_hal_t *hal, s1394_node_t *node, uint32_t key,
    uint32_t *dir);

void s1394_get_maxpayload(s1394_target_t *target, uint_t *dev_max_payload,
    uint_t *current_max_payload);

int s1394_lock_tree(s1394_hal_t *hal);

void s1394_unlock_tree(s1394_hal_t *hal);

/* 1394 Services Layer Driver - Hotplug Routines */
dev_info_t *s1394_devi_find(dev_info_t *pdip, char *name, char *caddr);

int s1394_update_devinfo_tree(s1394_hal_t *hal, s1394_node_t *node);

int s1394_offline_node(s1394_hal_t *hal, s1394_node_t *node);

int s1394_process_topology_tree(s1394_hal_t *hal, int *wait_for_cbs,
    uint_t *wait_gen);

int s1394_process_old_tree(s1394_hal_t *hal);

void s1394_add_target_to_node(s1394_target_t *target);

void s1394_remove_target_from_node(s1394_target_t *target);

/* fixed address support */
int s1394_fa_claim_addr(s1394_hal_t *hal, s1394_fa_type_t type,
    s1394_fa_descr_t *descr);

void s1394_fa_free_addr(s1394_hal_t *hal, s1394_fa_type_t type);

void s1394_fa_list_add(s1394_hal_t *hal, s1394_target_t *target,
    s1394_fa_type_t type);

int s1394_fa_list_remove(s1394_hal_t *hal, s1394_target_t *target,
    s1394_fa_type_t type);

boolean_t s1394_fa_list_is_empty(s1394_hal_t *hal, s1394_fa_type_t type);

uint_t s1394_fa_list_gen(s1394_hal_t *hal, s1394_fa_type_t type);

void s1394_fa_init_cmd(s1394_cmd_priv_t *s_priv, s1394_fa_type_t type);

void s1394_fa_convert_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd);

void s1394_fa_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd);

void s1394_fa_check_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd);

/* FCP */
int s1394_fcp_hal_init(s1394_hal_t *hal);

int s1394_fcp_register_ctl(s1394_target_t *target, t1394_fcp_evts_t *evts);

int s1394_fcp_register_tgt(s1394_target_t *target, t1394_fcp_evts_t *evts);

int s1394_fcp_unregister_ctl(s1394_target_t *target);

int s1394_fcp_unregister_tgt(s1394_target_t *target);

int s1394_fcp_write_check_cmd(cmd1394_cmd_t *cmd);

/* CMP */
int s1394_cmp_register(s1394_target_t *target, t1394_cmp_evts_t *evts);

int s1394_cmp_unregister(s1394_target_t *target);

int s1394_cmp_read(s1394_target_t *target, t1394_cmp_reg_t reg, uint32_t *valp);

int s1394_cmp_cas(s1394_target_t *target, t1394_cmp_reg_t reg, uint32_t arg_val,
    uint32_t new_val, uint32_t *old_valp);

/* 1394 Services Layer Internals - Isochronous Communication Routines */
void s1394_isoch_rsrc_realloc(s1394_hal_t *hal);

void s1394_isoch_rsrc_realloc_notify(s1394_hal_t *hal);

int s1394_channel_alloc(s1394_hal_t *hal, uint32_t channel_mask,
    uint_t generation, uint_t flags, uint32_t *old_channels, int *result);

int s1394_channel_free(s1394_hal_t *hal, uint32_t channel_mask,
    uint_t generation, uint_t flags, uint32_t *old_channels, int *result);

int s1394_bandwidth_alloc(s1394_hal_t *hal, uint32_t bw_alloc_units,
    uint_t generation, int *result);

uint_t s1394_compute_bw_alloc_units(s1394_hal_t *hal, uint_t bandwidth,
    uint_t speed);

int s1394_bandwidth_free(s1394_hal_t *hal, uint32_t bw_alloc_units,
    uint_t generation, int *result);

void s1394_isoch_cec_list_insert(s1394_hal_t *hal, s1394_isoch_cec_t *cec);

void s1394_isoch_cec_list_remove(s1394_hal_t *hal, s1394_isoch_cec_t *cec);

void s1394_isoch_cec_member_list_insert(s1394_hal_t *hal,
    s1394_isoch_cec_t *cec, s1394_isoch_cec_member_t *member);

void s1394_isoch_cec_member_list_remove(s1394_hal_t *hal,
    s1394_isoch_cec_t *cec, s1394_isoch_cec_member_t *member);

/* 1394 Services Layer Internals - Miscellaneous Routines */
void s1394_cleanup_for_detach(s1394_hal_t *hal, uint_t cleanup_level);

void s1394_hal_shutdown(s1394_hal_t *hal, boolean_t disable_hal);

void s1394_initiate_hal_reset(s1394_hal_t *hal, int reason);

boolean_t s1394_on_br_thread(s1394_hal_t *hal);

void s1394_destroy_br_thread(s1394_hal_t *hal);

void s1394_tickle_bus_reset_thread(s1394_hal_t *hal);

void s1394_block_on_asynch_cmd(cmd1394_cmd_t *cmd);

int s1394_HAL_asynch_error(s1394_hal_t *hal, cmd1394_cmd_t *cmd,
    s1394_hal_state_t state);

boolean_t s1394_mblk_too_small(cmd1394_cmd_t *cmd);

boolean_t s1394_address_rollover(cmd1394_cmd_t *cmd);

uint_t s1394_stoi(char *p, int len, int base);

uint_t s1394_CRC16(uint_t *d, uint_t crc_length);

uint_t s1394_CRC16_old(uint_t *d, uint_t crc_length);

int s1394_ioctl(s1394_hal_t *hal, int cmd, intptr_t arg, int mode,
    cred_t *cred_p, int *rval_p);

void s1394_check_pwr_mgmt(s1394_hal_t *hal, s1394_target_t *target,
    boolean_t add);

int s1394_kstat_init(s1394_hal_t *hal);

int s1394_kstat_delete(s1394_hal_t *hal);

int s1394_kstat_update(kstat_t *ksp, int rw);

void s1394_addr_alloc_kstat(s1394_hal_t *hal, uint64_t addr);

void s1394_print_node_info(s1394_hal_t *hal);

s1394_hal_t *s1394_dip_to_hal(dev_info_t *dip);

s1394_target_t *s1394_target_from_dip(s1394_hal_t *hal, dev_info_t *tdip);
s1394_target_t *s1394_target_from_dip_locked(s1394_hal_t *hal,
    dev_info_t *tdip);

void s1394_destroy_timers(s1394_hal_t *hal);

void s1394_cycle_too_long_callback(void *arg);

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_1394_S1394_H */
